]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/commitdiff
Merge commit 'remotes/github/debian-unstable' into slop
authorJoey Hess <joey@gnu.kitenet.net>
Thu, 27 Aug 2009 23:43:18 +0000 (19:43 -0400)
committerJoey Hess <joey@gnu.kitenet.net>
Thu, 27 Aug 2009 23:43:18 +0000 (19:43 -0400)
1250 files changed:
.gitignore
.perlcriticrc
Bundle/IkiWiki.pm
Bundle/IkiWiki/Extras.pm
IkiWiki.pm
IkiWiki/CGI.pm
IkiWiki/Plugin/404.pm [new file with mode: 0644]
IkiWiki/Plugin/aggregate.pm
IkiWiki/Plugin/amazon_s3.pm
IkiWiki/Plugin/anonok.pm
IkiWiki/Plugin/attachment.pm
IkiWiki/Plugin/autoindex.pm [new file with mode: 0644]
IkiWiki/Plugin/blogspam.pm [new file with mode: 0644]
IkiWiki/Plugin/brokenlinks.pm
IkiWiki/Plugin/bzr.pm [new file with mode: 0644]
IkiWiki/Plugin/calendar.pm
IkiWiki/Plugin/camelcase.pm
IkiWiki/Plugin/color.pm [new file with mode: 0644]
IkiWiki/Plugin/comments.pm [new file with mode: 0644]
IkiWiki/Plugin/conditional.pm
IkiWiki/Plugin/creole.pm
IkiWiki/Plugin/cutpaste.pm [new file with mode: 0644]
IkiWiki/Plugin/darcs.pm [new file with mode: 0644]
IkiWiki/Plugin/ddate.pm
IkiWiki/Plugin/editdiff.pm
IkiWiki/Plugin/editpage.pm [new file with mode: 0644]
IkiWiki/Plugin/edittemplate.pm
IkiWiki/Plugin/embed.pm
IkiWiki/Plugin/external.pm
IkiWiki/Plugin/favicon.pm
IkiWiki/Plugin/filecheck.pm [new file with mode: 0644]
IkiWiki/Plugin/format.pm [new file with mode: 0644]
IkiWiki/Plugin/fortune.pm
IkiWiki/Plugin/getsource.pm [new file with mode: 0644]
IkiWiki/Plugin/git.pm [new file with mode: 0644]
IkiWiki/Plugin/goodstuff.pm
IkiWiki/Plugin/google.pm [new file with mode: 0644]
IkiWiki/Plugin/googlecalendar.pm [deleted file]
IkiWiki/Plugin/goto.pm [new file with mode: 0644]
IkiWiki/Plugin/graphviz.pm
IkiWiki/Plugin/haiku.pm
IkiWiki/Plugin/highlight.pm [new file with mode: 0644]
IkiWiki/Plugin/hnb.pm
IkiWiki/Plugin/html.pm
IkiWiki/Plugin/htmlbalance.pm [new file with mode: 0644]
IkiWiki/Plugin/htmlscrubber.pm
IkiWiki/Plugin/htmltidy.pm
IkiWiki/Plugin/httpauth.pm
IkiWiki/Plugin/img.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/link.pm
IkiWiki/Plugin/linkmap.pm
IkiWiki/Plugin/listdirectives.pm [new file with mode: 0644]
IkiWiki/Plugin/lockedit.pm
IkiWiki/Plugin/map.pm
IkiWiki/Plugin/mdwn.pm
IkiWiki/Plugin/mercurial.pm [new file with mode: 0644]
IkiWiki/Plugin/meta.pm
IkiWiki/Plugin/mirrorlist.pm
IkiWiki/Plugin/monotone.pm [new file with mode: 0644]
IkiWiki/Plugin/more.pm
IkiWiki/Plugin/norcs.pm [new file with mode: 0644]
IkiWiki/Plugin/opendiscussion.pm
IkiWiki/Plugin/openid.pm
IkiWiki/Plugin/orphans.pm
IkiWiki/Plugin/otl.pm
IkiWiki/Plugin/pagecount.pm
IkiWiki/Plugin/pagestats.pm
IkiWiki/Plugin/pagetemplate.pm
IkiWiki/Plugin/parentlinks.pm [new file with mode: 0644]
IkiWiki/Plugin/passwordauth.pm
IkiWiki/Plugin/pingee.pm
IkiWiki/Plugin/pinger.pm
IkiWiki/Plugin/po.pm [new file with mode: 0644]
IkiWiki/Plugin/poll.pm
IkiWiki/Plugin/polygen.pm
IkiWiki/Plugin/postsparkline.pm
IkiWiki/Plugin/prettydate.pm
IkiWiki/Plugin/progress.pm [new file with mode: 0644]
IkiWiki/Plugin/rawhtml.pm
IkiWiki/Plugin/recentchanges.pm
IkiWiki/Plugin/recentchangesdiff.pm
IkiWiki/Plugin/relativedate.pm [new file with mode: 0644]
IkiWiki/Plugin/remove.pm [new file with mode: 0644]
IkiWiki/Plugin/rename.pm [new file with mode: 0644]
IkiWiki/Plugin/repolist.pm [new file with mode: 0644]
IkiWiki/Plugin/search.pm
IkiWiki/Plugin/shortcut.pm
IkiWiki/Plugin/sidebar.pm
IkiWiki/Plugin/signinedit.pm
IkiWiki/Plugin/skeleton.pm [deleted file]
IkiWiki/Plugin/skeleton.pm.example [new file with mode: 0644]
IkiWiki/Plugin/smiley.pm
IkiWiki/Plugin/sparkline.pm
IkiWiki/Plugin/svn.pm [new file with mode: 0644]
IkiWiki/Plugin/table.pm
IkiWiki/Plugin/tag.pm
IkiWiki/Plugin/template.pm
IkiWiki/Plugin/testpagespec.pm
IkiWiki/Plugin/teximg.pm
IkiWiki/Plugin/textile.pm
IkiWiki/Plugin/tla.pm [new file with mode: 0644]
IkiWiki/Plugin/toc.pm
IkiWiki/Plugin/toggle.pm
IkiWiki/Plugin/txt.pm
IkiWiki/Plugin/typography.pm
IkiWiki/Plugin/underlay.pm [new file with mode: 0644]
IkiWiki/Plugin/version.pm
IkiWiki/Plugin/websetup.pm [new file with mode: 0644]
IkiWiki/Plugin/wikitext.pm
IkiWiki/Plugin/wmd.pm [new file with mode: 0644]
IkiWiki/Rcs/Stub.pm [deleted file]
IkiWiki/Rcs/bzr.pm [deleted file]
IkiWiki/Rcs/git.pm [deleted file]
IkiWiki/Rcs/mercurial.pm [deleted file]
IkiWiki/Rcs/monotone.pm [deleted file]
IkiWiki/Rcs/svn.pm [deleted file]
IkiWiki/Rcs/tla.pm [deleted file]
IkiWiki/Receive.pm [new file with mode: 0644]
IkiWiki/Render.pm
IkiWiki/Setup.pm
IkiWiki/Setup/Automator.pm [new file with mode: 0644]
IkiWiki/Setup/Standard.pm
IkiWiki/UserInfo.pm
IkiWiki/Wrapper.pm
Makefile.PL
README
auto-blog.setup [new file with mode: 0644]
auto.setup [new file with mode: 0644]
debian/NEWS
debian/changelog
debian/compat
debian/control
debian/copyright
debian/docs [new file with mode: 0644]
debian/examples [new file with mode: 0644]
debian/link [new file with mode: 0644]
debian/postinst
debian/preinst
debian/rules
doc/TourBusStop.mdwn
doc/anchor.mdwn [new file with mode: 0644]
doc/banned_users.mdwn
doc/basewiki.mdwn
doc/basewiki/index.mdwn
doc/blog.mdwn [new file with mode: 0644]
doc/bugs.mdwn
doc/bugs/Aggregated_Atom_feeds_are_double-encoded.mdwn [new file with mode: 0644]
doc/bugs/Allow_overriding_of_symlink_restriction.mdwn [new file with mode: 0644]
doc/bugs/Another_UTF-8_problem.mdwn
doc/bugs/Broken_URL_to_your_blog_script.mdwn [new file with mode: 0644]
doc/bugs/Broken_access_to_Ikiwiki_gitweb.mdwn [new file with mode: 0644]
doc/bugs/CGI__44___formbuilder__44___non-existent_field_address.mdwn [new file with mode: 0644]
doc/bugs/CGI_problem_with_some_webservers.mdwn
doc/bugs/Can__39__t_create_root_page.mdwn
doc/bugs/Cannot_inline_pages_with_apostrophes_in_title.mdwn [new file with mode: 0644]
doc/bugs/Command-line_arguments_should_override_settings_in_the_setup_file.mdwn
doc/bugs/Comments_link_is_to_index.html_if_usedirs_is_on.mdwn [new file with mode: 0644]
doc/bugs/Does_IkiWiki::Setup::load__40____41___really_return_a_hash__63__.mdwn [new file with mode: 0644]
doc/bugs/Dupe_entry_in_Bundle::IkiWiki::Extras.pm.mdwn [new file with mode: 0644]
doc/bugs/Error:_Your_login_session_has_expired._.mdwn [new file with mode: 0644]
doc/bugs/Filenames_with_colons_cause_problems_for_Windows_users.mdwn
doc/bugs/Git:_web_commit_message_not_utf-8.mdwn [new file with mode: 0644]
doc/bugs/Graphviz_plug-in_directive_changed_in_2.60.mdwn [new file with mode: 0644]
doc/bugs/HTML-escaped_titles_in_Atom__44___RSS_feeds_don__39__t_validate.mdwn [deleted file]
doc/bugs/HTML_for_parentlinks_makes_theming_hard.mdwn [new file with mode: 0644]
doc/bugs/HTML_inlined_into_Atom_not_necessarily_well-formed.mdwn [new file with mode: 0644]
doc/bugs/Hyperestraier_search_plug-in_defective.mdwn
doc/bugs/INC_location_not_set_correctly_in_make_test.mdwn [new file with mode: 0644]
doc/bugs/IkiWiki::Setup::load__40____41___broken_outside_ikiwiki__63__.mdwn [new file with mode: 0644]
doc/bugs/IkiWiki::Wrapper_should_use_destdir.mdwn [new file with mode: 0644]
doc/bugs/IkiWiki::Wrapper_should_use_destdir/discussion.mdwn [new file with mode: 0644]
doc/bugs/Index_files_have_wrong_permissions.mdwn [new file with mode: 0644]
doc/bugs/Inline_doesn__39__t_wikilink_to_pages.mdwn [new file with mode: 0644]
doc/bugs/Insecure_dependency_in_eval_while_running_with_-T_switch.mdwn
doc/bugs/Insecure_dependency_in_mkdir.mdwn
doc/bugs/Insecure_dependency_in_utime.mdwn
doc/bugs/Links_with_symbols_can__39__t_be_edited.mdwn [new file with mode: 0644]
doc/bugs/MTIME_not_set_for_inline_or_archive_entries.mdwn [new file with mode: 0644]
doc/bugs/Map_sorts_subtags_under_a_different_tag.mdwn
doc/bugs/Meta_plugin_does_not_respect_htmlscrubber__95__skip_setting.___40__patch__41__.mdwn [new file with mode: 0644]
doc/bugs/Missing_build-dep_on_perlmagick__63__.mdwn [new file with mode: 0644]
doc/bugs/Monotone_rcs_support.mdwn
doc/bugs/No___34__sid__34___in_forms_resulting_in_Error:_Your_login_session_has_expired..mdwn
doc/bugs/No_link_for_blog_items_when_filename_contains_a_colon.mdwn
doc/bugs/No_progress_in_progress_bar.mdwn [new file with mode: 0644]
doc/bugs/Obsolete_templates__47__estseek.conf.mdwn [new file with mode: 0644]
doc/bugs/OpenID_delegation_fails_on_my_server.mdwn [new file with mode: 0644]
doc/bugs/PNG_triggers_UTF-8_error_in_MimeInfo.pm.mdwn [new file with mode: 0644]
doc/bugs/Please_avoid_using___39__cp_-a__39___in_Makefile.PL.mdwn [new file with mode: 0644]
doc/bugs/Problem_with_toc.pm_plug-in.mdwn
doc/bugs/Problems_with_graphviz.pm_plug-in.mdwn
doc/bugs/RecentChanges_broken_with_empty_svnpath.mdwn
doc/bugs/RecentChanges_contains_invalid_XHTML.mdwn
doc/bugs/RecentChanges_links_to_deleted_pages.mdwn [new file with mode: 0644]
doc/bugs/Renaming_a_file_via_the_web_is_failing_when_using_subversion.mdwn [new file with mode: 0644]
doc/bugs/SSI_include_stripped_from_mdwn.mdwn [new file with mode: 0644]
doc/bugs/SVG_files_not_recognized_as_images.mdwn [new file with mode: 0644]
doc/bugs/Spaces_in_link_text_for_ikiwiki_links.mdwn
doc/bugs/Spurious___60__p__62___elements_added_to_tags_in_inliine_pages.mdwn
doc/bugs/Titles_are_lower-cased_when_creating_a_page.mdwn
doc/bugs/Toc_map_and_template_plugins_do_not_play_well_together.mdwn [new file with mode: 0644]
doc/bugs/URLs_with_parentheses_displayed_badly.mdwn [new file with mode: 0644]
doc/bugs/Undefined_subroutine_IkiWiki::refresh.mdwn [new file with mode: 0644]
doc/bugs/Use_install__40__1__41___instead_of_cp__40__1__41___for_installing_files.mdwn
doc/bugs/Warns_about_use_of_uninitialized_value_if_prefix__95__directives_is_on_and_a_directive_does_not_contain_a_space.mdwn [new file with mode: 0644]
doc/bugs/Wrong_permissions_on_4_smileys.mdwn
doc/bugs/__34__more__34___doesn__39__t_work.mdwn [new file with mode: 0644]
doc/bugs/__38__uuml__59___in_markup_makes_ikiwiki_not_un-escape_HTML_at_all.mdwn
doc/bugs/__60__br__62___tags_are_removed_from_markdown_inline_HTML.mdwn
doc/bugs/__96____96__clear:_both__39____39___for___96__.page__42____39____63__.mdwn
doc/bugs/aggregate_global_feed_names.mdwn [new file with mode: 0644]
doc/bugs/aggregate_plugin_errors.mdwn
doc/bugs/aggregate_plugin_should_honour_a_post__39__s_mctime.mdwn
doc/bugs/aggregateinline_planets_wrongly_link_to_posts.mdwn
doc/bugs/attachment:_escaping_underscores_in_filename__63__.mdwn [new file with mode: 0644]
doc/bugs/attachment:_failed_to_get_filehandle.mdwn [new file with mode: 0644]
doc/bugs/attachment_plugin_enabled_by_default__63__.mdwn
doc/bugs/backlinks_onhover_thing_can_go_weird.mdwn [new file with mode: 0644]
doc/bugs/barfs_on_recentchange_entry_for_a_change_removing_an_invalid_pagespec.mdwn [new file with mode: 0644]
doc/bugs/basewiki_uses_meta_directives_but_meta_is_not_enabled_by_default.mdwn [new file with mode: 0644]
doc/bugs/beautify__95__urlpath_will_add_.__47___even_if_it_is_already_present.mdwn [new file with mode: 0644]
doc/bugs/blog_posts_not_added_to_mercurial_repo.mdwn
doc/bugs/bugfix_for:___34__mtn:_operation_canceled:_Broken_pipe__34_____40__patch__41__.mdwn [new file with mode: 0644]
doc/bugs/bzr_RecentChanges_dates_start_from_1969.mdwn [new file with mode: 0644]
doc/bugs/bzr_plugin_does_not_define_rcs__95__diff.mdwn [new file with mode: 0644]
doc/bugs/cannot_preview_shortcuts.mdwn [new file with mode: 0644]
doc/bugs/cannot_reliably_use_meta_in_template.mdwn [new file with mode: 0644]
doc/bugs/colon:problem.mdwn [new file with mode: 0644]
doc/bugs/colon:problem/discussion.mdwn [new file with mode: 0644]
doc/bugs/comments_produce_broken_links_in_RecentChanges.mdwn [new file with mode: 0644]
doc/bugs/complex_wiki-code___40__braces__41___in_wikilink-text_breaks_wikilinks.mdwn [new file with mode: 0644]
doc/bugs/correct_published_and_updated_time_information_for_the_feeds.mdwn
doc/bugs/ddate_plugin_causes_websetup_to_change_timeformat__44___even_when_disabled.mdwn [new file with mode: 0644]
doc/bugs/debbug_shortcut_should_expand_differently.mdwn
doc/bugs/defintion_lists_appear_to_be_disabled.mdwn [new file with mode: 0644]
doc/bugs/disabling_backlinks.mdwn
doc/bugs/done.mdwn
doc/bugs/dumpsetup_does_not_save_destdir.mdwn [new file with mode: 0644]
doc/bugs/edit_preview_resolves_links_differently_from_commit.mdwn [new file with mode: 0644]
doc/bugs/entirely_negated_pagespec_matches_internal_pages.mdwn [new file with mode: 0644]
doc/bugs/errors_with_ampersand_in_filename.mdwn [new file with mode: 0644]
doc/bugs/external_links_inside_headings_don__39__t_work.mdwn [new file with mode: 0644]
doc/bugs/feedfile_does_the_wrong_thing_from_index.mdwn2.mdwn [new file with mode: 0644]
doc/bugs/firefox_doesn__39__t_want_to_load_updated_pages_at_ikiwiki.info.mdwn [new file with mode: 0644]
doc/bugs/format_bug.mdwn
doc/bugs/git_fails_to_compile.mdwn
doc/bugs/git_stderr_output_causes_problems.mdwn [new file with mode: 0644]
doc/bugs/gitweb_deficiency_w.r.t._log_messages.mdwn
doc/bugs/gitweb_deficiency_w.r.t._newly_created_pages.mdwn
doc/bugs/goto_with_bad_page_name.mdwn [new file with mode: 0644]
doc/bugs/html5_support.mdwn [new file with mode: 0644]
doc/bugs/html_errors.mdwn
doc/bugs/htmlscrubber_undoes_email_obfuscation_by_Text::Markdown.mdwn [new file with mode: 0644]
doc/bugs/htmltidy_has_no_possibilty_to_use_an_alternative_config_file_which_may_break_other_usages.mdwn
doc/bugs/http_proxy_for_openid.mdwn
doc/bugs/ikiwiki_is_not_truly_localizable.mdwn [deleted file]
doc/bugs/images_in_inlined_pages_have_wrong_relative_URL.mdwn [new file with mode: 0644]
doc/bugs/img_plugin_causes_taint_failure.mdwn
doc/bugs/img_plugin_renders___60__img__62___tag_without_src_attribute_post-2.20.mdwn
doc/bugs/img_plugin_should_pass_through_class_attribute.mdwn
doc/bugs/img_with_alt_has_extra_double_quote.mdwn [new file with mode: 0644]
doc/bugs/index.html__63__updated.mdwn
doc/bugs/index.html_is_made_visible_by_various_actions.mdwn [new file with mode: 0644]
doc/bugs/iniline_breaks_toc_plugin.mdwn
doc/bugs/inline_from_field_empty_if_rootpage_doesn__39__t_exist.mdwn [new file with mode: 0644]
doc/bugs/inline_plugin_rootpage_option_is_not_case_insensitive.mdwn
doc/bugs/inline_sort-by-title_issues.mdwn [new file with mode: 0644]
doc/bugs/inline_sort_order_and_meta_date_value.mdwn [new file with mode: 0644]
doc/bugs/install_into_home_dir_fails.mdwn [new file with mode: 0644]
doc/bugs/links_misparsed_in_CSV_files.mdwn [new file with mode: 0644]
doc/bugs/lockedit_plugin_should_alert_user_about_an_invalid_pagespec_in_preferences.mdwn
doc/bugs/login_page_should_note_cookie_requirement.mdwn [new file with mode: 0644]
doc/bugs/mailto:_links_not_properly_generated_in_rssatom_feeds.mdwn
doc/bugs/map_does_not_link_directory_for_which_a_file_also_exists.mdwn
doc/bugs/map_doesn__39__t_calculate___34__common__95__prefix__34___correctly.mdwn
doc/bugs/map_fails_to_close_ul_element_for_empty_list.mdwn [new file with mode: 0644]
doc/bugs/map_is_inconsistent_about_bare_directories.mdwn [new file with mode: 0644]
doc/bugs/markdown_bug:_email_escaping_and_plus_addresses.mdwn [new file with mode: 0644]
doc/bugs/mercurial_fail_to_add.mdwn
doc/bugs/messed_up_repository.mdwn [new file with mode: 0644]
doc/bugs/methodResponse_in_add__95__plugins.mdwn [new file with mode: 0644]
doc/bugs/multiple_pages_with_same_name.mdwn [new file with mode: 0644]
doc/bugs/nested_raw_included_inlines.mdwn [new file with mode: 0644]
doc/bugs/no_easy_way_to_wrap_HTML_container_around_a_set_of_inlined_pages.mdwn [new file with mode: 0644]
doc/bugs/openid_no_longer_pretty-prints_OpenIDs.mdwn [new file with mode: 0644]
doc/bugs/output_of_successful_rename_should_list_the_full_path_to_affected_pages.mdwn [new file with mode: 0644]
doc/bugs/package_build_fails_in_non-English_environment.mdwn [new file with mode: 0644]
doc/bugs/page_is_not_rebuilt_if_it_changes_extension.mdwn [new file with mode: 0644]
doc/bugs/pagecount_is_broken.mdwn [new file with mode: 0644]
doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn [new file with mode: 0644]
doc/bugs/pagespec_parsing_chokes_on_function__40____41__.mdwn
doc/bugs/pagetitle_function_does_not_respect_meta_titles.mdwn
doc/bugs/pipe-symbol_in_taglink_target.mdwn [new file with mode: 0644]
doc/bugs/pipe_in_tables_as_characters.mdwn
doc/bugs/po_plugin_adds_new_dependency.mdwn [new file with mode: 0644]
doc/bugs/po_plugin_cannot_add_po_files_into_git.mdwn [new file with mode: 0644]
doc/bugs/post-commit_hangs.mdwn [new file with mode: 0644]
doc/bugs/prettydate_with_weekday-date_inconsistency.mdwn [new file with mode: 0644]
doc/bugs/previewing_new_page_can_leave_files_dangling.mdwn [new file with mode: 0644]
doc/bugs/previewing_with_an_edittemplate_reverts_edit_box.mdwn [new file with mode: 0644]
doc/bugs/prune_causing_taint_mode_failures.mdwn
doc/bugs/quieten_mercurial.mdwn
doc/bugs/raw_html_in-page_and___91____91____33__included__93____93__.mdwn
doc/bugs/recentchanges_escaping.mdwn [new file with mode: 0644]
doc/bugs/recentchanges_feed_links.mdwn
doc/bugs/recentchangesdiff_crashes_on_commits_which_remove_a_lot_of_files.mdwn
doc/bugs/relative_date_weird_results.mdwn [new file with mode: 0644]
doc/bugs/relative_links.mdwn [deleted file]
doc/bugs/remove_orphaned_sparkline-php_from_Suggests.mdwn [new file with mode: 0644]
doc/bugs/remove_plugin_and_untracked_files.mdwn [new file with mode: 0644]
doc/bugs/rss_feeds_do_not_use_recommended_encoding_of_entities_for_some_fields.mdwn [new file with mode: 0644]
doc/bugs/rst_fails_on_file_containing_only_a_number.mdwn
doc/bugs/rst_plugin_hangs_on_utf-8.mdwn
doc/bugs/rst_tweak.mdwn
doc/bugs/search:___34__link__34___and___34__title__34___fields_are_incorrectly_specified.mdwn [new file with mode: 0644]
doc/bugs/search_for_locale_data_in_the_installed_location.mdwn
doc/bugs/search_plugin_and_CGI_preview.mdwn [new file with mode: 0644]
doc/bugs/search_plugin_uses_wrong_css_path.mdwn
doc/bugs/shortcut_encoding.mdwn
doc/bugs/shortcut_plugin_will_not_work_without_shortcuts.mdwn.mdwn [new file with mode: 0644]
doc/bugs/shortcuts_don__39__t_escape_from_Markdown.mdwn
doc/bugs/sidebar_is_obscured_by_recentchanges.mdwn [new file with mode: 0644]
doc/bugs/some_strings_are_not_internationalized.mdwn [new file with mode: 0644]
doc/bugs/space_in_a___91____91__page_link__93____93___doesn__39__t_make_link.mdwn
doc/bugs/special_characters_in_tag_names_need_manual_escaping.mdwn
doc/bugs/ssl_certificates_not_checked_with_openid.mdwn
doc/bugs/stray___60____47__p__62___tags.mdwn [new file with mode: 0644]
doc/bugs/support_for_openid2_logins.mdwn [new file with mode: 0644]
doc/bugs/syntax_error_in_aggregate.mdwn [new file with mode: 0644]
doc/bugs/table_external_file_links.mdwn [new file with mode: 0644]
doc/bugs/tagged__40____41___matching_wikilinks.mdwn [new file with mode: 0644]
doc/bugs/tags__44___backlinks_and_3.x.mdwn [new file with mode: 0644]
doc/bugs/tags_base_dir_not_used_when_creating_new_tags.mdwn
doc/bugs/taint_issue_with_regular_expressions.mdwn
doc/bugs/tbasewiki__95__brokenlinks.t_broken.mdwn
doc/bugs/teximg_fails_if_same_tex_is_used_on_multiple_pages.mdwn
doc/bugs/textile_plugin_dies_if_input_has_a_non-utf8_character.mdwn
doc/bugs/title__40____41___in_a_PageSpec__44___with_meta_enabled__44___causes_a_crash.mdwn [new file with mode: 0644]
doc/bugs/toggle_fails_on_Safari.mdwn [new file with mode: 0644]
doc/bugs/txt_plugin_having_problems_with_meta_directives.mdwn [new file with mode: 0644]
doc/bugs/typo_in_skeleton.pm:_sessionncgi.mdwn [new file with mode: 0644]
doc/bugs/undefined_tags_or_mismatched_tags_won__39__t_get_converted.mdwn
doc/bugs/underlaydir_file_expose.mdwn
doc/bugs/unicode_chars_in_wikiname_break_auth.mdwn [new file with mode: 0644]
doc/bugs/unicode_encoded_urls_and_recentchanges.mdwn [new file with mode: 0644]
doc/bugs/unwanted_discussion_links_on_discussion_pages.mdwn [new file with mode: 0644]
doc/bugs/user_links_on_recentchanges_pages_problem.mdwn [new file with mode: 0644]
doc/bugs/websetup_eats_setupconf_and_allow__95__symlinks__95__before__95__srcdir.mdwn [new file with mode: 0644]
doc/bugs/wiki_formatting_does_not_work_between_toc_and_an_inline.mdwn
doc/bugs/wiki_links_still_processed_inside_code_blocks.mdwn
doc/bugs/wikilink_in_table.mdwn
doc/cgi/discussion.mdwn [new file with mode: 0644]
doc/contact.mdwn
doc/convert.mdwn [new file with mode: 0644]
doc/css.mdwn
doc/css_market.mdwn
doc/css_market/actiontabs.css [new file with mode: 0644]
doc/css_market/discussion.mdwn [new file with mode: 0644]
doc/css_market/zack.css
doc/download.mdwn
doc/examples/blog.mdwn
doc/examples/blog/index.mdwn
doc/examples/blog/posts.mdwn
doc/examples/blog/posts/first_post.mdwn
doc/examples/blog/sidebar.mdwn
doc/examples/blog/tags.mdwn
doc/examples/blog/tags/life.mdwn
doc/examples/blog/tags/tech.mdwn
doc/examples/softwaresite/bugs.mdwn
doc/examples/softwaresite/bugs/done.mdwn
doc/examples/softwaresite/doc/faq.mdwn
doc/examples/softwaresite/index.mdwn
doc/examples/softwaresite/news.mdwn
doc/examples/softwaresite/templates/release.mdwn
doc/features.mdwn
doc/forum.mdwn
doc/forum/Accessing_meta_values_in_pages__63__.mdwn [new file with mode: 0644]
doc/forum/Adding_new_markup_to_markdown.mdwn [new file with mode: 0644]
doc/forum/Can_OpenID_users_be_adminusers__63__.mdwn [new file with mode: 0644]
doc/forum/Darcs_as_the_RCS___63__.mdwn [new file with mode: 0644]
doc/forum/How_does_ikiwiki_remember_times__63__.mdwn [new file with mode: 0644]
doc/forum/How_to_fix___34__does_not_map_to_Unicode__34___errors__63__.mdwn [new file with mode: 0644]
doc/forum/Is_there_a_pagespec_for_creation_dates_relative_to_today__63__.mdwn [new file with mode: 0644]
doc/forum/LaTeX_Error.mdwn [new file with mode: 0644]
doc/forum/Let__39__s_just_rely_on_backlinks_for_this__63__.mdwn [new file with mode: 0644]
doc/forum/Migrating_old_repository_to_new_ikiwiki_system__63__.mdwn [new file with mode: 0644]
doc/forum/Sidebar_with_links__63__.mdwn [new file with mode: 0644]
doc/forum/What_is_wrong_with_my_recentchange_page___63__.mdwn [new file with mode: 0644]
doc/forum/appear_if_you_are_login_or_not_in_a_page.mdwn [new file with mode: 0644]
doc/forum/bashman.mdwn [new file with mode: 0644]
doc/forum/chinese_character_problem.mdwn [new file with mode: 0644]
doc/forum/discussion.mdwn [new file with mode: 0644]
doc/forum/google_openid_broken__63__.mdwn [new file with mode: 0644]
doc/forum/ikiwiki__39__s_notion_of_time.mdwn [new file with mode: 0644]
doc/forum/ikiwiki_over_database__63__.wiki [new file with mode: 0644]
doc/forum/is_it_possible_to_NOT_add_openid2_meta_tags.mdwn [new file with mode: 0644]
doc/forum/managing_todo_lists.mdwn [new file with mode: 0644]
doc/forum/multi-user_setup_of_ikiwiki__44___gitosis_and_apache2_in_Debian_Sid.mdwn [new file with mode: 0644]
doc/forum/perl5lib_and_wrappers.mdwn [new file with mode: 0644]
doc/forum/speeding_up_ikiwiki.mdwn [new file with mode: 0644]
doc/forum/understanding_filter_hooks.mdwn [new file with mode: 0644]
doc/forum/usedirs___38___indexpages_using_problem.mdwn [new file with mode: 0644]
doc/forum/wiki_name_in_page_titles.mdwn [new file with mode: 0644]
doc/freesoftware.mdwn
doc/freesoftware/discussion.mdwn [new file with mode: 0644]
doc/git.mdwn
doc/ikiwiki-makerepo.mdwn
doc/ikiwiki-transition.mdwn
doc/ikiwiki-update-wikilist.mdwn
doc/ikiwiki.mdwn
doc/ikiwiki.setup [deleted file]
doc/ikiwiki/blog.mdwn [deleted file]
doc/ikiwiki/blog/discussion.mdwn [deleted file]
doc/ikiwiki/directive.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/aggregate.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/brokenlinks.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/brokenlinks/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/calendar.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/color.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/comment.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/copy.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/cut.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/cutpaste.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/edittemplate.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/format.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/fortune.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/graph.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/haiku.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/if.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/img.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/inline.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/inline/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/linkmap.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/listdirectives.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/map.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/map/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/meta.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/more.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/orphans.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/pagecount.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/pagestats.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/pagestats/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/pagetemplate.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/paste.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/ping.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/poll.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/polygen.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/postsparkline.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/progress.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/shortcut.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/sparkline.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/table.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/tag.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/taglink.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/template.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/testpagespec.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/testpagespec/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/teximg.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/toc.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/toggle.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/toggleable.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/version.mdwn [new file with mode: 0644]
doc/ikiwiki/formatting.mdwn
doc/ikiwiki/markdown.mdwn
doc/ikiwiki/openid.mdwn
doc/ikiwiki/pagespec.mdwn
doc/ikiwiki/pagespec/attachment.mdwn
doc/ikiwiki/pagespec/attachment/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/pagespec/discussion.mdwn
doc/ikiwiki/pagespec/po.mdwn [new file with mode: 0644]
doc/ikiwiki/preprocessordirective.mdwn [deleted file]
doc/ikiwiki/searching.mdwn
doc/ikiwiki/wikilink.mdwn
doc/ikiwiki/wikilink/discussion.mdwn
doc/ikiwikiusers.mdwn
doc/ikiwikiusers/discussion.mdwn
doc/index.mdwn
doc/index/discussion.mdwn
doc/index/openid/discussion.mdwn [new file with mode: 0644]
doc/install.mdwn
doc/install/discussion.mdwn
doc/news.mdwn
doc/news/code_swarm.mdwn [new file with mode: 0644]
doc/news/code_swarm/code_swarm.config [new file with mode: 0644]
doc/news/code_swarm/code_swarm_log.pl [new file with mode: 0755]
doc/news/code_swarm/screenshot.png [new file with mode: 0644]
doc/news/discussion.mdwn
doc/news/git_push_to_this_wiki.mdwn [new file with mode: 0644]
doc/news/git_push_to_this_wiki/discussion.mdwn [new file with mode: 0644]
doc/news/ikiwiki_version_2.0.mdwn
doc/news/ikiwiki_version_3.0.mdwn [new file with mode: 0644]
doc/news/openid.mdwn
doc/news/openid/discussion.mdwn
doc/news/server_speed.mdwn
doc/news/version_2.48.mdwn [deleted file]
doc/news/version_2.49.mdwn [deleted file]
doc/news/version_2.50.mdwn [deleted file]
doc/news/version_2.51.mdwn [deleted file]
doc/news/version_2.52.mdwn [deleted file]
doc/news/version_3.141.mdwn [new file with mode: 0644]
doc/news/version_3.141/discussion.mdwn [new file with mode: 0644]
doc/news/version_3.1415.mdwn [new file with mode: 0644]
doc/news/version_3.14159.mdwn [new file with mode: 0644]
doc/news/version_3.141592.mdwn [new file with mode: 0644]
doc/page_locking.mdwn [deleted file]
doc/pagehistory.mdwn
doc/patch.mdwn
doc/patch/core.mdwn [new file with mode: 0644]
doc/plugins.mdwn
doc/plugins/404.mdwn [new file with mode: 0644]
doc/plugins/aggregate.mdwn
doc/plugins/aggregate/discussion.mdwn [new file with mode: 0644]
doc/plugins/amazon_s3.mdwn
doc/plugins/anonok.mdwn
doc/plugins/attachment.mdwn
doc/plugins/autoindex.mdwn [new file with mode: 0644]
doc/plugins/autoindex/discussion.mdwn [new file with mode: 0644]
doc/plugins/blogspam.mdwn [new file with mode: 0644]
doc/plugins/brokenlinks.mdwn
doc/plugins/calendar.mdwn
doc/plugins/calendar/discussion.mdwn [new file with mode: 0644]
doc/plugins/camelcase.mdwn
doc/plugins/color.mdwn [new file with mode: 0644]
doc/plugins/comments.mdwn [new file with mode: 0644]
doc/plugins/comments/discussion.mdwn [new file with mode: 0644]
doc/plugins/conditional.mdwn
doc/plugins/conditional/discussion.mdwn
doc/plugins/contrib.mdwn
doc/plugins/contrib/album.mdwn [new file with mode: 0644]
doc/plugins/contrib/attach.mdwn
doc/plugins/contrib/cvs.mdwn [new file with mode: 0644]
doc/plugins/contrib/cvs/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/default_content_for___42__copyright__42___and___42__license__42__.mdwn
doc/plugins/contrib/gallery.mdwn
doc/plugins/contrib/gallery/discussion.mdwn
doc/plugins/contrib/googlemaps.mdwn
doc/plugins/contrib/headinganchors.mdwn
doc/plugins/contrib/headinganchors/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/highlightcode.mdwn
doc/plugins/contrib/img.mdwn
doc/plugins/contrib/img/discussion.mdwn
doc/plugins/contrib/linguas.mdwn
doc/plugins/contrib/mailbox.mdwn [new file with mode: 0644]
doc/plugins/contrib/mailbox/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/mediawiki.mdwn [new file with mode: 0644]
doc/plugins/contrib/mediawiki/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/navbar.mdwn
doc/plugins/contrib/navbar/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/opml.mdwn [new file with mode: 0644]
doc/plugins/contrib/opml/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/postal.mdwn [new file with mode: 0644]
doc/plugins/contrib/postal/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/rsync.mdwn [new file with mode: 0644]
doc/plugins/contrib/rsync/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/sar.mdwn
doc/plugins/contrib/siterel2pagerel.mdwn
doc/plugins/contrib/sourcehighlight.mdwn
doc/plugins/contrib/syntax.mdwn
doc/plugins/contrib/tex4ht.mdwn
doc/plugins/contrib/texinfo.mdwn
doc/plugins/contrib/trail.mdwn [new file with mode: 0644]
doc/plugins/contrib/unixauth.mdwn [new file with mode: 0644]
doc/plugins/contrib/unixauth/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/unixrelpagespec.mdwn [new file with mode: 0644]
doc/plugins/creole.mdwn
doc/plugins/creole/discussion.mdwn [new file with mode: 0644]
doc/plugins/cutpaste.mdwn [new file with mode: 0644]
doc/plugins/ddate.mdwn
doc/plugins/discussion.mdwn
doc/plugins/editdiff.mdwn
doc/plugins/editdiff/discussion.mdwn [new file with mode: 0644]
doc/plugins/editpage.mdwn [new file with mode: 0644]
doc/plugins/edittemplate.mdwn
doc/plugins/embed.mdwn
doc/plugins/favicon.mdwn
doc/plugins/filecheck.mdwn [new file with mode: 0644]
doc/plugins/filecheck/discussion.mdwn [new file with mode: 0644]
doc/plugins/format.mdwn [new file with mode: 0644]
doc/plugins/format/discussion.mdwn [new file with mode: 0644]
doc/plugins/fortune.mdwn
doc/plugins/getsource.mdwn [new file with mode: 0644]
doc/plugins/goodstuff.mdwn
doc/plugins/google.mdwn [new file with mode: 0644]
doc/plugins/google/discussion.mdwn [new file with mode: 0644]
doc/plugins/googlecalendar.mdwn [deleted file]
doc/plugins/goto.mdwn [new file with mode: 0644]
doc/plugins/graphviz.mdwn
doc/plugins/haiku.mdwn
doc/plugins/highlight.mdwn [new file with mode: 0644]
doc/plugins/highlight/discussion.mdwn [new file with mode: 0644]
doc/plugins/hnb.mdwn
doc/plugins/html.mdwn
doc/plugins/htmlbalance.mdwn [new file with mode: 0644]
doc/plugins/htmlbalance/discussion.mdwn [new file with mode: 0644]
doc/plugins/htmlscrubber.mdwn
doc/plugins/htmlscrubber/discussion.mdwn [new file with mode: 0644]
doc/plugins/htmltidy.mdwn
doc/plugins/httpauth.mdwn
doc/plugins/img.mdwn
doc/plugins/img/discussion.mdwn
doc/plugins/inline.mdwn
doc/plugins/install.mdwn
doc/plugins/link.mdwn
doc/plugins/linkmap.mdwn
doc/plugins/listdirectives.mdwn [new file with mode: 0644]
doc/plugins/lockedit.mdwn
doc/plugins/map.mdwn
doc/plugins/map/discussion.mdwn
doc/plugins/mdwn.mdwn
doc/plugins/mdwn/discussion.mdwn [new file with mode: 0644]
doc/plugins/meta.mdwn
doc/plugins/meta/discussion.mdwn
doc/plugins/mirrorlist.mdwn
doc/plugins/more.mdwn
doc/plugins/more/discussion.mdwn [new file with mode: 0644]
doc/plugins/opendiscussion.mdwn
doc/plugins/openid.mdwn
doc/plugins/openid/discussion.mdwn
doc/plugins/orphans.mdwn
doc/plugins/orphans/discussion.mdwn [new file with mode: 0644]
doc/plugins/otl.mdwn
doc/plugins/pagecount.mdwn
doc/plugins/pagestats.mdwn
doc/plugins/pagetemplate.mdwn
doc/plugins/parentlinks.mdwn [new file with mode: 0644]
doc/plugins/passwordauth.mdwn
doc/plugins/passwordauth/discussion.mdwn
doc/plugins/pingee.mdwn
doc/plugins/pinger.mdwn
doc/plugins/plaintext/discussion.mdwn [deleted file]
doc/plugins/po.mdwn [new file with mode: 0644]
doc/plugins/po/discussion.mdwn [new file with mode: 0644]
doc/plugins/poll.mdwn
doc/plugins/polygen.mdwn
doc/plugins/postsparkline.mdwn
doc/plugins/prettydate.mdwn
doc/plugins/progress.mdwn [new file with mode: 0644]
doc/plugins/rawhtml.mdwn
doc/plugins/recentchanges.mdwn
doc/plugins/recentchangesdiff.mdwn
doc/plugins/relativedate.mdwn [new file with mode: 0644]
doc/plugins/remove.mdwn [new file with mode: 0644]
doc/plugins/rename.mdwn [new file with mode: 0644]
doc/plugins/repolist.mdwn [new file with mode: 0644]
doc/plugins/rst.mdwn
doc/plugins/rst/discussion.mdwn
doc/plugins/search.mdwn
doc/plugins/shortcut.mdwn
doc/plugins/shortcut/discussion.mdwn
doc/plugins/sidebar.mdwn
doc/plugins/signinedit.mdwn
doc/plugins/smiley.mdwn
doc/plugins/sparkline.mdwn
doc/plugins/table.mdwn
doc/plugins/table/discussion.mdwn
doc/plugins/tag.mdwn
doc/plugins/tag/discussion.mdwn
doc/plugins/template.mdwn
doc/plugins/testpagespec.mdwn
doc/plugins/teximg.mdwn
doc/plugins/textile.mdwn
doc/plugins/textile/discussion.mdwn [deleted file]
doc/plugins/toc.mdwn
doc/plugins/toggle.mdwn
doc/plugins/toggle/discussion.mdwn
doc/plugins/txt.mdwn
doc/plugins/txt/discussion.mdwn [new file with mode: 0644]
doc/plugins/type/date.mdwn [new file with mode: 0644]
doc/plugins/type/web.mdwn [new file with mode: 0644]
doc/plugins/typography.mdwn
doc/plugins/underlay.mdwn [new file with mode: 0644]
doc/plugins/version.mdwn
doc/plugins/websetup.mdwn [new file with mode: 0644]
doc/plugins/wikitext.mdwn
doc/plugins/wmd.mdwn [new file with mode: 0644]
doc/plugins/write.mdwn
doc/plugins/write/discussion.mdwn [new file with mode: 0644]
doc/plugins/write/external.mdwn
doc/plugins/write/tutorial.mdwn
doc/post-commit/discussion.mdwn
doc/rcs.mdwn
doc/rcs/darcs.mdwn [new file with mode: 0644]
doc/rcs/details.mdwn
doc/rcs/git.mdwn
doc/rcs/git/discussion.mdwn
doc/rcs/mercurial.mdwn
doc/rcs/monotone.mdwn
doc/rcs/tla.mdwn
doc/recentchanges.mdwn
doc/roadmap.mdwn
doc/robots.txt [new file with mode: 0644]
doc/sandbox.mdwn
doc/sandbox/Blagging_is_cool.mdwn [new file with mode: 0644]
doc/sandbox/Bleep.mdwn [new file with mode: 0644]
doc/sandbox/I_hate_making_new_blog_entries_-_sometimes.wiki [new file with mode: 0644]
doc/sandbox/Omgwtf_a_blof_post__33____33____33____33____33__1__33__1__33__11111__33____33____33__1__33__1__33____33__1five.html [new file with mode: 0644]
doc/sandbox/Test:_with_a_colon_in_its_name.mdwn [new file with mode: 0644]
doc/sandbox/Teximg.mdwn [new file with mode: 0644]
doc/sandbox/Try_some_math_formulas.mdwn [new file with mode: 0644]
doc/sandbox/castle/discussion/jon_tests_too.mdwn
doc/sandbox/discussion.mdwn [new file with mode: 0644]
doc/sandbox/foobak.mdwn [new file with mode: 0644]
doc/sandbox/test.mdwn [new file with mode: 0644]
doc/sandbox/test_nested_inlines.mdwn
doc/sandbox/한글.mdwn [new file with mode: 0644]
doc/sandbox/한글페이지.mdwn [new file with mode: 0644]
doc/security.mdwn
doc/setup.mdwn
doc/setup/byhand.mdwn [new file with mode: 0644]
doc/setup/discussion.mdwn
doc/shortcuts.mdwn
doc/sitemap.mdwn
doc/smileys.mdwn
doc/soc.mdwn
doc/soc/ideas.mdwn
doc/style.css
doc/tags.mdwn
doc/tags/discussion.mdwn
doc/templates.mdwn
doc/templates/discussion.mdwn [new file with mode: 0644]
doc/templates/gitbranch.mdwn [new file with mode: 0644]
doc/templates/plugin.mdwn
doc/tipjar.mdwn
doc/tips.mdwn
doc/tips/Adding_Disqus_to_your_wiki.mdwn [new file with mode: 0644]
doc/tips/DreamHost.mdwn
doc/tips/DreamHost/discussion.mdwn
doc/tips/Git_repository_and_web_server_on_different_hosts.mdwn [new file with mode: 0644]
doc/tips/Google_custom_search.mdwn
doc/tips/Importing_posts_from_Wordpress.mdwn
doc/tips/Importing_posts_from_Wordpress/discussion.mdwn [new file with mode: 0644]
doc/tips/add_chatterbox_to_blog.mdwn [new file with mode: 0644]
doc/tips/add_chatterbox_to_blog/discussion.mdwn [new file with mode: 0644]
doc/tips/apache_cgi.mdwn [deleted file]
doc/tips/blog_script.mdwn
doc/tips/comments_feed.mdwn [new file with mode: 0644]
doc/tips/convert_MoinMoin_and_TWiki_to_ikiwiki.mdwn [new file with mode: 0644]
doc/tips/convert_mediawiki_to_ikiwiki.mdwn [new file with mode: 0644]
doc/tips/convert_mediawiki_to_ikiwiki/discussion.mdwn [new file with mode: 0644]
doc/tips/distributed_wikis.mdwn
doc/tips/distributed_wikis/discussion.mdwn [new file with mode: 0644]
doc/tips/dot_cgi.mdwn [new file with mode: 0644]
doc/tips/dot_cgi/discussion.mdwn [new file with mode: 0644]
doc/tips/emacs_syntax_highlighting.mdwn [new file with mode: 0644]
doc/tips/embedding_content.mdwn [new file with mode: 0644]
doc/tips/github.mdwn [new file with mode: 0644]
doc/tips/howto_avoid_flooding_aggregators.mdwn
doc/tips/importing_posts_from_typo.mdwn [new file with mode: 0644]
doc/tips/importing_posts_from_wordpress/ikiwiki-wordpress-import.mdwn [new file with mode: 0644]
doc/tips/inside_dot_ikiwiki.mdwn
doc/tips/inside_dot_ikiwiki/discussion.mdwn
doc/tips/integrated_issue_tracking_with_ikiwiki.mdwn
doc/tips/laptop_wiki_with_git.mdwn
doc/tips/laptop_wiki_with_git/discussion.mdwn
doc/tips/laptop_wiki_with_git_extended.mdwn
doc/tips/markdown_and_eclipse.mdwn [new file with mode: 0644]
doc/tips/mathopd_permissions.mdwn [new file with mode: 0644]
doc/tips/nearlyfreespeech.mdwn
doc/tips/parentlinks_style.mdwn [new file with mode: 0644]
doc/tips/untrusted_git_push.mdwn [new file with mode: 0644]
doc/tips/untrusted_git_push/discussion.mdwn [new file with mode: 0644]
doc/tips/upgrade_to_3.0.mdwn [new file with mode: 0644]
doc/tips/using_the_web_interface_with_a_real_text_editor.mdwn
doc/tips/vim_syntax_highlighting.mdwn
doc/tips/vim_syntax_highlighting/discussion.mdwn
doc/tips/vim_syntax_highlighting/ikiwiki.vim
doc/tips/wikiannounce.mdwn
doc/todo.mdwn
doc/todo/ACL.mdwn
doc/todo/A_page_that_inlines_pages__61____34____42____34___results_in_unnecessary_feed_generation.mdwn
doc/todo/Account_moderation.mdwn
doc/todo/Add_DATE_parameter_for_use_in_templates.mdwn
doc/todo/Add_a_plugin_to_list_available_pre-processor_commands.mdwn [new file with mode: 0644]
doc/todo/Add_camelcase_exclusions.mdwn [new file with mode: 0644]
doc/todo/Add_label_to_search_form_input_field.mdwn
doc/todo/Add_showdown_GUI_input__47__edit.mdwn
doc/todo/Add_space_before_slash_in_parent_links.mdwn
doc/todo/Add_support_for_latest_Text::Markdown_as_found_on_CPAN.mdwn
doc/todo/Adjust_goodstuff.mdwn
doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn [new file with mode: 0644]
doc/todo/Allow_change_of_wiki_file_types.mdwn [new file with mode: 0644]
doc/todo/Allow_disabling_edit_and_preferences_links.mdwn [new file with mode: 0644]
doc/todo/Allow_edittemplate_to_set_file_type.mdwn [new file with mode: 0644]
doc/todo/Allow_filenames_that_are_all_type.mdwn [new file with mode: 0644]
doc/todo/Allow_web_edit_form_comment_field_to_be_mandatory.mdwn
doc/todo/BTS_integration.mdwn
doc/todo/Bestdir_along_with_bestlink_in_IkiWiki.pm.mdwn
doc/todo/Bestdir_along_with_bestlink_in_IkiWiki.pm/discussion.mdwn [new file with mode: 0644]
doc/todo/Better_bug_tracking_support.mdwn
doc/todo/BibTeX.mdwn
doc/todo/CGI_method_to_pullrefresh.mdwn
doc/todo/CVS_backend.mdwn
doc/todo/Configurable_minimum_length_of_log_message_for_web_edits.mdwn
doc/todo/Default_text_for_new_pages.mdwn [new file with mode: 0644]
doc/todo/Enable_filtering_of_files_indexed_for_search.mdwn
doc/todo/Feature_parity_with_Trac.mdwn [new file with mode: 0644]
doc/todo/Gallery.mdwn
doc/todo/Give_access_to_more_TMPL__95__VAR_variables_in_templates_inserted_by_the_template_plugin.mdwn [new file with mode: 0644]
doc/todo/Google_Sitemap_protocol.mdwn
doc/todo/Have_xapian_index_pdf__44___openoffice__44___documents.mdwn [new file with mode: 0644]
doc/todo/Improve_display_of_OpenIDs.mdwn [new file with mode: 0644]
doc/todo/Inline_plugin_option_to_show_full_page_path.mdwn
doc/todo/Location_of_pages_starting_with___36__tagbase_should_be_in__by_default.mdwn
doc/todo/Mailing_list.mdwn [new file with mode: 0644]
doc/todo/Make_example_setup_file_consistent.mdwn [new file with mode: 0644]
doc/todo/Move_teximg_latex_preamble_to_config_file.mdwn [new file with mode: 0644]
doc/todo/Moving_Pages.mdwn
doc/todo/New_preprocessor_directive_syntax.mdwn
doc/todo/New_preprocessor_directive_syntax/discussion.mdwn
doc/todo/OpenSearch.mdwn
doc/todo/Option_to_make_title_an_h1__63__.mdwn
doc/todo/Overlay_directory_for_pagetemplates.mdwn
doc/todo/Post-compilation_inclusion_of_the_sidebar.mdwn
doc/todo/RSS_fields.mdwn
doc/todo/Raw_view_link.mdwn
doc/todo/RecentChanges_page_links_without_cgi_wrapper.mdwn [new file with mode: 0644]
doc/todo/Separate_OpenIDs_and_usernames.mdwn [new file with mode: 0644]
doc/todo/Set_arbitrary_date_to_be_used_by_calendar_plugin.mdwn
doc/todo/Short_wikilinks.mdwn
doc/todo/Silence_monotone_warning.mdwn [new file with mode: 0644]
doc/todo/Suggested_location_should_be_subpage_if_siblings_exist.mdwn
doc/todo/Support_XML-RPC-based_blogging.mdwn
doc/todo/Support_tab_insertion_in_textarea.mdwn
doc/todo/Support_wildcard_inside_of_link__40____41___within_a_pagespec.mdwn
doc/todo/Tags_list_in_page_footer_uses_basename.mdwn [new file with mode: 0644]
doc/todo/Unit_tests.mdwn [new file with mode: 0644]
doc/todo/Untrusted_push_in_Monotone.mdwn [new file with mode: 0644]
doc/todo/Updated_bug_tracking_example.mdwn [new file with mode: 0644]
doc/todo/Wrapper_config_with_multiline_regexp.mdwn
doc/todo/__42__forward__42__ing_functionality_for_the_meta_plugin.mdwn
doc/todo/a_navbar_based_on_page_properties.mdwn
doc/todo/ability_to_force_particular_UUIDs_on_blog_posts.mdwn
doc/todo/absolute_urls_in_wikilinks.mdwn
doc/todo/access_keys.mdwn
doc/todo/add_forward_age_sorting_option_to_inline.mdwn [new file with mode: 0644]
doc/todo/adding_new_pages_by_using_the_web_interface.mdwn
doc/todo/aggregate_401_handling.mdwn
doc/todo/aggregate_to_internal_pages.mdwn
doc/todo/allow_CGI_to_create_dynamic_pages.mdwn
doc/todo/allow_creation_of_non-existent_pages.mdwn
doc/todo/allow_disabling_backlinks.mdwn [new file with mode: 0644]
doc/todo/allow_full_post_from_the___34__add_a_new_post__34___form.mdwn
doc/todo/allow_site-wide_meta_definitions.mdwn [new file with mode: 0644]
doc/todo/anti-spam_protection.mdwn
doc/todo/apache_404_ErrorDocument_handler.mdwn [new file with mode: 0644]
doc/todo/applydiff_plugin.mdwn [new file with mode: 0644]
doc/todo/attachments.mdwn
doc/todo/auto-create_tag_pages_according_to_a_template.mdwn
doc/todo/automatic_use_of_syntax_plugin_on_source_code_files.mdwn
doc/todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion.mdwn [new file with mode: 0644]
doc/todo/avatar.mdwn [new file with mode: 0644]
doc/todo/avoid_thrashing.mdwn [new file with mode: 0644]
doc/todo/backlinks_result_is_lossy.mdwn [new file with mode: 0644]
doc/todo/basewiki_should_be_self_documenting.mdwn
doc/todo/blogpost_plugin.mdwn
doc/todo/blogspam_training.mdwn [new file with mode: 0644]
doc/todo/bzr.mdwn
doc/todo/calendar_--_archive_browsing_via_a_calendar_frontend.mdwn
doc/todo/canonical_feed_location.mdwn
doc/todo/cas_authentication.mdwn [new file with mode: 0644]
doc/todo/clear_page_to_delete.mdwn [new file with mode: 0644]
doc/todo/clickable-openid-urls-in-logs.mdwn
doc/todo/color_plugin.mdwn [new file with mode: 0644]
doc/todo/comment_by_mail.mdwn
doc/todo/comment_by_mail/discussion.mdwn [new file with mode: 0644]
doc/todo/comments.mdwn [new file with mode: 0644]
doc/todo/conditional_text_based_on_ikiwiki_features.mdwn
doc/todo/conditional_underlay_files.mdwn
doc/todo/configurable_timezones.mdwn
doc/todo/copyright_based_on_pagespec.mdwn [new file with mode: 0644]
doc/todo/correct_published_and_updated_time_information_for_the_feeds.mdwn
doc/todo/ctime_on_blog_post_pages_.mdwn
doc/todo/darcs.mdwn
doc/todo/datearchives-plugin.mdwn
doc/todo/different_search_engine.mdwn
doc/todo/directive_docs.mdwn [new file with mode: 0644]
doc/todo/discussion_page_as_blog.mdwn
doc/todo/discussion_page_as_blog/discussion/castle/discussion.mdwn
doc/todo/discussion_page_as_blog/discussion/castle/discussion/Don__39__t_like_foo.mdwn
doc/todo/done.mdwn
doc/todo/doxygen_support.mdwn
doc/todo/dynamic_rootpage.mdwn
doc/todo/edit_form:_no_fixed_size_for_textarea.mdwn [new file with mode: 0644]
doc/todo/else_parameter_for_map_plugin.mdwn [new file with mode: 0644]
doc/todo/enable-htaccess-files.mdwn
doc/todo/fastcgi_or_modperl_installation_instructions.mdwn [new file with mode: 0644]
doc/todo/fileupload.mdwn
doc/todo/fileupload/soc-proposal/discussion.mdwn
doc/todo/firm_up_plugin_interface.mdwn
doc/todo/format_escape.mdwn
doc/todo/fortune:_select_options_via_environment.mdwn
doc/todo/friendly_markup_names.mdwn [new file with mode: 0644]
doc/todo/generated_po_stuff_not_ignored_by_git.mdwn [new file with mode: 0644]
doc/todo/generic___39__do__61__goto__39___for_CGI.mdwn [new file with mode: 0644]
doc/todo/geotagging.mdwn
doc/todo/git-rev-list_requires_relative_path___40__fixes_git_ctime__41__.mdwn
doc/todo/git_attribution.mdwn
doc/todo/git_attribution/discussion.mdwn
doc/todo/graphviz.mdwn
doc/todo/hard-coded_location_for_man_pages_and_w3m_cgi_wrapper.mdwn
doc/todo/hidden_links__47__tags.mdwn [new file with mode: 0644]
doc/todo/htmlvalidation.mdwn
doc/todo/httpauth_feature_parity_with_passwordauth.mdwn [new file with mode: 0644]
doc/todo/improved_parentlinks_styling.mdwn
doc/todo/index.html_allowed.mdwn
doc/todo/inline:_numerical_ordering_by_title.mdwn [new file with mode: 0644]
doc/todo/inline_plugin:_ability_to_override_feed_name.mdwn [new file with mode: 0644]
doc/todo/inline_plugin:_hide_feed_buttons_if_empty.mdwn [new file with mode: 0644]
doc/todo/inline_plugin:_specifying_ordered_page_names.mdwn [new file with mode: 0644]
doc/todo/inline_postform_autotitles.mdwn [new file with mode: 0644]
doc/todo/inlines_inheriting_links.mdwn [new file with mode: 0644]
doc/todo/interactive_todo_lists.mdwn [new file with mode: 0644]
doc/todo/l10n.mdwn
doc/todo/language_definition_for_the_meta_plugin.mdwn
doc/todo/latex.mdwn
doc/todo/let_inline_plugin_use_pagetemplates.mdwn
doc/todo/limit_the_markup_formats_available_for_editing.mdwn
doc/todo/linktitle.mdwn
doc/todo/location_of_external_plugins.mdwn [new file with mode: 0644]
doc/todo/location_of_ikiwiki-w3m.cgi.mdwn [new file with mode: 0644]
doc/todo/matching_different_kinds_of_links.mdwn [new file with mode: 0644]
doc/todo/mbox.mdwn [new file with mode: 0644]
doc/todo/mdwn_preview.mdwn [new file with mode: 0644]
doc/todo/mercurial.mdwn
doc/todo/meta_rcsid.mdwn
doc/todo/metadata.mdwn
doc/todo/minor_adjustment_to_setup_documentation_for_recentchanges_feeds.mdwn
doc/todo/mirrorlist_with_per-mirror_usedirs_settings.mdwn [new file with mode: 0644]
doc/todo/missingparents.pm.mdwn
doc/todo/modify_page_filename_in_plugin.mdwn [new file with mode: 0644]
doc/todo/more_class__61____34____34___for_css.mdwn
doc/todo/more_customisable_titlepage_function.mdwn
doc/todo/more_flexible_inline_postform.mdwn [new file with mode: 0644]
doc/todo/mtime.mdwn
doc/todo/multiple_output_formats.mdwn
doc/todo/multiple_repository_support.mdwn [new file with mode: 0644]
doc/todo/multiple_templates.mdwn
doc/todo/natural_sorting.mdwn [new file with mode: 0644]
doc/todo/need_global_renamepage_hook.mdwn [new file with mode: 0644]
doc/todo/nested_preprocessor_directives.mdwn
doc/todo/online_configuration.mdwn [new file with mode: 0644]
doc/todo/optimisations.mdwn
doc/todo/overriding_displayed_modification_time.mdwn [new file with mode: 0644]
doc/todo/page_edit_disable.mdwn [new file with mode: 0644]
doc/todo/pagedeletion.mdwn
doc/todo/pageindexes.mdwn
doc/todo/pagespec_relative_to_a_target.mdwn
doc/todo/pagestats_among_a_subset_of_pages.mdwn [new file with mode: 0644]
doc/todo/parse_debian_packages.mdwn
doc/todo/passwordauth:_sendmail_interface.mdwn
doc/todo/paste_plugin.mdwn [new file with mode: 0644]
doc/todo/pedigree_plugin.mdwn [new file with mode: 0644]
doc/todo/pingback_support.mdwn [new file with mode: 0644]
doc/todo/plugin.mdwn
doc/todo/preprocessor_directive_for_proposed_changes.mdwn
doc/todo/pretty-print_OpenIDs_even_if_not_enabled.mdwn [new file with mode: 0644]
doc/todo/progressbar_plugin.mdwn [new file with mode: 0644]
doc/todo/provide_a_mailing_list.mdwn
doc/todo/provide_inline_diffs_in_recentchanges.mdwn
doc/todo/provide_sha1_for_git_diffurl.mdwn [new file with mode: 0644]
doc/todo/quieten-bzr.mdwn
doc/todo/rcs.mdwn
doc/todo/rcs_updates_needed.mdwn [new file with mode: 0644]
doc/todo/recentchanges.mdwn
doc/todo/redirect_automatically_after_rename.mdwn [new file with mode: 0644]
doc/todo/rel_attribute_for_links.mdwn
doc/todo/relative_pagespec_deficiency.mdwn [new file with mode: 0644]
doc/todo/remove_basewiki_redir_pages.mdwn
doc/todo/replace_HTML::Template_with_Template_Toolkit.mdwn
doc/todo/require_CAPTCHA_to_edit.mdwn
doc/todo/review_mechanism.mdwn
doc/todo/rewrite_ikiwiki_in_haskell.mdwn [new file with mode: 0644]
doc/todo/rewrite_ikiwiki_in_haskell/discussion.mdwn [new file with mode: 0644]
doc/todo/rss_title_description.mdwn
doc/todo/search_terms.mdwn
doc/todo/section-numbering.mdwn [new file with mode: 0644]
doc/todo/shortcut_link_text.mdwn
doc/todo/shortcut_optional_parameters.mdwn
doc/todo/shortcut_with_different_link_text.mdwn
doc/todo/shortcut_with_no_url_parameter__44___only_desc.mdwn
doc/todo/should_optimise_pagespecs.mdwn
doc/todo/simple_text_parsing_or_regex_in_template_or_shortcut.mdwn
doc/todo/skip_option_for_inline_plugin.mdwn
doc/todo/smileys_do_not_work_in_PreprocessorDirective_arguments.mdwn
doc/todo/softlinks.mdwn [new file with mode: 0644]
doc/todo/source_link.mdwn
doc/todo/structured_page_data.mdwn [new file with mode: 0644]
doc/todo/structured_page_data/discussion.mdwn [new file with mode: 0644]
doc/todo/stylesheet_suggestion_for_verbatim_content.mdwn
doc/todo/support_creole_markup.mdwn
doc/todo/support_for_SDF_documents.mdwn
doc/todo/support_for_plugins_written_in_other_languages.mdwn
doc/todo/supporting_comments_via_disussion_pages.mdwn
doc/todo/syntax_highlighting.mdwn [new file with mode: 0644]
doc/todo/syntax_highlighting/discussion.mdwn [new file with mode: 0644]
doc/todo/table_with_header_column.mdwn [new file with mode: 0644]
doc/todo/tag_pagespec_function.mdwn [new file with mode: 0644]
doc/todo/tagging_with_a_publication_date.mdwn
doc/todo/tags.mdwn
doc/todo/target_filter_for_brokenlinks.mdwn [new file with mode: 0644]
doc/todo/tidy_git__39__s_ctime_debug_output.mdwn
doc/todo/tla.mdwn
doc/todo/tmplvars_plugin.mdwn
doc/todo/tmplvars_plugin/discussion.mdwn [new file with mode: 0644]
doc/todo/toc_plugin:_set_a_header_ceiling___40__opposite_of_levels__61____41__.mdwn [new file with mode: 0644]
doc/todo/toc_plugin_to_skip_one_level.mdwn
doc/todo/toggle_initial_state.mdwn
doc/todo/tracking_bugs_with_dependencies.mdwn [new file with mode: 0644]
doc/todo/turn_edittemplate_verbosity_off_by_default.mdwn
doc/todo/typography_plugin_configuration.mdwn
doc/todo/unaccent_url_instead_of_encoding.mdwn
doc/todo/unified_temporary_file__47__directory_handling.mdwn [new file with mode: 0644]
doc/todo/varioki_--_add_template_variables___40__with_closures_for_values__41___in_ikiwiki.setup.mdwn
doc/todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both.mdwn [new file with mode: 0644]
doc/todo/web_gui_for_managing_tags.mdwn
doc/todo/wiki-formatted_comments_with_syntax_plugin.mdwn
doc/todo/wikitrails.mdwn [new file with mode: 0644]
doc/todo/wikitrails/discussion.mdwn [new file with mode: 0644]
doc/todo/wikiwyg.mdwn
doc/todo/wikiwyg/discussion.mdwn
doc/translation.mdwn
doc/translation/discussion.mdwn
doc/usage.mdwn
doc/users.mdwn
doc/users/Christine_Spang.mdwn [new file with mode: 0644]
doc/users/Edward_Betts.mdwn
doc/users/Jimmy_Tang.mdwn [new file with mode: 0644]
doc/users/KarlMW.mdwn
doc/users/StevenBlack.mdwn [new file with mode: 0644]
doc/users/TaylorKillian.mdwn
doc/users/TimBosse.mdwn [new file with mode: 0644]
doc/users/Tim_Lavoie.mdwn [new file with mode: 0644]
doc/users/Will.mdwn [new file with mode: 0644]
doc/users/adamshand.mdwn
doc/users/ajt.mdwn [new file with mode: 0644]
doc/users/alexander.mdwn [new file with mode: 0644]
doc/users/arpitjain.mdwn
doc/users/bbb.mdwn
doc/users/bstpierre.mdwn [new file with mode: 0644]
doc/users/cfm.mdwn [new file with mode: 0644]
doc/users/chris.mdwn
doc/users/cord.mdwn [new file with mode: 0644]
doc/users/dato.mdwn
doc/users/dom.mdwn [new file with mode: 0644]
doc/users/donmarti.mdwn [new file with mode: 0644]
doc/users/harishcm.mdwn [new file with mode: 0644]
doc/users/harningt.mdwn
doc/users/hb.mdwn
doc/users/hb/discussion.mdwn
doc/users/hendry.mdwn [new file with mode: 0644]
doc/users/intrigeri.mdwn [new file with mode: 0644]
doc/users/jasonblevins.mdwn
doc/users/jelmer.mdwn [new file with mode: 0644]
doc/users/jeremyreed.mdwn
doc/users/joey.mdwn
doc/users/jogo.mdwn [new file with mode: 0644]
doc/users/jon.mdwn [new file with mode: 0644]
doc/users/jonassmedegaard.mdwn
doc/users/jondowland.mdwn [deleted file]
doc/users/josephturian.mdwn [new file with mode: 0644]
doc/users/joshtriplett.mdwn
doc/users/jrblevin.mdwn [new file with mode: 0644]
doc/users/jwalzer.mdwn [new file with mode: 0644]
doc/users/kyle.mdwn
doc/users/madduck.mdwn
doc/users/marcelomagallon.mdwn
doc/users/neale.mdwn [new file with mode: 0644]
doc/users/nolan.mdwn [new file with mode: 0644]
doc/users/perolofsson.mdwn
doc/users/ptecza.mdwn
doc/users/sabr.mdwn
doc/users/schmonz.mdwn [new file with mode: 0644]
doc/users/seanh.mdwn [new file with mode: 0644]
doc/users/simonraven.mdwn [new file with mode: 0644]
doc/users/smcv.mdwn [new file with mode: 0644]
doc/users/smcv/gallery.mdwn [new file with mode: 0644]
doc/users/svend.mdwn [new file with mode: 0644]
doc/users/tschwinge.mdwn
doc/users/victormoral.mdwn
doc/users/weakish.mdwn [new file with mode: 0644]
doc/users/weakishjiang.mdwn [new file with mode: 0644]
doc/users/xma.mdwn [new file with mode: 0644]
doc/users/xma/discussion.mdwn [new file with mode: 0644]
doc/w3mmode/ikiwiki.setup
doc/wikiicons/openidlogin-bg.gif
doc/wikiicons/search-bg.gif [new file with mode: 0644]
doc/wikitemplates.mdwn
doc/wikitemplates/discussion.mdwn [new file with mode: 0644]
doc/wishlist.mdwn
docwiki.setup
gitremotes [new file with mode: 0755]
ikiwiki-makerepo
ikiwiki-transition
ikiwiki-update-wikilist
ikiwiki.in
plugins/externaldemo
plugins/rst
pm_filter
po/Makefile
po/bg.po
po/cs.po
po/da.po
po/de.po
po/es.po
po/fr.po
po/gu.po
po/ikiwiki.pot
po/it.po [new file with mode: 0644]
po/pl.po
po/po2wiki [new file with mode: 0755]
po/sv.po
po/underlay.setup [new file with mode: 0644]
po/underlays/basewiki/ikiwiki.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/blog.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/directive.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/formatting.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/markdown.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/openid.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/attachment.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/po.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/preprocessordirective.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/searching.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage/linkingrules.da.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/wikilink.da.po [new file with mode: 0644]
po/underlays/basewiki/index.da.po [new file with mode: 0644]
po/underlays/basewiki/recentchanges.da.po [new file with mode: 0644]
po/underlays/basewiki/sandbox.da.po [new file with mode: 0644]
po/underlays/basewiki/shortcuts.da.po [new file with mode: 0644]
po/underlays/basewiki/templates.da.po [new file with mode: 0644]
po/underlays/basewiki/templates/note.da.po [new file with mode: 0644]
po/underlays/basewiki/templates/popup.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/aggregate.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/brokenlinks.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/calendar.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/color.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/comment.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/copy.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cut.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cutpaste.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/edittemplate.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/format.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/fortune.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/graph.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/haiku.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/if.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/img.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/inline.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/linkmap.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/listdirectives.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/map.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/meta.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/more.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/orphans.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagecount.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagestats.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagetemplate.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/paste.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/ping.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/poll.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/polygen.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/postsparkline.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/progress.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/shortcut.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/sparkline.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/table.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/tag.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/taglink.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/template.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/testpagespec.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/teximg.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toc.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggle.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggleable.da.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/version.da.po [new file with mode: 0644]
po/underlays/smiley/smileys.da.po [new file with mode: 0644]
po/vi.po
t/404.t [new file with mode: 0755]
t/basewiki_brokenlinks.t
t/basewiki_brokenlinks/index.mdwn
t/bazaar.t
t/beautify_urlpath.t [new file with mode: 0755]
t/git.t
t/html.t
t/htmlbalance.t [new file with mode: 0755]
t/index.t
t/linkpage.t [new file with mode: 0755]
t/mercurial.t
t/openiduser.t [new file with mode: 0755]
t/pagename.t
t/pagespec_match.t
t/pagespec_merge.t [deleted file]
t/pagetitle.t
t/pagetype.mdwn [deleted file]
t/parentlinks.t [new file with mode: 0755]
t/parentlinks/templates/parentlinks.tmpl [new file with mode: 0644]
t/permalink.t [new file with mode: 0755]
t/po.t [new file with mode: 0755]
t/preprocess.t
t/renamepage.t [new file with mode: 0755]
t/svn.t
t/syntax.t
t/tinyblog/index.mdwn [new file with mode: 0644]
t/tinyblog/post.mdwn [new file with mode: 0644]
t/titlepage.t
t/yesno.t [new file with mode: 0755]
templates/archivepage.tmpl
templates/atomitem.tmpl
templates/atompage.tmpl
templates/autoindex.tmpl [new file with mode: 0644]
templates/change.tmpl
templates/comment.tmpl [new file with mode: 0644]
templates/commentmoderation.tmpl [new file with mode: 0644]
templates/editcomment.tmpl [new file with mode: 0644]
templates/editconflict.tmpl [new file with mode: 0644]
templates/editcreationconflict.tmpl [new file with mode: 0644]
templates/editfailedsave.tmpl [new file with mode: 0644]
templates/editpage.tmpl
templates/editpagegone.tmpl [new file with mode: 0644]
templates/estseek.conf [deleted file]
templates/googleform.tmpl [new file with mode: 0644]
templates/inlinepage.tmpl
templates/microblog.tmpl [new file with mode: 0644]
templates/misc.tmpl
templates/page.tmpl
templates/pocreatepage.tmpl [new file with mode: 0644]
templates/renamesummary.tmpl [new file with mode: 0644]
templates/rssitem.tmpl
templates/searchform.tmpl
templates/searchquery.tmpl
templates/titlepage.tmpl
underlays/basewiki/blog.mdwn [deleted file]
underlays/basewiki/helponformatting.mdwn [deleted file]
underlays/basewiki/ikiwiki/blog.mdwn [deleted symlink]
underlays/basewiki/ikiwiki/directive.mdwn [new symlink]
underlays/basewiki/ikiwiki/pagespec/po.mdwn [new symlink]
underlays/basewiki/ikiwiki/preprocessordirective.mdwn [deleted symlink]
underlays/basewiki/ikiwiki/subpage [deleted symlink]
underlays/basewiki/ikiwiki/subpage/linkingrules.mdwn [new symlink]
underlays/basewiki/markdown.mdwn [deleted file]
underlays/basewiki/openid.mdwn [deleted file]
underlays/basewiki/pagespec.mdwn [deleted file]
underlays/basewiki/preprocessordirective.mdwn [deleted file]
underlays/basewiki/subpage.mdwn [deleted file]
underlays/basewiki/wikilink.mdwn [deleted file]
underlays/javascript/ikiwiki.js [new file with mode: 0644]
underlays/javascript/relativedate.js [new file with mode: 0644]
underlays/javascript/toggle.js [new file with mode: 0644]

index bb02bcb31de37ae41831c6be5c4cf85f9c207a42..8de36e2c8df25ab30f7fadeffbcdf25f189863f3 100644 (file)
@@ -1,3 +1,4 @@
+ikiwiki.setup
 Makefile
 Makefile.old
 blib/*
@@ -7,3 +8,10 @@ ikiwiki.out
 pm_to_blib
 *.man
 build-stamp
+po/po2wiki_stamp
+po/underlays/*/*.mdwn
+po/underlays/basewiki/*/*.mdwn
+po/underlays/basewiki/*/*/*.mdwn
+po/underlays/directives/ikiwiki/directive/*.mdwn
+po/underlays_copy_stamp
+underlays/locale
index 0dd5260ae6022b4419f322bf0f9998eec48411ec..1e099736f487357eda17118e9f3a79e05870e312 100644 (file)
@@ -19,7 +19,7 @@ severity = 1
 # when they are part of the core program. I don't plan to have more than
 # the one exporting module in IkiWiki, so let's ignore this test.
 [-Modules::RequireFilenameMatchesPackage]
-# IkiWIki also switches _out_ of the core package when a package namespace
+# IkiWiki also switches _out_ of the core package when a package namespace
 # is a good way to group a set of functions. This doesn't mean I want it
 # loading up a separate file though, so it's in the same file.
 [-Modules::ProhibitMultiplePackages]
index 74832323a1dd7616950c7a68441526cf21b82f2e..769791d305b17ce03f6159a8d3094dbdb026cb80 100644 (file)
@@ -16,17 +16,17 @@ perl -MCPAN -e 'install Bundle::IkiWiki'
 
 =head1 CONTENTS
 
-XML::Simple
 Text::Markdown
-Date::Parse
-HTML::Template
 HTML::Scrubber
-CGI
+HTML::Template
+HTML::Parser
+URI
+XML::Simple
+Date::Parse
 CGI::FormBuilder
 CGI::Session
 Mail::Sendmail
-HTML::Parser
-URI
+CGI
 Data::Dumper
 
 =head1 AUTHOR
index abf596f0060712ca599fa5326da026b447fc947f..48bd127f1745c72459c213247cde1b3ffa3e4430 100644 (file)
@@ -31,6 +31,10 @@ Text::Textile
 Text::WikiFormat
 XML::Feed
 Net::Amazon::S3
+Text::WikiCreole
+Term::ReadLine::Gnu
+HTML::Tree
+Sort::Naturally
 
 =head1 AUTHOR
 
index 0b420e824975172b7a72ea6484f81c323cbde14e..5563a03af7d028a88c184d8f2ac227284c475f52 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/perl
 
 package IkiWiki;
+
 use warnings;
 use strict;
 use Encode;
@@ -11,19 +12,21 @@ use Storable;
 use open qw{:utf8 :std};
 
 use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
-           %pagestate %renderedfiles %oldrenderedfiles %pagesources
-           %destsources %depends %hooks %forcerebuild $gettext_obj};
+           %pagestate %wikistate %renderedfiles %oldrenderedfiles
+           %pagesources %destsources %depends %hooks %forcerebuild
+           %loaded_plugins};
 
 use Exporter q{import};
 our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
-                 bestlink htmllink readfile writefile pagetype srcfile pagename
-                 displaytime will_render gettext urlto targetpage
-                add_underlay
-                 %config %links %pagestate %renderedfiles
+                 pagespec_match_list bestlink htmllink readfile writefile
+                pagetype srcfile pagename displaytime will_render gettext urlto
+                targetpage add_underlay pagetitle titlepage linkpage
+                newpagefile inject add_link
+                 %config %links %pagestate %wikistate %renderedfiles
                  %pagesources %destsources);
-our $VERSION = 2.00; # plugin interface version, next is ikiwiki version
+our $VERSION = 3.00; # plugin interface version, next is ikiwiki version
 our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
-my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
+our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
 
 # Optimisation.
 use Memoize;
@@ -31,67 +34,430 @@ memoize("abs2rel");
 memoize("pagespec_translate");
 memoize("file_pruned");
 
-sub defaultconfig () { #{{{
-       return
-       wiki_file_prune_regexps => [qr/(^|\/)\.\.(\/|$)/, qr/^\./, qr/\/\./,
-               qr/\.x?html?$/, qr/\.ikiwiki-new$/,
-               qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//,
-               qr/(^|\/)_MTN\//,
-               qr/\.dpkg-tmp$/],
-       wiki_file_regexp => qr/(^[-[:alnum:]_.:\/+]+$)/,
-       web_commit_regexp => qr/^web commit (by (.*?(?=: |$))|from (\d+\.\d+\.\d+\.\d+)):?(.*)/,
-       verbose => 0,
-       syslog => 0,
-       wikiname => "wiki",
-       default_pageext => "mdwn",
-       htmlext => "html",
-       cgi => 0,
-       post_commit => 0,
-       rcs => '',
-       url => '',
-       cgiurl => '',
-       historyurl => '',
-       diffurl => '',
-       rss => 0,
-       atom => 0,
-       allowrss => 0,
-       allowatom => 0,
-       discussion => 1,
-       rebuild => 0,
-       refresh => 0,
-       getctime => 0,
-       w3mmode => 0,
-       wrapper => undef,
-       wrappermode => undef,
-       svnpath => "trunk",
-       gitorigin_branch => "origin",
-       gitmaster_branch => "master",
-       srcdir => undef,
-       destdir => undef,
-       pingurl => [],
-       templatedir => "$installdir/share/ikiwiki/templates",
-       underlaydir => "$installdir/share/ikiwiki/basewiki",
-       underlaydirs => [],
-       setup => undef,
-       adminuser => undef,
-       adminemail => undef,
-       plugin => [qw{mdwn link inline htmlscrubber passwordauth openid
-                       signinedit lockedit conditional recentchanges}],
-       libdir => undef,
-       timeformat => '%c',
-       locale => undef,
-       sslcookie => 0,
-       httpauth => 0,
-       userdir => "",
-       usedirs => 1,
-       numbacklinks => 10,
-       account_creation_password => "",
-       prefix_directives => 0,
-       hardlink => 0,
-       cgi_disable_uploads => 1,
-} #}}}
-
-sub checkconfig () { #{{{
+sub getsetup () {
+       wikiname => {
+               type => "string",
+               default => "wiki",
+               description => "name of the wiki",
+               safe => 1,
+               rebuild => 1,
+       },
+       adminemail => {
+               type => "string",
+               default => undef,
+               example => 'me@example.com',
+               description => "contact email for wiki",
+               safe => 1,
+               rebuild => 0,
+       },
+       adminuser => {
+               type => "string",
+               default => [],
+               description => "users who are wiki admins",
+               safe => 1,
+               rebuild => 0,
+       },
+       banned_users => {
+               type => "string",
+               default => [],
+               description => "users who are banned from the wiki",
+               safe => 1,
+               rebuild => 0,
+       },
+       srcdir => {
+               type => "string",
+               default => undef,
+               example => "$ENV{HOME}/wiki",
+               description => "where the source of the wiki is located",
+               safe => 0, # path
+               rebuild => 1,
+       },
+       destdir => {
+               type => "string",
+               default => undef,
+               example => "/var/www/wiki",
+               description => "where to build the wiki",
+               safe => 0, # path
+               rebuild => 1,
+       },
+       url => {
+               type => "string",
+               default => '',
+               example => "http://example.com/wiki",
+               description => "base url to the wiki",
+               safe => 1,
+               rebuild => 1,
+       },
+       cgiurl => {
+               type => "string",
+               default => '',
+               example => "http://example.com/wiki/ikiwiki.cgi",
+               description => "url to the ikiwiki.cgi",
+               safe => 1,
+               rebuild => 1,
+       },
+       cgi_wrapper => {
+               type => "string",
+               default => '',
+               example => "/var/www/wiki/ikiwiki.cgi",
+               description => "filename of cgi wrapper to generate",
+               safe => 0, # file
+               rebuild => 0,
+       },
+       cgi_wrappermode => {
+               type => "string",
+               default => '06755',
+               description => "mode for cgi_wrapper (can safely be made suid)",
+               safe => 0,
+               rebuild => 0,
+       },
+       rcs => {
+               type => "string",
+               default => '',
+               description => "rcs backend to use",
+               safe => 0, # don't allow overriding
+               rebuild => 0,
+       },
+       default_plugins => {
+               type => "internal",
+               default => [qw{mdwn link inline meta htmlscrubber passwordauth
+                               openid signinedit lockedit conditional
+                               recentchanges parentlinks editpage}],
+               description => "plugins to enable by default",
+               safe => 0,
+               rebuild => 1,
+       },
+       add_plugins => {
+               type => "string",
+               default => [],
+               description => "plugins to add to the default configuration",
+               safe => 1,
+               rebuild => 1,
+       },
+       disable_plugins => {
+               type => "string",
+               default => [],
+               description => "plugins to disable",
+               safe => 1,
+               rebuild => 1,
+       },
+       templatedir => {
+               type => "string",
+               default => "$installdir/share/ikiwiki/templates",
+               description => "location of template files",
+               advanced => 1,
+               safe => 0, # path
+               rebuild => 1,
+       },
+       underlaydir => {
+               type => "string",
+               default => "$installdir/share/ikiwiki/basewiki",
+               description => "base wiki source location",
+               advanced => 1,
+               safe => 0, # path
+               rebuild => 0,
+       },
+       underlaydirbase => {
+               type => "internal",
+               default => "$installdir/share/ikiwiki",
+               description => "parent directory containing additional underlays",
+               safe => 0,
+               rebuild => 0,
+       },
+       wrappers => {
+               type => "internal",
+               default => [],
+               description => "wrappers to generate",
+               safe => 0,
+               rebuild => 0,
+       },
+       underlaydirs => {
+               type => "internal",
+               default => [],
+               description => "additional underlays to use",
+               safe => 0,
+               rebuild => 0,
+       },
+       verbose => {
+               type => "boolean",
+               example => 1,
+               description => "display verbose messages?",
+               safe => 1,
+               rebuild => 0,
+       },
+       syslog => {
+               type => "boolean",
+               example => 1,
+               description => "log to syslog?",
+               safe => 1,
+               rebuild => 0,
+       },
+       usedirs => {
+               type => "boolean",
+               default => 1,
+               description => "create output files named page/index.html?",
+               safe => 0, # changing requires manual transition
+               rebuild => 1,
+       },
+       prefix_directives => {
+               type => "boolean",
+               default => 1,
+               description => "use '!'-prefixed preprocessor directives?",
+               safe => 0, # changing requires manual transition
+               rebuild => 1,
+       },
+       indexpages => {
+               type => "boolean",
+               default => 0,
+               description => "use page/index.mdwn source files",
+               safe => 1,
+               rebuild => 1,
+       },
+       discussion => {
+               type => "boolean",
+               default => 1,
+               description => "enable Discussion pages?",
+               safe => 1,
+               rebuild => 1,
+       },
+       discussionpage => {
+               type => "string",
+               default => gettext("Discussion"),
+               description => "name of Discussion pages",
+               safe => 1,
+               rebuild => 1,
+       },
+       sslcookie => {
+               type => "boolean",
+               default => 0,
+               description => "only send cookies over SSL connections?",
+               advanced => 1,
+               safe => 1,
+               rebuild => 0,
+       },
+       default_pageext => {
+               type => "string",
+               default => "mdwn",
+               description => "extension to use for new pages",
+               safe => 0, # not sanitized
+               rebuild => 0,
+       },
+       htmlext => {
+               type => "string",
+               default => "html",
+               description => "extension to use for html files",
+               safe => 0, # not sanitized
+               rebuild => 1,
+       },
+       timeformat => {
+               type => "string",
+               default => '%c',
+               description => "strftime format string to display date",
+               advanced => 1,
+               safe => 1,
+               rebuild => 1,
+       },
+       locale => {
+               type => "string",
+               default => undef,
+               example => "en_US.UTF-8",
+               description => "UTF-8 locale to use",
+               advanced => 1,
+               safe => 0,
+               rebuild => 1,
+       },
+       userdir => {
+               type => "string",
+               default => "",
+               example => "users",
+               description => "put user pages below specified page",
+               safe => 1,
+               rebuild => 1,
+       },
+       numbacklinks => {
+               type => "integer",
+               default => 10,
+               description => "how many backlinks to show before hiding excess (0 to show all)",
+               safe => 1,
+               rebuild => 1,
+       },
+       hardlink => {
+               type => "boolean",
+               default => 0,
+               description => "attempt to hardlink source files? (optimisation for large files)",
+               advanced => 1,
+               safe => 0, # paranoia
+               rebuild => 0,
+       },
+       umask => {
+               type => "integer",
+               example => "022",
+               description => "force ikiwiki to use a particular umask",
+               advanced => 1,
+               safe => 0, # paranoia
+               rebuild => 0,
+       },
+       wrappergroup => {
+               type => "string",
+               example => "ikiwiki",
+               description => "group for wrappers to run in",
+               advanced => 1,
+               safe => 0, # paranoia
+               rebuild => 0,
+       },
+       libdir => {
+               type => "string",
+               default => "",
+               example => "$ENV{HOME}/.ikiwiki/",
+               description => "extra library and plugin directory",
+               advanced => 1,
+               safe => 0, # directory
+               rebuild => 0,
+       },
+       ENV => {
+               type => "string", 
+               default => {},
+               description => "environment variables",
+               safe => 0, # paranoia
+               rebuild => 0,
+       },
+       exclude => {
+               type => "string",
+               default => undef,
+               example => '\.wav$',
+               description => "regexp of source files to ignore",
+               advanced => 1,
+               safe => 0, # regexp
+               rebuild => 1,
+       },
+       wiki_file_prune_regexps => {
+               type => "internal",
+               default => [qr/(^|\/)\.\.(\/|$)/, qr/^\./, qr/\/\./,
+                       qr/\.x?html?$/, qr/\.ikiwiki-new$/,
+                       qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//,
+                       qr/(^|\/)_MTN\//, qr/(^|\/)_darcs\//,
+                       qr/\.dpkg-tmp$/],
+               description => "regexps of source files to ignore",
+               safe => 0,
+               rebuild => 1,
+       },
+       wiki_file_chars => {
+               type => "string",
+               description => "specifies the characters that are allowed in source filenames",
+               default => "-[:alnum:]+/.:_",
+               safe => 0,
+               rebuild => 1,
+       },
+       wiki_file_regexp => {
+               type => "internal",
+               description => "regexp of legal source files",
+               safe => 0,
+               rebuild => 1,
+       },
+       web_commit_regexp => {
+               type => "internal",
+               default => qr/^web commit (by (.*?(?=: |$))|from (\d+\.\d+\.\d+\.\d+)):?(.*)/,
+               description => "regexp to parse web commits from logs",
+               safe => 0,
+               rebuild => 0,
+       },
+       cgi => {
+               type => "internal",
+               default => 0,
+               description => "run as a cgi",
+               safe => 0,
+               rebuild => 0,
+       },
+       cgi_disable_uploads => {
+               type => "internal",
+               default => 1,
+               description => "whether CGI should accept file uploads",
+               safe => 0,
+               rebuild => 0,
+       },
+       post_commit => {
+               type => "internal",
+               default => 0,
+               description => "run as a post-commit hook",
+               safe => 0,
+               rebuild => 0,
+       },
+       rebuild => {
+               type => "internal",
+               default => 0,
+               description => "running in rebuild mode",
+               safe => 0,
+               rebuild => 0,
+       },
+       setup => {
+               type => "internal",
+               default => undef,
+               description => "running in setup mode",
+               safe => 0,
+               rebuild => 0,
+       },
+       refresh => {
+               type => "internal",
+               default => 0,
+               description => "running in refresh mode",
+               safe => 0,
+               rebuild => 0,
+       },
+       test_receive => {
+               type => "internal",
+               default => 0,
+               description => "running in receive test mode",
+               safe => 0,
+               rebuild => 0,
+       },
+       getctime => {
+               type => "internal",
+               default => 0,
+               description => "running in getctime mode",
+               safe => 0,
+               rebuild => 0,
+       },
+       w3mmode => {
+               type => "internal",
+               default => 0,
+               description => "running in w3mmode",
+               safe => 0,
+               rebuild => 0,
+       },
+       wikistatedir => {
+               type => "internal",
+               default => undef,
+               description => "path to the .ikiwiki directory holding ikiwiki state",
+               safe => 0,
+               rebuild => 0,
+       },
+       setupfile => {
+               type => "internal",
+               default => undef,
+               description => "path to setup file",
+               safe => 0,
+               rebuild => 0,
+       },
+       allow_symlinks_before_srcdir => {
+               type => "boolean",
+               default => 0,
+               description => "allow symlinks in the path leading to the srcdir (potentially insecure)",
+               safe => 0,
+               rebuild => 0,
+       },
+}
+
+sub defaultconfig () {
+       my %s=getsetup();
+       my @ret;
+       foreach my $key (keys %s) {
+               push @ret, $key, $s{$key}->{default};
+       }
+       use Data::Dumper;
+       return @ret;
+}
+
+sub checkconfig () {
        # locale stuff; avoid LC_ALL since it overrides everything
        if (defined $ENV{LC_ALL}) {
                $ENV{LANG} = $ENV{LC_ALL};
@@ -100,9 +466,13 @@ sub checkconfig () { #{{{
        if (defined $config{locale}) {
                if (POSIX::setlocale(&POSIX::LC_ALL, $config{locale})) {
                        $ENV{LANG}=$config{locale};
-                       $gettext_obj=undef;
+                       define_gettext();
                }
        }
+               
+       if (! defined $config{wiki_file_regexp}) {
+               $config{wiki_file_regexp}=qr/(^[$config{wiki_file_chars}]+$)/;
+       }
 
        if (ref $config{ENV} eq 'HASH') {
                foreach my $val (keys %{$config{ENV}}) {
@@ -125,45 +495,67 @@ sub checkconfig () { #{{{
        }
        
        $config{wikistatedir}="$config{srcdir}/.ikiwiki"
-               unless exists $config{wikistatedir};
-       
-       if ($config{rcs}) {
-               eval qq{use IkiWiki::Rcs::$config{rcs}};
-               if ($@) {
-                       error("Failed to load RCS module IkiWiki::Rcs::$config{rcs}: $@");
-               }
-       }
-       else {
-               require IkiWiki::Rcs::Stub;
-       }
+               unless exists $config{wikistatedir} && defined $config{wikistatedir};
 
-       if (exists $config{umask}) {
+       if (defined $config{umask}) {
                umask(possibly_foolish_untaint($config{umask}));
        }
 
        run_hooks(checkconfig => sub { shift->() });
 
        return 1;
-} #}}}
+}
+
+sub listplugins () {
+       my %ret;
+
+       foreach my $dir (@INC, $config{libdir}) {
+               next unless defined $dir && length $dir;
+               foreach my $file (glob("$dir/IkiWiki/Plugin/*.pm")) {
+                       my ($plugin)=$file=~/.*\/(.*)\.pm$/;
+                       $ret{$plugin}=1;
+               }
+       }
+       foreach my $dir ($config{libdir}, "$installdir/lib/ikiwiki") {
+               next unless defined $dir && length $dir;
+               foreach my $file (glob("$dir/plugins/*")) {
+                       $ret{basename($file)}=1 if -x $file;
+               }
+       }
 
-sub loadplugins () { #{{{
-       if (defined $config{libdir}) {
+       return keys %ret;
+}
+
+sub loadplugins () {
+       if (defined $config{libdir} && length $config{libdir}) {
                unshift @INC, possibly_foolish_untaint($config{libdir});
        }
 
-       loadplugin($_) foreach @{$config{plugin}};
+       foreach my $plugin (@{$config{default_plugins}}, @{$config{add_plugins}}) {
+               loadplugin($plugin);
+       }
+       
+       if ($config{rcs}) {
+               if (exists $IkiWiki::hooks{rcs}) {
+                       error(gettext("cannot use multiple rcs plugins"));
+               }
+               loadplugin($config{rcs});
+       }
+       if (! exists $IkiWiki::hooks{rcs}) {
+               loadplugin("norcs");
+       }
 
        run_hooks(getopt => sub { shift->() });
        if (grep /^-/, @ARGV) {
-               print STDERR "Unknown option: $_\n"
+               print STDERR "Unknown option (or missing parameter): $_\n"
                        foreach grep /^-/, @ARGV;
                usage();
        }
 
        return 1;
-} #}}}
+}
 
-sub loadplugin ($) { #{{{
+sub loadplugin ($) {
        my $plugin=shift;
 
        return if grep { $_ eq $plugin} @{$config{disable_plugins}};
@@ -171,8 +563,13 @@ sub loadplugin ($) { #{{{
        foreach my $dir (defined $config{libdir} ? possibly_foolish_untaint($config{libdir}) : undef,
                         "$installdir/lib/ikiwiki") {
                if (defined $dir && -x "$dir/plugins/$plugin") {
-                       require IkiWiki::Plugin::external;
+                       eval { require IkiWiki::Plugin::external };
+                       if ($@) {
+                               my $reason=$@;
+                               error(sprintf(gettext("failed to load external plugin needed for %s plugin: %s"), $plugin, $reason));
+                       }
                        import IkiWiki::Plugin::external "$dir/plugins/$plugin";
+                       $loaded_plugins{$plugin}=1;
                        return 1;
                }
        }
@@ -182,31 +579,27 @@ sub loadplugin ($) { #{{{
        if ($@) {
                error("Failed to load plugin $mod: $@");
        }
+       $loaded_plugins{$plugin}=1;
        return 1;
-} #}}}
+}
 
-sub error ($;$) { #{{{
+sub error ($;$) {
        my $message=shift;
        my $cleaner=shift;
-       if ($config{cgi}) {
-               print "Content-type: text/html\n\n";
-               print misctemplate(gettext("Error"),
-                       "<p>".gettext("Error").": $message</p>");
-       }
        log_message('err' => $message) if $config{syslog};
        if (defined $cleaner) {
                $cleaner->();
        }
        die $message."\n";
-} #}}}
+}
 
-sub debug ($) { #{{{
+sub debug ($) {
        return unless $config{verbose};
        return log_message(debug => @_);
-} #}}}
+}
 
 my $log_open=0;
-sub log_message ($$) { #{{{
+sub log_message ($$) {
        my $type=shift;
 
        if ($config{syslog}) {
@@ -226,70 +619,105 @@ sub log_message ($$) { #{{{
        else {
                return print STDERR "@_\n";
        }
-} #}}}
+}
 
-sub possibly_foolish_untaint ($) { #{{{
+sub possibly_foolish_untaint ($) {
        my $tainted=shift;
        my ($untainted)=$tainted=~/(.*)/s;
        return $untainted;
-} #}}}
+}
 
-sub basename ($) { #{{{
+sub basename ($) {
        my $file=shift;
 
        $file=~s!.*/+!!;
        return $file;
-} #}}}
+}
 
-sub dirname ($) { #{{{
+sub dirname ($) {
        my $file=shift;
 
        $file=~s!/*[^/]+$!!;
        return $file;
-} #}}}
+}
 
-sub pagetype ($) { #{{{
+sub isinternal ($) {
        my $page=shift;
+       return exists $pagesources{$page} &&
+               $pagesources{$page} =~ /\._([^.]+)$/;
+}
+
+sub pagetype ($) {
+       my $file=shift;
        
-       if ($page =~ /\.([^.]+)$/) {
+       if ($file =~ /\.([^.]+)$/) {
                return $1 if exists $hooks{htmlize}{$1};
        }
+       my $base=basename($file);
+       if (exists $hooks{htmlize}{$base} &&
+           $hooks{htmlize}{$base}{noextension}) {
+               return $base;
+       }
        return;
-} #}}}
+}
 
-sub isinternal ($) { #{{{
-       my $page=shift;
-       return exists $pagesources{$page} &&
-               $pagesources{$page} =~ /\._([^.]+)$/;
-} #}}}
+my %pagename_cache;
 
-sub pagename ($) { #{{{
+sub pagename ($) {
        my $file=shift;
 
+       if (exists $pagename_cache{$file}) {
+               return $pagename_cache{$file};
+       }
+
        my $type=pagetype($file);
        my $page=$file;
-       $page=~s/\Q.$type\E*$// if defined $type;
+       $page=~s/\Q.$type\E*$//
+               if defined $type && !$hooks{htmlize}{$type}{keepextension}
+                       && !$hooks{htmlize}{$type}{noextension};
+       if ($config{indexpages} && $page=~/(.*)\/index$/) {
+               $page=$1;
+       }
+
+       $pagename_cache{$file} = $page;
        return $page;
-} #}}}
+}
+
+sub newpagefile ($$) {
+       my $page=shift;
+       my $type=shift;
+
+       if (! $config{indexpages} || $page eq 'index') {
+               return $page.".".$type;
+       }
+       else {
+               return $page."/index.".$type;
+       }
+}
 
-sub targetpage ($$) { #{{{
+sub targetpage ($$;$) {
        my $page=shift;
        my $ext=shift;
+       my $filename=shift;
        
-       if (! $config{usedirs} || $page =~ /^index$/ ) {
+       if (defined $filename) {
+               return $page."/".$filename.".".$ext;
+       }
+       elsif (! $config{usedirs} || $page eq 'index') {
                return $page.".".$ext;
-       } else {
+       }
+       else {
                return $page."/index.".$ext;
        }
-} #}}}
+}
 
-sub htmlpage ($) { #{{{
+sub htmlpage ($) {
        my $page=shift;
        
        return targetpage($page, $config{htmlext});
-} #}}}
+}
 
-sub srcfile_stat { #{{{
+sub srcfile_stat {
        my $file=shift;
        my $nothrow=shift;
 
@@ -299,26 +727,27 @@ sub srcfile_stat { #{{{
        }
        error("internal error: $file cannot be found in $config{srcdir} or underlay") unless $nothrow;
        return;
-} #}}}
+}
 
-sub srcfile ($;$) { #{{{
+sub srcfile ($;$) {
        return (srcfile_stat(@_))[0];
-} #}}}
+}
 
-sub add_underlay ($) { #{{{
+sub add_underlay ($) {
        my $dir=shift;
 
-       if ($dir=~/^\//) {
-               unshift @{$config{underlaydirs}}, $dir;
+       if ($dir !~ /^\//) {
+               $dir="$config{underlaydirbase}/$dir";
        }
-       else {
-               unshift @{$config{underlaydirs}}, "$config{underlaydir}/../$dir";
+
+       if (! grep { $_ eq $dir } @{$config{underlaydirs}}) {
+               unshift @{$config{underlaydirs}}, $dir;
        }
 
        return 1;
-} #}}}
+}
 
-sub readfile ($;$$) { #{{{
+sub readfile ($;$$) {
        my $file=shift;
        my $binary=shift;
        my $wantfd=shift;
@@ -332,9 +761,13 @@ sub readfile ($;$$) { #{{{
        binmode($in) if ($binary);
        return \*$in if $wantfd;
        my $ret=<$in>;
+       # check for invalid utf-8, and toss it back to avoid crashes
+       if (! utf8::valid($ret)) {
+               $ret=encode_utf8($ret);
+       }
        close $in || error("failed to read $file: $!");
        return $ret;
-} #}}}
+}
 
 sub prep_writefile ($$) {
        my $file=shift;
@@ -362,7 +795,7 @@ sub prep_writefile ($$) {
        return 1;
 }
 
-sub writefile ($$$;$$) { #{{{
+sub writefile ($$$;$$) {
        my $file=shift; # can include subdirs
        my $destdir=shift; # directory to put file in
        my $content=shift;
@@ -390,17 +823,17 @@ sub writefile ($$$;$$) { #{{{
                error("failed renaming $newfile to $destdir/$file: $!", $cleanup);
 
        return 1;
-} #}}}
+}
 
 my %cleared;
-sub will_render ($$;$) { #{{{
+sub will_render ($$;$) {
        my $page=shift;
        my $dest=shift;
        my $clear=shift;
 
        # Important security check.
        if (-e "$config{destdir}/$dest" && ! $config{rebuild} &&
-           ! grep { $_ eq $dest } (@{$renderedfiles{$page}}, @{$oldrenderedfiles{$page}})) {
+           ! grep { $_ eq $dest } (@{$renderedfiles{$page}}, @{$oldrenderedfiles{$page}}, @{$wikistate{editpage}{previews}})) {
                error("$config{destdir}/$dest independently created, not overwriting with version from $page");
        }
 
@@ -417,9 +850,9 @@ sub will_render ($$;$) { #{{{
        $destsources{$dest}=$page;
 
        return 1;
-} #}}}
+}
 
-sub bestlink ($$) { #{{{
+sub bestlink ($$) {
        my $page=shift;
        my $link=shift;
        
@@ -441,7 +874,7 @@ sub bestlink ($$) { #{{{
                elsif (exists $pagecase{lc $l}) {
                        return $pagecase{lc $l};
                }
-       } while $cwd=~s!/?[^/]+$!!;
+       } while $cwd=~s{/?[^/]+$}{};
 
        if (length $config{userdir}) {
                my $l = "$config{userdir}/".lc($link);
@@ -455,15 +888,15 @@ sub bestlink ($$) { #{{{
 
        #print STDERR "warning: page $page, broken link: $link\n";
        return "";
-} #}}}
+}
 
-sub isinlinableimage ($) { #{{{
+sub isinlinableimage ($) {
        my $file=shift;
        
        return $file =~ /\.(png|gif|jpg|jpeg)$/i;
-} #}}}
+}
 
-sub pagetitle ($;$) { #{{{
+sub pagetitle ($;$) {
        my $page=shift;
        my $unescaped=shift;
 
@@ -475,28 +908,31 @@ sub pagetitle ($;$) { #{{{
        }
 
        return $page;
-} #}}}
+}
 
-sub titlepage ($) { #{{{
+sub titlepage ($) {
        my $title=shift;
-       $title=~s/([^-[:alnum:]:+\/.])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+       # support use w/o %config set
+       my $chars = defined $config{wiki_file_chars} ? $config{wiki_file_chars} : "-[:alnum:]+/.:_";
+       $title=~s/([^$chars]|_)/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
        return $title;
-} #}}}
+}
 
-sub linkpage ($) { #{{{
+sub linkpage ($) {
        my $link=shift;
-       $link=~s/([^-[:alnum:]:+\/._])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+       my $chars = defined $config{wiki_file_chars} ? $config{wiki_file_chars} : "-[:alnum:]+/.:_";
+       $link=~s/([^$chars])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
        return $link;
-} #}}}
+}
 
-sub cgiurl (@) { #{{{
+sub cgiurl (@) {
        my %params=@_;
 
        return $config{cgiurl}."?".
                join("&amp;", map $_."=".uri_escape_utf8($params{$_}), keys %params);
-} #}}}
+}
 
-sub baseurl (;$) { #{{{
+sub baseurl (;$) {
        my $page=shift;
 
        return "$config{url}/" if ! defined $page;
@@ -505,9 +941,9 @@ sub baseurl (;$) { #{{{
        $page=~s/[^\/]+$//;
        $page=~s/[^\/]+\//..\//g;
        return $page;
-} #}}}
+}
 
-sub abs2rel ($$) { #{{{
+sub abs2rel ($$) {
        # Work around very innefficient behavior in File::Spec if abs2rel
        # is passed two relative paths. It's much faster if paths are
        # absolute! (Debian bug #376658; fixed in debian unstable now)
@@ -518,9 +954,16 @@ sub abs2rel ($$) { #{{{
        my $ret=File::Spec->abs2rel($path, $base);
        $ret=~s/^// if defined $ret;
        return $ret;
-} #}}}
+}
+
+sub displaytime ($;$) {
+       # Plugins can override this function to mark up the time to
+       # display.
+       return '<span class="date">'.formattime(@_).'</span>';
+}
 
-sub displaytime ($;$) { #{{{
+sub formattime ($;$) {
+       # Plugins can override this function to format the time.
        my $time=shift;
        my $format=shift;
        if (! defined $format) {
@@ -530,37 +973,47 @@ sub displaytime ($;$) { #{{{
        # strftime doesn't know about encodings, so make sure
        # its output is properly treated as utf8
        return decode_utf8(POSIX::strftime($format, localtime($time)));
-} #}}}
+}
 
-sub beautify_url ($) { #{{{
+sub beautify_urlpath ($) {
        my $url=shift;
 
+       # Ensure url is not an empty link, and if necessary,
+       # add ./ to avoid colon confusion.
+       if ($url !~ /^\// && $url !~ /^\.\.?\//) {
+               $url="./$url";
+       }
+
        if ($config{usedirs}) {
                $url =~ s!/index.$config{htmlext}$!/!;
        }
-       $url =~ s!^$!./!; # Browsers don't like empty links...
 
        return $url;
-} #}}}
+}
 
-sub urlto ($$) { #{{{
+sub urlto ($$;$) {
        my $to=shift;
        my $from=shift;
-
+       my $absolute=shift;
+       
        if (! length $to) {
-               return beautify_url(baseurl($from)."index.$config{htmlext}");
+               return beautify_urlpath(baseurl($from)."index.$config{htmlext}");
        }
 
        if (! $destsources{$to}) {
                $to=htmlpage($to);
        }
 
+       if ($absolute) {
+               return $config{url}.beautify_urlpath("/".$to);
+       }
+
        my $link = abs2rel($to, dirname(htmlpage($from)));
 
-       return beautify_url($link);
-} #}}}
+       return beautify_urlpath($link);
+}
 
-sub htmllink ($$$;@) { #{{{
+sub htmllink ($$$;@) {
        my $lpage=shift; # the page doing the linking
        my $page=shift; # the page that will contain the link (different for inline)
        my $link=shift;
@@ -604,7 +1057,7 @@ sub htmllink ($$$;@) { #{{{
        }
        
        $bestlink=abs2rel($bestlink, dirname(htmlpage($page)));
-       $bestlink=beautify_url($bestlink);
+       $bestlink=beautify_urlpath($bestlink);
        
        if (! $opts{noimageinline} && isinlinableimage($bestlink)) {
                return "<img src=\"$bestlink\" alt=\"$linktext\" />";
@@ -623,9 +1076,44 @@ sub htmllink ($$$;@) { #{{{
        }
 
        return "<a href=\"$bestlink\"@attrs>$linktext</a>";
-} #}}}
+}
 
-sub userlink ($) { #{{{
+sub openiduser ($) {
+       my $user=shift;
+
+       if ($user =~ m!^https?://! &&
+           eval q{use Net::OpenID::VerifiedIdentity; 1} && !$@) {
+               my $display;
+
+               if (Net::OpenID::VerifiedIdentity->can("DisplayOfURL")) {
+                       # this works in at least 2.x
+                       $display = Net::OpenID::VerifiedIdentity::DisplayOfURL($user);
+               }
+               else {
+                       # this only works in 1.x
+                       my $oid=Net::OpenID::VerifiedIdentity->new(identity => $user);
+                       $display=$oid->display;
+               }
+
+               # Convert "user.somehost.com" to "user [somehost.com]"
+               # (also "user.somehost.co.uk")
+               if ($display !~ /\[/) {
+                       $display=~s/^([-a-zA-Z0-9]+?)\.([-.a-zA-Z0-9]+\.[a-z]+)$/$1 [$2]/;
+               }
+               # Convert "http://somehost.com/user" to "user [somehost.com]".
+               # (also "https://somehost.com/user/")
+               if ($display !~ /\[/) {
+                       $display=~s/^https?:\/\/(.+)\/([^\/]+)\/?$/$2 [$1]/;
+               }
+               $display=~s!^https?://!!; # make sure this is removed
+               eval q{use CGI 'escapeHTML'};
+               error($@) if $@;
+               return escapeHTML($display);
+       }
+       return;
+}
+
+sub userlink ($) {
        my $user=shift;
 
        my $oiduser=eval { openiduser($user) };
@@ -640,9 +1128,9 @@ sub userlink ($) { #{{{
                        length $config{userdir} ? $config{userdir}."/".$user : $user
                ), noimageinline => 1);
        }
-} #}}}
+}
 
-sub htmlize ($$$$) { #{{{
+sub htmlize ($$$$) {
        my $page=shift;
        my $destpage=shift;
        my $type=shift;
@@ -677,9 +1165,9 @@ sub htmlize ($$$$) { #{{{
        }
 
        return $content;
-} #}}}
+}
 
-sub linkify ($$$) { #{{{
+sub linkify ($$$) {
        my $page=shift;
        my $destpage=shift;
        my $content=shift;
@@ -693,11 +1181,11 @@ sub linkify ($$$) { #{{{
        });
        
        return $content;
-} #}}}
+}
 
 our %preprocessing;
 our $preprocess_preview=0;
-sub preprocess ($$$;$$) { #{{{
+sub preprocess ($$$;$$) {
        my $page=shift; # the page the data comes from
        my $destpage=shift; # the page the data will appear in (different for inline)
        my $content=shift;
@@ -713,6 +1201,8 @@ sub preprocess ($$$;$$) { #{{{
                my $prefix=shift;
                my $command=shift;
                my $params=shift;
+               $params="" if ! defined $params;
+
                if (length $escape) {
                        return "[[$prefix$command $params]]";
                }
@@ -757,31 +1247,38 @@ sub preprocess ($$$;$$) { #{{{
                        if ($preprocessing{$page}++ > 3) {
                                # Avoid loops of preprocessed pages preprocessing
                                # other pages that preprocess them, etc.
-                               #translators: The first parameter is a
-                               #translators: preprocessor directive name,
-                               #translators: the second a page name, the
-                               #translators: third a number.
-                               return "[[".sprintf(gettext("%s preprocessing loop detected on %s at depth %i"),
-                                       $command, $page, $preprocessing{$page}).
-                               "]]";
+                               return "[[!$command <span class=\"error\">".
+                                       sprintf(gettext("preprocessing loop detected on %s at depth %i"),
+                                               $page, $preprocessing{$page}).
+                                       "</span>]]";
                        }
                        my $ret;
                        if (! $scan) {
-                               $ret=$hooks{preprocess}{$command}{call}->(
-                                       @params,
-                                       page => $page,
-                                       destpage => $destpage,
-                                       preview => $preprocess_preview,
-                               );
+                               $ret=eval {
+                                       $hooks{preprocess}{$command}{call}->(
+                                               @params,
+                                               page => $page,
+                                               destpage => $destpage,
+                                               preview => $preprocess_preview,
+                                       );
+                               };
+                               if ($@) {
+                                       my $error=$@;
+                                       chomp $error;
+                                       $ret="[[!$command <span class=\"error\">".
+                                               gettext("Error").": $error"."</span>]]";
+                               }
                        }
                        else {
                                # use void context during scan pass
-                               $hooks{preprocess}{$command}{call}->(
-                                       @params,
-                                       page => $page,
-                                       destpage => $destpage,
-                                       preview => $preprocess_preview,
-                               );
+                               eval {
+                                       $hooks{preprocess}{$command}{call}->(
+                                               @params,
+                                               page => $page,
+                                               destpage => $destpage,
+                                               preview => $preprocess_preview,
+                                       );
+                               };
                                $ret="";
                        }
                        $preprocessing{$page}--;
@@ -807,7 +1304,7 @@ sub preprocess ($$$;$$) { #{{{
                                                |
                                                "[^"]+"         # single-quoted value
                                                |
-                                               [^\s\]]+        # unquoted value
+                                               [^"\s\]]+       # unquoted value
                                        )
                                        \s*                     # whitespace or end
                                                                # of directive
@@ -815,7 +1312,8 @@ sub preprocess ($$$;$$) { #{{{
                        *)?             # 0 or more parameters
                        \]\]            # directive closed
                }sx;
-       } else {
+       }
+       else {
                $regex = qr{
                        (\\?)           # 1: escape?
                        \[\[(!?)        # directive open; 2: optional prefix
@@ -829,7 +1327,7 @@ sub preprocess ($$$;$$) { #{{{
                                                |
                                                "[^"]+"         # single-quoted value
                                                |
-                                               [^\s\]]+        # unquoted value
+                                               [^"\s\]]+       # unquoted value
                                        )
                                        \s*                     # whitespace or end
                                                                # of directive
@@ -841,9 +1339,9 @@ sub preprocess ($$$;$$) { #{{{
 
        $content =~ s{$regex}{$handle->($1, $2, $3, $4)}eg;
        return $content;
-} #}}}
+}
 
-sub filter ($$$) { #{{{
+sub filter ($$$) {
        my $page=shift;
        my $destpage=shift;
        my $content=shift;
@@ -854,16 +1352,79 @@ sub filter ($$$) { #{{{
        });
 
        return $content;
-} #}}}
+}
 
-sub indexlink () { #{{{
+sub indexlink () {
        return "<a href=\"$config{url}\">$config{wikiname}</a>";
-} #}}}
+}
+
+sub check_canedit ($$$;$) {
+       my $page=shift;
+       my $q=shift;
+       my $session=shift;
+       my $nonfatal=shift;
+       
+       my $canedit;
+       run_hooks(canedit => sub {
+               return if defined $canedit;
+               my $ret=shift->($page, $q, $session);
+               if (defined $ret) {
+                       if ($ret eq "") {
+                               $canedit=1;
+                       }
+                       elsif (ref $ret eq 'CODE') {
+                               $ret->() unless $nonfatal;
+                               $canedit=0;
+                       }
+                       elsif (defined $ret) {
+                               error($ret) unless $nonfatal;
+                               $canedit=0;
+                       }
+               }
+       });
+       return defined $canedit ? $canedit : 1;
+}
+
+sub check_content (@) {
+       my %params=@_;
+       
+       return 1 if ! exists $hooks{checkcontent}; # optimisation
+
+       if (exists $pagesources{$params{page}}) {
+               my @diff;
+               my %old=map { $_ => 1 }
+                       split("\n", readfile(srcfile($pagesources{$params{page}})));
+               foreach my $line (split("\n", $params{content})) {
+                       push @diff, $line if ! exists $old{$_};
+               }
+               $params{diff}=join("\n", @diff);
+       }
+
+       my $ok;
+       run_hooks(checkcontent => sub {
+               return if defined $ok;
+               my $ret=shift->(%params);
+               if (defined $ret) {
+                       if ($ret eq "") {
+                               $ok=1;
+                       }
+                       elsif (ref $ret eq 'CODE') {
+                               $ret->() unless $params{nonfatal};
+                               $ok=0;
+                       }
+                       elsif (defined $ret) {
+                               error($ret) unless $params{nonfatal};
+                               $ok=0;
+                       }
+               }
+
+       });
+       return defined $ok ? $ok : 1;
+}
 
 my $wikilock;
 
-sub lockwiki (;$) { #{{{
-       my $wait=@_ ? shift : 1;
+sub lockwiki () {
        # Take an exclusive lock on the wiki to prevent multiple concurrent
        # run issues. The lock will be dropped on program exit.
        if (! -d $config{wikistatedir}) {
@@ -871,32 +1432,21 @@ sub lockwiki (;$) { #{{{
        }
        open($wikilock, '>', "$config{wikistatedir}/lockfile") ||
                error ("cannot write to $config{wikistatedir}/lockfile: $!");
-       if (! flock($wikilock, 2 | 4)) { # LOCK_EX | LOCK_NB
-               if ($wait) {
-                       debug("wiki seems to be locked, waiting for lock");
-                       my $wait=600; # arbitrary, but don't hang forever to 
-                                     # prevent process pileup
-                       for (1..$wait) {
-                               return if flock($wikilock, 2 | 4);
-                               sleep 1;
-                       }
-                       error("wiki is locked; waited $wait seconds without lock being freed (possible stuck process or stale lock?)");
-               }
-               else {
-                       return 0;
-               }
+       if (! flock($wikilock, 2)) { # LOCK_EX
+               error("failed to get lock");
        }
        return 1;
-} #}}}
+}
 
-sub unlockwiki () { #{{{
+sub unlockwiki () {
+       POSIX::close($ENV{IKIWIKI_CGILOCK_FD}) if exists $ENV{IKIWIKI_CGILOCK_FD};
        return close($wikilock) if $wikilock;
        return;
-} #}}}
+}
 
 my $commitlock;
 
-sub commit_hook_enabled () { #{{{
+sub commit_hook_enabled () {
        open($commitlock, '+>', "$config{wikistatedir}/commitlock") ||
                error("cannot write to $config{wikistatedir}/commitlock: $!");
        if (! flock($commitlock, 1 | 4)) { # LOCK_SH | LOCK_NB to test
@@ -905,23 +1455,23 @@ sub commit_hook_enabled () { #{{{
        }
        close($commitlock) || error("failed closing commitlock: $!");
        return 1;
-} #}}}
+}
 
-sub disable_commit_hook () { #{{{
+sub disable_commit_hook () {
        open($commitlock, '>', "$config{wikistatedir}/commitlock") ||
                error("cannot write to $config{wikistatedir}/commitlock: $!");
        if (! flock($commitlock, 2)) { # LOCK_EX
                error("failed to get commit lock");
        }
        return 1;
-} #}}}
+}
 
-sub enable_commit_hook () { #{{{
+sub enable_commit_hook () {
        return close($commitlock) if $commitlock;
        return;
-} #}}}
+}
 
-sub loadindex () { #{{{
+sub loadindex () {
        %oldrenderedfiles=%pagectime=();
        if (! $config{rebuild}) {
                %pagesources=%pagemtime=%oldlinks=%links=%depends=
@@ -937,31 +1487,47 @@ sub loadindex () { #{{{
                        return;
                }
        }
-       my $ret=Storable::fd_retrieve($in);
-       if (! defined $ret) {
+
+       my $index=Storable::fd_retrieve($in);
+       if (! defined $index) {
                return 0;
        }
-       my %index=%$ret;
-       foreach my $src (keys %index) {
-               my %d=%{$index{$src}};
+
+       my $pages;
+       if (exists $index->{version} && ! ref $index->{version}) {
+               $pages=$index->{page};
+               %wikistate=%{$index->{state}};
+       }
+       else {
+               $pages=$index;
+               %wikistate=();
+       }
+
+       foreach my $src (keys %$pages) {
+               my $d=$pages->{$src};
                my $page=pagename($src);
-               $pagectime{$page}=$d{ctime};
+               $pagectime{$page}=$d->{ctime};
                if (! $config{rebuild}) {
                        $pagesources{$page}=$src;
-                       $pagemtime{$page}=$d{mtime};
-                       $renderedfiles{$page}=$d{dest};
-                       if (exists $d{links} && ref $d{links}) {
-                               $links{$page}=$d{links};
-                               $oldlinks{$page}=[@{$d{links}}];
+                       $pagemtime{$page}=$d->{mtime};
+                       $renderedfiles{$page}=$d->{dest};
+                       if (exists $d->{links} && ref $d->{links}) {
+                               $links{$page}=$d->{links};
+                               $oldlinks{$page}=[@{$d->{links}}];
+                       }
+                       if (exists $d->{dependslist}) {
+                               $depends{$page}={
+                                       map { $_ => 1 } @{$d->{dependslist}}
+                               };
                        }
-                       if (exists $d{depends}) {
-                               $depends{$page}=$d{depends};
+                       elsif (exists $d->{depends}) {
+                               $depends{$page}={$d->{depends} => 1};
                        }
-                       if (exists $d{state}) {
-                               $pagestate{$page}=$d{state};
+                       if (exists $d->{state}) {
+                               $pagestate{$page}=$d->{state};
                        }
                }
-               $oldrenderedfiles{$page}=[@{$d{dest}}];
+               $oldrenderedfiles{$page}=[@{$d->{dest}}];
        }
        foreach my $page (keys %pagesources) {
                $pagecase{lc $page}=$page;
@@ -970,9 +1536,9 @@ sub loadindex () { #{{{
                $destsources{$_}=$page foreach @{$renderedfiles{$page}};
        }
        return close($in);
-} #}}}
+}
 
-sub saveindex () { #{{{
+sub saveindex () {
        run_hooks(savestate => sub { shift->() });
 
        my %hookids;
@@ -987,12 +1553,13 @@ sub saveindex () { #{{{
        my $newfile="$config{wikistatedir}/indexdb.new";
        my $cleanup = sub { unlink($newfile) };
        open (my $out, '>', $newfile) || error("cannot write to $newfile: $!", $cleanup);
+
        my %index;
        foreach my $page (keys %pagemtime) {
                next unless $pagemtime{$page};
                my $src=$pagesources{$page};
 
-               $index{$src}={
+               $index{page}{$src}={
                        ctime => $pagectime{$page},
                        mtime => $pagemtime{$page},
                        dest => $renderedfiles{$page},
@@ -1000,17 +1567,26 @@ sub saveindex () { #{{{
                };
 
                if (exists $depends{$page}) {
-                       $index{$src}{depends} = $depends{$page};
+                       $index{page}{$src}{dependslist} = [ keys %{$depends{$page}} ];
                }
 
                if (exists $pagestate{$page}) {
                        foreach my $id (@hookids) {
                                foreach my $key (keys %{$pagestate{$page}{$id}}) {
-                                       $index{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
+                                       $index{page}{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
                                }
                        }
                }
        }
+
+       $index{state}={};
+       foreach my $id (@hookids) {
+               foreach my $key (keys %{$wikistate{$id}}) {
+                       $index{state}{$id}{$key}=$wikistate{$id}{$key};
+               }
+       }
+       
+       $index{version}="3";
        my $ret=Storable::nstore_fd(\%index, $out);
        return if ! defined $ret || ! $ret;
        close $out || error("failed saving to $newfile: $!", $cleanup);
@@ -1018,18 +1594,18 @@ sub saveindex () { #{{{
                error("failed renaming $newfile to $config{wikistatedir}/indexdb", $cleanup);
        
        return 1;
-} #}}}
+}
 
-sub template_file ($) { #{{{
+sub template_file ($) {
        my $template=shift;
 
        foreach my $dir ($config{templatedir}, "$installdir/share/ikiwiki/templates") {
                return "$dir/$template" if -e "$dir/$template";
        }
        return;
-} #}}}
+}
 
-sub template_params (@) { #{{{
+sub template_params (@) {
        my $filename=template_file(shift);
 
        if (! defined $filename) {
@@ -1048,14 +1624,14 @@ sub template_params (@) { #{{{
                @_
        );
        return wantarray ? @ret : {@ret};
-} #}}}
+}
 
-sub template ($;@) { #{{{
+sub template ($;@) {
        require HTML::Template;
        return HTML::Template->new(template_params(@_));
-} #}}}
+}
 
-sub misctemplate ($$;@) { #{{{
+sub misctemplate ($$;@) {
        my $title=shift;
        my $pagebody=shift;
        
@@ -1072,9 +1648,9 @@ sub misctemplate ($$;@) { #{{{
                shift->(page => "", destpage => "", template => $template);
        });
        return $template->output;
-}#}}}
+}
 
-sub hook (@) { # {{{
+sub hook (@) {
        my %param=@_;
        
        if (! exists $param{type} || ! ref $param{call} || ! exists $param{id}) {
@@ -1085,85 +1661,90 @@ sub hook (@) { # {{{
        
        $hooks{$param{type}}{$param{id}}=\%param;
        return 1;
-} # }}}
+}
 
-sub run_hooks ($$) { # {{{
+sub run_hooks ($$) {
        # Calls the given sub for each hook of the given type,
        # passing it the hook function to call.
        my $type=shift;
        my $sub=shift;
 
        if (exists $hooks{$type}) {
-               my @deferred;
+               my (@first, @middle, @last);
                foreach my $id (keys %{$hooks{$type}}) {
-                       if ($hooks{$type}{$id}{last}) {
-                               push @deferred, $id;
-                               next;
+                       if ($hooks{$type}{$id}{first}) {
+                               push @first, $id;
+                       }
+                       elsif ($hooks{$type}{$id}{last}) {
+                               push @last, $id;
+                       }
+                       else {
+                               push @middle, $id;
                        }
-                       $sub->($hooks{$type}{$id}{call});
                }
-               foreach my $id (@deferred) {
+               foreach my $id (@first, @middle, @last) {
                        $sub->($hooks{$type}{$id}{call});
                }
        }
 
        return 1;
-} #}}}
+}
 
-sub globlist_to_pagespec ($) { #{{{
-       my @globlist=split(' ', shift);
+sub rcs_update () {
+       $hooks{rcs}{rcs_update}{call}->(@_);
+}
 
-       my (@spec, @skip);
-       foreach my $glob (@globlist) {
-               if ($glob=~/^!(.*)/) {
-                       push @skip, $glob;
-               }
-               else {
-                       push @spec, $glob;
-               }
-       }
+sub rcs_prepedit ($) {
+       $hooks{rcs}{rcs_prepedit}{call}->(@_);
+}
 
-       my $spec=join(' or ', @spec);
-       if (@skip) {
-               my $skip=join(' and ', @skip);
-               if (length $spec) {
-                       $spec="$skip and ($spec)";
-               }
-               else {
-                       $spec=$skip;
-               }
-       }
-       return $spec;
-} #}}}
+sub rcs_commit ($$$;$$) {
+       $hooks{rcs}{rcs_commit}{call}->(@_);
+}
 
-sub is_globlist ($) { #{{{
-       my $s=shift;
-       return ( $s =~ /[^\s]+\s+([^\s]+)/ && $1 ne "and" && $1 ne "or" );
-} #}}}
+sub rcs_commit_staged ($$$) {
+       $hooks{rcs}{rcs_commit_staged}{call}->(@_);
+}
+
+sub rcs_add ($) {
+       $hooks{rcs}{rcs_add}{call}->(@_);
+}
 
-sub safequote ($) { #{{{
-       my $s=shift;
-       $s=~s/[{}]//g;
-       return "q{$s}";
-} #}}}
+sub rcs_remove ($) {
+       $hooks{rcs}{rcs_remove}{call}->(@_);
+}
 
-sub add_depends ($$) { #{{{
+sub rcs_rename ($$) {
+       $hooks{rcs}{rcs_rename}{call}->(@_);
+}
+
+sub rcs_recentchanges ($) {
+       $hooks{rcs}{rcs_recentchanges}{call}->(@_);
+}
+
+sub rcs_diff ($) {
+       $hooks{rcs}{rcs_diff}{call}->(@_);
+}
+
+sub rcs_getctime ($) {
+       $hooks{rcs}{rcs_getctime}{call}->(@_);
+}
+
+sub rcs_receive () {
+       $hooks{rcs}{rcs_receive}{call}->();
+}
+
+sub add_depends ($$) {
        my $page=shift;
        my $pagespec=shift;
-       
-       return unless pagespec_valid($pagespec);
 
-       if (! exists $depends{$page}) {
-               $depends{$page}=$pagespec;
-       }
-       else {
-               $depends{$page}=pagespec_merge($depends{$page}, $pagespec);
-       }
+       return unless pagespec_valid($pagespec);
 
+       $depends{$page}{$pagespec} = 1;
        return 1;
-} # }}}
+}
 
-sub file_pruned ($$) { #{{{
+sub file_pruned ($$) {
        require File::Spec;
        my $file=File::Spec->canonpath(shift);
        my $base=File::Spec->canonpath(shift);
@@ -1171,58 +1752,84 @@ sub file_pruned ($$) { #{{{
 
        my $regexp='('.join('|', @{$config{wiki_file_prune_regexps}}).')';
        return $file =~ m/$regexp/ && $file ne $base;
-} #}}}
+}
 
-sub gettext { #{{{
-       # Only use gettext in the rare cases it's needed.
+sub define_gettext () {
+       # If translation is needed, redefine the gettext function to do it.
+       # Otherwise, it becomes a quick no-op.
+       no warnings 'redefine';
        if ((exists $ENV{LANG} && length $ENV{LANG}) ||
            (exists $ENV{LC_ALL} && length $ENV{LC_ALL}) ||
            (exists $ENV{LC_MESSAGES} && length $ENV{LC_MESSAGES})) {
-               if (! $gettext_obj) {
-                       $gettext_obj=eval q{
+               *gettext=sub {
+                       my $gettext_obj=eval q{
                                use Locale::gettext q{textdomain};
                                Locale::gettext->domain('ikiwiki')
                        };
-                       if ($@) {
-                               print STDERR "$@";
-                               $gettext_obj=undef;
+
+                       if ($gettext_obj) {
+                               $gettext_obj->get(shift);
+                       }
+                       else {
                                return shift;
                        }
-               }
-               return $gettext_obj->get(shift);
+               };
        }
        else {
-               return shift;
+               *gettext=sub { return shift };
        }
-} #}}}
+}
 
-sub pagespec_merge ($$) { #{{{
-       my $a=shift;
-       my $b=shift;
+sub gettext {
+       define_gettext();
+       gettext(@_);
+}
 
-       return $a if $a eq $b;
+sub yesno ($) {
+       my $val=shift;
 
-        # Support for old-style GlobLists.
-        if (is_globlist($a)) {
-                $a=globlist_to_pagespec($a);
-        }
-        if (is_globlist($b)) {
-                $b=globlist_to_pagespec($b);
-        }
+       return (defined $val && (lc($val) eq gettext("yes") || lc($val) eq "yes" || $val eq "1"));
+}
 
-       return "($a) or ($b)";
-} #}}}
+sub inject {
+       # Injects a new function into the symbol table to replace an
+       # exported function.
+       my %params=@_;
 
-sub pagespec_translate ($) { #{{{
-       my $spec=shift;
+       # This is deep ugly perl foo, beware.
+       no strict;
+       no warnings;
+       if (! defined $params{parent}) {
+               $params{parent}='::';
+               $params{old}=\&{$params{name}};
+               $params{name}=~s/.*:://;
+       }
+       my $parent=$params{parent};
+       foreach my $ns (grep /^\w+::/, keys %{$parent}) {
+               $ns = $params{parent} . $ns;
+               inject(%params, parent => $ns) unless $ns eq '::main::';
+               *{$ns . $params{name}} = $params{call}
+                       if exists ${$ns}{$params{name}} &&
+                          \&{${$ns}{$params{name}}} == $params{old};
+       }
+       use strict;
+       use warnings;
+}
 
-       # Support for old-style GlobLists.
-       if (is_globlist($spec)) {
-               $spec=globlist_to_pagespec($spec);
-       }
+sub add_link ($$) {
+       my $page=shift;
+       my $link=shift;
+
+       push @{$links{$page}}, $link
+               unless grep { $_ eq $link } @{$links{$page}};
+}
+
+sub pagespec_translate ($) {
+       my $spec=shift;
 
        # Convert spec to perl code.
        my $code="";
+       my @data;
        while ($spec=~m{
                \s*             # ignore whitespace
                (               # 1: match a single word
@@ -1250,26 +1857,29 @@ sub pagespec_translate ($) { #{{{
                }
                elsif ($word =~ /^(\w+)\((.*)\)$/) {
                        if (exists $IkiWiki::PageSpec::{"match_$1"}) {
-                               $code.="IkiWiki::PageSpec::match_$1(\$page, ".safequote($2).", \@_)";
+                               push @data, $2;
+                               $code.="IkiWiki::PageSpec::match_$1(\$page, \$data[$#data], \@_)";
                        }
                        else {
-                               $code.=' 0';
+                               push @data, qq{unknown function in pagespec "$word"};
+                               $code.="IkiWiki::ErrorReason->new(\$data[$#data])";
                        }
                }
                else {
-                       $code.=" IkiWiki::PageSpec::match_glob(\$page, ".safequote($word).", \@_)";
+                       push @data, $word;
+                       $code.=" IkiWiki::PageSpec::match_glob(\$page, \$data[$#data], \@_)";
                }
        }
 
        if (! length $code) {
-               $code=0;
+               $code="IkiWiki::FailReason->new('empty pagespec')";
        }
 
        no warnings;
        return eval 'sub { my $page=shift; '.$code.' }';
-} #}}}
+}
 
-sub pagespec_match ($$;@) { #{{{
+sub pagespec_match ($$;@) {
        my $page=shift;
        my $spec=shift;
        my @params=@_;
@@ -1280,69 +1890,104 @@ sub pagespec_match ($$;@) { #{{{
        }
 
        my $sub=pagespec_translate($spec);
-       return IkiWiki::FailReason->new("syntax error in pagespec \"$spec\"") if $@;
+       return IkiWiki::ErrorReason->new("syntax error in pagespec \"$spec\"")
+               if $@ || ! defined $sub;
        return $sub->($page, @params);
-} #}}}
+}
 
-sub pagespec_valid ($) { #{{{
+sub pagespec_match_list ($$;@) {
+       my $pages=shift;
        my $spec=shift;
+       my @params=@_;
 
        my $sub=pagespec_translate($spec);
-       return ! $@;
-} #}}}
+       error "syntax error in pagespec \"$spec\""
+               if $@ || ! defined $sub;
        
-sub glob2re ($) { #{{{
+       my @ret;
+       my $r;
+       foreach my $page (@$pages) {
+               $r=$sub->($page, @params);
+               push @ret, $page if $r;
+       }
+
+       if (! @ret && defined $r && $r->isa("IkiWiki::ErrorReason")) {
+               error(sprintf(gettext("cannot match pages: %s"), $r));
+       }
+       else {
+               return @ret;
+       }
+}
+
+sub pagespec_valid ($) {
+       my $spec=shift;
+
+       my $sub=pagespec_translate($spec);
+       return ! $@;
+}
+
+sub glob2re ($) {
        my $re=quotemeta(shift);
        $re=~s/\\\*/.*/g;
        $re=~s/\\\?/./g;
        return $re;
-} #}}}
+}
 
 package IkiWiki::FailReason;
 
-use overload ( #{{{
+use overload (
        '""'    => sub { ${$_[0]} },
        '0+'    => sub { 0 },
        '!'     => sub { bless $_[0], 'IkiWiki::SuccessReason'},
        fallback => 1,
-); #}}}
+);
 
-sub new { #{{{
+sub new {
        my $class = shift;
        my $value = shift;
        return bless \$value, $class;
-} #}}}
+}
+
+package IkiWiki::ErrorReason;
+
+our @ISA = 'IkiWiki::FailReason';
 
 package IkiWiki::SuccessReason;
 
-use overload ( #{{{
+use overload (
        '""'    => sub { ${$_[0]} },
        '0+'    => sub { 1 },
        '!'     => sub { bless $_[0], 'IkiWiki::FailReason'},
        fallback => 1,
-); #}}}
+);
 
-sub new { #{{{
+sub new {
        my $class = shift;
        my $value = shift;
        return bless \$value, $class;
-}; #}}}
+};
 
 package IkiWiki::PageSpec;
 
-sub match_glob ($$;@) { #{{{
+sub derel ($$) {
+       my $path=shift;
+       my $from=shift;
+
+       if ($path =~ m!^\./!) {
+               $from=~s#/?[^/]+$## if defined $from;
+               $path=~s#^\./##;
+               $path="$from/$path" if length $from;
+       }
+
+       return $path;
+}
+
+sub match_glob ($$;@) {
        my $page=shift;
        my $glob=shift;
        my %params=@_;
        
-       my $from=exists $params{location} ? $params{location} : '';
-       
-       # relative matching
-       if ($glob =~ m!^\./!) {
-               $from=~s#/?[^/]+$##;
-               $glob=~s#^\./##;
-               $glob="$from/$glob" if length $from;
-       }
+       $glob=derel($glob, $params{location});
 
        my $regexp=IkiWiki::glob2re($glob);
        if ($page=~/^$regexp$/i) {
@@ -1356,26 +2001,20 @@ sub match_glob ($$;@) { #{{{
        else {
                return IkiWiki::FailReason->new("$glob does not match $page");
        }
-} #}}}
+}
 
-sub match_internal ($$;@) { #{{{
+sub match_internal ($$;@) {
        return match_glob($_[0], $_[1], @_, internal => 1)
-} #}}}
+}
 
-sub match_link ($$;@) { #{{{
+sub match_link ($$;@) {
        my $page=shift;
        my $link=lc(shift);
        my %params=@_;
 
+       $link=derel($link, $params{location});
        my $from=exists $params{location} ? $params{location} : '';
 
-       # relative matching
-       if ($link =~ m!^\.! && defined $from) {
-               $from=~s#/?[^/]+$##;
-               $link=~s#^\./##;
-               $link="$from/$link" if length $from;
-       }
-
        my $links = $IkiWiki::links{$page};
        return IkiWiki::FailReason->new("$page has no links") unless $links && @{$links};
        my $bestlink = IkiWiki::bestlink($from, $link);
@@ -1387,18 +2026,25 @@ sub match_link ($$;@) { #{{{
                else {
                        return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
                                if match_glob($p, $link, %params);
+                       $p=~s/^\///;
+                       $link=~s/^\///;
+                       return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
+                               if match_glob($p, $link, %params);
                }
        }
        return IkiWiki::FailReason->new("$page does not link to $link");
-} #}}}
+}
 
-sub match_backlink ($$;@) { #{{{
+sub match_backlink ($$;@) {
        return match_link($_[1], $_[0], @_);
-} #}}}
+}
 
-sub match_created_before ($$;@) { #{{{
+sub match_created_before ($$;@) {
        my $page=shift;
        my $testpage=shift;
+       my %params=@_;
+       
+       $testpage=derel($testpage, $params{location});
 
        if (exists $IkiWiki::pagectime{$testpage}) {
                if ($IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage}) {
@@ -1409,13 +2055,16 @@ sub match_created_before ($$;@) { #{{{
                }
        }
        else {
-               return IkiWiki::FailReason->new("$testpage has no ctime");
+               return IkiWiki::ErrorReason->new("$testpage does not exist");
        }
-} #}}}
+}
 
-sub match_created_after ($$;@) { #{{{
+sub match_created_after ($$;@) {
        my $page=shift;
        my $testpage=shift;
+       my %params=@_;
+       
+       $testpage=derel($testpage, $params{location});
 
        if (exists $IkiWiki::pagectime{$testpage}) {
                if ($IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage}) {
@@ -1426,35 +2075,92 @@ sub match_created_after ($$;@) { #{{{
                }
        }
        else {
-               return IkiWiki::FailReason->new("$testpage has no ctime");
+               return IkiWiki::ErrorReason->new("$testpage does not exist");
        }
-} #}}}
+}
 
-sub match_creation_day ($$;@) { #{{{
+sub match_creation_day ($$;@) {
        if ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift) {
                return IkiWiki::SuccessReason->new('creation_day matched');
        }
        else {
                return IkiWiki::FailReason->new('creation_day did not match');
        }
-} #}}}
+}
 
-sub match_creation_month ($$;@) { #{{{
+sub match_creation_month ($$;@) {
        if ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) {
                return IkiWiki::SuccessReason->new('creation_month matched');
        }
        else {
                return IkiWiki::FailReason->new('creation_month did not match');
        }
-} #}}}
+}
 
-sub match_creation_year ($$;@) { #{{{
+sub match_creation_year ($$;@) {
        if ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) {
                return IkiWiki::SuccessReason->new('creation_year matched');
        }
        else {
                return IkiWiki::FailReason->new('creation_year did not match');
        }
-} #}}}
+}
+
+sub match_user ($$;@) {
+       shift;
+       my $user=shift;
+       my %params=@_;
+       
+       if (! exists $params{user}) {
+               return IkiWiki::ErrorReason->new("no user specified");
+       }
+
+       if (defined $params{user} && lc $params{user} eq lc $user) {
+               return IkiWiki::SuccessReason->new("user is $user");
+       }
+       elsif (! defined $params{user}) {
+               return IkiWiki::FailReason->new("not logged in");
+       }
+       else {
+               return IkiWiki::FailReason->new("user is $params{user}, not $user");
+       }
+}
+
+sub match_admin ($$;@) {
+       shift;
+       shift;
+       my %params=@_;
+       
+       if (! exists $params{user}) {
+               return IkiWiki::ErrorReason->new("no user specified");
+       }
+
+       if (defined $params{user} && IkiWiki::is_admin($params{user})) {
+               return IkiWiki::SuccessReason->new("user is an admin");
+       }
+       elsif (! defined $params{user}) {
+               return IkiWiki::FailReason->new("not logged in");
+       }
+       else {
+               return IkiWiki::FailReason->new("user is not an admin");
+       }
+}
+
+sub match_ip ($$;@) {
+       shift;
+       my $ip=shift;
+       my %params=@_;
+       
+       if (! exists $params{ip}) {
+               return IkiWiki::ErrorReason->new("no IP specified");
+       }
+
+       if (defined $params{ip} && lc $params{ip} eq lc $ip) {
+               return IkiWiki::SuccessReason->new("IP is $ip");
+       }
+       else {
+               return IkiWiki::FailReason->new("IP is $params{ip}, not $ip");
+       }
+}
 
 1
index 99cead64fcbbf5461820720c415f5eb91e8a58fc..af58d7cb56893a831d5ae798d5c5f16fc96b23fd 100644 (file)
@@ -1,5 +1,7 @@
 #!/usr/bin/perl
 
+package IkiWiki;
+
 use warnings;
 use strict;
 use IkiWiki;
@@ -7,21 +9,19 @@ use IkiWiki::UserInfo;
 use open qw{:utf8 :std};
 use Encode;
 
-package IkiWiki;
-
-sub printheader ($) { #{{{
+sub printheader ($) {
        my $session=shift;
        
        if ($config{sslcookie}) {
                print $session->header(-charset => 'utf-8',
-                       -cookie => $session->cookie(-secure => 1));
+                       -cookie => $session->cookie(-httponly => 1, -secure => 1));
        } else {
-               print $session->header(-charset => 'utf-8');
+               print $session->header(-charset => 'utf-8',
+                       -cookie => $session->cookie(-httponly => 1));
        }
+}
 
-} #}}}
-
-sub showform ($$$$;@) { #{{{
+sub showform ($$$$;@) {
        my $form=shift;
        my $buttons=shift;
        my $session=shift;
@@ -38,7 +38,7 @@ sub showform ($$$$;@) { #{{{
        print misctemplate($form->title, $form->render(submit => $buttons), @_);
 }
 
-sub redirect ($$) { #{{{
+sub redirect ($$) {
        my $q=shift;
        my $url=shift;
        if (! $config{w3mmode}) {
@@ -48,36 +48,9 @@ sub redirect ($$) { #{{{
                print "Content-type: text/plain\n";
                print "W3m-control: GOTO $url\n\n";
        }
-} #}}}
-
-sub check_canedit ($$$;$) { #{{{
-       my $page=shift;
-       my $q=shift;
-       my $session=shift;
-       my $nonfatal=shift;
-       
-       my $canedit;
-       run_hooks(canedit => sub {
-               return if defined $canedit;
-               my $ret=shift->($page, $q, $session);
-               if (defined $ret) {
-                       if ($ret eq "") {
-                               $canedit=1;
-                       }
-                       elsif (ref $ret eq 'CODE') {
-                               $ret->() unless $nonfatal;
-                               $canedit=0;
-                       }
-                       elsif (defined $ret) {
-                               error($ret) unless $nonfatal;
-                               $canedit=0;
-                       }
-               }
-       });
-       return $canedit;
-} #}}}
+}
 
-sub decode_cgi_utf8 ($) { #{{{
+sub decode_cgi_utf8 ($) {
        # decode_form_utf8 method is needed for 5.10
        if ($] < 5.01) {
                my $cgi = shift;
@@ -85,9 +58,9 @@ sub decode_cgi_utf8 ($) { #{{{
                        $cgi->param($f, map { decode_utf8 $_ } $cgi->param($f));
                }
        }
-} #}}}
+}
 
-sub decode_form_utf8 ($) { #{{{
+sub decode_form_utf8 ($) {
        if ($] >= 5.01) {
                my $form = shift;
                foreach my $f ($form->field) {
@@ -97,11 +70,11 @@ sub decode_form_utf8 ($) { #{{{
                        );
                }
        }
-} #}}}
+}
 
 # Check if the user is signed in. If not, redirect to the signin form and
 # save their place to return to later.
-sub needsignin ($$) { #{{{
+sub needsignin ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -112,9 +85,9 @@ sub needsignin ($$) { #{{{
                cgi_savesession($session);
                exit;
        }
-} #}}} 
+}
 
-sub cgi_signin ($$) { #{{{
+sub cgi_signin ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -154,9 +127,9 @@ sub cgi_signin ($$) { #{{{
        }
 
        showform($form, $buttons, $session, $q);
-} #}}}
+}
 
-sub cgi_postsignin ($$) { #{{{
+sub cgi_postsignin ($$) {
        my $q=shift;
        my $session=shift;
        
@@ -169,11 +142,16 @@ sub cgi_postsignin ($$) { #{{{
                exit;
        }
        else {
-               error(gettext("login failed, perhaps you need to turn on cookies?"));
+               if ($config{sslcookie} && ! $q->https()) {
+                       error(gettext("probable misconfiguration: sslcookie is set, but you are attempting to login via http, not https"));
+               }
+               else {
+                       error(gettext("login failed, perhaps you need to turn on cookies?"));
+               }
        }
-} #}}}
+}
 
-sub cgi_prefs ($$) { #{{{
+sub cgi_prefs ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -227,21 +205,12 @@ sub cgi_prefs ($$) { #{{{
        $form->field(name => "sid", type => "hidden", value => $session->id,
                force => 1);
        $form->field(name => "email", size => 50, fieldset => "preferences");
-       $form->field(name => "banned_users", size => 50,
-               fieldset => "admin");
        
        my $user_name=$session->param("name");
-       if (! is_admin($user_name)) {
-               $form->field(name => "banned_users", type => "hidden");
-       }
 
        if (! $form->submitted) {
                $form->field(name => "email", force => 1,
                        value => userinfo_get($user_name, "email"));
-               if (is_admin($user_name)) {
-                       $form->field(name => "banned_users", force => 1,
-                               value => join(" ", get_banned_users()));
-               }
        }
        
        if ($form->submitted eq 'Logout') {
@@ -258,410 +227,90 @@ sub cgi_prefs ($$) { #{{{
                        userinfo_set($user_name, 'email', $form->field('email')) ||
                                error("failed to set email");
                }
-               if (is_admin($user_name)) {
-                       set_banned_users(grep { ! is_admin($_) }
-                                       split(' ',
-                                               $form->field("banned_users"))) ||
-                               error("failed saving changes");
-               }
+
                $form->text(gettext("Preferences saved."));
        }
        
        showform($form, $buttons, $session, $q);
-} #}}}
-
-sub cgi_editpage ($$) { #{{{
-       my $q=shift;
-       my $session=shift;
-       
-       decode_cgi_utf8($q);
-
-       my @fields=qw(do rcsinfo subpage from page type editcontent comments);
-       my @buttons=("Save Page", "Preview", "Cancel");
-       eval q{use CGI::FormBuilder};
-       error($@) if $@;
-       my $form = CGI::FormBuilder->new(
-               fields => \@fields,
-               charset => "utf-8",
-               method => 'POST',
-               required => [qw{editcontent}],
-               javascript => 0,
-               params => $q,
-               action => $config{cgiurl},
-               header => 0,
-               table => 0,
-               template => scalar template_params("editpage.tmpl"),
-               wikiname => $config{wikiname},
-       );
-       
-       decode_form_utf8($form);
-       run_hooks(formbuilder_setup => sub {
-               shift->(form => $form, cgi => $q, session => $session,
-                       buttons => \@buttons);
-       });
-       decode_form_utf8($form);
-       
-       # This untaint is safe because we check file_pruned.
-       my $page=$form->field('page');
-       $page=possibly_foolish_untaint($page);
-       if (! defined $page || ! length $page ||
-           file_pruned($page, $config{srcdir}) || $page=~/^\//) {
-               error("bad page name");
-       }
-
-       my $baseurl=$config{url}."/".htmlpage($page);
-       
-       my $from;
-       if (defined $form->field('from')) {
-               ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
-       }
-       
-       my $file;
-       my $type;
-       if (exists $pagesources{$page} && $form->field("do") ne "create") {
-               $file=$pagesources{$page};
-               $type=pagetype($file);
-               if (! defined $type || $type=~/^_/) {
-                       error(sprintf(gettext("%s is not an editable page"), $page));
-               }
-               if (! $form->submitted) {
-                       $form->field(name => "rcsinfo",
-                               value => rcs_prepedit($file), force => 1);
-               }
-               $form->field(name => "editcontent", validate => '/.*/');
-       }
-       else {
-               $type=$form->param('type');
-               if (defined $type && length $type && $hooks{htmlize}{$type}) {
-                       $type=possibly_foolish_untaint($type);
-               }
-               elsif (defined $from && exists $pagesources{$from}) {
-                       # favor the type of linking page
-                       $type=pagetype($pagesources{$from});
-               }
-               $type=$config{default_pageext} unless defined $type;
-               $file=$page.".".$type;
-               if (! $form->submitted) {
-                       $form->field(name => "rcsinfo", value => "", force => 1);
-               }
-               $form->field(name => "editcontent", validate => '/.+/');
-       }
-
-       $form->field(name => "do", type => 'hidden');
-       $form->field(name => "sid", type => "hidden", value => $session->id,
-               force => 1);
-       $form->field(name => "from", type => 'hidden');
-       $form->field(name => "rcsinfo", type => 'hidden');
-       $form->field(name => "subpage", type => 'hidden');
-       $form->field(name => "page", value => $page, force => 1);
-       $form->field(name => "type", value => $type, force => 1);
-       $form->field(name => "comments", type => "text", size => 80);
-       $form->field(name => "editcontent", type => "textarea", rows => 20,
-               cols => 80);
-       $form->tmpl_param("can_commit", $config{rcs});
-       $form->tmpl_param("indexlink", indexlink());
-       $form->tmpl_param("helponformattinglink",
-               htmllink($page, $page, "ikiwiki/formatting",
-                       noimageinline => 1,
-                       linktext => "FormattingHelp"));
-       
-       if ($form->submitted eq "Cancel") {
-               if ($form->field("do") eq "create" && defined $from) {
-                       redirect($q, "$config{url}/".htmlpage($from));
-               }
-               elsif ($form->field("do") eq "create") {
-                       redirect($q, $config{url});
-               }
-               else {
-                       redirect($q, "$config{url}/".htmlpage($page));
-               }
-               return;
-       }
-       elsif ($form->submitted eq "Preview") {
-               my $new=not exists $pagesources{$page};
-               if ($new) {
-                       # temporarily record its type
-                       $pagesources{$page}=$page.".".$type;
-               }
+}
 
-               my $content=$form->field('editcontent');
+sub cgi_custom_failure ($$) {
+       my $header=shift;
+       my $message=shift;
 
-               run_hooks(editcontent => sub {
-                       $content=shift->(
-                               content => $content,
-                               page => $page,
-                               cgi => $q,
-                               session => $session,
-                       );
-               });
-               my $preview=htmlize($page, $page, $type,
-                       linkify($page, $page,
-                       preprocess($page, $page,
-                       filter($page, $page, $content), 0, 1)));
-               run_hooks(format => sub {
-                       $preview=shift->(
-                               page => $page,
-                               content => $preview,
-                       );
-               });
-               $form->tmpl_param("page_preview", $preview);
-       
-               if ($new) {
-                       delete $pagesources{$page};
-               }
-               # previewing may have created files on disk
-               saveindex();
-       }
-       elsif ($form->submitted eq "Save Page") {
-               $form->tmpl_param("page_preview", "");
-       }
-       $form->tmpl_param("page_conflict", "");
-       
-       if ($form->submitted ne "Save Page" || ! $form->validate) {
-               if ($form->field("do") eq "create") {
-                       my @page_locs;
-                       my $best_loc;
-                       if (! defined $from || ! length $from ||
-                           $from ne $form->field('from') ||
-                           file_pruned($from, $config{srcdir}) ||
-                           $from=~/^\// ||
-                           $form->submitted eq "Preview") {
-                               @page_locs=$best_loc=$page;
-                       }
-                       else {
-                               my $dir=$from."/";
-                               $dir=~s![^/]+/+$!!;
-                               
-                               if ((defined $form->field('subpage') && length $form->field('subpage')) ||
-                                   $page eq gettext('discussion')) {
-                                       $best_loc="$from/$page";
-                               }
-                               else {
-                                       $best_loc=$dir.$page;
-                               }
-                               
-                               push @page_locs, $dir.$page;
-                               push @page_locs, "$from/$page";
-                               while (length $dir) {
-                                       $dir=~s![^/]+/+$!!;
-                                       push @page_locs, $dir.$page;
-                               }
-                       
-                               push @page_locs, "$config{userdir}/$page"
-                                       if length $config{userdir};
-                       }
+       print $header;
+       print $message;
 
-                       @page_locs = grep {
-                               ! exists $pagecase{lc $_}
-                       } @page_locs;
-                       if (! @page_locs) {
-                               # hmm, someone else made the page in the
-                               # meantime?
-                               if ($form->submitted eq "Preview") {
-                                       # let them go ahead with the edit
-                                       # and resolve the conflict at save
-                                       # time
-                                       @page_locs=$page;
-                               }
-                               else {
-                                       redirect($q, "$config{url}/".htmlpage($page));
-                                       return;
-                               }
-                       }
+       # Internet Explod^Hrer won't show custom 404 responses
+       # unless they're >= 512 bytes
+       print ' ' x 512;
 
-                       my @editable_locs = grep {
-                               check_canedit($_, $q, $session, 1)
-                       } @page_locs;
-                       if (! @editable_locs) {
-                               # let it throw an error this time
-                               map { check_canedit($_, $q, $session) } @page_locs;
-                       }
-                       
-                       my @page_types;
-                       if (exists $hooks{htmlize}) {
-                               @page_types=grep { !/^_/ }
-                                       keys %{$hooks{htmlize}};
-                       }
-                       
-                       $form->tmpl_param("page_select", 1);
-                       $form->field(name => "page", type => 'select',
-                               options => [ map { [ $_, pagetitle($_, 1) ] } @editable_locs ],
-                               value => $best_loc);
-                       $form->field(name => "type", type => 'select',
-                               options => \@page_types);
-                       $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
-                       
-               }
-               elsif ($form->field("do") eq "edit") {
-                       check_canedit($page, $q, $session);
-                       if (! defined $form->field('editcontent') || 
-                           ! length $form->field('editcontent')) {
-                               my $content="";
-                               if (exists $pagesources{$page}) {
-                                       $content=readfile(srcfile($pagesources{$page}));
-                                       $content=~s/\n/\r\n/g;
-                               }
-                               $form->field(name => "editcontent", value => $content,
-                                       force => 1);
-                       }
-                       $form->tmpl_param("page_select", 0);
-                       $form->field(name => "page", type => 'hidden');
-                       $form->field(name => "type", type => 'hidden');
-                       $form->title(sprintf(gettext("editing %s"), pagetitle($page)));
-               }
-               
-               showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
-       }
-       else {
-               # save page
-               check_canedit($page, $q, $session);
-       
-               # The session id is stored on the form and checked to
-               # guard against CSRF. But only if the user is logged in,
-               # as anonok can allow anonymous edits.
-               if (defined $session->param("name")) {
-                       my $sid=$q->param('sid');
-                       if (! defined $sid || $sid ne $session->id) {
-                               error(gettext("Your login session has expired."));
-                       }
-               }
+       exit;
+}
 
-               my $exists=-e "$config{srcdir}/$file";
-
-               if ($form->field("do") ne "create" && ! $exists &&
-                   ! defined srcfile($file, 1)) {
-                       $form->tmpl_param("page_gone", 1);
-                       $form->field(name => "do", value => "create", force => 1);
-                       $form->tmpl_param("page_select", 0);
-                       $form->field(name => "page", type => 'hidden');
-                       $form->field(name => "type", type => 'hidden');
-                       $form->title(sprintf(gettext("editing %s"), $page));
-                       showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
-                       return;
-               }
-               elsif ($form->field("do") eq "create" && $exists) {
-                       $form->tmpl_param("creation_conflict", 1);
-                       $form->field(name => "do", value => "edit", force => 1);
-                       $form->tmpl_param("page_select", 0);
-                       $form->field(name => "page", type => 'hidden');
-                       $form->field(name => "type", type => 'hidden');
-                       $form->title(sprintf(gettext("editing %s"), $page));
-                       $form->field("editcontent", 
-                               value => readfile("$config{srcdir}/$file").
-                                        "\n\n\n".$form->field("editcontent"),
-                               force => 1);
-                       showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
-                       return;
-               }
-               
-               my $content=$form->field('editcontent');
-               run_hooks(editcontent => sub {
-                       $content=shift->(
-                               content => $content,
-                               page => $page,
-                               cgi => $q,
-                               session => $session,
-                       );
-               });
-               $content=~s/\r\n/\n/g;
-               $content=~s/\r/\n/g;
-               $content.="\n" if $content !~ /\n$/;
-
-               $config{cgi}=0; # avoid cgi error message
-               eval { writefile($file, $config{srcdir}, $content) };
-               $config{cgi}=1;
-               if ($@) {
-                       $form->field(name => "rcsinfo", value => rcs_prepedit($file),
-                               force => 1);
-                       $form->tmpl_param("failed_save", 1);
-                       $form->tmpl_param("error_message", $@);
-                       $form->field("editcontent", value => $content, force => 1);
-                       $form->tmpl_param("page_select", 0);
-                       $form->field(name => "page", type => 'hidden');
-                       $form->field(name => "type", type => 'hidden');
-                       $form->title(sprintf(gettext("editing %s"), $page));
-                       showform($form, \@buttons, $session, $q,
-                               forcebaseurl => $baseurl);
-                       return;
-               }
-               
-               my $conflict;
-               if ($config{rcs}) {
-                       my $message="";
-                       if (defined $form->field('comments') &&
-                           length $form->field('comments')) {
-                               $message=$form->field('comments');
-                       }
-                       
-                       if (! $exists) {
-                               rcs_add($file);
-                       }
+sub check_banned ($$) {
+       my $q=shift;
+       my $session=shift;
 
-                       # Prevent deadlock with post-commit hook by
-                       # signaling to it that it should not try to
-                       # do anything.
-                       disable_commit_hook();
-                       $conflict=rcs_commit($file, $message,
-                               $form->field("rcsinfo"),
-                               $session->param("name"), $ENV{REMOTE_ADDR});
-                       enable_commit_hook();
-                       rcs_update();
-               }
-               
-               # Refresh even if there was a conflict, since other changes
-               # may have been committed while the post-commit hook was
-               # disabled.
-               require IkiWiki::Render;
-               refresh();
-               saveindex();
-
-               if (defined $conflict) {
-                       $form->field(name => "rcsinfo", value => rcs_prepedit($file),
-                               force => 1);
-                       $form->tmpl_param("page_conflict", 1);
-                       $form->field("editcontent", value => $conflict, force => 1);
-                       $form->field("do", "edit", force => 1);
-                       $form->tmpl_param("page_select", 0);
-                       $form->field(name => "page", type => 'hidden');
-                       $form->field(name => "type", type => 'hidden');
-                       $form->title(sprintf(gettext("editing %s"), $page));
-                       showform($form, \@buttons, $session, $q,
-                               forcebaseurl => $baseurl);
-                       return;
-               }
-               else {
-                       # The trailing question mark tries to avoid broken
-                       # caches and get the most recent version of the page.
-                       redirect($q, "$config{url}/".htmlpage($page)."?updated");
+       my $name=$session->param("name");
+       if (defined $name) {
+               if (grep { $name eq $_ } @{$config{banned_users}}) {
+                       $session->delete();
+                       cgi_savesession($session);
+                       cgi_custom_failure(
+                               $q->header(-status => "403 Forbidden"),
+                               gettext("You are banned."));
                }
        }
-} #}}}
+}
 
-sub cgi_getsession ($) { #{{{
+sub cgi_getsession ($) {
        my $q=shift;
 
-       eval q{use CGI::Session};
+       eval q{use CGI::Session; use HTML::Entities};
        error($@) if $@;
-       CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname}));
+       CGI::Session->name("ikiwiki_session_".encode_entities($config{wikiname}));
        
        my $oldmask=umask(077);
-       my $session = CGI::Session->new("driver:DB_File", $q,
-               { FileName => "$config{wikistatedir}/sessions.db" });
+       my $session = eval {
+               CGI::Session->new("driver:DB_File", $q,
+                       { FileName => "$config{wikistatedir}/sessions.db" })
+       };
+       if (! $session || $@) {
+               error($@." ".CGI::Session->errstr());
+       }
+       
        umask($oldmask);
 
        return $session;
-} #}}}
+}
+
+# To guard against CSRF, the user's session id (sid)
+# can be stored on a form. This function will check
+# (for logged in users) that the sid on the form matches
+# the session id in the cookie.
+sub checksessionexpiry ($$) {
+       my $q=shift;
+       my $session = shift;
 
-sub cgi_savesession ($) { #{{{
+       if (defined $session->param("name")) {
+               my $sid=$q->param('sid');
+               if (! defined $sid || $sid ne $session->id) {
+                       error(gettext("Your login session has expired."));
+               }
+       }
+}
+
+sub cgi_savesession ($) {
        my $session=shift;
 
        # Force session flush with safe umask.
        my $oldmask=umask(077);
        $session->flush;
        umask($oldmask);
-} #}}}
+}
 
-sub cgi (;$$) { #{{{
+sub cgi (;$$) {
        my $q=shift;
        my $session=shift;
 
@@ -687,7 +336,7 @@ sub cgi (;$$) { #{{{
                        error("\"do\" parameter missing");
                }
        }
-       
+
        # Need to lock the wiki before getting a session.
        lockwiki();
        loadindex();
@@ -714,14 +363,8 @@ sub cgi (;$$) { #{{{
                }
        }
        
-       if (defined $session->param("name") &&
-           userinfo_get($session->param("name"), "banned")) {
-               print $q->header(-status => "403 Forbidden");
-               $session->delete();
-               print gettext("You are banned.");
-               cgi_savesession($session);
-       }
-
+       check_banned($q, $session);
+       
        run_hooks(sessioncgi => sub { shift->($q, $session) });
 
        if ($do eq 'signin') {
@@ -731,15 +374,22 @@ sub cgi (;$$) { #{{{
        elsif ($do eq 'prefs') {
                cgi_prefs($q, $session);
        }
-       elsif ($do eq 'create' || $do eq 'edit') {
-               cgi_editpage($q, $session);
-       }
        elsif (defined $session->param("postsignin") || $do eq 'postsignin') {
                cgi_postsignin($q, $session);
        }
        else {
                error("unknown do parameter");
        }
-} #}}}
+}
+
+# Does not need to be called directly; all errors will go through here.
+sub cgierror ($) {
+       my $message=shift;
+
+       print "Content-type: text/html\n\n";
+       print misctemplate(gettext("Error"),
+               "<p class=\"error\">".gettext("Error").": $message</p>");
+       die $@;
+}
 
 1
diff --git a/IkiWiki/Plugin/404.pm b/IkiWiki/Plugin/404.pm
new file mode 100644 (file)
index 0000000..bae9e15
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/perl
+# Copyright © 2009 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+# Licensed under the GNU GPL, version 2, or any later version published by the
+# Free Software Foundation
+package IkiWiki::Plugin::404;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "cgi", id => '404',  call => \&cgi);
+       IkiWiki::loadplugin("goto");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       # not really a matter of safety, but enabling/disabling
+                       # through a web interface is useless - it needs web
+                       # server admin action too
+                       safe => 0,
+                       rebuild => 0,
+               }
+}
+
+sub cgi_page_from_404 ($$$) {
+       my $path = shift;
+       my $baseurl = shift;
+       my $usedirs = shift;
+
+       # fail if missing from environment or whatever
+       return undef unless defined $path;
+       return undef unless defined $baseurl;
+
+       # with usedirs on, path is like /~fred/foo/bar/ or /~fred/foo/bar or
+       #    /~fred/foo/bar/index.html
+       # with usedirs off, path is like /~fred/foo/bar.html
+       # baseurl is like 'http://people.example.com/~fred'
+
+       # convert baseurl to ~fred
+       unless ($baseurl =~ s{^https?://[^/]+/?}{}) {
+               return undef;
+       }
+
+       # convert path to /~fred/foo/bar
+       if ($usedirs) {
+               $path =~ s/\/*(?:index\.$config{htmlext})?$//;
+       }
+       else {
+               $path =~ s/\.$config{htmlext}$//;
+       }
+
+       # remove /~fred/
+       unless ($path =~ s{^/*\Q$baseurl\E/*}{}) {
+               return undef;
+       }
+
+       # special case for the index
+       unless ($path) {
+               return 'index';
+       }
+
+       return $path;
+}
+
+sub cgi ($) {
+       my $cgi=shift;
+
+       if (exists $ENV{REDIRECT_STATUS} && 
+           $ENV{REDIRECT_STATUS} eq '404') {
+               my $page = cgi_page_from_404($ENV{REDIRECT_URL},
+                       $config{url}, $config{usedirs});
+               IkiWiki::Plugin::goto::cgi_goto($cgi, $page);
+       }
+}
+
+1;
index b5354a823482e243e3c7d9fdd9ec4a2db6e010eb..5a9eb433de8311e0a9d77909aa45343c609bdea5 100644 (file)
@@ -4,7 +4,7 @@ package IkiWiki::Plugin::aggregate;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Parser;
 use HTML::Tagset;
 use HTML::Entities;
@@ -14,33 +14,64 @@ use open qw{:utf8 :std};
 my %feeds;
 my %guids;
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "aggregate", call => \&getopt);
+       hook(type => "getsetup", id => "aggregate", call => \&getsetup);
        hook(type => "checkconfig", id => "aggregate", call => \&checkconfig);
        hook(type => "needsbuild", id => "aggregate", call => \&needsbuild);
        hook(type => "preprocess", id => "aggregate", call => \&preprocess);
         hook(type => "delete", id => "aggregate", call => \&delete);
        hook(type => "savestate", id => "aggregate", call => \&savestate);
+       hook(type => "htmlize", id => "_aggregated", call => \&htmlize);
        if (exists $config{aggregate_webtrigger} && $config{aggregate_webtrigger}) {
                hook(type => "cgi", id => "aggregate", call => \&cgi);
        }
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
         eval q{use Getopt::Long};
        error($@) if $@;
         Getopt::Long::Configure('pass_through');
-        GetOptions("aggregate" => \$config{aggregate});
-} #}}}
+        GetOptions(
+               "aggregate" => \$config{aggregate},
+               "aggregateinternal!" => \$config{aggregateinternal},
+       );
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               aggregateinternal => {
+                       type => "boolean",
+                       example => 1,
+                       description => "enable aggregation to internal pages?",
+                       safe => 0, # enabling needs manual transition
+                       rebuild => 0,
+               },
+               aggregate_webtrigger => {
+                       type => "boolean",
+                       example => 0,
+                       description => "allow aggregation to be triggered via the web?",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
+       if (! defined $config{aggregateinternal}) {
+               $config{aggregateinternal}=1;
+       }
 
-sub checkconfig () { #{{{
        if ($config{aggregate} && ! ($config{post_commit} && 
                                     IkiWiki::commit_hook_enabled())) {
                launchaggregation();
        }
-} #}}}
+}
 
-sub cgi ($) { #{{{
+sub cgi ($) {
        my $cgi=shift;
 
        if (defined $cgi->param('do') &&
@@ -63,9 +94,9 @@ sub cgi ($) { #{{{
                }
                exit 0;
        }
-} #}}}
+}
 
-sub launchaggregation () { #{{{
+sub launchaggregation () {
        # See if any feeds need aggregation.
        loadstate();
        my @feeds=needsaggregate();
@@ -108,9 +139,64 @@ sub launchaggregation () { #{{{
        unlockaggregate();
 
        return 1;
-} #}}}
+}
+
+#  Pages with extension _aggregated have plain html markup, pass through.
+sub htmlize (@) {
+       my %params=@_;
+       return $params{content};
+}
 
-sub needsbuild (@) { #{{{
+# Used by ikiwiki-transition aggregateinternal.
+sub migrate_to_internal {
+       if (! lockaggregate()) {
+               error("an aggregation process is currently running");
+       }
+
+       IkiWiki::lockwiki();
+       loadstate();
+       $config{verbose}=1;
+
+       foreach my $data (values %guids) {
+               next unless $data->{page};
+               next if $data->{expired};
+               
+               $config{aggregateinternal} = 0;
+               my $oldname = "$config{srcdir}/".htmlfn($data->{page});
+               my $oldoutput = $config{destdir}."/".IkiWiki::htmlpage($data->{page});
+               
+               $config{aggregateinternal} = 1;
+               my $newname = "$config{srcdir}/".htmlfn($data->{page});
+               
+               debug "moving $oldname -> $newname";
+               if (-e $newname) {
+                       if (-e $oldname) {
+                               error("$newname already exists");
+                       }
+                       else {
+                               debug("already renamed to $newname?");
+                       }
+               }
+               elsif (-e $oldname) {
+                       rename($oldname, $newname) || error("$!");
+               }
+               else {
+                       debug("$oldname not found");
+               }
+               if (-e $oldoutput) {
+                       require IkiWiki::Render;
+                       debug("removing output file $oldoutput");
+                       IkiWiki::prune($oldoutput);
+               }
+       }
+       
+       savestate();
+       IkiWiki::unlockwiki;
+       
+       unlockaggregate();
+}
+
+sub needsbuild (@) {
        my $needsbuild=shift;
        
        loadstate();
@@ -124,14 +210,14 @@ sub needsbuild (@) { #{{{
                        markunseen($feed->{sourcepage});
                }
        }
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        foreach my $required (qw{name url}) {
                if (! exists $params{$required}) {
-                       return "[[aggregate ".sprintf(gettext("missing %s parameter"), $required)."]]";
+                       error sprintf(gettext("missing %s parameter"), $required)
                }
        }
 
@@ -146,7 +232,7 @@ sub preprocess (@) { #{{{
        $feed->{name}=$name;
        $feed->{sourcepage}=$params{page};
        $feed->{url}=$params{url};
-       my $dir=exists $params{dir} ? $params{dir} : $params{page}."/".IkiWiki::titlepage($params{name});
+       my $dir=exists $params{dir} ? $params{dir} : $params{page}."/".titlepage($params{name});
        $dir=~s/^\/+//;
        ($dir)=$dir=~/$config{wiki_file_regexp}/;
        $feed->{dir}=$dir;
@@ -163,6 +249,7 @@ sub preprocess (@) { #{{{
        $feed->{template}=$params{template} . ".tmpl";
        delete $feed->{unseen};
        $feed->{lastupdate}=0 unless defined $feed->{lastupdate};
+       $feed->{lasttry}=$feed->{lastupdate} unless defined $feed->{lasttry};
        $feed->{numposts}=0 unless defined $feed->{numposts};
        $feed->{newposts}=0 unless defined $feed->{newposts};
        $feed->{message}=gettext("new feed") unless defined $feed->{message};
@@ -183,9 +270,9 @@ sub preprocess (@) { #{{{
               ($feed->{newposts} ? "; ".$feed->{newposts}.
                                    " ".gettext("new") : "").
               ")";
-} # }}}
+}
 
-sub delete (@) { #{{{
+sub delete (@) {
        my @files=@_;
 
        # Remove feed data for removed pages.
@@ -193,9 +280,9 @@ sub delete (@) { #{{{
                my $page=pagename($file);
                markunseen($page);
        }
-} #}}}
+}
 
-sub markunseen ($) { #{{{
+sub markunseen ($) {
        my $page=shift;
 
        foreach my $id (keys %feeds) {
@@ -203,11 +290,11 @@ sub markunseen ($) { #{{{
                        $feeds{$id}->{unseen}=1;
                }
        }
-} #}}}
+}
 
 my $state_loaded=0;
 
-sub loadstate () { #{{{
+sub loadstate () {
        return if $state_loaded;
        $state_loaded=1;
        if (-e "$config{wikistatedir}/aggregate") {
@@ -241,9 +328,9 @@ sub loadstate () { #{{{
 
                close IN;
        }
-} #}}}
+}
 
-sub savestate () { #{{{
+sub savestate () {
        return unless $state_loaded;
        garbage_collect();
        my $newfile="$config{wikistatedir}/aggregate.new";
@@ -260,7 +347,8 @@ sub savestate () { #{{{
                                push @line, "tag=$_" foreach @{$data->{tags}};
                        }
                        else {
-                               push @line, "$field=".$data->{$field};
+                               push @line, "$field=".$data->{$field}
+                                       if defined $data->{$field};
                        }
                }
                print OUT join(" ", @line)."\n" || error("write $newfile: $!", $cleanup);
@@ -268,9 +356,9 @@ sub savestate () { #{{{
        close OUT || error("save $newfile: $!", $cleanup);
        rename($newfile, "$config{wikistatedir}/aggregate") ||
                error("rename $newfile: $!", $cleanup);
-} #}}}
+}
 
-sub garbage_collect () { #{{{
+sub garbage_collect () {
        foreach my $name (keys %feeds) {
                # remove any feeds that were not seen while building the pages
                # that used to contain them
@@ -282,20 +370,20 @@ sub garbage_collect () { #{{{
        foreach my $guid (values %guids) {
                # any guid whose feed is gone should be removed
                if (! exists $feeds{$guid->{feed}}) {
-                       unlink pagefile($guid->{page})
+                       unlink "$config{srcdir}/".htmlfn($guid->{page})
                                if exists $guid->{page};
                        delete $guids{$guid->{guid}};
                }
                # handle expired guids
                elsif ($guid->{expired} && exists $guid->{page}) {
-                       unlink pagefile($guid->{page});
+                       unlink "$config{srcdir}/".htmlfn($guid->{page});
                        delete $guid->{page};
                        delete $guid->{md5};
                }
        }
-} #}}}
+}
 
-sub mergestate () { #{{{
+sub mergestate () {
        # Load the current state in from disk, and merge into it
        # values from the state in memory that might have changed
        # during aggregation.
@@ -308,14 +396,15 @@ sub mergestate () { #{{{
        # fields.
        foreach my $name (keys %myfeeds) {
                if (exists $feeds{$name}) {
-                       foreach my $field (qw{message lastupdate numposts
-                                             newposts error}) {
+                       foreach my $field (qw{message lastupdate lasttry
+                                             numposts newposts error}) {
                                $feeds{$name}->{$field}=$myfeeds{$name}->{$field};
                        }
                }
        }
 
        # New guids can be created during aggregation.
+       # Guids have a few fields that may be updated during aggregation.
        # It's also possible that guids were removed from the on-disk state
        # while the aggregation was in process. That would only happen if
        # their feed was also removed, so any removed guids added back here
@@ -324,25 +413,30 @@ sub mergestate () { #{{{
                if (! exists $guids{$guid}) {
                        $guids{$guid}=$myguids{$guid};
                }
+               else {
+                       foreach my $field (qw{md5}) {
+                               $guids{$guid}->{$field}=$myguids{$guid}->{$field};
+                       }
+               }
        }
-} #}}}
+}
 
-sub clearstate () { #{{{
+sub clearstate () {
        %feeds=();
        %guids=();
        $state_loaded=0;
-} #}}}
+}
 
-sub expire () { #{{{
+sub expire () {
        foreach my $feed (values %feeds) {
                next unless $feed->{expireage} || $feed->{expirecount};
                my $count=0;
                my %seen;
-               foreach my $item (sort { $IkiWiki::pagectime{$b->{page}} <=> $IkiWiki::pagectime{$a->{page}} }
-                                 grep { exists $_->{page} && $_->{feed} eq $feed->{name} && $IkiWiki::pagectime{$_->{page}} }
+               foreach my $item (sort { ($IkiWiki::pagectime{$b->{page}} || 0) <=> ($IkiWiki::pagectime{$a->{page}} || 0) }
+                                 grep { exists $_->{page} && $_->{feed} eq $feed->{name} }
                                  values %guids) {
                        if ($feed->{expireage}) {
-                               my $days_old = (time - $IkiWiki::pagectime{$item->{page}}) / 60 / 60 / 24;
+                               my $days_old = (time - ($IkiWiki::pagectime{$item->{page}} || 0)) / 60 / 60 / 24;
                                if ($days_old > $feed->{expireage}) {
                                        debug(sprintf(gettext("expiring %s (%s days old)"),
                                                $item->{page}, int($days_old)));
@@ -362,24 +456,24 @@ sub expire () { #{{{
                        }
                }
        }
-} #}}}
+}
 
-sub needsaggregate () { #{{{
+sub needsaggregate () {
        return values %feeds if $config{rebuild};
        return grep { time - $_->{lastupdate} >= $_->{updateinterval} } values %feeds;
-} #}}}
+}
 
-sub aggregate (@) { #{{{
+sub aggregate (@) {
        eval q{use XML::Feed};
        error($@) if $@;
        eval q{use URI::Fetch};
        error($@) if $@;
 
        foreach my $feed (@_) {
-               $feed->{lastupdate}=time;
+               $feed->{lasttry}=time;
                $feed->{newposts}=0;
-               $feed->{message}=sprintf(gettext("processed ok at %s"),
-                       displaytime($feed->{lastupdate}));
+               $feed->{message}=sprintf(gettext("last checked %s"),
+                       displaytime($feed->{lasttry}));
                $feed->{error}=0;
 
                debug(sprintf(gettext("checking feed %s ..."), $feed->{name}));
@@ -401,6 +495,10 @@ sub aggregate (@) { #{{{
                        debug($feed->{message});
                        next;
                }
+
+               # lastupdate is only set if we were able to contact the server
+               $feed->{lastupdate}=$feed->{lasttry};
+
                if ($res->status == URI::Fetch::URI_GONE()) {
                        $feed->{message}=gettext("feed not found");
                        $feed->{error}=1;
@@ -414,15 +512,19 @@ sub aggregate (@) { #{{{
                        # that contains invalid UTF-8 sequences. Convert
                        # feed to ascii to try to work around.
                        $feed->{message}.=" ".sprintf(gettext("(invalid UTF-8 stripped from feed)"));
-                       $content=Encode::decode_utf8($content, 0);
-                       $f=eval{XML::Feed->parse(\$content)};
+                       $f=eval {
+                               $content=Encode::decode_utf8($content, 0);
+                               XML::Feed->parse(\$content)
+                       };
                }
                if ($@) {
                        # Another possibility is badly escaped entities.
                        $feed->{message}.=" ".sprintf(gettext("(feed entities escaped)"));
                        $content=~s/\&(?!amp)(\w+);/&amp;$1;/g;
-                       $content=Encode::decode_utf8($content, 0);
-                       $f=eval{XML::Feed->parse(\$content)};
+                       $f=eval {
+                               $content=Encode::decode_utf8($content, 0);
+                               XML::Feed->parse(\$content)
+                       };
                }
                if ($@) {
                        $feed->{message}=gettext("feed crashed XML::Feed!")." ($@)";
@@ -438,20 +540,32 @@ sub aggregate (@) { #{{{
                }
 
                foreach my $entry ($f->entries) {
+                       # XML::Feed doesn't work around XML::Atom's bizarre
+                       # API, so we will. Real unicode strings? Yes please.
+                       # See [[bugs/Aggregated_Atom_feeds_are_double-encoded]]
+                       local $XML::Atom::ForceUnicode = 1;
+
+                       my $c=$entry->content;
+                       # atom feeds may have no content, only a summary
+                       if (! defined $c && ref $entry->summary) {
+                               $c=$entry->summary;
+                       }
+
                        add_page(
                                feed => $feed,
                                copyright => $f->copyright,
                                title => defined $entry->title ? decode_entities($entry->title) : "untitled",
                                link => $entry->link,
-                               content => defined $entry->content->body ? $entry->content->body : "",
+                               content => (defined $c && defined $c->body) ? $c->body : "",
                                guid => defined $entry->id ? $entry->id : time."_".$feed->{name},
                                ctime => $entry->issued ? ($entry->issued->epoch || time) : time,
+                               base => (defined $c && $c->can("base")) ? $c->base : undef,
                        );
                }
        }
-} #}}}
+}
 
-sub add_page (@) { #{{{
+sub add_page (@) {
        my %params=@_;
        
        my $feed=$params{feed};
@@ -471,7 +585,7 @@ sub add_page (@) { #{{{
                $feed->{newposts}++;
 
                # assign it an unused page
-               my $page=IkiWiki::titlepage($params{title});
+               my $page=titlepage($params{title});
                # escape slashes and periods in title so it doesn't specify
                # directory name or trigger ".." disallowing code.
                $page=~s!([/.])!"__".ord($1)."__"!eg;
@@ -482,7 +596,7 @@ sub add_page (@) { #{{{
                }
                my $c="";
                while (exists $IkiWiki::pagecase{lc $page.$c} ||
-                      -e pagefile($page.$c)) {
+                      -e "$config{srcdir}/".htmlfn($page.$c)) {
                        $c++
                }
 
@@ -493,7 +607,7 @@ sub add_page (@) { #{{{
                        $c="";
                        $page=$feed->{dir}."/item";
                        while (exists $IkiWiki::pagecase{lc $page.$c} ||
-                              -e pagefile($page.$c)) {
+                              -e "$config{srcdir}/".htmlfn($page.$c)) {
                                $c++
                        }
                }
@@ -517,7 +631,8 @@ sub add_page (@) { #{{{
        my $template=template($feed->{template}, blind_cache => 1);
        $template->param(title => $params{title})
                if defined $params{title} && length($params{title});
-       $template->param(content => htmlescape(htmlabs($params{content}, $feed->{feedurl})));
+       $template->param(content => wikiescape(htmlabs($params{content},
+               defined $params{base} ? $params{base} : $feed->{feedurl})));
        $template->param(name => $feed->{name});
        $template->param(url => $feed->{url});
        $template->param(copyright => $params{copyright})
@@ -530,27 +645,34 @@ sub add_page (@) { #{{{
        writefile(htmlfn($guid->{page}), $config{srcdir},
                $template->output);
 
-       # Set the mtime, this lets the build process get the right creation
-       # time on record for the new page.
-       utime $mtime, $mtime, pagefile($guid->{page})
-               if defined $mtime && $mtime <= time;
-} #}}}
+       if (defined $mtime && $mtime <= time) {
+               # Set the mtime, this lets the build process get the right
+               # creation time on record for the new page.
+               utime $mtime, $mtime, "$config{srcdir}/".htmlfn($guid->{page});
+               # Store it in pagectime for expiry code to use also.
+               $IkiWiki::pagectime{$guid->{page}}=$mtime
+                       unless exists $IkiWiki::pagectime{$guid->{page}};
+       }
+       else {
+               # Dummy value for expiry code.
+               $IkiWiki::pagectime{$guid->{page}}=time
+                       unless exists $IkiWiki::pagectime{$guid->{page}};
+       }
+}
 
-sub htmlescape ($) { #{{{
+sub wikiescape ($) {
        # escape accidental wikilinks and preprocessor stuff
-       my $html=shift;
-       $html=~s/(?<!\\)\[\[/\\\[\[/g;
-       return $html;
-} #}}}
+       return encode_entities(shift, '\[\]');
+}
 
-sub urlabs ($$) { #{{{
+sub urlabs ($$) {
        my $url=shift;
        my $urlbase=shift;
 
        URI->new_abs($url, $urlbase)->as_string;
-} #}}}
+}
 
-sub htmlabs ($$) { #{{{
+sub htmlabs ($$) {
        # Convert links in html from relative to absolute.
        # Note that this is a heuristic, which is not specified by the rss
        # spec and may not be right for all feeds. Also, see Debian
@@ -586,21 +708,15 @@ sub htmlabs ($$) { #{{{
        $p->eof;
 
        return $ret;
-} #}}}
-
-sub pagefile ($) { #{{{
-       my $page=shift;
-
-       return "$config{srcdir}/".htmlfn($page);
-} #}}}
+}
 
-sub htmlfn ($) { #{{{
-       return shift().".".$config{htmlext};
-} #}}}
+sub htmlfn ($) {
+       return shift().".".($config{aggregateinternal} ? "_aggregated" : $config{htmlext});
+}
 
 my $aggregatelock;
 
-sub lockaggregate () { #{{{
+sub lockaggregate () {
        # Take an exclusive lock to prevent multiple concurrent aggregators.
        # Returns true if the lock was aquired.
        if (! -d $config{wikistatedir}) {
@@ -613,11 +729,11 @@ sub lockaggregate () { #{{{
                return 0;
        }
        return 1;
-} #}}}
+}
 
-sub unlockaggregate () { #{{{
+sub unlockaggregate () {
        return close($aggregatelock) if $aggregatelock;
        return;
-} #}}}
+}
 
 1
index 187700f30d911dee95009a7d2515ef3aca61e176..3571c4189e43fe5b70e1032832a6978cded1af6b 100644 (file)
@@ -4,7 +4,7 @@ package IkiWiki::Plugin::amazon_s3;
 use warnings;
 no warnings 'redefine';
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use IkiWiki::Render;
 use Net::Amazon::S3;
 
@@ -16,12 +16,13 @@ BEGIN {
        }
 };
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "amazon_s3", call => \&getopt);
+       hook(type => "getsetup", id => "amazon_s3", call => \&getsetup);
        hook(type => "checkconfig", id => "amazon_s3", call => \&checkconfig);
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
         eval q{use Getopt::Long};
         error($@) if $@;
         Getopt::Long::Configure('pass_through');
@@ -37,9 +38,59 @@ sub getopt () { #{{{
                debug(gettext("done"));
                exit(0);
        });
-} #}}}
+}
 
-sub checkconfig { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0,
+                       rebuild => 0,
+               },
+               amazon_s3_key_id => {
+                       type => "string",
+                       example => "XXXXXXXXXXXXXXXXXXXX",
+                       description => "public access key id",
+                       safe => 1,
+                       rebuild => 0,
+               },
+               amazon_s3_key_id => {
+                       type => "string",
+                       example => "$ENV{HOME}/.s3_key",
+                       description => "file holding secret key (must not be readable by others!)",
+                       safe => 0, # ikiwiki reads this file
+                       rebuild => 0,
+               },
+               amazon_s3_bucket => {
+                       type => "string",
+                       example => "mywiki",
+                       description => "globally unique name of bucket to store wiki in",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               amazon_s3_prefix => {
+                       type => "string",
+                       example => "wiki/",
+                       description => "a prefix to prepend to each page name",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               amazon_s3_location => {
+                       type => "string",
+                       example => "EU",
+                       description => "which S3 datacenter to use (leave blank for default)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               amazon_s3_dupindex => {
+                       type => "boolean",
+                       example => 0,
+                       description => "store each index file twice? (allows urls ending in \"/index.html\" and \"/\")",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig {
        foreach my $field (qw{amazon_s3_key_id amazon_s3_key_file
                              amazon_s3_bucket}) {
                if (! exists $config{$field} || ! defined $config{$field}) {
@@ -50,11 +101,11 @@ sub checkconfig { #{{{
            ! defined $config{amazon_s3_prefix}) {
            $config{amazon_s3_prefix}="wiki/";
        }
-} #}}}
+}
 
 {
 my $bucket;
-sub getbucket { #{{{
+sub getbucket {
        return $bucket if defined $bucket;
        
        open(IN, "<", $config{amazon_s3_key_file}) || error($config{amazon_s3_key_file}.": ".$!);
@@ -82,16 +133,16 @@ sub getbucket { #{{{
        }
 
        if (! $bucket) {
-               error(gettext("Failed to create bucket in S3: ").
+               error(gettext("Failed to create S3 bucket: ").
                        $s3->err.": ".$s3->errstr."\n");
        }
 
        return $bucket;
-} #}}}
+}
 }
 
 # Given a file, return any S3 keys associated with it.
-sub file2keys ($) { #{{{
+sub file2keys ($) {
        my $file=shift;
 
        my @keys;
@@ -111,14 +162,14 @@ sub file2keys ($) { #{{{
                }
        }
        return @keys;
-} #}}}
+}
 
 package IkiWiki;
 use File::MimeInfo;
 use Encode;
 
 # This is a wrapper around the real writefile.
-sub writefile ($$$;$$) { #{{{
+sub writefile ($$$;$$) {
         my $file=shift;
         my $destdir=shift;
         my $content=shift;
@@ -174,10 +225,10 @@ sub writefile ($$$;$$) { #{{{
        }
 
        return $ret;
-} #}}}
+}
 
 # This is a wrapper around the real prune.
-sub prune ($) { #{{{
+sub prune ($) {
        my $file=shift;
 
        my @keys=IkiWiki::Plugin::amazon_s3::file2keys($file);
@@ -196,6 +247,6 @@ sub prune ($) { #{{{
        }
 
        return $IkiWiki::Plugin::amazon_s3::subs{'IkiWiki::prune'}->($file);
-} #}}}
+}
 
 1
index 1880516d568b35e2b96463676d23c04c62f103f2..243b9892056028ea3cd289257c70274a54a410f6 100644 (file)
@@ -3,13 +3,30 @@ package IkiWiki::Plugin::anonok;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-       hook(type => "canedit", id => "anonok", call => \&canedit,);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "anonok", call => \&getsetup);
+       hook(type => "canedit", id => "anonok", call => \&canedit);
+}
 
-sub canedit ($$$) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               anonok_pagespec => {
+                       type => "pagespec",
+                       example => "*/discussion",
+                       description => "PageSpec to limit which pages anonymous users can edit",
+                       link => "ikiwiki/PageSpec",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub canedit ($$$) {
        my $page=shift;
        my $cgi=shift;
        my $session=shift;
@@ -28,6 +45,6 @@ sub canedit ($$$) { #{{{
        else {
                return "";
        }
-} #}}}
+}
 
 1
index cb762e453e9f92c368fed3784c1ad5820455e6f6..087c315a9af355569921c9150c05c0ba89ec8df1 100644 (file)
@@ -3,80 +3,114 @@ package IkiWiki::Plugin::attachment;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       add_underlay("javascript");
+       hook(type => "getsetup", id => "attachment", call => \&getsetup);
        hook(type => "checkconfig", id => "attachment", call => \&checkconfig);
        hook(type => "formbuilder_setup", id => "attachment", call => \&formbuilder_setup);
        hook(type => "formbuilder", id => "attachment", call => \&formbuilder);
-} # }}}
+       IkiWiki::loadplugin("filecheck");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               allowed_attachments => {
+                       type => "pagespec",
+                       example => "virusfree() and mimetype(image/*) and maxsize(50kb)",
+                       description => "enhanced PageSpec specifying what attachments are allowed",
+                       link => "ikiwiki/PageSpec/attachment",
+                       safe => 1,
+                       rebuild => 0,
+               },
+               virus_checker => {
+                       type => "string",
+                       example => "clamdscan -",
+                       description => "virus checker program (reads STDIN, returns nonzero if virus found)",
+                       safe => 0, # executed
+                       rebuild => 0,
+               },
+}
 
-sub checkconfig () { #{{{
+sub check_canattach ($$;$) {
+       my $session=shift;
+       my $dest=shift; # where it's going to be put, under the srcdir
+       my $file=shift; # the path to the attachment currently
+
+       # Don't allow an attachment to be uploaded with the same name as an
+       # existing page.
+       if (exists $IkiWiki::pagesources{$dest} &&
+           $IkiWiki::pagesources{$dest} ne $dest) {
+               error(sprintf(gettext("there is already a page named %s"), $dest));
+       }
+
+       # Use a special pagespec to test that the attachment is valid.
+       my $allowed=1;
+       if (defined $config{allowed_attachments} &&
+           length $config{allowed_attachments}) {
+               $allowed=pagespec_match($dest,
+                       $config{allowed_attachments},
+                       file => $file,
+                       user => $session->param("name"),
+                       ip => $ENV{REMOTE_ADDR},
+               );
+       }
+
+       if (! $allowed) {
+               error(gettext("prohibited by allowed_attachments")." ($allowed)");
+       }
+       else {
+               return 1;
+       }
+}
+
+sub checkconfig () {
        $config{cgi_disable_uploads}=0;
-} #}}}
+}
 
-sub formbuilder_setup (@) { #{{{
+sub formbuilder_setup (@) {
        my %params=@_;
        my $form=$params{form};
        my $q=$params{cgi};
 
-       if (defined $form->field("do") && $form->field("do") eq "edit") {
+       if (defined $form->field("do") && ($form->field("do") eq "edit" ||
+           $form->field("do") eq "create")) {
+               # Add attachment field, set type to multipart.
+               $form->enctype(&CGI::MULTIPART);
                $form->field(name => 'attachment', type => 'file');
                # These buttons are not put in the usual place, so
                # are not added to the normal formbuilder button list.
                $form->tmpl_param("field-upload" => '<input name="_submit" type="submit" value="Upload Attachment" />');
                $form->tmpl_param("field-link" => '<input name="_submit" type="submit" value="Insert Links" />');
 
-               # Add the javascript from the toggle plugin;
-               # the attachments interface uses it to toggle visibility.
+               # Add the toggle javascript; the attachments interface uses
+               # it to toggle visibility.
                require IkiWiki::Plugin::toggle;
-               $form->tmpl_param("javascript" => $IkiWiki::Plugin::toggle::javascript);
+               $form->tmpl_param("javascript" => IkiWiki::Plugin::toggle::include_javascript($params{page}, 1));
                # Start with the attachments interface toggled invisible,
                # but if it was used, keep it open.
                if ($form->submitted ne "Upload Attachment" &&
-                   ! length $q->param("attachment_select")) {
+                   (! defined $q->param("attachment_select") ||
+                   ! length $q->param("attachment_select"))) {
                        $form->tmpl_param("attachments-class" => "toggleable");
                }
                else {
                        $form->tmpl_param("attachments-class" => "toggleable-open");
                }
        }
-       elsif ($form->title eq "preferences") {
-               my $session=$params{session};
-               my $user_name=$session->param("name");
-
-               $form->field(name => "allowed_attachments", size => 50,
-                       fieldset => "admin",
-                       comment => "(".
-                               htmllink("", "", 
-                                       "ikiwiki/PageSpec/attachment", 
-                                       noimageinline => 1,
-                                       linktext => "Enhanced PageSpec",
-                               ).")"
-               );
-               if (! IkiWiki::is_admin($user_name)) {
-                       $form->field(name => "allowed_attachments", type => "hidden");
-               }
-                if (! $form->submitted) {
-                       $form->field(name => "allowed_attachments", force => 1,
-                               value => IkiWiki::userinfo_get($user_name, "allowed_attachments"));
-                }
-               if ($form->submitted && $form->submitted eq 'Save Preferences') {
-                       if (defined $form->field("allowed_attachments")) {
-                               IkiWiki::userinfo_set($user_name, "allowed_attachments",
-                               $form->field("allowed_attachments")) ||
-                                       error("failed to set allowed_attachments");
-                       }
-               }
-       }
-} #}}}
+}
 
-sub formbuilder (@) { #{{{
+sub formbuilder (@) {
        my %params=@_;
        my $form=$params{form};
        my $q=$params{cgi};
 
-       return if ! defined $form->field("do") || $form->field("do") ne "edit";
+       return if ! defined $form->field("do") || ($form->field("do") ne "edit" && $form->field("do") ne "create") ;
 
        my $filename=$q->param('attachment');
        if (defined $filename && length $filename &&
@@ -86,9 +120,20 @@ sub formbuilder (@) { #{{{
                # This is an (apparently undocumented) way to get the name
                # of the temp file that CGI writes the upload to.
                my $tempfile=$q->tmpFileName($filename);
-               
-               $filename=IkiWiki::titlepage(
-                       IkiWiki::possibly_foolish_untaint(
+               if (! defined $tempfile || ! length $tempfile) {
+                       # perl 5.8 needs an alternative, awful method
+                       if ($q =~ /HASH/ && exists $q->{'.tmpfiles'}) {
+                               foreach my $key (keys(%{$q->{'.tmpfiles'}})) {
+                                       $tempfile=$q->tmpFileName(\$key);
+                                       last if defined $tempfile && length $tempfile;
+                               }
+                       }
+                       if (! defined $tempfile || ! length $tempfile) {
+                               error("CGI::tmpFileName failed to return the uploaded file name");
+                       }
+               }
+
+               $filename=linkpage(IkiWiki::possibly_foolish_untaint(
                                attachment_location($form->field('page')).
                                IkiWiki::basename($filename)));
                if (IkiWiki::file_pruned($filename, $config{srcdir})) {
@@ -98,25 +143,8 @@ sub formbuilder (@) { #{{{
                # Check that the user is allowed to edit a page with the
                # name of the attachment.
                IkiWiki::check_canedit($filename, $q, $session, 1);
-               
-               # Use a special pagespec to test that the attachment is valid.
-               my $allowed=1;
-               foreach my $admin (@{$config{adminuser}}) {
-                       my $allowed_attachments=IkiWiki::userinfo_get($admin, "allowed_attachments");
-                       if (defined $allowed_attachments &&
-                           length $allowed_attachments) {
-                               $allowed=pagespec_match($filename,
-                                       $allowed_attachments,
-                                       file => $tempfile,
-                                       user => $session->param("name"),
-                                       ip => $ENV{REMOTE_ADDR},
-                               );
-                               last if $allowed;
-                       }
-               }
-               if (! $allowed) {
-                       error(gettext("attachment rejected")." ($allowed)");
-               }
+               # And that the attachment itself is acceptable.
+               check_canattach($session, $filename, $tempfile);
 
                # Needed for fast_file_copy and for rendering below.
                require IkiWiki::Render;
@@ -132,7 +160,14 @@ sub formbuilder (@) { #{{{
                else {
                        my $fh=$q->upload('attachment');
                        if (! defined $fh || ! ref $fh) {
-                               error("failed to get filehandle");
+                               # needed by old CGI versions
+                               $fh=$q->param('attachment');
+                               if (! defined $fh || ! ref $fh) {
+                                       # even that doesn't always work,
+                                       # fall back to opening the tempfile
+                                       $fh=undef;
+                                       open($fh, "<", $tempfile) || error("failed to open \"$tempfile\": $!");
+                               }
                        }
                        binmode($fh);
                        writefile($filename, $config{srcdir}, undef, 1, sub {
@@ -154,8 +189,10 @@ sub formbuilder (@) { #{{{
                IkiWiki::saveindex();
        }
        elsif ($form->submitted eq "Insert Links") {
+               my $page=quotemeta($q->param("page"));
                my $add="";
                foreach my $f ($q->param("attachment_select")) {
+                       $f=~s/^$page\///;
                        $add.="[[$f]]\n";
                }
                $form->field(name => 'editcontent',
@@ -166,7 +203,7 @@ sub formbuilder (@) { #{{{
        # Generate the attachment list only after having added any new
        # attachments.
        $form->tmpl_param("attachment_list" => [attachment_list($form->field('page'))]);
-} # }}}
+}
 
 sub attachment_location ($) {
        my $page=shift;
@@ -185,15 +222,14 @@ sub attachment_list ($) {
 
        my @ret;
        foreach my $f (values %pagesources) {
-               if (! defined IkiWiki::pagetype($f) &&
+               if (! defined pagetype($f) &&
                    $f=~m/^\Q$loc\E[^\/]+$/ &&
                    -e "$config{srcdir}/$f") {
                        push @ret, {
                                "field-select" => '<input type="checkbox" name="attachment_select" value="'.$f.'" />',
                                link => htmllink($page, $page, $f, noimageinline => 1),
-                               size => humansize((stat(_))[7]),
+                               size => IkiWiki::Plugin::filecheck::humansize((stat(_))[7]),
                                mtime => displaytime($IkiWiki::pagemtime{$f}),
-                               mtime_raw => $IkiWiki::pagemtime{$f},
                        };
                }
        }
@@ -203,217 +239,4 @@ sub attachment_list ($) {
        return sort { $b->{mtime_raw} <=> $a->{mtime_raw} || $a->{link} cmp $b->{link} } @ret;
 }
 
-my %units=(            # size in bytes
-       B               => 1,
-       byte            => 1,
-       KB              => 2 ** 10,
-       kilobyte        => 2 ** 10,
-       K               => 2 ** 10,
-       KB              => 2 ** 10,
-       kilobyte        => 2 ** 10,
-       M               => 2 ** 20,
-       MB              => 2 ** 20,
-       megabyte        => 2 ** 20,
-       G               => 2 ** 30,
-       GB              => 2 ** 30,
-       gigabyte        => 2 ** 30,
-       T               => 2 ** 40,
-       TB              => 2 ** 40,
-       terabyte        => 2 ** 40,
-       P               => 2 ** 50,
-       PB              => 2 ** 50,
-       petabyte        => 2 ** 50,
-       E               => 2 ** 60,
-       EB              => 2 ** 60,
-       exabyte         => 2 ** 60,
-       Z               => 2 ** 70,
-       ZB              => 2 ** 70,
-       zettabyte       => 2 ** 70,
-       Y               => 2 ** 80,
-       YB              => 2 ** 80,
-       yottabyte       => 2 ** 80,
-       # ikiwiki, if you find you need larger data quantities, either modify
-       # yourself to add them, or travel back in time to 2008 and kill me.
-       #   -- Joey
-);
-
-sub parsesize ($) { #{{{
-       my $size=shift;
-
-       no warnings;
-       my $base=$size+0; # force to number
-       use warnings;
-       foreach my $unit (sort keys %units) {
-               if ($size=~/[0-9\s]\Q$unit\E$/i) {
-                       return $base * $units{$unit};
-               }
-       }
-       return $base;
-} #}}}
-
-sub humansize ($) { #{{{
-       my $size=shift;
-
-       foreach my $unit (reverse sort { $units{$a} <=> $units{$b} || $b cmp $a } keys %units) {
-               if ($size / $units{$unit} > 0.25) {
-                       return (int($size / $units{$unit} * 10)/10).$unit;
-               }
-       }
-       return $size; # near zero, or negative
-} #}}}
-
-package IkiWiki::PageSpec;
-
-sub match_maxsize ($$;@) { #{{{
-       shift;
-       my $maxsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)};
-       if ($@) {
-               return IkiWiki::FailReason->new("unable to parse maxsize (or number too large)");
-       }
-
-       my %params=@_;
-       if (! exists $params{file}) {
-               return IkiWiki::FailReason->new("no file specified");
-       }
-
-       if (-s $params{file} > $maxsize) {
-               return IkiWiki::FailReason->new("file too large (".(-s $params{file})." >  $maxsize)");
-       }
-       else {
-               return IkiWiki::SuccessReason->new("file not too large");
-       }
-} #}}}
-
-sub match_minsize ($$;@) { #{{{
-       shift;
-       my $minsize=eval{IkiWiki::Plugin::attachment::parsesize(shift)};
-       if ($@) {
-               return IkiWiki::FailReason->new("unable to parse minsize (or number too large)");
-       }
-
-       my %params=@_;
-       if (! exists $params{file}) {
-               return IkiWiki::FailReason->new("no file specified");
-       }
-
-       if (-s $params{file} < $minsize) {
-               return IkiWiki::FailReason->new("file too small");
-       }
-       else {
-               return IkiWiki::SuccessReason->new("file not too small");
-       }
-} #}}}
-
-sub match_mimetype ($$;@) { #{{{
-       shift;
-       my $wanted=shift;
-
-       my %params=@_;
-       if (! exists $params{file}) {
-               return IkiWiki::FailReason->new("no file specified");
-       }
-
-       # Use ::magic to get the mime type, the idea is to only trust
-       # data obtained by examining the actual file contents.
-       eval q{use File::MimeInfo::Magic};
-       if ($@) {
-               return IkiWiki::FailReason->new("failed to load File::MimeInfo::Magic ($@); cannot check MIME type");
-       }
-       my $mimetype=File::MimeInfo::Magic::magic($params{file});
-       if (! defined $mimetype) {
-               $mimetype="unknown";
-       }
-
-       my $regexp=IkiWiki::glob2re($wanted);
-       if ($mimetype!~/^$regexp$/i) {
-               return IkiWiki::FailReason->new("file MIME type is $mimetype, not $wanted");
-       }
-       else {
-               return IkiWiki::SuccessReason->new("file MIME type is $mimetype");
-       }
-} #}}}
-
-sub match_virusfree ($$;@) { #{{{
-       shift;
-       my $wanted=shift;
-
-       my %params=@_;
-       if (! exists $params{file}) {
-               return IkiWiki::FailReason->new("no file specified");
-       }
-
-       if (! exists $IkiWiki::config{virus_checker} ||
-           ! length $IkiWiki::config{virus_checker}) {
-               return IkiWiki::FailReason->new("no virus_checker configured");
-       }
-
-       # The file needs to be fed into the virus checker on stdin,
-       # because the file is not world-readable, and if clamdscan is
-       # used, clamd would fail to read it.
-       eval q{use IPC::Open2};
-       error($@) if $@;
-       open (IN, "<", $params{file}) || return IkiWiki::FailReason->new("failed to read file");
-       binmode(IN);
-       my $sigpipe=0;
-       $SIG{PIPE} = sub { $sigpipe=1 };
-       my $pid=open2(\*CHECKER_OUT, "<&IN", $IkiWiki::config{virus_checker}); 
-       my $reason=<CHECKER_OUT>;
-       chomp $reason;
-       1 while (<CHECKER_OUT>);
-       close(CHECKER_OUT);
-       waitpid $pid, 0;
-       $SIG{PIPE}="DEFAULT";
-       if ($sigpipe || $?) {
-               return IkiWiki::FailReason->new("file seems to contain a virus ($reason)");
-       }
-       else {
-               return IkiWiki::SuccessReason->new("file seems virusfree ($reason)");
-       }
-} #}}}
-
-sub match_ispage ($$;@) { #{{{
-       my $filename=shift;
-
-       if (defined IkiWiki::pagetype($filename)) {
-               return IkiWiki::SuccessReason->new("file is a wiki page");
-       }
-       else {
-               return IkiWiki::FailReason->new("file is not a wiki page");
-       }
-} #}}}
-
-sub match_user ($$;@) { #{{{
-       shift;
-       my $user=shift;
-       my %params=@_;
-       
-       if (! exists $params{user}) {
-               return IkiWiki::FailReason->new("no user specified");
-       }
-
-       if (defined $params{user} && lc $params{user} eq lc $user) {
-               return IkiWiki::SuccessReason->new("user is $user");
-       }
-       else {
-               return IkiWiki::FailReason->new("user is $params{user}, not $user");
-       }
-} #}}}
-
-sub match_ip ($$;@) { #{{{
-       shift;
-       my $ip=shift;
-       my %params=@_;
-       
-       if (! exists $params{ip}) {
-               return IkiWiki::FailReason->new("no IP specified");
-       }
-
-       if (defined $params{ip} && lc $params{ip} eq lc $ip) {
-               return IkiWiki::SuccessReason->new("IP is $ip");
-       }
-       else {
-               return IkiWiki::FailReason->new("IP is $params{ip}, not $ip");
-       }
-} #}}}
-
 1
diff --git a/IkiWiki/Plugin/autoindex.pm b/IkiWiki/Plugin/autoindex.pm
new file mode 100644 (file)
index 0000000..555856b
--- /dev/null
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::autoindex;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use Encode;
+
+sub import {
+       hook(type => "getsetup", id => "autoindex", call => \&getsetup);
+       hook(type => "refresh", id => "autoindex", call => \&refresh);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub genindex ($) {
+       my $page=shift;
+       my $file=newpagefile($page, $config{default_pageext});
+       my $template=template("autoindex.tmpl");
+       $template->param(page => $page);
+       writefile($file, $config{srcdir}, $template->output);
+       if ($config{rcs}) {
+               IkiWiki::rcs_add($file);
+       }
+}
+
+sub refresh () {
+       eval q{use File::Find};
+       error($@) if $@;
+
+       my (%pages, %dirs);
+       foreach my $dir ($config{srcdir}, @{$config{underlaydirs}}, $config{underlaydir}) {
+               find({
+                       no_chdir => 1,
+                       wanted => sub {
+                               $_=decode_utf8($_);
+                               if (IkiWiki::file_pruned($_, $dir)) {
+                                       $File::Find::prune=1;
+                               }
+                               elsif (! -l $_) {
+                                       my ($f)=/$config{wiki_file_regexp}/; # untaint
+                                       return unless defined $f;
+                                       $f=~s/^\Q$dir\E\/?//;
+                                       return unless length $f;
+                                       return if $f =~ /\._([^.]+)$/; # skip internal page
+                                       if (! -d _) {
+                                               $pages{pagename($f)}=1;
+                                       }
+                                       elsif ($dir eq $config{srcdir}) {
+                                               $dirs{$f}=1;
+                                       }
+                               }
+                       }
+               }, $dir);
+       }
+       
+       my %deleted;
+        if (ref $pagestate{index}{autoindex}{deleted}) {
+              %deleted=%{$pagestate{index}{autoindex}{deleted}};
+               foreach my $dir (keys %deleted) {
+                       # remove deleted page state if the deleted page is re-added,
+                       # or if all its subpages are deleted
+                       if ($deleted{$dir} && (exists $pages{$dir} ||
+                                              ! grep /^$dir\/.*/, keys %pages)) {
+                               delete $deleted{$dir};
+                       }
+               }
+               $pagestate{index}{autoindex}{deleted}=\%deleted;
+       }
+
+       my @needed;
+       foreach my $dir (keys %dirs) {
+               if (! exists $pages{$dir} && ! $deleted{$dir} &&
+                   grep /^$dir\/.*/, keys %pages) {
+                       if (exists $IkiWiki::pagemtime{$dir}) {
+                               # This page must have just been deleted, so
+                               # don't re-add it. And remember it was
+                               # deleted.
+                               if (! ref $pagestate{index}{autoindex}{deleted}) {
+                                       $pagestate{index}{autoindex}{deleted}={};
+                               }
+                               ${$pagestate{index}{autoindex}{deleted}}{$dir}=1;
+                       }
+                       else {
+                               push @needed, $dir;
+                       }
+               }
+       }
+       
+       if (@needed) {
+               if ($config{rcs}) {
+                       IkiWiki::disable_commit_hook();
+               }
+               foreach my $page (@needed) {
+                       genindex($page);
+               }
+               if ($config{rcs}) {
+                       IkiWiki::rcs_commit_staged(
+                               gettext("automatic index generation"),
+                               undef, undef);
+                       IkiWiki::enable_commit_hook();
+               }
+       }
+}
+
+1
diff --git a/IkiWiki/Plugin/blogspam.pm b/IkiWiki/Plugin/blogspam.pm
new file mode 100644 (file)
index 0000000..626c8ec
--- /dev/null
@@ -0,0 +1,119 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::blogspam;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+my $defaulturl='http://test.blogspam.net:8888/';
+
+sub import {
+       hook(type => "getsetup", id => "blogspam",  call => \&getsetup);
+       hook(type => "checkconfig", id => "blogspam", call => \&checkconfig);
+       hook(type => "checkcontent", id => "blogspam", call => \&checkcontent);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               blogspam_pagespec => {
+                       type => 'pagespec',
+                       example => 'postcomment(*)',
+                       description => 'PageSpec of pages to check for spam',
+                       link => 'ikiwiki/PageSpec',
+                       safe => 1,
+                       rebuild => 0,
+               },
+               blogspam_options => {
+                       type => "string",
+                       example => "blacklist=1.2.3.4,blacklist=8.7.6.5,max-links=10",
+                       description => "options to send to blogspam server",
+                       link => "http://blogspam.net/api/testComment.html#options",
+                       safe => 1,
+                       rebuild => 0,
+               },
+               blogspam_server => {
+                       type => "string",
+                       default => $defaulturl,
+                       description => "blogspam server XML-RPC url",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
+       # This is done at checkconfig time because printing an error
+       # if the module is missing when a spam is posted would not
+       # let the admin know about the problem.
+       eval q{
+               use RPC::XML;
+               use RPC::XML::Client;
+       };
+       error $@ if $@;
+}
+
+sub checkcontent (@) {
+       my %params=@_;
+       
+       if (exists $config{blogspam_pagespec}) {
+               return undef
+                       if ! pagespec_match($params{page}, $config{blogspam_pagespec},
+                               location => $params{page});
+       }
+
+       my $url=$defaulturl;
+       $url = $config{blogspam_server} if exists $config{blogspam_server};
+       my $client = RPC::XML::Client->new($url);
+
+       my @options = split(",", $config{blogspam_options})
+               if exists $config{blogspam_options};
+
+       # Allow short comments and whitespace-only edits, unless the user
+       # has overridden min-words themselves.
+       push @options, "min-words=0"
+               unless grep /^min-words=/i, @options;
+       # Wiki pages can have a lot of urls, unless the user specifically
+       # wants to limit them.
+       push @options, "exclude=lotsaurls"
+               unless grep /^max-links/i, @options;
+       # Unless the user specified a size check, disable such checking.
+       push @options, "exclude=size"
+               unless grep /^(?:max|min)-size/i, @options;
+       # This test has absurd false positives on words like "alpha"
+       # and "buy".
+       push @options, "exclude=stopwords";
+
+       my %req=(
+               ip => $ENV{REMOTE_ADDR},
+               comment => defined $params{diff} ? $params{diff} : $params{content},
+               subject => defined $params{subject} ? $params{subject} : "",
+               name => defined $params{author} ? $params{author} : "",
+               link => exists $params{url} ? $params{url} : "",
+               options => join(",", @options),
+               site => $config{url},
+               version => "ikiwiki ".$IkiWiki::version,
+       );
+       my $res = $client->send_request('testComment', \%req);
+
+       if (! ref $res || ! defined $res->value) {
+               debug("failed to get response from blogspam server ($url)");
+               return undef;
+       }
+       elsif ($res->value =~ /^SPAM:(.*)/) {
+               eval q{use Data::Dumper};
+               debug("blogspam server reports ".$res->value.": ".Dumper(\%req));
+               return gettext("Sorry, but that looks like spam to <a href=\"http://blogspam.net/\">blogspam</a>: ").$1;
+       }
+       elsif ($res->value ne 'OK') {
+               debug("blogspam server failure: ".$res->value);
+               return undef;
+       }
+       else {
+               return undef;
+       }
+}
+
+1
index 0295a8fe6b570d7b49503ba6587ae41a28f0cfa7..eb698b0bef9f7b2c9df90b342dcfac56c79a1795 100644 (file)
@@ -4,13 +4,22 @@ package IkiWiki::Plugin::brokenlinks;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "brokenlinks", call => \&getsetup);
        hook(type => "preprocess", id => "brokenlinks", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        $params{pages}="*" unless defined $params{pages};
        
@@ -18,33 +27,27 @@ sub preprocess (@) { #{{{
        # register a dependency.
        add_depends($params{page}, $params{pages});
        
-       my %broken;
-       foreach my $page (keys %links) {
-               if (pagespec_match($page, $params{pages}, location => $params{page})) {
-                       my $discussion=gettext("discussion");
-                       my %seen;
-                       foreach my $link (@{$links{$page}}) {
-                               next if $seen{$link};
-                               $seen{$link}=1;
-                               next if $link =~ /.*\/\Q$discussion\E/i && $config{discussion};
-                               my $bestlink=bestlink($page, $link);
-                               next if length $bestlink;
-                               push @{$broken{$link}}, $page;
-                       }
+       my @broken;
+       foreach my $link (keys %IkiWiki::brokenlinks) {
+               next if $link =~ /.*\/\Q$config{discussionpage}\E/i && $config{discussion};
+
+               my @pages;
+               foreach my $page (@{$IkiWiki::brokenlinks{$link}}) {
+                       push @pages, $page
+                               if pagespec_match($page, $params{pages}, location => $params{page});
                }
-       }
+               next unless @pages;
 
-       my @broken;
-       foreach my $link (keys %broken) {
-               my $page=$broken{$link}->[0];
+               my $page=$IkiWiki::brokenlinks{$link}->[0];
                push @broken, sprintf(gettext("%s from %s"),
                        htmllink($page, $params{destpage}, $link, noimageinline => 1),
                        join(", ", map {
                                htmllink($params{page}, $params{destpage}, $_,  noimageinline => 1)
-                       } @{$broken{$link}}));
+                       } @pages)
+               );
        }
        
-       return gettext("There are no broken links!") unless %broken;
+       return gettext("There are no broken links!") unless @broken;
        return "<ul>\n"
                .join("\n",
                        map {
@@ -52,6 +55,6 @@ sub preprocess (@) { #{{{
                        }
                        sort @broken)
                ."</ul>\n";
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/bzr.pm b/IkiWiki/Plugin/bzr.pm
new file mode 100644 (file)
index 0000000..8830073
--- /dev/null
@@ -0,0 +1,299 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::bzr;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+use open qw{:utf8 :std};
+
+sub import {
+       hook(type => "checkconfig", id => "bzr", call => \&checkconfig);
+       hook(type => "getsetup", id => "bzr", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub checkconfig () {
+       if (defined $config{bzr_wrapper} && length $config{bzr_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{bzr_wrapper},
+                       wrappermode => (defined $config{bzr_wrappermode} ? $config{bzr_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               bzr_wrapper => {
+                       type => "string",
+                       #example => "", # FIXME add example
+                       description => "bzr post-commit hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               bzr_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for bzr_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       #example => "", # FIXME add example
+                       description => "url to show file history, using loggerhead ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://example.com/revision?start_revid=[[r2]]#[[file]]-s",
+                       description => "url to view a diff, using loggerhead ([[file]] and [[r2]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub bzr_log ($) {
+       my $out = shift;
+       my @infos = ();
+       my $key = undef;
+
+       while (<$out>) {
+               my $line = $_;
+               my ($value);
+               if ($line =~ /^message:/) {
+                       $key = "message";
+                       $infos[$#infos]{$key} = "";
+               }
+               elsif ($line =~ /^(modified|added|renamed|renamed and modified|removed):/) {
+                       $key = "files";
+                       unless (defined($infos[$#infos]{$key})) { $infos[$#infos]{$key} = ""; }
+               }
+               elsif (defined($key) and $line =~ /^  (.*)/) {
+                       $infos[$#infos]{$key} .= "$1\n";
+               }
+               elsif ($line eq "------------------------------------------------------------\n") {
+                       $key = undef;
+                       push (@infos, {});
+               }
+               else {
+                       chomp $line;
+                               ($key, $value) = split /: +/, $line, 2;
+                       $infos[$#infos]{$key} = $value;
+               } 
+       }
+       close $out;
+
+       return @infos;
+}
+
+sub rcs_update () {
+       my @cmdline = ("bzr", "update", "--quiet", $config{srcdir});
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_prepedit ($) {
+       return "";
+}
+
+sub bzr_author ($$) {
+       my ($user, $ipaddr) = @_;
+
+       if (defined $user) {
+               return IkiWiki::possibly_foolish_untaint($user);
+       }
+       elsif (defined $ipaddr) {
+               return "Anonymous from ".IkiWiki::possibly_foolish_untaint($ipaddr);
+       }
+       else {
+               return "Anonymous";
+       }
+}
+
+sub rcs_commit ($$$;$$) {
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+
+       $user = bzr_author($user, $ipaddr);
+
+       $message = IkiWiki::possibly_foolish_untaint($message);
+       if (! length $message) {
+               $message = "no message given";
+       }
+
+       my @cmdline = ("bzr", "commit", "--quiet", "-m", $message, "--author", $user,
+                      $config{srcdir}."/".$file);
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+
+       return undef; # success
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+
+       $user = bzr_author($user, $ipaddr);
+
+       $message = IkiWiki::possibly_foolish_untaint($message);
+       if (! length $message) {
+               $message = "no message given";
+       }
+
+       my @cmdline = ("bzr", "commit", "--quiet", "-m", $message, "--author", $user,
+                      $config{srcdir});
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+
+       return undef; # success
+}
+
+sub rcs_add ($) {
+       my ($file) = @_;
+
+       my @cmdline = ("bzr", "add", "--quiet", "$config{srcdir}/$file");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_remove ($) {
+       my ($file) = @_;
+
+       my @cmdline = ("bzr", "rm", "--force", "--quiet", "$config{srcdir}/$file");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_rename ($$) {
+       my ($src, $dest) = @_;
+
+       my $parent = IkiWiki::dirname($dest);
+       if (system("bzr", "add", "--quiet", "$config{srcdir}/$parent") != 0) {
+               warn("bzr add $parent failed\n");
+       }
+
+       my @cmdline = ("bzr", "mv", "--quiet", "$config{srcdir}/$src", "$config{srcdir}/$dest");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_recentchanges ($) {
+       my ($num) = @_;
+
+       my @cmdline = ("bzr", "log", "-v", "--show-ids", "--limit", $num, 
+                          $config{srcdir});
+       open (my $out, "@cmdline |");
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+
+       my @ret;
+       foreach my $info (bzr_log($out)) {
+               my @pages = ();
+               my @message = ();
+        
+               foreach my $msgline (split(/\n/, $info->{message})) {
+                       push @message, { line => $msgline };
+               }
+
+               foreach my $file (split(/\n/, $info->{files})) {
+                       my ($filename, $fileid) = ($file =~ /^(.*?) +([^ ]+)$/);
+
+                       # Skip directories
+                       next if ($filename =~ /\/$/);
+
+                       # Skip source name in renames
+                       $filename =~ s/^.* => //;
+
+                       my $diffurl = defined $config{'diffurl'} ? $config{'diffurl'} : "";
+                       $diffurl =~ s/\[\[file\]\]/$filename/go;
+                       $diffurl =~ s/\[\[file-id\]\]/$fileid/go;
+                       $diffurl =~ s/\[\[r2\]\]/$info->{revno}/go;
+
+                       push @pages, {
+                               page => pagename($filename),
+                               diffurl => $diffurl,
+                       };
+               }
+
+               my $user = $info->{"committer"};
+               if (defined($info->{"author"})) { $user = $info->{"author"}; }
+               $user =~ s/\s*<.*>\s*$//;
+               $user =~ s/^\s*//;
+
+               push @ret, {
+                       rev        => $info->{"revno"},
+                       user       => $user,
+                       committype => "bzr",
+                       when       => str2time($info->{"timestamp"}),
+                       message    => [@message],
+                       pages      => [@pages],
+               };
+       }
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       my $taintedrev=shift;
+       my ($rev) = $taintedrev =~ /^(\d+(\.\d+)*)$/; # untaint
+
+       my $prevspec = "before:" . $rev;
+       my $revspec = "revno:" . $rev;
+       my @cmdline = ("bzr", "diff", "--old", $config{srcdir},
+               "--new", $config{srcdir},
+               "-r", $prevspec . ".." . $revspec);
+       open (my $out, "@cmdline |");
+
+       my @lines = <$out>;
+       if (wantarray) {
+               return @lines;
+       }
+       else {
+               return join("", @lines);
+       }
+}
+
+sub rcs_getctime ($) {
+       my ($file) = @_;
+
+       # XXX filename passes through the shell here, should try to avoid
+       # that just in case
+       my @cmdline = ("bzr", "log", "--limit", '1', "$config{srcdir}/$file");
+       open (my $out, "@cmdline |");
+
+       my @log = bzr_log($out);
+
+       if (length @log < 1) {
+               return 0;
+       }
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+       
+       my $ctime = str2time($log[0]->{"timestamp"});
+       return $ctime;
+}
+
+1
index aed087eed58248d5da153543dba03abba17b5ef0..5d16dff75ba7a98a68c3fc8c94d9d9378cb11732 100644 (file)
@@ -20,7 +20,7 @@ package IkiWiki::Plugin::calendar;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use Time::Local;
 use POSIX;
 
@@ -29,26 +29,42 @@ my %linkcache;
 my $time=time;
 my @now=localtime($time);
 
-sub import { #{{{
-       hook(type => "needsbuild", id => "version", call => \&needsbuild);
+sub import {
+       hook(type => "getsetup", id => "calendar", call => \&getsetup);
+       hook(type => "needsbuild", id => "calendar", call => \&needsbuild);
        hook(type => "preprocess", id => "calendar", call => \&preprocess);
-} #}}}
-
-sub is_leap_year (@) { #{{{
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               archivebase => {
+                       type => "string",
+                       example => "archives",
+                       description => "base of the archives hierarchy",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub is_leap_year (@) {
        my %params=@_;
        return ($params{year} % 4 == 0 && (($params{year} % 100 != 0) || $params{year} % 400 == 0));
-} #}}}
+}
 
-sub month_days { #{{{
+sub month_days {
        my %params=@_;
        my $days_in_month = (31,28,31,30,31,30,31,31,30,31,30,31)[$params{month}-1];
        if ($params{month} == 2 && is_leap_year(%params)) {
                $days_in_month++;
        }
        return $days_in_month;
-} #}}}
+}
 
-sub format_month (@) { #{{{
+sub format_month (@) {
        my %params=@_;
 
        my $pagespec = $params{pages};
@@ -195,13 +211,15 @@ EOF
        # matching the pagespec are added or removed.
        add_depends($params{page}, $params{pages});
        # Explicitly add all currently linked pages as dependencies, so
-        # that if they are removed, the calendar will be sure to be updated.
-        add_depends($params{page}, join(" or ", @list));
+       # that if they are removed, the calendar will be sure to be updated.
+       foreach my $p (@list) {
+               add_depends($params{page}, $p);
+       }
 
        return $calendar;
-} #}}}
+}
 
-sub format_year (@) { #{{{
+sub format_year (@) {
        my %params=@_;
 
        my $pagespec = $params{pages};
@@ -302,9 +320,9 @@ EOF
 EOF
 
        return $calendar;
-} #}}}
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
        $params{pages} = "*"            unless defined $params{pages};
        $params{type}  = "month"        unless defined $params{type};
@@ -353,8 +371,7 @@ sub preprocess (@) { #{{{
        my $page =$params{page};
 
        if (! defined $cache{$pagespec}) {
-               foreach my $p (keys %pagesources) {
-                       next unless pagespec_match($p, $pagespec);
+               foreach my $p (pagespec_match_list([keys %pagesources], $pagespec)) {
                        my $mtime = $IkiWiki::pagectime{$p};
                        my $src   = $pagesources{$p};
                        my @date  = localtime($mtime);
@@ -381,7 +398,7 @@ sub preprocess (@) { #{{{
        return "\n<div><div class=\"calendar\">$calendar</div></div>\n";
 } #}}
 
-sub needsbuild (@) { #{{{
+sub needsbuild (@) {
        my $needsbuild=shift;
        foreach my $page (keys %pagestate) {
                if (exists $pagestate{$page}{calendar}{nextchange}) {
@@ -399,6 +416,6 @@ sub needsbuild (@) { #{{{
                        }
                }
        }
-} # }}}
+}
 
 1
index 0739bb01ae3c2d0498c58fa428451afb208fcfdf..088447d6b4d133d0197e6bc3c1df57fd9c3292e8 100644 (file)
@@ -4,7 +4,7 @@ package IkiWiki::Plugin::camelcase;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 # This regexp is based on the one in Text::WikiFormat.
 my $link_regexp=qr{
@@ -22,31 +22,52 @@ my $link_regexp=qr{
        )
 }x;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "camelcase", call => \&getsetup);
        hook(type => "linkify", id => "camelcase", call => \&linkify);
        hook(type => "scan", id => "camelcase", call => \&scan);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               camelcase_ignore => {
+                       type => "string",
+                       example => [],
+                       description => "list of words to not turn into links",
+                       safe => 1,
+                       rebuild => undef, # might change links
+               },
+}
 
-sub linkify (@) { #{{{
+sub linkify (@) {
        my %params=@_;
        my $page=$params{page};
        my $destpage=$params{destpage};
 
        $params{content}=~s{$link_regexp}{
-               htmllink($page, $destpage, IkiWiki::linkpage($1))
+               ignored($1) ? $1 : htmllink($page, $destpage, linkpage($1))
        }eg;
 
        return $params{content};
-} #}}}
+}
 
-sub scan (@) { #{{{
+sub scan (@) {
         my %params=@_;
         my $page=$params{page};
         my $content=$params{content};
 
        while ($content =~ /$link_regexp/g) {
-               push @{$links{$page}}, IkiWiki::linkpage($1);
+               add_link($page, linkpage($1)) unless ignored($1)
        }
 }
 
+sub ignored ($) {
+       my $word=lc shift;
+       grep { $word eq lc $_ } @{$config{'camelcase_ignore'}}
+}
+
 1
diff --git a/IkiWiki/Plugin/color.pm b/IkiWiki/Plugin/color.pm
new file mode 100644 (file)
index 0000000..2050589
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+# Ikiwiki text colouring plugin
+# Paweł‚ Tęcza <ptecza@net.icm.edu.pl>
+package IkiWiki::Plugin::color;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "preprocess", id => "color", call => \&preprocess);
+       hook(type => "format",     id => "color", call => \&format);
+}
+
+sub preserve_style ($$$) {
+       my $foreground = shift;
+       my $background = shift;
+       my $text       = shift;
+
+       $foreground = defined $foreground ? lc($foreground) : '';
+       $background = defined $background ? lc($background) : '';
+       $text       = '' unless (defined $text);
+
+       # Validate colors. Only color name or color code are valid.
+       $foreground = '' unless ($foreground &&
+                               ($foreground =~ /^[a-z]+$/ || $foreground =~ /^#[0-9a-f]{3,6}$/));
+       $background = '' unless ($background &&
+                               ($background =~ /^[a-z]+$/ || $background =~ /^#[0-9a-f]{3,6}$/));
+
+       my $preserved = '';
+       $preserved .= '<span class="color">';
+       $preserved .= 'color: '.$foreground if ($foreground);
+       $preserved .= '; ' if ($foreground && $background);
+       $preserved .= 'background-color: '.$background if ($background);
+       $preserved .= '</span>';
+       $preserved .= '<span class="colorend">'.$text.'</span>';
+       
+       return $preserved;
+
+}
+
+sub replace_preserved_style ($) {
+       my $content = shift;
+
+       $content =~ s!<span class="color">((color: ([a-z]+|\#[0-9a-f]{3,6})?)?((; )?(background-color: ([a-z]+|\#[0-9a-f]{3,6})?)?)?)</span>!<span class="color" style="$1">!g;
+       $content =~ s!<span class="colorend">!!g;
+
+       return $content;
+}
+
+sub preprocess (@) {
+       my %params = @_;
+
+       # Preprocess the text to expand any preprocessor directives
+       # embedded inside it.
+       $params{text} = IkiWiki::preprocess($params{page}, $params{destpage},
+                               IkiWiki::filter($params{page}, $params{destpage}, $params{text}));
+
+       return preserve_style($params{foreground}, $params{background}, $params{text});
+}
+
+sub format (@) {
+       my %params = @_;
+
+       $params{content} = replace_preserved_style($params{content});
+       return $params{content};        
+}
+
+1
diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm
new file mode 100644 (file)
index 0000000..517e16f
--- /dev/null
@@ -0,0 +1,854 @@
+#!/usr/bin/perl
+# Copyright © 2006-2008 Joey Hess <joey@ikiwiki.info>
+# Copyright © 2008 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+# Licensed under the GNU GPL, version 2, or any later version published by the
+# Free Software Foundation
+package IkiWiki::Plugin::comments;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use Encode;
+use POSIX qw(strftime);
+
+use constant PREVIEW => "Preview";
+use constant POST_COMMENT => "Post comment";
+use constant CANCEL => "Cancel";
+
+my $postcomment;
+my %commentstate;
+
+sub import {
+       hook(type => "checkconfig", id => 'comments',  call => \&checkconfig);
+       hook(type => "getsetup", id => 'comments',  call => \&getsetup);
+       hook(type => "preprocess", id => 'comment', call => \&preprocess);
+       # here for backwards compatability with old comments
+       hook(type => "preprocess", id => '_comment', call => \&preprocess);
+       hook(type => "sessioncgi", id => 'comment', call => \&sessioncgi);
+       hook(type => "htmlize", id => "_comment", call => \&htmlize);
+       hook(type => "pagetemplate", id => "comments", call => \&pagetemplate);
+       hook(type => "formbuilder_setup", id => "comments", call => \&formbuilder_setup);
+       # Load goto to fix up user page links for logged-in commenters
+       IkiWiki::loadplugin("goto");
+       IkiWiki::loadplugin("inline");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               comments_pagespec => {
+                       type => 'pagespec',
+                       example => 'blog/* and !*/Discussion',
+                       description => 'PageSpec of pages where comments are allowed',
+                       link => 'ikiwiki/PageSpec',
+                       safe => 1,
+                       rebuild => 1,
+               },
+               comments_closed_pagespec => {
+                       type => 'pagespec',
+                       example => 'blog/controversial or blog/flamewar',
+                       description => 'PageSpec of pages where posting new comments is not allowed',
+                       link => 'ikiwiki/PageSpec',
+                       safe => 1,
+                       rebuild => 1,
+               },
+               comments_pagename => {
+                       type => 'string',
+                       default => 'comment_',
+                       description => 'Base name for comments, e.g. "comment_" for pages like "sandbox/comment_12"',
+                       safe => 0, # manual page moving required
+                       rebuild => undef,
+               },
+               comments_allowdirectives => {
+                       type => 'boolean',
+                       example => 0,
+                       description => 'Interpret directives in comments?',
+                       safe => 1,
+                       rebuild => 0,
+               },
+               comments_allowauthor => {
+                       type => 'boolean',
+                       example => 0,
+                       description => 'Allow anonymous commenters to set an author name?',
+                       safe => 1,
+                       rebuild => 0,
+               },
+               comments_commit => {
+                       type => 'boolean',
+                       example => 1,
+                       description => 'commit comments to the VCS',
+                       # old uncommitted comments are likely to cause
+                       # confusion if this is changed
+                       safe => 0,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
+       $config{comments_commit} = 1
+               unless defined $config{comments_commit};
+       $config{comments_pagespec} = ''
+               unless defined $config{comments_pagespec};
+       $config{comments_closed_pagespec} = ''
+               unless defined $config{comments_closed_pagespec};
+       $config{comments_pagename} = 'comment_'
+               unless defined $config{comments_pagename};
+}
+
+sub htmlize {
+       my %params = @_;
+       return $params{content};
+}
+
+# FIXME: copied verbatim from meta
+sub safeurl ($) {
+       my $url=shift;
+       if (exists $IkiWiki::Plugin::htmlscrubber::{safe_url_regexp} &&
+           defined $IkiWiki::Plugin::htmlscrubber::safe_url_regexp) {
+               return $url=~/$IkiWiki::Plugin::htmlscrubber::safe_url_regexp/;
+       }
+       else {
+               return 1;
+       }
+}
+
+sub preprocess {
+       my %params = @_;
+       my $page = $params{page};
+
+       my $format = $params{format};
+       if (defined $format && ! exists $IkiWiki::hooks{htmlize}{$format}) {
+               error(sprintf(gettext("unsupported page format %s"), $format));
+       }
+
+       my $content = $params{content};
+       if (! defined $content) {
+               error(gettext("comment must have content"));
+       }
+       $content =~ s/\\"/"/g;
+
+       $content = IkiWiki::filter($page, $params{destpage}, $content);
+
+       if ($config{comments_allowdirectives}) {
+               $content = IkiWiki::preprocess($page, $params{destpage},
+                       $content);
+       }
+
+       # no need to bother with htmlize if it's just HTML
+       $content = IkiWiki::htmlize($page, $params{destpage}, $format, $content)
+               if defined $format;
+
+       IkiWiki::run_hooks(sanitize => sub {
+               $content = shift->(
+                       page => $page,
+                       destpage => $params{destpage},
+                       content => $content,
+               );
+       });
+
+       # set metadata, possibly overriding [[!meta]] directives from the
+       # comment itself
+
+       my $commentuser;
+       my $commentip;
+       my $commentauthor;
+       my $commentauthorurl;
+       my $commentopenid;
+       if (defined $params{username}) {
+               $commentuser = $params{username};
+
+               my $oiduser = eval { IkiWiki::openiduser($commentuser) };
+
+               if (defined $oiduser) {
+                       # looks like an OpenID
+                       $commentauthorurl = $commentuser;
+                       $commentauthor = $oiduser;
+                       $commentopenid = $commentuser;
+               }
+               else {
+                       $commentauthorurl = IkiWiki::cgiurl(
+                               do => 'goto',
+                               page => (length $config{userdir}
+                                       ? "$config{userdir}/$commentuser"
+                                       : "$commentuser"));
+
+                       $commentauthor = $commentuser;
+               }
+       }
+       else {
+               if (defined $params{ip}) {
+                       $commentip = $params{ip};
+               }
+               $commentauthor = gettext("Anonymous");
+       }
+
+       $commentstate{$page}{commentuser} = $commentuser;
+       $commentstate{$page}{commentopenid} = $commentopenid;
+       $commentstate{$page}{commentip} = $commentip;
+       $commentstate{$page}{commentauthor} = $commentauthor;
+       $commentstate{$page}{commentauthorurl} = $commentauthorurl;
+       if (! defined $pagestate{$page}{meta}{author}) {
+               $pagestate{$page}{meta}{author} = $commentauthor;
+       }
+       if (! defined $pagestate{$page}{meta}{authorurl}) {
+               $pagestate{$page}{meta}{authorurl} = $commentauthorurl;
+       }
+
+       if ($config{comments_allowauthor}) {
+               if (defined $params{claimedauthor}) {
+                       $pagestate{$page}{meta}{author} = $params{claimedauthor};
+               }
+
+               if (defined $params{url}) {
+                       my $url=$params{url};
+
+                       eval q{use URI::Heuristic}; 
+                       if (! $@) {
+                               $url=URI::Heuristic::uf_uristr($url);
+                       }
+
+                       if (safeurl($url)) {
+                               $pagestate{$page}{meta}{authorurl} = $url;
+                       }
+               }
+       }
+       else {
+               $pagestate{$page}{meta}{author} = $commentauthor;
+               $pagestate{$page}{meta}{authorurl} = $commentauthorurl;
+       }
+
+       if (defined $params{subject}) {
+               $pagestate{$page}{meta}{title} = $params{subject};
+       }
+
+       if ($params{page} =~ m/\/(\Q$config{comments_pagename}\E\d+)$/) {
+               $pagestate{$page}{meta}{permalink} = urlto(IkiWiki::dirname($params{page}), undef, 1).
+                       "#".page_to_id($params{page});
+       }
+
+       eval q{use Date::Parse};
+       if (! $@) {
+               my $time = str2time($params{date});
+               $IkiWiki::pagectime{$page} = $time if defined $time;
+       }
+
+       return $content;
+}
+
+sub sessioncgi ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       my $do = $cgi->param('do');
+       if ($do eq 'comment') {
+               editcomment($cgi, $session);
+       }
+       elsif ($do eq 'commentmoderation') {
+               commentmoderation($cgi, $session);
+       }
+}
+
+# Mostly cargo-culted from IkiWiki::plugin::editpage
+sub editcomment ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       IkiWiki::decode_cgi_utf8($cgi);
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+
+       my @buttons = (POST_COMMENT, PREVIEW, CANCEL);
+       my $form = CGI::FormBuilder->new(
+               fields => [qw{do sid page subject editcontent type author url}],
+               charset => 'utf-8',
+               method => 'POST',
+               required => [qw{editcontent}],
+               javascript => 0,
+               params => $cgi,
+               action => $config{cgiurl},
+               header => 0,
+               table => 0,
+               template => scalar IkiWiki::template_params('editcomment.tmpl'),
+       );
+
+       IkiWiki::decode_form_utf8($form);
+       IkiWiki::run_hooks(formbuilder_setup => sub {
+                       shift->(title => "comment", form => $form, cgi => $cgi,
+                               session => $session, buttons => \@buttons);
+               });
+       IkiWiki::decode_form_utf8($form);
+
+       my $type = $form->param('type');
+       if (defined $type && length $type && $IkiWiki::hooks{htmlize}{$type}) {
+               $type = IkiWiki::possibly_foolish_untaint($type);
+       }
+       else {
+               $type = $config{default_pageext};
+       }
+
+
+       my @page_types;
+       if (exists $IkiWiki::hooks{htmlize}) {
+               foreach my $key (grep { !/^_/ } keys %{$IkiWiki::hooks{htmlize}}) {
+                       push @page_types, [$key, $IkiWiki::hooks{htmlize}{$key}{longname} || $key];
+               }
+       }
+       @page_types=sort @page_types;
+
+       $form->field(name => 'do', type => 'hidden');
+       $form->field(name => 'sid', type => 'hidden', value => $session->id,
+               force => 1);
+       $form->field(name => 'page', type => 'hidden');
+       $form->field(name => 'subject', type => 'text', size => 72);
+       $form->field(name => 'editcontent', type => 'textarea', rows => 10);
+       $form->field(name => "type", value => $type, force => 1,
+               type => 'select', options => \@page_types);
+
+       $form->tmpl_param(username => $session->param('name'));
+
+       if ($config{comments_allowauthor} and
+           ! defined $session->param('name')) {
+               $form->tmpl_param(allowauthor => 1);
+               $form->field(name => 'author', type => 'text', size => '40');
+               $form->field(name => 'url', type => 'text', size => '40');
+       }
+       else {
+               $form->tmpl_param(allowauthor => 0);
+               $form->field(name => 'author', type => 'hidden', value => '',
+                       force => 1);
+               $form->field(name => 'url', type => 'hidden', value => '',
+                       force => 1);
+       }
+
+       if (! defined $session->param('name')) {
+               # Make signinurl work and return here.
+               $form->tmpl_param(signinurl => IkiWiki::cgiurl(do => 'signin'));
+               $session->param(postsignin => $ENV{QUERY_STRING});
+               IkiWiki::cgi_savesession($session);
+       }
+
+       # The untaint is OK (as in editpage) because we're about to pass
+       # it to file_pruned anyway
+       my $page = $form->field('page');
+       $page = IkiWiki::possibly_foolish_untaint($page);
+       if (! defined $page || ! length $page ||
+               IkiWiki::file_pruned($page, $config{srcdir})) {
+               error(gettext("bad page name"));
+       }
+
+       my $baseurl = urlto($page, undef, 1);
+
+       $form->title(sprintf(gettext("commenting on %s"),
+                       IkiWiki::pagetitle($page)));
+
+       $form->tmpl_param('helponformattinglink',
+               htmllink($page, $page, 'ikiwiki/formatting',
+                       noimageinline => 1,
+                       linktext => 'FormattingHelp'),
+                       allowdirectives => $config{allow_directives});
+
+       if ($form->submitted eq CANCEL) {
+               # bounce back to the page they wanted to comment on, and exit.
+               # CANCEL need not be considered in future
+               IkiWiki::redirect($cgi, urlto($page, undef, 1));
+               exit;
+       }
+
+       if (not exists $pagesources{$page}) {
+               error(sprintf(gettext(
+                       "page '%s' doesn't exist, so you can't comment"),
+                       $page));
+       }
+
+       if (pagespec_match($page, $config{comments_closed_pagespec},
+               location => $page)) {
+               error(sprintf(gettext(
+                       "comments on page '%s' are closed"),
+                       $page));
+       }
+
+       # Set a flag to indicate that we're posting a comment,
+       # so that postcomment() can tell it should match.
+       $postcomment=1;
+       IkiWiki::check_canedit($page, $cgi, $session);
+       $postcomment=0;
+
+       my $location=unique_comment_location($page, $config{srcdir});
+
+       my $content = "[[!comment format=$type\n";
+
+       # FIXME: handling of double quotes probably wrong?
+       if (defined $session->param('name')) {
+               my $username = $session->param('name');
+               $username =~ s/"/&quot;/g;
+               $content .= " username=\"$username\"\n";
+       }
+       elsif (defined $ENV{REMOTE_ADDR}) {
+               my $ip = $ENV{REMOTE_ADDR};
+               if ($ip =~ m/^([.0-9]+)$/) {
+                       $content .= " ip=\"$1\"\n";
+               }
+       }
+
+       if ($config{comments_allowauthor}) {
+               my $author = $form->field('author');
+               if (defined $author && length $author) {
+                       $author =~ s/"/&quot;/g;
+                       $content .= " claimedauthor=\"$author\"\n";
+               }
+               my $url = $form->field('url');
+               if (defined $url && length $url) {
+                       $url =~ s/"/&quot;/g;
+                       $content .= " url=\"$url\"\n";
+               }
+       }
+
+       my $subject = $form->field('subject');
+       if (defined $subject && length $subject) {
+               $subject =~ s/"/&quot;/g;
+               $content .= " subject=\"$subject\"\n";
+       }
+
+       $content .= " date=\"" . decode_utf8(strftime('%Y-%m-%dT%H:%M:%SZ', gmtime)) . "\"\n";
+
+       my $editcontent = $form->field('editcontent') || '';
+       $editcontent =~ s/\r\n/\n/g;
+       $editcontent =~ s/\r/\n/g;
+       $editcontent =~ s/"/\\"/g;
+       $content .= " content=\"\"\"\n$editcontent\n\"\"\"]]\n";
+
+       # This is essentially a simplified version of editpage:
+       # - the user does not control the page that's created, only the parent
+       # - it's always a create operation, never an edit
+       # - this means that conflicts should never happen
+       # - this means that if they do, rocks fall and everyone dies
+
+       if ($form->submitted eq PREVIEW) {
+               my $preview=previewcomment($content, $location, $page, time);
+               IkiWiki::run_hooks(format => sub {
+                       $preview = shift->(page => $page,
+                               content => $preview);
+               });
+               $form->tmpl_param(page_preview => $preview);
+       }
+       else {
+               $form->tmpl_param(page_preview => "");
+       }
+
+       if ($form->submitted eq POST_COMMENT && $form->validate) {
+               IkiWiki::checksessionexpiry($cgi, $session);
+               
+               $postcomment=1;
+               my $ok=IkiWiki::check_content(content => $form->field('editcontent'),
+                       subject => $form->field('subject'),
+                       $config{comments_allowauthor} ? (
+                               author => $form->field('author'),
+                               url => $form->field('url'),
+                       ) : (),
+                       page => $location,
+                       cgi => $cgi,
+                       session => $session,
+                       nonfatal => 1,
+               );
+               $postcomment=0;
+
+               if (! $ok) {
+                       my $penddir=$config{wikistatedir}."/comments_pending";
+                       $location=unique_comment_location($page, $penddir);
+                       writefile("$location._comment", $penddir, $content);
+                       IkiWiki::printheader($session);
+                       print IkiWiki::misctemplate(gettext(gettext("comment stored for moderation")),
+                               "<p>".
+                               gettext("Your comment will be posted after moderator review").
+                               "</p>");
+                       exit;
+               }
+
+               # FIXME: could probably do some sort of graceful retry
+               # on error? Would require significant unwinding though
+               my $file = "$location._comment";
+               writefile($file, $config{srcdir}, $content);
+
+               my $conflict;
+
+               if ($config{rcs} and $config{comments_commit}) {
+                       my $message = gettext("Added a comment");
+                       if (defined $form->field('subject') &&
+                               length $form->field('subject')) {
+                               $message = sprintf(
+                                       gettext("Added a comment: %s"),
+                                       $form->field('subject'));
+                       }
+
+                       IkiWiki::rcs_add($file);
+                       IkiWiki::disable_commit_hook();
+                       $conflict = IkiWiki::rcs_commit_staged($message,
+                               $session->param('name'), $ENV{REMOTE_ADDR});
+                       IkiWiki::enable_commit_hook();
+                       IkiWiki::rcs_update();
+               }
+
+               # Now we need a refresh
+               require IkiWiki::Render;
+               IkiWiki::refresh();
+               IkiWiki::saveindex();
+
+               # this should never happen, unless a committer deliberately
+               # breaks it or something
+               error($conflict) if defined $conflict;
+
+               # Jump to the new comment on the page.
+               # The trailing question mark tries to avoid broken
+               # caches and get the most recent version of the page.
+               IkiWiki::redirect($cgi, urlto($page, undef, 1).
+                       "?updated#".page_to_id($location));
+
+       }
+       else {
+               IkiWiki::showform ($form, \@buttons, $session, $cgi,
+                       forcebaseurl => $baseurl);
+       }
+
+       exit;
+}
+
+sub commentmoderation ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       IkiWiki::needsignin($cgi, $session);
+       if (! IkiWiki::is_admin($session->param("name"))) {
+               error(gettext("you are not logged in as an admin"));
+       }
+
+       IkiWiki::decode_cgi_utf8($cgi);
+       
+       if (defined $cgi->param('sid')) {
+               IkiWiki::checksessionexpiry($cgi, $session);
+
+               my $rejectalldefer=$cgi->param('rejectalldefer');
+
+               my %vars=$cgi->Vars;
+               my $added=0;
+               foreach my $id (keys %vars) {
+                       if ($id =~ /(.*)\Q._comment\E$/) {
+                               my $action=$cgi->param($id);
+                               next if $action eq 'Defer' && ! $rejectalldefer;
+
+                               # Make sure that the id is of a legal
+                               # pending comment before untainting.
+                               my ($f)= $id =~ /$config{wiki_file_regexp}/;
+                               if (! defined $f || ! length $f ||
+                                   IkiWiki::file_pruned($f, $config{srcdir})) {
+                                       error("illegal file");
+                               }
+
+                               my $page=IkiWiki::possibly_foolish_untaint(IkiWiki::dirname($1));
+                               my $file="$config{wikistatedir}/comments_pending/".
+                                       IkiWiki::possibly_foolish_untaint($id);
+
+                               if ($action eq 'Accept') {
+                                       my $content=eval { readfile($file) };
+                                       next if $@; # file vanished since form was displayed
+                                       my $dest=unique_comment_location($page, $config{srcdir})."._comment";
+                                       writefile($dest, $config{srcdir}, $content);
+                                       if ($config{rcs} and $config{comments_commit}) {
+                                               IkiWiki::rcs_add($dest);
+                                       }
+                                       $added++;
+                               }
+
+                               # This removes empty subdirs, so the
+                               # .ikiwiki/comments_pending dir will
+                               # go away when all are moderated.
+                               require IkiWiki::Render;
+                               IkiWiki::prune($file);
+                       }
+               }
+
+               if ($added) {
+                       my $conflict;
+                       if ($config{rcs} and $config{comments_commit}) {
+                               my $message = gettext("Comment moderation");
+                               IkiWiki::disable_commit_hook();
+                               $conflict=IkiWiki::rcs_commit_staged($message,
+                                       $session->param('name'), $ENV{REMOTE_ADDR});
+                               IkiWiki::enable_commit_hook();
+                               IkiWiki::rcs_update();
+                       }
+               
+                       # Now we need a refresh
+                       require IkiWiki::Render;
+                       IkiWiki::refresh();
+                       IkiWiki::saveindex();
+               
+                       error($conflict) if defined $conflict;
+               }
+       }
+
+       my @comments=map {
+               my ($id, $ctime)=@{$_};
+               my $file="$config{wikistatedir}/comments_pending/$id";
+               my $content=readfile($file);
+               my $preview=previewcomment($content, $id,
+                       IkiWiki::dirname($_), $ctime);
+               {
+                       id => $id,
+                       view => $preview,
+               } 
+       } sort { $b->[1] <=> $a->[1] } comments_pending();
+
+       my $template=template("commentmoderation.tmpl");
+       $template->param(
+               sid => $session->id,
+               comments => \@comments,
+       );
+       IkiWiki::printheader($session);
+       my $out=$template->output;
+       IkiWiki::run_hooks(format => sub {
+               $out = shift->(page => "", content => $out);
+       });
+       print IkiWiki::misctemplate(gettext("comment moderation"), $out);
+       exit;
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+
+       my $form=$params{form};
+       if ($form->title eq "preferences" &&
+           IkiWiki::is_admin($params{session}->param("name"))) {
+               push @{$params{buttons}}, "Comment Moderation";
+               if ($form->submitted && $form->submitted eq "Comment Moderation") {
+                       commentmoderation($params{cgi}, $params{session});
+               }
+       }
+}
+
+sub comments_pending () {
+       my $dir="$config{wikistatedir}/comments_pending/";
+       return unless -d $dir;
+
+       my @ret;
+       eval q{use File::Find};
+       error($@) if $@;
+       find({
+               no_chdir => 1,
+               wanted => sub {
+                       $_=decode_utf8($_);
+                       if (IkiWiki::file_pruned($_, $dir)) {
+                               $File::Find::prune=1;
+                       }
+                       elsif (! -l $_ && ! -d _) {
+                               $File::Find::prune=0;
+                               my ($f)=/$config{wiki_file_regexp}/; # untaint
+                               if (defined $f && $f =~ /\Q._comment\E$/) {
+                                       my $ctime=(stat($f))[10];
+                                       $f=~s/^\Q$dir\E\/?//;
+                                        push @ret, [$f, $ctime];
+                               }
+                       }
+               }
+       }, $dir);
+
+       return @ret;
+}
+
+sub previewcomment ($$$) {
+       my $content=shift;
+       my $location=shift;
+       my $page=shift;
+       my $time=shift;
+
+       my $preview = IkiWiki::htmlize($location, $page, '_comment',
+                       IkiWiki::linkify($location, $page,
+                       IkiWiki::preprocess($location, $page,
+                       IkiWiki::filter($location, $page, $content), 0, 1)));
+
+       my $template = template("comment.tmpl");
+       $template->param(content => $preview);
+       $template->param(ctime => displaytime($time));
+
+       IkiWiki::run_hooks(pagetemplate => sub {
+               shift->(page => $location,
+                       destpage => $page,
+                       template => $template);
+       });
+
+       $template->param(have_actions => 0);
+
+       return $template->output;
+}
+
+sub commentsshown ($) {
+       my $page=shift;
+
+       return ! pagespec_match($page, "internal(*/$config{comments_pagename}*)",
+                               location => $page) &&
+              pagespec_match($page, $config{comments_pagespec},
+                             location => $page);
+}
+
+sub commentsopen ($) {
+       my $page = shift;
+
+       return length $config{cgiurl} > 0 &&
+              (! length $config{comments_closed_pagespec} ||
+               ! pagespec_match($page, $config{comments_closed_pagespec},
+                                location => $page));
+}
+
+sub pagetemplate (@) {
+       my %params = @_;
+
+       my $page = $params{page};
+       my $template = $params{template};
+       my $shown = ($template->query(name => 'commentslink') ||
+                    $template->query(name => 'commentsurl') ||
+                    $template->query(name => 'atomcommentsurl') ||
+                    $template->query(name => 'comments')) &&
+                   commentsshown($page);
+
+       if ($template->query(name => 'comments')) {
+               my $comments = undef;
+               if ($shown) {
+                       $comments = IkiWiki::preprocess_inline(
+                               pages => "internal($page/$config{comments_pagename}*)",
+                               template => 'comment',
+                               show => 0,
+                               reverse => 'yes',
+                               page => $page,
+                               destpage => $params{destpage},
+                               feedfile => 'comments',
+                               emptyfeeds => 'no',
+                       );
+               }
+
+               if (defined $comments && length $comments) {
+                       $template->param(comments => $comments);
+               }
+
+               if ($shown && commentsopen($page)) {
+                       my $addcommenturl = IkiWiki::cgiurl(do => 'comment',
+                               page => $page);
+                       $template->param(addcommenturl => $addcommenturl);
+               }
+       }
+
+       if ($template->query(name => 'commentsurl')) {
+               if ($shown) {
+                       $template->param(commentsurl =>
+                               urlto($page, undef, 1).'#comments');
+               }
+       }
+
+       if ($template->query(name => 'atomcommentsurl') && $config{usedirs}) {
+               if ($shown) {
+                       # This will 404 until there are some comments, but I
+                       # think that's probably OK...
+                       $template->param(atomcommentsurl =>
+                               urlto($page, undef, 1).'comments.atom');
+               }
+       }
+
+       if ($template->query(name => 'commentslink')) {
+               # XXX Would be nice to say how many comments there are in
+               # the link. But, to update the number, blog pages
+               # would have to update whenever comments of any inlines
+               # page are added, which is not currently done.
+               if ($shown) {
+                       $template->param(commentslink =>
+                               htmllink($page, $params{destpage}, $page,
+                                       linktext => gettext("Comments"),
+                                       anchor => "comments",
+                                       noimageinline => 1));
+               }
+       }
+
+       # everything below this point is only relevant to the comments
+       # themselves
+       if (!exists $commentstate{$page}) {
+               return;
+       }
+       
+       if ($template->query(name => 'commentid')) {
+               $template->param(commentid => page_to_id($page));
+       }
+
+       if ($template->query(name => 'commentuser')) {
+               $template->param(commentuser =>
+                       $commentstate{$page}{commentuser});
+       }
+
+       if ($template->query(name => 'commentopenid')) {
+               $template->param(commentopenid =>
+                       $commentstate{$page}{commentopenid});
+       }
+
+       if ($template->query(name => 'commentip')) {
+               $template->param(commentip =>
+                       $commentstate{$page}{commentip});
+       }
+
+       if ($template->query(name => 'commentauthor')) {
+               $template->param(commentauthor =>
+                       $commentstate{$page}{commentauthor});
+       }
+
+       if ($template->query(name => 'commentauthorurl')) {
+               $template->param(commentauthorurl =>
+                       $commentstate{$page}{commentauthorurl});
+       }
+
+       if ($template->query(name => 'removeurl') &&
+           IkiWiki::Plugin::remove->can("check_canremove") &&
+           length $config{cgiurl}) {
+               $template->param(removeurl => IkiWiki::cgiurl(do => 'remove',
+                       page => $page));
+               $template->param(have_actions => 1);
+       }
+}
+
+sub unique_comment_location ($) {
+       my $page=shift;
+       my $dir=shift;
+
+       my $location;
+       my $i = 0;
+       do {
+               $i++;
+               $location = "$page/$config{comments_pagename}$i";
+       } while (-e "$dir/$location._comment");
+
+       return $location;
+}
+
+sub page_to_id ($) {
+       # Converts a comment page name into a unique, legal html id
+       # addtibute value, that can be used as an anchor to link to the
+       # comment.
+       my $page=shift;
+
+       eval q{use Digest::MD5 'md5_hex'};
+       error($@) if $@;
+
+       return "comment-".md5_hex($page);
+}
+       
+package IkiWiki::PageSpec;
+
+sub match_postcomment ($$;@) {
+       my $page = shift;
+       my $glob = shift;
+
+       if (! $postcomment) {
+               return IkiWiki::FailReason->new("not posting a comment");
+       }
+       return match_glob($page, $glob);
+}
+
+1
index 57db010544b52d436e7dac2ed42e34ef80445360..7445dbdad71420bb4228f573543ac673732b197c 100644 (file)
@@ -3,19 +3,28 @@ package IkiWiki::Plugin::conditional;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use UNIVERSAL;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "conditional", call => \&getsetup);
        hook(type => "preprocess", id => "if", call => \&preprocess_if);
-} # }}}
+}
 
-sub preprocess_if (@) { #{{{
+sub getsetup {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess_if (@) {
        my %params=@_;
 
        foreach my $param (qw{test then}) {
                if (! exists $params{$param}) {
-                       return "[[if ".sprintf(gettext('%s parameter is required'), $param)."]]";
+                       error sprintf(gettext('%s parameter is required'), $param);
                }
        }
 
@@ -24,8 +33,8 @@ sub preprocess_if (@) { #{{{
                # An optimisation to avoid needless looping over every page
                # and adding of dependencies for simple uses of some of the
                # tests.
-               $params{test} =~ /^\s*\!?\s*(enabled|sourcepage|destpage|included)\((.*)\)\s*$/) {
-               add_depends($params{page}, "$params{test} and $params{page}");
+               $params{test} =~ /^([\s\!()]*((enabled|sourcepage|destpage|included)\([^)]*\)|(and|or))[\s\!()]*)+$/) {
+               add_depends($params{page}, "($params{test}) and $params{page}");
                $result=pagespec_match($params{page}, $params{test},
                                location => $params{page},
                                sourcepage => $params{page},
@@ -57,11 +66,11 @@ sub preprocess_if (@) { #{{{
        }
        return IkiWiki::preprocess($params{page}, $params{destpage}, 
                IkiWiki::filter($params{page}, $params{destpage}, $ret));
-} # }}}
+}
 
 package IkiWiki::PageSpec;
 
-sub match_enabled ($$;@) { #{{{
+sub match_enabled ($$;@) {
        shift;
        my $plugin=shift;
        
@@ -72,12 +81,14 @@ sub match_enabled ($$;@) { #{{{
        else {
                return IkiWiki::FailReason->new("$plugin is not enabled");
        }
-} #}}}
+}
 
-sub match_sourcepage ($$;@) { #{{{
+sub match_sourcepage ($$;@) {
        shift;
        my $glob=shift;
        my %params=@_;
+       
+       $glob=derel($glob, $params{location});
 
        return IkiWiki::FailReason->new("cannot match sourcepage") unless exists $params{sourcepage};
        if (match_glob($params{sourcepage}, $glob, @_)) {
@@ -86,13 +97,15 @@ sub match_sourcepage ($$;@) { #{{{
        else {
                return IkiWiki::FailReason->new("sourcepage does not match $glob");
        }
-} #}}}
+}
 
-sub match_destpage ($$;@) { #{{{
+sub match_destpage ($$;@) {
        shift;
        my $glob=shift;
        my %params=@_;
        
+       $glob=derel($glob, $params{location});
+
        return IkiWiki::FailReason->new("cannot match destpage") unless exists $params{destpage};
        if (match_glob($params{destpage}, $glob, @_)) {
                return IkiWiki::SuccessReason->new("destpage matches $glob");
@@ -100,9 +113,9 @@ sub match_destpage ($$;@) { #{{{
        else {
                return IkiWiki::FailReason->new("destpage does not match $glob");
        }
-} #}}}
+}
 
-sub match_included ($$;@) { #{{{
+sub match_included ($$;@) {
        shift;
        shift;
        my %params=@_;
@@ -114,6 +127,6 @@ sub match_included ($$;@) { #{{{
        else {
                return IkiWiki::FailReason->new("page $params{sourcepage} is not included");
        }
-} #}}}
+}
 
 1
index 0c857d125bd1bc544c5a52a44f94a385cec13e08..425e71043f0133f5b855c32932bc114542c83d7d 100644 (file)
@@ -5,13 +5,22 @@ package IkiWiki::Plugin::creole;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "creole", call => \&getsetup);
        hook(type => "htmlize", id => "creole", call => \&htmlize);
-} # }}}
+}
 
-sub htmlize (@) { #{{{
+sub getsetup {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
+sub htmlize (@) {
        my %params=@_;
        my $content = $params{content};
 
@@ -23,6 +32,6 @@ sub htmlize (@) { #{{{
        creole_custombarelinks();
 
        return creole_parse($content);
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/cutpaste.pm b/IkiWiki/Plugin/cutpaste.pm
new file mode 100644 (file)
index 0000000..417442f
--- /dev/null
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::cutpaste;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+my %savedtext;
+
+sub import {
+       hook(type => "getsetup", id => "cutpaste", call => \&getsetup);
+       hook(type => "preprocess", id => "cut", call => \&preprocess_cut, scan => 1);
+       hook(type => "preprocess", id => "copy", call => \&preprocess_copy, scan => 1);
+       hook(type => "preprocess", id => "paste", call => \&preprocess_paste);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess_cut (@) {
+       my %params=@_;
+
+       foreach my $param (qw{id text}) {
+               if (! exists $params{$param}) {
+                       error sprintf(gettext('%s parameter is required'), $param);
+               }
+       }
+
+       $savedtext{$params{page}} = {} if not exists $savedtext{$params{"page"}};
+       $savedtext{$params{page}}->{$params{id}} = $params{text};
+
+       return "" if defined wantarray;
+}
+
+sub preprocess_copy (@) {
+       my %params=@_;
+
+       foreach my $param (qw{id text}) {
+               if (! exists $params{$param}) {
+                       error sprintf(gettext('%s parameter is required'), $param);
+               }
+       }
+
+       $savedtext{$params{page}} = {} if not exists $savedtext{$params{"page"}};
+       $savedtext{$params{page}}->{$params{id}} = $params{text};
+
+       return IkiWiki::preprocess($params{page}, $params{destpage}, 
+               IkiWiki::filter($params{page}, $params{destpage}, $params{text})) if defined wantarray;
+}
+
+sub preprocess_paste (@) {
+       my %params=@_;
+
+       foreach my $param (qw{id}) {
+               if (! exists $params{$param}) {
+                       error sprintf(gettext('%s parameter is required'), $param);
+               }
+       }
+
+       if (! exists $savedtext{$params{page}}) {
+               error gettext('no text was copied in this page');
+       }
+       if (! exists $savedtext{$params{page}}->{$params{id}}) {
+               error sprintf(gettext('no text was copied in this page with id %s'), $params{id});
+       }
+
+       return IkiWiki::preprocess($params{page}, $params{destpage}, 
+               IkiWiki::filter($params{page}, $params{destpage}, $savedtext{$params{page}}->{$params{id}}));
+}
+
+1;
diff --git a/IkiWiki/Plugin/darcs.pm b/IkiWiki/Plugin/darcs.pm
new file mode 100644 (file)
index 0000000..2448673
--- /dev/null
@@ -0,0 +1,429 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::darcs;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import {
+       hook(type => "checkconfig", id => "darcs", call => \&checkconfig);
+       hook(type => "getsetup", id => "darcs", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub silentsystem (@) {
+       open(SAVED_STDOUT, ">&STDOUT");
+       open(STDOUT, ">/dev/null");
+       my $ret = system @_;
+       open(STDOUT, ">&SAVED_STDOUT");
+       return $ret;
+}
+
+sub darcs_info ($$$) {
+       my $field = shift;
+       my $repodir = shift;
+       my $file = shift; # Relative to the repodir.
+
+       my $child = open(DARCS_CHANGES, "-|");
+       if (! $child) {
+               exec('darcs', 'changes', '--repodir', $repodir, '--xml-output', $file) or
+                       error("failed to run 'darcs changes'");
+       }
+
+       # Brute force for now.  :-/
+       while (<DARCS_CHANGES>) {
+               last if /^<\/created_as>$/;
+       }
+       ($_) = <DARCS_CHANGES> =~ /$field=\'([^\']+)/;
+       $field eq 'hash' and s/\.gz//; # Strip away the '.gz' from 'hash'es.
+
+       close(DARCS_CHANGES);
+
+       return $_;
+}
+
+sub file_in_vc($$) {
+       my $repodir = shift;
+       my $file = shift;
+
+       my $child = open(DARCS_MANIFEST, "-|");
+       if (! $child) {
+               exec('darcs', 'query', 'manifest', '--repodir', $repodir) or
+                       error("failed to run 'darcs query manifest'");
+       }
+       my $found=0;
+       while (<DARCS_MANIFEST>) {
+               $found = 1, last if /^(\.\/)?$file$/;
+       }
+       close(DARCS_MANIFEST) or error("'darcs query manifest' exited " . $?);
+
+       return $found;
+}
+
+sub darcs_rev($) {
+       my $file = shift; # Relative to the repodir.
+       my $repodir = $config{srcdir};
+
+       return "" if (! file_in_vc($repodir, $file));
+       my $hash = darcs_info('hash', $repodir, $file);
+       return defined $hash ? $hash : "";
+}
+
+sub checkconfig() {
+       if (defined $config{darcs_wrapper} && length $config{darcs_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{darcs_wrapper},
+                       wrappermode => (defined $config{darcs_wrappermode} ? $config{darcs_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup() {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               darcs_wrapper => {
+                       type => "string",
+                       example => "/darcs/repo/_darcs/ikiwiki-wrapper",
+                       description => "wrapper to generate (set as master repo apply hook)",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               darcs_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for darcs_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filehistory;f=[[file]]",
+                       description => "darcsweb url to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filediff;h=[[hash]];f=[[file]]",
+                       description => "darcsweb url to show a diff ([[hash]] and [[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub rcs_update () {
+       silentsystem('darcs', "pull", "--repodir", $config{srcdir}, "-qa")
+}
+
+sub rcs_prepedit ($) {
+       # Prepares to edit a file under revision control.  Returns a token that
+       # must be passed to rcs_commit() when the file is to be commited.  For us,
+       # this token the hash value of the latest patch that modifies the file,
+       # i.e. something like its current revision.
+
+       my $file = shift; # Relative to the repodir.
+       my $rev = darcs_rev($file);
+       return $rev;
+}
+
+sub rcs_commit ($$$;$$) {
+       # Commit the page.  Returns 'undef' on success and a version of the page
+       # with conflict markers on failure.
+
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+
+       # Compute if the "revision" of $file changed.
+       my $changed = darcs_rev($file) ne $rcstoken;
+
+       # Yes, the following is a bit convoluted.
+       if ($changed) {
+               # TODO.  Invent a better, non-conflicting name.
+               rename("$config{srcdir}/$file", "$config{srcdir}/$file.save") or
+                       error("failed to rename $file to $file.save: $!");
+
+               # Roll the repository back to $rcstoken.
+
+               # TODO.  Can we be sure that no changes are lost?  I think that
+               # we can, if we make sure that the 'darcs push' below will always
+               # succeed.
+       
+               # We need to revert everything as 'darcs obliterate' might choke
+               # otherwise.
+               # TODO: 'yes | ...' needed?  Doesn't seem so.
+               silentsystem('darcs', "revert", "--repodir", $config{srcdir}, "--all") == 0 ||
+                       error("'darcs revert' failed");
+               # Remove all patches starting at $rcstoken.
+               my $child = open(DARCS_OBLITERATE, "|-");
+               if (! $child) {
+                       open(STDOUT, ">/dev/null");
+                       exec('darcs', "obliterate", "--repodir", $config{srcdir},
+                          "--match", "hash " . $rcstoken) and
+                          error("'darcs obliterate' failed");
+               }
+               1 while print DARCS_OBLITERATE "y";
+               close(DARCS_OBLITERATE);
+               # Restore the $rcstoken one.
+               silentsystem('darcs', "pull", "--quiet", "--repodir", $config{srcdir},
+                       "--match", "hash " . $rcstoken, "--all") == 0 ||
+                       error("'darcs pull' failed");
+       
+               # We're back at $rcstoken.  Re-install the modified file.
+               rename("$config{srcdir}/$file.save", "$config{srcdir}/$file") or
+                       error("failed to rename $file.save to $file: $!");
+       }
+
+       # Record the changes.
+       my $author;
+       if (defined $user) {
+               $author = "$user\@web";
+       }
+       elsif (defined $ipaddr) {
+               $author = "$ipaddr\@web";
+       }
+       else {
+               $author = "anon\@web";
+       }
+       if (!defined $message || !length($message)) {
+               $message = "empty message";
+       }
+       silentsystem('darcs', 'record', '--repodir', $config{srcdir}, '--all',
+                       '-m', $message, '--author', $author, $file) == 0 ||
+               error("'darcs record' failed");
+
+       # Update the repository by pulling from the default repository, which is
+       # master repository.
+       silentsystem('darcs', "pull", "--quiet", "--repodir", $config{srcdir},
+               "--all") == 0 || error("'darcs pull' failed");
+
+       # If this updating yields any conflicts, we'll record them now to resolve
+       # them.  If nothing is recorded, there are no conflicts.
+       $rcstoken = darcs_rev($file);
+       # TODO: Use only the first line here, i.e. only the patch name?
+       writefile("$file.log", $config{srcdir}, 'resolve conflicts: ' . $message);
+       silentsystem('darcs', 'record', '--repodir', $config{srcdir}, '--all',
+               '-m', 'resolve conflicts: ' . $message, '--author', $author, $file) == 0 ||
+               error("'darcs record' failed");
+       my $conflicts = darcs_rev($file) ne $rcstoken;
+       unlink("$config{srcdir}/$file.log") or
+               error("failed to remove '$file.log'");
+
+       # Push the changes to the main repository.
+       silentsystem('darcs', 'push', '--quiet', '--repodir', $config{srcdir}, '--all') == 0 ||
+               error("'darcs push' failed");
+       # TODO: darcs send?
+
+       if ($conflicts) {
+               my $document = readfile("$config{srcdir}/$file");
+               # Try to leave everything in a consistent state.
+               # TODO: 'yes | ...' needed?  Doesn't seem so.
+               silentsystem('darcs', "revert", "--repodir", $config{srcdir}, "--all") == 0 || 
+                       warn("'darcs revert' failed");
+               return $document;
+       }
+       else {
+               return undef;
+       }
+}
+
+sub rcs_commit_staged($$$) {
+       my ($message, $user, $ipaddr) = @_;
+
+       my $author;
+       if (defined $user) {
+               $author = "$user\@web";
+       }
+       elsif (defined $ipaddr) {
+               $author = "$ipaddr\@web";
+       }
+       else {
+               $author = "anon\@web";
+       }
+       if (!defined $message || !length($message)) {
+               $message = "empty message";
+       }
+
+       silentsystem('darcs', "record", "--repodir", $config{srcdir}, "-a", "-A", $author,
+               "-m", $message) == 0 || error("'darcs record' failed");
+
+       # Push the changes to the main repository.
+       silentsystem('darcs', 'push', '--quiet', '--repodir', $config{srcdir}, '--all') == 0 ||
+               error("'darcs push' failed");
+       # TODO: darcs send?
+
+       return undef;
+}
+
+sub rcs_add ($) {
+       my $file = shift; # Relative to the repodir.
+
+       if(! file_in_vc($config{srcdir}, $file)) {
+               # Intermediate directories will be added automagically.
+               system('darcs', 'add', '--quiet', '--repodir', $config{srcdir},
+                       '--boring', $file) == 0 || error("'darcs add' failed");
+       }
+}
+
+sub rcs_remove ($) {
+       my $file = shift; # Relative to the repodir.
+
+       unlink($config{srcdir}.'/'.$file);
+}
+
+sub rcs_rename ($$) {
+       my $a = shift; # Relative to the repodir.
+       my $b = shift; # Relative to the repodir.
+
+       system('darcs', 'mv', '--repodir', $config{srcdir}, $a, $b) == 0 ||
+               error("'darcs mv' failed");
+}
+
+sub rcs_recentchanges ($) {
+       my $num=shift;
+       my @ret;
+
+       eval q{use Date::Parse};
+       eval q{use XML::Simple};
+
+       my $repodir=$config{srcdir};
+
+       my $child = open(LOG, "-|");
+       if (! $child) {
+               $ENV{"DARCS_DONT_ESCAPE_ANYTHING"}=1;
+               exec("darcs", "changes", "--xml", 
+                       "--summary",
+                        "--repodir", "$repodir",
+                        "--last", "$num")
+               || error("'darcs changes' failed to run");
+       }
+       my $data;
+       $data .= $_ while(<LOG>);
+       close LOG;
+
+       my $log = XMLin($data, ForceArray => 1);
+
+       foreach my $patch (@{$log->{patch}}) {
+               my $date=$patch->{local_date};
+               my $hash=$patch->{hash};
+               my $when=str2time($date);
+               my (@pages, @files, @pg);
+               push @pages, $_ foreach (@{$patch->{summary}->[0]->{modify_file}});
+               push @pages, $_ foreach (@{$patch->{summary}->[0]->{add_file}});
+               push @pages, $_ foreach (@{$patch->{summary}->[0]->{remove_file}});
+               foreach my $f (@pages) {
+                       $f = $f->{content} if ref $f;
+                       $f =~ s,^\s+,,; $f =~ s,\s+$,,; # cut whitespace
+
+                       push @files, $f;
+               }
+               foreach my $p (@{$patch->{summary}->[0]->{move}}) {
+                       push @files, $p->{from};
+               }
+
+               foreach my $f (@files) {
+                       my $d = defined $config{'diffurl'} ? $config{'diffurl'} : "";
+                       $d =~ s/\[\[file\]\]/$f/go;
+                       $d =~ s/\[\[hash\]\]/$hash/go;
+
+                       push @pg, {
+                               page => pagename($f),
+                               diffurl => $d,
+                       };
+               }
+               next unless (scalar @pg > 0);
+
+               my @message;
+               push @message, { line => $_ } foreach (@{$patch->{name}});
+
+               my $committype;
+               my $author;
+               if ($patch->{author} =~ /(.*)\@web$/) {
+                       $author = $1;
+                       $committype = "web";
+               }
+               else {
+                       $author=$patch->{author};
+                       $committype = "darcs";
+               }
+
+               push @ret, {
+                       rev => $patch->{hash},
+                       user => $author,
+                       committype => $committype,
+                       when => $when, 
+                       message => [@message],
+                       pages => [@pg],
+               };
+       }
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       my $rev=shift;
+       my @lines;
+       foreach my $line (silentsystem("darcs", "diff", "--match", "hash ".$rev)) {
+               if (@lines || $line=~/^diff/) {
+                       push @lines, $line."\n";
+               }
+       }
+       if (wantarray) {
+               return @lines;
+       }
+       else {
+               return join("", @lines);
+       }
+}
+
+sub rcs_getctime ($) {
+       my $file=shift;
+
+       eval q{use Date::Parse};
+       eval q{use XML::Simple};
+       local $/=undef;
+
+       my $filer=substr($file, length($config{srcdir}));
+       $filer =~ s:^[/]+::;
+
+       my $child = open(LOG, "-|");
+       if (! $child) {
+               exec("darcs", "changes", "--xml", "--reverse",
+                       "--repodir", $config{srcdir}, $filer)
+               || error("'darcs changes $filer' failed to run");
+       }
+
+       my $data;
+       {
+               local $/=undef;
+               $data = <LOG>;
+       }
+       close LOG;
+
+       my $log = XMLin($data, ForceArray => 1);
+
+       my $datestr = $log->{patch}[0]->{local_date};
+
+       if (! defined $datestr) {
+               warn "failed to get ctime for $filer";
+               return 0;
+       }
+
+       my $date = str2time($datestr);
+       
+       debug("ctime for '$file': ". localtime($date));
+
+       return $date;
+}
+
+1
index d081cb5094d56b5030ba54f7504d911785000643..bb77ce59f267a5c9e541a1f42f88d6eca0eee4f1 100644 (file)
@@ -2,25 +2,29 @@
 # Discordian date support fnord ikiwiki.
 package IkiWiki::Plugin::ddate;
 
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 no warnings;
 
-sub import { #{{{
-       hook(type => "checkconfig", id => "ddate", call => \&checkconfig);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "ddate", call => \&getsetup);
+}
 
-sub checkconfig () { #{{{
-       if (! defined $config{timeformat} ||
-           $config{timeformat} eq '%c') {
-               $config{timeformat}='on %A, the %e of %B, %Y. %N%nCelebrate %H';
-       }
-} #}}}
+sub getsetup {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
 
-sub IkiWiki::displaytime ($;$) { #{{{
+sub IkiWiki::formattime ($;$) {
        my $time=shift;
        my $format=shift;
        if (! defined $format) {
                $format=$config{timeformat};
+               if ($format eq '%c') {
+                       $format='on %A, the %e of %B, %Y. %N%nCelebrate %H';
+               }
        }
        eval q{
                use DateTime;
@@ -32,6 +36,6 @@ sub IkiWiki::displaytime ($;$) { #{{{
        my $dt = DateTime->from_epoch(epoch => $time);
        my $dd = DateTime::Calendar::Discordian->from_object(object => $dt);
        return $dd->strftime($format);
-} #}}}
+}
 
 5
index 9872e9686c2a3255d638968002a5d6339c1d20e2..7df6a9ffb42f53960f4881b43b34b86f49f6e798 100644 (file)
@@ -4,16 +4,25 @@ package IkiWiki::Plugin::editdiff;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Entities;
 use IPC::Open2;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "editdiff", call => \&getsetup);
        hook(type => "formbuilder_setup", id => "editdiff",
                call => \&formbuilder_setup);
-} #}}}
+}
 
-sub diff ($$) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub diff ($$) {
        my $orig=shift;
        my $content=shift;
 
@@ -41,13 +50,13 @@ sub diff ($$) { #{{{
        return "couldn't run diff\n" if $sigpipe;
 
        return "<pre>".encode_entities($ret)."</pre>";
-} #}}}
+}
 
-sub formbuilder_setup { #{{{
+sub formbuilder_setup {
        my %params=@_;
        my $form=$params{form};
 
-       return if defined ! $form->field("do") || $form->field("do") ne "edit";
+       return if ! defined $form->field("do") || $form->field("do") ne "edit";
 
        my $page=$form->field("page");
        $page = IkiWiki::possibly_foolish_untaint($page);
@@ -63,6 +72,6 @@ sub formbuilder_setup { #{{{
                my $diff = diff(srcfile($pagesources{$page}), $content);
                $form->tmpl_param("page_preview", $diff);
        }
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm
new file mode 100644 (file)
index 0000000..fca970c
--- /dev/null
@@ -0,0 +1,436 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::editpage;
+
+use warnings;
+use strict;
+use IkiWiki;
+use open qw{:utf8 :std};
+
+sub import {
+       hook(type => "getsetup", id => "editpage", call => \&getsetup);
+       hook(type => "refresh", id => "editpage", call => \&refresh);
+        hook(type => "sessioncgi", id => "editpage", call => \&IkiWiki::cgi_editpage);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub refresh () {
+       if (exists $wikistate{editpage} && exists $wikistate{editpage}{previews}) {
+               # Expire old preview files after one hour.
+               my $expire=time - (60 * 60);
+
+               my @previews;
+               foreach my $file (@{$wikistate{editpage}{previews}}) {
+                       my $mtime=(stat("$config{destdir}/$file"))[9];
+                       if (defined $mtime && $mtime <= $expire) {
+                               # Avoid deleting a preview that was later saved.
+                               my $delete=1;
+                               foreach my $page (keys %renderedfiles) {
+                                       if (grep { $_ eq $file } @{$renderedfiles{$page}}) {
+                                               $delete=0;
+                                       }
+                               }
+                               if ($delete) {
+                                       debug(sprintf(gettext("removing old preview %s"), $file));
+                                       IkiWiki::prune("$config{destdir}/$file");
+                               }
+                       }
+                       elsif (defined $mtime) {
+                               push @previews, $file;
+                       }
+               }
+               $wikistate{editpage}{previews}=\@previews;
+       }
+}
+
+# Back to ikiwiki namespace for the rest, this code is very much
+# internal to ikiwiki even though it's separated into a plugin,
+# and other plugins use the function below.
+package IkiWiki;
+
+sub cgi_editpage ($$) {
+       my $q=shift;
+       my $session=shift;
+       
+        my $do=$q->param('do');
+       return unless $do eq 'create' || $do eq 'edit';
+
+       decode_cgi_utf8($q);
+
+       my @fields=qw(do rcsinfo subpage from page type editcontent comments);
+       my @buttons=("Save Page", "Preview", "Cancel");
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       my $form = CGI::FormBuilder->new(
+               fields => \@fields,
+               charset => "utf-8",
+               method => 'POST',
+               required => [qw{editcontent}],
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               header => 0,
+               table => 0,
+               template => scalar template_params("editpage.tmpl"),
+       );
+       
+       decode_form_utf8($form);
+       run_hooks(formbuilder_setup => sub {
+               shift->(form => $form, cgi => $q, session => $session,
+                       buttons => \@buttons);
+       });
+       decode_form_utf8($form);
+       
+       # This untaint is safe because we check file_pruned and
+       # wiki_file_regexp.
+       my ($page)=$form->field('page')=~/$config{wiki_file_regexp}/;
+       $page=possibly_foolish_untaint($page);
+       my $absolute=($page =~ s#^/+##);
+       if (! defined $page || ! length $page ||
+           file_pruned($page, $config{srcdir})) {
+               error(gettext("bad page name"));
+       }
+
+       my $baseurl = urlto($page, undef, 1);
+
+       my $from;
+       if (defined $form->field('from')) {
+               ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
+       }
+       
+       my $file;
+       my $type;
+       if (exists $pagesources{$page} && $form->field("do") ne "create") {
+               $file=$pagesources{$page};
+               $type=pagetype($file);
+               if (! defined $type || $type=~/^_/) {
+                       error(sprintf(gettext("%s is not an editable page"), $page));
+               }
+               if (! $form->submitted) {
+                       $form->field(name => "rcsinfo",
+                               value => rcs_prepedit($file), force => 1);
+               }
+               $form->field(name => "editcontent", validate => '/.*/');
+       }
+       else {
+               $type=$form->param('type');
+               if (defined $type && length $type && $hooks{htmlize}{$type}) {
+                       $type=possibly_foolish_untaint($type);
+               }
+               elsif (defined $from && exists $pagesources{$from}) {
+                       # favor the type of linking page
+                       $type=pagetype($pagesources{$from});
+               }
+               $type=$config{default_pageext} unless defined $type;
+               $file=newpagefile($page, $type);
+               if (! $form->submitted) {
+                       $form->field(name => "rcsinfo", value => "", force => 1);
+               }
+               $form->field(name => "editcontent", validate => '/.+/');
+       }
+
+       $form->field(name => "do", type => 'hidden');
+       $form->field(name => "sid", type => "hidden", value => $session->id,
+               force => 1);
+       $form->field(name => "from", type => 'hidden');
+       $form->field(name => "rcsinfo", type => 'hidden');
+       $form->field(name => "subpage", type => 'hidden');
+       $form->field(name => "page", value => $page, force => 1);
+       $form->field(name => "type", value => $type, force => 1);
+       $form->field(name => "comments", type => "text", size => 80);
+       $form->field(name => "editcontent", type => "textarea", rows => 20,
+               cols => 80);
+       $form->tmpl_param("can_commit", $config{rcs});
+       $form->tmpl_param("indexlink", indexlink());
+       $form->tmpl_param("helponformattinglink",
+               htmllink($page, $page, "ikiwiki/formatting",
+                       noimageinline => 1,
+                       linktext => "FormattingHelp"));
+       
+       if ($form->submitted eq "Cancel") {
+               if ($form->field("do") eq "create" && defined $from) {
+                       redirect($q, urlto($from, undef, 1));
+               }
+               elsif ($form->field("do") eq "create") {
+                       redirect($q, $config{url});
+               }
+               else {
+                       redirect($q, urlto($page, undef, 1));
+               }
+               exit;
+       }
+       elsif ($form->submitted eq "Preview") {
+               my $new=not exists $pagesources{$page};
+               if ($new) {
+                       # temporarily record its type
+                       $pagesources{$page}=$page.".".$type;
+               }
+               my %wasrendered=map { $_ => 1 } @{$renderedfiles{$page}};
+
+               my $content=$form->field('editcontent');
+
+               run_hooks(editcontent => sub {
+                       $content=shift->(
+                               content => $content,
+                               page => $page,
+                               cgi => $q,
+                               session => $session,
+                       );
+               });
+               my $preview=htmlize($page, $page, $type,
+                       linkify($page, $page,
+                       preprocess($page, $page,
+                       filter($page, $page, $content), 0, 1)));
+               run_hooks(format => sub {
+                       $preview=shift->(
+                               page => $page,
+                               content => $preview,
+                       );
+               });
+               $form->tmpl_param("page_preview", $preview);
+               
+               if ($new) {
+                       delete $pagesources{$page};
+               }
+
+               # Previewing may have created files on disk.
+               # Keep a list of these to be deleted later.
+               my %previews = map { $_ => 1 } @{$wikistate{editpage}{previews}};
+               foreach my $f (@{$renderedfiles{$page}}) {
+                       $previews{$f}=1 unless $wasrendered{$f};
+               }
+               @{$wikistate{editpage}{previews}} = keys %previews;
+               $renderedfiles{$page}=[keys %wasrendered];
+               saveindex();
+       }
+       elsif ($form->submitted eq "Save Page") {
+               $form->tmpl_param("page_preview", "");
+       }
+       
+       if ($form->submitted ne "Save Page" || ! $form->validate) {
+               if ($form->field("do") eq "create") {
+                       my @page_locs;
+                       my $best_loc;
+                       if (! defined $from || ! length $from ||
+                           $from ne $form->field('from') ||
+                           file_pruned($from, $config{srcdir}) ||
+                           $from=~/^\// || 
+                           $absolute ||
+                           $form->submitted) {
+                               @page_locs=$best_loc=$page;
+                       }
+                       else {
+                               my $dir=$from."/";
+                               $dir=~s![^/]+/+$!!;
+                               
+                               if ((defined $form->field('subpage') &&
+                                    length $form->field('subpage')) ||
+                                   $page eq lc($config{discussionpage})) {
+                                       $best_loc="$from/$page";
+                               }
+                               else {
+                                       $best_loc=$dir.$page;
+                               }
+                               
+                               push @page_locs, $dir.$page;
+                               push @page_locs, "$from/$page";
+                               while (length $dir) {
+                                       $dir=~s![^/]+/+$!!;
+                                       push @page_locs, $dir.$page;
+                               }
+                       
+                               push @page_locs, "$config{userdir}/$page"
+                                       if length $config{userdir};
+                       }
+
+                       @page_locs = grep {
+                               ! exists $pagecase{lc $_}
+                       } @page_locs;
+                       if (! @page_locs) {
+                               # hmm, someone else made the page in the
+                               # meantime?
+                               if ($form->submitted eq "Preview") {
+                                       # let them go ahead with the edit
+                                       # and resolve the conflict at save
+                                       # time
+                                       @page_locs=$page;
+                               }
+                               else {
+                                       redirect($q, urlto($page, undef, 1));
+                                       exit;
+                               }
+                       }
+
+                       my @editable_locs = grep {
+                               check_canedit($_, $q, $session, 1)
+                       } @page_locs;
+                       if (! @editable_locs) {
+                               # let it throw an error this time
+                               map { check_canedit($_, $q, $session) } @page_locs;
+                       }
+                       
+                       my @page_types;
+                       if (exists $hooks{htmlize}) {
+                               foreach my $key (grep { !/^_/ } keys %{$hooks{htmlize}}) {
+                                       push @page_types, [$key, $hooks{htmlize}{$key}{longname} || $key];
+                               }
+                       }
+                       @page_types=sort @page_types;
+                       
+                       $form->tmpl_param("page_select", 1);
+                       $form->field(name => "page", type => 'select',
+                               options => [ map { [ $_, pagetitle($_, 1) ] } @editable_locs ],
+                               value => $best_loc);
+                       $form->field(name => "type", type => 'select',
+                               options => \@page_types);
+                       $form->title(sprintf(gettext("creating %s"), pagetitle($page)));
+                       
+               }
+               elsif ($form->field("do") eq "edit") {
+                       check_canedit($page, $q, $session);
+                       if (! defined $form->field('editcontent') || 
+                           ! length $form->field('editcontent')) {
+                               my $content="";
+                               if (exists $pagesources{$page}) {
+                                       $content=readfile(srcfile($pagesources{$page}));
+                                       $content=~s/\n/\r\n/g;
+                               }
+                               $form->field(name => "editcontent", value => $content,
+                                       force => 1);
+                       }
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title(sprintf(gettext("editing %s"), pagetitle($page)));
+               }
+               
+               showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+       }
+       else {
+               # save page
+               check_canedit($page, $q, $session);
+               checksessionexpiry($q, $session, $q->param('sid'));
+
+               my $exists=-e "$config{srcdir}/$file";
+
+               if ($form->field("do") ne "create" && ! $exists &&
+                   ! defined srcfile($file, 1)) {
+                       $form->tmpl_param("message", template("editpagegone.tmpl")->output);
+                       $form->field(name => "do", value => "create", force => 1);
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title(sprintf(gettext("editing %s"), $page));
+                       showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+                       exit;
+               }
+               elsif ($form->field("do") eq "create" && $exists) {
+                       $form->tmpl_param("message", template("editcreationconflict.tmpl")->output);
+                       $form->field(name => "do", value => "edit", force => 1);
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title(sprintf(gettext("editing %s"), $page));
+                       $form->field("editcontent", 
+                               value => readfile("$config{srcdir}/$file").
+                                        "\n\n\n".$form->field("editcontent"),
+                               force => 1);
+                       showform($form, \@buttons, $session, $q, forcebaseurl => $baseurl);
+                       exit;
+               }
+                       
+               my $message="";
+               if (defined $form->field('comments') &&
+                   length $form->field('comments')) {
+                       $message=$form->field('comments');
+               }
+               
+               my $content=$form->field('editcontent');
+               check_content(content => $content, page => $page,
+                       cgi => $q, session => $session,
+                       subject => $message);
+               run_hooks(editcontent => sub {
+                       $content=shift->(
+                               content => $content,
+                               page => $page,
+                               cgi => $q,
+                               session => $session,
+                       );
+               });
+               $content=~s/\r\n/\n/g;
+               $content=~s/\r/\n/g;
+               $content.="\n" if $content !~ /\n$/;
+
+               $config{cgi}=0; # avoid cgi error message
+               eval { writefile($file, $config{srcdir}, $content) };
+               $config{cgi}=1;
+               if ($@) {
+                       $form->field(name => "rcsinfo", value => rcs_prepedit($file),
+                               force => 1);
+                       my $mtemplate=template("editfailedsave.tmpl");
+                       $mtemplate->param(error_message => $@);
+                       $form->tmpl_param("message", $mtemplate->output);
+                       $form->field("editcontent", value => $content, force => 1);
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title(sprintf(gettext("editing %s"), $page));
+                       showform($form, \@buttons, $session, $q,
+                               forcebaseurl => $baseurl);
+                       exit;
+               }
+               
+               my $conflict;
+               if ($config{rcs}) {
+                       if (! $exists) {
+                               rcs_add($file);
+                       }
+
+                       # Prevent deadlock with post-commit hook by
+                       # signaling to it that it should not try to
+                       # do anything.
+                       disable_commit_hook();
+                       $conflict=rcs_commit($file, $message,
+                               $form->field("rcsinfo"),
+                               $session->param("name"), $ENV{REMOTE_ADDR});
+                       enable_commit_hook();
+                       rcs_update();
+               }
+               
+               # Refresh even if there was a conflict, since other changes
+               # may have been committed while the post-commit hook was
+               # disabled.
+               require IkiWiki::Render;
+               refresh();
+               saveindex();
+
+               if (defined $conflict) {
+                       $form->field(name => "rcsinfo", value => rcs_prepedit($file),
+                               force => 1);
+                       $form->tmpl_param("message", template("editconflict.tmpl")->output);
+                       $form->field("editcontent", value => $conflict, force => 1);
+                       $form->field("do", "edit", force => 1);
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title(sprintf(gettext("editing %s"), $page));
+                       showform($form, \@buttons, $session, $q,
+                               forcebaseurl => $baseurl);
+               }
+               else {
+                       # The trailing question mark tries to avoid broken
+                       # caches and get the most recent version of the page.
+                       redirect($q, urlto($page, undef, 1)."?updated");
+               }
+       }
+
+       exit;
+}
+
+1
index 76c1cd42aed37b24ff3f313a50c0d49cd4112aa7..0bafc95d06d854b860e566a8c14134119d51db17 100644 (file)
@@ -3,20 +3,30 @@ package IkiWiki::Plugin::edittemplate;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Template;
 use Encode;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "edittemplate",
+               call => \&getsetup);
        hook(type => "needsbuild", id => "edittemplate",
                call => \&needsbuild);
        hook(type => "preprocess", id => "edittemplate",
                call => \&preprocess);
        hook(type => "formbuilder", id => "edittemplate",
                call => \&formbuilder);
-} #}}}
+}
 
-sub needsbuild (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub needsbuild (@) {
        my $needsbuild=shift;
 
        foreach my $page (keys %pagestate) {
@@ -30,31 +40,37 @@ sub needsbuild (@) { #{{{
                        }
                }
        }
-} #}}}
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
         my %params=@_;
 
        return "" if $params{page} ne $params{destpage};
 
        if (! exists $params{template} || ! length($params{template})) {
-               return "[[meta ".gettext("template not specified")."]]";
+               error gettext("template not specified")
        }
        if (! exists $params{match} || ! length($params{match})) {
-               return "[[meta ".gettext("match not specified")."]]";
+               error gettext("match not specified")
        }
 
-       $pagestate{$params{page}}{edittemplate}{$params{match}}=$params{template};
+       my $link=linkpage($params{template});
+       $pagestate{$params{page}}{edittemplate}{$params{match}}=$link;
 
+       return "" if ($params{silent} && IkiWiki::yesno($params{silent}));
+       add_depends($params{page}, $link);
        return sprintf(gettext("edittemplate %s registered for %s"),
-               $params{template}, $params{match});
-} # }}}
+               htmllink($params{page}, $params{destpage}, $link),
+               $params{match});
+}
 
-sub formbuilder (@) { #{{{
+sub formbuilder (@) {
        my %params=@_;
        my $form=$params{form};
 
-       return if $form->field("do") ne "create";
+       return if $form->field("do") ne "create" ||
+               (defined $form->field("editcontent") && length $form->field("editcontent"));
+       
        my $page=$form->field("page");
        
        # The tricky bit here is that $page is probably just the base
@@ -75,17 +91,21 @@ sub formbuilder (@) { #{{{
                        if (exists $pagestate{$registering_page}{edittemplate}) {
                                foreach my $pagespec (sort keys %{$pagestate{$registering_page}{edittemplate}}) {
                                        if (pagespec_match($p, $pagespec, location => $registering_page)) {
+                                               my $template=$pagestate{$registering_page}{edittemplate}{$pagespec};
                                                $form->field(name => "editcontent",
-                                                        value => filltemplate($pagestate{$registering_page}{edittemplate}{$pagespec}, $page));
+                                                        value =>  filltemplate($template, $page));
+                                               $form->field(name => "type",
+                                                        value => pagetype($pagesources{$template}))
+                                                               if $pagesources{$template};
                                                return;
                                        }
                                }
                        }
                }
        }
-} #}}}
+}
 
-sub filltemplate ($$) { #{{{
+sub filltemplate ($$) {
        my $template_page=shift;
        my $page=shift;
 
@@ -108,12 +128,14 @@ sub filltemplate ($$) { #{{{
                );
        };
        if ($@) {
-               return "[[pagetemplate ".gettext("failed to process")." $@]]";
+               # Indicate that the earlier preprocessor directive set 
+               # up a template that doesn't work.
+               return "[[!pagetemplate ".gettext("failed to process")." $@]]";
        }
 
        $template->param(name => $page);
 
        return $template->output;
-} #}}}
+}
 
 1
index 4fc91d978a5295473fac4135270c14027304ad2b..a7d38358fe3ab4177c2cf6a7817f3e037f2c8e4a 100644 (file)
@@ -3,7 +3,7 @@ package IkiWiki::Plugin::embed;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my $attribr=qr/[^<>"]+/;
 
@@ -43,26 +43,35 @@ my $safehtml=qr{(
 
 my @embedded;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "embed", call => \&getsetup);
        hook(type => "filter", id => "embed", call => \&filter);
-} # }}}
+}
 
-sub embed ($) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub embed ($) {
        hook(type => "format", id => "embed", call => \&format) unless @embedded;
        push @embedded, shift;
        return "<div class=\"embed$#embedded\"></div>";
-} #}}}
+}
 
-sub filter (@) { #{{{
+sub filter (@) {
        my %params=@_;
        $params{content} =~ s/$safehtml/embed($1)/eg;
        return $params{content};
-} # }}}
+}
 
-sub format (@) { #{{{
+sub format (@) {
         my %params=@_;
        $params{content} =~ s/<div class="embed(\d+)"><\/div>/$embedded[$1]/eg;
         return $params{content};
-} # }}}
+}
 
 1
index 204442c1e0b731db6d985cef61181e0c7b0fc424..0d292dfc2520e0020e5eee164084d4ab93751a10 100644 (file)
@@ -1,12 +1,12 @@
 #!/usr/bin/perl
 # Support for external plugins written in other languages.
-# Communication via XML RPC a pipe.
+# Communication via XML RPC to a pipe.
 # See externaldemo for an example of a plugin that uses this.
 package IkiWiki::Plugin::external;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use RPC::XML;
 use RPC::XML::Parser;
 use IPC::Open2;
@@ -14,7 +14,7 @@ use IO::Handle;
 
 my %plugins;
 
-sub import { #{{{
+sub import {
        my $self=shift;
        my $plugin=shift;
        return unless defined $plugin;
@@ -32,17 +32,17 @@ sub import { #{{{
        $RPC::XML::ENCODING="utf-8";
 
        rpc_call($plugins{$plugin}, "import");
-} #}}}
+}
 
-sub rpc_write ($$) { #{{{
+sub rpc_write ($$) {
        my $fh=shift;
        my $string=shift;
 
        $fh->print($string."\n");
        $fh->flush;
-} #}}}
+}
 
-sub rpc_call ($$;@) { #{{{
+sub rpc_call ($$;@) {
        my $plugin=shift;
        my $command=shift;
 
@@ -131,12 +131,12 @@ sub rpc_call ($$;@) { #{{{
        }
 
        return undef;
-} #}}}
+}
 
 package IkiWiki::RPC::XML;
 use Memoize;
 
-sub getvar ($$$) { #{{{
+sub getvar ($$$) {
        my $plugin=shift;
        my $varname="IkiWiki::".shift;
        my $key=shift;
@@ -145,9 +145,9 @@ sub getvar ($$$) { #{{{
        my $ret=$varname->{$key};
        use strict 'refs';
        return $ret;
-} #}}}
+}
 
-sub setvar ($$$;@) { #{{{
+sub setvar ($$$;@) {
        my $plugin=shift;
        my $varname="IkiWiki::".shift;
        my $key=shift;
@@ -157,18 +157,18 @@ sub setvar ($$$;@) { #{{{
        my $ret=$varname->{$key}=$value;
        use strict 'refs';
        return $ret;
-} #}}}
+}
 
-sub getstate ($$$$) { #{{{
+sub getstate ($$$$) {
        my $plugin=shift;
        my $page=shift;
        my $id=shift;
        my $key=shift;
 
        return $IkiWiki::pagestate{$page}{$id}{$key};
-} #}}}
+}
 
-sub setstate ($$$$;@) { #{{{
+sub setstate ($$$$;@) {
        my $plugin=shift;
        my $page=shift;
        my $id=shift;
@@ -176,22 +176,22 @@ sub setstate ($$$$;@) { #{{{
        my $value=shift;
 
        return $IkiWiki::pagestate{$page}{$id}{$key}=$value;
-} #}}}
+}
 
-sub getargv ($) { #{{{
+sub getargv ($) {
        my $plugin=shift;
 
        return \@ARGV;
-} #}}}
+}
 
-sub setargv ($@) { #{{{
+sub setargv ($@) {
        my $plugin=shift;
        my $array=shift;
 
        @ARGV=@$array;
-} #}}}
+}
 
-sub inject ($@) { #{{{
+sub inject ($@) {
        # Bind a given perl function name to a particular RPC request.
        my $plugin=shift;
        my %params=@_;
@@ -202,12 +202,20 @@ sub inject ($@) { #{{{
        my $sub = sub {
                IkiWiki::Plugin::external::rpc_call($plugin, $params{call}, @_)
        };
+       $sub=memoize($sub) if $params{memoize};
+
+       # This will add it to the symbol table even if not present.
+       no warnings;
        eval qq{*$params{name}=\$sub};
-       memoize($params{name}) if $params{memoize};
+       use warnings;
+
+       # This will ensure that everywhere it was exported to sees
+       # the injected version.
+       IkiWiki::inject(name => $params{name}, call => $sub);
        return 1;
-} #}}}
+}
 
-sub hook ($@) { #{{{
+sub hook ($@) {
        # the call parameter is a function name to call, since XML RPC
        # cannot pass a function reference
        my $plugin=shift;
@@ -217,16 +225,18 @@ sub hook ($@) { #{{{
        delete $params{call};
 
        IkiWiki::hook(%params, call => sub {
-               my $ret=IkiWiki::Plugin::external::rpc_call($plugin, $callback, @_);
-               return $ret;
+               IkiWiki::Plugin::external::rpc_call($plugin, $callback, @_);
        });
-} #}}}
+}
 
-sub pagespec_match ($@) { #{{{
-       # convert pagespec_match's return object into a XML RPC boolean
+sub pagespec_match ($@) {
+       # convert return object into a XML RPC boolean
        my $plugin=shift;
+       my $page=shift;
+       my $spec=shift;
 
-       return RPC::XML::boolean->new(0 + IkiWiki::pagespec_march(@_));
-} #}}}
+       return RPC::XML::boolean->new(0 + IkiWiki::pagespec_match(
+                       $page, $spec, @_));
+}
 
 1
index 7169c58c342f9ef97defe60a1004aebab8f98555..6060914c5a59a6736971f5557d97b3efc992d953 100644 (file)
@@ -5,13 +5,22 @@ package IkiWiki::Plugin::favicon;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "favicon", call => \&getsetup);
        hook(type => "pagetemplate", id => "favicon", call => \&pagetemplate);
-} # }}}
+}
 
-sub pagetemplate (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub pagetemplate (@) {
        my %params=@_;
 
        my $template=$params{template};
@@ -19,6 +28,6 @@ sub pagetemplate (@) { #{{{
        if ($template->query(name => "favicon")) {
                $template->param(favicon => "favicon.ico");
        }
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/filecheck.pm b/IkiWiki/Plugin/filecheck.pm
new file mode 100644 (file)
index 0000000..01d4909
--- /dev/null
@@ -0,0 +1,196 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::filecheck;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+my %units=( #{{{       # size in bytes
+       B               => 1,
+       byte            => 1,
+       KB              => 2 ** 10,
+       kilobyte        => 2 ** 10,
+       K               => 2 ** 10,
+       KB              => 2 ** 10,
+       kilobyte        => 2 ** 10,
+       M               => 2 ** 20,
+       MB              => 2 ** 20,
+       megabyte        => 2 ** 20,
+       G               => 2 ** 30,
+       GB              => 2 ** 30,
+       gigabyte        => 2 ** 30,
+       T               => 2 ** 40,
+       TB              => 2 ** 40,
+       terabyte        => 2 ** 40,
+       P               => 2 ** 50,
+       PB              => 2 ** 50,
+       petabyte        => 2 ** 50,
+       E               => 2 ** 60,
+       EB              => 2 ** 60,
+       exabyte         => 2 ** 60,
+       Z               => 2 ** 70,
+       ZB              => 2 ** 70,
+       zettabyte       => 2 ** 70,
+       Y               => 2 ** 80,
+       YB              => 2 ** 80,
+       yottabyte       => 2 ** 80,
+       # ikiwiki, if you find you need larger data quantities, either modify
+       # yourself to add them, or travel back in time to 2008 and kill me.
+       #   -- Joey
+);
+
+sub parsesize ($) {
+       my $size=shift;
+
+       no warnings;
+       my $base=$size+0; # force to number
+       use warnings;
+       foreach my $unit (sort keys %units) {
+               if ($size=~/[0-9\s]\Q$unit\E$/i) {
+                       return $base * $units{$unit};
+               }
+       }
+       return $base;
+}
+
+# This is provided for other plugins that want to convert back the other way.
+sub humansize ($) {
+       my $size=shift;
+
+       foreach my $unit (reverse sort { $units{$a} <=> $units{$b} || $b cmp $a } keys %units) {
+               if ($size / $units{$unit} > 0.25) {
+                       return (int($size / $units{$unit} * 10)/10).$unit;
+               }
+       }
+       return $size; # near zero, or negative
+}
+
+package IkiWiki::PageSpec;
+
+sub match_maxsize ($$;@) {
+       my $page=shift;
+       my $maxsize=eval{IkiWiki::Plugin::filecheck::parsesize(shift)};
+       if ($@) {
+               return IkiWiki::ErrorReason->new("unable to parse maxsize (or number too large)");
+       }
+
+       my %params=@_;
+       my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+       if (! defined $file) {
+               return IkiWiki::ErrorReason->new("no file specified");
+       }
+
+       if (-s $file > $maxsize) {
+               return IkiWiki::FailReason->new("file too large (".(-s $file)." >  $maxsize)");
+       }
+       else {
+               return IkiWiki::SuccessReason->new("file not too large");
+       }
+}
+
+sub match_minsize ($$;@) {
+       my $page=shift;
+       my $minsize=eval{IkiWiki::Plugin::filecheck::parsesize(shift)};
+       if ($@) {
+               return IkiWiki::ErrorReason->new("unable to parse minsize (or number too large)");
+       }
+
+       my %params=@_;
+       my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+       if (! defined $file) {
+               return IkiWiki::ErrorReason->new("no file specified");
+       }
+
+       if (-s $file < $minsize) {
+               return IkiWiki::FailReason->new("file too small");
+       }
+       else {
+               return IkiWiki::SuccessReason->new("file not too small");
+       }
+}
+
+sub match_mimetype ($$;@) {
+       my $page=shift;
+       my $wanted=shift;
+
+       my %params=@_;
+       my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+       if (! defined $file) {
+               return IkiWiki::ErrorReason->new("no file specified");
+       }
+
+       # Use ::magic to get the mime type, the idea is to only trust
+       # data obtained by examining the actual file contents.
+       eval q{use File::MimeInfo::Magic};
+       if ($@) {
+               return IkiWiki::ErrorReason->new("failed to load File::MimeInfo::Magic ($@); cannot check MIME type");
+       }
+       my $mimetype=File::MimeInfo::Magic::magic($file);
+       if (! defined $mimetype) {
+               $mimetype=File::MimeInfo::Magic::default($file);
+               if (! defined $mimetype) {
+                       $mimetype="unknown";
+               }
+       }
+
+       my $regexp=IkiWiki::glob2re($wanted);
+       if ($mimetype!~/^$regexp$/i) {
+               return IkiWiki::FailReason->new("file MIME type is $mimetype, not $wanted");
+       }
+       else {
+               return IkiWiki::SuccessReason->new("file MIME type is $mimetype");
+       }
+}
+
+sub match_virusfree ($$;@) {
+       my $page=shift;
+       my $wanted=shift;
+
+       my %params=@_;
+       my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
+       if (! defined $file) {
+               return IkiWiki::ErrorReason->new("no file specified");
+       }
+
+       if (! exists $IkiWiki::config{virus_checker} ||
+           ! length $IkiWiki::config{virus_checker}) {
+               return IkiWiki::ErrorReason->new("no virus_checker configured");
+       }
+
+       # The file needs to be fed into the virus checker on stdin,
+       # because the file is not world-readable, and if clamdscan is
+       # used, clamd would fail to read it.
+       eval q{use IPC::Open2};
+       error($@) if $@;
+       open (IN, "<", $file) || return IkiWiki::ErrorReason->new("failed to read file");
+       binmode(IN);
+       my $sigpipe=0;
+       $SIG{PIPE} = sub { $sigpipe=1 };
+       my $pid=open2(\*CHECKER_OUT, "<&IN", $IkiWiki::config{virus_checker}); 
+       my $reason=<CHECKER_OUT>;
+       chomp $reason;
+       1 while (<CHECKER_OUT>);
+       close(CHECKER_OUT);
+       waitpid $pid, 0;
+       $SIG{PIPE}="DEFAULT";
+       if ($sigpipe || $?) {
+               if (! length $reason) {
+                       $reason="virus checker $IkiWiki::config{virus_checker}; failed with no output";
+               }
+               return IkiWiki::FailReason->new("file seems to contain a virus ($reason)");
+       }
+       else {
+               return IkiWiki::SuccessReason->new("file seems virusfree ($reason)");
+       }
+}
+
+sub match_ispage ($$;@) {
+       my $filename=shift;
+
+       if (defined IkiWiki::pagetype($filename)) {
+               return IkiWiki::SuccessReason->new("file is a wiki page");
+       }
+       else {
+               return IkiWiki::FailReason->new("file is not a wiki page");
+       }
+}
diff --git a/IkiWiki/Plugin/format.pm b/IkiWiki/Plugin/format.pm
new file mode 100644 (file)
index 0000000..1513cbe
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::format;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "preprocess", id => "format", call => \&preprocess);
+}
+
+sub preprocess (@) {
+       my %params=@_;
+       my $format=shift;
+       shift;
+       my $text=IkiWiki::preprocess($params{page}, $params{destpage}, shift);
+       shift;
+
+       if (! defined $format || ! defined $text) {
+               error(gettext("must specify format and text"));
+       }
+       elsif (exists $IkiWiki::hooks{htmlize}{$format}) {
+               return IkiWiki::htmlize($params{page}, $params{destpage},
+                                       $format, $text);
+       }
+       else {
+               # Other plugins can register htmlizefallback
+               # hooks to add support for page types
+               # not suitable for htmlize. Try them until
+               # one succeeds.
+               my $ret;
+               IkiWiki::run_hooks(htmlizefallback => sub {
+                       $ret=shift->($format, $text)
+                               unless defined $ret;
+               });
+               return $ret if defined $ret;
+
+               error(sprintf(gettext("unsupported page format %s"), $format));
+       }
+}
+
+1
index a3b13f687dac48aa37eee64ddf2eb7035dbac064..17e57dea14fccb4c3f9e1c21a5926ef4880033cd 100644 (file)
@@ -4,22 +4,31 @@ package IkiWiki::Plugin::fortune;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "fortune", call => \&getsetup);
        hook(type => "preprocess", id => "fortune", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        $ENV{PATH}="$ENV{PATH}:/usr/games:/usr/local/games";
        my $f = `fortune 2>/dev/null`;
 
        if ($?) {
-               return "[[".gettext("fortune failed")."]]";
+               error gettext("fortune failed");
        }
        else {
                return "<pre>$f</pre>\n";
        }
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/getsource.pm b/IkiWiki/Plugin/getsource.pm
new file mode 100644 (file)
index 0000000..ae9ea3c
--- /dev/null
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::getsource;
+
+use warnings;
+use strict;
+use IkiWiki;
+use open qw{:utf8 :std};
+
+sub import {
+       hook(type => "getsetup", id => "getsource", call => \&getsetup);
+       hook(type => "pagetemplate", id => "getsource", call => \&pagetemplate);
+       hook(type => "cgi", id => "getsource", call => \&cgi_getsource);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               getsource_mimetype => {
+                       type => "string",
+                       example => "text/plain; charset=utf-8",
+                       description => "Mime type for returned source.",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub pagetemplate (@) {
+       my %params=@_;
+
+       my $page=$params{page};
+       my $template=$params{template};
+
+       if (length $config{cgiurl}) {
+               $template->param(getsourceurl => IkiWiki::cgiurl(do => "getsource", page => $page));
+               $template->param(have_actions => 1);
+       }
+}
+
+sub cgi_getsource ($) {
+       my $cgi=shift;
+
+       return unless defined $cgi->param('do') &&
+                     $cgi->param("do") eq "getsource";
+
+       IkiWiki::decode_cgi_utf8($cgi);
+
+       my $page=$cgi->param('page');
+
+       if (! defined $page || $page !~ /$config{wiki_file_regexp}/) {
+               error("invalid page parameter");
+       }
+
+       # For %pagesources.
+       IkiWiki::loadindex();
+
+       if (! exists $pagesources{$page}) {
+               IkiWiki::cgi_custom_failure(
+                       $cgi->header(-status => "404 Not Found"),
+                       IkiWiki::misctemplate(gettext("missing page"),
+                               "<p>".
+                               sprintf(gettext("The page %s does not exist."),
+                                       htmllink("", "", $page)).
+                               "</p>"));
+               exit;
+       }
+
+       if (! defined pagetype($pagesources{$page})) {
+               IkiWiki::cgi_custom_failure(
+                       $cgi->header(-status => "403 Forbidden"),
+                       IkiWiki::misctemplate(gettext("not a page"),
+                               "<p>".
+                               sprintf(gettext("%s is an attachment, not a page."),
+                                       htmllink("", "", $page)).
+                               "</p>"));
+               exit;
+       }
+
+       if (! $config{getsource_mimetype}) {
+               $config{getsource_mimetype} = "text/plain; charset=utf-8";
+       }
+
+       print "Content-Type: $config{getsource_mimetype}\r\n";
+       print ("\r\n");
+       print readfile(srcfile($pagesources{$page}));
+
+       exit 0;
+}
+
+1
diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm
new file mode 100644 (file)
index 0000000..68b114a
--- /dev/null
@@ -0,0 +1,698 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::git;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+use open qw{:utf8 :std};
+
+my $sha1_pattern     = qr/[0-9a-fA-F]{40}/; # pattern to validate Git sha1sums
+my $dummy_commit_msg = 'dummy commit';      # message to skip in recent changes
+my $no_chdir=0;
+
+sub import {
+       hook(type => "checkconfig", id => "git", call => \&checkconfig);
+       hook(type => "getsetup", id => "git", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+       hook(type => "rcs", id => "rcs_receive", call => \&rcs_receive);
+}
+
+sub checkconfig () {
+       if (! defined $config{gitorigin_branch}) {
+               $config{gitorigin_branch}="origin";
+       }
+       if (! defined $config{gitmaster_branch}) {
+               $config{gitmaster_branch}="master";
+       }
+       if (defined $config{git_wrapper} &&
+           length $config{git_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{git_wrapper},
+                       wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
+               };
+       }
+       if (defined $config{git_test_receive_wrapper} &&
+           length $config{git_test_receive_wrapper}) {
+               push @{$config{wrappers}}, {
+                       test_receive => 1,
+                       wrapper => $config{git_test_receive_wrapper},
+                       wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               git_wrapper => {
+                       type => "string",
+                       example => "/git/wiki.git/hooks/post-update",
+                       description => "git hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               git_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for git_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               git_test_receive_wrapper => {
+                       type => "string",
+                       example => "/git/wiki.git/hooks/pre-receive",
+                       description => "git pre-receive hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               untrusted_committers => {
+                       type => "string",
+                       example => [],
+                       description => "unix users whose commits should be checked by the pre-receive hook",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
+                       description => "gitweb url to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;f=[[file]];h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_commit]];hpb=[[sha1_parent]]",
+                       description => "gitweb url to show a diff ([[file]], [[sha1_to]], [[sha1_from]], [[sha1_commit]], and [[sha1_parent]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               gitorigin_branch => {
+                       type => "string",
+                       example => "origin",
+                       description => "where to pull and push changes (set to empty string to disable)",
+                       safe => 0, # paranoia
+                       rebuild => 0,
+               },
+               gitmaster_branch => {
+                       type => "string",
+                       example => "master",
+                       description => "branch that the wiki is stored in",
+                       safe => 0, # paranoia
+                       rebuild => 0,
+               },
+}
+
+sub safe_git (&@) {
+       # Start a child process safely without resorting /bin/sh.
+       # Return command output or success state (in scalar context).
+
+       my ($error_handler, @cmdline) = @_;
+
+       my $pid = open my $OUT, "-|";
+
+       error("Cannot fork: $!") if !defined $pid;
+
+       if (!$pid) {
+               # In child.
+               # Git commands want to be in wc.
+               if (! $no_chdir) {
+                       chdir $config{srcdir}
+                           or error("Cannot chdir to $config{srcdir}: $!");
+               }
+               exec @cmdline or error("Cannot exec '@cmdline': $!");
+       }
+       # In parent.
+
+       # git output is probably utf-8 encoded, but may contain
+       # other encodings or invalidly encoded stuff. So do not rely
+       # on the normal utf-8 IO layer, decode it by hand.
+       binmode($OUT);
+
+       my @lines;
+       while (<$OUT>) {
+               $_=decode_utf8($_, 0);
+
+               chomp;
+
+               push @lines, $_;
+       }
+
+       close $OUT;
+
+       $error_handler->("'@cmdline' failed: $!") if $? && $error_handler;
+
+       return wantarray ? @lines : ($? == 0);
+}
+# Convenient wrappers.
+sub run_or_die ($@) { safe_git(\&error, @_) }
+sub run_or_cry ($@) { safe_git(sub { warn @_ },  @_) }
+sub run_or_non ($@) { safe_git(undef,            @_) }
+
+
+sub merge_past ($$$) {
+       # Unlike with Subversion, Git cannot make a 'svn merge -rN:M file'.
+       # Git merge commands work with the committed changes, except in the
+       # implicit case of '-m' of git checkout(1).  So we should invent a
+       # kludge here.  In principle, we need to create a throw-away branch
+       # in preparing for the merge itself.  Since branches are cheap (and
+       # branching is fast), this shouldn't cost high.
+       #
+       # The main problem is the presence of _uncommitted_ local changes.  One
+       # possible approach to get rid of this situation could be that we first
+       # make a temporary commit in the master branch and later restore the
+       # initial state (this is possible since Git has the ability to undo a
+       # commit, i.e. 'git reset --soft HEAD^').  The method can be summarized
+       # as follows:
+       #
+       #       - create a diff of HEAD:current-sha1
+       #       - dummy commit
+       #       - create a dummy branch and switch to it
+       #       - rewind to past (reset --hard to the current-sha1)
+       #       - apply the diff and commit
+       #       - switch to master and do the merge with the dummy branch
+       #       - make a soft reset (undo the last commit of master)
+       #
+       # The above method has some drawbacks: (1) it needs a redundant commit
+       # just to get rid of local changes, (2) somewhat slow because of the
+       # required system forks.  Until someone points a more straight method
+       # (which I would be grateful) I have implemented an alternative method.
+       # In this approach, we hide all the modified files from Git by renaming
+       # them (using the 'rename' builtin) and later restore those files in
+       # the throw-away branch (that is, we put the files themselves instead
+       # of applying a patch).
+
+       my ($sha1, $file, $message) = @_;
+
+       my @undo;      # undo stack for cleanup in case of an error
+       my $conflict;  # file content with conflict markers
+
+       eval {
+               # Hide local changes from Git by renaming the modified file.
+               # Relative paths must be converted to absolute for renaming.
+               my ($target, $hidden) = (
+                   "$config{srcdir}/${file}", "$config{srcdir}/${file}.${sha1}"
+               );
+               rename($target, $hidden)
+                   or error("rename '$target' to '$hidden' failed: $!");
+               # Ensure to restore the renamed file on error.
+               push @undo, sub {
+                       return if ! -e "$hidden"; # already renamed
+                       rename($hidden, $target)
+                           or warn "rename '$hidden' to '$target' failed: $!";
+               };
+
+               my $branch = "throw_away_${sha1}"; # supposed to be unique
+
+               # Create a throw-away branch and rewind backward.
+               push @undo, sub { run_or_cry('git', 'branch', '-D', $branch) };
+               run_or_die('git', 'branch', $branch, $sha1);
+
+               # Switch to throw-away branch for the merge operation.
+               push @undo, sub {
+                       if (!run_or_cry('git', 'checkout', $config{gitmaster_branch})) {
+                               run_or_cry('git', 'checkout','-f',$config{gitmaster_branch});
+                       }
+               };
+               run_or_die('git', 'checkout', $branch);
+
+               # Put the modified file in _this_ branch.
+               rename($hidden, $target)
+                   or error("rename '$hidden' to '$target' failed: $!");
+
+               # _Silently_ commit all modifications in the current branch.
+               run_or_non('git', 'commit', '-m', $message, '-a');
+               # ... and re-switch to master.
+               run_or_die('git', 'checkout', $config{gitmaster_branch});
+
+               # Attempt to merge without complaining.
+               if (!run_or_non('git', 'pull', '--no-commit', '.', $branch)) {
+                       $conflict = readfile($target);
+                       run_or_die('git', 'reset', '--hard');
+               }
+       };
+       my $failure = $@;
+
+       # Process undo stack (in reverse order).  By policy cleanup
+       # actions should normally print a warning on failure.
+       while (my $handle = pop @undo) {
+               $handle->();
+       }
+
+       error("Git merge failed!\n$failure\n") if $failure;
+
+       return $conflict;
+}
+
+sub parse_diff_tree ($@) {
+       # Parse the raw diff tree chunk and return the info hash.
+       # See git-diff-tree(1) for the syntax.
+
+       my ($prefix, $dt_ref) = @_;
+
+       # End of stream?
+       return if !defined @{ $dt_ref } ||
+                 !defined @{ $dt_ref }[0] || !length @{ $dt_ref }[0];
+
+       my %ci;
+       # Header line.
+       while (my $line = shift @{ $dt_ref }) {
+               return if $line !~ m/^(.+) ($sha1_pattern)/;
+
+               my $sha1 = $2;
+               $ci{'sha1'} = $sha1;
+               last;
+       }
+
+       # Identification lines for the commit.
+       while (my $line = shift @{ $dt_ref }) {
+               # Regexps are semi-stolen from gitweb.cgi.
+               if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
+                       $ci{'tree'} = $1;
+               }
+               elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) {
+                       # XXX: collecting in reverse order
+                       push @{ $ci{'parents'} }, $1;
+               }
+               elsif ($line =~ m/^(author|committer) (.*) ([0-9]+) (.*)$/) {
+                       my ($who, $name, $epoch, $tz) =
+                          ($1,   $2,    $3,     $4 );
+
+                       $ci{  $who          } = $name;
+                       $ci{ "${who}_epoch" } = $epoch;
+                       $ci{ "${who}_tz"    } = $tz;
+
+                       if ($name =~ m/^[^<]+\s+<([^@>]+)/) {
+                               $ci{"${who}_username"} = $1;
+                       }
+                       elsif ($name =~ m/^([^<]+)\s+<>$/) {
+                               $ci{"${who}_username"} = $1;
+                       }
+                       else {
+                               $ci{"${who}_username"} = $name;
+                       }
+               }
+               elsif ($line =~ m/^$/) {
+                       # Trailing empty line signals next section.
+                       last;
+               }
+       }
+
+       debug("No 'tree' seen in diff-tree output") if !defined $ci{'tree'};
+       
+       if (defined $ci{'parents'}) {
+               $ci{'parent'} = @{ $ci{'parents'} }[0];
+       }
+       else {
+               $ci{'parent'} = 0 x 40;
+       }
+
+       # Commit message (optional).
+       while ($dt_ref->[0] =~ /^    /) {
+               my $line = shift @{ $dt_ref };
+               $line =~ s/^    //;
+               push @{ $ci{'comment'} }, $line;
+       }
+       shift @{ $dt_ref } if $dt_ref->[0] =~ /^$/;
+
+       # Modified files.
+       while (my $line = shift @{ $dt_ref }) {
+               if ($line =~ m{^
+                       (:+)       # number of parents
+                       ([^\t]+)\t # modes, sha1, status
+                       (.*)       # file names
+               $}xo) {
+                       my $num_parents = length $1;
+                       my @tmp = split(" ", $2);
+                       my ($file, $file_to) = split("\t", $3);
+                       my @mode_from = splice(@tmp, 0, $num_parents);
+                       my $mode_to = shift(@tmp);
+                       my @sha1_from = splice(@tmp, 0, $num_parents);
+                       my $sha1_to = shift(@tmp);
+                       my $status = shift(@tmp);
+
+                       # git does not output utf-8 filenames, but instead
+                       # double-quotes them with the utf-8 characters
+                       # escaped as \nnn\nnn.
+                       if ($file =~ m/^"(.*)"$/) {
+                               ($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg;
+                       }
+                       $file =~ s/^\Q$prefix\E//;
+                       if (length $file) {
+                               push @{ $ci{'details'} }, {
+                                       'file'      => decode("utf8", $file),
+                                       'sha1_from' => $sha1_from[0],
+                                       'sha1_to'   => $sha1_to,
+                                       'mode_from' => $mode_from[0],
+                                       'mode_to'   => $mode_to,
+                                       'status'    => $status,
+                               };
+                       }
+                       next;
+               };
+               last;
+       }
+
+       return \%ci;
+}
+
+sub git_commit_info ($;$) {
+       # Return an array of commit info hashes of num commits
+       # starting from the given sha1sum.
+       my ($sha1, $num) = @_;
+
+       my @opts;
+       push @opts, "--max-count=$num" if defined $num;
+
+       my @raw_lines = run_or_die('git', 'log', @opts,
+               '--pretty=raw', '--raw', '--abbrev=40', '--always', '-c',
+               '-r', $sha1, '--', '.');
+       my ($prefix) = run_or_die('git', 'rev-parse', '--show-prefix');
+
+       my @ci;
+       while (my $parsed = parse_diff_tree(($prefix or ""), \@raw_lines)) {
+               push @ci, $parsed;
+       }
+
+       warn "Cannot parse commit info for '$sha1' commit" if !@ci;
+
+       return wantarray ? @ci : $ci[0];
+}
+
+sub git_sha1 (;$) {
+       # Return head sha1sum (of given file).
+       my $file = shift || q{--};
+
+       # Ignore error since a non-existing file might be given.
+       my ($sha1) = run_or_non('git', 'rev-list', '--max-count=1', 'HEAD',
+               '--', $file);
+       if ($sha1) {
+               ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
+       } else { debug("Empty sha1sum for '$file'.") }
+       return defined $sha1 ? $sha1 : q{};
+}
+
+sub rcs_update () {
+       # Update working directory.
+
+       if (length $config{gitorigin_branch}) {
+               run_or_cry('git', 'pull', $config{gitorigin_branch});
+       }
+}
+
+sub rcs_prepedit ($) {
+       # Return the commit sha1sum of the file when editing begins.
+       # This will be later used in rcs_commit if a merge is required.
+       my ($file) = @_;
+
+       return git_sha1($file);
+}
+
+sub rcs_commit ($$$;$$) {
+       # Try to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on
+       # failure.
+
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+
+       # Check to see if the page has been changed by someone else since
+       # rcs_prepedit was called.
+       my $cur    = git_sha1($file);
+       my ($prev) = $rcstoken =~ /^($sha1_pattern)$/; # untaint
+
+       if (defined $cur && defined $prev && $cur ne $prev) {
+               my $conflict = merge_past($prev, $file, $dummy_commit_msg);
+               return $conflict if defined $conflict;
+       }
+
+       rcs_add($file); 
+       return rcs_commit_staged($message, $user, $ipaddr);
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+
+       # Set the commit author and email to the web committer.
+       my %env=%ENV;
+       if (defined $user || defined $ipaddr) {
+               my $u=encode_utf8(defined $user ? $user : $ipaddr);
+               $ENV{GIT_AUTHOR_NAME}=$u;
+               $ENV{GIT_AUTHOR_EMAIL}="$u\@web";
+       }
+
+       $message = IkiWiki::possibly_foolish_untaint($message);
+       my @opts;
+       if ($message !~ /\S/) {
+               # Force git to allow empty commit messages.
+               # (If this version of git supports it.)
+               my ($version)=`git --version` =~ /git version (.*)/;
+               if ($version ge "1.5.4") {
+                       push @opts, '--cleanup=verbatim';
+               }
+               else {
+                       $message.=".";
+               }
+       }
+       push @opts, '-q';
+       # git commit returns non-zero if file has not been really changed.
+       # so we should ignore its exit status (hence run_or_non).
+       if (run_or_non('git', 'commit', @opts, '-m', $message)) {
+               if (length $config{gitorigin_branch}) {
+                       run_or_cry('git', 'push', $config{gitorigin_branch});
+               }
+       }
+       
+       %ENV=%env;
+       return undef; # success
+}
+
+sub rcs_add ($) {
+       # Add file to archive.
+
+       my ($file) = @_;
+
+       run_or_cry('git', 'add', $file);
+}
+
+sub rcs_remove ($) {
+       # Remove file from archive.
+
+       my ($file) = @_;
+
+       run_or_cry('git', 'rm', '-f', $file);
+}
+
+sub rcs_rename ($$) {
+       my ($src, $dest) = @_;
+
+       run_or_cry('git', 'mv', '-f', $src, $dest);
+}
+
+sub rcs_recentchanges ($) {
+       # List of recent changes.
+
+       my ($num) = @_;
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+
+       my @rets;
+       foreach my $ci (git_commit_info('HEAD', $num || 1)) {
+               # Skip redundant commits.
+               next if ($ci->{'comment'} && @{$ci->{'comment'}}[0] eq $dummy_commit_msg);
+
+               my ($sha1, $when) = (
+                       $ci->{'sha1'},
+                       $ci->{'author_epoch'}
+               );
+
+               my @pages;
+               foreach my $detail (@{ $ci->{'details'} }) {
+                       my $file = $detail->{'file'};
+
+                       my $diffurl = defined $config{'diffurl'} ? $config{'diffurl'} : "";
+                       $diffurl =~ s/\[\[file\]\]/$file/go;
+                       $diffurl =~ s/\[\[sha1_parent\]\]/$ci->{'parent'}/go;
+                       $diffurl =~ s/\[\[sha1_from\]\]/$detail->{'sha1_from'}/go;
+                       $diffurl =~ s/\[\[sha1_to\]\]/$detail->{'sha1_to'}/go;
+                       $diffurl =~ s/\[\[sha1_commit\]\]/$sha1/go;
+
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       };
+               }
+
+               my @messages;
+               my $pastblank=0;
+               foreach my $line (@{$ci->{'comment'}}) {
+                       $pastblank=1 if $line eq '';
+                       next if $pastblank && $line=~m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i;
+                       push @messages, { line => $line };
+               }
+
+               my $user=$ci->{'author_username'};
+               my $web_commit = ($ci->{'author'} =~ /\@web>/);
+               
+               # compatability code for old web commit messages
+               if (! $web_commit &&
+                     defined $messages[0] &&
+                     $messages[0]->{line} =~ m/$config{web_commit_regexp}/) {
+                       $user = defined $2 ? "$2" : "$3";
+                       $messages[0]->{line} = $4;
+                       $web_commit=1;
+               }
+
+               push @rets, {
+                       rev        => $sha1,
+                       user       => $user,
+                       committype => $web_commit ? "web" : "git",
+                       when       => $when,
+                       message    => [@messages],
+                       pages      => [@pages],
+               } if @pages;
+
+               last if @rets >= $num;
+       }
+
+       return @rets;
+}
+
+sub rcs_diff ($) {
+       my $rev=shift;
+       my ($sha1) = $rev =~ /^($sha1_pattern)$/; # untaint
+       my @lines;
+       foreach my $line (run_or_non("git", "show", $sha1)) {
+               if (@lines || $line=~/^diff --git/) {
+                       push @lines, $line."\n";
+               }
+       }
+       if (wantarray) {
+               return @lines;
+       }
+       else {
+               return join("", @lines);
+       }
+}
+
+sub rcs_getctime ($) {
+       my $file=shift;
+       # Remove srcdir prefix
+       $file =~ s/^\Q$config{srcdir}\E\/?//;
+
+       my @sha1s = run_or_non('git', 'rev-list', 'HEAD', '--', $file);
+       my $ci    = git_commit_info($sha1s[$#sha1s], 1);
+       my $ctime = $ci->{'author_epoch'};
+       debug("ctime for '$file': ". localtime($ctime));
+
+       return $ctime;
+}
+
+sub rcs_receive () {
+       # The wiki may not be the only thing in the git repo.
+       # Determine if it is in a subdirectory by examining the srcdir,
+       # and its parents, looking for the .git directory.
+       my $subdir="";
+       my $dir=$config{srcdir};
+       while (! -d "$dir/.git") {
+               $subdir=IkiWiki::basename($dir)."/".$subdir;
+               $dir=IkiWiki::dirname($dir);
+               if (! length $dir) {
+                       error("cannot determine root of git repo");
+               }
+       }
+
+       my @rets;
+       while (<>) {
+               chomp;
+               my ($oldrev, $newrev, $refname) = split(' ', $_, 3);
+               
+               # only allow changes to gitmaster_branch
+               if ($refname !~ /^refs\/heads\/\Q$config{gitmaster_branch}\E$/) {
+                       error sprintf(gettext("you are not allowed to change %s"), $refname);
+               }
+               
+               # Avoid chdir when running git here, because the changes
+               # are in the master git repo, not the srcdir repo.
+               # The pre-recieve hook already puts us in the right place.
+               $no_chdir=1;
+               my @changes=git_commit_info($oldrev."..".$newrev);
+               $no_chdir=0;
+
+               foreach my $ci (@changes) {
+                       foreach my $detail (@{ $ci->{'details'} }) {
+                               my $file = $detail->{'file'};
+
+                               # check that all changed files are in the
+                               # subdir
+                               if (length $subdir &&
+                                   ! ($file =~ s/^\Q$subdir\E//)) {
+                                       error sprintf(gettext("you are not allowed to change %s"), $file);
+                               }
+
+                               my ($action, $mode, $path);
+                               if ($detail->{'status'} =~ /^[M]+\d*$/) {
+                                       $action="change";
+                                       $mode=$detail->{'mode_to'};
+                               }
+                               elsif ($detail->{'status'} =~ /^[AM]+\d*$/) {
+                                       $action="add";
+                                       $mode=$detail->{'mode_to'};
+                               }
+                               elsif ($detail->{'status'} =~ /^[DAM]+\d*/) {
+                                       $action="remove";
+                                       $mode=$detail->{'mode_from'};
+                               }
+                               else {
+                                       error "unknown status ".$detail->{'status'};
+                               }
+                               
+                               # test that the file mode is ok
+                               if ($mode !~ /^100[64][64][64]$/) {
+                                       error sprintf(gettext("you cannot act on a file with mode %s"), $mode);
+                               }
+                               if ($action eq "change") {
+                                       if ($detail->{'mode_from'} ne $detail->{'mode_to'}) {
+                                               error gettext("you are not allowed to change file modes");
+                                       }
+                               }
+                               
+                               # extract attachment to temp file
+                               if (($action eq 'add' || $action eq 'change') &&
+                                    ! pagetype($file)) {
+                                       eval q{use File::Temp};
+                                       die $@ if $@;
+                                       my $fh;
+                                       ($fh, $path)=File::Temp::tempfile("XXXXXXXXXX", UNLINK => 1);
+                                       if (system("git show ".$detail->{sha1_to}." > '$path'") != 0) {
+                                               error("failed writing temp file");
+                                       }
+                               }
+
+                               push @rets, {
+                                       file => $file,
+                                       action => $action,
+                                       path => $path,
+                               };
+                       }
+               }
+       }
+
+       return reverse @rets;
+}
+
+1
index effbc7de9ff14759409ba36bf9b18d8230fe2123..451cd6f84fce568167c1d8ef045baba3513dcb80 100644 (file)
@@ -4,27 +4,40 @@ package IkiWiki::Plugin::goodstuff;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my @bundle=qw{
        brokenlinks
        img
        map
-       meta
+       more
        orphans
        pagecount
        pagestats
+       progress
        shortcut
        smiley
        tag
+       table
        template
        toc
        toggle
-       otl
+       repolist
 };
 
-sub import { #{{{
-       IkiWiki::loadplugin($_) foreach @bundle;
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "goodstuff", call => \&getsetup);
+       foreach my $plugin (@bundle) {
+               IkiWiki::loadplugin($plugin);
+       }
+}
+
+sub getsetup {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
 1
diff --git a/IkiWiki/Plugin/google.pm b/IkiWiki/Plugin/google.pm
new file mode 100644 (file)
index 0000000..1683220
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::google;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use URI;
+
+my $host;
+
+sub import {
+       hook(type => "getsetup", id => "google", call => \&getsetup);
+       hook(type => "checkconfig", id => "google", call => \&checkconfig);
+       hook(type => "pagetemplate", id => "google", call => \&pagetemplate);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig () {
+       if (! length $config{url}) {
+               error(sprintf(gettext("Must specify %s when using the %s plugin"), "url", 'google'));
+       }
+       my $uri=URI->new($config{url});
+       if (! $uri || ! defined $uri->host) {
+               error(gettext("Failed to parse url, cannot determine domain name"));
+       }
+       $host=$uri->host;
+}
+
+my $form;
+sub pagetemplate (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+
+       # Add search box to page header.
+       if ($template->query(name => "searchform")) {
+               if (! defined $form) {
+                       my $searchform = template("googleform.tmpl", blind_cache => 1);
+                       $searchform->param(sitefqdn => $host);
+                       $form=$searchform->output;
+               }
+
+               $template->param(searchform => $form);
+       }
+}
+
+1
diff --git a/IkiWiki/Plugin/googlecalendar.pm b/IkiWiki/Plugin/googlecalendar.pm
deleted file mode 100644 (file)
index c6409e5..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/perl
-package IkiWiki::Plugin::googlecalendar;
-
-use warnings;
-use strict;
-use IkiWiki 2.00;
-
-sub import { #{{{
-       hook(type => "preprocess", id => "googlecalendar",
-               call => \&preprocess);
-       hook(type => "format", id => "googlecalendar",
-               call => \&format);
-} # }}}
-
-sub preprocess (@) { #{{{
-       my %params=@_;
-
-       # Parse the html, looking for the url to embed for the calendar.
-       # Avoid XSS attacks..
-       my ($url)=$params{html}=~m#iframe\s+src="http://www\.google\.com/calendar/embed\?([^"<>]+)"#;
-       if (! defined $url || ! length $url) {
-               return "[[googlecalendar ".gettext("failed to find url in html")."]]";
-       }
-       my ($height)=$params{html}=~m#height="(\d+)"#;
-       my ($width)=$params{html}=~m#width="(\d+)"#;
-
-       return "<div class=\"googlecalendar\" src=\"$url\" height=\"$height\" width=\"$width\"></div>";
-} # }}}
-
-sub format (@) { #{{{
-        my %params=@_;
-
-       $params{content}=~s/<div class=\"googlecalendar" src="([^"]+)" height="([^"]+)" width="([^"]+)"><\/div>/gencal($1,$2,$3)/eg;
-
-        return $params{content};
-} # }}}
-
-sub gencal ($$$) { #{{{
-       my $url=shift;
-       my $height=shift;
-       my $width=shift;
-       return qq{<iframe src="http://www.google.com/calendar/embed?$url" style=" border-width:0 " width="$width" frameborder="0" height="$height"></iframe>};
-} #}}}
-
-1
diff --git a/IkiWiki/Plugin/goto.pm b/IkiWiki/Plugin/goto.pm
new file mode 100644 (file)
index 0000000..2e2dc04
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::goto;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "cgi", id => 'goto',  call => \&cgi);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               }
+}
+
+# cgi_goto(CGI, [page])
+# Redirect to a specified page, or display "not found". If not specified,
+# the page param from the CGI object is used.
+sub cgi_goto ($;$) {
+       my $q = shift;
+       my $page = shift;
+
+       if (!defined $page) {
+               $page = IkiWiki::decode_utf8($q->param("page"));
+
+               if (!defined $page) {
+                       error("missing page parameter");
+               }
+       }
+
+       # It's possible that $page is not a valid page name;
+       # if so attempt to turn it into one.
+       if ($page !~ /$config{wiki_file_regexp}/) {
+               $page=titlepage($page);
+       }
+
+       IkiWiki::loadindex();
+
+       # If the page is internal (like a comment), see if it has a
+       # permalink. Comments do.
+       if (IkiWiki::isinternal($page) &&
+           defined $pagestate{$page}{meta}{permalink}) {
+               IkiWiki::redirect($q, $pagestate{$page}{meta}{permalink});
+       }
+
+       my $link = bestlink("", $page);
+
+       if (! length $link) {
+               IkiWiki::cgi_custom_failure(
+                       $q->header(-status => "404 Not Found"),
+                       IkiWiki::misctemplate(gettext("missing page"),
+                               "<p>".
+                               sprintf(gettext("The page %s does not exist."),
+                                       htmllink("", "", $page)).
+                               "</p>")
+               )
+       }
+       else {
+               IkiWiki::redirect($q, urlto($link, undef, 1));
+       }
+
+       exit;
+}
+
+sub cgi ($) {
+       my $cgi=shift;
+       my $do = $cgi->param('do');
+
+       if (defined $do && ($do eq 'goto' || $do eq 'commenter' ||
+                              $do eq 'recentchanges_link')) {
+               # goto is the preferred name for this; recentchanges_link and
+               # commenter are for compatibility with any saved URLs
+               cgi_goto($cgi);
+       }
+}
+
+1;
index fe3559857a211807a133d9b95be05dafac5254b7..32e994d6b96c4d10dce2998db005ac22729a7ce5 100644 (file)
@@ -5,18 +5,27 @@ package IkiWiki::Plugin::graphviz;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use IPC::Open2;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "graphviz", call => \&getsetup);
        hook(type => "preprocess", id => "graph", call => \&graph);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
 my %graphviz_programs = (
        "dot" => 1, "neato" => 1, "fdp" => 1, "twopi" => 1, "circo" => 1
 );
 
-sub render_graph (\%) { #{{{
+sub render_graph (\%) {
        my %params = %{(shift)};
 
        my $src = "$params{type} g {\n";
@@ -36,7 +45,7 @@ sub render_graph (\%) { #{{{
 
        if (! -e "$config{destdir}/$dest") {
                my $pid;
-               my $sigpipe=0;;
+               my $sigpipe=0;
                $SIG{PIPE}=sub { $sigpipe=1 };
                $pid=open2(*IN, *OUT, "$params{prog} -Tpng");
 
@@ -55,7 +64,7 @@ sub render_graph (\%) { #{{{
 
                waitpid $pid, 0;
                $SIG{PIPE}="DEFAULT";
-               return  "[[graph ".gettext("failed to run graphviz")."]]" if ($sigpipe);
+               error gettext("failed to run graphviz") if $sigpipe;
 
                if (! $params{preview}) {
                        writefile($dest, $config{destdir}, $png, 1);
@@ -75,16 +84,16 @@ sub render_graph (\%) { #{{{
        else {
                return "<img src=\"".urlto($dest, $params{destpage})."\" />\n";
        }
-} #}}}
+}
 
-sub graph (@) { #{{{
+sub graph (@) {
        my %params=@_;
        $params{src} = "" unless defined $params{src};
        $params{type} = "digraph" unless defined $params{type};
        $params{prog} = "dot" unless defined $params{prog};
-       return "[[graph ".gettext("prog not a valid graphviz program")."]]" unless $graphviz_programs{$params{prog}};
+       error gettext("prog not a valid graphviz program") unless $graphviz_programs{$params{prog}};
 
        return render_graph(%params);
-} # }}}
+}
 
 1
index 5d5e8d5aaf93089fe84cc3774966f7a914aa516c..5a062a27606be6a0cb8d9a5a4f06ce8c0ec5cd6a 100644 (file)
@@ -4,13 +4,22 @@ package IkiWiki::Plugin::haiku;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "haiku", call => \&getsetup);
        hook(type => "preprocess", id => "haiku", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
 
        my $haiku;
@@ -45,6 +54,6 @@ sub preprocess (@) { #{{{
        $haiku=~s/\n/<br \/>\n/mg;
        
        return "\n\n<blockquote><p>$haiku</p></blockquote>\n\n";
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/highlight.pm b/IkiWiki/Plugin/highlight.pm
new file mode 100644 (file)
index 0000000..9bdde85
--- /dev/null
@@ -0,0 +1,144 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::highlight;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use Encode;
+
+# locations of highlight's files
+my $filetypes="/etc/highlight/filetypes.conf";
+my $langdefdir="/usr/share/highlight/langDefs";
+
+sub import {
+       hook(type => "getsetup", id => "highlight",  call => \&getsetup);
+       hook(type => "checkconfig", id => "highlight", call => \&checkconfig);
+       # this hook is used by the format plugin
+       hook(type => "htmlizefallback", id => "highlight", call =>
+               \&htmlizefallback);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+               tohighlight => {
+                       type => "string",
+                       example => ".c .h .cpp .pl .py Makefile:make",
+                       description => "types of source files to syntax highlight",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig () {
+       if (exists $config{tohighlight}) {
+               foreach my $file (split ' ', $config{tohighlight}) {
+                       my @opts = $file=~s/^\.// ?
+                               (keepextension => 1) :
+                               (noextension => 1);
+                       my $ext = $file=~s/:(.*)// ? $1 : $file;
+               
+                       my $langfile=ext2langfile($ext);
+                       if (! defined $langfile) {
+                               error(sprintf(gettext(
+                                       "tohighlight contains unknown file type '%s'"),
+                                       $ext));
+                       }
+       
+                       hook(
+                               type => "htmlize",
+                               id => $file,
+                               call => sub {
+                                       my %params=@_;
+                                       highlight($langfile, $params{content});
+                               },
+                               longname => sprintf(gettext("Source code: %s"), $file),
+                               @opts,
+                       );
+               }
+       }
+}
+
+sub htmlizefallback {
+       my $format=lc shift;
+       my $langfile=ext2langfile($format);
+
+       if (! defined $langfile) {
+               return;
+       }
+
+       return Encode::decode_utf8(highlight($langfile, shift));
+}
+
+my %ext2lang;
+my $filetypes_read=0;
+my %highlighters;
+
+# Parse highlight's config file to get extension => language mappings.
+sub read_filetypes () {
+       open (IN, $filetypes);
+       while (<IN>) {
+               chomp;
+               if (/^\$ext\((.*)\)=(.*)$/) {
+                       $ext2lang{$_}=$1 foreach $1, split ' ', $2;
+               }
+       }
+       close IN;
+       $filetypes_read=1;
+}
+
+
+# Given a filename extension, determines the language definition to
+# use to highlight it.
+sub ext2langfile ($) {
+       my $ext=shift;
+
+       my $langfile="$langdefdir/$ext.lang";
+       return $langfile if exists $highlighters{$langfile};
+
+       read_filetypes() unless $filetypes_read;
+       if (exists $ext2lang{$ext}) {
+               return "$langdefdir/$ext2lang{$ext}.lang";
+       }
+       # If a language only has one common extension, it will not
+       # be listed in filetypes, so check the langfile.
+       elsif (-e $langfile) {
+               return $langfile;
+       }
+       else {
+               return undef;
+       }
+}
+
+# Interface to the highlight C library.
+sub highlight ($$) {
+       my $langfile=shift;
+       my $input=shift;
+
+       eval q{use highlight};
+       if ($@) {
+               print STDERR gettext("warning: highlight perl module not available; falling back to pass through");
+               return $input;
+       }
+
+       my $gen;
+       if (! exists $highlighters{$langfile}) {
+               $gen = highlightc::CodeGenerator_getInstance($highlightc::XHTML);
+               $gen->setFragmentCode(1); # generate html fragment
+               $gen->setHTMLEnclosePreTag(1); # include stylish <pre>
+               $gen->initTheme("/dev/null"); # theme is not needed because CSS is not emitted
+               $gen->initLanguage($langfile); # must come after initTheme
+               $gen->setEncoding("utf-8");
+               $highlighters{$langfile}=$gen;
+       }
+       else {          
+               $gen=$highlighters{$langfile};
+       }
+
+       return $gen->generateString($input);
+}
+
+1
index 846b0f2c9333f27c2356fecca9d679cba8159964..bd2177a06a1217de57700c40de641e9794133b5f 100644 (file)
@@ -10,13 +10,22 @@ package IkiWiki::Plugin::hnb;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use File::Temp qw(:mktemp);
 
 sub import {
+       hook(type => "getsetup", id => "hnb", call => \&getsetup);
        hook(type => "htmlize", id => "hnb", call => \&htmlize);
 }
 
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
 sub htmlize (@) {
        my %params = @_;
 
index 7623ba6a96accd71d67d8a7ac84c1422ed535224..a7d5e8ce91af28d9053b9b831564e9b1fc13a7b3 100644 (file)
@@ -4,20 +4,29 @@ package IkiWiki::Plugin::html;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "html", call => \&getsetup);
        hook(type => "htmlize", id => "html", call => \&htmlize);
        hook(type => "htmlize", id => "htm", call => \&htmlize);
 
        # ikiwiki defaults to skipping .html files as a security measure;
        # make it process them so this plugin can take effect
        $config{wiki_file_prune_regexps} = [ grep { !m/\\\.x\?html\?\$/ } @{$config{wiki_file_prune_regexps}} ];
-} # }}}
+}
 
-sub htmlize (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
+sub htmlize (@) {
        my %params=@_;
        return $params{content};
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/htmlbalance.pm b/IkiWiki/Plugin/htmlbalance.pm
new file mode 100644 (file)
index 0000000..26f8e49
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::htmlbalance;
+
+# htmlbalance: Parse and re-serialize HTML to ensure balanced tags
+#
+# Copyright 2008 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+# Licensed under the GNU GPL, version 2, or any later version published by the
+# Free Software Foundation
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use HTML::Entities;
+
+sub import {
+       hook(type => "getsetup", id => "htmlbalance", call => \&getsetup);
+       hook(type => "sanitize", id => "htmlbalance", call => \&sanitize);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub sanitize (@) {
+       my %params=@_;
+       my $ret = '';
+
+       eval q{use HTML::TreeBuilder};
+       error $@ if $@;
+       my $tree = HTML::TreeBuilder->new();
+       $tree->ignore_unknown(0);
+       $tree->ignore_ignorable_whitespace(0);
+       $tree->no_space_compacting(1);
+       $tree->p_strict(1);
+       $tree->store_comments(0);
+       $tree->store_declarations(0);
+       $tree->store_pis(0);
+       $tree->parse_content($params{content});
+       my @nodes = $tree->disembowel();
+       foreach my $node (@nodes) {
+               if (ref $node) {
+                       $ret .= $node->as_XML();
+                       chomp $ret;
+                       $node->delete();
+               }
+               else {
+                       $ret .= encode_entities($node);
+               }
+       }
+       $tree->delete();
+       return $ret;
+}
+
+1
index 3bdaccea119ec0e1b289a0da2f6d90e2219b8d66..a249cdf7a43b2986b5ca519f88c01cc6fcf85141 100644 (file)
@@ -3,13 +3,14 @@ package IkiWiki::Plugin::htmlscrubber;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 # This regexp matches urls that are in a known safe scheme.
 # Feel free to use it from other plugins.
 our $safe_url_regexp;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "htmlscrubber", call => \&getsetup);
        hook(type => "sanitize", id => "htmlscrubber", call => \&sanitize);
 
        # Only known uri schemes are allowed to avoid all the ways of
@@ -32,15 +33,39 @@ sub import { #{{{
        # data is a special case. Allow data:image/*, but
        # disallow data:text/javascript and everything else.
        $safe_url_regexp=qr/^(?:(?:$uri_schemes):|data:image\/|[^:]+(?:$|\/))/i;
-} # }}}
+}
 
-sub sanitize (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               htmlscrubber_skip => {
+                       type => "pagespec",
+                       example => "!*/Discussion",
+                       description => "PageSpec specifying pages not to scrub",
+                       link => "ikiwiki/PageSpec",
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub sanitize (@) {
        my %params=@_;
+
+       if (exists $config{htmlscrubber_skip} &&
+           length $config{htmlscrubber_skip} &&
+           exists $params{destpage} &&
+           pagespec_match($params{destpage}, $config{htmlscrubber_skip})) {
+               return $params{content};
+       }
+
        return scrubber()->scrub($params{content});
-} # }}}
+}
 
 my $_scrubber;
-sub scrubber { #{{{
+sub scrubber {
        return $_scrubber if defined $_scrubber;
 
        eval q{use HTML::Scrubber};
@@ -86,6 +111,6 @@ sub scrubber { #{{{
                }],
        );
        return $_scrubber;
-} # }}}
+}
 
 1
index 9591fbe04b3d7a9ef5a0718fc3bc8ff36b1741a3..e6d377f8ab96a853f0bfcbc51ab2d09126e6d14e 100644 (file)
@@ -9,24 +9,33 @@ package IkiWiki::Plugin::htmltidy;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use IPC::Open2;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "tidy", call => \&getsetup);
        hook(type => "sanitize", id => "tidy", call => \&sanitize);
-} # }}}
+}
 
-sub sanitize (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub sanitize (@) {
        my %params=@_;
 
        my $pid;
        my $sigpipe=0;
        $SIG{PIPE}=sub { $sigpipe=1 };
-       $pid=open2(*IN, *OUT, 'tidy -quiet -asxhtml -utf8 --show-body-only yes --show-warnings no --tidy-mark no --markup yes');
-       
+       $pid=open2(*IN, *OUT, 'tidy -quiet -asxhtml -utf8 --show-body-only yes --show-warnings no --tidy-mark no --markup yes 2>/dev/null');
+
        # open2 doesn't respect "use open ':utf8'"
        binmode (IN, ':utf8');
-       binmode (OUT, ':utf8'); 
+       binmode (OUT, ':utf8');
        
        print OUT $params{content};
        close OUT;
@@ -37,9 +46,11 @@ sub sanitize (@) { #{{{
        waitpid $pid, 0;
 
        $SIG{PIPE}="DEFAULT";
-       return $params{content} if $sigpipe;
+       if ($sigpipe || ! defined $ret) {
+               return gettext("htmltidy failed to parse this html");
+       }
 
        return $ret;
-} # }}}
+}
 
 1
index d28b6d2d0f033dcd107ceb7b9632b991c8da73a9..1816c9d74c27aaee1e2b6114e62dd06b8fca1d4c 100644 (file)
@@ -4,19 +4,28 @@ package IkiWiki::Plugin::httpauth;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "httpauth", call => \&getsetup);
        hook(type => "auth", id => "httpauth", call => \&auth);
-} # }}}
+}
 
-sub auth ($$) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub auth ($$) {
        my $cgi=shift;
        my $session=shift;
 
        if (defined $cgi->remote_user()) {
                $session->param("name", $cgi->remote_user());
        }
-} #}}}
+}
 
 1
index cc0e84b01f09a7527c341a99c8262eeebb34d106..5f97e38108ad22cfb9cde8dd9500d298201752be 100644 (file)
@@ -5,15 +5,24 @@ package IkiWiki::Plugin::img;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %imgdefaults;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "img", call => \&getsetup);
        hook(type => "preprocess", id => "img", call => \&preprocess, scan => 1);
-} #}}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my ($image) = $_[0] =~ /$config{wiki_file_regexp}/; # untaint
        my %params=@_;
 
@@ -34,43 +43,51 @@ sub preprocess (@) { #{{{
                return '';
        }
 
-       push @{$links{$params{page}}}, $image;
+       add_link($params{page}, $image);
+
        # optimisation: detect scan mode, and avoid generating the image
        if (! defined wantarray) {
                return;
        }
 
        my $file = bestlink($params{page}, $image);
+       my $srcfile = srcfile($file, 1);
+       if (! length $file || ! defined $srcfile) {
+               return htmllink($params{page}, $params{destpage}, $image);
+       }
 
        my $dir = $params{page};
        my $base = IkiWiki::basename($file);
 
        eval q{use Image::Magick};
-       error($@) if $@;
+       error gettext("Image::Magick is not installed") if $@;
        my $im = Image::Magick->new;
        my $imglink;
        my $r;
 
        if ($params{size} ne 'full') {
-               my ($w, $h) = ($params{size} =~ /^(\d+)x(\d+)$/);
-               return "[[img ".sprintf(gettext('bad size "%s"'), $params{size})."]]"
-                       unless (defined $w && defined $h);
+               add_depends($params{page}, $image);
+
+               my ($w, $h) = ($params{size} =~ /^(\d*)x(\d*)$/);
+               error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size})
+                       unless (defined $w && defined $h &&
+                               (length $w || length $h));
 
                my $outfile = "$config{destdir}/$dir/${w}x${h}-$base";
                $imglink = "$dir/${w}x${h}-$base";
                
                will_render($params{page}, $imglink);
 
-               if (-e $outfile && (-M srcfile($file) >= -M $outfile)) {
+               if (-e $outfile && (-M $srcfile >= -M $outfile)) {
                        $r = $im->Read($outfile);
-                       return "[[img ".sprintf(gettext("failed to read %s: %s"), $outfile, $r)."]]" if $r;
+                       error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r;
                }
                else {
-                       $r = $im->Read(srcfile($file));
-                       return "[[img ".sprintf(gettext("failed to read %s: %s"), $file, $r)."]]" if $r;
+                       $r = $im->Read($srcfile);
+                       error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r;
 
                        $r = $im->Resize(geometry => "${w}x${h}");
-                       return "[[img ".sprintf(gettext("failed to resize: %s"), $r)."]]" if $r;
+                       error sprintf(gettext("failed to resize: %s"), $r) if $r;
 
                        # don't actually write file in preview mode
                        if (! $params{preview}) {
@@ -83,13 +100,11 @@ sub preprocess (@) { #{{{
                }
        }
        else {
-               $r = $im->Read(srcfile($file));
-               return "[[img ".sprintf(gettext("failed to read %s: %s"), $file, $r)."]]" if $r;
+               $r = $im->Read($srcfile);
+               error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r;
                $imglink = $file;
        }
 
-       add_depends($imglink, $params{page});
-
        my ($fileurl, $imgurl);
        if (! $params{preview}) {
                $fileurl=urlto($file, $params{destpage});
@@ -101,14 +116,15 @@ sub preprocess (@) { #{{{
        }
 
        if (! defined($im->Get("width")) || ! defined($im->Get("height"))) {
-               return "[[img ".sprintf(gettext("failed to determine size of image %s"), $file)."]]";
+               error sprintf(gettext("failed to determine size of image %s"), $file)
        }
 
        my $imgtag='<img src="'.$imgurl.
-               '" alt="'.(exists $params{alt} ? $params{alt} : '').
                '" width="'.$im->Get("width").
                '" height="'.$im->Get("height").'"'.
+               (exists $params{alt} ? ' alt="'.$params{alt}.'"' : '').
                (exists $params{title} ? ' title="'.$params{title}.'"' : '').
+               (exists $params{align} ? ' align="'.$params{align}.'"' : '').
                (exists $params{class} ? ' class="'.$params{class}.'"' : '').
                (exists $params{id} ? ' id="'.$params{id}.'"' : '').
                ' />';
@@ -119,11 +135,15 @@ sub preprocess (@) { #{{{
        elsif ($params{link} =~ /^\w+:\/\//) {
                $imgtag='<a href="'.$params{link}.'">'.$imgtag.'</a>';
        }
-       elsif (length bestlink($params{page}, $params{link})) {
-               add_depends($params{page}, $params{link});
-               $imgtag=htmllink($params{page}, $params{destpage},
-                       $params{link}, linktext => $imgtag,
-                       noimageinline => 1);
+       else {
+               my $b = bestlink($params{page}, $params{link});
+       
+               if (length $b) {
+                       add_depends($params{page}, $b);
+                       $imgtag=htmllink($params{page}, $params{destpage},
+                               $params{link}, linktext => $imgtag,
+                               noimageinline => 1);
+               }
        }
 
        if (exists $params{caption}) {
@@ -135,6 +155,6 @@ sub preprocess (@) { #{{{
        else {
                return $imgtag;
        }
-} #}}}
+}
 
 1
index 8890e5ed068c3b0dad86d8def01c7ce1016434c2..a501566b554d11cd1894878637aaf5d2204089d4 100644 (file)
@@ -5,7 +5,7 @@ package IkiWiki::Plugin::inline;
 use warnings;
 use strict;
 use Encode;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use URI;
 
 my %knownfeeds;
@@ -13,24 +13,23 @@ my %page_numfeeds;
 my @inline;
 my $nested=0;
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "inline", call => \&getopt);
+       hook(type => "getsetup", id => "inline", call => \&getsetup);
        hook(type => "checkconfig", id => "inline", call => \&checkconfig);
        hook(type => "sessioncgi", id => "inline", call => \&sessioncgi);
        hook(type => "preprocess", id => "inline", 
                call => \&IkiWiki::preprocess_inline);
        hook(type => "pagetemplate", id => "inline",
                call => \&IkiWiki::pagetemplate_inline);
-       hook(type => "format", id => "inline", call => \&format);
+       hook(type => "format", id => "inline", call => \&format, first => 1);
        # Hook to change to do pinging since it's called late.
        # This ensures each page only pings once and prevents slow
        # pings interrupting page builds.
-       hook(type => "change", id => "inline", 
-               call => \&IkiWiki::pingurl);
-
-} # }}}
+       hook(type => "change", id => "inline", call => \&IkiWiki::pingurl);
+}
 
-sub getopt () { #{{{
+sub getopt () {
        eval q{use Getopt::Long};
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
@@ -39,10 +38,56 @@ sub getopt () { #{{{
                "atom!" => \$config{atom},
                "allowrss!" => \$config{allowrss},
                "allowatom!" => \$config{allowatom},
+               "pingurl=s" => sub {
+                       push @{$config{pingurl}}, $_[1];
+               },      
        );
 }
 
-sub checkconfig () { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               rss => {
+                       type => "boolean",
+                       example => 0,
+                       description => "enable rss feeds by default?",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               atom => {
+                       type => "boolean",
+                       example => 0,
+                       description => "enable atom feeds by default?",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               allowrss => {
+                       type => "boolean",
+                       example => 0,
+                       description => "allow rss feeds to be used?",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               allowatom => {
+                       type => "boolean",
+                       example => 0,
+                       description => "allow atom feeds to be used?",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               pingurl => {
+                       type => "string",
+                       example => "http://rpc.technorati.com/rpc/ping",
+                       description => "urls to ping (using XML-RPC) on feed update",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
        if (($config{rss} || $config{atom}) && ! length $config{url}) {
                error(gettext("Must specify url to wiki with --url when using --rss or --atom"));
        }
@@ -52,9 +97,12 @@ sub checkconfig () { #{{{
        if ($config{atom}) {
                push @{$config{wiki_file_prune_regexps}}, qr/\.atom$/;
        }
-} #}}}
+       if (! exists $config{pingurl}) {
+               $config{pingurl}=[];
+       }
+}
 
-sub format (@) { #{{{
+sub format (@) {
         my %params=@_;
 
        # Fill in the inline content generated earlier. This is actually an
@@ -63,14 +111,14 @@ sub format (@) { #{{{
                delete @inline[$1,]
        }eg;
        return $params{content};
-} #}}}
+}
 
-sub sessioncgi () { #{{{
+sub sessioncgi ($$) {
        my $q=shift;
        my $session=shift;
 
        if ($q->param('do') eq 'blog') {
-               my $page=IkiWiki::titlepage(decode_utf8($q->param('title')));
+               my $page=titlepage(decode_utf8($q->param('title')));
                $page=~s/(\/)/"__".ord($1)."__"/eg; # don't create subdirs
                # if the page already exists, munge it to be unique
                my $from=$q->param('from');
@@ -82,7 +130,13 @@ sub sessioncgi () { #{{{
                $q->param('page', $page.$add);
                # now go create the page
                $q->param('do', 'create');
-               IkiWiki::cgi_editpage($q, $session);
+               # make sure the editpage plugin in loaded
+               if (IkiWiki->can("cgi_editpage")) {
+                       IkiWiki::cgi_editpage($q, $session);
+               }
+               else {
+                       error(gettext("page editing not allowed"));
+               }
                exit;
        }
 }
@@ -94,16 +148,11 @@ package IkiWiki;
 my %toping;
 my %feedlinks;
 
-sub yesno ($) { #{{{
-       my $val=shift;
-       return (defined $val && lc($val) eq "yes");
-} #}}}
-
-sub preprocess_inline (@) { #{{{
+sub preprocess_inline (@) {
        my %params=@_;
        
-       if (! exists $params{pages}) {
-               return "[[inline ".gettext("missing pages parameter")."]]";
+       if (! exists $params{pages} && ! exists $params{pagenames}) {
+               error gettext("missing pages parameter");
        }
        my $raw=yesno($params{raw});
        my $archive=yesno($params{archive});
@@ -111,6 +160,7 @@ sub preprocess_inline (@) { #{{{
        my $atom=(($config{atom} || $config{allowatom}) && exists $params{atom}) ? yesno($params{atom}) : $config{atom};
        my $quick=exists $params{quick} ? yesno($params{quick}) : 0;
        my $feeds=exists $params{feeds} ? yesno($params{feeds}) : !$quick;
+       my $emptyfeeds=exists $params{emptyfeeds} ? yesno($params{emptyfeeds}) : 1;
        my $feedonly=yesno($params{feedonly});
        if (! exists $params{show} && ! $archive) {
                $params{show}=10;
@@ -134,24 +184,44 @@ sub preprocess_inline (@) { #{{{
        }
 
        my @list;
-       foreach my $page (keys %pagesources) {
-               next if $page eq $params{page};
-               if (pagespec_match($page, $params{pages}, location => $params{page})) {
-                       push @list, $page;
+
+       if (exists $params{pagenames}) {
+               foreach my $p (qw(sort pages)) {
+                       if (exists $params{$p}) {
+                               error sprintf(gettext("the %s and %s parameters cannot be used together"),
+                                       "pagenames", $p);
+                       }
                }
-       }
 
-       if (exists $params{sort} && $params{sort} eq 'title') {
-               @list=sort @list;
-       }
-       elsif (exists $params{sort} && $params{sort} eq 'mtime') {
-               @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
-       }
-       elsif (! exists $params{sort} || $params{sort} eq 'age') {
-               @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+               @list = map { bestlink($params{page}, $_) }
+                       split ' ', $params{pagenames};
+
+               $params{pages} = join(" or ", @list);
        }
        else {
-               return sprintf(gettext("unknown sort type %s"), $params{sort});
+               @list = pagespec_match_list(
+                       [ grep { $_ ne $params{page} } keys %pagesources ],
+                       $params{pages}, location => $params{page});
+
+               if (exists $params{sort} && $params{sort} eq 'title') {
+                       @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
+               }
+               elsif (exists $params{sort} && $params{sort} eq 'title_natural') {
+                       eval q{use Sort::Naturally};
+                       if ($@) {
+                               error(gettext("Sort::Naturally needed for title_natural sort"));
+                       }
+                       @list=sort { Sort::Naturally::ncmp(pagetitle(basename($a)), pagetitle(basename($b))) } @list;
+               }
+               elsif (exists $params{sort} && $params{sort} eq 'mtime') {
+                       @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
+               }
+               elsif (! exists $params{sort} || $params{sort} eq 'age') {
+                       @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+               }
+               else {
+                       error sprintf(gettext("unknown sort type %s"), $params{sort});
+               }
        }
 
        if (yesno($params{reverse})) {
@@ -181,39 +251,73 @@ sub preprocess_inline (@) { #{{{
        # Explicitly add all currently displayed pages as dependencies, so
        # that if they are removed or otherwise changed, the inline will be
        # sure to be updated.
-       add_depends($params{page}, join(" or ", $#list >= $#feedlist ? @list : @feedlist));
-
-       my $feednum="";
-
-       my $feedid=join("\0", map { $_."\0".$params{$_} } sort keys %params);
-       if (exists $knownfeeds{$feedid}) {
-               $feednum=$knownfeeds{$feedid};
+       foreach my $p ($#list >= $#feedlist ? @list : @feedlist) {
+               add_depends($params{page}, $p);
        }
-       else {
-               if (exists $page_numfeeds{$params{destpage}}) {
-                       if ($feeds) {
-                               $feednum=$knownfeeds{$feedid}=++$page_numfeeds{$params{destpage}};
+       
+       if ($feeds && exists $params{feedpages}) {
+               @feedlist=pagespec_match_list(\@feedlist, $params{feedpages}, location => $params{page});
+       }
+
+       my ($feedbase, $feednum);
+       if ($feeds) {
+               # Ensure that multiple feeds on a page go to unique files.
+               
+               # Feedfile can lead to conflicts if usedirs is not enabled,
+               # so avoid supporting it in that case.
+               delete $params{feedfile} if ! $config{usedirs};
+               # Tight limits on legal feedfiles, to avoid security issues
+               # and conflicts.
+               if (defined $params{feedfile}) {
+                       if ($params{feedfile} =~ /\// ||
+                           $params{feedfile} !~ /$config{wiki_file_regexp}/) {
+                               error("illegal feedfile");
                        }
+                       $params{feedfile}=possibly_foolish_untaint($params{feedfile});
+               }
+               $feedbase=targetpage($params{destpage}, "", $params{feedfile});
+
+               my $feedid=join("\0", $feedbase, map { $_."\0".$params{$_} } sort keys %params);
+               if (exists $knownfeeds{$feedid}) {
+                       $feednum=$knownfeeds{$feedid};
                }
                else {
-                       $feednum=$knownfeeds{$feedid}="";
-                       if ($feeds) {
-                               $page_numfeeds{$params{destpage}}=1;
+                       if (exists $page_numfeeds{$params{destpage}}{$feedbase}) {
+                               if ($feeds) {
+                                       $feednum=$knownfeeds{$feedid}=++$page_numfeeds{$params{destpage}}{$feedbase};
+                               }
+                       }
+                       else {
+                               $feednum=$knownfeeds{$feedid}="";
+                               if ($feeds) {
+                                       $page_numfeeds{$params{destpage}}{$feedbase}=1;
+                               }
                        }
                }
        }
 
-       my $rssurl=basename(rsspage($params{destpage}).$feednum) if $feeds && $rss;
-       my $atomurl=basename(atompage($params{destpage}).$feednum) if $feeds && $atom;
+       my $rssurl=abs2rel($feedbase."rss".$feednum, dirname(htmlpage($params{destpage}))) if $feeds && $rss;
+       my $atomurl=abs2rel($feedbase."atom".$feednum, dirname(htmlpage($params{destpage}))) if $feeds && $atom;
+
        my $ret="";
 
-       if ($config{cgiurl} && ! $params{preview} && (exists $params{rootpage} ||
-                       (exists $params{postform} && yesno($params{postform})))) {
+       if (length $config{cgiurl} && ! $params{preview} && (exists $params{rootpage} ||
+           (exists $params{postform} && yesno($params{postform}))) &&
+           IkiWiki->can("cgi_editpage")) {
                # Add a blog post form, with feed buttons.
                my $formtemplate=template("blogpost.tmpl", blind_cache => 1);
                $formtemplate->param(cgiurl => $config{cgiurl});
-               $formtemplate->param(rootpage => 
-                       exists $params{rootpage} ? $params{rootpage} : $params{page});
+               my $rootpage;
+               if (exists $params{rootpage}) {
+                       $rootpage=bestlink($params{page}, $params{rootpage});
+                       if (!length $rootpage) {
+                               $rootpage=$params{rootpage};
+                       }
+               }
+               else {
+                       $rootpage=$params{page};
+               }
+               $formtemplate->param(rootpage => $rootpage);
                $formtemplate->param(rssurl => $rssurl) if $feeds && $rss;
                $formtemplate->param(atomurl => $atomurl) if $feeds && $atom;
                if (exists $params{postformtext}) {
@@ -225,8 +329,12 @@ sub preprocess_inline (@) { #{{{
                                gettext("Add a new post titled:"));
                }
                $ret.=$formtemplate->output;
+               
+               # The post form includes the feed buttons, so
+               # emptyfeeds cannot be hidden.
+               $emptyfeeds=1;
        }
-       elsif ($feeds && !$params{preview}) {
+       elsif ($feeds && !$params{preview} && ($emptyfeeds || @feedlist)) {
                # Add feed buttons.
                my $linktemplate=template("feedlink.tmpl", blind_cache => 1);
                $linktemplate->param(rssurl => $rssurl) if $rss;
@@ -238,7 +346,7 @@ sub preprocess_inline (@) { #{{{
                require HTML::Template;
                my @params=IkiWiki::template_params($params{template}.".tmpl", blind_cache => 1);
                if (! @params) {
-                       return sprintf(gettext("nonexistant template %s"), $params{template});
+                       error sprintf(gettext("nonexistant template %s"), $params{template});
                }
                my $template=HTML::Template->new(@params) unless $raw;
        
@@ -253,9 +361,11 @@ sub preprocess_inline (@) { #{{{
                                        my $content=get_inline_content($page, $params{destpage});
                                        $template->param(content => $content);
                                }
-                               $template->param(pageurl => urlto(bestlink($params{page}, $page), $params{destpage}));
+                               $template->param(pageurl => urlto($page, $params{destpage}));
+                               $template->param(inlinepage => $page);
                                $template->param(title => pagetitle(basename($page)));
                                $template->param(ctime => displaytime($pagectime{$page}, $params{timeformat}));
+                               $template->param(mtime => displaytime($pagemtime{$page}, $params{timeformat}));
                                $template->param(first => 1) if $page eq $list[0];
                                $template->param(last => 1) if $page eq $list[$#list];
        
@@ -263,15 +373,14 @@ sub preprocess_inline (@) { #{{{
                                        my $file = $pagesources{$page};
                                        my $type = pagetype($file);
                                        if ($config{discussion}) {
-                                               my $discussionlink=gettext("discussion");
-                                               if ($page !~ /.*\/\Q$discussionlink\E$/ &&
+                                               if ($page !~ /.*\/\Q$config{discussionpage}\E$/ &&
                                                    (length $config{cgiurl} ||
-                                                    exists $links{$page."/".$discussionlink})) {
+                                                    exists $links{$page."/".$config{discussionpage}})) {
                                                        $template->param(have_actions => 1);
                                                        $template->param(discussionlink =>
                                                                htmllink($page,
                                                                        $params{destpage},
-                                                                       gettext("Discussion"),
+                                                                       $config{discussionpage},
                                                                        noimageinline => 1,
                                                                        forcesubpage => 1));
                                                }
@@ -302,30 +411,26 @@ sub preprocess_inline (@) { #{{{
                }
        }
        
-       if ($feeds) {
-               if (exists $params{feedpages}) {
-                       @feedlist=grep { pagespec_match($_, $params{feedpages}, location => $params{page}) } @feedlist;
-               }
-       
+       if ($feeds && ($emptyfeeds || @feedlist)) {
                if ($rss) {
-                       my $rssp=rsspage($params{destpage}).$feednum;
+                       my $rssp=$feedbase."rss".$feednum;
                        will_render($params{destpage}, $rssp);
                        if (! $params{preview}) {
                                writefile($rssp, $config{destdir},
                                        genfeed("rss",
-                                               $config{url}."/".rsspage($params{destpage}).$feednum, $desc, $params{destpage}, @feedlist));
+                                               $config{url}."/".$rssp, $desc, $params{guid}, $params{destpage}, @feedlist));
                                $toping{$params{destpage}}=1 unless $config{rebuild};
-                               $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/rss+xml" title="RSS" href="$rssurl" />};
+                               $feedlinks{$params{destpage}}.=qq{<link rel="alternate" type="application/rss+xml" title="$desc (RSS)" href="$rssurl" />};
                        }
                }
                if ($atom) {
-                       my $atomp=atompage($params{destpage}).$feednum;
+                       my $atomp=$feedbase."atom".$feednum;
                        will_render($params{destpage}, $atomp);
                        if (! $params{preview}) {
                                writefile($atomp, $config{destdir},
-                                       genfeed("atom", $config{url}."/".atompage($params{destpage}).$feednum, $desc, $params{destpage}, @feedlist));
+                                       genfeed("atom", $config{url}."/".$atomp, $desc, $params{guid}, $params{destpage}, @feedlist));
                                $toping{$params{destpage}}=1 unless $config{rebuild};
-                               $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/atom+xml" title="Atom" href="$atomurl" />};
+                               $feedlinks{$params{destpage}}.=qq{<link rel="alternate" type="application/atom+xml" title="$desc (Atom)" href="$atomurl" />};
                        }
                }
        }
@@ -333,18 +438,18 @@ sub preprocess_inline (@) { #{{{
        return $ret if $raw || $nested;
        push @inline, $ret;
        return "<div class=\"inline\" id=\"$#inline\"></div>\n\n";
-} #}}}
+}
 
-sub pagetemplate_inline (@) { #{{{
+sub pagetemplate_inline (@) {
        my %params=@_;
        my $page=$params{page};
        my $template=$params{template};
 
        $template->param(feedlinks => $feedlinks{$page})
                if exists $feedlinks{$page} && $template->query(name => "feedlinks");
-} #}}}
+}
 
-sub get_inline_content ($$) { #{{{
+sub get_inline_content ($$) {
        my $page=shift;
        my $destpage=shift;
        
@@ -363,9 +468,9 @@ sub get_inline_content ($$) { #{{{
        else {
                return "";
        }
-} #}}}
+}
 
-sub date_822 ($) { #{{{
+sub date_822 ($) {
        my $time=shift;
 
        my $lc_time=POSIX::setlocale(&POSIX::LC_TIME);
@@ -373,9 +478,9 @@ sub date_822 ($) { #{{{
        my $ret=POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time));
        POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
        return $ret;
-} #}}}
+}
 
-sub date_3339 ($) { #{{{
+sub date_3339 ($) {
        my $time=shift;
 
        my $lc_time=POSIX::setlocale(&POSIX::LC_TIME);
@@ -383,9 +488,9 @@ sub date_3339 ($) { #{{{
        my $ret=POSIX::strftime("%Y-%m-%dT%H:%M:%SZ", gmtime($time));
        POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
        return $ret;
-} #}}}
+}
 
-sub absolute_urls ($$) { #{{{
+sub absolute_urls ($$) {
        # sucky sub because rss sucks
        my $content=shift;
        my $baseurl=shift;
@@ -406,30 +511,23 @@ sub absolute_urls ($$) { #{{{
        $content=~s/(<a(?:\s+(?:class|id)\s*="?\w+"?)?)\s+href=\s*"(?!\w+:)(\/[^"]*)"/$1 href="$urltop$2"/mig;
        $content=~s/(<img(?:\s+(?:class|id|width|height)\s*="?\w+"?)*)\s+src=\s*"(?!\w+:)(\/[^"]*)"/$1 src="$urltop$2"/mig;
        return $content;
-} #}}}
-
-sub rsspage ($) { #{{{
-       return targetpage(shift, "rss");
-} #}}}
-
-sub atompage ($) { #{{{
-       return targetpage(shift, "atom");
-} #}}}
+}
 
-sub genfeed ($$$$@) { #{{{
+sub genfeed ($$$$$@) {
        my $feedtype=shift;
        my $feedurl=shift;
        my $feeddesc=shift;
+       my $guid=shift;
        my $page=shift;
        my @pages=@_;
        
-       my $url=URI->new(encode_utf8($config{url}."/".urlto($page,"")));
+       my $url=URI->new(encode_utf8(urlto($page,"",1)));
        
        my $itemtemplate=template($feedtype."item.tmpl", blind_cache => 1);
        my $content="";
        my $lasttime = 0;
        foreach my $p (@pages) {
-               my $u=URI->new(encode_utf8($config{url}."/".urlto($p, "")));
+               my $u=URI->new(encode_utf8(urlto($p, "", 1)));
                my $pcontent = absolute_urls(get_inline_content($p, $page), $url);
 
                $itemtemplate->param(
@@ -442,6 +540,17 @@ sub genfeed ($$$$@) { #{{{
                        mdate_3339 => date_3339($pagemtime{$p}),
                );
 
+               if (exists $pagestate{$p}) {
+                       if (exists $pagestate{$p}{meta}{guid}) {
+                               $itemtemplate->param(guid => $pagestate{$p}{meta}{guid});
+                       }
+
+                       if (exists $pagestate{$p}{meta}{updated}) {
+                               $itemtemplate->param(mdate_822 => date_822($pagestate{$p}{meta}{updated}));
+                               $itemtemplate->param(mdate_3339 => date_3339($pagestate{$p}{meta}{updated}));
+                       }
+               }
+
                if ($itemtemplate->query(name => "enclosure")) {
                        my $file=$pagesources{$p};
                        my $type=pagetype($file);
@@ -484,6 +593,7 @@ sub genfeed ($$$$@) { #{{{
                pageurl => $url,
                content => $content,
                feeddesc => $feeddesc,
+               guid => $guid,
                feeddate => date_3339($lasttime),
                feedurl => $feedurl,
                version => $IkiWiki::version,
@@ -494,9 +604,9 @@ sub genfeed ($$$$@) { #{{{
        });
        
        return $template->output;
-} #}}}
+}
 
-sub pingurl (@) { #{{{
+sub pingurl (@) {
        return unless @{$config{pingurl}} && %toping;
 
        eval q{require RPC::XML::Client};
@@ -519,7 +629,7 @@ sub pingurl (@) { #{{{
 
        foreach my $page (keys %toping) {
                my $title=pagetitle(basename($page), 0);
-               my $url="$config{url}/".urlto($page, "");
+               my $url=urlto($page, "", 1);
                foreach my $pingurl (@{$config{pingurl}}) {
                        debug("Pinging $pingurl for $page");
                        eval {
@@ -528,20 +638,20 @@ sub pingurl (@) { #{{{
                                        $title, $url);
                                my $res = $client->send_request($req);
                                if (! ref $res) {
-                                       debug("Did not receive response to ping");
+                                       error("Did not receive response to ping");
                                }
                                my $r=$res->value;
                                if (! exists $r->{flerror} || $r->{flerror}) {
-                                       debug("Ping rejected: ".(exists $r->{message} ? $r->{message} : "[unknown reason]"));
+                                       error("Ping rejected: ".(exists $r->{message} ? $r->{message} : "[unknown reason]"));
                                }
                        };
                        if ($@) {
-                               debug "Ping failed: $@";
+                               error "Ping failed: $@";
                        }
                }
        }
 
        exit 0; # daemon done
-} #}}}
+}
 
 1
index 24579057ccb159450bf5d9a49e892be848747eb6..4c1add9853a3b4053f34b8d927e52ea0e7e4d1f4 100644 (file)
@@ -3,17 +3,27 @@ package IkiWiki::Plugin::link;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my $link_regexp;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "link", call => \&getsetup);
        hook(type => "checkconfig", id => "link", call => \&checkconfig);
        hook(type => "linkify", id => "link", call => \&linkify);
        hook(type => "scan", id => "link", call => \&scan);
-} # }}}
+       hook(type => "renamepage", id => "link", call => \&renamepage);
+}
 
-sub checkconfig () { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig () {
        if ($config{prefix_directives}) {
                $link_regexp = qr{
                        \[\[(?=[^!])            # beginning of link
@@ -48,9 +58,9 @@ sub checkconfig () { #{{{
                        \]\]                    # end of link
                }x,
        }
-} #}}}
+}
 
-sub linkify (@) { #{{{
+sub linkify (@) {
        my %params=@_;
        my $page=$params{page};
        my $destpage=$params{destpage};
@@ -59,25 +69,55 @@ sub linkify (@) { #{{{
                defined $2
                        ? ( $1 
                                ? "[[$2|$3".($4 ? "#$4" : "")."]]" 
-                               : htmllink($page, $destpage, IkiWiki::linkpage($3),
-                                       anchor => $4, linktext => IkiWiki::pagetitle($2)))
+                               : htmllink($page, $destpage, linkpage($3),
+                                       anchor => $4, linktext => pagetitle($2)))
                        : ( $1 
                                ? "[[$3".($4 ? "#$4" : "")."]]"
-                               : htmllink($page, $destpage, IkiWiki::linkpage($3),
+                               : htmllink($page, $destpage, linkpage($3),
                                        anchor => $4))
        }eg;
        
        return $params{content};
-} #}}}
+}
 
-sub scan (@) { #{{{
+sub scan (@) {
        my %params=@_;
        my $page=$params{page};
        my $content=$params{content};
 
        while ($content =~ /(?<!\\)$link_regexp/g) {
-               push @{$links{$page}}, IkiWiki::linkpage($2);
+               add_link($page, linkpage($2));
        }
-} # }}}
+}
+
+sub renamepage (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $old=$params{oldpage};
+       my $new=$params{newpage};
+
+       $params{content} =~ s{(?<!\\)$link_regexp}{
+               my $linktext=$2;
+               my $link=$linktext;
+               if (bestlink($page, linkpage($linktext)) eq $old) {
+                       $link=pagetitle($new, 1);
+                       $link=~s/ /_/g;
+                       if ($linktext =~ m/.*\/*?[A-Z]/) {
+                               # preserve leading cap of last component
+                               my @bits=split("/", $link);
+                               $link=join("/", @bits[0..$#bits-1], ucfirst($bits[$#bits]));
+                       }
+                       if (index($linktext, "/") == 0) {
+                               # absolute link
+                               $link="/$link";
+                       }
+               }
+               defined $1
+                       ? ( "[[$1|$link".($3 ? "#$3" : "")."]]" )
+                       : ( "[[$link".   ($3 ? "#$3" : "")."]]" )
+       }eg;
+
+       return $params{content};
+}
 
 1
index 82b38f4cb79909c449e29bd8a68340db9d343bde..941ed5f3672145bb6111c5a6650fb14431641297 100644 (file)
@@ -3,18 +3,27 @@ package IkiWiki::Plugin::linkmap;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use IPC::Open2;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "linkmap", call => \&getsetup);
        hook(type => "preprocess", id => "linkmap", call => \&preprocess);
        hook(type => "format", id => "linkmap", call => \&format);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
 my $mapnum=0;
 my %maps;
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        $params{pages}="*" unless defined $params{pages};
@@ -30,17 +39,17 @@ sub preprocess (@) { #{{{
        $mapnum++;
        $maps{$mapnum}=\%params;
        return "<div class=\"linkmap$mapnum\"></div>";
-} # }}}
+}
 
-sub format (@) { #{{{
+sub format (@) {
         my %params=@_;
 
        $params{content}=~s/<div class=\"linkmap(\d+)"><\/div>/genmap($1)/eg;
 
         return $params{content};
-} # }}}
+}
 
-sub genmap ($) { #{{{
+sub genmap ($) {
        my $mapnum=shift;
        return "" unless exists $maps{$mapnum};
        my %params=%{$maps{$mapnum}};
@@ -94,11 +103,9 @@ sub genmap ($) { #{{{
        
        waitpid $pid, 0;
        $SIG{PIPE}="DEFAULT";
-       if ($sigpipe) {
-               return  "[[linkmap ".gettext("failed to run dot")."]]";
-       }
+       error gettext("failed to run dot") if $sigpipe;
 
        return $ret;
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/listdirectives.pm b/IkiWiki/Plugin/listdirectives.pm
new file mode 100644 (file)
index 0000000..bd73f1a
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+# Ikiwiki listdirectives plugin.
+package IkiWiki::Plugin::listdirectives;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       add_underlay("directives");
+       hook(type => "getsetup", id => "listdirectives", call => \&getsetup);
+       hook(type => "checkconfig", id => "listdirectives", call => \&checkconfig);
+       hook(type => "needsbuild", id => "listdirectives", call => \&needsbuild);
+       hook(type => "preprocess", id => "listdirectives", call => \&preprocess);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               directive_description_dir => {
+                       type => "string",
+                       description => "directory in srcdir that contains directive descriptions",
+                       example => "ikiwiki/directive",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+my @fulllist;
+my @shortlist;
+my $pluginstring;
+
+sub checkconfig () {
+       if (! defined $config{directive_description_dir}) {
+               $config{directive_description_dir} = "ikiwiki/directive";
+       }
+       else {
+               $config{directive_description_dir} =~ s/\/+$//;
+       }
+}
+
+sub needsbuild (@) {
+       my $needsbuild=shift;
+
+       @fulllist = grep { ! /^_/ } sort keys %{$IkiWiki::hooks{preprocess}};
+       @shortlist = grep { ! $IkiWiki::hooks{preprocess}{$_}{shortcut} } @fulllist;
+       $pluginstring = join(' ', @shortlist) . " : " . join(' ', @fulllist);
+
+       foreach my $page (keys %pagestate) {
+               if (exists $pagestate{$page}{listdirectives}{shown}) {
+                       if ($pagestate{$page}{listdirectives}{shown} ne $pluginstring) {
+                               push @$needsbuild, $pagesources{$page};
+                       }
+                       if (exists $pagesources{$page} &&
+                           grep { $_ eq $pagesources{$page} } @$needsbuild) {
+                               # remove state, will be re-added if
+                               # the [[!listdirectives]] is still there during the
+                               # rebuild
+                               delete $pagestate{$page}{listdirectives}{shown};
+                       }
+               }
+       }
+}
+
+sub preprocess (@) {
+       my %params=@_;
+       
+       $pagestate{$params{destpage}}{listdirectives}{shown}=$pluginstring;
+       
+       my @pluginlist;
+       
+       if (defined $params{generated}) {
+               @pluginlist = @fulllist;
+       }
+       else {
+               @pluginlist = @shortlist;
+       }
+       
+       my $result = '<ul class="listdirectives">';
+       
+       foreach my $plugin (@pluginlist) {
+               $result .= '<li class="listdirectives">';
+               my $link=linkpage($config{directive_description_dir}."/".$plugin);
+               add_depends($params{page}, $link);
+               $result .= htmllink($params{page}, $params{destpage}, $link);
+               $result .= '</li>';
+       }
+       
+       $result .= "</ul>";
+
+       return $result;
+}
+
+1
index 5ffb4e6f9edd254691f4fb5b246e3afb2aeea147..0fa329251f0b7eb5e6814e50f68d020eaf047eb8 100644 (file)
@@ -3,15 +3,30 @@ package IkiWiki::Plugin::lockedit;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "lockedit", call => \&getsetup);
        hook(type => "canedit", id => "lockedit", call => \&canedit);
-       hook(type => "formbuilder_setup", id => "lockedit",
-            call => \&formbuilder_setup);
-} # }}}
-
-sub canedit ($$) { #{{{
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               locked_pages => {
+                       type => "pagespec",
+                       example => "!*/Discussion",
+                       description => "PageSpec controlling which pages are locked",
+                       link => "ikiwiki/PageSpec",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub canedit ($$) {
        my $page=shift;
        my $cgi=shift;
        my $session=shift;
@@ -19,50 +34,23 @@ sub canedit ($$) { #{{{
        my $user=$session->param("name");
        return undef if defined $user && IkiWiki::is_admin($user);
 
-       foreach my $admin (@{$config{adminuser}}) {
-               if (pagespec_match($page, IkiWiki::userinfo_get($admin, "locked_pages"))) {
-                       if (! defined $user ||
-                           ! IkiWiki::userinfo_get($session->param("name"), "regdate")) {
-                               return sub { IkiWiki::needsignin($cgi, $session) };
-                       }
-                       else {
-                               return sprintf(gettext("%s is locked by %s and cannot be edited"),
-                                       htmllink("", "", $page, noimageinline => 1),
-                                       IkiWiki::userlink($admin));
-                       }
+       if (defined $config{locked_pages} && length $config{locked_pages} &&
+           pagespec_match($page, $config{locked_pages},
+                   user => $session->param("name"),
+                   ip => $ENV{REMOTE_ADDR},
+           )) {
+               if (! defined $user ||
+                   ! IkiWiki::userinfo_get($session->param("name"), "regdate")) {
+                       return sub { IkiWiki::needsignin($cgi, $session) };
+               }
+               else {
+                       return sprintf(gettext("%s is locked and cannot be edited"),
+                               htmllink("", "", $page, noimageinline => 1));
+                       
                }
        }
 
        return undef;
-} #}}}
-
-sub formbuilder_setup (@) { #{{{
-       my %params=@_;
-       
-       my $form=$params{form};
-       if ($form->title eq "preferences") {
-               my $session=$params{session};
-               my $cgi=$params{cgi};
-               my $user_name=$session->param("name");
-
-               $form->field(name => "locked_pages", size => 50,
-                       fieldset => "admin",
-                       comment => "(".htmllink("", "", "ikiwiki/PageSpec", noimageinline => 1).")");
-               if (! IkiWiki::is_admin($user_name)) {
-                       $form->field(name => "locked_pages", type => "hidden");
-               }
-               if (! $form->submitted) {
-                       $form->field(name => "locked_pages", force => 1,
-                               value => IkiWiki::userinfo_get($user_name, "locked_pages"));
-               }
-               if ($form->submitted && $form->submitted eq 'Save Preferences') {
-                       if (defined $form->field("locked_pages")) {
-                               IkiWiki::userinfo_set($user_name, "locked_pages",
-                                       $form->field("locked_pages")) ||
-                                               error("failed to set locked_pages");
-                       }
-               }
-       }
-} #}}}
+}
 
 1
index 5b6a843e7ae2680d654317fc35368190c2d9d087..54146dc467bdcb513e426257a6fd0879005cd35a 100644 (file)
@@ -9,13 +9,22 @@ package IkiWiki::Plugin::map;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "map", call => \&getsetup);
        hook(type => "preprocess", id => "map", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        $params{pages}="*" unless defined $params{pages};
        
@@ -23,32 +32,31 @@ sub preprocess (@) { #{{{
 
        # Get all the items to map.
        my %mapitems;
-       foreach my $page (keys %pagesources) {
-               if (pagespec_match($page, $params{pages}, location => $params{page})) {
-                       if (exists $params{show} && 
-                           exists $pagestate{$page} &&
-                           exists $pagestate{$page}{meta}{$params{show}}) {
-                               $mapitems{$page}=$pagestate{$page}{meta}{$params{show}};
-                       }
-                       else {
-                               $mapitems{$page}='';
-                       }
-                       # Check for a common prefix.
-                       if (! defined $common_prefix) {
-                               $common_prefix=$page;
-                       }
-                       elsif (length $common_prefix &&
-                              $page !~ /^\Q$common_prefix\E(\/|$)/) {
-                               my @a=split(/\//, $page);
-                               my @b=split(/\//, $common_prefix);
-                               $common_prefix="";
-                               while (@a && @b && $a[0] eq $b[0]) {
-                                       if (length $common_prefix) {
-                                               $common_prefix.="/";
-                                       }
-                                       $common_prefix.=shift(@a);
-                                       shift @b;
+       foreach my $page (pagespec_match_list([keys %pagesources],
+                               $params{pages}, location => $params{page})) {
+               if (exists $params{show} && 
+                   exists $pagestate{$page} &&
+                   exists $pagestate{$page}{meta}{$params{show}}) {
+                       $mapitems{$page}=$pagestate{$page}{meta}{$params{show}};
+               }
+               else {
+                       $mapitems{$page}='';
+               }
+               # Check for a common prefix.
+               if (! defined $common_prefix) {
+                       $common_prefix=$page;
+               }
+               elsif (length $common_prefix &&
+                      $page !~ /^\Q$common_prefix\E(\/|$)/) {
+                       my @a=split(/\//, $page);
+                       my @b=split(/\//, $common_prefix);
+                       $common_prefix="";
+                       while (@a && @b && $a[0] eq $b[0]) {
+                               if (length $common_prefix) {
+                                       $common_prefix.="/";
                                }
+                               $common_prefix.=shift(@a);
+                               shift @b;
                        }
                }
        }
@@ -65,14 +73,26 @@ sub preprocess (@) { #{{{
        add_depends($params{page}, $params{pages});
        # Explicitly add all currently shown pages, to detect when pages
        # are removed.
-       add_depends($params{page}, join(" or ", keys %mapitems));
+       foreach my $item (keys %mapitems) {
+               add_depends($params{page}, $item);
+       }
 
        # Create the map.
        my $parent="";
        my $indent=0;
        my $openli=0;
-       my $dummy=0;
-       my $map = "<div class='map'>\n<ul>\n";
+       my $addparent="";
+       my $map = "<div class='map'>\n";
+
+       # Return empty div if %mapitems is empty
+       if (!scalar(keys %mapitems)) {
+               $map .= "</div>\n";
+               return $map; 
+       } 
+       else { # continue populating $map
+               $map .= "<ul>\n";
+       }
+
        foreach my $item (sort keys %mapitems) {
                my @linktext = (length $mapitems{$item} ? (linktext => $mapitems{$item}) : ());
                $item=~s/^\Q$common_prefix\E\///
@@ -81,14 +101,14 @@ sub preprocess (@) { #{{{
                my $baseitem=IkiWiki::dirname($item);
                while (length $parent && length $baseitem && $baseitem !~ /^\Q$parent\E(\/|$)/) {
                        $parent=IkiWiki::dirname($parent);
-                       last if !$dummy && length $parent && $baseitem =~ /^\Q$parent\E(\/|$)/;
+                       last if length $addparent && $baseitem =~ /^\Q$addparent\E(\/|$)/;
+                       $addparent="";
                        $indent--;
                        $map .= "</li>\n";
                        if ($indent > 0) {
                                $map .= "</ul>\n";
                        }
                }
-               $dummy=0;
                while ($depth < $indent) {
                        $indent--;
                        $map .= "</li>\n";
@@ -105,11 +125,12 @@ sub preprocess (@) { #{{{
                                $map .= "<ul>\n";
                        }
                        if ($depth > $indent) {
-                               $dummy=1;
                                $p.="/".shift(@bits);
+                               $addparent=$p;
+                               $addparent=~s/^\///;
                                $map .= "<li>"
                                        .htmllink($params{page}, $params{destpage},
-                                                $p, class => "mapparent",
+                                                "/".$common_prefix.$p, class => "mapparent",
                                                 noimageinline => 1)
                                        ."\n";
                                $openli=1;
@@ -134,6 +155,6 @@ sub preprocess (@) { #{{{
        }
        $map .= "</div>\n";
        return $map;
-} # }}}
+}
 
 1
index 11f3f0137627643fe285e0464b59b2e0086b3f88..c62780cb892b37a9c5dd8b6c5230bdd4e4567d2e 100644 (file)
@@ -4,14 +4,30 @@ package IkiWiki::Plugin::mdwn;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-       hook(type => "htmlize", id => "mdwn", call => \&htmlize);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "mdwn", call => \&getsetup);
+       hook(type => "htmlize", id => "mdwn", call => \&htmlize, longname => "Markdown");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+               multimarkdown => {
+                       type => "boolean",
+                       example => 0,
+                       description => "enable multimarkdown features?",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
 
 my $markdown_sub;
-sub htmlize (@) { #{{{
+sub htmlize (@) {
        my %params=@_;
        my $content = $params{content};
 
@@ -25,13 +41,13 @@ sub htmlize (@) { #{{{
                if (exists $config{multimarkdown} && $config{multimarkdown}) {
                        eval q{use Text::MultiMarkdown};
                        if ($@) {
-                               error(gettext("multimarkdown is enabled, but Text::MultiMarkdown is not installed"));
+                               debug(gettext("multimarkdown is enabled, but Text::MultiMarkdown is not installed"));
                        }
                        $markdown_sub=sub {
                                Text::MultiMarkdown::markdown(shift, {use_metadata => 0});
                        }
                }
-               else {
+               if (! defined $markdown_sub) {
                        eval q{use Text::Markdown};
                        if (! $@) {
                                if (Text::Markdown->can('markdown')) {
@@ -67,6 +83,6 @@ sub htmlize (@) { #{{{
        $content=Encode::decode_utf8($content);
 
        return $content;
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/mercurial.pm b/IkiWiki/Plugin/mercurial.pm
new file mode 100644 (file)
index 0000000..11fdec5
--- /dev/null
@@ -0,0 +1,256 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::mercurial;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+use open qw{:utf8 :std};
+
+sub import {
+       hook(type => "checkconfig", id => "mercurial", call => \&checkconfig);
+       hook(type => "getsetup", id => "mercurial", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub checkconfig () {
+       if (exists $config{mercurial_wrapper} && length $config{mercurial_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{mercurial_wrapper},
+                       wrappermode => (defined $config{mercurial_wrappermode} ? $config{mercurial_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               mercurial_wrapper => {
+                       type => "string",
+                       #example => # FIXME add example
+                       description => "mercurial post-commit hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               mercurial_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for mercurial_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       example => "http://example.com:8000/log/tip/[[file]]",
+                       description => "url to hg serve'd repository, to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://localhost:8000/?fd=[[r2]];file=[[file]]",
+                       description => "url to hg serve'd repository, to show diff ([[file]] and [[r2]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub mercurial_log ($) {
+       my $out = shift;
+       my @infos;
+
+       while (<$out>) {
+               my $line = $_;
+               my ($key, $value);
+
+               if (/^description:/) {
+                       $key = "description";
+                       $value = "";
+
+                       # slurp everything as the description text 
+                       # until the next changeset
+                       while (<$out>) {
+                               if (/^changeset: /) {
+                                       $line = $_;
+                                       last;
+                               }
+
+                               $value .= $_;
+                       }
+
+                       local $/ = "";
+                       chomp $value;
+                       $infos[$#infos]{$key} = $value;
+               }
+
+               chomp $line;
+               ($key, $value) = split /: +/, $line, 2;
+
+               if ($key eq "changeset") {
+                       push @infos, {};
+
+                       # remove the revision index, which is strictly 
+                       # local to the repository
+                       $value =~ s/^\d+://;
+               }
+
+               $infos[$#infos]{$key} = $value;
+       }
+       close $out;
+
+       return @infos;
+}
+
+sub rcs_update () {
+       my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_prepedit ($) {
+       return "";
+}
+
+sub rcs_commit ($$$;$$) {
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+
+       if (defined $user) {
+               $user = IkiWiki::possibly_foolish_untaint($user);
+       }
+       elsif (defined $ipaddr) {
+               $user = "Anonymous from ".IkiWiki::possibly_foolish_untaint($ipaddr);
+       }
+       else {
+               $user = "Anonymous";
+       }
+
+       $message = IkiWiki::possibly_foolish_untaint($message);
+       if (! length $message) {
+               $message = "no message given";
+       }
+
+       my @cmdline = ("hg", "-q", "-R", $config{srcdir}, "commit", 
+                      "-m", $message, "-u", $user);
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+
+       return undef; # success
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+       
+       error("rcs_commit_staged not implemented for mercurial"); # TODO
+}
+
+sub rcs_add ($) {
+       my ($file) = @_;
+
+       my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "add", "$config{srcdir}/$file");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+}
+
+sub rcs_remove ($) {
+       my ($file) = @_;
+
+       error("rcs_remove not implemented for mercurial"); # TODO
+}
+
+sub rcs_rename ($$) {
+       my ($src, $dest) = @_;
+
+       error("rcs_rename not implemented for mercurial"); # TODO
+}
+
+sub rcs_recentchanges ($) {
+       my ($num) = @_;
+
+       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v", "-l", $num,
+               "--style", "default");
+       open (my $out, "@cmdline |");
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+
+       my @ret;
+       foreach my $info (mercurial_log($out)) {
+               my @pages = ();
+               my @message = ();
+        
+               foreach my $msgline (split(/\n/, $info->{description})) {
+                       push @message, { line => $msgline };
+               }
+
+               foreach my $file (split / /,$info->{files}) {
+                       my $diffurl = defined $config{diffurl} ? $config{'diffurl'} : "";
+                       $diffurl =~ s/\[\[file\]\]/$file/go;
+                       $diffurl =~ s/\[\[r2\]\]/$info->{changeset}/go;
+
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       };
+               }
+
+               my $user = $info->{"user"};
+               $user =~ s/\s*<.*>\s*$//;
+               $user =~ s/^\s*//;
+
+               push @ret, {
+                       rev        => $info->{"changeset"},
+                       user       => $user,
+                       committype => "hg",
+                       when       => str2time($info->{"date"}),
+                       message    => [@message],
+                       pages      => [@pages],
+               };
+       }
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       # TODO
+}
+
+sub rcs_getctime ($) {
+       my ($file) = @_;
+
+       # XXX filename passes through the shell here, should try to avoid
+       # that just in case
+       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v",
+               "--style", "default", "$config{srcdir}/$file");
+       open (my $out, "@cmdline |");
+
+       my @log = mercurial_log($out);
+
+       if (length @log < 1) {
+               return 0;
+       }
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+       
+       my $ctime = str2time($log[$#log]->{"date"});
+       return $ctime;
+}
+
+1
index 671060fbfa677e300a1f5ec7036c1488957e88bf..514b0936907ce58edabcbafcb44d5559a154eec9 100644 (file)
@@ -4,17 +4,26 @@ package IkiWiki::Plugin::meta;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %metaheaders;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "meta", call => \&getsetup);
        hook(type => "needsbuild", id => "meta", call => \&needsbuild);
        hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1);
        hook(type => "pagetemplate", id => "meta", call => \&pagetemplate);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
-sub needsbuild (@) { #{{{
+sub needsbuild (@) {
        my $needsbuild=shift;
        foreach my $page (keys %pagestate) {
                if (exists $pagestate{$page}{meta}) {
@@ -29,16 +38,17 @@ sub needsbuild (@) { #{{{
        }
 }
 
-sub scrub ($) { #{{{
+sub scrub ($$) {
        if (IkiWiki::Plugin::htmlscrubber->can("sanitize")) {
-               return IkiWiki::Plugin::htmlscrubber::sanitize(content => shift);
+               return IkiWiki::Plugin::htmlscrubber::sanitize(
+                       content => shift, destpage => shift);
        }
        else {
                return shift;
        }
-} #}}}
+}
 
-sub safeurl ($) { #{{{
+sub safeurl ($) {
        my $url=shift;
        if (exists $IkiWiki::Plugin::htmlscrubber::{safe_url_regexp} &&
            defined $IkiWiki::Plugin::htmlscrubber::safe_url_regexp) {
@@ -47,9 +57,9 @@ sub safeurl ($) { #{{{
        else {
                return 1;
        }
-} #}}}
+}
 
-sub htmlize ($$$) { #{{{
+sub htmlize ($$$) {
        my $page = shift;
        my $destpage = shift;
 
@@ -58,7 +68,7 @@ sub htmlize ($$$) { #{{{
                IkiWiki::preprocess($page, $destpage, shift)));
 }
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        return "" unless @_;
        my %params=@_;
        my $key=shift;
@@ -84,6 +94,10 @@ sub preprocess (@) { #{{{
                $pagestate{$page}{meta}{description}=HTML::Entities::encode_numeric($value);
                # fallthrough
        }
+       elsif ($key eq 'guid') {
+               $pagestate{$page}{meta}{guid}=HTML::Entities::encode_numeric($value);
+               # fallthrough
+       }
        elsif ($key eq 'license') {
                push @{$metaheaders{$page}}, '<link rel="license" href="#page_license" />';
                $pagestate{$page}{meta}{license}=$value;
@@ -96,7 +110,7 @@ sub preprocess (@) { #{{{
        }
        elsif ($key eq 'link' && ! %params) {
                # hidden WikiLink
-               push @{$links{$page}}, $value;
+               add_link($page, $value);
                return "";
        }
        elsif ($key eq 'author') {
@@ -107,6 +121,20 @@ sub preprocess (@) { #{{{
                $pagestate{$page}{meta}{authorurl}=$value if safeurl($value);
                # fallthrough
        }
+       elsif ($key eq 'date') {
+               eval q{use Date::Parse};
+               if (! $@) {
+                       my $time = str2time($value);
+                       $IkiWiki::pagectime{$page}=$time if defined $time;
+               }
+       }
+       elsif ($key eq 'updated') {
+               eval q{use Date::Parse};
+               if (! $@) {
+                       my $time = str2time($value);
+                       $pagestate{$page}{meta}{updated}=$time if defined $time;
+               }
+       }
 
        if (! defined wantarray) {
                # avoid collecting duplicate data during scan pass
@@ -114,17 +142,10 @@ sub preprocess (@) { #{{{
        }
 
        # Metadata collection that happens only during preprocessing pass.
-       if ($key eq 'date') {
-               eval q{use Date::Parse};
-               if (! $@) {
-                       my $time = str2time($value);
-                       $IkiWiki::pagectime{$page}=$time if defined $time;
-               }
-       }
-       elsif ($key eq 'permalink') {
+       if ($key eq 'permalink') {
                if (safeurl($value)) {
                        $pagestate{$page}{meta}{permalink}=$value;
-                       push @{$metaheaders{$page}}, scrub('<link rel="bookmark" href="'.encode_entities($value).'" />');
+                       push @{$metaheaders{$page}}, scrub('<link rel="bookmark" href="'.encode_entities($value).'" />', $destpage);
                }
        }
        elsif ($key eq 'stylesheet') {
@@ -134,7 +155,7 @@ sub preprocess (@) { #{{{
                # editable page as a stylesheet
                my $stylesheet=bestlink($page, $value.".css");
                if (! length $stylesheet) {
-                       return "[[meta ".gettext("stylesheet not found")."]]";
+                       error gettext("stylesheet not found")
                }
                push @{$metaheaders{$page}}, '<link href="'.urlto($stylesheet, $page).
                        '" rel="'.encode_entities($rel).
@@ -142,17 +163,22 @@ sub preprocess (@) { #{{{
                        "\" type=\"text/css\" />";
        }
        elsif ($key eq 'openid') {
+               my $delegate=0; # both by default
+               if (exists $params{delegate}) {
+                       $delegate = 1 if lc $params{delegate} eq 'openid';
+                       $delegate = 2 if lc $params{delegate} eq 'openid2';
+               }
                if (exists $params{server} && safeurl($params{server})) {
                        push @{$metaheaders{$page}}, '<link href="'.encode_entities($params{server}).
-                               '" rel="openid.server" />';
+                               '" rel="openid.server" />' if $delegate ne 2;
                        push @{$metaheaders{$page}}, '<link href="'.encode_entities($params{server}).
-                               '" rel="openid2.provider" />';
+                               '" rel="openid2.provider" />' if $delegate ne 1;
                }
                if (safeurl($value)) {
                        push @{$metaheaders{$page}}, '<link href="'.encode_entities($value).
-                               '" rel="openid.delegate" />';
+                               '" rel="openid.delegate" />' if $delegate ne 2;
                        push @{$metaheaders{$page}}, '<link href="'.encode_entities($value).
-                               '" rel="openid2.local_id" />';
+                               '" rel="openid2.local_id" />' if $delegate ne 1;
                }
                if (exists $params{"xrds-location"} && safeurl($params{"xrds-location"})) {
                        push @{$metaheaders{$page}}, '<meta http-equiv="X-XRDS-Location"'.
@@ -165,11 +191,11 @@ sub preprocess (@) { #{{{
                if ($value !~ /^\w+:\/\//) {
                        my ($redir_page, $redir_anchor) = split /\#/, $value;
 
-                       add_depends($page, $redir_page);
                        my $link=bestlink($page, $redir_page);
                        if (! length $link) {
-                               return "[[meta ".gettext("redir page not found")."]]";
+                               error gettext("redir page not found")
                        }
+                       add_depends($page, $link);
 
                        $value=urlto($link, $page);
                        $value.='#'.$redir_anchor if defined $redir_anchor;
@@ -181,7 +207,7 @@ sub preprocess (@) { #{{{
                        my %seen;
                        while (exists $pagestate{$at}{meta}{redir}) {
                                if ($seen{$at}) {
-                                       return "[[meta ".gettext("redir cycle is not allowed")."]]";
+                                       error gettext("redir cycle is not allowed")
                                }
                                $seen{$at}=1;
                                $at=$pagestate{$at}{meta}{redir};
@@ -193,7 +219,7 @@ sub preprocess (@) { #{{{
                my $delay=int(exists $params{delay} ? $params{delay} : 0);
                my $redir="<meta http-equiv=\"refresh\" content=\"$delay; URL=$value\" />";
                if (! $safe) {
-                       $redir=scrub($redir);
+                       $redir=scrub($redir, $destpage);
                }
                push @{$metaheaders{$page}}, $redir;
        }
@@ -203,7 +229,7 @@ sub preprocess (@) { #{{{
                                join(" ", map {
                                        encode_entities($_)."=\"".encode_entities(decode_entities($params{$_}))."\""
                                } keys %params).
-                               " />\n");
+                               " />\n", $destpage);
                }
        }
        elsif ($key eq 'robots') {
@@ -212,13 +238,13 @@ sub preprocess (@) { #{{{
        }
        else {
                push @{$metaheaders{$page}}, scrub('<meta name="'.encode_entities($key).
-                       '" content="'.encode_entities($value).'" />');
+                       '" content="'.encode_entities($value).'" />', $destpage);
        }
 
        return "";
-} # }}}
+}
 
-sub pagetemplate (@) { #{{{
+sub pagetemplate (@) {
        my %params=@_;
         my $page=$params{page};
         my $destpage=$params{destpage};
@@ -246,9 +272,9 @@ sub pagetemplate (@) { #{{{
                        $template->param($field => htmlize($page, $destpage, $pagestate{$page}{meta}{$field}));
                }
        }
-} # }}}
+}
 
-sub match { #{{{
+sub match {
        my $field=shift;
        my $page=shift;
        
@@ -260,7 +286,7 @@ sub match { #{{{
                $val=$pagestate{$page}{meta}{$field};
        }
        elsif ($field eq 'title') {
-               $val=pagetitle($page);
+               $val = pagetitle($page);
        }
 
        if (defined $val) {
@@ -274,28 +300,28 @@ sub match { #{{{
        else {
                return IkiWiki::FailReason->new("$page does not have a $field");
        }
-} #}}}
+}
 
 package IkiWiki::PageSpec;
 
-sub match_title ($$;@) { #{{{
+sub match_title ($$;@) {
        IkiWiki::Plugin::meta::match("title", @_);      
-} #}}}
+}
 
-sub match_author ($$;@) { #{{{
+sub match_author ($$;@) {
        IkiWiki::Plugin::meta::match("author", @_);
-} #}}}
+}
 
-sub match_authorurl ($$;@) { #{{{
+sub match_authorurl ($$;@) {
        IkiWiki::Plugin::meta::match("authorurl", @_);
-} #}}}
+}
 
-sub match_license ($$;@) { #{{{
+sub match_license ($$;@) {
        IkiWiki::Plugin::meta::match("license", @_);
-} #}}}
+}
 
-sub match_copyright ($$;@) { #{{{
+sub match_copyright ($$;@) {
        IkiWiki::Plugin::meta::match("copyright", @_);
-} #}}}
+}
 
 1
index 3997e6fefcd31c15a8fa6df7e559a6ffdf84e863..737dcf767379e69819bc71c4f7d02800be5b62f6 100644 (file)
@@ -3,21 +3,40 @@ package IkiWiki::Plugin::mirrorlist;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "mirrorlist", call => \&getsetup);
        hook(type => "pagetemplate", id => "mirrorlist", call => \&pagetemplate);
-} # }}}
+}
 
-sub pagetemplate (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               mirrorlist => {
+                       type => "string",
+                       example => {},
+                       description => "list of mirrors",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub pagetemplate (@) {
        my %params=@_;
         my $template=$params{template};
        
-       $template->param(extrafooter => mirrorlist($params{page}))
-               if $template->query(name => "extrafooter");
-} # }}}
+       if ($template->query(name => "extrafooter")) {
+               my $value=$template->param("extrafooter");
+               $value.=mirrorlist($params{page});
+               $template->param(extrafooter => $value);
+       }
+}
 
-sub mirrorlist ($) { #{{{
+sub mirrorlist ($) {
        my $page=shift;
        return "<p>".
                (keys %{$config{mirrorlist}} > 1 ? gettext("Mirrors") : gettext("Mirror")).
@@ -30,6 +49,6 @@ sub mirrorlist ($) { #{{{
                        } keys %{$config{mirrorlist}}
                ).
                "</p>";
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/monotone.pm b/IkiWiki/Plugin/monotone.pm
new file mode 100644 (file)
index 0000000..05c5a51
--- /dev/null
@@ -0,0 +1,694 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::monotone;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Monotone;
+use Date::Parse qw(str2time);
+use Date::Format qw(time2str);
+
+my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate sha1sums
+
+sub import {
+       hook(type => "checkconfig", id => "monotone", call => \&checkconfig);
+       hook(type => "getsetup", id => "monotone", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub checkconfig () {
+       if (!defined($config{mtnrootdir})) {
+               $config{mtnrootdir} = $config{srcdir};
+       }
+       if (! -d "$config{mtnrootdir}/_MTN") {
+               error("Ikiwiki srcdir does not seem to be a Monotone workspace (or set the mtnrootdir)!");
+       }
+       
+       my $child = open(MTN, "-|");
+       if (! $child) {
+               open STDERR, ">/dev/null";
+               exec("mtn", "version") || error("mtn version failed to run");
+       }
+
+       my $version=undef;
+       while (<MTN>) {
+               if (/^monotone (\d+\.\d+) /) {
+                       $version=$1;
+               }
+       }
+
+       close MTN || debug("mtn version exited $?");
+
+       if (!defined($version)) {
+               error("Cannot determine monotone version");
+       }
+       if ($version < 0.38) {
+               error("Monotone version too old, is $version but required 0.38");
+       }
+
+       if (defined $config{mtn_wrapper} && length $config{mtn_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{mtn_wrapper},
+                       wrappermode => (defined $config{mtn_wrappermode} ? $config{mtn_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               mtn_wrapper => {
+                       type => "string",
+                       example => "/srv/mtn/wiki/_MTN/ikiwiki-netsync-hook",
+                       description => "monotone netsync hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               mtn_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for mtn_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               mtnkey => {
+                       type => "string",
+                       example => 'web@example.com',
+                       description => "your monotone key",
+                       safe => 1,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       example => "http://viewmtn.example.com/branch/head/filechanges/com.example.branch/[[file]]",
+                       description => "viewmtn url to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://viewmtn.example.com/revision/diff/[[r1]]/with/[[r2]]/[[file]]",
+                       description => "viewmtn url to show a diff ([[r1]], [[r2]], and [[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               mtnsync => {
+                       type => "boolean",
+                       example => 0,
+                       description => "sync on update and commit?",
+                       safe => 0, # paranoia
+                       rebuild => 0,
+               },
+               mtnrootdir => {
+                       type => "string",
+                       description => "path to your workspace (defaults to the srcdir; specify if the srcdir is a subdirectory of the workspace)",
+                       safe => 0, # path
+                       rebuild => 0,
+               },
+}
+
+sub get_rev () {
+       my $sha1 = `mtn --root=$config{mtnrootdir} automate get_base_revision_id`;
+
+       ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
+       if (! $sha1) {
+               debug("Unable to get base revision for '$config{srcdir}'.")
+       }
+
+       return $sha1;
+}
+
+sub get_rev_auto ($) {
+       my $automator=shift;
+
+       my @results = $automator->call("get_base_revision_id");
+
+       my $sha1 = $results[0];
+       ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
+       if (! $sha1) {
+               debug("Unable to get base revision for '$config{srcdir}'.")
+       }
+
+       return $sha1;
+}
+
+sub mtn_merge ($$$$) {
+       my $leftRev=shift;
+       my $rightRev=shift;
+       my $branch=shift;
+       my $author=shift;
+    
+       my $mergeRev;
+
+       my $child = open(MTNMERGE, "-|");
+       if (! $child) {
+               open STDERR, ">&STDOUT";
+               exec("mtn", "--root=$config{mtnrootdir}",
+                    "explicit_merge", $leftRev, $rightRev,
+                    $branch, "--author", $author, "--key", 
+                    $config{mtnkey}) || error("mtn merge failed to run");
+       }
+
+       while (<MTNMERGE>) {
+               if (/^mtn.\s.merged.\s($sha1_pattern)$/) {
+                       $mergeRev=$1;
+               }
+       }
+       
+       close MTNMERGE || return undef;
+
+       debug("merged $leftRev, $rightRev to make $mergeRev");
+
+       return $mergeRev;
+}
+
+sub commit_file_to_new_rev ($$$$$$$$) {
+       my $automator=shift;
+       my $wsfilename=shift;
+       my $oldFileID=shift;
+       my $newFileContents=shift;
+       my $oldrev=shift;
+       my $branch=shift;
+       my $author=shift;
+       my $message=shift;
+       
+       #store the file
+       my ($out, $err) = $automator->call("put_file", $oldFileID, $newFileContents);
+       my ($newFileID) = ($out =~ m/^($sha1_pattern)$/);
+       error("Failed to store file data for $wsfilename in repository")
+               if (! defined $newFileID || length $newFileID != 40);
+
+       # get the mtn filename rather than the workspace filename
+       ($out, $err) = $automator->call("get_corresponding_path", $oldrev, $wsfilename, $oldrev);
+       my ($filename) = ($out =~ m/^file "(.*)"$/);
+       error("Couldn't find monotone repository path for file $wsfilename") if (! $filename);
+       debug("Converted ws filename of $wsfilename to repos filename of $filename");
+
+       # then stick in a new revision for this file
+       my $manifest = "format_version \"1\"\n\n".
+                      "new_manifest [0000000000000000000000000000000000000000]\n\n".
+                      "old_revision [$oldrev]\n\n".
+                      "patch \"$filename\"\n".
+                      " from [$oldFileID]\n".
+                      "   to [$newFileID]\n";
+       ($out, $err) = $automator->call("put_revision", $manifest);
+       my ($newRevID) = ($out =~ m/^($sha1_pattern)$/);
+       error("Unable to make new monotone repository revision")
+               if (! defined $newRevID || length $newRevID != 40);
+       debug("put revision: $newRevID");
+       
+       # now we need to add certs for this revision...
+       # author, branch, changelog, date
+       $automator->call("cert", $newRevID, "author", $author);
+       $automator->call("cert", $newRevID, "branch", $branch);
+       $automator->call("cert", $newRevID, "changelog", $message);
+       $automator->call("cert", $newRevID, "date",
+               time2str("%Y-%m-%dT%T", time, "UTC"));
+       
+       debug("Added certs for rev: $newRevID");
+       return $newRevID;
+}
+
+sub read_certs ($$) {
+       my $automator=shift;
+       my $rev=shift;
+       my @results = $automator->call("certs", $rev);
+       my @ret;
+
+       my $line = $results[0];
+       while ($line =~ m/\s+key\s"(.*?)"\nsignature\s"(ok|bad|unknown)"\n\s+name\s"(.*?)"\n\s+value\s"(.*?)"\n\s+trust\s"(trusted|untrusted)"\n/sg) {
+               push @ret, {
+                       key => $1,
+                       signature => $2,
+                       name => $3,
+                       value => $4,
+                       trust => $5,
+               };
+       }
+
+       return @ret;
+}
+
+sub get_changed_files ($$) {
+       my $automator=shift;
+       my $rev=shift;
+       
+       my @results = $automator->call("get_revision", $rev);
+       my $changes=$results[0];
+
+       my @ret;
+       my %seen = ();
+       
+       while ($changes =~ m/\s*(add_file|patch|delete|rename)\s"(.*?)(?<!\\)"\n/sg) {
+               my $file = $2;
+               # don't add the same file multiple times
+               if (! $seen{$file}) {
+                       push @ret, $file;
+                       $seen{$file} = 1;
+               }
+       }
+       
+       return @ret;
+}
+
+sub rcs_update () {
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       if (defined($config{mtnsync}) && $config{mtnsync}) {
+               if (system("mtn", "--root=$config{mtnrootdir}", "sync",
+                          "--quiet", "--ticker=none", 
+                          "--key", $config{mtnkey}) != 0) {
+                       debug("monotone sync failed before update");
+               }
+       }
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "update", "--quiet") != 0) {
+               debug("monotone update failed");
+       }
+}
+
+sub rcs_prepedit ($) {
+       my $file=shift;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       # For monotone, return the revision of the file when
+       # editing begins.
+       return get_rev();
+}
+
+sub rcs_commit ($$$;$$) {
+       # Tries to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on failure.
+       # The file is relative to the srcdir.
+       my $file=shift;
+       my $message=shift;
+       my $rcstoken=shift;
+       my $user=shift;
+       my $ipaddr=shift;
+       my $author;
+
+       if (defined $user) {
+               $author="Web user: " . $user;
+       }
+       elsif (defined $ipaddr) {
+               $author="Web IP: " . $ipaddr;
+       }
+       else {
+               $author="Web: Anonymous";
+       }
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       my ($oldrev)= $rcstoken=~ m/^($sha1_pattern)$/; # untaint
+       my $rev = get_rev();
+       if (defined $rev && defined $oldrev && $rev ne $oldrev) {
+               my $automator = Monotone->new();
+               $automator->open_args("--root", $config{mtnrootdir}, "--key", $config{mtnkey});
+
+               # Something has been committed, has this file changed?
+               my ($out, $err);
+               $automator->setOpts("r", $oldrev, "r", $rev);
+               ($out, $err) = $automator->call("content_diff", $file);
+               debug("Problem committing $file") if ($err ne "");
+               my $diff = $out;
+               
+               if ($diff) {
+                       # Commit a revision with just this file changed off
+                       # the old revision.
+                       #
+                       # first get the contents
+                       debug("File changed: forming branch");
+                       my $newfile=readfile("$config{srcdir}/$file");
+                       
+                       # then get the old content ID from the diff
+                       if ($diff !~ m/^---\s$file\s+($sha1_pattern)$/m) {
+                               error("Unable to find previous file ID for $file");
+                       }
+                       my $oldFileID = $1;
+
+                       # get the branch we're working in
+                       ($out, $err) = $automator->call("get_option", "branch");
+                       chomp $out;
+                       error("Illegal branch name in monotone workspace") if ($out !~ m/^([-\@\w\.]+)$/);
+                       my $branch = $1;
+
+                       # then put the new content into the DB (and record the new content ID)
+                       my $newRevID = commit_file_to_new_rev($automator, $file, $oldFileID, $newfile, $oldrev, $branch, $author, $message);
+
+                       $automator->close();
+
+                       # if we made it to here then the file has been committed... revert the local copy
+                       if (system("mtn", "--root=$config{mtnrootdir}", "revert", $file) != 0) {
+                               debug("Unable to revert $file after merge on conflicted commit!");
+                       }
+                       debug("Divergence created! Attempting auto-merge.");
+
+                       # see if it will merge cleanly
+                       $ENV{MTN_MERGE}="fail";
+                       my $mergeResult = mtn_merge($newRevID, $rev, $branch, $author);
+                       $ENV{MTN_MERGE}="";
+
+                       # push any changes so far
+                       if (defined($config{mtnsync}) && $config{mtnsync}) {
+                               if (system("mtn", "--root=$config{mtnrootdir}", "push", "--quiet", "--ticker=none", "--key", $config{mtnkey}) != 0) {
+                                       debug("monotone push failed");
+                               }
+                       }
+                       
+                       if (defined($mergeResult)) {
+                               # everything is merged - bring outselves up to date
+                               if (system("mtn", "--root=$config{mtnrootdir}",
+                                          "update", "-r", $mergeResult) != 0) {
+                                       debug("Unable to update to rev $mergeResult after merge on conflicted commit!");
+                               }
+                       }
+                       else {
+                               debug("Auto-merge failed.  Using diff-merge to add conflict markers.");
+                               
+                               $ENV{MTN_MERGE}="diffutils";
+                               $ENV{MTN_MERGE_DIFFUTILS}="partial=true";
+                               $mergeResult = mtn_merge($newRevID, $rev, $branch, $author);
+                               $ENV{MTN_MERGE}="";
+                               $ENV{MTN_MERGE_DIFFUTILS}="";
+                               
+                               if (!defined($mergeResult)) {
+                                       debug("Unable to insert conflict markers!");
+                                       error("Your commit succeeded. Unfortunately, someone else committed something to the same ".
+                                               "part of the wiki at the same time. Both versions are stored in the monotone repository, ".
+                                               "but at present the different versions cannot be reconciled through the web interface. ".
+                                               "Please use the non-web interface to resolve the conflicts.");
+                               }
+                               
+                               if (system("mtn", "--root=$config{mtnrootdir}",
+                                          "update", "-r", $mergeResult) != 0) {
+                                       debug("Unable to update to rev $mergeResult after conflict-enhanced merge on conflicted commit!");
+                               }
+                               
+                               # return "conflict enhanced" file to the user
+                               # for cleanup note, this relies on the fact
+                               # that ikiwiki seems to call rcs_prepedit()
+                               # again after we return
+                               return readfile("$config{srcdir}/$file");
+                       }
+                       return undef;
+               }
+               $automator->close();
+       }
+
+       # If we reached here then the file we're looking at hasn't changed
+       # since $oldrev. Commit it.
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "commit", "--quiet",
+                  "--author", $author, "--key", $config{mtnkey}, "-m",
+                  IkiWiki::possibly_foolish_untaint($message), $file) != 0) {
+               debug("Traditional commit failed! Returning data as conflict.");
+               my $conflict=readfile("$config{srcdir}/$file");
+               if (system("mtn", "--root=$config{mtnrootdir}", "revert",
+                          "--quiet", $file) != 0) {
+                       debug("monotone revert failed");
+               }
+               return $conflict;
+       }
+       if (defined($config{mtnsync}) && $config{mtnsync}) {
+               if (system("mtn", "--root=$config{mtnrootdir}", "push",
+                          "--quiet", "--ticker=none", "--key",
+                          $config{mtnkey}) != 0) {
+                       debug("monotone push failed");
+               }
+       }
+
+       return undef # success
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+       
+       # Note - this will also commit any spurious changes that happen to be
+       # lying around in the working copy.  There shouldn't be any, but...
+       
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       my $author;
+
+       if (defined $user) {
+               $author="Web user: " . $user;
+       }
+       elsif (defined $ipaddr) {
+               $author="Web IP: " . $ipaddr;
+       }
+       else {
+               $author="Web: Anonymous";
+       }
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "commit", "--quiet",
+                  "--author", $author, "--key", $config{mtnkey}, "-m",
+                  IkiWiki::possibly_foolish_untaint($message)) != 0) {
+               error("Monotone commit failed");
+       }
+}
+
+sub rcs_add ($) {
+       my $file=shift;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "add", "--quiet",
+                  $file) != 0) {
+               error("Monotone add failed");
+       }
+}
+
+sub rcs_remove ($) {
+       my $file = shift;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       # Note: it is difficult to undo a remove in Monotone at the moment.
+       # Until this is fixed, it might be better to make 'rm' move things
+       # into an attic, rather than actually remove them.
+       # To resurrect a file, you currently add a new file with the contents
+       # you want it to have.  This loses all connectivity and automated
+       # merging with the 'pre-delete' versions of the file.
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "rm", "--quiet",
+                  $file) != 0) {
+               error("Monotone remove failed");
+       }
+}
+
+sub rcs_rename ($$) {
+       my ($src, $dest) = @_;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       if (system("mtn", "--root=$config{mtnrootdir}", "rename", "--quiet",
+                  $src, $dest) != 0) {
+               error("Monotone rename failed");
+       }
+}
+
+sub rcs_recentchanges ($) {
+       my $num=shift;
+       my @ret;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       # use log --brief to get a list of revs, as this
+       # gives the results in a nice order
+       # (otherwise we'd have to do our own date sorting)
+
+       my @revs;
+
+       my $child = open(MTNLOG, "-|");
+       if (! $child) {
+               exec("mtn", "log", "--root=$config{mtnrootdir}", "--no-graph",
+                    "--brief", "--last=$num") || error("mtn log failed to run");
+       }
+
+       while (my $line = <MTNLOG>) {
+               if ($line =~ m/^($sha1_pattern)/) {
+                       push @revs, $1;
+               }
+       }
+       close MTNLOG || debug("mtn log exited $?");
+
+       my $automator = Monotone->new();
+       $automator->open(undef, $config{mtnrootdir});
+
+       while (@revs != 0) {
+               my $rev = shift @revs;
+               # first go through and figure out the messages, etc
+
+               my $certs = [read_certs($automator, $rev)];
+               
+               my $user;
+               my $when;
+               my $committype;
+               my (@pages, @message);
+               
+               foreach my $cert (@$certs) {
+                       if ($cert->{signature} eq "ok" &&
+                           $cert->{trust} eq "trusted") {
+                               if ($cert->{name} eq "author") {
+                                       $user = $cert->{value};
+                                       # detect the source of the commit
+                                       # from the changelog
+                                       if ($cert->{key} eq $config{mtnkey}) {
+                                               $committype = "web";
+                                       } else {
+                                               $committype = "mtn";
+                                       }
+                               } elsif ($cert->{name} eq "date") {
+                                       $when = str2time($cert->{value}, 'UTC');
+                               } elsif ($cert->{name} eq "changelog") {
+                                       my $messageText = $cert->{value};
+                                       # split the changelog into multiple
+                                       # lines
+                                       foreach my $msgline (split(/\n/, $messageText)) {
+                                               push @message, { line => $msgline };
+                                       }
+                               }
+                       }
+               }
+               
+               my @changed_files = get_changed_files($automator, $rev);
+               
+               my ($out, $err) = $automator->call("parents", $rev);
+               my @parents = ($out =~ m/^($sha1_pattern)$/);
+               my $parent = $parents[0];
+
+               foreach my $file (@changed_files) {
+                       next unless length $file;
+                       
+                       if (defined $config{diffurl} and (@parents == 1)) {
+                               my $diffurl=$config{diffurl};
+                               $diffurl=~s/\[\[r1\]\]/$parent/g;
+                               $diffurl=~s/\[\[r2\]\]/$rev/g;
+                               $diffurl=~s/\[\[file\]\]/$file/g;
+                               push @pages, {
+                                       page => pagename($file),
+                                       diffurl => $diffurl,
+                               };
+                       }
+                       else {
+                               push @pages, {
+                                       page => pagename($file),
+                               }
+                       }
+               }
+               
+               push @ret, {
+                       rev => $rev,
+                       user => $user,
+                       committype => $committype,
+                       when => $when,
+                       message => [@message],
+                       pages => [@pages],
+               } if @pages;
+       }
+
+       $automator->close();
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       my $rev=shift;
+       my ($sha1) = $rev =~ /^($sha1_pattern)$/; # untaint
+       
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       my $child = open(MTNDIFF, "-|");
+       if (! $child) {
+               exec("mtn", "diff", "--root=$config{mtnrootdir}", "-r", "p:".$sha1, "-r", $sha1) || error("mtn diff $sha1 failed to run");
+       }
+
+       my (@lines) = <MTNDIFF>;
+
+       close MTNDIFF || debug("mtn diff $sha1 exited $?");
+
+       if (wantarray) {
+               return @lines;
+       }
+       else {
+               return join("", @lines);
+       }
+}
+
+sub rcs_getctime ($) {
+       my $file=shift;
+
+       chdir $config{srcdir}
+           or error("Cannot chdir to $config{srcdir}: $!");
+
+       my $child = open(MTNLOG, "-|");
+       if (! $child) {
+               exec("mtn", "log", "--root=$config{mtnrootdir}", "--no-graph",
+                    "--brief", $file) || error("mtn log $file failed to run");
+       }
+
+       my $firstRev;
+       while (<MTNLOG>) {
+               if (/^($sha1_pattern)/) {
+                       $firstRev=$1;
+               }
+       }
+       close MTNLOG || debug("mtn log $file exited $?");
+
+       if (! defined $firstRev) {
+               debug "failed to parse mtn log for $file";
+               return 0;
+       }
+
+       my $automator = Monotone->new();
+       $automator->open(undef, $config{mtnrootdir});
+
+       my $certs = [read_certs($automator, $firstRev)];
+
+       $automator->close();
+
+       my $date;
+
+       foreach my $cert (@$certs) {
+               if ($cert->{signature} eq "ok" && $cert->{trust} eq "trusted") {
+                       if ($cert->{name} eq "date") {
+                               $date = $cert->{value};
+                       }
+               }
+       }
+
+       if (! defined $date) {
+               debug "failed to find date cert for revision $firstRev when looking for creation time of $file";
+               return 0;
+       }
+
+       $date=str2time($date, 'UTC');
+       debug("found ctime ".localtime($date)." for $file");
+       return $date;
+}
+
+1
index 667cd64154803c37e6aad977932767cadba4f5a6..77d5fb0772846dde323fd78a809f936365224fa5 100644 (file)
@@ -3,15 +3,24 @@ package IkiWiki::Plugin::more;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my $linktext = gettext("more");
 
-sub import { #{{{
-       hook(type => "preprocess",  id => "more", call => \&preprocess);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "more", call => \&getsetup);
+       hook(type => "preprocess", id => "more", call => \&preprocess);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        $params{linktext} = $linktext unless defined $params{linktext};
diff --git a/IkiWiki/Plugin/norcs.pm b/IkiWiki/Plugin/norcs.pm
new file mode 100644 (file)
index 0000000..bfe84c0
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+# Stubs for no revision control.
+package IkiWiki::Plugin::norcs;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import {
+       hook(type => "getsetup", id => "norcs", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => 0,
+               },
+}
+
+
+sub rcs_update () {
+}
+
+sub rcs_prepedit ($) {
+       return ""
+}
+
+sub rcs_commit ($$$;$$) {
+       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+       return undef # success
+}
+
+sub rcs_commit_staged ($$$) {
+       my ($message, $user, $ipaddr)=@_;
+       return undef # success
+}
+
+sub rcs_add ($) {
+}
+
+sub rcs_remove ($) {
+}
+
+sub rcs_rename ($$) {
+}
+
+sub rcs_recentchanges ($) {
+}
+
+sub rcs_diff ($) {
+}
+
+sub rcs_getctime ($) {
+       error gettext("getctime not implemented");
+}
+
+1
index c835f01061ea8a5364d369b768ebbada2fb6acfd..1bec4b013a9be6686f08a29b2c1a6658b353c635 100644 (file)
@@ -3,20 +3,28 @@ package IkiWiki::Plugin::opendiscussion;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "opendiscussion", call => \&getsetup);
        hook(type => "canedit", id => "opendiscussion", call => \&canedit);
-} # }}}
+}
 
-sub canedit ($$) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub canedit ($$) {
        my $page=shift;
        my $cgi=shift;
        my $session=shift;
 
-       my $discussion=gettext("discussion");
-       return "" if $page=~/(\/|^)\Q$discussion\E$/;
+       return "" if $page=~/(\/|^)\Q$config{discussionpage}\E$/;
        return undef;
-} #}}}
+}
 
 1
index 10a8fa22f46aa8116f10e13a48ac01678b8ba997..dc0e0f48ee98e70313abce4d195092989e5537c6 100644 (file)
@@ -4,23 +4,39 @@ package IkiWiki::Plugin::openid;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "openid", call => \&getopt);
+       hook(type => "getsetup", id => "openid", call => \&getsetup);
        hook(type => "auth", id => "openid", call => \&auth);
        hook(type => "formbuilder_setup", id => "openid",
                call => \&formbuilder_setup, last => 1);
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
        eval q{use Getopt::Long};
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
        GetOptions("openidsignup=s" => \$config{openidsignup});
-} #}}}
+}
 
-sub formbuilder_setup (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               openidsignup => {
+                       type => "string",
+                       example => "http://myopenid.com/",
+                       description => "an url where users can signup for an OpenID",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub formbuilder_setup (@) {
        my %params=@_;
 
        my $form=$params{form};
@@ -32,7 +48,7 @@ sub formbuilder_setup (@) { #{{{
                # needing to depend on it.
                eval q{use Net::OpenID::Consumer};
                if ($@) {
-                       debug("unable to load Net::OpenID::Consumer, not enabling OpenID login");
+                       debug("unable to load Net::OpenID::Consumer, not enabling OpenID login ($@)");
                        return;
                }
 
@@ -76,7 +92,7 @@ sub formbuilder_setup (@) { #{{{
        }
 }
 
-sub validate ($$$;$) { #{{{
+sub validate ($$$;$) {
        my $q=shift;
        my $session=shift;
        my $openid_url=shift;
@@ -105,9 +121,9 @@ sub validate ($$$;$) { #{{{
        # eventually bounce them back to auth()
        IkiWiki::redirect($q, $check_url);
        exit 0;
-} #}}}
+}
 
-sub auth ($$) { #{{{
+sub auth ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -131,9 +147,9 @@ sub auth ($$) { #{{{
                # myopenid.com affiliate support
                validate($q, $session, $q->param('openid_identifier'));
        }
-} #}}}
+}
 
-sub getobj ($$) { #{{{
+sub getobj ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -162,33 +178,6 @@ sub getobj ($$) { #{{{
                consumer_secret => sub { return shift()+$secret },
                required_root => $config{cgiurl},
        );
-} #}}}
-
-package IkiWiki;
-
-# This is not used by this plugin, but this seems the best place to put it.
-# Used elsewhere to pretty-display the name of an openid user.
-sub openiduser ($) { #{{{
-       my $user=shift;
-
-       if ($user =~ m!^https?://! &&
-           eval q{use Net::OpenID::VerifiedIdentity; 1} && !$@) {
-               my $oid=Net::OpenID::VerifiedIdentity->new(identity => $user);
-               my $display=$oid->display;
-               # Convert "user.somehost.com" to "user [somehost.com]".
-               if ($display !~ /\[/) {
-                       $display=~s/^(.*?)\.([^.]+\.[a-z]+)$/$1 [$2]/;
-               }
-               # Convert "http://somehost.com/user" to "user [somehost.com]".
-               if ($display !~ /\[/) {
-                       $display=~s/^https?:\/\/(.+)\/([^\/]+)$/$2 [$1]/;
-               }
-               $display=~s!^https?://!!; # make sure this is removed
-               eval q{use CGI 'escapeHTML'};
-               error($@) if $@;
-               return escapeHTML($display);
-       }
-       return;
 }
 
 1
index 0f96b9397445ea6f15b4b82cd2bded46143f6aaf..71122677273275d3e2f160bde3c8b44a8f333e49 100644 (file)
@@ -4,13 +4,22 @@ package IkiWiki::Plugin::orphans;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "orphans", call => \&getsetup);
        hook(type => "preprocess", id => "orphans", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        $params{pages}="*" unless defined $params{pages};
        
@@ -18,28 +27,22 @@ sub preprocess (@) { #{{{
        # register a dependency.
        add_depends($params{page}, $params{pages});
        
-       my %linkedto;
-       foreach my $p (keys %links) {
-               map { $linkedto{bestlink($p, $_)}=1 if length $_ }
-                       @{$links{$p}};
-       }
-       
        my @orphans;
-       my $discussion=gettext("discussion");
-       foreach my $page (keys %pagesources) {
-               next if $linkedto{$page} || $page eq 'index';
-               next unless pagespec_match($page, $params{pages}, location => $params{page});
+       foreach my $page (pagespec_match_list(
+                       [ grep { ! IkiWiki::backlink_pages($_) && $_ ne 'index' }
+                               keys %pagesources ],
+                       $params{pages}, location => $params{page})) {
                # If the page has a link to some other page, it's
                # indirectly linked to a page via that page's backlinks.
                next if grep { 
                        length $_ &&
-                       ($_ !~ /\/\Q$discussion\E$/i || ! $config{discussion}) &&
-                       bestlink($page, $_) !~ /^($page|)$/ 
+                       ($_ !~ /\/\Q$config{discussionpage}\E$/i || ! $config{discussion}) &&
+                       bestlink($page, $_) !~ /^(\Q$page\E|)$/ 
                } @{$links{$page}};
                push @orphans, $page;
        }
        
-       return gettext("All pages are linked to by other pages.") unless @orphans;
+       return gettext("All pages have other pages linking to them.") unless @orphans;
        return "<ul>\n".
                join("\n",
                        map {
@@ -49,6 +52,6 @@ sub preprocess (@) { #{{{
                                "</li>"
                        } sort @orphans).
                "</ul>\n";
-} # }}}
+}
 
 1
index 20291d7e535aecb1e6d1fe36a7ed713aec7edf84..c68fcbbe358762127411faec18840070f5bf8bd1 100644 (file)
@@ -4,15 +4,25 @@ package IkiWiki::Plugin::otl;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
+use open qw{:utf8 :std};
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "otl", call => \&getsetup);
        hook(type => "filter", id => "otl", call => \&filter);
        hook(type => "htmlize", id => "otl", call => \&htmlize);
 
-} # }}}
+}
 
-sub filter (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
+sub filter (@) {
        my %params=@_;
         
        # Munge up check boxes to look a little bit better. This is a hack.
@@ -24,9 +34,9 @@ sub filter (@) { #{{{
        $params{content}=~s/^(\s*)\[_\]\s/${1}$unchecked /mg;
         
        return $params{content};
-} # }}}
+}
 
-sub htmlize (@) { #{{{
+sub htmlize (@) {
        my %params=@_;
 
        # Can't use open2 since otl2html doesn't play nice with buffering.
@@ -85,6 +95,6 @@ sub htmlize (@) { #{{{
        $ret=~s/<body>.*//s;
        $ret=~s/<div class="Footer">.*//s;
        return $ret;
-} # }}}
+}
 
 1
index 2c20ca195dcd1f55ff4cdbe9ad70fed642c236af..5a2301af49232943d4f0889c0f3b9ba28f05396f 100644 (file)
@@ -3,13 +3,22 @@ package IkiWiki::Plugin::pagecount;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "pagecount", call => \&getsetup);
        hook(type => "preprocess", id => "pagecount", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        $params{pages}="*" unless defined $params{pages};
        
@@ -17,13 +26,14 @@ sub preprocess (@) { #{{{
        # register a dependency.
        add_depends($params{page}, $params{pages});
        
-       my @pages=keys %pagesources;
-       return $#pages+1 if $params{pages} eq "*"; # optimisation
-       my $count=0;
-       foreach my $page (@pages) {
-               $count++ if pagespec_match($page, $params{pages}, location => $params{page});
+       my @pages;
+       if ($params{pages} eq "*") {
+               @pages=keys %pagesources;
+       }
+       else {
+               @pages=pagespec_match_list([keys %pagesources], $params{pages}, location => $params{page});
        }
-       return $count;
-} # }}}
+       return $#pages+1;
+}
 
 1
index 5479e89864f792341505bea00b533b56b3bcc39f..874ead7e6de669c1d33c66b74984ef90504f9b8e 100644 (file)
@@ -12,16 +12,25 @@ package IkiWiki::Plugin::pagestats;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 # Names of the HTML classes to use for the tag cloud
 our @classes = ('smallestPC', 'smallPC', 'normalPC', 'bigPC', 'biggestPC' );
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "pagestats", call => \&getsetup);
        hook(type => "preprocess", id => "pagestats", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        $params{pages}="*" unless defined $params{pages};
        my $style = ($params{style} or 'cloud');
@@ -29,15 +38,23 @@ sub preprocess (@) { #{{{
        # Needs to update whenever a page is added or removed, so
        # register a dependency.
        add_depends($params{page}, $params{pages});
+       add_depends($params{page}, $params{among}) if exists $params{among};
        
        my %counts;
        my $max = 0;
-       foreach my $page (keys %links) {
-               if (pagespec_match($page, $params{pages}, location => $params{page})) {
-                       use IkiWiki::Render;
-                       $counts{$page} = scalar(IkiWiki::backlinks($page));
-                       $max = $counts{$page} if $counts{$page} > $max;
+       foreach my $page (pagespec_match_list([keys %links],
+                       $params{pages}, location => $params{page})) {
+               use IkiWiki::Render;
+
+               my @backlinks = IkiWiki::backlink_pages($page);
+
+               if (exists $params{among}) {
+                       @backlinks = pagespec_match_list(\@backlinks,
+                               $params{among}, location => $params{page});
                }
+
+               $counts{$page} = scalar(@backlinks);
+               $max = $counts{$page} if $counts{$page} > $max;
        }
 
        if ($style eq 'table') {
@@ -55,6 +72,8 @@ sub preprocess (@) { #{{{
 
                my $res = "<div class='pagecloud'>\n";
                foreach my $page (sort keys %counts) {
+                       next unless $counts{$page} > 0;
+
                        my $class = $classes[$counts{$page} * scalar(@classes) / ($max + 1)];
                        $res .= "<span class=\"$class\">".
                                htmllink($params{page}, $params{destpage}, $page).
@@ -64,6 +83,6 @@ sub preprocess (@) { #{{{
 
                return $res;
        }
-} # }}}
+}
 
 1
index 69a2433a8ffb1d74119762c8d9aeae3e3cedae01..1d8a84ca77726d5d8486fc632b2606b98e25b5f6 100644 (file)
@@ -3,22 +3,31 @@ package IkiWiki::Plugin::pagetemplate;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %templates;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "pagetemplate", call => \&getsetup);
        hook(type => "preprocess", id => "pagetemplate", call => \&preprocess);
        hook(type => "templatefile", id => "pagetemplate", call => \&templatefile);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
 
        if (! exists $params{template} ||
            $params{template} !~ /^[-A-Za-z0-9._+]+$/ ||
            ! defined IkiWiki::template_file($params{template})) {
-                return "[[pagetemplate ".gettext("bad or missing template")."]]";
+                error gettext("bad or missing template")
        }
 
        if ($params{page} eq $params{destpage}) {
@@ -26,9 +35,9 @@ sub preprocess (@) { #{{{
        }
 
        return "";
-} # }}}
+}
 
-sub templatefile (@) { #{{{
+sub templatefile (@) {
        my %params=@_;
 
        if (exists $templates{$params{page}}) {
@@ -36,6 +45,6 @@ sub templatefile (@) { #{{{
        }
        
        return undef;
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/parentlinks.pm b/IkiWiki/Plugin/parentlinks.pm
new file mode 100644 (file)
index 0000000..1ee69cb
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+# Ikiwiki parentlinks plugin.
+package IkiWiki::Plugin::parentlinks;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "parentlinks", id => "parentlinks", call => \&parentlinks);
+       hook(type => "pagetemplate", id => "parentlinks", call => \&pagetemplate);
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub parentlinks ($) {
+       my $page=shift;
+
+       my @ret;
+       my $path="";
+       my $title=$config{wikiname};
+       my $i=0;
+       my $depth=0;
+       my $height=0;
+
+       my @pagepath=(split("/", $page));
+       my $pagedepth=@pagepath;
+       foreach my $dir (@pagepath) {
+               next if $dir eq 'index';
+               $depth=$i;
+               $height=($pagedepth - $depth);
+               push @ret, {
+                       url => urlto(bestlink($page, $path), $page),
+                       page => $title,
+                       depth => $depth,
+                       height => $height,
+                       "depth_$depth" => 1,
+                       "height_$height" => 1,
+               };
+               $path.="/".$dir;
+               $title=pagetitle($dir);
+               $i++;
+       }
+       return @ret;
+}
+
+sub pagetemplate (@) {
+       my %params=@_;
+        my $page=$params{page};
+        my $template=$params{template};
+
+       if ($template->query(name => "parentlinks")) {
+               $template->param(parentlinks => [parentlinks($page)]);
+       }
+}
+
+1
index f3f1aa4bf2b7b5f761859d7a75a2c0d68f8b4eb7..8cf5af51ed03d47ff90963dd1aece3c9ea773cbb 100644 (file)
@@ -4,18 +4,40 @@ package IkiWiki::Plugin::passwordauth;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-        hook(type => "formbuilder_setup", id => "passwordauth",
-               call => \&formbuilder_setup);
-        hook(type => "formbuilder", id => "passwordauth",
-               call => \&formbuilder);
+sub import {
+       hook(type => "getsetup", id => "passwordauth", "call" => \&getsetup);
+       hook(type => "formbuilder_setup", id => "passwordauth", call => \&formbuilder_setup);
+       hook(type => "formbuilder", id => "passwordauth", call => \&formbuilder);
        hook(type => "sessioncgi", id => "passwordauth", call => \&sessioncgi);
-} # }}}
+       hook(type => "auth", id => "passwordauth", call => \&auth);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               account_creation_password => {
+                       type => "string",
+                       example => "s3cr1t",
+                       description => "a password that must be entered when signing up for an account",
+                       safe => 1,
+                       rebuild => 0,
+               },
+               password_cost => {
+                       type => "integer",
+                       example => 8,
+                       description => "cost of generating a password using Authen::Passphrase::BlowfishCrypt",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
 
 # Checks if a string matches a user's password, and returns true or false.
-sub checkpassword ($$;$) { #{{{
+sub checkpassword ($$;$) {
        my $user=shift;
        my $password=shift;
        my $field=shift || "password";
@@ -53,9 +75,9 @@ sub checkpassword ($$;$) { #{{{
        }
 
        return $ret;
-} #}}}
+}
 
-sub setpassword ($$;$) { #{{{
+sub setpassword ($$;$) {
        my $user=shift;
        my $password=shift;
        my $field=shift || "password";
@@ -73,9 +95,9 @@ sub setpassword ($$;$) { #{{{
        else {
                IkiWiki::userinfo_set($user, $field, $password);
        }
-} #}}}
+}
 
-sub formbuilder_setup (@) { #{{{
+sub formbuilder_setup (@) {
        my %params=@_;
 
        my $form=$params{form};
@@ -88,7 +110,9 @@ sub formbuilder_setup (@) { #{{{
                
                if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
                        $form->field(name => "confirm_password", type => "password");
-                       $form->field(name => "account_creation_password", type => "password") if (length $config{account_creation_password});
+                       $form->field(name => "account_creation_password", type => "password")
+                                if (defined $config{account_creation_password} &&
+                                    length $config{account_creation_password});
                        $form->field(name => "email", size => 50);
                        $form->title("register");
                        $form->text("");
@@ -125,7 +149,8 @@ sub formbuilder_setup (@) { #{{{
                                                shift eq $config{account_creation_password};
                                        },
                                        required => 1,
-                               ) if (length $config{account_creation_password});
+                               ) if (defined $config{account_creation_password} &&
+                                     length $config{account_creation_password});
                                $form->field(
                                        name => "email",
                                        validate => "EMAIL",
@@ -198,7 +223,7 @@ sub formbuilder_setup (@) { #{{{
        }
 }
 
-sub formbuilder (@) { #{{{
+sub formbuilder (@) {
        my %params=@_;
 
        my $form=$params{form};
@@ -259,7 +284,9 @@ sub formbuilder (@) { #{{{
                                error($@) if $@;
                                sendmail(
                                        To => IkiWiki::userinfo_get($user_name, "email"),
-                                       From => "$config{wikiname} admin <$config{adminemail}>",
+                                       From => "$config{wikiname} admin <".
+                                               (defined $config{adminemail} ? $config{adminemail} : "")
+                                               .">",
                                        Subject => "$config{wikiname} information",
                                        Message => $template->output,
                                ) or error(gettext("Failed to send mail"));
@@ -287,9 +314,9 @@ sub formbuilder (@) { #{{{
                        }
                }
        }
-} #}}}
+}
 
-sub sessioncgi ($$) { #{{{
+sub sessioncgi ($$) {
        my $q=shift;
        my $session=shift;
 
@@ -309,6 +336,12 @@ sub sessioncgi ($$) { #{{{
                IkiWiki::cgi_prefs($q, $session);
                exit;
        }
-} #}}}
+}
+
+sub auth ($$) {
+       # While this hook is not currently used, it needs to exist
+       # so ikiwiki knows that the wiki supports logins, and will
+       # enable the Preferences page.
+}
 
 1
index ee799a57a119b9e079cfc13f81b92b48317a5dc0..f5386d0cae4ccb638913c9d6a7ac9a8e2a3d94af 100644 (file)
@@ -3,13 +3,22 @@ package IkiWiki::Plugin::pingee;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-       hook(type => "cgi", id => "aggregate", call => \&cgi);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "pingee", call => \&getsetup);
+       hook(type => "cgi", id => "pingee", call => \&cgi);
+}
 
-sub cgi ($) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub cgi ($) {
        my $cgi=shift;
 
        if (defined $cgi->param('do') && $cgi->param("do") eq "ping") {
@@ -28,6 +37,6 @@ sub cgi ($) { #{{{
                IkiWiki::saveindex();
                exit 0;
        }
-} #}}}
+}
 
 1
index c6fa76e3f8fde2652e7703e50b84f03f1a1ff829..c20ecb5d4ef3a663f5496135f56ddb5369c5dd87 100644 (file)
@@ -3,19 +3,35 @@ package IkiWiki::Plugin::pinger;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %pages;
 my $pinged=0;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "pinger", call => \&getsetup);
        hook(type => "needsbuild", id => "pinger", call => \&needsbuild);
        hook(type => "preprocess", id => "ping", call => \&preprocess);
        hook(type => "delete", id => "pinger", call => \&ping);
        hook(type => "change", id => "pinger", call => \&ping);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               pinger_timeout => {
+                       type => "integer",
+                       example => 15,
+                       description => "how many seconds to try pinging before timing out",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
 
-sub needsbuild (@) { #{{{
+sub needsbuild (@) {
        my $needsbuild=shift;
        foreach my $page (keys %pagestate) {
                if (exists $pagestate{$page}{pinger}) {
@@ -29,12 +45,12 @@ sub needsbuild (@) { #{{{
                        }
                }
        }
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
        if (! exists $params{from} || ! exists $params{to}) {
-               return "[[ping ".gettext("requires 'from' and 'to' parameters")."]]";
+               error gettext("requires 'from' and 'to' parameters");
        }
        if ($params{from} eq $config{url}) {
                $pagestate{$params{destpage}}{pinger}{$params{to}}=1;
@@ -44,7 +60,7 @@ sub preprocess (@) { #{{{
        else {
                return sprintf(gettext("Ignoring ping directive for wiki %s (this wiki is %s)"), $params{from}, $config{url});
        }
-} # }}}
+}
 
 sub ping {
        if (! $pinged && %pages) {
@@ -90,7 +106,7 @@ sub ping {
                        # will still be avoided.
                        next if $url=~/^\Q$config{cgiurl}\E/;
                        
-                       $ua->head($url);
+                       $ua->get($url);
                }
                
                exit 0;
diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
new file mode 100644 (file)
index 0000000..12f41f6
--- /dev/null
@@ -0,0 +1,1190 @@
+#!/usr/bin/perl
+# .po as a wiki page type
+# Licensed under GPL v2 or greater
+# Copyright (C) 2008-2009 intrigeri <intrigeri@boum.org>
+# inspired by the GPL'd po4a-translate,
+# which is Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org)
+package IkiWiki::Plugin::po;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use Encode;
+eval q{use Locale::Po4a::Common qw(nowrapi18n !/.*/)};
+if ($@) {
+       print STDERR gettext("warning: Old po4a detected! Recommend upgrade to 0.35.")."\n";
+       eval q{use Locale::Po4a::Common qw(!/.*/)};
+       die $@ if $@;
+}
+use Locale::Po4a::Chooser;
+use Locale::Po4a::Po;
+use File::Basename;
+use File::Copy;
+use File::Spec;
+use File::Temp;
+use Memoize;
+use UNIVERSAL;
+
+my %translations;
+my @origneedsbuild;
+my %origsubs;
+
+memoize("istranslatable");
+memoize("_istranslation");
+memoize("percenttranslated");
+
+sub import {
+       hook(type => "getsetup", id => "po", call => \&getsetup);
+       hook(type => "checkconfig", id => "po", call => \&checkconfig);
+       hook(type => "needsbuild", id => "po", call => \&needsbuild);
+       hook(type => "scan", id => "po", call => \&scan, last => 1);
+       hook(type => "filter", id => "po", call => \&filter);
+       hook(type => "htmlize", id => "po", call => \&htmlize);
+       hook(type => "pagetemplate", id => "po", call => \&pagetemplate, last => 1);
+       hook(type => "rename", id => "po", call => \&renamepages, first => 1);
+       hook(type => "delete", id => "po", call => \&mydelete);
+       hook(type => "change", id => "po", call => \&change);
+       hook(type => "checkcontent", id => "po", call => \&checkcontent);
+       hook(type => "canremove", id => "po", call => \&canremove);
+       hook(type => "canrename", id => "po", call => \&canrename);
+       hook(type => "editcontent", id => "po", call => \&editcontent);
+       hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1);
+       hook(type => "formbuilder", id => "po", call => \&formbuilder);
+
+       $origsubs{'beautify_urlpath'}=\&IkiWiki::beautify_urlpath;
+       inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
+       $origsubs{'targetpage'}=\&IkiWiki::targetpage;
+       inject(name => "IkiWiki::targetpage", call => \&mytargetpage);
+       $origsubs{'urlto'}=\&IkiWiki::urlto;
+       inject(name => "IkiWiki::urlto", call => \&myurlto);
+       $origsubs{'cgiurl'}=\&IkiWiki::cgiurl;
+       inject(name => "IkiWiki::cgiurl", call => \&mycgiurl);
+}
+
+
+# ,----
+# | Table of contents
+# `----
+
+# 1. Hooks
+# 2. Injected functions
+# 3. Blackboxes for private data
+# 4. Helper functions
+# 5. PageSpecs
+
+
+# ,----
+# | Hooks
+# `----
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0,
+                       rebuild => 1,
+               },
+               po_master_language => {
+                       type => "string",
+                       example => {
+                               'code' => 'en',
+                               'name' => 'English'
+                       },
+                       description => "master language (non-PO files)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               po_slave_languages => {
+                       type => "string",
+                       example => {
+                               'fr' => 'Français',
+                               'es' => 'Español',
+                               'de' => 'Deutsch'
+                       },
+                       description => "slave languages (PO files)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               po_translatable_pages => {
+                       type => "pagespec",
+                       example => "* and !*/Discussion",
+                       description => "PageSpec controlling which pages are translatable",
+                       link => "ikiwiki/PageSpec",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               po_link_to => {
+                       type => "string",
+                       example => "current",
+                       description => "internal linking behavior (default/current/negotiated)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig () {
+       foreach my $field (qw{po_master_language}) {
+               if (! exists $config{$field} || ! defined $config{$field}) {
+                       error(sprintf(gettext("Must specify %s when using the %s plugin"),
+                                     $field, 'po'));
+               }
+       }
+
+       map {
+               islanguagecode($_)
+                       or error(sprintf(gettext("%s is not a valid language code"), $_));
+       } ($config{po_master_language}{code}, keys %{$config{po_slave_languages}});
+
+       if (! exists $config{po_translatable_pages} ||
+           ! defined $config{po_translatable_pages}) {
+               $config{po_translatable_pages}="";
+       }
+       if (! exists $config{po_link_to} ||
+           ! defined $config{po_link_to}) {
+               $config{po_link_to}='default';
+       }
+       elsif ($config{po_link_to} !~ /^(default|current|negotiated)$/) {
+               warn(sprintf(gettext('%s is not a valid value for po_link_to, falling back to po_link_to=default'),
+                            $config{po_link_to}));
+               $config{po_link_to}='default';
+       }
+       elsif ($config{po_link_to} eq "negotiated" && ! $config{usedirs}) {
+               warn(gettext('po_link_to=negotiated requires usedirs to be enabled, falling back to po_link_to=default'));
+               $config{po_link_to}='default';
+       }
+       unless ($config{po_link_to} eq 'default') {
+               $origsubs{'bestlink'}=\&IkiWiki::bestlink;
+               inject(name => "IkiWiki::bestlink", call => \&mybestlink);
+       }
+
+       push @{$config{wiki_file_prune_regexps}}, qr/\.pot$/;
+
+       # Translated versions of the underlays are added if available.
+       foreach my $underlay ("basewiki",
+                             map { m/^\Q$config{underlaydirbase}\E\/*(.*)/ }
+                                 reverse @{$config{underlaydirs}}) {
+               next if $underlay=~/^locale\//;
+
+               # Underlays containing the po files for slave languages.
+               foreach my $ll (keys %{$config{po_slave_languages}}) {
+                       add_underlay("po/$ll/$underlay")
+                               if -d "$config{underlaydirbase}/po/$ll/$underlay";
+               }
+       
+               if ($config{po_master_language}{code} ne 'en') {
+                       # Add underlay containing translated source files
+                       # for the master language.
+                       add_underlay("locale/$config{po_master_language}{code}/$underlay");
+               }
+       }
+}
+
+sub needsbuild () {
+       my $needsbuild=shift;
+
+       # backup @needsbuild content so that change() can know whether
+       # a given master page was rendered because its source file was changed
+       @origneedsbuild=(@$needsbuild);
+
+       flushmemoizecache();
+       buildtranslationscache();
+
+       # make existing translations depend on the corresponding master page
+       foreach my $master (keys %translations) {
+               map add_depends($_, $master), values %{otherlanguages($master)};
+       }
+}
+
+# Massage the recorded state of internal links so that:
+# - it matches the actually generated links, rather than the links as written
+#   in the pages' source
+# - backlinks are consistent in all cases
+sub scan (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $content=$params{content};
+
+       if (istranslation($page)) {
+               foreach my $destpage (@{$links{$page}}) {
+                       if (istranslatable($destpage)) {
+                               # replace the occurence of $destpage in $links{$page}
+                               for (my $i=0; $i<@{$links{$page}}; $i++) {
+                                       if (@{$links{$page}}[$i] eq $destpage) {
+                                               @{$links{$page}}[$i] = $destpage . '.' . lang($page);
+                                               last;
+                                       }
+                               }
+                       }
+               }
+       }
+       elsif (! istranslatable($page) && ! istranslation($page)) {
+               foreach my $destpage (@{$links{$page}}) {
+                       if (istranslatable($destpage)) {
+                               # make sure any destpage's translations has
+                               # $page in its backlinks
+                               push @{$links{$page}},
+                                       values %{otherlanguages($destpage)};
+                       }
+               }
+       }
+}
+
+# We use filter to convert PO to the master page's format,
+# since the rest of ikiwiki should not work on PO files.
+sub filter (@) {
+       my %params = @_;
+
+       my $page = $params{page};
+       my $destpage = $params{destpage};
+       my $content = $params{content};
+       if (istranslation($page) && ! alreadyfiltered($page, $destpage)) {
+               $content = po_to_markup($page, $content);
+               setalreadyfiltered($page, $destpage);
+       }
+       return $content;
+}
+
+sub htmlize (@) {
+       my %params=@_;
+
+       my $page = $params{page};
+       my $content = $params{content};
+
+       # ignore PO files this plugin did not create
+       return $content unless istranslation($page);
+
+       # force content to be htmlize'd as if it was the same type as the master page
+       return IkiWiki::htmlize($page, $page,
+               pagetype(srcfile($pagesources{masterpage($page)})),
+               $content);
+}
+
+sub pagetemplate (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $destpage=$params{destpage};
+       my $template=$params{template};
+
+       my ($masterpage, $lang) = istranslation($page);
+
+       if (istranslation($page) && $template->query(name => "percenttranslated")) {
+               $template->param(percenttranslated => percenttranslated($page));
+       }
+       if ($template->query(name => "istranslation")) {
+               $template->param(istranslation => scalar istranslation($page));
+       }
+       if ($template->query(name => "istranslatable")) {
+               $template->param(istranslatable => istranslatable($page));
+       }
+       if ($template->query(name => "HOMEPAGEURL")) {
+               $template->param(homepageurl => homepageurl($page));
+       }
+       if ($template->query(name => "otherlanguages")) {
+               $template->param(otherlanguages => [otherlanguagesloop($page)]);
+               map add_depends($page, $_), (values %{otherlanguages($page)});
+       }
+       if ($config{discussion} && istranslation($page)) {
+               if ($page !~ /.*\/\Q$config{discussionpage}\E$/i &&
+                  (length $config{cgiurl} ||
+                   exists $links{$masterpage."/".lc($config{discussionpage})})) {
+                       $template->param('discussionlink' => htmllink(
+                               $page,
+                               $destpage,
+                               $masterpage . '/' . $config{discussionpage},
+                               noimageinline => 1,
+                               forcesubpage => 0,
+                               linktext => $config{discussionpage},
+               ));
+               }
+       }
+       # Remove broken parentlink to ./index.html on home page's translations.
+       # It works because this hook has the "last" parameter set, to ensure it
+       # runs after parentlinks' own pagetemplate hook.
+       if ($template->param('parentlinks')
+           && istranslation($page)
+           && $masterpage eq "index") {
+               $template->param('parentlinks' => []);
+       }
+       if (ishomepage($page) && $template->query(name => "title")) {
+               $template->param(title => $config{wikiname});
+       }
+} # }}}
+
+# Add the renamed page translations to the list of to-be-renamed pages.
+sub renamepages (@) {
+       my %params = @_;
+
+       my %torename = %{$params{torename}};
+       my $session = $params{session};
+
+       # Save the page(s) the user asked to rename, so that our
+       # canrename hook can tell the difference between:
+       #  - a translation being renamed as a consequence of its master page
+       #    being renamed
+       #  - a user trying to directly rename a translation
+       # This is why this hook has to be run first, before the list of pages
+       # to rename is modified by other plugins.
+       my @orig_torename;
+       @orig_torename=@{$session->param("po_orig_torename")}
+               if defined $session->param("po_orig_torename");
+       push @orig_torename, $torename{src};
+       $session->param(po_orig_torename => \@orig_torename);
+       IkiWiki::cgi_savesession($session);
+
+       return () unless istranslatable($torename{src});
+
+       my @ret;
+       my %otherpages=%{otherlanguages($torename{src})};
+       while (my ($lang, $otherpage) = each %otherpages) {
+               push @ret, {
+                       src => $otherpage,
+                       srcfile => $pagesources{$otherpage},
+                       dest => otherlanguage($torename{dest}, $lang),
+                       destfile => $torename{dest}.".".$lang.".po",
+                       required => 0,
+               };
+       }
+       return @ret;
+}
+
+sub mydelete (@) {
+       my @deleted=@_;
+
+       map { deletetranslations($_) } grep istranslatablefile($_), @deleted;
+}
+
+sub change (@) {
+       my @rendered=@_;
+
+       # All meta titles are first extracted at scan time, i.e. before we turn
+       # PO files back into translated markdown; escaping of double-quotes in
+       # PO files breaks the meta plugin's parsing enough to save ugly titles
+       # to %pagestate at this time.
+       #
+       # Then, at render time, every page passes in turn through the Great
+       # Rendering Chain (filter->preprocess->linkify->htmlize), and the meta
+       # plugin's preprocess hook is this time in a position to correctly
+       # extract the titles from slave pages.
+       #
+       # This is, unfortunately, too late: if the page A, linking to the page
+       # B, is rendered before B, it will display the wrongly-extracted meta
+       # title as the link text to B.
+       #
+       # On the one hand, such a corner case only happens on rebuild: on
+       # refresh, every rendered page is fixed to contain correct meta titles.
+       # On the other hand, it can take some time to get every page fixed.
+       # We therefore re-render every rendered page after a rebuild to fix them
+       # at once. As this more or less doubles the time needed to rebuild the
+       # wiki, we do so only when really needed.
+
+       if (@rendered
+           && exists $config{rebuild} && defined $config{rebuild} && $config{rebuild}
+           && UNIVERSAL::can("IkiWiki::Plugin::meta", "getsetup")
+           && exists $config{meta_overrides_page_title}
+           && defined $config{meta_overrides_page_title}
+           && $config{meta_overrides_page_title}) {
+               debug(sprintf(gettext("rebuilding all pages to fix meta titles")));
+               resetalreadyfiltered();
+               require IkiWiki::Render;
+               foreach my $file (@rendered) {
+                       debug(sprintf(gettext("building %s"), $file));
+                       IkiWiki::render($file);
+               }
+       }
+
+       my $updated_po_files=0;
+
+       # Refresh/create POT and PO files as needed.
+       # (But avoid doing so if they are in an underlay directory.)
+       foreach my $file (grep {istranslatablefile($_)} @rendered) {
+               my $masterfile=srcfile($file);
+               my $page=pagename($file);
+               my $updated_pot_file=0;
+               # Only refresh POT file if it does not exist, or if
+               # $pagesources{$page} was changed: don't if only the HTML was
+               # refreshed, e.g. because of a dependency.
+               if ($masterfile eq "$config{srcdir}/$file" &&
+                  ((grep { $_ eq $pagesources{$page} } @origneedsbuild)
+                   || ! -e potfile($masterfile))) {
+                       refreshpot($masterfile);
+                       $updated_pot_file=1;
+               }
+               my @pofiles;
+               foreach my $po (pofiles($masterfile)) {
+                       next if ! $updated_pot_file && ! -e $po;
+                       next if grep { $po=~/\Q$_\E/ } @{$config{underlaydirs}};
+                       push @pofiles, $po;
+               }
+               if (@pofiles) {
+                       refreshpofiles($masterfile, @pofiles);
+                       map { s/^\Q$config{srcdir}\E\/*//; IkiWiki::rcs_add($_) } @pofiles if $config{rcs};
+                       $updated_po_files=1;
+               }
+       }
+
+       if ($updated_po_files) {
+               commit_and_refresh(
+                       gettext("updated PO files"),
+                       "IkiWiki::Plugin::po::change");
+       }
+}
+
+sub checkcontent (@) {
+       my %params=@_;
+
+       if (istranslation($params{page})) {
+               my $res = isvalidpo($params{content});
+               if ($res) {
+                       return undef;
+               }
+               else {
+                       return "$res";
+               }
+       }
+       return undef;
+}
+
+sub canremove (@) {
+       my %params = @_;
+
+       if (istranslation($params{page})) {
+               return gettext("Can not remove a translation. If the master page is removed, ".
+                              "however, its translations will be removed as well.");
+       }
+       return undef;
+}
+
+sub canrename (@) {
+       my %params = @_;
+       my $session = $params{session};
+
+       if (istranslation($params{src})) {
+               my $masterpage = masterpage($params{src});
+               # Tell the difference between:
+               #  - a translation being renamed as a consequence of its master page
+               #    being renamed, which is allowed
+               #  - a user trying to directly rename a translation, which is forbidden
+               # by looking for the master page in the list of to-be-renamed pages we
+               # saved early in the renaming process.
+               my $orig_torename = $session->param("po_orig_torename");
+               unless (grep { $_ eq $masterpage } @{$orig_torename}) {
+                       return gettext("Can not rename a translation. If the master page is renamed, ".
+                                      "however, its translations will be renamed as well.");
+               }
+       }
+       return undef;
+}
+
+# As we're previewing or saving a page, the content may have
+# changed, so tell the next filter() invocation it must not be lazy.
+sub editcontent () {
+       my %params=@_;
+
+       unsetalreadyfiltered($params{page}, $params{page});
+       return $params{content};
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+       my $form=$params{form};
+       my $q=$params{cgi};
+
+       return unless defined $form->field("do");
+
+       if ($form->field("do") eq "create") {
+               # Warn the user: new pages must be written in master language.
+               my $template=template("pocreatepage.tmpl");
+               $template->param(LANG => $config{po_master_language}{name});
+               $form->tmpl_param(message => $template->output);
+       }
+       elsif ($form->field("do") eq "edit") {
+               # Remove the rename/remove buttons on slave pages.
+               # This has to be done after the rename/remove plugins have added
+               # their buttons, which is why this hook must be run last.
+               # The canrename/canremove hooks already ensure this is forbidden
+               # at the backend level, so this is only UI sugar.
+               if (istranslation($form->field("page"))) {
+                       map {
+                               for (my $i = 0; $i < @{$params{buttons}}; $i++) {
+                                       if (@{$params{buttons}}[$i] eq $_) {
+                                               delete  @{$params{buttons}}[$i];
+                                               last;
+                                       }
+                               }
+                       } qw(Rename Remove);
+               }
+       }
+}
+
+sub formbuilder (@) {
+       my %params=@_;
+       my $form=$params{form};
+       my $q=$params{cgi};
+
+       return unless defined $form->field("do");
+
+       # Do not allow to create pages of type po: they are automatically created.
+       # The main reason to do so is to bypass the "favor the type of linking page
+       # on page creation" logic, which is unsuitable when a broken link is clicked
+       # on a slave (PO) page.
+       # This cannot be done in the formbuilder_setup hook as the list of types is
+       # computed later.
+       if ($form->field("do") eq "create") {
+               foreach my $field ($form->field) {
+                       next unless "$field" eq "type";
+                       if ($field->type eq 'select') {
+                               # remove po from the list of types
+                               my @types = grep { $_ ne 'po' } $field->options;
+                               $field->options(\@types) if @types;
+                       }
+               }
+       }
+}
+
+# ,----
+# | Injected functions
+# `----
+
+# Implement po_link_to 'current' and 'negotiated' settings.
+# Not injected otherwise.
+sub mybestlink ($$) {
+       my $page=shift;
+       my $link=shift;
+
+       my $res=$origsubs{'bestlink'}->(masterpage($page), $link);
+       if (length $res
+           && istranslatable($res)
+           && istranslation($page)) {
+               return $res . "." . lang($page);
+       }
+       return $res;
+}
+
+sub mybeautify_urlpath ($) {
+       my $url=shift;
+
+       my $res=$origsubs{'beautify_urlpath'}->($url);
+       if ($config{po_link_to} eq "negotiated") {
+               $res =~ s!/\Qindex.$config{po_master_language}{code}.$config{htmlext}\E$!/!;
+               $res =~ s!/\Qindex.$config{htmlext}\E$!/!;
+               map {
+                       $res =~ s!/\Qindex.$_.$config{htmlext}\E$!/!;
+               } (keys %{$config{po_slave_languages}});
+       }
+       return $res;
+}
+
+sub mytargetpage ($$) {
+       my $page=shift;
+       my $ext=shift;
+
+       if (istranslation($page) || istranslatable($page)) {
+               my ($masterpage, $lang) = (masterpage($page), lang($page));
+               if (! $config{usedirs} || $masterpage eq 'index') {
+                       return $masterpage . "." . $lang . "." . $ext;
+               }
+               else {
+                       return $masterpage . "/index." . $lang . "." . $ext;
+               }
+       }
+       return $origsubs{'targetpage'}->($page, $ext);
+}
+
+sub myurlto ($$;$) {
+       my $to=shift;
+       my $from=shift;
+       my $absolute=shift;
+
+       # workaround hard-coded /index.$config{htmlext} in IkiWiki::urlto()
+       if (! length $to
+           && $config{po_link_to} eq "current"
+           && istranslatable('index')) {
+               return IkiWiki::beautify_urlpath(IkiWiki::baseurl($from) . "index." . lang($from) . ".$config{htmlext}");
+       }
+       # avoid using our injected beautify_urlpath if run by cgi_editpage,
+       # so that one is redirected to the just-edited page rather than to the
+       # negociated translation; to prevent unnecessary fiddling with caller/inject,
+       # we only do so when our beautify_urlpath would actually do what we want to
+       # avoid, i.e. when po_link_to = negotiated.
+       # also avoid doing so when run by cgi_goto, so that the links on recentchanges
+       # page actually lead to the exact page they pretend to.
+       if ($config{po_link_to} eq "negotiated") {
+               my @caller = caller(1);
+               my $use_orig = 0;
+               $use_orig = 1 if (exists $caller[3] && defined $caller[3]
+                                && ($caller[3] eq "IkiWiki::cgi_editpage" ||
+                                    $caller[3] eq "IkiWiki::Plugin::goto::cgi_goto")
+                                );
+               inject(name => "IkiWiki::beautify_urlpath", call => $origsubs{'beautify_urlpath'})
+                       if $use_orig;
+               my $res = $origsubs{'urlto'}->($to,$from,$absolute);
+               inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath)
+                       if $use_orig;
+               return $res;
+       }
+       else {
+               return $origsubs{'urlto'}->($to,$from,$absolute)
+       }
+}
+
+sub mycgiurl (@) {
+       my %params=@_;
+
+       # slave pages have no subpages
+       if (istranslation($params{'from'})) {
+               $params{'from'} = masterpage($params{'from'});
+       }
+       return $origsubs{'cgiurl'}->(%params);
+}
+
+# ,----
+# | Blackboxes for private data
+# `----
+
+{
+       my %filtered;
+
+       sub alreadyfiltered($$) {
+               my $page=shift;
+               my $destpage=shift;
+
+               return exists $filtered{$page}{$destpage}
+                        && $filtered{$page}{$destpage} eq 1;
+       }
+
+       sub setalreadyfiltered($$) {
+               my $page=shift;
+               my $destpage=shift;
+
+               $filtered{$page}{$destpage}=1;
+       }
+
+       sub unsetalreadyfiltered($$) {
+               my $page=shift;
+               my $destpage=shift;
+
+               if (exists $filtered{$page}{$destpage}) {
+                       delete $filtered{$page}{$destpage};
+               }
+       }
+
+       sub resetalreadyfiltered() {
+               undef %filtered;
+       }
+}
+
+# ,----
+# | Helper functions
+# `----
+
+sub maybe_add_leading_slash ($;$) {
+       my $str=shift;
+       my $add=shift;
+       $add=1 unless defined $add;
+       return '/' . $str if $add;
+       return $str;
+}
+
+sub istranslatablefile ($) {
+       my $file=shift;
+
+       return 0 unless defined $file;
+       my $type=pagetype($file);
+       return 0 if ! defined $type || $type eq 'po';
+       return 0 if $file =~ /\.pot$/;
+       return 1 if pagespec_match(pagename($file), $config{po_translatable_pages});
+       return;
+}
+
+sub istranslatable ($) {
+       my $page=shift;
+
+       $page=~s#^/##;
+       return 1 if istranslatablefile($pagesources{$page});
+       return;
+}
+
+sub _istranslation ($) {
+       my $page=shift;
+
+       $page='' unless defined $page && length $page;
+       my $hasleadingslash = ($page=~s#^/##);
+       my $file=$pagesources{$page};
+       return 0 unless defined $file
+                        && defined pagetype($file)
+                        && pagetype($file) eq 'po';
+       return 0 if $file =~ /\.pot$/;
+
+       my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
+       return 0 unless defined $masterpage && defined $lang
+                        && length $masterpage && length $lang
+                        && defined $pagesources{$masterpage}
+                        && defined $config{po_slave_languages}{$lang};
+
+       return (maybe_add_leading_slash($masterpage, $hasleadingslash), $lang)
+               if istranslatable($masterpage);
+}
+
+sub istranslation ($) {
+       my $page=shift;
+
+       if (1 < (my ($masterpage, $lang) = _istranslation($page))) {
+               my $hasleadingslash = ($masterpage=~s#^/##);
+               $translations{$masterpage}{$lang}=$page unless exists $translations{$masterpage}{$lang};
+               return (maybe_add_leading_slash($masterpage, $hasleadingslash), $lang);
+       }
+       return "";
+}
+
+sub masterpage ($) {
+       my $page=shift;
+
+       if ( 1 < (my ($masterpage, $lang) = _istranslation($page))) {
+               return $masterpage;
+       }
+       return $page;
+}
+
+sub lang ($) {
+       my $page=shift;
+
+       if (1 < (my ($masterpage, $lang) = _istranslation($page))) {
+               return $lang;
+       }
+       return $config{po_master_language}{code};
+}
+
+sub islanguagecode ($) {
+       my $code=shift;
+
+       return $code =~ /^[a-z]{2}$/;
+}
+
+sub otherlanguage ($$) {
+       my $page=shift;
+       my $code=shift;
+
+       return masterpage($page) if $code eq $config{po_master_language}{code};
+       return masterpage($page) . '.' . $code;
+}
+
+sub otherlanguages ($) {
+       my $page=shift;
+
+       my %ret;
+       return \%ret unless istranslation($page) || istranslatable($page);
+       my $curlang=lang($page);
+       foreach my $lang
+               ($config{po_master_language}{code}, keys %{$config{po_slave_languages}}) {
+               next if $lang eq $curlang;
+               $ret{$lang}=otherlanguage($page, $lang);
+       }
+       return \%ret;
+}
+
+sub potfile ($) {
+       my $masterfile=shift;
+
+       (my $name, my $dir, my $suffix) = fileparse($masterfile, qr/\.[^.]*/);
+       $dir='' if $dir eq './';
+       return File::Spec->catpath('', $dir, $name . ".pot");
+}
+
+sub pofile ($$) {
+       my $masterfile=shift;
+       my $lang=shift;
+
+       (my $name, my $dir, my $suffix) = fileparse($masterfile, qr/\.[^.]*/);
+       $dir='' if $dir eq './';
+       return File::Spec->catpath('', $dir, $name . "." . $lang . ".po");
+}
+
+sub pofiles ($) {
+       my $masterfile=shift;
+
+       return map pofile($masterfile, $_), (keys %{$config{po_slave_languages}});
+}
+
+sub refreshpot ($) {
+       my $masterfile=shift;
+
+       my $potfile=potfile($masterfile);
+       my %options = ("markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0);
+       my $doc=Locale::Po4a::Chooser::new('text',%options);
+       $doc->{TT}{utf_mode} = 1;
+       $doc->{TT}{file_in_charset} = 'utf-8';
+       $doc->{TT}{file_out_charset} = 'utf-8';
+       $doc->read($masterfile);
+       # let's cheat a bit to force porefs option to be passed to
+       # Locale::Po4a::Po; this is undocument use of internal
+       # Locale::Po4a::TransTractor's data, compulsory since this module
+       # prevents us from using the porefs option.
+       $doc->{TT}{po_out}=Locale::Po4a::Po->new({ 'porefs' => 'none' });
+       $doc->{TT}{po_out}->set_charset('utf-8');
+       # do the actual work
+       $doc->parse;
+       IkiWiki::prep_writefile(basename($potfile),dirname($potfile));
+       $doc->writepo($potfile);
+}
+
+sub refreshpofiles ($@) {
+       my $masterfile=shift;
+       my @pofiles=@_;
+
+       my $potfile=potfile($masterfile);
+       if (! -e $potfile) {
+               error("po(refreshpofiles) ".sprintf(gettext("POT file (%s) does not exist"), $potfile));
+       }
+
+       foreach my $pofile (@pofiles) {
+               IkiWiki::prep_writefile(basename($pofile),dirname($pofile));
+
+               if (! -e $pofile) {
+                       # If the po file exists in an underlay, copy it
+                       # from there.
+                       my ($pobase)=$pofile=~/^\Q$config{srcdir}\E\/?(.*)$/;
+                       foreach my $dir (@{$config{underlaydirs}}) {
+                               if (-e "$dir/$pobase") {
+                                       File::Copy::syscopy("$dir/$pobase",$pofile)
+                                               or error("po(refreshpofiles) ".
+                                                        sprintf(gettext("failed to copy underlay PO file to %s"),
+                                                                $pofile));
+                               }
+                       }
+               }
+
+               if (-e $pofile) {
+                       system("msgmerge", "--previous", "-q", "-U", "--backup=none", $pofile, $potfile) == 0
+                               or error("po(refreshpofiles) ".
+                                        sprintf(gettext("failed to update %s"),
+                                                $pofile));
+               }
+               else {
+                       File::Copy::syscopy($potfile,$pofile)
+                               or error("po(refreshpofiles) ".
+                                        sprintf(gettext("failed to copy the POT file to %s"),
+                                                $pofile));
+               }
+       }
+}
+
+sub buildtranslationscache() {
+       # use istranslation's side-effect
+       map istranslation($_), (keys %pagesources);
+}
+
+sub resettranslationscache() {
+       undef %translations;
+}
+
+sub flushmemoizecache() {
+       Memoize::flush_cache("istranslatable");
+       Memoize::flush_cache("_istranslation");
+       Memoize::flush_cache("percenttranslated");
+}
+
+sub urlto_with_orig_beautiful_urlpath($$) {
+       my $to=shift;
+       my $from=shift;
+
+       inject(name => "IkiWiki::beautify_urlpath", call => $origsubs{'beautify_urlpath'});
+       my $res=urlto($to, $from);
+       inject(name => "IkiWiki::beautify_urlpath", call => \&mybeautify_urlpath);
+
+       return $res;
+}
+
+sub percenttranslated ($) {
+       my $page=shift;
+
+       $page=~s/^\///;
+       return gettext("N/A") unless istranslation($page);
+       my $file=srcfile($pagesources{$page});
+       my $masterfile = srcfile($pagesources{masterpage($page)});
+       my %options = (
+               "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
+       );
+       my $doc=Locale::Po4a::Chooser::new('text',%options);
+       $doc->process(
+               'po_in_name'    => [ $file ],
+               'file_in_name'  => [ $masterfile ],
+               'file_in_charset'  => 'utf-8',
+               'file_out_charset' => 'utf-8',
+       ) or error("po(percenttranslated) ".
+                  sprintf(gettext("failed to translate %s"), $page));
+       my ($percent,$hit,$queries) = $doc->stats();
+       $percent =~ s/\.[0-9]+$//;
+       return $percent;
+}
+
+sub languagename ($) {
+       my $code=shift;
+
+       return $config{po_master_language}{name}
+               if $code eq $config{po_master_language}{code};
+       return $config{po_slave_languages}{$code}
+               if defined $config{po_slave_languages}{$code};
+       return;
+}
+
+sub otherlanguagesloop ($) {
+       my $page=shift;
+
+       my @ret;
+       my %otherpages=%{otherlanguages($page)};
+       while (my ($lang, $otherpage) = each %otherpages) {
+               if (istranslation($page) && masterpage($page) eq $otherpage) {
+                       push @ret, {
+                               url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
+                               code => $lang,
+                               language => languagename($lang),
+                               master => 1,
+                       };
+               }
+               elsif (istranslation($otherpage)) {
+                       push @ret, {
+                               url => urlto_with_orig_beautiful_urlpath($otherpage, $page),
+                               code => $lang,
+                               language => languagename($lang),
+                               percent => percenttranslated($otherpage),
+                       }
+               }
+       }
+       return sort {
+               return -1 if $a->{code} eq $config{po_master_language}{code};
+               return 1 if $b->{code} eq $config{po_master_language}{code};
+               return $a->{language} cmp $b->{language};
+       } @ret;
+}
+
+sub homepageurl (;$) {
+       my $page=shift;
+
+       return urlto('', $page);
+}
+
+sub ishomepage ($) {
+       my $page = shift;
+
+       return 1 if $page eq 'index';
+       map { return 1 if $page eq 'index.'.$_ } keys %{$config{po_slave_languages}};
+       return undef;
+}
+
+sub deletetranslations ($) {
+       my $deletedmasterfile=shift;
+
+       my $deletedmasterpage=pagename($deletedmasterfile);
+       my @todelete;
+       map {
+               my $file = newpagefile($deletedmasterpage.'.'.$_, 'po');
+               my $absfile = "$config{srcdir}/$file";
+               if (-e $absfile && ! -l $absfile && ! -d $absfile) {
+                       push @todelete, $file;
+               }
+       } keys %{$config{po_slave_languages}};
+
+       map {
+               if ($config{rcs}) {
+                       IkiWiki::rcs_remove($_);
+               }
+               else {
+                       IkiWiki::prune("$config{srcdir}/$_");
+               }
+       } @todelete;
+
+       if (@todelete) {
+               commit_and_refresh(
+                       gettext("removed obsolete PO files"),
+                       "IkiWiki::Plugin::po::deletetranslations");
+       }
+}
+
+sub commit_and_refresh ($$) {
+       my ($msg, $author) = (shift, shift);
+
+       if ($config{rcs}) {
+               IkiWiki::disable_commit_hook();
+               IkiWiki::rcs_commit_staged($msg, $author, "127.0.0.1");
+               IkiWiki::enable_commit_hook();
+               IkiWiki::rcs_update();
+       }
+       # Reinitialize module's private variables.
+       resetalreadyfiltered();
+       resettranslationscache();
+       flushmemoizecache();
+       # Trigger a wiki refresh.
+       require IkiWiki::Render;
+       # without preliminary saveindex/loadindex, refresh()
+       # complains about a lot of uninitialized variables
+       IkiWiki::saveindex();
+       IkiWiki::loadindex();
+       IkiWiki::refresh();
+       IkiWiki::saveindex();
+}
+
+# on success, returns the filtered content.
+# on error, if $nonfatal, warn and return undef; else, error out.
+sub po_to_markup ($$;$) {
+       my ($page, $content) = (shift, shift);
+       my $nonfatal = shift;
+
+       $content = '' unless defined $content;
+       $content = decode_utf8(encode_utf8($content));
+       # CRLF line terminators make poor Locale::Po4a feel bad
+       $content=~s/\r\n/\n/g;
+
+       # There are incompatibilities between some File::Temp versions
+       # (including 0.18, bundled with Lenny's perl-modules package)
+       # and others (e.g. 0.20, previously present in the archive as
+       # a standalone package): under certain circumstances, some
+       # return a relative filename, whereas others return an absolute one;
+       # we here use this module in a way that is at least compatible
+       # with 0.18 and 0.20. Beware, hit'n'run refactorers!
+       my $infile = new File::Temp(TEMPLATE => "ikiwiki-po-filter-in.XXXXXXXXXX",
+                                   DIR => File::Spec->tmpdir,
+                                   UNLINK => 1)->filename;
+       my $outfile = new File::Temp(TEMPLATE => "ikiwiki-po-filter-out.XXXXXXXXXX",
+                                    DIR => File::Spec->tmpdir,
+                                    UNLINK => 1)->filename;
+
+       my $fail = sub ($) {
+               my $msg = "po(po_to_markup) - $page : " . shift;
+               if ($nonfatal) {
+                       warn $msg;
+                       return undef;
+               }
+               error($msg, sub { unlink $infile, $outfile});
+       };
+
+       writefile(basename($infile), File::Spec->tmpdir, $content)
+               or return $fail->(sprintf(gettext("failed to write %s"), $infile));
+
+       my $masterfile = srcfile($pagesources{masterpage($page)});
+       my %options = (
+               "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
+       );
+       my $doc=Locale::Po4a::Chooser::new('text',%options);
+       $doc->process(
+               'po_in_name'    => [ $infile ],
+               'file_in_name'  => [ $masterfile ],
+               'file_in_charset'  => 'utf-8',
+               'file_out_charset' => 'utf-8',
+       ) or return $fail->(gettext("failed to translate"));
+       $doc->write($outfile)
+               or return $fail->(sprintf(gettext("failed to write %s"), $outfile));
+
+       $content = readfile($outfile)
+               or return $fail->(sprintf(gettext("failed to read %s"), $outfile));
+
+       # Unlinking should happen automatically, thanks to File::Temp,
+       # but it does not work here, probably because of the way writefile()
+       # and Locale::Po4a::write() work.
+       unlink $infile, $outfile;
+
+       return $content;
+}
+
+# returns a SuccessReason or FailReason object
+sub isvalidpo ($) {
+       my $content = shift;
+
+       # NB: we don't use po_to_markup here, since Po4a parser does
+       # not mind invalid PO content
+       $content = '' unless defined $content;
+       $content = decode_utf8(encode_utf8($content));
+
+       # There are incompatibilities between some File::Temp versions
+       # (including 0.18, bundled with Lenny's perl-modules package)
+       # and others (e.g. 0.20, previously present in the archive as
+       # a standalone package): under certain circumstances, some
+       # return a relative filename, whereas others return an absolute one;
+       # we here use this module in a way that is at least compatible
+       # with 0.18 and 0.20. Beware, hit'n'run refactorers!
+       my $infile = new File::Temp(TEMPLATE => "ikiwiki-po-isvalidpo.XXXXXXXXXX",
+                                   DIR => File::Spec->tmpdir,
+                                   UNLINK => 1)->filename;
+
+       my $fail = sub ($) {
+               my $msg = '[po/isvalidpo] ' . shift;
+               unlink $infile;
+               return IkiWiki::FailReason->new("$msg");
+       };
+
+       writefile(basename($infile), File::Spec->tmpdir, $content)
+               or return $fail->(sprintf(gettext("failed to write %s"), $infile));
+
+       my $res = (system("msgfmt", "--check", $infile, "-o", "/dev/null") == 0);
+
+       # Unlinking should happen automatically, thanks to File::Temp,
+       # but it does not work here, probably because of the way writefile()
+       # and Locale::Po4a::write() work.
+       unlink $infile;
+
+       if ($res) {
+           return IkiWiki::SuccessReason->new("valid gettext data");
+       }
+       return IkiWiki::FailReason->new(gettext("invalid gettext data, go back ".
+                                       "to previous page to continue edit"));
+}
+
+# ,----
+# | PageSpecs
+# `----
+
+package IkiWiki::PageSpec;
+
+sub match_istranslation ($;@) {
+       my $page=shift;
+
+       if (IkiWiki::Plugin::po::istranslation($page)) {
+               return IkiWiki::SuccessReason->new("is a translation page");
+       }
+       else {
+               return IkiWiki::FailReason->new("is not a translation page");
+       }
+}
+
+sub match_istranslatable ($;@) {
+       my $page=shift;
+
+       if (IkiWiki::Plugin::po::istranslatable($page)) {
+               return IkiWiki::SuccessReason->new("is set as translatable in po_translatable_pages");
+       }
+       else {
+               return IkiWiki::FailReason->new("is not set as translatable in po_translatable_pages");
+       }
+}
+
+sub match_lang ($$;@) {
+       my $page=shift;
+       my $wanted=shift;
+
+       my $regexp=IkiWiki::glob2re($wanted);
+       my $lang=IkiWiki::Plugin::po::lang($page);
+       if ($lang !~ /^$regexp$/i) {
+               return IkiWiki::FailReason->new("file language is $lang, not $wanted");
+       }
+       else {
+               return IkiWiki::SuccessReason->new("file language is $wanted");
+       }
+}
+
+sub match_currentlang ($$;@) {
+       my $page=shift;
+       shift;
+       my %params=@_;
+
+       return IkiWiki::FailReason->new("no location provided") unless exists $params{location};
+
+       my $currentlang=IkiWiki::Plugin::po::lang($params{location});
+       my $lang=IkiWiki::Plugin::po::lang($page);
+
+       if ($lang eq $currentlang) {
+               return IkiWiki::SuccessReason->new("file language is the same as current one, i.e. $currentlang");
+       }
+       else {
+               return IkiWiki::FailReason->new("file language is $lang, whereas current language is $currentlang");
+       }
+}
+
+1
index 6edf233b4f07e3b7b926a765970bdaed538b75b8..bc1e3501e5e6b7c9c4a0d1568367e5d60bbf61cb 100644 (file)
@@ -3,26 +3,30 @@ package IkiWiki::Plugin::poll;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use Encode;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "poll", call => \&getsetup);
        hook(type => "preprocess", id => "poll", call => \&preprocess);
        hook(type => "sessioncgi", id => "poll", call => \&sessioncgi);
-} # }}}
+}
 
-sub yesno ($) { #{{{
-       my $val=shift;
-       return (defined $val && lc($val) eq "yes");
-} #}}}
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
 my %pagenum;
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=(open => "yes", total => "yes", percent => "yes", @_);
 
-       my $open=yesno($params{open});
-       my $showtotal=yesno($params{total});
-       my $showpercent=yesno($params{percent});
+       my $open=IkiWiki::yesno($params{open});
+       my $showtotal=IkiWiki::yesno($params{total});
+       my $showpercent=IkiWiki::yesno($params{percent});
        $pagenum{$params{page}}++;
 
        my %choices;
@@ -73,9 +77,9 @@ sub preprocess (@) { #{{{
                $ret.="<span>".gettext("Total votes:")." $total</span>\n";
        }
        return "<div class=poll>$ret</div>";
-} # }}}
+}
 
-sub sessioncgi ($$) { #{{{
+sub sessioncgi ($$) {
        my $cgi=shift;
        my $session=shift;
        if (defined $cgi->param('do') && $cgi->param('do') eq "poll") {
@@ -98,7 +102,7 @@ sub sessioncgi ($$) { #{{{
                my $oldchoice=$session->param($choice_param);
                if (defined $oldchoice && $oldchoice eq $choice) {
                        # Same vote; no-op.
-                       IkiWiki::redirect($cgi, "$config{url}/".htmlpage($page));
+                       IkiWiki::redirect($cgi, urlto($page, undef, 1));
                        exit;
                }
 
@@ -145,9 +149,9 @@ sub sessioncgi ($$) { #{{{
                error($@) if $@;
                my $cookie = CGI::Cookie->new(-name=> $session->name, -value=> $session->id);
                print $cgi->redirect(-cookie => $cookie,
-                       -url => "$config{url}/".htmlpage($page));
+                       -url => urlto($page, undef, 1));
                exit;
        }
-} #}}}
+}
 
 1
index 5208a44ec5c9a342ff798a3ec8401f240f8562ba..bc21d71c725f892d3432dfa5ac22feb1241cfd97 100644 (file)
@@ -7,14 +7,23 @@ package IkiWiki::Plugin::polygen;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use File::Find;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "polygen", call => \&getsetup);
        hook(type => "preprocess", id => "polygen", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        my $grammar = ($params{grammar} or 'polygen');
        my $symbol = ($params{symbol} or undef);
@@ -29,7 +38,7 @@ sub preprocess (@) { #{{{
 
        my $grmfile = '/usr/share/polygen/ita/polygen.grm';
        if (! -d '/usr/share/polygen') {
-               return "[[".gettext("polygen not installed")."]]";
+               error gettext("polygen not installed");
        }
        find({wanted => sub {
                        if (substr($File::Find::name, -length($grammar)) eq $grammar) {
@@ -48,13 +57,13 @@ sub preprocess (@) { #{{{
        }
 
        if ($?) {
-               $res="[[".gettext("polygen failed")."]]";
+               error gettext("command failed");
        }
 
        # Strip trailing spaces and newlines so that we flow well with the
        # markdown text
        $res =~ s/\s*$//;
        return $res;
-} # }}}
+}
 
 1
index 9e885741e073bc4ded2e3947366ea6265d8249db..d2e5c23788678efb7819e10c59964bd852663e06 100644 (file)
@@ -3,14 +3,23 @@ package IkiWiki::Plugin::postsparkline;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
        IkiWiki::loadplugin('sparkline');
+       hook(type => "getsetup", id => "postsparkline", call => \&getsetup);
        hook(type => "preprocess", id => "postsparkline", call => \&preprocess);
-} # }}}
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        if (! exists $params{max}) {
@@ -29,31 +38,26 @@ sub preprocess (@) { #{{{
        }
 
        if (! exists $params{formula}) {
-               return "[[postsparkline ".gettext("missing formula")."]]";
+               error gettext("missing formula")
        }
        my $formula=$params{formula};
        $formula=~s/[^a-zA-Z0-9]*//g;
        $formula=IkiWiki::possibly_foolish_untaint($formula);
        if (! length $formula ||
            ! IkiWiki::Plugin::postsparkline::formula->can($formula)) {
-               return "[[postsparkline ".gettext("unknown formula")."]]";
+               error gettext("unknown formula");
        }
 
        add_depends($params{page}, $params{pages});
 
-       my @list;
-       foreach my $page (keys %pagesources) {
-               next if $page eq $params{page};
-               if (pagespec_match($page, $params{pages}, location => $params{page})) {
-                       push @list, $page;
-               }
-       }
-       
-       @list = sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } @list;
+       my @list=sort { $params{timehash}->{$b} <=> $params{timehash}->{$a} } 
+               pagespec_match_list(
+                       [ grep { $_ ne $params{page} } keys %pagesources],
+                       $params{pages}, location => $params{page});
 
        my @data=eval qq{IkiWiki::Plugin::postsparkline::formula::$formula(\\\%params, \@list)};
        if ($@) {
-               return "[[postsparkline error $@]]";
+               error $@;
        }
 
        if (! @data) {
@@ -69,7 +73,7 @@ sub preprocess (@) { #{{{
        delete $params{color};
        return IkiWiki::Plugin::sparkline::preprocess(%params, 
                map { $_.$color => "" } reverse @data);
-} # }}}
+}
 
 sub perfoo ($@) {
        my $sub=shift;
index 745e6a1de436e2db15b97ebe897858f891de2a51..82d8a3df3eeef1c0b4a45c532774637a2a3e5209 100644 (file)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 package IkiWiki::Plugin::prettydate;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use warnings;
 no warnings 'redefine';
 use strict;
@@ -33,17 +33,40 @@ sub default_timetable {
                gettext("%A evening"),                          # 6
                "",                                             # 7
                gettext("late %A evening"),                     # 8
-               "",                     # 9                     # 9
+               "",                                             # 9
                gettext("%A night"),                            # 10
                "",                                             # 11
        ];
 }
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "prettydate", call => \&getsetup);
        hook(type => "checkconfig", id => "prettydate", call => \&checkconfig);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               prettydateformat => {
+                       type => "string",
+                       example => '%X, %B %o, %Y',
+                       description => "format to use to display date",
+                       advanced => 1,
+                       safe => 1,
+                       rebuild => 1,
+               },
+               timetable => {
+                       type => "internal",
+                       description => "array of time descriptions",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
 
-sub checkconfig () { #{{{
+sub checkconfig () {
        if (! defined $config{prettydateformat} ||
            $config{prettydateformat} eq '%c') {
                $config{prettydateformat}='%X, %B %o, %Y';
@@ -59,9 +82,9 @@ sub checkconfig () { #{{{
                        $config{timetable}[$h] = $config{timetable}[$h - 1];
                }
        }
-} #}}}
+}
 
-sub IkiWiki::displaytime ($;$) { #{{{
+sub IkiWiki::formattime ($;$) {
        my $time=shift;
        my $format=shift;
        if (! defined $format) {
@@ -99,6 +122,6 @@ sub IkiWiki::displaytime ($;$) { #{{{
 
        $format=~s/\%X/$t/g;
        return strftime($format, \@t);
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/progress.pm b/IkiWiki/Plugin/progress.pm
new file mode 100644 (file)
index 0000000..76d994a
--- /dev/null
@@ -0,0 +1,79 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::progress;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+my $percentage_pattern = qr/[0-9]+\%?/; # pattern to validate percentages
+
+sub import {
+       hook(type => "getsetup", id => "progress", call => \&getsetup);
+       hook(type => "preprocess", id => "progress", call => \&preprocess);
+       hook(type => "format",     id => "progress", call => \&format);
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
+       my %params=@_;
+       
+       my $fill;
+       
+       if (defined $params{percent}) {
+               $fill = $params{percent};
+               ($fill) = $fill =~ m/($percentage_pattern)/; # fill is untainted now
+               $fill=~s/%$//;
+               if (! defined $fill || ! length $fill || $fill > 100 || $fill < 0) {
+                       error(sprintf(gettext("illegal percent value %s"), $params{percent}));
+               }
+               $fill.="%";
+       }
+       elsif (defined $params{totalpages} and defined $params{donepages}) {
+               add_depends($params{page}, $params{totalpages});
+               add_depends($params{page}, $params{donepages});
+
+               my @pages=keys %pagesources;
+               my $totalcount=0;
+               my $donecount=0;
+               foreach my $page (@pages) {
+                       $totalcount++ if pagespec_match($page, $params{totalpages}, location => $params{page});
+                       $donecount++ if pagespec_match($page, $params{donepages}, location => $params{page});
+               }
+               
+               if ($totalcount == 0) {
+                       $fill = "100%";
+               }
+               else {
+                       my $number = $donecount/$totalcount*100;
+                       $fill = sprintf("%u%%", $number);
+               }
+       }
+       else {
+               error(gettext("need either `percent` or `totalpages` and `donepages` parameters"));
+       }
+
+       return <<EODIV
+<div class="progress">
+  <div class="progress-done" style="width: $fill">$fill</div>
+</div>
+EODIV
+}
+
+sub format(@) {
+       my %params = @_;
+
+       # If HTMLScrubber has removed the style attribute, then bring it back
+
+       $params{content} =~ s!<div class="progress-done">($percentage_pattern)</div>!<div class="progress-done" style="width: $1">$1</div>!g;
+
+       return $params{content};    
+}
+
+1
index 011c3a862c678d0cae73a3df3f669dec6b8d1917..ad8a610c1420f73a3ce0eabf30f9300afcdff5a4 100644 (file)
@@ -4,10 +4,19 @@ package IkiWiki::Plugin::rawhtml;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "rawhtml", call => \&getsetup);
        $config{wiki_file_prune_regexps} = [ grep { !m/\\\.x\?html\?\$/ } @{$config{wiki_file_prune_regexps}} ];
-} # }}}
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # changes file types
+               },
+}
 
 1
index f4f9ca348d84a569e866a3cfd33837a24d664a0c..fa851e46678f208efa04def72e988366df6ea87d 100644 (file)
@@ -3,22 +3,48 @@ package IkiWiki::Plugin::recentchanges;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
+use Encode;
+use HTML::Entities;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "recentchanges", call => \&getsetup);
        hook(type => "checkconfig", id => "recentchanges", call => \&checkconfig);
        hook(type => "refresh", id => "recentchanges", call => \&refresh);
        hook(type => "pagetemplate", id => "recentchanges", call => \&pagetemplate);
        hook(type => "htmlize", id => "_change", call => \&htmlize);
-       hook(type => "cgi", id => "recentchanges", call => \&cgi);
-} #}}}
+       # Load goto to fix up links from recentchanges
+       IkiWiki::loadplugin("goto");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               recentchangespage => {
+                       type => "string",
+                       example => "recentchanges",
+                       description => "name of the recentchanges page",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               recentchangesnum => {
+                       type => "integer",
+                       example => 100,
+                       description => "number of changes to track",
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
 
-sub checkconfig () { #{{{
+sub checkconfig () {
        $config{recentchangespage}='recentchanges' unless defined $config{recentchangespage};
        $config{recentchangesnum}=100 unless defined $config{recentchangesnum};
-} #}}}
+}
 
-sub refresh ($) { #{{{
+sub refresh ($) {
        my %seen;
 
        # add new changes
@@ -32,10 +58,10 @@ sub refresh ($) { #{{{
                        unlink($config{srcdir}.'/'.$pagesources{$page});
                }
        }
-} #}}}
+}
 
 # Enable the recentchanges link on wiki pages.
-sub pagetemplate (@) { #{{{
+sub pagetemplate (@) {
        my %params=@_;
        my $template=$params{template};
        my $page=$params{page};
@@ -46,51 +72,18 @@ sub pagetemplate (@) { #{{{
                $template->param(recentchangesurl => urlto($config{recentchangespage}, $page));
                $template->param(have_actions => 1);
        }
-} #}}}
+}
 
 # Pages with extension _change have plain html markup, pass through.
-sub htmlize (@) { #{{{
+sub htmlize (@) {
        my %params=@_;
        return $params{content};
-} #}}}
-
-sub cgi ($) { #{{{
-       my $cgi=shift;
-       if (defined $cgi->param('do') && $cgi->param('do') eq "recentchanges_link") {
-               # This is a link from a change page to some
-               # other page. Since the change pages are only generated
-               # once, statically, links on them won't be updated if the
-               # page they link to is deleted, or newly created, or
-               # changes for whatever reason. So this CGI handles that
-               # dynamic linking stuff.
-               my $page=$cgi->param("page");
-               if (!defined $page) {
-                       error("missing page parameter");
-               }
-
-               IkiWiki::loadindex();
-
-               my $link=bestlink("", $page);
-               if (! length $link) {
-                       print "Content-type: text/html\n\n";
-                       print IkiWiki::misctemplate(gettext(gettext("missing page")),
-                               "<p>".
-                               sprintf(gettext("The page %s does not exist."),
-                                       htmllink("", "", $page)).
-                               "</p>");
-               }
-               else {
-                       IkiWiki::redirect($cgi, $config{url}."/".htmlpage($link));
-               }
-
-               exit;
-       }
 }
 
-sub store ($$$) { #{{{
+sub store ($$$) {
        my $change=shift;
 
-       my $page="$config{recentchangespage}/change_".IkiWiki::titlepage($change->{rev});
+       my $page="$config{recentchangespage}/change_".titlepage($change->{rev});
 
        # Optimisation to avoid re-writing pages. Assumes commits never
        # change (or that any changes are not important).
@@ -104,15 +97,15 @@ sub store ($$$) { #{{{
                        if (length $config{cgiurl}) {
                                $_->{link} = "<a href=\"".
                                        IkiWiki::cgiurl(
-                                               do => "recentchanges_link",
+                                               do => "goto",
                                                page => $_->{page}
                                        ).
-                                       "\">".
-                                       IkiWiki::pagetitle($_->{page}).
+                                       "\" rel=\"nofollow\">".
+                                       pagetitle($_->{page}).
                                        "</a>"
                        }
                        else {
-                               $_->{link} = IkiWiki::pagetitle($_->{page});
+                               $_->{link} = pagetitle($_->{page});
                        }
                        $_->{baseurl}="$config{url}/" if length $config{url};
 
@@ -130,16 +123,18 @@ sub store ($$$) { #{{{
        }
        elsif (length $config{cgiurl}) {
                $change->{authorurl} = IkiWiki::cgiurl(
-                       do => "recentchanges_link",
+                       do => "goto",
                        page => (length $config{userdir} ? "$config{userdir}/" : "").$change->{author},
                );
        }
 
-       # escape wikilinks and preprocessor stuff in commit messages
        if (ref $change->{message}) {
                foreach my $field (@{$change->{message}}) {
                        if (exists $field->{line}) {
-                               $field->{line} =~ s/(?<!\\)\[\[/\\\[\[/g;
+                               # escape html
+                               $field->{line} = encode_entities($field->{line});
+                               # escape links and preprocessor stuff
+                               $field->{line} = encode_entities($field->{line}, '\[\]');
                        }
                }
        }
@@ -151,6 +146,10 @@ sub store ($$$) { #{{{
                commitdate => displaytime($change->{when}, "%X %x"),
                wikiname => $config{wikiname},
        );
+       
+       $template->param(permalink => "$config{url}/$config{recentchangespage}/#change-".titlepage($change->{rev}))
+               if exists $config{url};
+       
        IkiWiki::run_hooks(pagetemplate => sub {
                shift->(page => $page, destpage => $page,
                        template => $template, rev => $change->{rev});
@@ -161,6 +160,6 @@ sub store ($$$) { #{{{
        utime $change->{when}, $change->{when}, "$config{srcdir}/$file";
 
        return $page;
-} #}}}
+}
 
 1
index 3942f308b05a86b5d4e7f0524fd756534a492391..e3ba9b8d8248858689619fee48a963912c593648 100644 (file)
@@ -3,16 +3,27 @@ package IkiWiki::Plugin::recentchangesdiff;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
+use HTML::Entities;
 
 my $maxlines=200;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "recentchangesdiff",
+               call => \&getsetup);
        hook(type => "pagetemplate", id => "recentchangesdiff",
                call => \&pagetemplate);
-} #}}}
+}
 
-sub pagetemplate (@) { #{{{
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub pagetemplate (@) {
        my %params=@_;
        my $template=$params{template};
        if ($config{rcs} && exists $params{rev} && length $params{rev} &&
@@ -28,11 +39,13 @@ sub pagetemplate (@) { #{{{
                        else {
                                $diff=join("", @lines);
                        }
+                       # escape html
+                       $diff = encode_entities($diff);
                        # escape links and preprocessor stuff
-                       $diff =~ s/(?<!\\)\[\[/\\\[\[/g;
+                       $diff = encode_entities($diff, '\[\]');
                        $template->param(diff => $diff);
                }
        }
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/relativedate.pm b/IkiWiki/Plugin/relativedate.pm
new file mode 100644 (file)
index 0000000..3e33cd5
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::relativedate;
+
+use warnings;
+no warnings 'redefine';
+use strict;
+use IkiWiki 3.00;
+use POSIX;
+use Encode;
+
+sub import {
+       add_underlay("javascript");
+       hook(type => "getsetup", id => "relativedate", call => \&getsetup);
+       hook(type => "format", id => "relativedate", call => \&format);
+       inject(name => "IkiWiki::displaytime", call => \&mydisplaytime);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub format (@) {
+        my %params=@_;
+
+       if (! ($params{content}=~s!^(<body>)!$1.include_javascript($params{page})!em)) {
+               # no </body> tag, probably in preview mode
+               $params{content}=include_javascript($params{page}, 1).$params{content};
+       }
+       return $params{content};
+}
+
+sub include_javascript ($;$) {
+       my $page=shift;
+       my $absolute=shift;
+       
+       return '<script src="'.urlto("ikiwiki.js", $page, $absolute).
+               '" type="text/javascript" charset="utf-8"></script>'."\n".
+               '<script src="'.urlto("relativedate.js", $page, $absolute).
+               '" type="text/javascript" charset="utf-8"></script>';
+}
+
+sub mydisplaytime ($;$) {
+       my $time=shift;
+       my $format=shift;
+
+       # This needs to be in a form that can be parsed by javascript.
+       # Being fairly human readable is also nice, as it will be exposed
+       # as the title if javascript is not available.
+       my $gmtime=decode_utf8(POSIX::strftime("%a, %d %b %Y %H:%M:%S %z",
+                       localtime($time)));
+
+       return '<span class="relativedate" title="'.$gmtime.'">'.
+               IkiWiki::formattime($time, $format).'</span>';
+}
+
+1
diff --git a/IkiWiki/Plugin/remove.pm b/IkiWiki/Plugin/remove.pm
new file mode 100644 (file)
index 0000000..cbc8a0f
--- /dev/null
@@ -0,0 +1,247 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::remove;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getsetup", id => "remove", call => \&getsetup);
+       hook(type => "formbuilder_setup", id => "remove", call => \&formbuilder_setup);
+       hook(type => "formbuilder", id => "remove", call => \&formbuilder);
+       hook(type => "sessioncgi", id => "remove", call => \&sessioncgi);
+
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub check_canremove ($$$) {
+       my $page=shift;
+       my $q=shift;
+       my $session=shift;
+
+       # Must be a known source file.
+       if (! exists $pagesources{$page}) {
+               error(sprintf(gettext("%s does not exist"),
+                       htmllink("", "", $page, noimageinline => 1)));
+       }
+
+       # Must exist on disk, and be a regular file.
+       my $file=$pagesources{$page};
+       if (! -e "$config{srcdir}/$file") {
+               error(sprintf(gettext("%s is not in the srcdir, so it cannot be deleted"), $file));
+       }
+       elsif (-l "$config{srcdir}/$file" && ! -f _) {
+               error(sprintf(gettext("%s is not a file"), $file));
+       }
+       
+       # Must be editable.
+       IkiWiki::check_canedit($page, $q, $session);
+
+       # If a user can't upload an attachment, don't let them delete it.
+       # This is sorta overkill, but better safe than sorry.
+       if (! defined pagetype($pagesources{$page})) {
+               if (IkiWiki::Plugin::attachment->can("check_canattach")) {
+                       IkiWiki::Plugin::attachment::check_canattach($session, $page, $file);
+               }
+               else {
+                       error("renaming of attachments is not allowed");
+               }
+       }
+
+       my $canremove;
+       IkiWiki::run_hooks(canremove => sub {
+               return if defined $canremove;
+               my $ret=shift->(page => $page, cgi => $q, session => $session);
+               if (defined $ret) {
+                       if ($ret eq "") {
+                               $canremove=1;
+                       }
+                       elsif (ref $ret eq 'CODE') {
+                               $ret->();
+                               $canremove=0;
+                       }
+                       elsif (defined $ret) {
+                               error($ret);
+                               $canremove=0;
+                       }
+               }
+       });
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+       my $form=$params{form};
+       my $q=$params{cgi};
+
+       if (defined $form->field("do") && ($form->field("do") eq "edit" ||
+           $form->field("do") eq "create")) {
+               # Removal button for the page, and also for attachments.
+               push @{$params{buttons}}, "Remove" if $form->field("do") eq "edit";
+               $form->tmpl_param("field-remove" => '<input name="_submit" type="submit" value="Remove Attachments" />');
+       }
+}
+
+sub confirmation_form ($$) {
+       my $q=shift;
+       my $session=shift;
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       my $f = CGI::FormBuilder->new(
+               name => "remove",
+               header => 0,
+               charset => "utf-8",
+               method => 'POST',
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               stylesheet => IkiWiki::baseurl()."style.css",
+               fields => [qw{do page}],
+       );
+       
+       $f->field(name => "do", type => "hidden", value => "remove", force => 1);
+
+       return $f, ["Remove", "Cancel"];
+}
+
+sub removal_confirm ($$@) {
+       my $q=shift;
+       my $session=shift;
+       my $attachment=shift;
+       my @pages=@_;
+
+       foreach my $page (@pages) {
+               check_canremove($page, $q, $session);
+       }
+
+       # Save current form state to allow returning to it later
+       # without losing any edits.
+       # (But don't save what button was submitted, to avoid
+       # looping back to here.)
+       # Note: "_submit" is CGI::FormBuilder internals.
+       $q->param(-name => "_submit", -value => "");
+       $session->param(postremove => scalar $q->Vars);
+       IkiWiki::cgi_savesession($session);
+       
+       my ($f, $buttons)=confirmation_form($q, $session);
+       $f->title(sprintf(gettext("confirm removal of %s"),
+               join(", ", map { pagetitle($_) } @pages)));
+       $f->field(name => "page", type => "hidden", value => \@pages, force => 1);
+       if (defined $attachment) {
+               $f->field(name => "attachment", type => "hidden",
+                       value => $attachment, force => 1);
+       }
+
+       IkiWiki::showform($f, $buttons, $session, $q);
+       exit 0;
+}
+
+sub postremove ($) {
+       my $session=shift;
+
+       # Load saved form state and return to edit form.
+       my $postremove=CGI->new($session->param("postremove"));
+       $session->clear("postremove");
+       IkiWiki::cgi_savesession($session);
+       IkiWiki::cgi($postremove, $session);
+}
+
+sub formbuilder (@) {
+       my %params=@_;
+       my $form=$params{form};
+
+       if (defined $form->field("do") && ($form->field("do") eq "edit" ||
+           $form->field("do") eq "create")) {
+               my $q=$params{cgi};
+               my $session=$params{session};
+
+               if ($form->submitted eq "Remove" && $form->field("do") eq "edit") {
+                       removal_confirm($q, $session, 0, $form->field("page"));
+               }
+               elsif ($form->submitted eq "Remove Attachments") {
+                       my @selected=$q->param("attachment_select");
+                       if (! @selected) {
+                               error(gettext("Please select the attachments to remove."));
+                       }
+                       removal_confirm($q, $session, 1, @selected);
+               }
+       }
+}
+
+sub sessioncgi ($$) {
+        my $q=shift;
+
+       if ($q->param("do") eq 'remove') {
+               my $session=shift;
+               my ($form, $buttons)=confirmation_form($q, $session);
+               IkiWiki::decode_form_utf8($form);
+
+               if ($form->submitted eq 'Cancel') {
+                       postremove($session);
+               }
+               elsif ($form->submitted eq 'Remove' && $form->validate) {
+                       my @pages=$q->param("page");
+       
+                       # Validate removal by checking that the page exists,
+                       # and that the user is allowed to edit(/remove) it.
+                       my @files;
+                       foreach my $page (@pages) {
+                               check_canremove($page, $q, $session);
+                               
+                               # This untaint is safe because of the
+                               # checks performed above, which verify the
+                               # page is a normal file, etc.
+                               push @files, IkiWiki::possibly_foolish_untaint($pagesources{$page});
+                       }
+
+                       # Do removal, and update the wiki.
+                       require IkiWiki::Render;
+                       if ($config{rcs}) {
+                               IkiWiki::disable_commit_hook();
+                               foreach my $file (@files) {
+                                       IkiWiki::rcs_remove($file);
+                               }
+                               IkiWiki::rcs_commit_staged(gettext("removed"),
+                                       $session->param("name"), $ENV{REMOTE_ADDR});
+                               IkiWiki::enable_commit_hook();
+                               IkiWiki::rcs_update();
+                       }
+                       else {
+                               foreach my $file (@files) {
+                                       IkiWiki::prune("$config{srcdir}/$file");
+                               }
+                       }
+                       IkiWiki::refresh();
+                       IkiWiki::saveindex();
+
+                       if ($q->param("attachment")) {
+                               # Attachments were deleted, so redirect
+                               # back to the edit form.
+                               postremove($session);
+                       }
+                       else {
+                               # The page is gone, so redirect to parent
+                               # of the page.
+                               my $parent=IkiWiki::dirname($pages[0]);
+                               if (! exists $pagesources{$parent}) {
+                                       $parent="index";
+                               }
+                               IkiWiki::redirect($q, urlto($parent, '/', 1));
+                       }
+               }
+               else {
+                       removal_confirm($q, $session, 0, $q->param("page"));
+               }
+
+               exit 0;
+       }
+}
+
+1
diff --git a/IkiWiki/Plugin/rename.pm b/IkiWiki/Plugin/rename.pm
new file mode 100644 (file)
index 0000000..c3e0349
--- /dev/null
@@ -0,0 +1,584 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::rename;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getsetup", id => "rename", call => \&getsetup);
+       hook(type => "formbuilder_setup", id => "rename", call => \&formbuilder_setup);
+       hook(type => "formbuilder", id => "rename", call => \&formbuilder);
+       hook(type => "sessioncgi", id => "rename", call => \&sessioncgi);
+       hook(type => "rename", id => "rename", call => \&rename_subpages);
+}
+
+sub getsetup () {
+       return 
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub check_canrename ($$$$$$) {
+       my $src=shift;
+       my $srcfile=shift;
+       my $dest=shift;
+       my $destfile=shift;
+       my $q=shift;
+       my $session=shift;
+
+       my $attachment=! defined pagetype($pagesources{$src});
+
+       # Must be a known source file.
+       if (! exists $pagesources{$src}) {
+               error(sprintf(gettext("%s does not exist"),
+                       htmllink("", "", $src, noimageinline => 1)));
+       }
+       
+       # Must exist on disk, and be a regular file.
+       if (! -e "$config{srcdir}/$srcfile") {
+               error(sprintf(gettext("%s is not in the srcdir, so it cannot be renamed"), $srcfile));
+       }
+       elsif (-l "$config{srcdir}/$srcfile" && ! -f _) {
+               error(sprintf(gettext("%s is not a file"), $srcfile));
+       }
+
+       # Must be editable.
+       IkiWiki::check_canedit($src, $q, $session);
+       if ($attachment) {
+               if (IkiWiki::Plugin::attachment->can("check_canattach")) {
+                       IkiWiki::Plugin::attachment::check_canattach($session, $src, $srcfile);
+               }
+               else {
+                       error("renaming of attachments is not allowed");
+               }
+       }
+       
+       # Dest checks can be omitted by passing undef.
+       if (defined $dest) {
+               if ($srcfile eq $destfile) {
+                       error(gettext("no change to the file name was specified"));
+               }
+
+               # Must be a legal filename, and not absolute.
+               if (IkiWiki::file_pruned($destfile, $config{srcdir}) || 
+                   $destfile=~/^\//) {
+                       error(sprintf(gettext("illegal name")));
+               }
+
+               # Must not be a known source file.
+               if ($src ne $dest && exists $pagesources{$dest}) {
+                       error(sprintf(gettext("%s already exists"),
+                               htmllink("", "", $dest, noimageinline => 1)));
+               }
+       
+               # Must not exist on disk already.
+               if (-l "$config{srcdir}/$destfile" || -e _) {
+                       error(sprintf(gettext("%s already exists on disk"), $destfile));
+               }
+       
+               # Must be editable.
+               IkiWiki::check_canedit($dest, $q, $session);
+               if ($attachment) {
+                       # Note that $srcfile is used here, not $destfile,
+                       # because it wants the current file, to check it.
+                       IkiWiki::Plugin::attachment::check_canattach($session, $dest, $srcfile);
+               }
+       }
+
+       my $canrename;
+       IkiWiki::run_hooks(canrename => sub {
+               return if defined $canrename;
+               my $ret=shift->(cgi => $q, session => $session,
+                       src => $src, srcfile => $srcfile,
+                       dest => $dest, destfile => $destfile);
+               if (defined $ret) {
+                       if ($ret eq "") {
+                               $canrename=1;
+                       }
+                       elsif (ref $ret eq 'CODE') {
+                               $ret->();
+                               $canrename=0;
+                       }
+                       elsif (defined $ret) {
+                               error($ret);
+                               $canrename=0;
+                       }
+               }
+       });
+}
+
+sub rename_form ($$$) {
+       my $q=shift;
+       my $session=shift;
+       my $page=shift;
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       my $f = CGI::FormBuilder->new(
+               name => "rename",
+               title => sprintf(gettext("rename %s"), pagetitle($page)),
+               header => 0,
+               charset => "utf-8",
+               method => 'POST',
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               stylesheet => IkiWiki::baseurl()."style.css",
+               fields => [qw{do page new_name attachment}],
+       );
+       
+       $f->field(name => "do", type => "hidden", value => "rename", force => 1);
+       $f->field(name => "page", type => "hidden", value => $page, force => 1);
+       $f->field(name => "new_name", value => pagetitle($page, 1), size => 60);
+       if (!$q->param("attachment")) {
+               # insert the standard extensions
+               my @page_types;
+               if (exists $IkiWiki::hooks{htmlize}) {
+                       foreach my $key (grep { !/^_/ } keys %{$IkiWiki::hooks{htmlize}}) {
+                               push @page_types, [$key, $IkiWiki::hooks{htmlize}{$key}{longname} || $key];
+                       }
+               }
+               @page_types=sort @page_types;
+       
+               # make sure the current extension is in the list
+               my ($ext) = $pagesources{$page}=~/\.([^.]+)$/;
+               if (! $IkiWiki::hooks{htmlize}{$ext}) {
+                       unshift(@page_types, [$ext, $ext]);
+               }
+       
+               $f->field(name => "type", type => 'select',
+                       options => \@page_types,
+                       value => $ext, force => 1);
+               
+               foreach my $p (keys %pagesources) {
+                       if ($pagesources{$p}=~m/^\Q$page\E\//) {
+                               $f->field(name => "subpages",
+                                       label => "",
+                                       type => "checkbox",
+                                       options => [ [ 1 => gettext("Also rename SubPages and attachments") ] ],
+                                       value => 1,
+                                       force => 1);
+                               last;
+                       }
+               }
+       }
+       $f->field(name => "attachment", type => "hidden");
+
+       return $f, ["Rename", "Cancel"];
+}
+
+sub rename_start ($$$$) {
+       my $q=shift;
+       my $session=shift;
+       my $attachment=shift;
+       my $page=shift;
+
+       check_canrename($page, $pagesources{$page}, undef, undef,
+               $q, $session);
+
+       # Save current form state to allow returning to it later
+       # without losing any edits.
+       # (But don't save what button was submitted, to avoid
+       # looping back to here.)
+       # Note: "_submit" is CGI::FormBuilder internals.
+       $q->param(-name => "_submit", -value => "");
+       $session->param(postrename => scalar $q->Vars);
+       IkiWiki::cgi_savesession($session);
+       
+       if (defined $attachment) {
+               $q->param(-name => "attachment", -value => $attachment);
+       }
+       my ($f, $buttons)=rename_form($q, $session, $page);
+       IkiWiki::showform($f, $buttons, $session, $q);
+       exit 0;
+}
+
+sub postrename ($;$$$) {
+       my $session=shift;
+       my $src=shift;
+       my $dest=shift;
+       my $attachment=shift;
+
+       # Load saved form state and return to edit page.
+       my $postrename=CGI->new($session->param("postrename"));
+       $session->clear("postrename");
+       IkiWiki::cgi_savesession($session);
+
+       if (defined $dest) {
+               if (! $attachment) {
+                       # They renamed the page they were editing. This requires
+                       # fixups to the edit form state.
+                       # Tweak the edit form to be editing the new page.
+                       $postrename->param("page", $dest);
+               }
+
+               # Update edit form content to fix any links present
+               # on it.
+               $postrename->param("editcontent",
+                       renamepage_hook($dest, $src, $dest,
+                                $postrename->param("editcontent")));
+
+               # Get a new edit token; old was likely invalidated.
+               $postrename->param("rcsinfo",
+                       IkiWiki::rcs_prepedit($pagesources{$dest}));
+       }
+
+       IkiWiki::cgi_editpage($postrename, $session);
+}
+
+sub formbuilder (@) {
+       my %params=@_;
+       my $form=$params{form};
+
+       if (defined $form->field("do") && ($form->field("do") eq "edit" ||
+           $form->field("do") eq "create")) {
+               my $q=$params{cgi};
+               my $session=$params{session};
+
+               if ($form->submitted eq "Rename" && $form->field("do") eq "edit") {
+                       rename_start($q, $session, 0, $form->field("page"));
+               }
+               elsif ($form->submitted eq "Rename Attachment") {
+                       my @selected=$q->param("attachment_select");
+                       if (@selected > 1) {
+                               error(gettext("Only one attachment can be renamed at a time."));
+                       }
+                       elsif (! @selected) {
+                               error(gettext("Please select the attachment to rename."))
+                       }
+                       rename_start($q, $session, 1, $selected[0]);
+               }
+       }
+}
+
+my $renamesummary;
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+       my $form=$params{form};
+       my $q=$params{cgi};
+
+       if (defined $form->field("do") && ($form->field("do") eq "edit" ||
+           $form->field("do") eq "create")) {
+               # Rename button for the page, and also for attachments.
+               push @{$params{buttons}}, "Rename" if $form->field("do") eq "edit";
+               $form->tmpl_param("field-rename" => '<input name="_submit" type="submit" value="Rename Attachment" />');
+
+               if (defined $renamesummary) {
+                       $form->tmpl_param(message => $renamesummary);
+               }
+       }
+}
+
+sub sessioncgi ($$) {
+        my $q=shift;
+
+       if ($q->param("do") eq 'rename') {
+               my $session=shift;
+               my ($form, $buttons)=rename_form($q, $session, $q->param("page"));
+               IkiWiki::decode_form_utf8($form);
+
+               if ($form->submitted eq 'Cancel') {
+                       postrename($session);
+               }
+               elsif ($form->submitted eq 'Rename' && $form->validate) {
+                       # Queue of rename actions to perfom.
+                       my @torename;
+
+                       # These untaints are safe because of the checks
+                       # performed in check_canrename later.
+                       my $src=$q->param("page");
+                       my $srcfile=IkiWiki::possibly_foolish_untaint($pagesources{$src});
+                       my $dest=IkiWiki::possibly_foolish_untaint(titlepage($q->param("new_name")));
+                       my $destfile=$dest;
+                       if (! $q->param("attachment")) {
+                               my $type=$q->param('type');
+                               if (defined $type && length $type && $IkiWiki::hooks{htmlize}{$type}) {
+                                       $type=IkiWiki::possibly_foolish_untaint($type);
+                               }
+                               else {
+                                       my ($ext)=$srcfile=~/\.([^.]+)$/;
+                                       $type=$ext;
+                               }
+                               
+                               $destfile=newpagefile($dest, $type);
+                       }
+                       push @torename, {
+                               src => $src,
+                               srcfile => $srcfile,
+                               dest => $dest,
+                               destfile => $destfile,
+                               required => 1,
+                       };
+
+                       @torename=rename_hook(
+                               torename => \@torename,
+                               done => {},
+                               cgi => $q,
+                               session => $session,
+                       );
+
+                       require IkiWiki::Render;
+                       IkiWiki::disable_commit_hook() if $config{rcs};
+                       my %origpagesources=%pagesources;
+
+                       # First file renaming.
+                       foreach my $rename (@torename) {
+                               if ($rename->{required}) {
+                                       do_rename($rename, $q, $session);
+                               }
+                               else {
+                                       eval {do_rename($rename, $q, $session)};
+                                       if ($@) {
+                                               $rename->{error}=$@;
+                                               next;
+                                       }
+                               }
+
+                               # Temporarily tweak pagesources to point to
+                               # the renamed file, in case fixlinks needs
+                               # to edit it.
+                               $pagesources{$rename->{src}}=$rename->{destfile};
+                       }
+                       IkiWiki::rcs_commit_staged(
+                               sprintf(gettext("rename %s to %s"), $srcfile, $destfile),
+                               $session->param("name"), $ENV{REMOTE_ADDR}) if $config{rcs};
+
+                       # Then link fixups.
+                       foreach my $rename (@torename) {
+                               next if $rename->{src} eq $rename->{dest};
+                               next if $rename->{error};
+                               foreach my $p (fixlinks($rename, $session)) {
+                                       # map old page names to new
+                                       foreach my $r (@torename) {
+                                               next if $rename->{error};
+                                               if ($r->{src} eq $p) {
+                                                       $p=$r->{dest};
+                                                       last;
+                                               }
+                                       }
+                                       push @{$rename->{fixedlinks}}, $p;
+                               }
+                       }
+
+                       # Then refresh.
+                       %pagesources=%origpagesources;
+                       if ($config{rcs}) {
+                               IkiWiki::enable_commit_hook();
+                               IkiWiki::rcs_update();
+                       }
+                       IkiWiki::refresh();
+                       IkiWiki::saveindex();
+
+                       # Find pages with remaining, broken links.
+                       foreach my $rename (@torename) {
+                               next if $rename->{src} eq $rename->{dest};
+                               
+                               foreach my $page (keys %links) {
+                                       my $broken=0;
+                                       foreach my $link (@{$links{$page}}) {
+                                               my $bestlink=bestlink($page, $link);
+                                               if ($bestlink eq $rename->{src}) {
+                                                       push @{$rename->{brokenlinks}}, $page;
+                                                       last;
+                                               }
+                                       }
+                               }
+                       }
+
+                       # Generate a summary, that will be shown at the top
+                       # of the edit template.
+                       $renamesummary="";
+                       foreach my $rename (@torename) {
+                               my $template=template("renamesummary.tmpl");
+                               $template->param(src => $rename->{srcfile});
+                               $template->param(dest => $rename->{destfile});
+                               $template->param(error => $rename->{error});
+                               if ($rename->{src} ne $rename->{dest}) {
+                                       $template->param(brokenlinks_checked => 1);
+                                       $template->param(brokenlinks => linklist($rename->{dest}, $rename->{brokenlinks}));
+                                       $template->param(fixedlinks => linklist($rename->{dest}, $rename->{fixedlinks}));
+                               }
+                               $renamesummary.=$template->output;
+                       }
+
+                       postrename($session, $src, $dest, $q->param("attachment"));
+               }
+               else {
+                       IkiWiki::showform($form, $buttons, $session, $q);
+               }
+
+               exit 0;
+       }
+}
+
+# Add subpages to the list of pages to be renamed, if needed.
+sub rename_subpages (@) {
+       my %params = @_;
+
+       my %torename = %{$params{torename}};
+       my $q = $params{cgi};
+       my $src = $torename{src};
+       my $srcfile = $torename{src};
+       my $dest = $torename{dest};
+       my $destfile = $torename{dest};
+
+       return () unless ($q->param("subpages") && $src ne $dest);
+
+       my @ret;
+       foreach my $p (keys %pagesources) {
+               next unless $pagesources{$p}=~m/^\Q$src\E\//;
+               # If indexpages is enabled, the srcfile should not be confused
+               # with a subpage.
+               next if $pagesources{$p} eq $srcfile;
+
+               my $d=$pagesources{$p};
+               $d=~s/^\Q$src\E\//$dest\//;
+               push @ret, {
+                       src => $p,
+                       srcfile => $pagesources{$p},
+                       dest => pagename($d),
+                       destfile => $d,
+                       required => 0,
+               };
+       }
+       return @ret;
+}
+
+sub linklist {
+       # generates a list of links in a form suitable for FormBuilder
+       my $dest=shift;
+       my $list=shift;
+       # converts a list of pages into a list of links
+       # in a form suitable for FormBuilder.
+
+       [map {
+               {
+                       page => htmllink($dest, $dest, $_,
+                                       noimageinline => 1,
+                                       linktext => pagetitle($_),
+                               )
+               }
+       } @{$list}]
+}
+
+sub renamepage_hook ($$$$) {
+       my ($page, $src, $dest, $content)=@_;
+
+       IkiWiki::run_hooks(renamepage => sub {
+               $content=shift->(
+                       page => $page,
+                       oldpage => $src,
+                       newpage => $dest,
+                       content => $content,
+               );
+       });
+
+       return $content;
+}
+
+sub rename_hook {
+       my %params = @_;
+
+       my @torename=@{$params{torename}};
+       my %done=%{$params{done}};
+       my $q=$params{cgi};
+       my $session=$params{session};
+
+       return () unless @torename;
+
+       my @nextset;
+       foreach my $torename (@torename) {
+               unless (exists $done{$torename->{src}} && $done{$torename->{src}}) {
+                       IkiWiki::run_hooks(rename => sub {
+                               push @nextset, shift->(
+                                       torename => $torename,
+                                       cgi => $q,
+                                       session => $session,
+                               );
+                       });
+                       $done{$torename->{src}}=1;
+               }
+       }
+
+       push @torename, rename_hook(
+               torename => \@nextset,
+               done => \%done,
+               cgi => $q,
+               session => $session,
+       );
+
+       # dedup
+       my %seen;
+       return grep { ! $seen{$_->{src}}++ } @torename;
+}
+
+sub do_rename ($$$) {
+       my $rename=shift;
+       my $q=shift;
+       my $session=shift;
+
+       # First, check if this rename is allowed.
+       check_canrename($rename->{src},
+               $rename->{srcfile},
+               $rename->{dest},
+               $rename->{destfile},
+               $q, $session);
+
+       # Ensure that the dest directory exists and is ok.
+       IkiWiki::prep_writefile($rename->{destfile}, $config{srcdir});
+
+       if ($config{rcs}) {
+               IkiWiki::rcs_rename($rename->{srcfile}, $rename->{destfile});
+       }
+       else {
+               if (! rename($config{srcdir}."/".$rename->{srcfile},
+                            $config{srcdir}."/".$rename->{destfile})) {
+                       error("rename: $!");
+               }
+       }
+
+}
+
+sub fixlinks ($$$) {
+       my $rename=shift;
+       my $session=shift;
+
+       my @fixedlinks;
+
+       foreach my $page (keys %links) {
+               my $needfix=0;
+               foreach my $link (@{$links{$page}}) {
+                       my $bestlink=bestlink($page, $link);
+                       if ($bestlink eq $rename->{src}) {
+                               $needfix=1;
+                               last;
+                       }
+               }
+               if ($needfix) {
+                       my $file=$pagesources{$page};
+                       my $oldcontent=readfile($config{srcdir}."/".$file);
+                       my $content=renamepage_hook($page, $rename->{src}, $rename->{dest}, $oldcontent);
+                       if ($oldcontent ne $content) {
+                               my $token=IkiWiki::rcs_prepedit($file);
+                               eval { writefile($file, $config{srcdir}, $content) };
+                               next if $@;
+                               my $conflict=IkiWiki::rcs_commit(
+                                       $file,
+                                       sprintf(gettext("update for rename of %s to %s"), $rename->{srcfile}, $rename->{destfile}),
+                                       $token,
+                                       $session->param("name"), 
+                                       $ENV{REMOTE_ADDR}
+                               );
+                               push @fixedlinks, $page if ! defined $conflict;
+                       }
+               }
+       }
+
+       return @fixedlinks;
+}
+
+1
diff --git a/IkiWiki/Plugin/repolist.pm b/IkiWiki/Plugin/repolist.pm
new file mode 100644 (file)
index 0000000..f69ec39
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::repolist;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getsetup", id => "repolist",  call => \&getsetup);
+       hook(type => "checkconfig", id => "repolist", call => \&checkconfig);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               repositories => {
+                       type => "string",
+                       example => ["svn://svn.example.org/wiki/trunk"],
+                       description => "URIs of repositories containing the wiki's source",
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+my $relvcs;
+
+sub checkconfig () {
+       if (defined $config{rcs} && $config{repositories}) {
+               $relvcs=join("\n", map {
+                       s/"//g; # avoid quotes just in case
+                       qq{<link rel="vcs-$config{rcs}" href="$_" title="wiki $config{rcs} repository" />}
+               } @{$config{repositories}});
+               
+               hook(type => "pagetemplate", id => "repolist", call => \&pagetemplate);
+       }
+}
+
+sub pagetemplate (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+       
+        if (defined $relvcs && $template->query(name => "relvcs")) {
+               $template->param(relvcs => $relvcs);
+       }
+}
+
+1
index 284f477fae5b32f63f9c9159f06c4af84dea2acd..393c17e0fe8cf6b9ec137ba7cfc8ac64e008cd4b 100644 (file)
@@ -4,30 +4,46 @@ package IkiWiki::Plugin::search;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "search", call => \&getsetup);
        hook(type => "checkconfig", id => "search", call => \&checkconfig);
        hook(type => "pagetemplate", id => "search", call => \&pagetemplate);
-       hook(type => "sanitize", id => "search", call => \&index);
+       hook(type => "postscan", id => "search", call => \&index);
        hook(type => "delete", id => "search", call => \&delete);
        hook(type => "cgi", id => "search", call => \&cgi);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               omega_cgi => {
+                       type => "string",
+                       example => "/usr/lib/cgi-bin/omega/omega",
+                       description => "path to the omega cgi program",
+                       safe => 0, # external program
+                       rebuild => 0,
+               },
+}
 
-sub checkconfig () { #{{{
+sub checkconfig () {
        foreach my $required (qw(url cgiurl)) {
                if (! length $config{$required}) {
-                       error(sprintf(gettext("Must specify %s when using the search plugin"), $required));
+                       error(sprintf(gettext("Must specify %s when using the %s plugin"), $required, 'search'));
                }
        }
        
-       if (! exists $config{omega_cgi}) {
+       if (! defined $config{omega_cgi}) {
                $config{omega_cgi}="/usr/lib/cgi-bin/omega/omega";
        }
-} #}}}
+}
 
 my $form;
-sub pagetemplate (@) { #{{{
+sub pagetemplate (@) {
        my %params=@_;
        my $page=$params{page};
        my $template=$params{template};
@@ -42,14 +58,12 @@ sub pagetemplate (@) { #{{{
 
                $template->param(searchform => $form);
        }
-} #}}}
+}
 
 my $scrubber;
 my $stemmer;
-sub index (@) { #{{{
+sub index (@) {
        my %params=@_;
-       
-       return $params{content} if $IkiWiki::preprocessing{$params{destpage}};
 
        setupfiles();
 
@@ -59,7 +73,7 @@ sub index (@) { #{{{
        
        my $db=xapiandb();
        my $doc=Search::Xapian::Document->new();
-       my $caption=IkiWiki::pagetitle($params{page});
+       my $caption=pagetitle($params{page});
        my $title;
        if (exists $pagestate{$params{page}}{meta} &&
                exists $pagestate{$params{page}}{meta}{title}) {
@@ -125,26 +139,24 @@ sub index (@) { #{{{
        $tg->index_text($caption, 2);
        $tg->index_text($title, 2) if $title ne $caption;
        $tg->index_text($toindex);
-       $tg->index_text(lc($title), 1, "ZS"); # for title:foo
+       $tg->index_text(lc($title), 1, "S"); # for title:foo
        foreach my $link (@{$links{$params{page}}}) {
-               $tg->index_text(lc($link), 1, "ZLINK"); # for link:bar
+               $tg->index_text(lc($link), 1, "XLINK"); # for link:bar
        }
 
        $doc->add_term($pageterm);
        $db->replace_document_by_term($pageterm, $doc);
+}
 
-       return $params{content};
-} #}}}
-
-sub delete (@) { #{{{
+sub delete (@) {
        my $db=xapiandb();
        foreach my $page (@_) {
                my $pageterm=pageterm(pagename($page));
                $db->delete_document_by_term($pageterm) if defined $pageterm;
        }
-} #}}}
+}
 
-sub cgi ($) { #{{{
+sub cgi ($) {
        my $cgi=shift;
 
        if (defined $cgi->param('P')) {
@@ -157,9 +169,9 @@ sub cgi ($) { #{{{
                        noimageinline => 1, linktext => "Help");
                exec($config{omega_cgi}) || error("$config{omega_cgi} failed: $!");
        }
-} #}}}
+}
 
-sub pageterm ($) { #{{{
+sub pageterm ($) {
        my $page=shift;
 
        # 240 is the number used by omindex to decide when to hash an
@@ -178,10 +190,10 @@ sub pageterm ($) { #{{{
        else {
                return "U:".$page;
        }
-} #}}}
+}
 
 my $db;
-sub xapiandb () { #{{{
+sub xapiandb () {
        if (! defined $db) {
                eval q{
                        use Search::Xapian;
@@ -192,11 +204,11 @@ sub xapiandb () { #{{{
                        Search::Xapian::DB_CREATE_OR_OPEN());
        }
        return $db;
-} #}}}
+}
 
 {
 my $setup=0;
-sub setupfiles () { #{{{
+sub setupfiles () {
        if (! $setup and (! -e $config{wikistatedir}."/xapian" || $config{rebuild})) {
                writefile("omega.conf", $config{wikistatedir}."/xapian",
                        "database_dir .\n".
@@ -206,7 +218,7 @@ sub setupfiles () { #{{{
                                readfile(IkiWiki::template_file("searchquery.tmpl"))));
                $setup=1;
        }
-} #}}}
+}
 }
 
 1
index f1a38ea48070ed255ea8046e8b4d5c1dd6787af3..1840a5722a6300d7ce30d14cd4534ef2bc16a48d 100644 (file)
@@ -3,40 +3,58 @@ package IkiWiki::Plugin::shortcut;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "shortcut", call => \&getsetup);
        hook(type => "checkconfig", id => "shortcut", call => \&checkconfig);
        hook(type => "preprocess", id => "shortcut", call => \&preprocess_shortcut);
-} #}}}
+}
 
-sub checkconfig () { #{{{
-       # Preprocess the shortcuts page to get all the available shortcuts
-       # defined before other pages are rendered.
-       my $srcfile=srcfile("shortcuts.mdwn", 1);
-       if (! defined $srcfile) {
-               error(gettext("shortcut plugin will not work without a shortcuts.mdwn"));
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub checkconfig () {
+       if (defined $config{srcdir} && length $config{srcdir}) {
+               # Preprocess the shortcuts page to get all the available shortcuts
+               # defined before other pages are rendered.
+               my $srcfile=srcfile("shortcuts.".$config{default_pageext}, 1);
+               if (! defined $srcfile) {
+                       $srcfile=srcfile("shortcuts.mdwn", 1);
+               }
+               if (! defined $srcfile) {
+                       print STDERR sprintf(gettext("shortcut plugin will not work without %s"),
+                               "shortcuts.".$config{default_pageext})."\n";
+               }
+               else {
+                       IkiWiki::preprocess("shortcuts", "shortcuts", readfile($srcfile));
+               }
        }
-       IkiWiki::preprocess("shortcuts", "shortcuts", readfile($srcfile));
-} # }}}
+}
 
-sub preprocess_shortcut (@) { #{{{
+sub preprocess_shortcut (@) {
        my %params=@_;
 
        if (! defined $params{name} || ! defined $params{url}) {
-               return "[[shortcut ".gettext("missing name or url parameter")."]]";
+               error gettext("missing name or url parameter");
        }
 
        hook(type => "preprocess", no_override => 1, id => $params{name},
+               shortcut => 1,
                call => sub { shortcut_expand($params{url}, $params{desc}, @_) });
 
        #translators: This is used to display what shortcuts are defined.
        #translators: First parameter is the name of the shortcut, the second
        #translators: is an URL.
        return sprintf(gettext("shortcut %s points to <i>%s</i>"), $params{name}, $params{url});
-} # }}}
+}
 
-sub shortcut_expand ($$@) { #{{{
+sub shortcut_expand ($$@) {
        my $url=shift;
        my $desc=shift;
        my %params=@_;
@@ -73,6 +91,6 @@ sub shortcut_expand ($$@) { #{{{
        }
 
        return "<a href=\"$url\">$desc</a>";
-} #}}}
+}
 
 1
index 7c2e6e1f680a28561cf0282f0ff631afd76b034b..41812e1c1f671da84be1a06a5821695fc5dc6f11 100644 (file)
@@ -6,13 +6,22 @@ package IkiWiki::Plugin::sidebar;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "sidebar", call => \&getsetup);
        hook(type => "pagetemplate", id => "sidebar", call => \&pagetemplate);
-} # }}}
+}
 
-sub sidebar_content ($) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub sidebar_content ($) {
        my $page=shift;
        
        my $sidebar_page=bestlink($page, "sidebar") || return;
@@ -33,9 +42,9 @@ sub sidebar_content ($) { #{{{
                       IkiWiki::filter($sidebar_page, $page, $content))));
        }
 
-} # }}}
+}
 
-sub pagetemplate (@) { #{{{
+sub pagetemplate (@) {
        my %params=@_;
 
        my $page=$params{page};
@@ -47,6 +56,6 @@ sub pagetemplate (@) { #{{{
                        $template->param(sidebar => $content);
                }
        }
-} # }}}
+}
 
 1
index 84ab3a4d0cbc7777b8df2b5b8c62cb0f0b94a9c9..032a0034c0c4e3354ea8274a6259fb0478ad949e 100644 (file)
@@ -3,14 +3,23 @@ package IkiWiki::Plugin::signinedit;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "signinedit", call => \&getsetup);
        hook(type => "canedit", id => "signinedit", call => \&canedit,
             last => 1);
-} # }}}
+}
 
-sub canedit ($$$) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+}
+
+sub canedit ($$$) {
        my $page=shift;
        my $cgi=shift;
        my $session=shift;
@@ -25,6 +34,6 @@ sub canedit ($$$) { #{{{
        else {
                return "";
        }
-} #}}}
+}
 
 1
diff --git a/IkiWiki/Plugin/skeleton.pm b/IkiWiki/Plugin/skeleton.pm
deleted file mode 100644 (file)
index 17a2162..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/usr/bin/perl
-# Ikiwiki skeleton plugin. Replace "skeleton" with the name of your plugin
-# in the lines below, remove hooks you don't use, and flesh out the code to
-# make it do something.
-package IkiWiki::Plugin::skeleton;
-
-use warnings;
-use strict;
-use IkiWiki 2.00;
-
-sub import { #{{{
-       hook(type => "getopt", id => "skeleton",  call => \&getopt);
-       hook(type => "checkconfig", id => "skeleton", call => \&checkconfig);
-       hook(type => "needsbuild", id => "skeleton", call => \&needsbuild);
-       hook(type => "preprocess", id => "skeleton", call => \&preprocess);
-       hook(type => "filter", id => "skeleton", call => \&filter);
-       hook(type => "linkify", id => "skeleton", call => \&linkify);
-       hook(type => "scan", id => "skeleton", call => \&scan);
-       hook(type => "htmlize", id => "skeleton", call => \&htmlize);
-       hook(type => "sanitize", id => "skeleton", call => \&sanitize);
-       hook(type => "format", id => "skeleton", call => \&format);
-       hook(type => "pagetemplate", id => "skeleton", call => \&pagetemplate);
-       hook(type => "templatefile", id => "skeleton", call => \&templatefile);
-       hook(type => "delete", id => "skeleton", call => \&delete);
-       hook(type => "change", id => "skeleton", call => \&change);
-       hook(type => "cgi", id => "skeleton", call => \&cgi);
-       hook(type => "auth", id => "skeleton", call => \&auth);
-       hook(type => "sessioncgi", id => "skeleton", call => \&sessioncgi);
-       hook(type => "canedit", id => "skeleton", call => \&canedit);
-       hook(type => "editcontent", id => "skeleton", call => \&editcontent);
-       hook(type => "formbuilder_setup", id => "skeleton", call => \&formbuilder_setup);
-       hook(type => "formbuilder", id => "skeleton", call => \&formbuilder);
-       hook(type => "savestate", id => "skeleton", call => \&savestate);
-} # }}}
-
-sub getopt () { #{{{
-       debug("skeleton plugin getopt");
-} #}}}
-
-sub checkconfig () { #{{{
-       debug("skeleton plugin checkconfig");
-} #}}}
-
-sub needsbuild () { #{{{
-       debug("skeleton plugin needsbuild");
-} #}}}
-
-sub preprocess (@) { #{{{
-       my %params=@_;
-
-       return "skeleton plugin result";
-} # }}}
-
-sub filter (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running as filter");
-
-       return $params{content};
-} # }}}
-
-sub linkify (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running as linkify");
-
-       return $params{content};
-} # }}}
-
-sub scan (@) { #{{{a
-       my %params=@_;
-
-       debug("skeleton plugin running as scan");
-} # }}}
-
-sub htmlize (@) { #{{{
-       my %params=@_;
-
-       debug("skeleton plugin running as htmlize");
-
-       return $params{content};
-} # }}}
-
-sub sanitize (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running as a sanitizer");
-
-       return $params{content};
-} # }}}
-
-sub format (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running as a formatter");
-
-       return $params{content};
-} # }}}
-
-sub pagetemplate (@) { #{{{
-       my %params=@_;
-       my $page=$params{page};
-       my $template=$params{template};
-       
-       debug("skeleton plugin running as a pagetemplate hook");
-} # }}}
-
-sub templatefile (@) { #{{{
-       my %params=@_;
-       my $page=$params{page};
-       
-       debug("skeleton plugin running as a templatefile hook");
-} # }}}
-
-sub delete (@) { #{{{
-       my @files=@_;
-
-       debug("skeleton plugin told that files were deleted: @files");
-} #}}}
-
-sub change (@) { #{{{
-       my @files=@_;
-
-       debug("skeleton plugin told that changed files were rendered: @files");
-} #}}}
-
-sub cgi ($) { #{{{
-       my $cgi=shift;
-
-       debug("skeleton plugin running in cgi");
-} #}}}
-
-sub auth ($$) { #{{{
-       my $cgi=shift;
-       my $session=shift;
-
-       debug("skeleton plugin running in auth");
-} #}}}
-
-sub sessionncgi ($$) { #{{{
-       my $cgi=shift;
-       my $session=shift;
-
-       debug("skeleton plugin running in sessioncgi");
-} #}}}
-
-sub canedit ($$$) { #{{{
-       my $page=shift;
-       my $cgi=shift;
-       my $session=shift;
-
-       debug("skeleton plugin running in canedit");
-} #}}}
-
-sub editcontent ($$$) { #{{{
-       my %params=@_;
-
-       debug("skeleton plugin running in editcontent");
-
-       return $params{content};
-} #}}}
-
-sub formbuilder_setup (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running in formbuilder_setup");
-} # }}}
-
-sub formbuilder (@) { #{{{
-       my %params=@_;
-       
-       debug("skeleton plugin running in formbuilder");
-} # }}}
-
-sub savestate () { #{{{
-       debug("skeleton plugin running in savestate");
-} #}}}
-
-1
diff --git a/IkiWiki/Plugin/skeleton.pm.example b/IkiWiki/Plugin/skeleton.pm.example
new file mode 100644 (file)
index 0000000..5735101
--- /dev/null
@@ -0,0 +1,242 @@
+#!/usr/bin/perl
+# Ikiwiki skeleton plugin. Replace "skeleton" with the name of your plugin
+# in the lines below, remove hooks you don't use, and flesh out the code to
+# make it do something.
+package IkiWiki::Plugin::skeleton;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getopt", id => "skeleton",  call => \&getopt);
+       hook(type => "getsetup", id => "skeleton",  call => \&getsetup);
+       hook(type => "checkconfig", id => "skeleton", call => \&checkconfig);
+       hook(type => "refresh", id => "skeleton", call => \&refresh);
+       hook(type => "needsbuild", id => "skeleton", call => \&needsbuild);
+       hook(type => "preprocess", id => "skeleton", call => \&preprocess);
+       hook(type => "filter", id => "skeleton", call => \&filter);
+       hook(type => "linkify", id => "skeleton", call => \&linkify);
+       hook(type => "scan", id => "skeleton", call => \&scan);
+       hook(type => "htmlize", id => "skeleton", call => \&htmlize);
+       hook(type => "sanitize", id => "skeleton", call => \&sanitize);
+       hook(type => "postscan", id => "skeleton", call => \&postscan);
+       hook(type => "format", id => "skeleton", call => \&format);
+       hook(type => "pagetemplate", id => "skeleton", call => \&pagetemplate);
+       hook(type => "templatefile", id => "skeleton", call => \&templatefile);
+       hook(type => "delete", id => "skeleton", call => \&delete);
+       hook(type => "change", id => "skeleton", call => \&change);
+       hook(type => "cgi", id => "skeleton", call => \&cgi);
+       hook(type => "auth", id => "skeleton", call => \&auth);
+       hook(type => "sessioncgi", id => "skeleton", call => \&sessioncgi);
+       hook(type => "canedit", id => "skeleton", call => \&canedit);
+       hook(type => "canremove", id => "skeleton", call => \&canremove);
+       hook(type => "canrename", id => "skeleton", call => \&canrename);
+       hook(type => "checkcontent", id => "skeleton", call => \&checkcontent);
+       hook(type => "editcontent", id => "skeleton", call => \&editcontent);
+       hook(type => "formbuilder_setup", id => "skeleton", call => \&formbuilder_setup);
+       hook(type => "formbuilder", id => "skeleton", call => \&formbuilder);
+       hook(type => "renamepage", id => "skeleton", call => \&renamepage);
+       hook(type => "rename", id => "skeleton", call => \&rename);
+       hook(type => "savestate", id => "skeleton", call => \&savestate);
+}
+
+sub getopt () {
+       debug("skeleton plugin getopt");
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               skeleton => {
+                       type => "boolean",
+                       example => 0,
+                       description => "example option",
+                       safe => 0,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
+       debug("skeleton plugin checkconfig");
+}
+
+sub refresh () {
+       debug("skeleton plugin refresh");
+}
+
+sub needsbuild () {
+       debug("skeleton plugin needsbuild");
+}
+
+sub preprocess (@) {
+       my %params=@_;
+
+       return "skeleton plugin result";
+}
+
+sub filter (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running as filter");
+
+       return $params{content};
+}
+
+sub linkify (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running as linkify");
+
+       return $params{content};
+}
+
+sub scan (@) {
+       my %params=@_;
+
+       debug("skeleton plugin running as scan");
+}
+
+sub htmlize (@) {
+       my %params=@_;
+
+       debug("skeleton plugin running as htmlize");
+
+       return $params{content};
+}
+
+sub sanitize (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running as a sanitizer");
+
+       return $params{content};
+}
+
+sub postscan (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running as postscan");
+}
+
+sub format (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running as a formatter");
+
+       return $params{content};
+}
+
+sub pagetemplate (@) {
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+       
+       debug("skeleton plugin running as a pagetemplate hook");
+}
+
+sub templatefile (@) {
+       my %params=@_;
+       my $page=$params{page};
+       
+       debug("skeleton plugin running as a templatefile hook");
+}
+
+sub delete (@) {
+       my @files=@_;
+
+       debug("skeleton plugin told that files were deleted: @files");
+}
+
+sub change (@) {
+       my @files=@_;
+
+       debug("skeleton plugin told that changed files were rendered: @files");
+}
+
+sub cgi ($) {
+       my $cgi=shift;
+
+       debug("skeleton plugin running in cgi");
+}
+
+sub auth ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       debug("skeleton plugin running in auth");
+}
+
+sub sessioncgi ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       debug("skeleton plugin running in sessioncgi");
+}
+
+sub canedit ($$$) {
+       my $page=shift;
+       my $cgi=shift;
+       my $session=shift;
+
+       debug("skeleton plugin running in canedit");
+}
+
+sub canremove (@) {
+       my %params=@_;
+
+       debug("skeleton plugin running in canremove");
+}
+
+sub canrename (@) {
+       my %params=@_;
+
+       debug("skeleton plugin running in canrename");
+}
+
+sub checkcontent (@) {
+       my %params=@_;
+
+       debug("skeleton plugin running in checkcontent");
+}
+
+sub editcontent ($$$) {
+       my %params=@_;
+
+       debug("skeleton plugin running in editcontent");
+
+       return $params{content};
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running in formbuilder_setup");
+}
+
+sub formbuilder (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running in formbuilder");
+}
+
+sub renamepage (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running in renamepage");
+}
+
+sub rename (@) {
+       my %params=@_;
+       
+       debug("skeleton plugin running in rename");
+}
+
+sub savestate () {
+       debug("skeleton plugin running in savestate");
+}
+
+1
index 51b32b28fa1a1a18823ef3fed6206b53c8faffb3..0d77916d0d3d633e7656d79527cce12647089d47 100644 (file)
@@ -3,19 +3,30 @@ package IkiWiki::Plugin::smiley;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %smileys;
 my $smiley_regexp;
 
-sub import { #{{{
+sub import {
        add_underlay("smiley");
+       hook(type => "getsetup", id => "smiley", call => \&getsetup);
        hook(type => "sanitize", id => "smiley", call => \&sanitize);
-} # }}}
+}
 
-sub build_regexp () { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       # force a rebuild because turning it off
+                       # removes the smileys, which would break links
+                       rebuild => 1,
+               },
+}
+
+sub build_regexp () {
        my $list=readfile(srcfile("smileys.mdwn"));
-       while ($list =~ m/^\s*\*\s+\\([^\s]+)\s+\[\[([^]]+)\]\]/mg) {
+       while ($list =~ m/^\s*\*\s+\\\\([^\s]+)\s+\[\[([^]]+)\]\]/mg) {
                my $smiley=$1;
                my $file=$2;
 
@@ -39,16 +50,16 @@ sub build_regexp () { #{{{
        $smiley_regexp='('.join('|', map { quotemeta }
                reverse sort keys %smileys).')';
        #debug($smiley_regexp);
-} #}}}
+}
 
-sub sanitize (@) { #{{{
+sub sanitize (@) {
        my %params=@_;
 
        build_regexp() unless defined $smiley_regexp;
        
        $_=$params{content};
        return $_ unless length $smiley_regexp;
-       
+                       
 MATCH: while (m{(?:^|(?<=\s|>))(\\?)$smiley_regexp(?:(?=\s|<)|$)}g) {
                my $escape=$1;
                my $smiley=$2;
@@ -68,20 +79,22 @@ MATCH:      while (m{(?:^|(?<=\s|>))(\\?)$smiley_regexp(?:(?=\s|<)|$)}g) {
                        # Reset pos back to where it was before this test.
                        pos=$pos;
                }
-
+       
                if ($escape) {
                        # Remove escape.
                        substr($_, $epos, 1)="";
+                       pos=$epos+1;
                }
                else {
                        # Replace the smiley with its expanded value.
-                       substr($_, $spos, length($smiley))=
-                               htmllink($params{page}, $params{destpage},
+                       my $link=htmllink($params{page}, $params{destpage},
                                         $smileys{$smiley}, linktext => $smiley);
+                       substr($_, $spos, length($smiley))=$link;
+                       pos=$epos+length($link);
                }
        }
 
        return $_;
-} # }}}
+}
 
 1
index 69b3512c27e708d1155fab842e76b46b7dbff9f5..c1f016ffd0e7055bae3f5ba72f9f04b643285c01 100644 (file)
@@ -3,7 +3,7 @@ package IkiWiki::Plugin::sparkline;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use IPC::Open2;
 
 my $match_num=qr/[-+]?[0-9]+(?:\.[0-9]+)?/;
@@ -14,11 +14,20 @@ my %locmap=(
        left => 'TEXT_LEFT',
 );
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "sparkline", call => \&getsetup);
        hook(type => "preprocess", id => "sparkline", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
 
        my $php;
@@ -60,13 +69,13 @@ sub preprocess (@) { #{{{
                        }
                }
                elsif (! length $value) {
-                       return "[[sparkline ".gettext("parse error")." \"$key\"]]";
+                       error gettext("parse error")." \"$key\"";
                }
                elsif ($key eq 'featurepoint') {
                        my ($x, $y, $color, $diameter, $text, $location)=
                                split(/\s*,\s*/, $value);
                        if (! defined $diameter || $diameter < 0) {
-                               return "[[sparkline ".gettext("bad featurepoint diameter")."]]";
+                               error gettext("invalid featurepoint diameter");
                        }
                        $x=int($x);
                        $y=int($y);
@@ -76,7 +85,7 @@ sub preprocess (@) { #{{{
                        if (defined $location) {
                                $location=$locmap{$location};
                                if (! defined $location) {
-                                       return "[[sparkline ".gettext("bad featurepoint location")."]]";
+                                       error gettext("invalid featurepoint location");
                                }
                        }
                        $php.=qq{\$sparkline->SetFeaturePoint($x, $y, '$color', $diameter};
@@ -87,23 +96,23 @@ sub preprocess (@) { #{{{
        }
 
        if ($c eq 0) {
-               return "[[sparkline ".gettext("missing values")."]]";
+               error gettext("missing values");
        }
 
        my $height=int($params{height} || 20);
        if ($height < 2 || $height > 100) {
-               return "[[sparkline ".gettext("bad height value")."]]";
+               error gettext("invalid height value");
        }
        if ($style eq "Bar") {
                $php.=qq{\$sparkline->Render($height);\n};
        }
        else {
                if (! exists $params{width}) {
-                       return "[[sparkline ".gettext("missing width parameter")."]]";
+                       error gettext("missing width parameter");
                }
                my $width=int($params{width});
                if ($width < 2 || $width > 1024) {
-                       return "[[sparkline ".gettext("bad width value")."]]";
+                       error gettext("invalid width value");
                }
                $php.=qq{\$sparkline->RenderResampled($width, $height);\n};
        }
@@ -121,7 +130,7 @@ sub preprocess (@) { #{{{
 
        if (! -e "$config{destdir}/$fn") {
                my $pid;
-               my $sigpipe=0;;
+               my $sigpipe=0;
                $SIG{PIPE}=sub { $sigpipe=1 };
                $pid=open2(*IN, *OUT, "php");
 
@@ -141,7 +150,7 @@ sub preprocess (@) { #{{{
                waitpid $pid, 0;
                $SIG{PIPE}="DEFAULT";
                if ($sigpipe) {
-                       return  "[[sparkline ".gettext("failed to run php")."]]";
+                       error gettext("failed to run php");
                }
 
                if (! $params{preview}) {
@@ -157,6 +166,6 @@ sub preprocess (@) { #{{{
        }
 
        return '<img src="'.urlto($fn, $params{destpage}).'" alt="graph" />';
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/svn.pm b/IkiWiki/Plugin/svn.pm
new file mode 100644 (file)
index 0000000..06b987f
--- /dev/null
@@ -0,0 +1,381 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::svn;
+
+use warnings;
+use strict;
+use IkiWiki;
+use POSIX qw(setlocale LC_CTYPE);
+
+sub import {
+       hook(type => "checkconfig", id => "svn", call => \&checkconfig);
+       hook(type => "getsetup", id => "svn", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub checkconfig () {
+       if (! defined $config{svnpath}) {
+               $config{svnpath}="trunk";
+       }
+       if (exists $config{svnpath}) {
+               # code depends on the path not having extraneous slashes
+               $config{svnpath}=~tr#/#/#s;
+               $config{svnpath}=~s/\/$//;
+               $config{svnpath}=~s/^\///;
+       }
+       if (defined $config{svn_wrapper} && length $config{svn_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{svn_wrapper},
+                       wrappermode => (defined $config{svn_wrappermode} ? $config{svn_wrappermode} : "04755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               svnrepo => {
+                       type => "string",
+                       example => "/svn/wiki",
+                       description => "subversion repository location",
+                       safe => 0, # path
+                       rebuild => 0,
+               },
+               svnpath => {
+                       type => "string",
+                       example => "trunk",
+                       description => "path inside repository where the wiki is located",
+                       safe => 0, # paranoia
+                       rebuild => 0,
+               },
+               svn_wrapper => {
+                       type => "string",
+                       example => "/svn/wikirepo/hooks/post-commit",
+                       description => "svn post-commit hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               svn_wrappermode => {
+                       type => "string",
+                       example => '04755',
+                       description => "mode for svn_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       example => "http://svn.example.org/trunk/[[file]]",
+                       description => "viewvc url to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       example => "http://svn.example.org/trunk/[[file]]?root=wiki&amp;r1=[[r1]]&amp;r2=[[r2]]",
+                       description => "viewvc url to show a diff ([[file]], [[r1]], and [[r2]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+# svn needs LC_CTYPE set to a UTF-8 locale, so try to find one. Any will do.
+sub find_lc_ctype() {
+       my $current = setlocale(LC_CTYPE());
+       return $current if $current =~ m/UTF-?8$/i;
+
+       # Make some obvious attempts to avoid calling `locale -a`
+       foreach my $locale ("$current.UTF-8", "en_US.UTF-8", "en_GB.UTF-8") {
+               return $locale if setlocale(LC_CTYPE(), $locale);
+       }
+
+       # Try to get all available locales and pick the first UTF-8 one found.
+       if (my @locale = grep(/UTF-?8$/i, `locale -a`)) {
+               chomp @locale;
+               return $locale[0] if setlocale(LC_CTYPE(), $locale[0]);
+       }
+
+       # fallback to the current locale
+       return $current;
+}
+$ENV{LC_CTYPE} = $ENV{LC_CTYPE} || find_lc_ctype();
+
+sub svn_info ($$) {
+       my $field=shift;
+       my $file=shift;
+
+       my $info=`LANG=C svn info $file`;
+       my ($ret)=$info=~/^$field: (.*)$/m;
+       return $ret;
+}
+
+sub rcs_update () {
+       if (-d "$config{srcdir}/.svn") {
+               if (system("svn", "update", "--quiet", $config{srcdir}) != 0) {
+                       warn("svn update failed\n");
+               }
+       }
+}
+
+sub rcs_prepedit ($) {
+       # Prepares to edit a file under revision control. Returns a token
+       # that must be passed into rcs_commit when the file is ready
+       # for committing.
+       # The file is relative to the srcdir.
+       my $file=shift;
+       
+       if (-d "$config{srcdir}/.svn") {
+               # For subversion, return the revision of the file when
+               # editing begins.
+               my $rev=svn_info("Revision", "$config{srcdir}/$file");
+               return defined $rev ? $rev : "";
+       }
+}
+
+sub rcs_commit ($$$;$$) {
+       # Tries to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on failure.
+       # The file is relative to the srcdir.
+       my $file=shift;
+       my $message=shift;
+       my $rcstoken=shift;
+       my $user=shift;
+       my $ipaddr=shift;
+
+       if (defined $user) {
+               $message="web commit by $user".(length $message ? ": $message" : "");
+       }
+       elsif (defined $ipaddr) {
+               $message="web commit from $ipaddr".(length $message ? ": $message" : "");
+       }
+
+       if (-d "$config{srcdir}/.svn") {
+               # Check to see if the page has been changed by someone
+               # else since rcs_prepedit was called.
+               my ($oldrev)=$rcstoken=~/^([0-9]+)$/; # untaint
+               my $rev=svn_info("Revision", "$config{srcdir}/$file");
+               if (defined $rev && defined $oldrev && $rev != $oldrev) {
+                       # Merge their changes into the file that we've
+                       # changed.
+                       if (system("svn", "merge", "--quiet", "-r$oldrev:$rev",
+                                  "$config{srcdir}/$file", "$config{srcdir}/$file") != 0) {
+                               warn("svn merge -r$oldrev:$rev failed\n");
+                       }
+               }
+
+               if (system("svn", "commit", "--quiet", 
+                          "--encoding", "UTF-8", "-m",
+                          IkiWiki::possibly_foolish_untaint($message),
+                          $config{srcdir}) != 0) {
+                       my $conflict=readfile("$config{srcdir}/$file");
+                       if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
+                               warn("svn revert failed\n");
+                       }
+                       return $conflict;
+               }
+       }
+       return undef # success
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+       
+       if (defined $user) {
+               $message="web commit by $user".(length $message ? ": $message" : "");
+       }
+       elsif (defined $ipaddr) {
+               $message="web commit from $ipaddr".(length $message ? ": $message" : "");
+       }
+       
+       if (system("svn", "commit", "--quiet",
+                  "--encoding", "UTF-8", "-m",
+                  IkiWiki::possibly_foolish_untaint($message),
+                  $config{srcdir}) != 0) {
+               warn("svn commit failed\n");
+               return 1; # failure     
+       }
+       return undef # success
+}
+
+sub rcs_add ($) {
+       # filename is relative to the root of the srcdir
+       my $file=shift;
+
+       if (-d "$config{srcdir}/.svn") {
+               my $parent=IkiWiki::dirname($file);
+               while (! -d "$config{srcdir}/$parent/.svn") {
+                       $file=$parent;
+                       $parent=IkiWiki::dirname($file);
+               }
+               
+               if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
+                       warn("svn add failed\n");
+               }
+       }
+}
+
+sub rcs_remove ($) {
+       # filename is relative to the root of the srcdir
+       my $file=shift;
+
+       if (-d "$config{srcdir}/.svn") {
+               if (system("svn", "rm", "--force", "--quiet", "$config{srcdir}/$file") != 0) {
+                       warn("svn rm failed\n");
+               }
+       }
+}
+
+sub rcs_rename ($$) {
+       # filenames relative to the root of the srcdir
+       my ($src, $dest)=@_;
+       
+       if (-d "$config{srcdir}/.svn") {
+               # Add parent directory for $dest
+               my $parent=IkiWiki::dirname($dest);
+               if (! -d "$config{srcdir}/$parent/.svn") {
+                       while (! -d "$config{srcdir}/$parent/.svn") {
+                               $parent=IkiWiki::dirname($dest);
+                       }
+                       if (system("svn", "add", "--quiet", "$config{srcdir}/$parent") != 0) {
+                               warn("svn add $parent failed\n");
+                       }
+               }
+
+               if (system("svn", "mv", "--force", "--quiet", 
+                   "$config{srcdir}/$src", "$config{srcdir}/$dest") != 0) {
+                       warn("svn rename failed\n");
+               }
+       }
+}
+
+sub rcs_recentchanges ($) {
+       my $num=shift;
+       my @ret;
+       
+       return unless -d "$config{srcdir}/.svn";
+
+       eval q{
+               use Date::Parse;
+               use XML::SAX;
+               use XML::Simple;
+       };
+       error($@) if $@;
+
+       # avoid using XML::SAX::PurePerl, it's buggy with UTF-8 data
+       my @parsers = map { ${$_}{Name} } @{XML::SAX->parsers()};
+       do {
+               $XML::Simple::PREFERRED_PARSER = pop @parsers;
+       } until $XML::Simple::PREFERRED_PARSER ne 'XML::SAX::PurePerl';
+
+       # --limit is only supported on Subversion 1.2.0+
+       my $svn_version=`svn --version -q`;
+       my $svn_limit='';
+       $svn_limit="--limit $num"
+               if $svn_version =~ /\d\.(\d)\.\d/ && $1 >= 2;
+
+       my $svn_url=svn_info("URL", $config{srcdir});
+       my $xml = XMLin(scalar `svn $svn_limit --xml -v log '$svn_url'`,
+               ForceArray => [ 'logentry', 'path' ],
+               GroupTags => { paths => 'path' },
+               KeyAttr => { path => 'content' },
+       );
+       foreach my $logentry (@{$xml->{logentry}}) {
+               my (@pages, @message);
+
+               my $rev = $logentry->{revision};
+               my $user = $logentry->{author};
+
+               my $when=str2time($logentry->{date}, 'UTC');
+
+               foreach my $msgline (split(/\n/, $logentry->{msg})) {
+                       push @message, { line => $msgline };
+               }
+
+               my $committype="web";
+               if (defined $message[0] &&
+                   $message[0]->{line}=~/$config{web_commit_regexp}/) {
+                       $user=defined $2 ? "$2" : "$3";
+                       $message[0]->{line}=$4;
+               }
+               else {
+                       $committype="svn";
+               }
+
+               foreach my $file (keys %{$logentry->{paths}}) {
+                       if (length $config{svnpath}) {
+                               next unless $file=~/^\/\Q$config{svnpath}\E\/([^ ]+)(?:$|\s)/;
+                               $file=$1;
+                       }
+
+                       my $diffurl=defined $config{diffurl} ? $config{diffurl} : "";
+                       $diffurl=~s/\[\[file\]\]/$file/g;
+                       $diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
+                       $diffurl=~s/\[\[r2\]\]/$rev/g;
+
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       } if length $file;
+               }
+               push @ret, {
+                       rev => $rev,
+                       user => $user,
+                       committype => $committype,
+                       when => $when,
+                       message => [@message],
+                       pages => [@pages],
+               } if @pages;
+               return @ret if @ret >= $num;
+       }
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       my $rev=IkiWiki::possibly_foolish_untaint(int(shift));
+       return `svnlook diff $config{svnrepo} -r$rev --no-diff-deleted`;
+}
+
+sub rcs_getctime ($) {
+       my $file=shift;
+
+       my $svn_log_infoline=qr/^r\d+\s+\|\s+[^\s]+\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
+               
+       my $child = open(SVNLOG, "-|");
+       if (! $child) {
+               exec("svn", "log", $file) || error("svn log $file failed to run");
+       }
+
+       my $date;
+       while (<SVNLOG>) {
+               if (/$svn_log_infoline/) {
+                       $date=$1;
+               }
+       }
+       close SVNLOG || warn "svn log $file exited $?";
+
+       if (! defined $date) {
+               warn "failed to parse svn log for $file\n";
+               return 0;
+       }
+               
+       eval q{use Date::Parse};
+       error($@) if $@;
+       $date=str2time($date);
+       debug("found ctime ".localtime($date)." for $file");
+       return $date;
+}
+
+1
index 11474c8f08412c701a58f60ce350888f84a1057a..96d63f455f886e9111f0e7bd26558b020c1de61b 100644 (file)
@@ -4,27 +4,54 @@ package IkiWiki::Plugin::table;
 use warnings;
 use strict;
 use Encode;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-       hook(type => "preprocess", id => "table", call => \&preprocess);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "table", call => \&getsetup);
+       hook(type => "preprocess", id => "table", call => \&preprocess, scan => 1);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params =(
                format  => 'auto',
-               header  => 'yes',
+               header  => 'row',
                @_
        );
 
        if (exists $params{file}) {
-               if (! $pagesources{$params{file}}) {
-                       return "[[table ".gettext("cannot find file")."]]";
+               if (! exists $pagesources{$params{file}}) {
+                       error gettext("cannot find file");
                }
                $params{data} = readfile(srcfile($params{file}));
                add_depends($params{page}, $params{file});
        }
 
+       if (! defined wantarray) {
+               # scan mode --  if the table uses an external file, need to
+               # scan that file too.
+               return unless exists $params{file};
+
+               IkiWiki::run_hooks(scan => sub {
+                       shift->(
+                               page => $params{page},
+                               content => $params{data},
+                       );
+               });
+
+               # Preprocess in scan-only mode.
+               IkiWiki::preprocess($params{page}, $params{page}, $params{data}, 1);
+
+               return;
+       }
+
        if (lc $params{format} eq 'auto') {
                # first try the more simple format
                if (is_dsv_data($params{data})) {
@@ -41,35 +68,31 @@ sub preprocess (@) { #{{{
                        defined $params{delimiter} ? $params{delimiter} : ",",);
                # linkify after parsing since html link quoting can
                # confuse CSV parsing
-               if (! exists $params{file}) {
-                       @data=map {
-                               [ map {
-                                       IkiWiki::linkify($params{page},
-                                               $params{destpage}, $_);
-                               } @$_ ]
-                       } @data;
-               }
+               @data=map {
+                       [ map {
+                               IkiWiki::linkify($params{page},
+                                       $params{destpage}, $_);
+                       } @$_ ]
+               } @data;
        }
        elsif (lc $params{format} eq 'dsv') {
                # linkify before parsing since wikilinks can contain the
                # delimiter
-               if (! exists $params{file}) {
-                       $params{data} = IkiWiki::linkify($params{page},
-                               $params{destpage}, $params{data});
-               }
+               $params{data} = IkiWiki::linkify($params{page},
+                       $params{destpage}, $params{data});
                @data=split_dsv($params{data},
                        defined $params{delimiter} ? $params{delimiter} : "|",);
        }
        else {
-               return "[[table ".gettext("unknown data format")."]]";
+               error gettext("unknown data format");
        }
 
        my $header;
-       if (lc($params{header}) eq "yes") {
+       if (lc($params{header}) eq "row" || IkiWiki::yesno($params{header})) {
                $header=shift @data;
        }
        if (! @data) {
-               return "[[table ".gettext("empty data")."]]";
+               error gettext("empty data");
        }
 
        my @lines;
@@ -77,11 +100,10 @@ sub preprocess (@) { #{{{
                        ? "<table class=\"".$params{class}.'">'
                        : '<table>';
        push @lines, "\t<thead>",
-               genrow($params{page}, $params{destpage}, "th", @$header),
+               genrow(\%params, "th", @$header),
                "\t</thead>" if defined $header;
        push @lines, "\t<tbody>" if defined $header;
-       push @lines, genrow($params{page}, $params{destpage}, "td", @$_)
-               foreach @data;
+       push @lines, genrow(\%params, "td", @$_) foreach @data;
        push @lines, "\t</tbody>" if defined $header;
        push @lines, '</table>';
        my $html = join("\n", @lines);
@@ -94,16 +116,16 @@ sub preprocess (@) { #{{{
        else {  
                return $html;
        }            
-} #}}}
+}
 
-sub is_dsv_data ($) { #{{{
+sub is_dsv_data ($) {
        my $text = shift;
 
        my ($line) = split(/\n/, $text);
        return $line =~ m{.+\|};
 }
 
-sub split_csv ($$) { #{{{
+sub split_csv ($$) {
        my @text_lines = split(/\n/, shift);
        my $delimiter = shift;
 
@@ -129,9 +151,9 @@ sub split_csv ($$) { #{{{
        }
 
        return @data;
-} #}}}
+}
 
-sub split_dsv ($$) { #{{{
+sub split_dsv ($$) {
        my @text_lines = split(/\n/, shift);
        my $delimiter = shift;
        $delimiter="|" unless defined $delimiter;
@@ -142,41 +164,46 @@ sub split_dsv ($$) { #{{{
        }
     
        return @data;
-} #}}}
+}
 
-sub genrow ($$$@) { #{{{
-       my $page = shift;
-       my $destpage = shift;
+sub genrow ($@) {
+       my %params=%{shift()};
        my $elt = shift;
        my @data = @_;
 
+       my $page=$params{page};
+       my $destpage=$params{destpage};
+       my $type=pagetype($pagesources{$page});
+
        my @ret;
        push @ret, "\t\t<tr>";
        for (my $x=0; $x < @data; $x++) {
-               my $cell=htmlize($page, $destpage, $data[$x]);
+               my $cell=IkiWiki::htmlize($page, $destpage, $type,
+                        IkiWiki::preprocess($page, $destpage, $data[$x]));
+
+               # automatic colspan for empty cells
                my $colspan=1;
                while ($x+1 < @data && $data[$x+1] eq '') {
                        $x++;
                        $colspan++;
                }
+
+               # check if the first column should be a header
+               my $e=$elt;
+               if ($x == 0 && lc($params{header}) eq "column") {
+                       $e="th";
+               }
+
                if ($colspan > 1) {
-                       push @ret, "\t\t\t<$elt colspan=\"$colspan\">$cell</$elt>"
+                       push @ret, "\t\t\t<$e colspan=\"$colspan\">$cell</$e>"
                }
                else {
-                       push @ret, "\t\t\t<$elt>$cell</$elt>"
+                       push @ret, "\t\t\t<$e>$cell</$e>"
                }
        }
        push @ret, "\t\t</tr>";
 
        return @ret;
-} #}}}
-
-sub htmlize ($$$) { #{{{
-       my $page = shift;
-       my $destpage = shift;
-
-       return IkiWiki::htmlize($page, $destpage, pagetype($pagesources{$page}),
-               IkiWiki::preprocess($page, $destpage, shift));
 }
 
 1
index f0e3c223c5523a3c40cb47909099bfc2972e9b76..cdcfaf536082825444b3e8d3f27b406bc413cd53 100644 (file)
@@ -4,36 +4,62 @@ package IkiWiki::Plugin::tag;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
 my %tags;
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "tag", call => \&getopt);
+       hook(type => "getsetup", id => "tag", call => \&getsetup);
        hook(type => "preprocess", id => "tag", call => \&preprocess_tag, scan => 1);
        hook(type => "preprocess", id => "taglink", call => \&preprocess_taglink, scan => 1);
        hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
        eval q{use Getopt::Long};
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
        GetOptions("tagbase=s" => \$config{tagbase});
-} #}}}
+}
 
-sub tagpage ($) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               tagbase => {
+                       type => "string",
+                       example => "tag",
+                       description => "parent page tags are located under",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub tagpage ($) {
        my $tag=shift;
                        
-       if (exists $config{tagbase} &&
+       if ($tag !~ m{^\.?/} &&
            defined $config{tagbase}) {
-               $tag=$config{tagbase}."/".$tag;
+               $tag="/".$config{tagbase}."/".$tag;
+               $tag=~y#/#/#s; # squash dups
        }
 
        return $tag;
-} #}}}
+}
+
+sub taglink ($$$;@) {
+       my $page=shift;
+       my $destpage=shift;
+       my $tag=shift;
+       my %opts=@_;
 
-sub preprocess_tag (@) { #{{{
+       return htmllink($page, $destpage, tagpage($tag), %opts);
+}
+
+sub preprocess_tag (@) {
        if (! @_) {
                return "";
        }
@@ -44,43 +70,41 @@ sub preprocess_tag (@) { #{{{
        delete $params{preview};
 
        foreach my $tag (keys %params) {
-               $tag=IkiWiki::linkpage($tag);
+               $tag=linkpage($tag);
                $tags{$page}{$tag}=1;
                # hidden WikiLink
-               push @{$links{$page}}, tagpage($tag);
+               add_link($page, tagpage($tag));
        }
                
        return "";
-} # }}}
+}
 
-sub preprocess_taglink (@) { #{{{
+sub preprocess_taglink (@) {
        if (! @_) {
                return "";
        }
        my %params=@_;
        return join(" ", map {
                if (/(.*)\|(.*)/) {
-                       my $tag=IkiWiki::linkpage($2);
+                       my $tag=linkpage($2);
                        $tags{$params{page}}{$tag}=1;
-                       push @{$links{$params{page}}}, tagpage($tag);
-                       return htmllink($params{page}, $params{destpage},
-                               tagpage($tag),
-                               linktext => IkiWiki::pagetitle($1));
+                       add_link($params{page}, tagpage($tag));
+                       return taglink($params{page}, $params{destpage}, $tag,
+                               linktext => pagetitle($1));
                }
                else {
-                       my $tag=IkiWiki::linkpage($_);
+                       my $tag=linkpage($_);
                        $tags{$params{page}}{$tag}=1;
-                       push @{$links{$params{page}}}, tagpage($tag);
-                       return htmllink($params{page}, $params{destpage},
-                               tagpage($tag));
+                       add_link($params{page}, tagpage($tag));
+                       return taglink($params{page}, $params{destpage}, $tag);
                }
        }
        grep {
                $_ ne 'page' && $_ ne 'destpage' && $_ ne 'preview'
        } keys %params);
-} # }}}
+}
 
-sub pagetemplate (@) { #{{{
+sub pagetemplate (@) {
        my %params=@_;
        my $page=$params{page};
        my $destpage=$params{destpage};
@@ -88,8 +112,7 @@ sub pagetemplate (@) { #{{{
 
        $template->param(tags => [
                map { 
-                       link => htmllink($page, $destpage, tagpage($_),
-                                       rel => "tag")
+                       link => taglink($page, $destpage, $_, rel => "tag")
                }, sort keys %{$tags{$page}}
        ]) if exists $tags{$page} && %{$tags{$page}} && $template->query(name => "tags");
 
@@ -100,6 +123,14 @@ sub pagetemplate (@) { #{{{
                                sort keys %{$tags{$page}}]);
                }
        }
-} # }}}
+}
+
+package IkiWiki::PageSpec;
+
+sub match_tagged ($$;@) {
+       my $page = shift;
+       my $glob = shift;
+       return match_link($page, IkiWiki::Plugin::tag::tagpage($glob));
+}
 
 1
index a6e34fcc9935546fca9cf0bbf136abee3887af42..b6097bb49d26133a54dc2fa27c3fc98e59d657bb 100644 (file)
@@ -4,19 +4,29 @@ package IkiWiki::Plugin::template;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Template;
 use Encode;
 
-sub import { #{{{
-       hook(type => "preprocess", id => "template", call => \&preprocess);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "template", call => \&getsetup);
+       hook(type => "preprocess", id => "template", call => \&preprocess,
+               scan => 1);
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
 
        if (! exists $params{id}) {
-               return "[[template ".gettext("missing id parameter")."]]";
+               error gettext("missing id parameter")
        }
 
        my $template_page="templates/$params{id}";
@@ -24,7 +34,7 @@ sub preprocess (@) { #{{{
 
        my $template_file=$pagesources{$template_page};
        return sprintf(gettext("template %s not found"),
-               htmllink($params{page}, $params{destpage}, $template_page))
+               htmllink($params{page}, $params{destpage}, "/".$template_page))
                        unless defined $template_file;
 
        my $template;
@@ -42,9 +52,11 @@ sub preprocess (@) { #{{{
                );
        };
        if ($@) {
-               return "[[template ".gettext("failed to process:")." $@]]";
+               error gettext("failed to process:")." $@"
        }
 
+       $params{basename}=IkiWiki::basename($params{page});
+
        foreach my $param (keys %params) {
                if ($template->query(name => $param)) {
                        $template->param($param =>
@@ -57,9 +69,13 @@ sub preprocess (@) { #{{{
                }
        }
 
+       # This needs to run even in scan mode, in order to process
+       # links and other metadata includes via the template.
+       my $scan=! defined wantarray;
+
        return IkiWiki::preprocess($params{page}, $params{destpage},
                IkiWiki::filter($params{page}, $params{destpage},
-               $template->output));
-} # }}}
+               $template->output), $scan);
+}
 
 1
index f9ec90d8791f8b5e6aa422ceb527fe272bfea9df..440fca33be02cc6cf91ff9072c725d936571b334 100644 (file)
@@ -3,18 +3,27 @@ package IkiWiki::Plugin::testpagespec;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "testpagespec", call => \&getsetup);
        hook(type => "preprocess", id => "testpagespec", call => \&preprocess);
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub preprocess (@) {
        my %params=@_;
        
        foreach my $param (qw{match pagespec}) {
                if (! exists $params{$param}) {
-                       return "[[testpagespec $param parameter is required]]";
+                       error sprintf(gettext("%s parameter is required"), $param);
                }
        }
 
@@ -28,6 +37,6 @@ sub preprocess (@) { #{{{
        else {
                return "no match: $ret";
        }
-} # }}}
+}
 
 1
index 8c3e88c6974a8f2d5aa00fc119ba1f8941f4c943..dba5372b5fee98c33cf044e3b28024c53033649a 100644 (file)
@@ -8,13 +8,53 @@ use strict;
 use Digest::MD5 qw(md5_hex);
 use File::Temp qw(tempdir);
 use HTML::Entities;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
-       hook(type => "preprocess", id => "teximg", call => \&preprocess);
-} #}}}
+my $default_prefix = <<EOPREFIX;
+\\documentclass{article}
+\\usepackage{amsmath}
+\\usepackage{amsfonts}
+\\usepackage{amssymb}
+\\pagestyle{empty}
+\\begin{document}
+EOPREFIX
+
+my $default_postfix = '\\end{document}';
 
-sub preprocess (@) { #{{{
+sub import {
+       hook(type => "getsetup", id => "teximg", call => \&getsetup);
+       hook(type => "preprocess", id => "teximg", call => \&preprocess);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+               teximg_dvipng => {
+                       type => "boolean",
+                       description => "Should teximg use dvipng to render, or dvips and convert?",
+                       safe => 0,
+                       rebuild => undef,
+               },
+               teximg_prefix => {
+                       type => "string",
+                       example => $default_prefix,
+                       description => "LaTeX prefix for teximg plugin",
+                       safe => 0, # Not sure how secure LaTeX is...
+                       rebuild => 1,
+               },
+               teximg_postfix => {
+                       type => "string",
+                       example => $default_postfix,
+                       description => "LaTeX postfix for teximg plugin",
+                       safe => 0, # Not sure how secure LaTeX is...
+                       rebuild => 1,
+               },
+}
+
+sub preprocess (@) {
        my %params = @_;
        
        my $height = $params{height};
@@ -27,18 +67,18 @@ sub preprocess (@) { #{{{
        
        my $code = $params{code};
        if (! defined $code && ! length $code) {
-               return "[[teximg ".gettext("missing tex code"). "]]";
+               error gettext("missing tex code");
        }
 
        if (check($code)) {
                return create($code, check_height($height), \%params);
        }
        else {
-               return "[[teximg ".gettext("code includes disallowed latex commands"). "]]";
+               error gettext("code includes disallowed latex commands")
        }
-} #}}}
+}
 
-sub check_height ($) { #{{{
+sub check_height ($) {
        # Since latex doesn't support unlimited scaling this function
        # returns the closest supported size.
        my $height =shift;
@@ -55,9 +95,9 @@ sub check_height ($) { #{{{
                }
        }
        return $ret;
-} #}}}
+}
 
-sub create ($$$) { #{{{
+sub create ($$$) {
        # This function calls the image generating function and returns
        # the <img .. /> for the generated image.
        my $code = shift;
@@ -85,36 +125,45 @@ sub create ($$$) { #{{{
                        .qq{" class="teximg" />};
        }
        else {
-               return qq{[[teximg <a href="$logurl">}.gettext("failed to generate image from code")."</a>]]";
+               error qq{<a href="$logurl">}.gettext("failed to generate image from code")."</a>";
        }
-} #}}}
+}
 
-sub gen_image ($$$$) { #{{{
+sub gen_image ($$$$) {
        # Actually creates the image.
        my $code = shift;
        my $height = shift;
        my $digest = shift;
        my $imagedir = shift;
 
-       #TODO This should move into the setup file.
-       my $tex = '\documentclass['.$height.'pt]{scrartcl}';
-       $tex .= '\usepackage[version=3]{mhchem}';
-       $tex .= '\usepackage{amsmath}';
-       $tex .= '\usepackage{amsfonts}';
-       $tex .= '\usepackage{amssymb}';
-       $tex .= '\pagestyle{empty}';
-       $tex .= '\begin{document}';
+       if (!defined $config{teximg_prefix}) {
+               $config{teximg_prefix} = $default_prefix;
+       }
+       if (!defined $config{teximg_postfix}) {
+               $config{teximg_postfix} = $default_postfix;
+       }
+       if (!defined $config{teximg_dvipng}) {
+               $config{teximg_dvipng} = length `which dvipng 2>/dev/null`;
+       }
+       
+       my $tex = $config{teximg_prefix};
        $tex .= '$$'.$code.'$$';
-       $tex .= '\end{document}';
+       $tex .= $config{teximg_postfix};
+       $tex =~ s!\\documentclass{article}!\\documentclass[${height}pt]{article}!g;
+       $tex =~ s!\\documentclass{scrartcl}!\\documentclass[${height}pt]{scrartcl}!g;
 
        my $tmp = eval { create_tmp_dir($digest) };
        if (! $@ &&
            writefile("$digest.tex", $tmp, $tex) &&
            system("cd $tmp; latex --interaction=nonstopmode $tmp/$digest.tex > /dev/null") == 0 &&
-           system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
            # ensure destination directory exists
            writefile("$imagedir/$digest.png", $config{destdir}, "") &&
-           system("convert -density 120  -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0) {
+           (($config{teximg_dvipng} &&
+               system("dvipng -D 120 -bg Transparent -T tight -o $config{destdir}/$imagedir/$digest.png $tmp/$digest.dvi > $tmp/$digest.log") == 0
+           ) || (!$config{teximg_dvipng} &&
+               system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
+               system("convert -density 120  -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0
+           ))) {
                return 1;
        }
        else {
@@ -131,18 +180,18 @@ sub gen_image ($$$$) { #{{{
 
                return 0;
        }
-} #}}}
+}
 
-sub create_tmp_dir ($) { #{{{
+sub create_tmp_dir ($) {
        # Create a temp directory, it will be removed when ikiwiki exits.
        my $base = shift;
 
        my $template = $base.".XXXXXXXXXX";
        my $tmpdir = tempdir($template, TMPDIR => 1, CLEANUP => 1);
        return $tmpdir;
-} #}}}
+}
 
-sub check ($) { #{{{
+sub check ($) {
        # Check if the code is ok
        my $code = shift;
 
@@ -170,6 +219,6 @@ sub check ($) { #{{{
                }
        }
        return 1;
-} #}}}
+}
 
 1
index 208f295d2b16aeb37c4434253c46d48d66057222..8cc5a7951d3575e67b221ca312993fff158bae20 100644 (file)
@@ -6,20 +6,29 @@ package IkiWiki::Plugin::textile;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use Encode;
 
-sub import { #{{{
-       hook(type => "htmlize", id => "txtl", call => \&htmlize);
-} # }}}
+sub import {
+       hook(type => "getsetup", id => "textile", call => \&getsetup);
+       hook(type => "htmlize", id => "txtl", call => \&htmlize, longname => "Textile");
+}
 
-sub htmlize (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
+sub htmlize (@) {
        my %params=@_;
        my $content = decode_utf8(encode_utf8($params{content}));
 
        eval q{use Text::Textile};
        return $content if $@;
        return Text::Textile::textile($content);
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/tla.pm b/IkiWiki/Plugin/tla.pm
new file mode 100644 (file)
index 0000000..f4b20a6
--- /dev/null
@@ -0,0 +1,286 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::tla;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import {
+       hook(type => "checkconfig", id => "tla", call => \&checkconfig);
+       hook(type => "getsetup", id => "tla", call => \&getsetup);
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+       hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
+       hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
+       hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
+       hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
+       hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
+       hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
+       hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+       hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+}
+
+sub checkconfig () {
+       if (defined $config{tla_wrapper} && length $config{tla_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{tla_wrapper},
+                       wrappermode => (defined $config{tla_wrappermode} ? $config{tla_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # rcs plugin
+                       rebuild => undef,
+               },
+               tla_wrapper => {
+                       type => "string",
+                       #example => "", # TODO example
+                       description => "tla post-commit hook to generate",
+                       safe => 0, # file
+                       rebuild => 0,
+               },
+               tla_wrappermode => {
+                       type => "string",
+                       example => '06755',
+                       description => "mode for tla_wrapper (can safely be made suid)",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               historyurl => {
+                       type => "string",
+                       #example => "", # TODO example
+                       description => "url to show file history ([[file]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+               diffurl => {
+                       type => "string",
+                       #example => "", # TODO example
+                       description => "url to show a diff ([[file]] and [[rev]] substituted)",
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub quiet_system (@) {
+       # See Debian bug #385939.
+       open (SAVEOUT, ">&STDOUT");
+       close STDOUT;
+       open (STDOUT, ">/dev/null");
+       my $ret=system(@_);
+       close STDOUT;
+       open (STDOUT, ">&SAVEOUT");
+       close SAVEOUT;
+       return $ret;
+}
+
+sub rcs_update () {
+       if (-d "$config{srcdir}/{arch}") {
+               if (quiet_system("tla", "replay", "-d", $config{srcdir}) != 0) {
+                       warn("tla replay failed\n");
+               }
+       }
+}
+
+sub rcs_prepedit ($) {
+       my $file=shift;
+
+       if (-d "$config{srcdir}/{arch}") {
+               # For Arch, return the tree-id of archive when
+               # editing begins.
+               my $rev=`tla tree-id $config{srcdir}`;
+               return defined $rev ? $rev : "";
+       }
+}
+
+sub rcs_commit ($$$;$$) {
+       my $file=shift;
+       my $message=shift;
+       my $rcstoken=shift;
+       my $user=shift;
+       my $ipaddr=shift;
+
+       if (defined $user) {
+               $message="web commit by $user".(length $message ? ": $message" : "");
+       }
+       elsif (defined $ipaddr) {
+               $message="web commit from $ipaddr".(length $message ? ": $message" : "");
+       }
+
+       if (-d "$config{srcdir}/{arch}") {
+               # Check to see if the page has been changed by someone
+               # else since rcs_prepedit was called.
+               my ($oldrev)=$rcstoken=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
+               my $rev=`tla tree-id $config{srcdir}`;
+               if (defined $rev && defined $oldrev && $rev ne $oldrev) {
+                       # Merge their changes into the file that we've
+                       # changed.
+                       if (quiet_system("tla", "update", "-d",
+                                  "$config{srcdir}") != 0) {
+                               warn("tla update failed\n");
+                       }
+               }
+
+               if (quiet_system("tla", "commit",
+                          "-L".IkiWiki::possibly_foolish_untaint($message),
+                          '-d', $config{srcdir}) != 0) {
+                       my $conflict=readfile("$config{srcdir}/$file");
+                       if (system("tla", "undo", "-n", "--quiet", "-d", "$config{srcdir}") != 0) {
+                               warn("tla undo failed\n");
+                       }
+                       return $conflict;
+               }
+       }
+       return undef # success
+}
+
+sub rcs_commit_staged ($$$) {
+       # Commits all staged changes. Changes can be staged using rcs_add,
+       # rcs_remove, and rcs_rename.
+       my ($message, $user, $ipaddr)=@_;
+       
+       error("rcs_commit_staged not implemented for tla"); # TODO
+}
+
+sub rcs_add ($) {
+       my $file=shift;
+
+       if (-d "$config{srcdir}/{arch}") {
+               if (quiet_system("tla", "add", "$config{srcdir}/$file") != 0) {
+                       warn("tla add failed\n");
+               }
+       }
+}
+
+sub rcs_remove ($) {
+       my $file = shift;
+
+       error("rcs_remove not implemented for tla"); # TODO
+}
+
+sub rcs_rename ($$) { # {{{a
+       my ($src, $dest) = @_;
+
+       error("rcs_rename not implemented for tla"); # TODO
+}
+
+sub rcs_recentchanges ($) {
+       my $num=shift;
+       my @ret;
+
+       return unless -d "$config{srcdir}/{arch}";
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+       eval q{use Mail::Header};
+       error($@) if $@;
+
+       my $logs = `tla logs -d $config{srcdir}`;
+       my @changesets = reverse split(/\n/, $logs);
+
+       for (my $i=0; $i<$num && $i<$#changesets; $i++) {
+               my ($change)=$changesets[$i]=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
+
+               open(LOG, "tla cat-log -d $config{srcdir} $change|");
+               my $head = Mail::Header->new(\*LOG);
+               close(LOG);
+
+               my $rev = $head->get("Revision");
+               my $summ = $head->get("Summary");
+               my $newfiles = $head->get("New-files");
+               my $modfiles = $head->get("Modified-files");
+               my $remfiles = $head->get("Removed-files");
+               my $user = $head->get("Creator");
+
+               my @paths = grep { !/^(.*\/)?\.arch-ids\/.*\.id$/ }
+                       split(/ /, "$newfiles $modfiles .arch-ids/fake.id");
+
+               my $sdate = $head->get("Standard-date");
+               my $when = str2time($sdate, 'UTC');
+
+               my $committype = "web";
+               if (defined $summ && $summ =~ /$config{web_commit_regexp}/) {
+                       $user = defined $2 ? "$2" : "$3";
+                       $summ = $4;
+               }
+               else {
+                       $committype="tla";
+               }
+
+               my @message;
+               push @message, { line => $summ };
+
+               my @pages;
+
+               foreach my $file (@paths) {
+                       my $diffurl=defined $config{diffurl} ? $config{diffurl} : "";
+                       $diffurl=~s/\[\[file\]\]/$file/g;
+                       $diffurl=~s/\[\[rev\]\]/$change/g;
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       } if length $file;
+               }
+               push @ret, {
+                       rev => $change,
+                       user => $user,
+                       committype => $committype,
+                       when => $when,
+                       message => [@message],
+                       pages => [@pages],
+               } if @pages;
+
+               last if $i == $num;
+       }
+
+       return @ret;
+}
+
+sub rcs_diff ($) {
+       my $rev=shift;
+       my $logs = `tla logs -d $config{srcdir}`;
+       my @changesets = reverse split(/\n/, $logs);
+       my $i;
+
+       for($i=0;$i<$#changesets;$i++) {
+               last if $changesets[$i] eq $rev;
+       }
+
+       my $revminusone = $changesets[$i+1];
+       return `tla diff -d $config{srcdir} $revminusone`;
+}
+
+sub rcs_getctime ($) {
+       my $file=shift;
+       eval q{use Date::Parse};
+       error($@) if $@;
+       eval q{use Mail::Header};
+       error($@) if $@;
+
+       my $logs = `tla logs -d $config{srcdir}`;
+       my @changesets = reverse split(/\n/, $logs);
+       my $sdate;
+
+       for (my $i=0; $i<$#changesets; $i++) {
+               my $change = $changesets[$i];
+
+               open(LOG, "tla cat-log -d $config{srcdir} $change|");
+               my $head = Mail::Header->new(\*LOG);
+               close(LOG);
+
+               $sdate = $head->get("Standard-date");
+               my $newfiles = $head->get("New-files");
+
+               my ($lastcreation) = grep {/^$file$/} split(/ /, "$newfiles");
+               last if defined($lastcreation);
+       }
+
+       my $date=str2time($sdate, 'UTC');
+       debug("found ctime ".localtime($date)." for $file");
+       return $date;
+}
+
+1
index 639cae4a90e88d437824f51689824fa1b30e95ca..a585564e74761045ee8e178b6dd8262ede94ee97 100644 (file)
@@ -4,17 +4,26 @@ package IkiWiki::Plugin::toc;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Parser;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "toc", call => \&getsetup);
        hook(type => "preprocess", id => "toc", call => \&preprocess);
        hook(type => "format", id => "toc", call => \&format);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
 my %tocpages;
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
 
        if ($params{page} eq $params{destpage}) {
@@ -31,9 +40,9 @@ sub preprocess (@) { #{{{
                # right.
                return "";
        }
-} # }}}
+}
 
-sub format (@) { #{{{
+sub format (@) {
        my %params=@_;
        my $content=$params{content};
        
index 284eb8249df031e77f2e1ff1796d19624bbae1cf..aae8cdf84beeff62d54197db0e5f1e2733fe5810 100644 (file)
@@ -3,67 +3,27 @@ package IkiWiki::Plugin::toggle;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-# Here's the javascript that makes this possible. A key feature is the use
-# of css to hide toggleables, to avoid any flashing on page load. The css
-# is only emitted after the javascript tests that it's going to be able to
-# show the toggleables.
-our $javascript=<<'EOF';
-<script type="text/javascript">
-<!--
-if (document.getElementById && document.getElementsByTagName && document.createTextNode) {
-       document.write('<style type="text/css">div.toggleable { display: none; }</style>');
-       window.onload = inittoggle;
-}
-
-function inittoggle() {
-       var as = getElementsByClass('toggle');
-       for (var i = 0; i < as.length; i++) {
-               var id = as[i].href.match(/#(\w.+)/)[1];
-               if (document.getElementById(id).className == "toggleable")
-                       document.getElementById(id).style.display="none";
-               as[i].onclick = function() {
-                       toggle(this);
-                       return false;
-               }
-       }
-}
-
-function toggle(s) {
-       var id = s.href.match(/#(\w.+)/)[1];
-       style = document.getElementById(id).style;
-       if (style.display == "none")
-               style.display = "block";
-       else
-               style.display = "none";
-}
-
-function getElementsByClass(class) {
-       var ret = new Array();
-       var pattern = new RegExp("(^|\\s)"+class+"(\\s|$)");
-       var els = document.getElementsByTagName('*');
-       for (i = 0, j = 0; i < els.length; i++) {
-               if ( pattern.test(els[i].className) ) {
-                       ret[j] = els[i];
-                       j++;
-               }
-       }
-       return ret;
-}
-//-->
-</script>
-EOF
-
-sub import { #{{{
+sub import {
+       add_underlay("javascript");
+       hook(type => "getsetup", id => "toggle", call => \&getsetup);
        hook(type => "preprocess", id => "toggle",
                call => \&preprocess_toggle);
        hook(type => "preprocess", id => "toggleable",
                call => \&preprocess_toggleable);
        hook(type => "format", id => "toggle", call => \&format);
-} # }}}
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
 
-sub genid ($$) { #{{{
+sub genid ($$) {
        my $page=shift;
        my $id=shift;
 
@@ -75,16 +35,16 @@ sub genid ($$) { #{{{
                $id="id$id";
        }
        return $id;
-} #}}}
+}
 
-sub preprocess_toggle (@) { #{{{
+sub preprocess_toggle (@) {
        my %params=(id => "default", text => "more", @_);
 
        my $id=genid($params{page}, $params{id});
        return "<a class=\"toggle\" href=\"#$id\">$params{text}</a>";
-} # }}}
+}
 
-sub preprocess_toggleable (@) { #{{{
+sub preprocess_toggleable (@) {
        my %params=(id => "default", text => "", open => "no", @_);
 
        # Preprocess the text to expand any preprocessor directives
@@ -101,19 +61,29 @@ sub preprocess_toggleable (@) { #{{{
        my ($indent)=$params{text}=~/( +)$/;
        $indent="" unless defined $indent;
        return "<div class=\"$class\" id=\"$id\"></div>\n\n$params{text}\n$indent<div class=\"toggleableend\"></div>";
-} # }}}
+}
 
-sub format (@) { #{{{
+sub format (@) {
         my %params=@_;
 
-       if ($params{content}=~s!(<div class="toggleable(?:-open)?" id="[^"]+">)</div>!$1!g) {
+       if ($params{content}=~s!(<div class="toggleable(?:-open)?" id="[^"]+">\s*)</div>!$1!g) {
                $params{content}=~s/<div class="toggleableend">//g;
-               if (! ($params{content}=~s!^<body>!<body>$javascript!m)) {
+               if (! ($params{content}=~s!^(<body>)!$1.include_javascript($params{page})!em)) {
                        # no </body> tag, probably in preview mode
-                       $params{content}=$javascript.$params{content};
+                       $params{content}=include_javascript($params{page}, 1).$params{content};
                }
        }
        return $params{content};
-} # }}}
+}
+
+sub include_javascript ($;$) {
+       my $page=shift;
+       my $absolute=shift;
+       
+       return '<script src="'.urlto("ikiwiki.js", $page, $absolute).
+               '" type="text/javascript" charset="utf-8"></script>'."\n".
+               '<script src="'.urlto("toggle.js", $page, $absolute).
+               '" type="text/javascript" charset="utf-8"></script>';
+}
 
 1
index 3aad5fa07a6aa3a349fab19ba7b182fe667f60ca..8599bdc8ec881429472ef19f760113f27d0a678f 100644 (file)
@@ -8,13 +8,14 @@ package IkiWiki::Plugin::txt;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 use HTML::Entities;
 
 my $findurl=0;
 
 sub import {
-       hook(type => "filter",  id => "txt", call => \&filter);
+       hook(type => "getsetup", id => "txt", call => \&getsetup);
+       hook(type => "filter", id => "txt", call => \&filter);
        hook(type => "htmlize", id => "txt", call => \&htmlize);
 
        eval q{use URI::Find};
@@ -23,6 +24,14 @@ sub import {
        }
 }
 
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+}
+
 # We use filter to convert raw text to HTML
 # (htmlize is called after other plugins insert HTML)
 sub filter (@) {
@@ -30,7 +39,7 @@ sub filter (@) {
        my $content = $params{content};
 
        if (defined $pagesources{$params{page}} && $pagesources{$params{page}} =~ /\.txt$/) {
-               encode_entities($content);
+               encode_entities($content, "<>&");
                if ($findurl) {
                        my $finder = URI::Find->new(sub {
                                my ($uri, $orig_uri) = @_;
index fe69968981029f07e0a60c2903bfb9e02fe6a4a6..f62be82bbea849090876053a4d81ee6c558260c6 100644 (file)
@@ -4,28 +4,48 @@ package IkiWiki::Plugin::typography;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
        hook(type => "getopt", id => "typography", call => \&getopt);
+       hook(type => "getsetup", id => "typography", call => \&getsetup);
        IkiWiki::hook(type => "sanitize", id => "typography", call => \&sanitize);
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
        eval q{use Getopt::Long};
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
        GetOptions("typographyattributes=s" => \$config{typographyattributes});
-} #}}}
+}
 
-sub sanitize (@) { #{{{
+sub getsetup () {
+       eval q{use Text::Typography};
+       error($@) if $@;
+
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               typographyattributes => {
+                       type => "string",
+                       example => "3",
+                       description => "Text::Typography attributes value",
+                       advanced => 1,
+                       safe => 1,
+                       rebuild => 1,
+               },
+}
+
+sub sanitize (@) {
        my %params=@_;
 
        eval q{use Text::Typography};
-       error($@) if $@;
+       return $params{content} if $@;
 
        my $attributes=defined $config{typographyattributes} ? $config{typographyattributes} : '3';
        return Text::Typography::typography($params{content}, $attributes);
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/underlay.pm b/IkiWiki/Plugin/underlay.pm
new file mode 100644 (file)
index 0000000..380d418
--- /dev/null
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::underlay;
+# Copyright © 2008 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+# Licensed under the GNU GPL, version 2, or any later version published by the
+# Free Software Foundation
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getsetup", id => "underlay",  call => \&getsetup);
+       hook(type => "checkconfig", id => "underlay", call => \&checkconfig);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0,
+                       rebuild => undef,
+               },
+               add_underlays => {
+                       type => "string",
+                       default => [],
+                       description => "extra underlay directories to add",
+                       advanced => 1,
+                       safe => 0,
+                       rebuild => 1,
+               },
+}
+
+sub checkconfig () {
+       return unless exists $config{add_underlays};
+
+       foreach my $dir (@{$config{add_underlays}}) {
+               add_underlay($dir);
+       }
+}
+
+1;
index f96d2df06ce345d9939c356637e6e6d0e2d06e8b..587cd55fa8f608fc2309d23eaa91ad1e32539c62 100644 (file)
@@ -4,14 +4,23 @@ package IkiWiki::Plugin::version;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "version", call => \&getsetup);
        hook(type => "needsbuild", id => "version", call => \&needsbuild);
        hook(type => "preprocess", id => "version", call => \&preprocess);
-} # }}}
+}
 
-sub needsbuild (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+}
+
+sub needsbuild (@) {
        my $needsbuild=shift;
        foreach my $page (keys %pagestate) {
                if (exists $pagestate{$page}{version}{shown}) {
@@ -27,11 +36,11 @@ sub needsbuild (@) { #{{{
                        }
                }
        }
-} # }}}
+}
 
-sub preprocess (@) { #{{{
+sub preprocess (@) {
        my %params=@_;
        $pagestate{$params{destpage}}{version}{shown}=$IkiWiki::version;
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/websetup.pm b/IkiWiki/Plugin/websetup.pm
new file mode 100644 (file)
index 0000000..9edd22d
--- /dev/null
@@ -0,0 +1,475 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::websetup;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+
+sub import {
+       hook(type => "getsetup", id => "websetup", call => \&getsetup);
+       hook(type => "checkconfig", id => "websetup", call => \&checkconfig);
+       hook(type => "sessioncgi", id => "websetup", call => \&sessioncgi);
+       hook(type => "formbuilder_setup", id => "websetup", 
+            call => \&formbuilder_setup);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 0,
+               },
+               websetup_force_plugins => {
+                       type => "string",
+                       example => [],
+                       description => "list of plugins that cannot be enabled/disabled via the web interface",
+                       safe => 0,
+                       rebuild => 0,
+               },
+               websetup_show_unsafe => {
+                       type => "boolean",
+                       example => 1,
+                       description => "show unsafe settings, read-only, in web interface?",
+                       safe => 0,
+                       rebuild => 0,
+               },
+}
+
+sub checkconfig () {
+       if (! exists $config{websetup_show_unsafe}) {
+               $config{websetup_show_unsafe}=1;
+       }
+}
+
+sub formatexample ($$) {
+       my $example=shift;
+       my $value=shift;
+
+       if (defined $value && length $value) {
+               return "";
+       }
+       elsif (defined $example && ! ref $example && length $example) {
+               return "<br/ ><small>Example: <tt>$example</tt></small>";
+       }
+       else {
+               return "";
+       }
+}
+
+sub showfields ($$$@) {
+       my $form=shift;
+       my $plugin=shift;
+       my $enabled=shift;
+
+       my @show;
+       my %plugininfo;
+       while (@_) {
+               my $key=shift;
+               my %info=%{shift()};
+
+               # skip internal settings
+               next if defined $info{type} && $info{type} eq "internal";
+               # XXX hashes not handled yet
+               next if ref $config{$key} && ref $config{$key} eq 'HASH' || ref $info{example} eq 'HASH';
+               # maybe skip unsafe settings
+               next if ! $info{safe} && ! ($config{websetup_show_unsafe} && $config{websetup_advanced});
+               # maybe skip advanced settings
+               next if $info{advanced} && ! $config{websetup_advanced};
+               # these are handled specially, so don't show
+               next if $key eq 'add_plugins' || $key eq 'disable_plugins';
+
+               if ($key eq 'plugin') {
+                       %plugininfo=%info;
+                       next;
+               }
+               
+               push @show, $key, \%info;
+       }
+
+       my $section=defined $plugin ? $plugin." ".gettext("plugin") : "main";
+       my %enabledfields;
+       my $shownfields=0;
+       
+       my $plugin_forced=defined $plugin && (! $plugininfo{safe} ||
+               (exists $config{websetup_force_plugins} && grep { $_ eq $plugin } @{$config{websetup_force_plugins}}));
+       if ($plugin_forced && ! $enabled) {
+               # plugin is forced disabled, so skip its settings
+               @show=();
+       }
+
+       # show plugin toggle
+       if (defined $plugin && (! $plugin_forced || $config{websetup_advanced})) {
+               my $name="enable.$plugin";
+               $form->field(
+                       name => $name,
+                       label => "",
+                       type => "checkbox",
+                       fieldset => $section,
+                       options => [ [ 1 => sprintf(gettext("enable %s?"), $plugin) ]]
+               );
+               if (! $form->submitted) {
+                       $form->field(name => $name, value => $enabled);
+               }
+               if ($plugin_forced) {
+                       $form->field(name => $name, disabled => 1);
+               }
+               else {
+                       $enabledfields{$name}=[$name, \%plugininfo];
+               }
+       }
+
+       # show plugin settings
+       while (@show) {
+               my $key=shift @show;
+               my %info=%{shift @show};
+
+               my $description=$info{description};
+               if (exists $info{link} && length $info{link}) {
+                       if ($info{link} =~ /^\w+:\/\//) {
+                               $description="<a href=\"$info{link}\">$description</a>";
+                       }
+                       else {
+                               $description=htmllink("", "", $info{link}, noimageinline => 1, linktext => $description);
+                       }
+               }
+
+               # multiple plugins can have the same field
+               my $name=defined $plugin ? $plugin.".".$key : $section.".".$key;
+
+               my $value=$config{$key};
+
+               if ($info{safe} && (ref $value eq 'ARRAY' || ref $info{example} eq 'ARRAY')) {
+                       $value=[(ref $value eq 'ARRAY' ? @{$value} : ""), "", ""]; # blank items for expansion
+               }
+
+               if ($info{type} eq "string") {
+                       $form->field(
+                               name => $name,
+                               label => $description,
+                               comment => formatexample($info{example}, $value),
+                               type => "text",
+                               value => $value,
+                               size => 60,
+                               fieldset => $section,
+                       );
+               }
+               elsif ($info{type} eq "pagespec") {
+                       $form->field(
+                               name => $name,
+                               label => $description,
+                               comment => formatexample($info{example}, $value),
+                               type => "text",
+                               value => $value,
+                               size => 60,
+                               validate => \&IkiWiki::pagespec_valid,
+                               fieldset => $section,
+                       );
+               }
+               elsif ($info{type} eq "integer") {
+                       $form->field(
+                               name => $name,
+                               label => $description,
+                               comment => formatexample($info{example}, $value),
+                               type => "text",
+                               value => $value,
+                               size => 5,
+                               validate => '/^[0-9]+$/',
+                               fieldset => $section,
+                       );
+               }
+               elsif ($info{type} eq "boolean") {
+                       $form->field(
+                               name => $name,
+                               label => "",
+                               type => "checkbox",
+                               options => [ [ 1 => $description ] ],
+                               fieldset => $section,
+                       );
+                       if (! $form->submitted) {
+                               $form->field(name => $name, value => $value);
+                       }
+               }
+               
+               if (! $info{safe}) {
+                       $form->field(name => $name, disabled => 1);
+               }
+               else {
+                       $enabledfields{$name}=[$key, \%info];
+               }
+               $shownfields++;
+       }
+       
+       # if no fields were shown for the plugin, drop it into the
+       # plugins fieldset
+       if (defined $plugin && (! $plugin_forced || $config{websetup_advanced}) &&
+           ! $shownfields) {
+               $form->field(name => "enable.$plugin", fieldset => "plugins");
+       }
+
+       return %enabledfields;
+}
+
+sub enable_plugin ($) {
+       my $plugin=shift;
+
+       $config{disable_plugins}=[grep { $_ ne $plugin } @{$config{disable_plugins}}];
+       push @{$config{add_plugins}}, $plugin;
+}
+
+sub disable_plugin ($) {
+       my $plugin=shift;
+
+       if (grep { $_ eq $plugin } @{$config{add_plugins}}) {
+               $config{add_plugins}=[grep { $_ ne $plugin } @{$config{add_plugins}}];
+       }
+       else {
+               push @{$config{disable_plugins}}, $plugin;
+       }
+}
+
+sub showform ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       if (! defined $session->param("name") || 
+           ! IkiWiki::is_admin($session->param("name"))) {
+               error(gettext("you are not logged in as an admin"));
+       }
+
+       if (! exists $config{setupfile}) {
+               error(gettext("setup file for this wiki is not known"));
+       }
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+
+       my $form = CGI::FormBuilder->new(
+               title => "setup",
+               name => "setup",
+               header => 0,
+               charset => "utf-8",
+               method => 'POST',
+               javascript => 0,
+               reset => 1,
+               params => $cgi,
+               fieldsets => [
+                       [main => gettext("main")], 
+                       [plugins => gettext("plugins")]
+               ],
+               action => $config{cgiurl},
+               template => {type => 'div'},
+               stylesheet => IkiWiki::baseurl()."style.css",
+       );
+       
+       $form->field(name => "do", type => "hidden", value => "setup",
+               force => 1);
+       $form->field(name => "rebuild_asked", type => "hidden");
+
+       if ($form->submitted eq 'Basic Mode') {
+               $form->field(name => "showadvanced", type => "hidden", 
+                       value => 0, force => 1);
+       }
+       elsif ($form->submitted eq 'Advanced Mode') {
+               $form->field(name => "showadvanced", type => "hidden", 
+                       value => 1, force => 1);
+       }
+       my $advancedtoggle;
+       if ($form->field("showadvanced")) {
+               $config{websetup_advanced}=1;
+               $advancedtoggle="Basic Mode";
+       }
+       else {
+               $config{websetup_advanced}=0;
+               $advancedtoggle="Advanced Mode";
+       }
+
+       my $buttons=["Save Setup", $advancedtoggle, "Cancel"];
+
+       IkiWiki::decode_form_utf8($form);
+       IkiWiki::run_hooks(formbuilder_setup => sub {
+               shift->(form => $form, cgi => $cgi, session => $session,
+                       buttons => $buttons);
+       });
+       IkiWiki::decode_form_utf8($form);
+
+       my %fields=showfields($form, undef, undef, IkiWiki::getsetup());
+       
+       # record all currently enabled plugins before all are loaded
+       my %enabled_plugins=%IkiWiki::loaded_plugins;
+
+       # per-plugin setup
+       require IkiWiki::Setup;
+       foreach my $pair (IkiWiki::Setup::getsetup()) {
+               my $plugin=$pair->[0];
+               my $setup=$pair->[1];
+
+               my %shown=showfields($form, $plugin, $enabled_plugins{$plugin}, @{$setup});
+               if (%shown) {
+                       $fields{$_}=$shown{$_} foreach keys %shown;
+               }
+       }
+       
+       if ($form->submitted eq "Cancel") {
+               IkiWiki::redirect($cgi, $config{url});
+               return;
+       }
+       elsif (($form->submitted eq 'Save Setup' || $form->submitted eq 'Rebuild Wiki') && $form->validate) {
+               # Push values from form into %config, avoiding unnecessary
+               # changes, and keeping track of which changes need a
+               # rebuild.
+               my %rebuild;
+               foreach my $field (keys %fields) {
+                       my %info=%{$fields{$field}->[1]};
+                       my $key=$fields{$field}->[0];
+                       my @value=$form->field($field);
+                       if (! @value) {
+                               @value=0;
+                       }
+               
+                       if (! $info{safe}) {
+                               error("unsafe field $key"); # should never happen
+                       }
+               
+                       if (exists $info{rebuild} &&
+                           ($info{rebuild} || ! defined $info{rebuild})) {
+                               $rebuild{$field}=$info{rebuild};
+                       }
+                                       
+                       if ($field=~/^enable\.(.*)/) {
+                               my $plugin=$1;
+                               $value[0]=0 if ! length $value[0];
+                               if ($value[0] != exists $enabled_plugins{$plugin}) {
+                                       if ($value[0]) {
+                                               enable_plugin($plugin);
+                                       }
+                                       else {
+                                               disable_plugin($plugin);
+
+                                       }
+                               }
+                               else {
+                                       delete $rebuild{$field};
+                               }
+                               next;
+                       }
+
+                       if (ref $config{$key} eq "ARRAY" || ref $info{example} eq "ARRAY") {
+                               @value=sort grep { length $_ } @value;
+                               my @oldvalue=sort grep { length $_ }
+                                       (defined $config{$key} ? @{$config{$key}} : ());
+                               if ((@oldvalue) == (@value)) {
+                                       delete $rebuild{$field};
+                               }
+                               else {
+                                       $config{$key}=\@value;
+                               }
+                       }
+                       elsif (ref $config{$key} || ref $info{example}) {
+                               error("complex field $key"); # should never happen
+                       }
+                       else {
+                               if (defined $config{$key} && $config{$key} eq $value[0]) {
+                                       delete $rebuild{$field};
+                               }
+                               elsif (! defined $config{$key} && ! length $value[0]) {
+                                       delete $rebuild{$field};
+                               }
+                               elsif ((! defined $config{$key} || ! $config{$key}) &&
+                                      ! $value[0] && $info{type} eq "boolean") {
+                                       delete $rebuild{$field};
+                               }
+                               else {
+                                       $config{$key}=$value[0];
+                               }
+                       }
+               }
+               
+               if (%rebuild && ! $form->field("rebuild_asked")) {
+                       my $required=0;
+                       foreach my $field ($form->field) {
+                               $required=1 if $rebuild{$field};
+                               next if exists $rebuild{$field};
+                               $form->field(name => $field, type => "hidden");
+                       }
+                       if ($required) {
+                               $form->text(gettext("The configuration changes shown below require a wiki rebuild to take effect."));
+                               $buttons=["Rebuild Wiki", "Cancel"];
+                       }
+                       else {
+                               $form->text(gettext("For the configuration changes shown below to fully take effect, you may need to rebuild the wiki."));
+                               $buttons=["Rebuild Wiki", "Save Setup", "Cancel"];
+                       }
+                       $form->field(name => "rebuild_asked", value => 1, force => 1);
+                       $form->reset(0); # doesn't really make sense here
+               }
+               else {
+                       my $oldsetup=readfile($config{setupfile});
+                       IkiWiki::Setup::dump($config{setupfile});
+
+                       IkiWiki::saveindex();
+                       IkiWiki::unlockwiki();
+
+                       # Print the top part of a standard misctemplate,
+                       # then show the rebuild or refresh.
+                       my $divider="xxx";
+                       my $html=IkiWiki::misctemplate("setup", $divider);
+                       IkiWiki::printheader($session);
+                       my ($head, $tail)=split($divider, $html, 2);
+                       print $head."<pre>\n";
+
+                       my @command;
+                       if ($form->submitted eq 'Rebuild Wiki') {
+                               @command=("ikiwiki", "-setup", $config{setupfile},
+                                        "-rebuild", "-v");
+                       }
+                       else {
+                               @command=("ikiwiki", "-setup", $config{setupfile},
+                                       "-refresh", "-wrappers", "-v");
+                       }
+
+                       close STDERR;
+                       open(STDERR, ">&STDOUT");
+                       my $ret=system(@command);
+                       print "\n<\/pre>";
+                       if ($ret != 0) {
+                               print '<p class="error">'.
+                                       sprintf(gettext("Error: %s exited nonzero (%s). Discarding setup changes."),
+                                               join(" ", @command), $ret).
+                                       '</p>';
+                               open(OUT, ">", $config{setupfile}) || error("$config{setupfile}: $!");
+                               print OUT $oldsetup;
+                               close OUT;
+                       }
+
+                       print $tail;
+                       exit 0;
+               }
+       }
+
+       IkiWiki::showform($form, $buttons, $session, $cgi);
+}
+
+sub sessioncgi ($$) {
+       my $cgi=shift;
+       my $session=shift;
+
+       if ($cgi->param("do") eq "setup") {
+               showform($cgi, $session);
+               exit;
+       }
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+
+       my $form=$params{form};
+       if ($form->title eq "preferences") {
+               push @{$params{buttons}}, "Wiki Setup";
+               if ($form->submitted && $form->submitted eq "Wiki Setup") {
+                       showform($params{cgi}, $params{session});
+                       exit;
+               }
+       }
+}
+
+1
index e1d346ae67d19962fc732759e540c17776d8f2a6..accb03bbef8317cad028d95fe36a68b466d9bd0f 100644 (file)
@@ -4,19 +4,29 @@ package IkiWiki::Plugin::wikitext;
 
 use warnings;
 use strict;
-use IkiWiki 2.00;
+use IkiWiki 3.00;
 
-sub import { #{{{
+sub import {
+       hook(type => "getsetup", id => "wiki", call => \&getsetup);
        hook(type => "htmlize", id => "wiki", call => \&htmlize);
-} # }}}
+}
 
-sub htmlize (@) { #{{{
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 0, # format plugin
+                       rebuild => undef,
+               },
+}
+
+
+sub htmlize (@) {
        my %params=@_;
        my $content = $params{content};
 
        eval q{use Text::WikiFormat};
        return $content if $@;
        return Text::WikiFormat::format($content, undef, { implicit_links => 0 });
-} # }}}
+}
 
 1
diff --git a/IkiWiki/Plugin/wmd.pm b/IkiWiki/Plugin/wmd.pm
new file mode 100644 (file)
index 0000000..9ddd237
--- /dev/null
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::wmd;
+
+use warnings;
+use strict;
+use IkiWiki 3.00;
+use POSIX;
+use Encode;
+
+sub import {
+       add_underlay("wmd");
+       hook(type => "getsetup", id => "wmd", call => \&getsetup);
+       hook(type => "formbuilder_setup", id => "wmd", call => \&formbuilder_setup);
+}
+
+sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+               },
+}
+
+sub formbuilder_setup (@) {
+       my %params=@_;
+       my $form=$params{form};
+
+       return if ! defined $form->field("do");
+       
+       return unless $form->field("do") eq "edit" ||
+                       $form->field("do") eq "create" ||
+                       $form->field("do") eq "comment";
+
+       $form->tmpl_param("wmd_preview", "<div class=\"wmd-preview\"></div>\n".
+               include_javascript(undef, 1));
+}
+
+sub include_javascript ($;$) {
+       my $page=shift;
+       my $absolute=shift;
+
+       my $wmdjs=urlto("wmd/wmd.js", $page, $absolute);
+       return <<"EOF"
+<script type="text/javascript">
+wmd_options = {
+       output: "Markdown"
+};
+</script>
+<script src="$wmdjs" type="text/javascript"></script>
+EOF
+}
+
+1
diff --git a/IkiWiki/Rcs/Stub.pm b/IkiWiki/Rcs/Stub.pm
deleted file mode 100644 (file)
index a460f29..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/usr/bin/perl
-# Stubs for no revision control.
-
-use warnings;
-use strict;
-use IkiWiki;
-
-package IkiWiki;
-
-sub rcs_update () {
-       # Update working directory to current version.
-       # (May be more complex for distributed RCS.)
-}
-
-sub rcs_prepedit ($) {
-       # Prepares to edit a file under revision control. Returns a token
-       # that must be passed into rcs_commit when the file is ready
-       # for committing.
-       # The file is relative to the srcdir.
-       return ""
-}
-
-sub rcs_commit ($$$;$$) {
-       # Tries to commit the page; returns undef on _success_ and
-       # a version of the page with the rcs's conflict markers on failure.
-       # The file is relative to the srcdir.
-       return undef # success
-}
-
-sub rcs_add ($) {
-       # Add a file. The filename is relative to the root of the srcdir.
-       # Note that this should not check the new file in, it should only
-       # prepare for it to be checked in when rcs_commit is called.
-}
-
-sub rcs_recentchanges ($) {
-       # Examine the RCS history and generate a list of recent changes.
-       # The data structure returned for each change is:
-       # {
-       #       rev => # the RCSs id for this commit
-       #       user => # name of user who made the change,
-       #       committype => # either "web" or the name of the rcs,
-       #       when => # time when the change was made,
-       #       message => [
-       #               { line => "commit message line" },
-       #               { line => "commit message line" },
-       #               # etc,
-       #       ],
-       #       pages => [
-       #               {
-       #                       page => # name of page changed,
-       #                       diffurl => # optional url to a diff showing 
-       #                                  # the changes,
-       #               },
-       #               # repeat for each page changed in this commit,
-       #       ],
-       # }
-}
-
-sub rcs_diff ($) {
-       # Optional, used to get diffs for recentchanges.
-       # The parameter is the rev from rcs_recentchanges.
-       # Should return a list of lines of the diff (including \n) in list
-       # context, and the whole diff in scalar context.
-}
-
-sub rcs_getctime ($) {
-       # Optional, used to get the page creation time from the RCS.
-       error gettext("getctime not implemented");
-}
-
-1
diff --git a/IkiWiki/Rcs/bzr.pm b/IkiWiki/Rcs/bzr.pm
deleted file mode 100644 (file)
index af311fa..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-use IkiWiki;
-use Encode;
-use open qw{:utf8 :std};
-
-package IkiWiki;
-
-sub bzr_log ($) { #{{{
-       my $out = shift;
-       my @infos = ();
-       my $key = undef;
-
-       while (<$out>) {
-               my $line = $_;
-               my ($value);
-               if ($line =~ /^message:/) {
-                       $key = "message";
-                       $infos[$#infos]{$key} = "";
-               }
-               elsif ($line =~ /^(modified|added|renamed|renamed and modified|removed):/) {
-                       $key = "files";
-                       unless (defined($infos[$#infos]{$key})) { $infos[$#infos]{$key} = ""; }
-               }
-               elsif (defined($key) and $line =~ /^  (.*)/) {
-                       $infos[$#infos]{$key} .= $1;
-               }
-               elsif ($line eq "------------------------------------------------------------\n") {
-                       $key = undef;
-                       push (@infos, {});
-               }
-               else {
-                       chomp $line;
-                               ($key, $value) = split /: +/, $line, 2;
-                       $infos[$#infos]{$key} = $value;
-               } 
-       }
-       close $out;
-
-       return @infos;
-} #}}}
-
-sub rcs_update () { #{{{
-       my @cmdline = ("bzr", "update", "--quiet", $config{srcdir});
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       return "";
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
-
-       if (defined $user) {
-               $user = possibly_foolish_untaint($user);
-       }
-       elsif (defined $ipaddr) {
-               $user = "Anonymous from ".possibly_foolish_untaint($ipaddr);
-       }
-       else {
-               $user = "Anonymous";
-       }
-
-       $message = possibly_foolish_untaint($message);
-       if (! length $message) {
-               $message = "no message given";
-       }
-
-       my @cmdline = ("bzr", "commit", "--quiet", "-m", $message, "--author", $user,
-                      $config{srcdir}."/".$file);
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-
-       return undef; # success
-} #}}}
-
-sub rcs_add ($) { # {{{
-       my ($file) = @_;
-
-       my @cmdline = ("bzr", "add", "--quiet", "$config{srcdir}/$file");
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-} #}}}
-
-sub rcs_recentchanges ($) { #{{{
-       my ($num) = @_;
-
-       my @cmdline = ("bzr", "log", "-v", "--show-ids", "--limit", $num, 
-                          $config{srcdir});
-       open (my $out, "@cmdline |");
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-
-       my @ret;
-       foreach my $info (bzr_log($out)) {
-               my @pages = ();
-               my @message = ();
-        
-               foreach my $msgline (split(/\n/, $info->{message})) {
-                       push @message, { line => $msgline };
-               }
-
-               foreach my $file (split(/\n/, $info->{files})) {
-                       my ($filename, $fileid) = split(/[ \t]+/, $file);
-                       my $diffurl = $config{'diffurl'};
-                       $diffurl =~ s/\[\[file\]\]/$filename/go;
-                       $diffurl =~ s/\[\[file-id\]\]/$fileid/go;
-                       $diffurl =~ s/\[\[r2\]\]/$info->{revno}/go;
-
-                       push @pages, {
-                               page => pagename($filename),
-                               diffurl => $diffurl,
-                       };
-               }
-
-               my $user = $info->{"committer"};
-               if (defined($info->{"author"})) { $user = $info->{"author"}; }
-               $user =~ s/\s*<.*>\s*$//;
-               $user =~ s/^\s*//;
-
-               push @ret, {
-                       rev        => $info->{"revno"},
-                       user       => $user,
-                       committype => "bzr",
-                       when       => time - str2time($info->{"timestamp"}),
-                       message    => [@message],
-                       pages      => [@pages],
-               };
-       }
-
-       return @ret;
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my ($file) = @_;
-
-       # XXX filename passes through the shell here, should try to avoid
-       # that just in case
-       my @cmdline = ("bzr", "log", "--limit", '1', "$config{srcdir}/$file");
-       open (my $out, "@cmdline |");
-
-       my @log = bzr_log($out);
-
-       if (length @log < 1) {
-               return 0;
-       }
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-       
-       my $ctime = str2time($log[0]->{"timestamp"});
-       return $ctime;
-} #}}}
-
-1
diff --git a/IkiWiki/Rcs/git.pm b/IkiWiki/Rcs/git.pm
deleted file mode 100644 (file)
index 0369008..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-use IkiWiki;
-use Encode;
-use open qw{:utf8 :std};
-
-package IkiWiki;
-
-my $sha1_pattern     = qr/[0-9a-fA-F]{40}/; # pattern to validate Git sha1sums
-my $dummy_commit_msg = 'dummy commit';      # message to skip in recent changes
-
-sub _safe_git (&@) { #{{{
-       # Start a child process safely without resorting /bin/sh.
-       # Return command output or success state (in scalar context).
-
-       my ($error_handler, @cmdline) = @_;
-
-       my $pid = open my $OUT, "-|";
-
-       error("Cannot fork: $!") if !defined $pid;
-
-       if (!$pid) {
-               # In child.
-               # Git commands want to be in wc.
-               chdir $config{srcdir}
-                   or error("Cannot chdir to $config{srcdir}: $!");
-               exec @cmdline or error("Cannot exec '@cmdline': $!");
-       }
-       # In parent.
-
-       my @lines;
-       while (<$OUT>) {
-               chomp;
-               push @lines, $_;
-       }
-
-       close $OUT;
-
-       $error_handler->("'@cmdline' failed: $!") if $? && $error_handler;
-
-       return wantarray ? @lines : ($? == 0);
-}
-# Convenient wrappers.
-sub run_or_die ($@) { _safe_git(\&error, @_) }
-sub run_or_cry ($@) { _safe_git(sub { warn @_ },  @_) }
-sub run_or_non ($@) { _safe_git(undef,            @_) }
-#}}}
-
-sub _merge_past ($$$) { #{{{
-       # Unlike with Subversion, Git cannot make a 'svn merge -rN:M file'.
-       # Git merge commands work with the committed changes, except in the
-       # implicit case of '-m' of git checkout(1).  So we should invent a
-       # kludge here.  In principle, we need to create a throw-away branch
-       # in preparing for the merge itself.  Since branches are cheap (and
-       # branching is fast), this shouldn't cost high.
-       #
-       # The main problem is the presence of _uncommitted_ local changes.  One
-       # possible approach to get rid of this situation could be that we first
-       # make a temporary commit in the master branch and later restore the
-       # initial state (this is possible since Git has the ability to undo a
-       # commit, i.e. 'git reset --soft HEAD^').  The method can be summarized
-       # as follows:
-       #
-       #       - create a diff of HEAD:current-sha1
-       #       - dummy commit
-       #       - create a dummy branch and switch to it
-       #       - rewind to past (reset --hard to the current-sha1)
-       #       - apply the diff and commit
-       #       - switch to master and do the merge with the dummy branch
-       #       - make a soft reset (undo the last commit of master)
-       #
-       # The above method has some drawbacks: (1) it needs a redundant commit
-       # just to get rid of local changes, (2) somewhat slow because of the
-       # required system forks.  Until someone points a more straight method
-       # (which I would be grateful) I have implemented an alternative method.
-       # In this approach, we hide all the modified files from Git by renaming
-       # them (using the 'rename' builtin) and later restore those files in
-       # the throw-away branch (that is, we put the files themselves instead
-       # of applying a patch).
-
-       my ($sha1, $file, $message) = @_;
-
-       my @undo;      # undo stack for cleanup in case of an error
-       my $conflict;  # file content with conflict markers
-
-       eval {
-               # Hide local changes from Git by renaming the modified file.
-               # Relative paths must be converted to absolute for renaming.
-               my ($target, $hidden) = (
-                   "$config{srcdir}/${file}", "$config{srcdir}/${file}.${sha1}"
-               );
-               rename($target, $hidden)
-                   or error("rename '$target' to '$hidden' failed: $!");
-               # Ensure to restore the renamed file on error.
-               push @undo, sub {
-                       return if ! -e "$hidden"; # already renamed
-                       rename($hidden, $target)
-                           or warn "rename '$hidden' to '$target' failed: $!";
-               };
-
-               my $branch = "throw_away_${sha1}"; # supposed to be unique
-
-               # Create a throw-away branch and rewind backward.
-               push @undo, sub { run_or_cry('git', 'branch', '-D', $branch) };
-               run_or_die('git', 'branch', $branch, $sha1);
-
-               # Switch to throw-away branch for the merge operation.
-               push @undo, sub {
-                       if (!run_or_cry('git', 'checkout', $config{gitmaster_branch})) {
-                               run_or_cry('git', 'checkout','-f',$config{gitmaster_branch});
-                       }
-               };
-               run_or_die('git', 'checkout', $branch);
-
-               # Put the modified file in _this_ branch.
-               rename($hidden, $target)
-                   or error("rename '$hidden' to '$target' failed: $!");
-
-               # _Silently_ commit all modifications in the current branch.
-               run_or_non('git', 'commit', '-m', $message, '-a');
-               # ... and re-switch to master.
-               run_or_die('git', 'checkout', $config{gitmaster_branch});
-
-               # Attempt to merge without complaining.
-               if (!run_or_non('git', 'pull', '--no-commit', '.', $branch)) {
-                       $conflict = readfile($target);
-                       run_or_die('git', 'reset', '--hard');
-               }
-       };
-       my $failure = $@;
-
-       # Process undo stack (in reverse order).  By policy cleanup
-       # actions should normally print a warning on failure.
-       while (my $handle = pop @undo) {
-               $handle->();
-       }
-
-       error("Git merge failed!\n$failure\n") if $failure;
-
-       return $conflict;
-} #}}}
-
-sub _parse_diff_tree ($@) { #{{{
-       # Parse the raw diff tree chunk and return the info hash.
-       # See git-diff-tree(1) for the syntax.
-
-       my ($prefix, $dt_ref) = @_;
-
-       # End of stream?
-       return if !defined @{ $dt_ref } ||
-                 !defined @{ $dt_ref }[0] || !length @{ $dt_ref }[0];
-
-       my %ci;
-       # Header line.
-       while (my $line = shift @{ $dt_ref }) {
-               return if $line !~ m/^(.+) ($sha1_pattern)/;
-
-               my $sha1 = $2;
-               $ci{'sha1'} = $sha1;
-               last;
-       }
-
-       # Identification lines for the commit.
-       while (my $line = shift @{ $dt_ref }) {
-               # Regexps are semi-stolen from gitweb.cgi.
-               if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
-                       $ci{'tree'} = $1;
-               }
-               elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) {
-                       # XXX: collecting in reverse order
-                       push @{ $ci{'parents'} }, $1;
-               }
-               elsif ($line =~ m/^(author|committer) (.*) ([0-9]+) (.*)$/) {
-                       my ($who, $name, $epoch, $tz) =
-                          ($1,   $2,    $3,     $4 );
-
-                       $ci{  $who          } = $name;
-                       $ci{ "${who}_epoch" } = $epoch;
-                       $ci{ "${who}_tz"    } = $tz;
-
-                       if ($name =~ m/^([^<]+) <([^@>]+)/) {
-                               my ($fullname, $username) = ($1, $2);
-                               $ci{"${who}_fullname"}    = $fullname;
-                               $ci{"${who}_username"}    = $username;
-                       }
-                       else {
-                               $ci{"${who}_fullname"} =
-                                       $ci{"${who}_username"} = $name;
-                       }
-               }
-               elsif ($line =~ m/^$/) {
-                       # Trailing empty line signals next section.
-                       last;
-               }
-       }
-
-       debug("No 'tree' seen in diff-tree output") if !defined $ci{'tree'};
-
-       if (defined $ci{'parents'}) {
-               $ci{'parent'} = @{ $ci{'parents'} }[0];
-       }
-       else {
-               $ci{'parent'} = 0 x 40;
-       }
-
-       # Commit message.
-       while (my $line = shift @{ $dt_ref }) {
-               if ($line =~ m/^$/) {
-                       # Trailing empty line signals next section.
-                       last;
-               };
-               $line =~ s/^    //;
-               push @{ $ci{'comment'} }, $line;
-       }
-
-       # Modified files.
-       while (my $line = shift @{ $dt_ref }) {
-               if ($line =~ m{^
-                       (:+)       # number of parents
-                       ([^\t]+)\t # modes, sha1, status
-                       (.*)       # file names
-               $}xo) {
-                       my $num_parents = length $1;
-                       my @tmp = split(" ", $2);
-                       my ($file, $file_to) = split("\t", $3);
-                       my @mode_from = splice(@tmp, 0, $num_parents);
-                       my $mode_to = shift(@tmp);
-                       my @sha1_from = splice(@tmp, 0, $num_parents);
-                       my $sha1_to = shift(@tmp);
-                       my $status = shift(@tmp);
-
-                       if ($file =~ m/^"(.*)"$/) {
-                               ($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg;
-                       }
-                       $file =~ s/^\Q$prefix\E//;
-                       if (length $file) {
-                               push @{ $ci{'details'} }, {
-                                       'file'      => decode_utf8($file),
-                                       'sha1_from' => $sha1_from[0],
-                                       'sha1_to'   => $sha1_to,
-                               };
-                       }
-                       next;
-               };
-               last;
-       }
-
-       return \%ci;
-} #}}}
-
-sub git_commit_info ($;$) { #{{{
-       # Return an array of commit info hashes of num commits (default: 1)
-       # starting from the given sha1sum.
-
-       my ($sha1, $num) = @_;
-
-       $num ||= 1;
-
-       my @raw_lines = run_or_die('git', 'log', "--max-count=$num", 
-               '--pretty=raw', '--raw', '--abbrev=40', '--always', '-c',
-               '-r', $sha1, '--', '.');
-       my ($prefix) = run_or_die('git', 'rev-parse', '--show-prefix');
-
-       my @ci;
-       while (my $parsed = _parse_diff_tree(($prefix or ""), \@raw_lines)) {
-               push @ci, $parsed;
-       }
-
-       warn "Cannot parse commit info for '$sha1' commit" if !@ci;
-
-       return wantarray ? @ci : $ci[0];
-} #}}}
-
-sub git_sha1 (;$) { #{{{
-       # Return head sha1sum (of given file).
-
-       my $file = shift || q{--};
-
-       # Ignore error since a non-existing file might be given.
-       my ($sha1) = run_or_non('git', 'rev-list', '--max-count=1', 'HEAD',
-               '--', $file);
-       if ($sha1) {
-               ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
-       } else { debug("Empty sha1sum for '$file'.") }
-       return defined $sha1 ? $sha1 : q{};
-} #}}}
-
-sub rcs_update () { #{{{
-       # Update working directory.
-
-       if (length $config{gitorigin_branch}) {
-               run_or_cry('git', 'pull', $config{gitorigin_branch});
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       # Return the commit sha1sum of the file when editing begins.
-       # This will be later used in rcs_commit if a merge is required.
-
-       my ($file) = @_;
-
-       return git_sha1($file);
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       # Try to commit the page; returns undef on _success_ and
-       # a version of the page with the rcs's conflict markers on
-       # failure.
-
-       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
-
-       if (defined $user) {
-               $message = "web commit by $user" .
-                   (length $message ? ": $message" : "");
-       }
-       elsif (defined $ipaddr) {
-               $message = "web commit from $ipaddr" .
-                   (length $message ? ": $message" : "");
-       }
-
-       # Check to see if the page has been changed by someone else since
-       # rcs_prepedit was called.
-       my $cur    = git_sha1($file);
-       my ($prev) = $rcstoken =~ /^($sha1_pattern)$/; # untaint
-
-       if (defined $cur && defined $prev && $cur ne $prev) {
-               my $conflict = _merge_past($prev, $file, $dummy_commit_msg);
-               return $conflict if defined $conflict;
-       }
-
-       # git commit returns non-zero if file has not been really changed.
-       # so we should ignore its exit status (hence run_or_non).
-       $message = possibly_foolish_untaint($message);
-       if (run_or_non('git', 'commit', '-q', '-m', $message, '-i', $file)) {
-               if (length $config{gitorigin_branch}) {
-                       run_or_cry('git', 'push', $config{gitorigin_branch});
-               }
-       }
-
-       return undef; # success
-} #}}}
-
-sub rcs_add ($) { # {{{
-       # Add file to archive.
-
-       my ($file) = @_;
-
-       run_or_cry('git', 'add', $file);
-} #}}}
-
-sub rcs_recentchanges ($) { #{{{
-       # List of recent changes.
-
-       my ($num) = @_;
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-
-       my @rets;
-       foreach my $ci (git_commit_info('HEAD', $num)) {
-               # Skip redundant commits.
-               next if (@{$ci->{'comment'}}[0] eq $dummy_commit_msg);
-
-               my ($sha1, $when) = (
-                       $ci->{'sha1'},
-                       $ci->{'author_epoch'}
-               );
-
-               my (@pages, @messages);
-               foreach my $detail (@{ $ci->{'details'} }) {
-                       my $file = $detail->{'file'};
-
-                       my $diffurl = $config{'diffurl'};
-                       $diffurl =~ s/\[\[file\]\]/$file/go;
-                       $diffurl =~ s/\[\[sha1_parent\]\]/$ci->{'parent'}/go;
-                       $diffurl =~ s/\[\[sha1_from\]\]/$detail->{'sha1_from'}/go;
-                       $diffurl =~ s/\[\[sha1_to\]\]/$detail->{'sha1_to'}/go;
-
-                       push @pages, {
-                               page => pagename($file),
-                               diffurl => $diffurl,
-                       };
-               }
-
-               push @messages, { line => $_ } foreach grep {
-                       ! m/^ *(signed[ \-]off[ \-]by[ :]|acked[ \-]by[ :]|cc[ :])/i
-               }  @{$ci->{'comment'}};
-
-               my ($user, $type) = (q{}, "web");
-
-               if (defined $messages[0] &&
-                   $messages[0]->{line} =~ m/$config{web_commit_regexp}/) {
-                       $user = defined $2 ? "$2" : "$3";
-                       $messages[0]->{line} = $4;
-               }
-               else {
-                       $type ="git";
-                       $user = $ci->{'author_username'};
-               }
-
-               push @rets, {
-                       rev        => $sha1,
-                       user       => $user,
-                       committype => $type,
-                       when       => $when,
-                       message    => [@messages],
-                       pages      => [@pages],
-               } if @pages;
-
-               last if @rets >= $num;
-       }
-
-       return @rets;
-} #}}}
-
-sub rcs_diff ($) { #{{{
-       my $rev=shift;
-       my ($sha1) = $rev =~ /^($sha1_pattern)$/; # untaint
-       my @lines;
-       foreach my $line (run_or_non("git", "show", $sha1)) {
-               if (@lines || $line=~/^diff --git/) {
-                       push @lines, $line."\n";
-               }
-       }
-       if (wantarray) {
-               return @lines;
-       }
-       else {
-               return join("", @lines);
-       }
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my $file=shift;
-       # Remove srcdir prefix
-       $file =~ s/^\Q$config{srcdir}\E\/?//;
-
-       my $sha1  = git_sha1($file);
-       my $ci    = git_commit_info($sha1);
-       my $ctime = $ci->{'author_epoch'};
-       debug("ctime for '$file': ". localtime($ctime));
-
-       return $ctime;
-} #}}}
-
-1
diff --git a/IkiWiki/Rcs/mercurial.pm b/IkiWiki/Rcs/mercurial.pm
deleted file mode 100644 (file)
index a042f4a..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-use IkiWiki;
-use Encode;
-use open qw{:utf8 :std};
-
-package IkiWiki;
-
-sub mercurial_log($) {
-       my $out = shift;
-       my @infos;
-
-       while (<$out>) {
-               my $line = $_;
-               my ($key, $value);
-
-               if (/^description:/) {
-                       $key = "description";
-                       $value = "";
-
-                       # slurp everything as the description text 
-                       # until the next changeset
-                       while (<$out>) {
-                               if (/^changeset: /) {
-                                       $line = $_;
-                                       last;
-                               }
-
-                               $value .= $_;
-                       }
-
-                       local $/ = "";
-                       chomp $value;
-                       $infos[$#infos]{$key} = $value;
-               }
-
-               chomp $line;
-               ($key, $value) = split /: +/, $line, 2;
-
-               if ($key eq "changeset") {
-                       push @infos, {};
-
-                       # remove the revision index, which is strictly 
-                       # local to the repository
-                       $value =~ s/^\d+://;
-               }
-
-               $infos[$#infos]{$key} = $value;
-       }
-       close $out;
-
-       return @infos;
-}
-
-sub rcs_update () { #{{{
-       my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       return "";
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
-
-       if (defined $user) {
-               $user = possibly_foolish_untaint($user);
-       }
-       elsif (defined $ipaddr) {
-               $user = "Anonymous from ".possibly_foolish_untaint($ipaddr);
-       }
-       else {
-               $user = "Anonymous";
-       }
-
-       $message = possibly_foolish_untaint($message);
-       if (! length $message) {
-               $message = "no message given";
-       }
-
-       my @cmdline = ("hg", "-q", "-R", $config{srcdir}, "commit", 
-                      "-m", $message, "-u", $user);
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-
-       return undef; # success
-} #}}}
-
-sub rcs_add ($) { # {{{
-       my ($file) = @_;
-
-       my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "add", "$config{srcdir}/$file");
-       if (system(@cmdline) != 0) {
-               warn "'@cmdline' failed: $!";
-       }
-} #}}}
-
-sub rcs_recentchanges ($) { #{{{
-       my ($num) = @_;
-
-       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v", "-l", $num,
-               "--style", "default");
-       open (my $out, "@cmdline |");
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-
-       my @ret;
-       foreach my $info (mercurial_log($out)) {
-               my @pages = ();
-               my @message = ();
-        
-               foreach my $msgline (split(/\n/, $info->{description})) {
-                       push @message, { line => $msgline };
-               }
-
-               foreach my $file (split / /,$info->{files}) {
-                       my $diffurl = $config{'diffurl'};
-                       $diffurl =~ s/\[\[file\]\]/$file/go;
-                       $diffurl =~ s/\[\[r2\]\]/$info->{changeset}/go;
-
-                       push @pages, {
-                               page => pagename($file),
-                               diffurl => $diffurl,
-                       };
-               }
-
-               my $user = $info->{"user"};
-               $user =~ s/\s*<.*>\s*$//;
-               $user =~ s/^\s*//;
-
-               push @ret, {
-                       rev        => $info->{"changeset"},
-                       user       => $user,
-                       committype => "mercurial",
-                       when       => str2time($info->{"date"}),
-                       message    => [@message],
-                       pages      => [@pages],
-               };
-       }
-
-       return @ret;
-} #}}}
-
-sub rcs_diff ($) { #{{{
-       # TODO
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my ($file) = @_;
-
-       # XXX filename passes through the shell here, should try to avoid
-       # that just in case
-       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v", "-l", '1', 
-               "--style", "default", "$config{srcdir}/$file");
-       open (my $out, "@cmdline |");
-
-       my @log = mercurial_log($out);
-
-       if (length @log < 1) {
-               return 0;
-       }
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-       
-       my $ctime = str2time($log[0]->{"date"});
-       return $ctime;
-} #}}}
-
-1
diff --git a/IkiWiki/Rcs/monotone.pm b/IkiWiki/Rcs/monotone.pm
deleted file mode 100644 (file)
index 6931fd3..0000000
+++ /dev/null
@@ -1,534 +0,0 @@
-#!/usr/bin/perl
-use warnings;
-use strict;
-use IkiWiki;
-use Monotone;
-use Date::Parse qw(str2time);
-use Date::Format qw(time2str);
-
-package IkiWiki;
-
-my $sha1_pattern = qr/[0-9a-fA-F]{40}/; # pattern to validate sha1sums
-
-sub check_config() { #{{{
-       if (!defined($config{mtnrootdir})) {
-               $config{mtnrootdir} = $config{srcdir};
-       }
-       if (! -d "$config{mtnrootdir}/_MTN") {
-               error("Ikiwiki srcdir does not seem to be a Monotone workspace (or set the mtnrootdir)!");
-       }
-       
-       chdir $config{srcdir}
-           or error("Cannot chdir to $config{srcdir}: $!");
-
-       my $child = open(MTN, "-|");
-       if (! $child) {
-               open STDERR, ">/dev/null";
-               exec("mtn", "version") || error("mtn version failed to run");
-       }
-
-       my $version=undef;
-       while (<MTN>) {
-               if (/^monotone (\d+\.\d+) /) {
-                       $version=$1;
-               }
-       }
-
-       close MTN || debug("mtn version exited $?");
-
-       if (!defined($version)) {
-               error("Cannot determine monotone version");
-       }
-       if ($version < 0.38) {
-               error("Monotone version too old, is $version but required 0.38");
-       }
-} #}}}
-
-sub get_rev () { #{{{
-       my $sha1 = `mtn --root=$config{mtnrootdir} automate get_base_revision_id`;
-
-       ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
-       if (! $sha1) {
-               debug("Unable to get base revision for '$config{srcdir}'.")
-       }
-
-       return $sha1;
-} #}}}
-
-sub get_rev_auto ($) { #{{{
-       my $automator=shift;
-
-       my @results = $automator->call("get_base_revision_id");
-
-       my $sha1 = $results[0];
-       ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
-       if (! $sha1) {
-               debug("Unable to get base revision for '$config{srcdir}'.")
-       }
-
-       return $sha1;
-} #}}}
-
-sub mtn_merge ($$$$) { #{{{
-       my $leftRev=shift;
-       my $rightRev=shift;
-       my $branch=shift;
-       my $author=shift;
-    
-       my $mergeRev;
-
-       my $child = open(MTNMERGE, "-|");
-       if (! $child) {
-               open STDERR, ">&STDOUT";
-               exec("mtn", "--root=$config{mtnrootdir}",
-                    "explicit_merge", $leftRev, $rightRev,
-                    $branch, "--author", $author, "--key", 
-                    $config{mtnkey}) || error("mtn merge failed to run");
-       }
-
-       while (<MTNMERGE>) {
-               if (/^mtn.\s.merged.\s($sha1_pattern)$/) {
-                       $mergeRev=$1;
-               }
-       }
-       
-       close MTNMERGE || return undef;
-
-       debug("merged $leftRev, $rightRev to make $mergeRev");
-
-       return $mergeRev;
-} #}}}
-
-sub commit_file_to_new_rev($$$$$$$$) { #{{{
-       my $automator=shift;
-       my $wsfilename=shift;
-       my $oldFileID=shift;
-       my $newFileContents=shift;
-       my $oldrev=shift;
-       my $branch=shift;
-       my $author=shift;
-       my $message=shift;
-       
-       #store the file
-       my ($out, $err) = $automator->call("put_file", $oldFileID, $newFileContents);
-       my ($newFileID) = ($out =~ m/^($sha1_pattern)$/);
-       error("Failed to store file data for $wsfilename in repository")
-               if (! defined $newFileID || length $newFileID != 40);
-
-       # get the mtn filename rather than the workspace filename
-       ($out, $err) = $automator->call("get_corresponding_path", $oldrev, $wsfilename, $oldrev);
-       my ($filename) = ($out =~ m/^file "(.*)"$/);
-       error("Couldn't find monotone repository path for file $wsfilename") if (! $filename);
-       debug("Converted ws filename of $wsfilename to repos filename of $filename");
-
-       # then stick in a new revision for this file
-       my $manifest = "format_version \"1\"\n\n".
-                      "new_manifest [0000000000000000000000000000000000000000]\n\n".
-                      "old_revision [$oldrev]\n\n".
-                      "patch \"$filename\"\n".
-                      " from [$oldFileID]\n".
-                      "   to [$newFileID]\n";
-       ($out, $err) = $automator->call("put_revision", $manifest);
-       my ($newRevID) = ($out =~ m/^($sha1_pattern)$/);
-       error("Unable to make new monotone repository revision")
-               if (! defined $newRevID || length $newRevID != 40);
-       debug("put revision: $newRevID");
-       
-       # now we need to add certs for this revision...
-       # author, branch, changelog, date
-       $automator->call("cert", $newRevID, "author", $author);
-       $automator->call("cert", $newRevID, "branch", $branch);
-       $automator->call("cert", $newRevID, "changelog", $message);
-       $automator->call("cert", $newRevID, "date",
-               time2str("%Y-%m-%dT%T", time, "UTC"));
-       
-       debug("Added certs for rev: $newRevID");
-       return $newRevID;
-} #}}}
-
-sub read_certs ($$) { #{{{
-       my $automator=shift;
-       my $rev=shift;
-       my @results = $automator->call("certs", $rev);
-       my @ret;
-
-       my $line = $results[0];
-       while ($line =~ m/\s+key\s"(.*?)"\nsignature\s"(ok|bad|unknown)"\n\s+name\s"(.*?)"\n\s+value\s"(.*?)"\n\s+trust\s"(trusted|untrusted)"\n/sg) {
-               push @ret, {
-                       key => $1,
-                       signature => $2,
-                       name => $3,
-                       value => $4,
-                       trust => $5,
-               };
-       }
-
-       return @ret;
-} #}}}
-
-sub get_changed_files ($$) { #{{{
-       my $automator=shift;
-       my $rev=shift;
-       
-       my @results = $automator->call("get_revision", $rev);
-       my $changes=$results[0];
-
-       my @ret;
-       my %seen = ();
-       
-       while ($changes =~ m/\s*(add_file|patch|delete|rename)\s"(.*?)(?<!\\)"\n/sg) {
-               my $file = $2;
-               # don't add the same file multiple times
-               if (! $seen{$file}) {
-                       push @ret, $file;
-                       $seen{$file} = 1;
-               }
-       }
-       
-       return @ret;
-} #}}}
-
-sub rcs_update () { #{{{
-       check_config();
-
-       if (defined($config{mtnsync}) && $config{mtnsync}) {
-               if (system("mtn", "--root=$config{mtnrootdir}", "sync",
-                          "--quiet", "--ticker=none", 
-                          "--key", $config{mtnkey}) != 0) {
-                       debug("monotone sync failed before update");
-               }
-       }
-
-       if (system("mtn", "--root=$config{mtnrootdir}", "update", "--quiet") != 0) {
-               debug("monotone update failed");
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       my $file=shift;
-
-       check_config();
-
-       # For monotone, return the revision of the file when
-       # editing begins.
-       return get_rev();
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       # Tries to commit the page; returns undef on _success_ and
-       # a version of the page with the rcs's conflict markers on failure.
-       # The file is relative to the srcdir.
-       my $file=shift;
-       my $message=shift;
-       my $rcstoken=shift;
-       my $user=shift;
-       my $ipaddr=shift;
-       my $author;
-
-       if (defined $user) {
-               $author="Web user: " . $user;
-       }
-       elsif (defined $ipaddr) {
-               $author="Web IP: " . $ipaddr;
-       }
-       else {
-               $author="Web: Anonymous";
-       }
-
-       check_config();
-
-       my ($oldrev)= $rcstoken=~ m/^($sha1_pattern)$/; # untaint
-       my $rev = get_rev();
-       if (defined $rev && defined $oldrev && $rev ne $oldrev) {
-               my $automator = Monotone->new();
-               $automator->open_args("--root", $config{mtnrootdir}, "--key", $config{mtnkey});
-
-               # Something has been committed, has this file changed?
-               my ($out, $err);
-               $automator->setOpts("r", $oldrev, "r", $rev);
-               ($out, $err) = $automator->call("content_diff", $file);
-               debug("Problem committing $file") if ($err ne "");
-               my $diff = $out;
-               
-               if ($diff) {
-                       # Commit a revision with just this file changed off
-                       # the old revision.
-                       #
-                       # first get the contents
-                       debug("File changed: forming branch");
-                       my $newfile=readfile("$config{srcdir}/$file");
-                       
-                       # then get the old content ID from the diff
-                       if ($diff !~ m/^---\s$file\s+($sha1_pattern)$/m) {
-                               error("Unable to find previous file ID for $file");
-                       }
-                       my $oldFileID = $1;
-
-                       # get the branch we're working in
-                       ($out, $err) = $automator->call("get_option", "branch");
-                       chomp $out;
-                       error("Illegal branch name in monotone workspace") if ($out !~ m/^([-\@\w\.]+)$/);
-                       my $branch = $1;
-
-                       # then put the new content into the DB (and record the new content ID)
-                       my $newRevID = commit_file_to_new_rev($automator, $file, $oldFileID, $newfile, $oldrev, $branch, $author, $message);
-
-                       $automator->close();
-
-                       # if we made it to here then the file has been committed... revert the local copy
-                       if (system("mtn", "--root=$config{mtnrootdir}", "revert", $file) != 0) {
-                               debug("Unable to revert $file after merge on conflicted commit!");
-                       }
-                       debug("Divergence created! Attempting auto-merge.");
-
-                       # see if it will merge cleanly
-                       $ENV{MTN_MERGE}="fail";
-                       my $mergeResult = mtn_merge($newRevID, $rev, $branch, $author);
-                       $ENV{MTN_MERGE}="";
-
-                       # push any changes so far
-                       if (defined($config{mtnsync}) && $config{mtnsync}) {
-                               if (system("mtn", "--root=$config{mtnrootdir}", "push", "--quiet", "--ticker=none", "--key", $config{mtnkey}) != 0) {
-                                       debug("monotone push failed");
-                               }
-                       }
-                       
-                       if (defined($mergeResult)) {
-                               # everything is merged - bring outselves up to date
-                               if (system("mtn", "--root=$config{mtnrootdir}",
-                                          "update", "-r", $mergeResult) != 0) {
-                                       debug("Unable to update to rev $mergeResult after merge on conflicted commit!");
-                               }
-                       }
-                       else {
-                               debug("Auto-merge failed.  Using diff-merge to add conflict markers.");
-                               
-                               $ENV{MTN_MERGE}="diffutils";
-                               $ENV{MTN_MERGE_DIFFUTILS}="partial=true";
-                               $mergeResult = mtn_merge($newRevID, $rev, $branch, $author);
-                               $ENV{MTN_MERGE}="";
-                               $ENV{MTN_MERGE_DIFFUTILS}="";
-                               
-                               if (!defined($mergeResult)) {
-                                       debug("Unable to insert conflict markers!");
-                                       error("Your commit succeeded. Unfortunately, someone else committed something to the same ".
-                                               "part of the wiki at the same time. Both versions are stored in the monotone repository, ".
-                                               "but at present the different versions cannot be reconciled through the web interface. ".
-                                               "Please use the non-web interface to resolve the conflicts.");
-                               }
-                               
-                               if (system("mtn", "--root=$config{mtnrootdir}",
-                                          "update", "-r", $mergeResult) != 0) {
-                                       debug("Unable to update to rev $mergeResult after conflict-enhanced merge on conflicted commit!");
-                               }
-                               
-                               # return "conflict enhanced" file to the user
-                               # for cleanup note, this relies on the fact
-                               # that ikiwiki seems to call rcs_prepedit()
-                               # again after we return
-                               return readfile("$config{srcdir}/$file");
-                       }
-                       return undef;
-               }
-               $automator->close();
-       }
-
-       # If we reached here then the file we're looking at hasn't changed
-       # since $oldrev. Commit it.
-
-       if (system("mtn", "--root=$config{mtnrootdir}", "commit", "--quiet",
-                  "--author", $author, "--key", $config{mtnkey}, "-m",
-                  possibly_foolish_untaint($message), $file) != 0) {
-               debug("Traditional commit failed! Returning data as conflict.");
-               my $conflict=readfile("$config{srcdir}/$file");
-               if (system("mtn", "--root=$config{mtnrootdir}", "revert",
-                          "--quiet", $file) != 0) {
-                       debug("monotone revert failed");
-               }
-               return $conflict;
-       }
-       if (defined($config{mtnsync}) && $config{mtnsync}) {
-               if (system("mtn", "--root=$config{mtnrootdir}", "push",
-                          "--quiet", "--ticker=none", "--key",
-                          $config{mtnkey}) != 0) {
-                       debug("monotone push failed");
-               }
-       }
-
-       return undef # success
-} #}}}
-
-sub rcs_add ($) { #{{{
-       my $file=shift;
-
-       check_config();
-
-       if (system("mtn", "--root=$config{mtnrootdir}", "add", "--quiet",
-                  $file) != 0) {
-               error("Monotone add failed");
-       }
-} #}}}
-
-sub rcs_recentchanges ($) { #{{{
-       my $num=shift;
-       my @ret;
-
-       check_config();
-
-       # use log --brief to get a list of revs, as this
-       # gives the results in a nice order
-       # (otherwise we'd have to do our own date sorting)
-
-       my @revs;
-
-       my $child = open(MTNLOG, "-|");
-       if (! $child) {
-               exec("mtn", "log", "--root=$config{mtnrootdir}", "--no-graph",
-                    "--brief") || error("mtn log failed to run");
-       }
-
-       while (($num >= 0) and (my $line = <MTNLOG>)) {
-               if ($line =~ m/^($sha1_pattern)/) {
-                       push @revs, $1;
-                       $num -= 1;
-               }
-       }
-       close MTNLOG || debug("mtn log exited $?");
-
-       my $automator = Monotone->new();
-       $automator->open(undef, $config{mtnrootdir});
-
-       while (@revs != 0) {
-               my $rev = shift @revs;
-               # first go through and figure out the messages, etc
-
-               my $certs = [read_certs($automator, $rev)];
-               
-               my $user;
-               my $when;
-               my $committype;
-               my (@pages, @message);
-               
-               foreach my $cert (@$certs) {
-                       if ($cert->{signature} eq "ok" &&
-                           $cert->{trust} eq "trusted") {
-                               if ($cert->{name} eq "author") {
-                                       $user = $cert->{value};
-                                       # detect the source of the commit
-                                       # from the changelog
-                                       if ($cert->{key} eq $config{mtnkey}) {
-                                               $committype = "web";
-                                       } else {
-                                               $committype = "monotone";
-                                       }
-                               } elsif ($cert->{name} eq "date") {
-                                       $when = str2time($cert->{value}, 'UTC');
-                               } elsif ($cert->{name} eq "changelog") {
-                                       my $messageText = $cert->{value};
-                                       # split the changelog into multiple
-                                       # lines
-                                       foreach my $msgline (split(/\n/, $messageText)) {
-                                               push @message, { line => $msgline };
-                                       }
-                               }
-                       }
-               }
-               
-               my @changed_files = get_changed_files($automator, $rev);
-               my $file;
-               
-               my ($out, $err) = $automator->call("parents", $rev);
-               my @parents = ($out =~ m/^($sha1_pattern)$/);
-               my $parent = $parents[0];
-
-               foreach $file (@changed_files) {
-                       next unless length $file;
-                       
-                       if (defined $config{diffurl} and (@parents == 1)) {
-                               my $diffurl=$config{diffurl};
-                               $diffurl=~s/\[\[r1\]\]/$parent/g;
-                               $diffurl=~s/\[\[r2\]\]/$rev/g;
-                               $diffurl=~s/\[\[file\]\]/$file/g;
-                               push @pages, {
-                                       page => pagename($file),
-                                       diffurl => $diffurl,
-                               };
-                       }
-                       else {
-                               push @pages, {
-                                       page => pagename($file),
-                               }
-                       }
-               }
-               
-               push @ret, {
-                       rev => $rev,
-                       user => $user,
-                       committype => $committype,
-                       when => $when,
-                       message => [@message],
-                       pages => [@pages],
-               } if @pages;
-       }
-
-       $automator->close();
-
-       return @ret;
-} #}}}
-
-sub rcs_diff ($) { #{{{
-       # TODO
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my $file=shift;
-
-       check_config();
-
-       my $child = open(MTNLOG, "-|");
-       if (! $child) {
-               exec("mtn", "log", "--root=$config{mtnrootdir}", "--no-graph",
-                    "--brief", $file) || error("mtn log $file failed to run");
-       }
-
-       my $firstRev;
-       while (<MTNLOG>) {
-               if (/^($sha1_pattern)/) {
-                       $firstRev=$1;
-               }
-       }
-       close MTNLOG || debug("mtn log $file exited $?");
-
-       if (! defined $firstRev) {
-               debug "failed to parse mtn log for $file";
-               return 0;
-       }
-
-       my $automator = Monotone->new();
-       $automator->open(undef, $config{mtnrootdir});
-
-       my $certs = [read_certs($automator, $firstRev)];
-
-       $automator->close();
-
-       my $date;
-
-       foreach my $cert (@$certs) {
-               if ($cert->{signature} eq "ok" && $cert->{trust} eq "trusted") {
-                       if ($cert->{name} eq "date") {
-                               $date = $cert->{value};
-                       }
-               }
-       }
-
-       if (! defined $date) {
-               debug "failed to find date cert for revision $firstRev when looking for creation time of $file";
-               return 0;
-       }
-
-       $date=str2time($date, 'UTC');
-       debug("found ctime ".localtime($date)." for $file");
-       return $date;
-} #}}}
-
-1
diff --git a/IkiWiki/Rcs/svn.pm b/IkiWiki/Rcs/svn.pm
deleted file mode 100644 (file)
index ea193e0..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-use IkiWiki;
-use POSIX qw(setlocale LC_CTYPE);
-
-package IkiWiki::Rcs::svn;
-
-sub import { #{{{
-       if (exists $IkiWiki::config{svnpath}) {
-               # code depends on the path not having extraneous slashes
-               $IkiWiki::config{svnpath}=~tr#/#/#s;
-               $IkiWiki::config{svnpath}=~s/\/$//;
-               $IkiWiki::config{svnpath}=~s/^\///;
-       }
-} #}}}
-
-
-package IkiWiki;
-
-# svn needs LC_CTYPE set to a UTF-8 locale, so try to find one. Any will do.
-sub find_lc_ctype() {
-       my $current = setlocale(LC_CTYPE());
-       return $current if $current =~ m/UTF-?8$/i;
-
-       # Make some obvious attempts to avoid calling `locale -a`
-       foreach my $locale ("$current.UTF-8", "en_US.UTF-8", "en_GB.UTF-8") {
-               return $locale if setlocale(LC_CTYPE(), $locale);
-       }
-
-       # Try to get all available locales and pick the first UTF-8 one found.
-       if (my @locale = grep(/UTF-?8$/i, `locale -a`)) {
-               chomp @locale;
-               return $locale[0] if setlocale(LC_CTYPE(), $locale[0]);
-       }
-
-       # fallback to the current locale
-       return $current;
-} # }}}
-$ENV{LC_CTYPE} = $ENV{LC_CTYPE} || find_lc_ctype();
-
-sub svn_info ($$) { #{{{
-       my $field=shift;
-       my $file=shift;
-
-       my $info=`LANG=C svn info $file`;
-       my ($ret)=$info=~/^$field: (.*)$/m;
-       return $ret;
-} #}}}
-
-sub rcs_update () { #{{{
-       if (-d "$config{srcdir}/.svn") {
-               if (system("svn", "update", "--quiet", $config{srcdir}) != 0) {
-                       warn("svn update failed\n");
-               }
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       # Prepares to edit a file under revision control. Returns a token
-       # that must be passed into rcs_commit when the file is ready
-       # for committing.
-       # The file is relative to the srcdir.
-       my $file=shift;
-       
-       if (-d "$config{srcdir}/.svn") {
-               # For subversion, return the revision of the file when
-               # editing begins.
-               my $rev=svn_info("Revision", "$config{srcdir}/$file");
-               return defined $rev ? $rev : "";
-       }
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       # Tries to commit the page; returns undef on _success_ and
-       # a version of the page with the rcs's conflict markers on failure.
-       # The file is relative to the srcdir.
-       my $file=shift;
-       my $message=shift;
-       my $rcstoken=shift;
-       my $user=shift;
-       my $ipaddr=shift;
-
-       if (defined $user) {
-               $message="web commit by $user".(length $message ? ": $message" : "");
-       }
-       elsif (defined $ipaddr) {
-               $message="web commit from $ipaddr".(length $message ? ": $message" : "");
-       }
-
-       if (-d "$config{srcdir}/.svn") {
-               # Check to see if the page has been changed by someone
-               # else since rcs_prepedit was called.
-               my ($oldrev)=$rcstoken=~/^([0-9]+)$/; # untaint
-               my $rev=svn_info("Revision", "$config{srcdir}/$file");
-               if (defined $rev && defined $oldrev && $rev != $oldrev) {
-                       # Merge their changes into the file that we've
-                       # changed.
-                       if (system("svn", "merge", "--quiet", "-r$oldrev:$rev",
-                                  "$config{srcdir}/$file", "$config{srcdir}/$file") != 0) {
-                               warn("svn merge -r$oldrev:$rev failed\n");
-                       }
-               }
-
-               if (system("svn", "commit", "--quiet", 
-                          "--encoding", "UTF-8", "-m",
-                          possibly_foolish_untaint($message),
-                          $config{srcdir}) != 0) {
-                       my $conflict=readfile("$config{srcdir}/$file");
-                       if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
-                               warn("svn revert failed\n");
-                       }
-                       return $conflict;
-               }
-       }
-       return undef # success
-} #}}}
-
-sub rcs_add ($) { #{{{
-       # filename is relative to the root of the srcdir
-       my $file=shift;
-
-       if (-d "$config{srcdir}/.svn") {
-               my $parent=dirname($file);
-               while (! -d "$config{srcdir}/$parent/.svn") {
-                       $file=$parent;
-                       $parent=dirname($file);
-               }
-               
-               if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
-                       warn("svn add failed\n");
-               }
-       }
-} #}}}
-
-sub rcs_recentchanges ($) { #{{{
-       my $num=shift;
-       my @ret;
-       
-       return unless -d "$config{srcdir}/.svn";
-
-       eval q{
-               use Date::Parse;
-               use XML::SAX;
-               use XML::Simple;
-       };
-       error($@) if $@;
-
-       # avoid using XML::SAX::PurePerl, it's buggy with UTF-8 data
-       my @parsers = map { ${$_}{Name} } @{XML::SAX->parsers()};
-       do {
-               $XML::Simple::PREFERRED_PARSER = pop @parsers;
-       } until $XML::Simple::PREFERRED_PARSER ne 'XML::SAX::PurePerl';
-
-       # --limit is only supported on Subversion 1.2.0+
-       my $svn_version=`svn --version -q`;
-       my $svn_limit='';
-       $svn_limit="--limit $num"
-               if $svn_version =~ /\d\.(\d)\.\d/ && $1 >= 2;
-
-       my $svn_url=svn_info("URL", $config{srcdir});
-       my $xml = XMLin(scalar `svn $svn_limit --xml -v log '$svn_url'`,
-               ForceArray => [ 'logentry', 'path' ],
-               GroupTags => { paths => 'path' },
-               KeyAttr => { path => 'content' },
-       );
-       foreach my $logentry (@{$xml->{logentry}}) {
-               my (@pages, @message);
-
-               my $rev = $logentry->{revision};
-               my $user = $logentry->{author};
-
-               my $when=str2time($logentry->{date}, 'UTC');
-
-               foreach my $msgline (split(/\n/, $logentry->{msg})) {
-                       push @message, { line => $msgline };
-               }
-
-               my $committype="web";
-               if (defined $message[0] &&
-                   $message[0]->{line}=~/$config{web_commit_regexp}/) {
-                       $user=defined $2 ? "$2" : "$3";
-                       $message[0]->{line}=$4;
-               }
-               else {
-                       $committype="svn";
-               }
-
-               foreach my $file (keys %{$logentry->{paths}}) {
-                       if (length $config{svnpath}) {
-                               next unless $file=~/^\/\Q$config{svnpath}\E\/([^ ]+)(?:$|\s)/;
-                               $file=$1;
-                       }
-
-                       my $diffurl=$config{diffurl};
-                       $diffurl=~s/\[\[file\]\]/$file/g;
-                       $diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
-                       $diffurl=~s/\[\[r2\]\]/$rev/g;
-
-                       push @pages, {
-                               page => pagename($file),
-                               diffurl => $diffurl,
-                       } if length $file;
-               }
-               push @ret, {
-                       rev => $rev,
-                       user => $user,
-                       committype => $committype,
-                       when => $when,
-                       message => [@message],
-                       pages => [@pages],
-               } if @pages;
-               return @ret if @ret >= $num;
-       }
-
-       return @ret;
-} #}}}
-
-sub rcs_diff ($) { #{{{
-       my $rev=possibly_foolish_untaint(int(shift));
-       return `svnlook diff $config{svnrepo} -r$rev --no-diff-deleted`;
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my $file=shift;
-
-       my $svn_log_infoline=qr/^r\d+\s+\|\s+[^\s]+\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
-               
-       my $child = open(SVNLOG, "-|");
-       if (! $child) {
-               exec("svn", "log", $file) || error("svn log $file failed to run");
-       }
-
-       my $date;
-       while (<SVNLOG>) {
-               if (/$svn_log_infoline/) {
-                       $date=$1;
-               }
-       }
-       close SVNLOG || warn "svn log $file exited $?";
-
-       if (! defined $date) {
-               warn "failed to parse svn log for $file\n";
-               return 0;
-       }
-               
-       eval q{use Date::Parse};
-       error($@) if $@;
-       $date=str2time($date);
-       debug("found ctime ".localtime($date)." for $file");
-       return $date;
-} #}}}
-
-1
diff --git a/IkiWiki/Rcs/tla.pm b/IkiWiki/Rcs/tla.pm
deleted file mode 100644 (file)
index 47579c1..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/perl
-
-use warnings;
-use strict;
-use IkiWiki;
-
-package IkiWiki;
-
-sub quiet_system (@) {
-       # See Debian bug #385939.
-       open (SAVEOUT, ">&STDOUT");
-       close STDOUT;
-       open (STDOUT, ">/dev/null");
-       my $ret=system(@_);
-       close STDOUT;
-       open (STDOUT, ">&SAVEOUT");
-       close SAVEOUT;
-       return $ret;
-}
-
-sub rcs_update () { #{{{
-       if (-d "$config{srcdir}/{arch}") {
-               if (quiet_system("tla", "replay", "-d", $config{srcdir}) != 0) {
-                       warn("tla replay failed\n");
-               }
-       }
-} #}}}
-
-sub rcs_prepedit ($) { #{{{
-       my $file=shift;
-
-       if (-d "$config{srcdir}/{arch}") {
-               # For Arch, return the tree-id of archive when
-               # editing begins.
-               my $rev=`tla tree-id $config{srcdir}`;
-               return defined $rev ? $rev : "";
-       }
-} #}}}
-
-sub rcs_commit ($$$;$$) { #{{{
-       my $file=shift;
-       my $message=shift;
-       my $rcstoken=shift;
-       my $user=shift;
-       my $ipaddr=shift;
-
-       if (defined $user) {
-               $message="web commit by $user".(length $message ? ": $message" : "");
-       }
-       elsif (defined $ipaddr) {
-               $message="web commit from $ipaddr".(length $message ? ": $message" : "");
-       }
-
-       if (-d "$config{srcdir}/{arch}") {
-               # Check to see if the page has been changed by someone
-               # else since rcs_prepedit was called.
-               my ($oldrev)=$rcstoken=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
-               my $rev=`tla tree-id $config{srcdir}`;
-               if (defined $rev && defined $oldrev && $rev ne $oldrev) {
-                       # Merge their changes into the file that we've
-                       # changed.
-                       if (quiet_system("tla", "update", "-d",
-                                  "$config{srcdir}") != 0) {
-                               warn("tla update failed\n");
-                       }
-               }
-
-               if (quiet_system("tla", "commit",
-                          "-L".possibly_foolish_untaint($message),
-                          '-d', $config{srcdir}) != 0) {
-                       my $conflict=readfile("$config{srcdir}/$file");
-                       if (system("tla", "undo", "-n", "--quiet", "-d", "$config{srcdir}") != 0) {
-                               warn("tla undo failed\n");
-                       }
-                       return $conflict;
-               }
-       }
-       return undef # success
-} #}}}
-
-sub rcs_add ($) { #{{{
-       my $file=shift;
-
-       if (-d "$config{srcdir}/{arch}") {
-               if (quiet_system("tla", "add", "$config{srcdir}/$file") != 0) {
-                       warn("tla add failed\n");
-               }
-       }
-} #}}}
-
-sub rcs_recentchanges ($) {
-       my $num=shift;
-       my @ret;
-
-       return unless -d "$config{srcdir}/{arch}";
-
-       eval q{use Date::Parse};
-       error($@) if $@;
-       eval q{use Mail::Header};
-       error($@) if $@;
-
-       my $logs = `tla logs -d $config{srcdir}`;
-       my @changesets = reverse split(/\n/, $logs);
-
-       for (my $i=0; $i<$num && $i<$#changesets; $i++) {
-               my ($change)=$changesets[$i]=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
-
-               open(LOG, "tla cat-log -d $config{srcdir} $change|");
-               my $head = Mail::Header->new(\*LOG);
-               close(LOG);
-
-               my $rev = $head->get("Revision");
-               my $summ = $head->get("Summary");
-               my $newfiles = $head->get("New-files");
-               my $modfiles = $head->get("Modified-files");
-               my $remfiles = $head->get("Removed-files");
-               my $user = $head->get("Creator");
-
-               my @paths = grep { !/^(.*\/)?\.arch-ids\/.*\.id$/ }
-                       split(/ /, "$newfiles $modfiles .arch-ids/fake.id");
-
-               my $sdate = $head->get("Standard-date");
-               my $when = str2time($sdate, 'UTC');
-
-               my $committype = "web";
-               if (defined $summ && $summ =~ /$config{web_commit_regexp}/) {
-                       $user = defined $2 ? "$2" : "$3";
-                       $summ = $4;
-               }
-               else {
-                       $committype="tla";
-               }
-
-               my @message;
-               push @message, { line => $summ };
-
-               my @pages;
-
-               foreach my $file (@paths) {
-                       my $diffurl=$config{diffurl};
-                       $diffurl=~s/\[\[file\]\]/$file/g;
-                       $diffurl=~s/\[\[rev\]\]/$change/g;
-                       push @pages, {
-                               page => pagename($file),
-                               diffurl => $diffurl,
-                       } if length $file;
-               }
-               push @ret, {
-                       rev => $change,
-                       user => $user,
-                       committype => $committype,
-                       when => $when,
-                       message => [@message],
-                       pages => [@pages],
-               } if @pages;
-
-               last if $i == $num;
-       }
-
-       return @ret;
-}
-
-sub rcs_diff ($) { #{{{
-       my $rev=shift;
-       my $logs = `tla logs -d $config{srcdir}`;
-       my @changesets = reverse split(/\n/, $logs);
-       my $i;
-
-       for($i=0;$i<$#changesets;$i++) {
-               last if $changesets[$i] eq $rev;
-       }
-
-       my $revminusone = $changesets[$i+1];
-       return `tla diff -d $config{srcdir} $revminusone`;
-} #}}}
-
-sub rcs_getctime ($) { #{{{
-       my $file=shift;
-       eval q{use Date::Parse};
-       error($@) if $@;
-       eval q{use Mail::Header};
-       error($@) if $@;
-
-       my $logs = `tla logs -d $config{srcdir}`;
-       my @changesets = reverse split(/\n/, $logs);
-       my $sdate;
-
-       for (my $i=0; $i<$#changesets; $i++) {
-               my $change = $changesets[$i];
-
-               open(LOG, "tla cat-log -d $config{srcdir} $change|");
-               my $head = Mail::Header->new(\*LOG);
-               close(LOG);
-
-               $sdate = $head->get("Standard-date");
-               my $newfiles = $head->get("New-files");
-
-               my ($lastcreation) = grep {/^$file$/} split(/ /, "$newfiles");
-               last if defined($lastcreation);
-       }
-
-       my $date=str2time($sdate, 'UTC');
-       debug("found ctime ".localtime($date)." for $file");
-       return $date;
-} #}}}
-
-1
diff --git a/IkiWiki/Receive.pm b/IkiWiki/Receive.pm
new file mode 100644 (file)
index 0000000..37b6f2a
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/perl
+
+package IkiWiki::Receive;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub getuser () {
+       my $user=(getpwuid(exists $ENV{CALLER_UID} ? $ENV{CALLER_UID} : $<))[0];
+       if (! defined $user) {
+               error("cannot determine username for $<");
+       }
+       return $user;
+}
+
+sub trusted () {
+       my $user=getuser();
+       return ! ref $config{untrusted_committers} ||
+               ! grep { $_ eq $user } @{$config{untrusted_committers}};
+}
+
+sub gen_wrapper () {
+       # Test for commits from untrusted committers in the wrapper, to
+       # avoid loading ikiwiki at all for trusted commits.
+
+       my $ret=<<"EOF";
+       {
+               int u=getuid();
+EOF
+       $ret.="\t\tif ( ".
+               join("&&", map {
+                       my $uid=getpwnam($_);
+                       if (! defined $uid) {
+                               error(sprintf(gettext("cannot determine id of untrusted committer %s"), $_));
+                       }
+                       "u != $uid";
+               } @{$config{untrusted_committers}}).
+               ") exit(0);\n";
+       $ret.=<<"EOF";
+               asprintf(&s, "CALLER_UID=%i", u);
+               newenviron[i++]=s;
+       }
+EOF
+       return $ret;
+}
+
+sub test () {
+       exit 0 if trusted();
+       
+       IkiWiki::lockwiki();
+       IkiWiki::loadindex();
+       
+       # Dummy up a cgi environment to use when calling check_canedit
+       # and friends.
+       eval q{use CGI};
+       error($@) if $@;
+       my $cgi=CGI->new;
+       $ENV{REMOTE_ADDR}='unknown' unless exists $ENV{REMOTE_ADDR};
+
+       # And dummy up a session object.
+       require IkiWiki::CGI;
+       my $session=IkiWiki::cgi_getsession($cgi);
+       $session->param("name", getuser());
+       # Make sure whatever user was authed is in the
+       # userinfo db.
+       require IkiWiki::UserInfo;
+       if (! IkiWiki::userinfo_get($session->param("name"), "regdate")) {
+               IkiWiki::userinfo_setall($session->param("name"), {
+                       email => "",
+                       password => "",
+                       regdate => time,
+               }) || error("failed adding user");
+       }
+       
+       my %newfiles;
+
+       foreach my $change (IkiWiki::rcs_receive()) {
+               # This untaint is safe because we check file_pruned and
+               # wiki_file_regexp.
+               my ($file)=$change->{file}=~/$config{wiki_file_regexp}/;
+               $file=IkiWiki::possibly_foolish_untaint($file);
+               if (! defined $file || ! length $file ||
+                   IkiWiki::file_pruned($file, $config{srcdir})) {
+                       error(gettext("bad file name %s"), $file);
+               }
+
+               my $type=pagetype($file);
+               my $page=pagename($file) if defined $type;
+               
+               if ($change->{action} eq 'add') {
+                       $newfiles{$file}=1;
+               }
+
+               if ($change->{action} eq 'change' ||
+                   $change->{action} eq 'add') {
+                       if (defined $page) {
+                               if (IkiWiki->can("check_canedit")) {
+                                       IkiWiki::check_canedit($page, $cgi, $session);
+                                       next;
+                               }
+                       }
+                       else {
+                               if (IkiWiki::Plugin::attachment->can("check_canattach")) {
+                                       IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path});
+                                       next;
+                               }
+                       }
+               }
+               elsif ($change->{action} eq 'remove') {
+                       # check_canremove tests to see if the file is present
+                       # on disk. This will fail is a single commit adds a
+                       # file and then removes it again. Avoid the problem
+                       # by not testing the removal in such pairs of changes.
+                       # (The add is still tested, just to make sure that
+                       # no data is added to the repo that a web edit
+                       # could add.)
+                       next if $newfiles{$file};
+
+                       if (IkiWiki::Plugin::remove->can("check_canremove")) {
+                               IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session);
+                               next;
+                       }
+               }
+               else {
+                       error "unknown action ".$change->{action};
+               }
+               
+               error sprintf(gettext("you are not allowed to change %s"), $file);
+       }
+
+       exit 0;
+}
+
+1
index c241fd40b5beb7abff5901246930d978cb9476b5..da2d7b4ccc1adc480c2acc20f6b5d167a8fc7ff2 100644 (file)
@@ -8,29 +8,40 @@ use IkiWiki;
 use Encode;
 
 my %backlinks;
-my $backlinks_calculated=0;
+our %brokenlinks;
+my $links_calculated=0;
 
-sub calculate_backlinks () { #{{{
-       return if $backlinks_calculated;
-       %backlinks=();
+sub calculate_links () {
+       return if $links_calculated;
+       %backlinks=%brokenlinks=();
        foreach my $page (keys %links) {
                foreach my $link (@{$links{$page}}) {
                        my $bestlink=bestlink($page, $link);
-                       if (length $bestlink && $bestlink ne $page) {
-                               $backlinks{$bestlink}{$page}=1;
+                       if (length $bestlink) {
+                               $backlinks{$bestlink}{$page}=1
+                                       if $bestlink ne $page;
+                       }
+                       else {
+                               push @{$brokenlinks{$link}}, $page;
                        }
                }
        }
-       $backlinks_calculated=1;
-} #}}}
+       $links_calculated=1;
+}
 
-sub backlinks ($) { #{{{
+sub backlink_pages ($) {
        my $page=shift;
 
-       calculate_backlinks();
+       calculate_links();
+
+       return keys %{$backlinks{$page}};
+}
+
+sub backlinks ($) {
+       my $page=shift;
 
        my @links;
-       foreach my $p (keys %{$backlinks{$page}}) {
+       foreach my $p (backlink_pages($page)) {
                my $href=urlto($p, $page);
                 
                # Trim common dir prefixes from both pages.
@@ -45,26 +56,9 @@ sub backlinks ($) { #{{{
                push @links, { url => $href, page => pagetitle($p_trimmed) };
        }
        return @links;
-} #}}}
-
-sub parentlinks ($) { #{{{
-       my $page=shift;
-       
-       my @ret;
-       my $pagelink="";
-       my $path="";
-       my $title=$config{wikiname};
-       
-       foreach my $dir (split("/", $page)) {
-               next if $dir eq 'index';
-               push @ret, { url => urlto($path, $page), page => $title };
-               $path.="/".$dir;
-               $title=pagetitle($dir);
-       }
-       return @ret;
-} #}}}
+}
 
-sub genpage ($$) { #{{{
+sub genpage ($$) {
        my $page=shift;
        my $content=shift;
 
@@ -80,23 +74,24 @@ sub genpage ($$) { #{{{
        my $actions=0;
 
        if (length $config{cgiurl}) {
-               $template->param(editurl => cgiurl(do => "edit", page => $page));
-               $template->param(prefsurl => cgiurl(do => "prefs"));
+               $template->param(editurl => cgiurl(do => "edit", page => $page))
+                       if IkiWiki->can("cgi_editpage");
+               $template->param(prefsurl => cgiurl(do => "prefs"))
+                       if exists $hooks{auth};
                $actions++;
        }
                
-       if (length $config{historyurl}) {
+       if (defined $config{historyurl} && length $config{historyurl}) {
                my $u=$config{historyurl};
                $u=~s/\[\[file\]\]/$pagesources{$page}/g;
                $template->param(historyurl => $u);
                $actions++;
        }
        if ($config{discussion}) {
-               my $discussionlink=gettext("discussion");
-               if ($page !~ /.*\/\Q$discussionlink\E$/ &&
+               if ($page !~ /.*\/\Q$config{discussionpage}\E$/ &&
                   (length $config{cgiurl} ||
-                   exists $links{$page."/".$discussionlink})) {
-                       $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1));
+                   exists $links{$page."/".$config{discussionpage}})) {
+                       $template->param(discussionlink => htmllink($page, $page, $config{discussionpage}, noimageinline => 1, forcesubpage => 1));
                        $actions++;
                }
        }
@@ -121,7 +116,6 @@ sub genpage ($$) { #{{{
                        ? $config{wikiname} 
                        : pagetitle(basename($page)),
                wikiname => $config{wikiname},
-               parentlinks => [parentlinks($page)],
                content => $content,
                backlinks => $backlinks,
                more_backlinks => $more_backlinks,
@@ -135,6 +129,10 @@ sub genpage ($$) { #{{{
        });
        
        $content=$template->output;
+       
+       run_hooks(postscan => sub {
+               shift->(page => $page, content => $content);
+       });
 
        run_hooks(format => sub {
                $content=shift->(
@@ -144,9 +142,9 @@ sub genpage ($$) { #{{{
        });
 
        return $content;
-} #}}}
+}
 
-sub scan ($) { #{{{
+sub scan ($) {
        my $file=shift;
 
        my $type=pagetype($file);
@@ -159,7 +157,7 @@ sub scan ($) { #{{{
                if ($config{discussion}) {
                        # Discussion links are a special case since they're
                        # not in the text of the page, but on its template.
-                       $links{$page}=[ $page."/".gettext("discussion") ];
+                       $links{$page}=[ $page."/".lc($config{discussionpage}) ];
                }
                else {
                        $links{$page}=[];
@@ -178,9 +176,9 @@ sub scan ($) { #{{{
        else {
                will_render($file, $file, 1);
        }
-} #}}}
+}
 
-sub fast_file_copy (@) { #{{{
+sub fast_file_copy (@) {
        my $srcfile=shift;
        my $destfile=shift;
        my $srcfd=shift;
@@ -204,7 +202,7 @@ sub fast_file_copy (@) { #{{{
        }
 }
 
-sub render ($) { #{{{
+sub render ($) {
        my $file=shift;
        
        my $type=pagetype($file);
@@ -229,10 +227,14 @@ sub render ($) { #{{{
                will_render($file, $file, 1);
                
                if ($config{hardlink}) {
-                       prep_writefile($file, $config{destdir});
-                       unlink($config{destdir}."/".$file);
-                       if (link($srcfile, $config{destdir}."/".$file)) {
-                               return;
+                       # only hardlink if owned by same user
+                       my @stat=stat($srcfile);
+                       if ($stat[4] == $>) {
+                               prep_writefile($file, $config{destdir});
+                               unlink($config{destdir}."/".$file);
+                               if (link($srcfile, $config{destdir}."/".$file)) {
+                                       return;
+                               }
                        }
                        # if hardlink fails, fall back to copying
                }
@@ -242,9 +244,9 @@ sub render ($) { #{{{
                        fast_file_copy($srcfile, $file, $srcfd, @_);
                });
        }
-} #}}}
+}
 
-sub prune ($) { #{{{
+sub prune ($) {
        my $file=shift;
 
        unlink($file);
@@ -252,25 +254,24 @@ sub prune ($) { #{{{
        while (rmdir($dir)) {
                $dir=dirname($dir);
        }
-} #}}}
+}
 
-sub refresh () { #{{{
-       # security check, avoid following symlinks in the srcdir path
+sub srcdir_check () {
+       # security check, avoid following symlinks in the srcdir path by default
        my $test=$config{srcdir};
        while (length $test) {
-               if (-l $test) {
-                       error("symlink found in srcdir path ($test)");
+               if (-l $test && ! $config{allow_symlinks_before_srcdir}) {
+                       error(sprintf(gettext("symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to allow this"), $test));
                }
                unless ($test=~s/\/+$//) {
                        $test=dirname($test);
                }
        }
        
-       run_hooks(refresh => sub { shift->() });
+}
 
-       # find existing pages
-       my %exists;
-       my @files;
+sub find_src_files () {
+       my (@files, %pages);
        eval q{use File::Find};
        error($@) if $@;
        find({
@@ -288,7 +289,11 @@ sub refresh () { #{{{
                                else {
                                        $f=~s/^\Q$config{srcdir}\E\/?//;
                                        push @files, $f;
-                                       $exists{pagename($f)}=1;
+                                       my $pagename = pagename($f);
+                                       if ($pages{$pagename}) {
+                                               debug(sprintf(gettext("%s has multiple possible source pages"), $pagename));
+                                       }
+                                       $pages{$pagename}=1;
                                }
                        }
                },
@@ -314,9 +319,9 @@ sub refresh () { #{{{
                                                if (! -l "$config{srcdir}/$f" && 
                                                    ! -e _) {
                                                        my $page=pagename($f);
-                                                       if (! $exists{$page}) {
+                                                       if (! $pages{$page}) {
                                                                push @files, $f;
-                                                               $exists{$page}=1;
+                                                               $pages{$page}=1;
                                                        }
                                                }
                                        }
@@ -325,10 +330,24 @@ sub refresh () { #{{{
                }, $dir);
        };
 
+       # Returns a list of all source files found, and a hash of 
+       # the corresponding page names.
+       return \@files, \%pages;
+}
+
+sub refresh () {
+       srcdir_check();
+       run_hooks(refresh => sub { shift->() });
+       my ($files, $exists)=find_src_files();
+
        my (%rendered, @add, @del, @internal);
        # check for added or removed pages
-       foreach my $file (@files) {
+       foreach my $file (@$files) {
                my $page=pagename($file);
+               if (exists $pagesources{$page} && $pagesources{$page} ne $file) {
+                       # the page has changed its type
+                       $forcerebuild{$page}=1;
+               }
                $pagesources{$page}=$file;
                if (! $pagemtime{$page}) {
                        if (isinternal($page)) {
@@ -353,7 +372,7 @@ sub refresh () { #{{{
                }
        }
        foreach my $page (keys %pagemtime) {
-               if (! $exists{$page}) {
+               if (! $exists->{$page}) {
                        if (isinternal($page)) {
                                push @internal, $pagesources{$page};
                        }
@@ -364,12 +383,13 @@ sub refresh () { #{{{
                        $links{$page}=[];
                        $renderedfiles{$page}=[];
                        $pagemtime{$page}=0;
-                       prune($config{destdir}."/".$_)
-                               foreach @{$oldrenderedfiles{$page}};
+                       foreach my $old (@{$oldrenderedfiles{$page}}) {
+                               prune($config{destdir}."/".$old);
+                       }
                        delete $pagesources{$page};
-                       foreach (keys %destsources) {
-                               if ($destsources{$_} eq $page) {
-                                       delete $destsources{$_};
+                       foreach my $source (keys %destsources) {
+                               if ($destsources{$source} eq $page) {
+                                       delete $destsources{$source};
                                }
                        }
                }
@@ -377,7 +397,7 @@ sub refresh () { #{{{
 
        # find changed and new files
        my @needsbuild;
-       foreach my $file (@files) {
+       foreach my $file (@$files) {
                my $page=pagename($file);
                my ($srcfile, @stat)=srcfile_stat($file);
                if (! exists $pagemtime{$page} ||
@@ -401,9 +421,9 @@ sub refresh () { #{{{
                debug(sprintf(gettext("scanning %s"), $file));
                scan($file);
        }
-       calculate_backlinks();
+       calculate_links();
        foreach my $file (@needsbuild) {
-               debug(sprintf(gettext("rendering %s"), $file));
+               debug(sprintf(gettext("building %s"), $file));
                render($file);
                $rendered{$file}=1;
        }
@@ -424,7 +444,7 @@ sub refresh () { #{{{
                        foreach my $page (keys %{$backlinks{$p}}) {
                                my $file=$pagesources{$page};
                                next if $rendered{$file};
-                               debug(sprintf(gettext("rendering %s, which links to %s"), $file, $p));
+                               debug(sprintf(gettext("building %s, which links to %s"), $file, $p));
                                render($file);
                                $rendered{$file}=1;
                        }
@@ -435,20 +455,26 @@ sub refresh () { #{{{
                my @changed=(keys %rendered, @del);
 
                # rebuild dependant pages
-               foreach my $f (@files) {
+               F: foreach my $f (@$files) {
                        next if $rendered{$f};
                        my $p=pagename($f);
                        if (exists $depends{$p}) {
-                               # only consider internal files
-                               # if the page explicitly depends on such files
-                               foreach my $file (@changed, $depends{$p}=~/internal\(/ ? @internal : ()) {
-                                       next if $f eq $file;
-                                       my $page=pagename($file);
-                                       if (pagespec_match($page, $depends{$p}, location => $p)) {
-                                               debug(sprintf(gettext("rendering %s, which depends on %s"), $f, $page));
-                                               render($f);
-                                               $rendered{$f}=1;
-                                               last;
+                               foreach my $d (keys %{$depends{$p}}) {
+                                       my $sub=pagespec_translate($d);
+                                       next if $@ || ! defined $sub;
+
+                                       # only consider internal files
+                                       # if the page explicitly depends
+                                       # on such files
+                                       foreach my $file (@changed, $d =~ /internal\(/ ? @internal : ()) {
+                                               next if $file eq $f;
+                                               my $page=pagename($file);
+                                               if ($sub->($page, location => $p)) {
+                                                       debug(sprintf(gettext("building %s, which depends on %s"), $f, $page));
+                                                       render($f);
+                                                       $rendered{$f}=1;
+                                                       next F;
+                                               }
                                        }
                                }
                        }
@@ -484,7 +510,7 @@ sub refresh () { #{{{
                        my $linkfile=$pagesources{$link};
                        if (defined $linkfile) {
                                next if $rendered{$linkfile};
-                               debug(sprintf(gettext("rendering %s, to update its backlinks"), $linkfile));
+                               debug(sprintf(gettext("building %s, to update its backlinks"), $linkfile));
                                render($linkfile);
                                $rendered{$linkfile}=1;
                        }
@@ -496,7 +522,7 @@ sub refresh () { #{{{
                my $page=pagename($src);
                foreach my $file (@{$oldrenderedfiles{$page}}) {
                        if (! grep { $_ eq $file } @{$renderedfiles{$page}}) {
-                               debug(sprintf(gettext("removing %s, no longer rendered by %s"), $file, $page));
+                               debug(sprintf(gettext("removing %s, no longer built by %s"), $file, $page));
                                prune($config{destdir}."/".$file);
                        }
                }
@@ -508,9 +534,9 @@ sub refresh () { #{{{
        if (%rendered) {
                run_hooks(change => sub { shift->(keys %rendered) });
        }
-} #}}}
+}
 
-sub commandline_render () { #{{{
+sub commandline_render () {
        lockwiki();
        loadindex();
        unlockwiki();
@@ -520,7 +546,7 @@ sub commandline_render () { #{{{
        $file=~s/\Q$config{srcdir}\E\/?//;
 
        my $type=pagetype($file);
-       die sprintf(gettext("ikiwiki: cannot render %s"), $srcfile)."\n" unless defined $type;
+       die sprintf(gettext("ikiwiki: cannot build %s"), $srcfile)."\n" unless defined $type;
        my $content=readfile($srcfile);
        my $page=pagename($file);
        $pagesources{$page}=$file;
@@ -529,9 +555,10 @@ sub commandline_render () { #{{{
        $content=linkify($page, $page, $content);
        $content=htmlize($page, $page, $type, $content);
        $pagemtime{$page}=(stat($srcfile))[9];
+       $pagectime{$page}=$pagemtime{$page} if ! exists $pagectime{$page};
 
        print genpage($page, $content);
        exit 0;
-} #}}}
+}
 
 1
index 235e93eafa061219e96736787273106ee6a32225..6ee11209624a20a1a0080852b6f4a64dda756543 100644 (file)
@@ -1,15 +1,19 @@
 #!/usr/bin/perl
+# Ikiwiki setup files are perl files that 'use IkiWiki::Setup::foo',
+# passing it some sort of configuration data.
+
+package IkiWiki::Setup;
 
 use warnings;
 use strict;
 use IkiWiki;
 use open qw{:utf8 :std};
+use File::Spec;
 
-package IkiWiki;
+sub load ($) {
+       my $setup=IkiWiki::possibly_foolish_untaint(shift);
+       $config{setupfile}=File::Spec->rel2abs($setup);
 
-sub setup () { # {{{
-       my $setup=possibly_foolish_untaint($config{setup});
-       delete $config{setup};
        #translators: The first parameter is a filename, and the second
        #translators: is a (probably not translated) error message.
        open (IN, $setup) || error(sprintf(gettext("cannot read %s: %s"), $setup, $!));
@@ -23,8 +27,95 @@ sub setup () { # {{{
 
        eval $code;
        error("$setup: ".$@) if $@;
+}
+
+sub merge ($) {
+       # Merge setup into existing config and untaint.
+       my %setup=%{shift()};
+
+       if (exists $setup{add_plugins} && exists $config{add_plugins}) {
+               push @{$setup{add_plugins}}, @{$config{add_plugins}};
+       }
+       if (exists $setup{exclude}) {
+               push @{$config{wiki_file_prune_regexps}}, $setup{exclude};
+       }
+       foreach my $c (keys %setup) {
+               if (defined $setup{$c}) {
+                       if (! ref $setup{$c} || ref $setup{$c} eq 'Regexp') {
+                               $config{$c}=IkiWiki::possibly_foolish_untaint($setup{$c});
+                       }
+                       elsif (ref $setup{$c} eq 'ARRAY') {
+                               if ($c eq 'wrappers') {
+                                       # backwards compatability code
+                                       $config{$c}=$setup{$c};
+                               }
+                               else {
+                                       $config{$c}=[map { IkiWiki::possibly_foolish_untaint($_) } @{$setup{$c}}]
+                               }
+                       }
+                       elsif (ref $setup{$c} eq 'HASH') {
+                               foreach my $key (keys %{$setup{$c}}) {
+                                       $config{$c}{$key}=IkiWiki::possibly_foolish_untaint($setup{$c}{$key});
+                               }
+                       }
+               }
+               else {
+                       $config{$c}=undef;
+               }
+       }
+       
+       if (length $config{cgi_wrapper}) {
+               push @{$config{wrappers}}, {
+                       cgi => 1,
+                       wrapper => $config{cgi_wrapper},
+                       wrappermode => (defined $config{cgi_wrappermode} ? $config{cgi_wrappermode} : "06755"),
+               };
+       }
+}
+
+sub getsetup () {
+       # Gets all available setup data from all plugins. Returns an
+       # ordered list of [plugin, setup] pairs.
+       my @ret;
+
+        # disable logging to syslog while dumping, broken plugins may
+       # whine when loaded
+       my $syslog=$config{syslog};
+        $config{syslog}=undef;
+
+       # Load all plugins, so that all setup options are available.
+       my @plugins=grep { $_ ne $config{rcs} } sort(IkiWiki::listplugins());
+       unshift @plugins, $config{rcs} if $config{rcs}; # rcs plugin 1st
+       foreach my $plugin (@plugins) {
+               eval { IkiWiki::loadplugin($plugin) };
+               if (exists $IkiWiki::hooks{checkconfig}{$plugin}{call}) {
+                       my @s=eval { $IkiWiki::hooks{checkconfig}{$plugin}{call}->() };
+               }
+       }
+
+       foreach my $plugin (@plugins) {
+               if (exists $IkiWiki::hooks{getsetup}{$plugin}{call}) {
+                       # use an array rather than a hash, to preserve order
+                       my @s=eval { $IkiWiki::hooks{getsetup}{$plugin}{call}->() };
+                       next unless @s;
+                       push @ret, [ $plugin, \@s ],
+               }
+       }
+       
+        $config{syslog}=$syslog;
+
+       return @ret;
+}
+
+sub dump ($) {
+       my $file=IkiWiki::possibly_foolish_untaint(shift);
+       
+       require IkiWiki::Setup::Standard;
+       my @dump=IkiWiki::Setup::Standard::gendump("Setup file for ikiwiki.");
 
-       exit;
-} #}}}
+       open (OUT, ">", $file) || die "$file: $!";
+       print OUT "$_\n" foreach @dump;
+       close OUT;
+}
 
 1
diff --git a/IkiWiki/Setup/Automator.pm b/IkiWiki/Setup/Automator.pm
new file mode 100644 (file)
index 0000000..742d676
--- /dev/null
@@ -0,0 +1,194 @@
+#!/usr/bin/perl
+# Ikiwiki setup automator.
+
+package IkiWiki::Setup::Automator;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IkiWiki::UserInfo;
+use Term::ReadLine;
+use File::Path;
+use Encode;
+
+sub ask ($$) {
+       my ($question, $default)=@_;
+
+       my $r=Term::ReadLine->new("ikiwiki");
+       $r->readline(encode_utf8($question)." ", $default);
+}
+
+sub prettydir ($) {
+       my $dir=shift;
+       $dir=~s/^\Q$ENV{HOME}\E\//~\//;
+       return $dir;
+}
+
+sub import (@) {
+       my $this=shift;
+       IkiWiki::Setup::merge({@_});
+
+       # Sanitize this to avoid problimatic directory names.
+       $config{wikiname}=~s/[^-A-Za-z0-9_]//g;
+       if (! length $config{wikiname}) {
+               error gettext("you must enter a wikiname (that contains alphanumerics)");
+       }
+
+       # Avoid overwriting any existing files.
+       foreach my $key (qw{srcdir destdir repository dumpsetup}) {
+               next unless exists $config{$key};
+               my $add="";
+               my $dir=IkiWiki::dirname($config{$key})."/";
+               my $base=IkiWiki::basename($config{$key});
+               while (-e $dir.$add.$base) {
+                       $add=1 if ! $add;
+                       $add++;
+               }
+               $config{$key}=$dir.$add.$base;
+       }
+       
+       # Set up wrapper
+       if ($config{rcs}) {
+               if ($config{rcs} eq 'git') {
+                       $config{git_wrapper}=$config{repository}."/hooks/post-update";
+               }
+               elsif ($config{rcs} eq 'svn') {
+                       $config{svn_wrapper}=$config{repository}."/hooks/post-commit";
+               }
+               elsif ($config{rcs} eq 'monotone') {
+                       $config{mtn_wrapper}=$config{srcdir}."_MTN/ikiwiki-netsync-hook";
+               }
+               elsif ($config{rcs} eq 'darcs') {
+                       $config{darcs_wrapper}=$config{repository}."/_darcs/ikiwiki-wrapper";
+               }
+               elsif ($config{rcs} eq 'bzr') {
+                       # TODO
+               }
+               elsif ($config{rcs} eq 'mercurial') {
+                       # TODO
+               }
+               else {
+                       error sprintf(gettext("unsupported revision control system %s"),
+                               $config{rcs});
+               }
+       }
+
+       IkiWiki::checkconfig();
+
+       print "\n\nSetting up $config{wikiname} ...\n";
+
+       # Set up the srcdir.
+       mkpath($config{srcdir}) || die "mkdir $config{srcdir}: $!";
+       # Copy in example wiki.
+       if (exists $config{example}) {
+               # cp -R is POSIX
+               # Another reason not to use -a is so that pages such as blog
+               # posts will not have old creation dates on this new wiki.
+               system("cp -R $IkiWiki::installdir/share/ikiwiki/examples/$config{example}/* $config{srcdir}");
+               delete $config{example};
+       }
+
+       # Set up the repository.
+       delete $config{repository} if ! $config{rcs} || $config{rcs}=~/bzr|mercurial/;
+       if ($config{rcs}) {
+               my @params=($config{rcs}, $config{srcdir});
+               push @params, $config{repository} if exists $config{repository};
+               if (system("ikiwiki-makerepo", @params) != 0) {
+                       error gettext("failed to set up the repository with ikiwiki-makerepo");
+               }
+       }
+
+       # Make sure that all the listed plugins can load
+       # and checkconfig is ok. If a plugin fails to work,
+       # remove it from the configuration and keep on truckin'.
+       my %bakconfig=%config; # checkconfig can modify %config so back up
+       if (! eval { IkiWiki::loadplugins(); IkiWiki::checkconfig() }) {
+               foreach my $plugin (@{$config{default_plugins}}, @{$bakconfig{add_plugins}}) {
+                       eval {
+                               # delete all hooks so that only this plugins's
+                               # checkconfig will be run
+                               %IkiWiki::hooks=();
+                               IkiWiki::loadplugin($plugin);
+                               IkiWiki::run_hooks(checkconfig => sub { shift->() });
+                       };
+                       if ($@) {
+                               print STDERR sprintf(gettext("** Disabling plugin %s, since it is failing with this message:"),
+                                       $plugin)."\n";
+                               print STDERR "$@\n";
+                               push @{$bakconfig{disable_plugins}}, $plugin;
+                       }
+               }
+       }
+       %config=%bakconfig;
+
+       # Generate setup file.
+       require IkiWiki::Setup;
+       IkiWiki::Setup::dump($config{dumpsetup});
+
+       # Build the wiki, but w/o wrappers, so it's not live yet.
+       mkpath($config{destdir}) || die "mkdir $config{destdir}: $!";
+       if (system("ikiwiki", "--refresh", "--setup", $config{dumpsetup}) != 0) {
+               die "ikiwiki --refresh --setup $config{dumpsetup} failed";
+       }
+
+       # Create admin user(s).
+       foreach my $admin (@{$config{adminuser}}) {
+               next if $admin=~/^http\?:\/\//; # openid
+               
+               # Prompt for password w/o echo.
+               my ($password, $password2);
+               system('stty -echo 2>/dev/null');
+               local $|=1;
+               print "\n\nCreating wiki admin $admin ...\n";
+               for (;;) {
+                       print "Choose a password: ";
+                       chomp($password=<STDIN>);
+                       print "\n";
+                       print "Confirm password: ";
+                       chomp($password2=<STDIN>);
+
+                       last if $password2 eq $password;
+
+                       print "Password mismatch.\n\n";
+               }
+               print "\n\n\n";
+               system('stty sane 2>/dev/null');
+
+               if (IkiWiki::userinfo_setall($admin, { regdate => time }) &&
+                   IkiWiki::Plugin::passwordauth::setpassword($admin, $password)) {
+                       IkiWiki::userinfo_set($admin, "email", $config{adminemail}) if defined $config{adminemail};
+               }
+               else {
+                       error("problem setting up $admin user");
+               }
+       }
+       
+       # Add wrappers, make live.
+       if (system("ikiwiki", "--wrappers", "--setup", $config{dumpsetup}) != 0) {
+               die "ikiwiki --wrappers --setup $config{dumpsetup} failed";
+       }
+
+       # Add it to the wikilist.
+       mkpath("$ENV{HOME}/.ikiwiki");
+       open (WIKILIST, ">>$ENV{HOME}/.ikiwiki/wikilist") || die "$ENV{HOME}/.ikiwiki/wikilist: $!";
+       print WIKILIST "$ENV{USER} $config{dumpsetup}\n";
+       close WIKILIST;
+       if (system("ikiwiki-update-wikilist") != 0) {
+               print STDERR "** Failed to add you to the system wikilist file.\n";
+               print STDERR "** (Probably ikiwiki-update-wikilist is not SUID root.)\n";
+               print STDERR "** Your wiki will not be automatically updated when ikiwiki is upgraded.\n";
+       }
+       
+       # Done!
+       print "\n\nSuccessfully set up $config{wikiname}:\n";
+       foreach my $key (qw{url srcdir destdir repository}) {
+               next unless exists $config{$key};
+               print "\t$key: ".(" " x (10 - length($key)))." ".
+                       prettydir($config{$key})."\n";
+       }
+       print "To modify settings, edit ".prettydir($config{dumpsetup})." and then run:\n";
+       print " ikiwiki -setup ".prettydir($config{dumpsetup})."\n";
+       exit 0;
+}
+
+1
index 0a34968855a2cd26ac4609d27b73b2d0e440ea76..951bcfc56febfce724d82c652f96468c227709d2 100644 (file)
 # Parameters to import should be all the standard ikiwiki config stuff,
 # plus an array of wrappers to set up.
 
+package IkiWiki::Setup::Standard;
+
 use warnings;
 use strict;
-use IkiWiki::Wrapper;
-use IkiWiki::Render;
-
-package IkiWiki::Setup::Standard;
+use IkiWiki;
 
 sub import {
-       IkiWiki::setup_standard(@_);
+       IkiWiki::Setup::merge($_[1]);
 }
-       
-package IkiWiki;
-
-sub setup_standard {
-       my %setup=%{$_[1]};
 
-       $setup{plugin}=$config{plugin};
-       if (exists $setup{add_plugins}) {
-               push @{$setup{plugin}}, @{$setup{add_plugins}};
-               delete $setup{add_plugins};
+sub dumpline ($$$$) {
+       my $key=shift;
+       my $value=shift;
+       my $type=shift;
+       my $prefix=shift;
+       
+       eval q{use Data::Dumper};
+       error($@) if $@;
+       local $Data::Dumper::Terse=1;
+       local $Data::Dumper::Indent=1;
+       local $Data::Dumper::Pad="\t";
+       local $Data::Dumper::Sortkeys=1;
+       local $Data::Dumper::Quotekeys=0;
+       # only the perl version preserves utf-8 in output
+       local $Data::Dumper::Useperl=1;
+       
+       my $dumpedvalue;
+       if (($type eq 'boolean' || $type eq 'integer') && $value=~/^[0-9]+$/) {
+               # avoid quotes
+               $dumpedvalue=$value;
        }
-       if (exists $setup{exclude}) {
-               push @{$config{wiki_file_prune_regexps}}, $setup{exclude};
+       elsif (ref $value eq 'ARRAY' && @$value && ! grep { /[^\S]/ } @$value) {
+               # dump simple array as qw{}
+               $dumpedvalue="[qw{".join(" ", @$value)."}]";
        }
-
-       if (! $config{render} && (! $config{refresh} || $config{wrappers})) {
-               debug(gettext("generating wrappers.."));
-               my @wrappers=@{$setup{wrappers}};
-               delete $setup{wrappers};
-               my %startconfig=(%config);
-               foreach my $wrapper (@wrappers) {
-                       %config=(%startconfig, rebuild => 0, verbose => 0, %setup, %{$wrapper});
-                       checkconfig();
-                       if (! $config{cgi} && ! $config{post_commit}) {
-                               $config{post_commit}=1;
+       else {
+               $dumpedvalue=Dumper($value);
+               chomp $dumpedvalue;
+               if (length $prefix) {
+                       # add to second and subsequent lines
+                       my @lines=split(/\n/, $dumpedvalue);
+                       $dumpedvalue="";
+                       for (my $x=0; $x <= $#lines; $x++) {
+                               $lines[$x] =~ s/^\t//;
+                               $dumpedvalue.="\t".($x ? $prefix : "").$lines[$x]."\n";
                        }
-                       gen_wrapper();
                }
-               %config=(%startconfig);
+               $dumpedvalue=~s/^\t//;
+               chomp $dumpedvalue;
        }
        
-       foreach my $c (keys %setup) {
-               next if $c eq 'syslog';
-               if (defined $setup{$c}) {
-                       if (! ref $setup{$c}) {
-                               $config{$c}=possibly_foolish_untaint($setup{$c});
-                       }
-                       elsif (ref $setup{$c} eq 'ARRAY') {
-                               $config{$c}=[map { possibly_foolish_untaint($_) } @{$setup{$c}}]
-                       }
-                       elsif (ref $setup{$c} eq 'HASH') {
-                               foreach my $key (keys %{$setup{$c}}) {
-                                       $config{$c}{$key}=possibly_foolish_untaint($setup{$c}{$key});
-                               }
-                       }
+       return "\t$prefix$key => $dumpedvalue,";
+}
+
+sub dumpvalues ($@) {
+       my $setup=shift;
+       my @ret;
+       while (@_) {
+               my $key=shift;
+               my %info=%{shift()};
+
+               next if $key eq "plugin" || $info{type} eq "internal";
+               
+               push @ret, "\t# ".$info{description} if exists $info{description};
+               
+               if (exists $setup->{$key} && defined $setup->{$key}) {
+                       push @ret, dumpline($key, $setup->{$key}, $info{type}, "");
+                       delete $setup->{$key};
+               }
+               elsif (exists $info{example}) {
+                       push @ret, dumpline($key, $info{example}, $info{type}, "#");
                }
                else {
-                       $config{$c}=undef;
+                       push @ret, dumpline($key, "", $info{type}, "#");
                }
        }
-       
-       if (! $config{refresh}) {
-               $config{rebuild}=1;
-       }
-       
-       loadplugins();
-       checkconfig();
+       return @ret;
+}
 
-       if ($config{render}) {
-               commandline_render();
-       }
+sub gendump ($) {
+       my $description=shift;
+       my %setup=(%config);
+       my @ret;
+       
+       # disable logging to syslog while dumping
+       $config{syslog}=undef;
 
-       if (! $config{refresh}) {
-               debug(gettext("rebuilding wiki.."));
-       }
-       else {
-               debug(gettext("refreshing wiki.."));
+       push @ret, dumpvalues(\%setup, IkiWiki::getsetup());
+       foreach my $pair (IkiWiki::Setup::getsetup()) {
+               my $plugin=$pair->[0];
+               my $setup=$pair->[1];
+               my @values=dumpvalues(\%setup, @{$setup});
+               if (@values) {
+                       push @ret, "", "\t# $plugin plugin", @values;
+               }
        }
 
-       lockwiki();
-       loadindex();
-       refresh();
+       unshift @ret,
+               "#!/usr/bin/perl",
+               "# $description",
+               "#",
+               "# Passing this to ikiwiki --setup will make ikiwiki generate",
+               "# wrappers and build the wiki.",
+               "#",
+               "# Remember to re-run ikiwiki --setup any time you edit this file.",
+               "use IkiWiki::Setup::Standard {";
+       push @ret, "}";
 
-       debug(gettext("done"));
-       saveindex();
+       return @ret;
 }
 
 1
index a0b1327b44fdeac0b3b37e46e863de95a0ad360e..0bf100a959c934d23c8f73ac1f0962f856732a35 100644 (file)
@@ -1,18 +1,18 @@
 #!/usr/bin/perl
 
+package IkiWiki;
+
 use warnings;
 use strict;
 use Storable;
 use IkiWiki;
 
-package IkiWiki;
-
-sub userinfo_retrieve () { #{{{
+sub userinfo_retrieve () {
        my $userinfo=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") };
        return $userinfo;
-} #}}}
+}
 
-sub userinfo_store ($) { #{{{
+sub userinfo_store ($) {
        my $userinfo=shift;
        
        my $newfile="$config{wikistatedir}/userdb.new";
@@ -26,9 +26,9 @@ sub userinfo_store ($) { #{{{
                }
        }
        return $ret;
-} #}}}
+}
 
-sub userinfo_get ($$) { #{{{
+sub userinfo_get ($$) {
        my $user=shift;
        my $field=shift;
 
@@ -39,9 +39,9 @@ sub userinfo_get ($$) { #{{{
                return "";
        }
        return $userinfo->{$user}->{$field};
-} #}}}
+}
 
-sub userinfo_set ($$$) { #{{{
+sub userinfo_set ($$$) {
        my $user=shift;
        my $field=shift;
        my $value=shift;
@@ -54,9 +54,9 @@ sub userinfo_set ($$$) { #{{{
        
        $userinfo->{$user}->{$field}=$value;
        return userinfo_store($userinfo);
-} #}}}
+}
 
-sub userinfo_setall ($$) { #{{{
+sub userinfo_setall ($$) {
        my $user=shift;
        my $info=shift;
        
@@ -66,30 +66,12 @@ sub userinfo_setall ($$) { #{{{
        }
        $userinfo->{$user}=$info;
        return userinfo_store($userinfo);
-} #}}}
+}
 
-sub is_admin ($) { #{{{
+sub is_admin ($) {
        my $user_name=shift;
 
        return grep { $_ eq $user_name } @{$config{adminuser}};
-} #}}}
-
-sub get_banned_users () { #{{{
-       my @ret;
-       my $userinfo=userinfo_retrieve();
-       foreach my $user (keys %{$userinfo}) {
-               push @ret, $user if $userinfo->{$user}->{banned};
-       }
-       return @ret;
-} #}}}
-
-sub set_banned_users (@) { #{{{
-       my %banned=map { $_ => 1 } @_;
-       my $userinfo=userinfo_retrieve();
-       foreach my $user (keys %{$userinfo}) {
-               $userinfo->{$user}->{banned} = $banned{$user};
-       }
-       return userinfo_store($userinfo);
-} #}}}
+}
 
 1
index 90a4c46c79141419c872e2f64102658f41dcefda..6555fe625f8e542e786f3b6d7d05a72772ea207f 100644 (file)
@@ -1,17 +1,17 @@
 #!/usr/bin/perl
 
+package IkiWiki;
+
 use warnings;
 use strict;
-use Cwd q{abs_path};
-use Data::Dumper ;
+use File::Spec;
+use Data::Dumper;
 use IkiWiki;
 
-package IkiWiki;
-
-sub gen_wrapper () { #{{{
-       $config{srcdir}=abs_path($config{srcdir});
-       $config{destdir}=abs_path($config{destdir});
-       my $this=abs_path($0);
+sub gen_wrapper () {
+       $config{srcdir}=File::Spec->rel2abs($config{srcdir});
+       $config{destdir}=File::Spec->rel2abs($config{destdir});
+       my $this=File::Spec->rel2abs($0);
        if (! -x $this) {
                error(sprintf(gettext("%s doesn't seem to be executable"), $this));
        }
@@ -28,34 +28,84 @@ sub gen_wrapper () { #{{{
        my @envsave;
        push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI
                       CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE
-                      HTTP_COOKIE REMOTE_USER} if $config{cgi};
+                      HTTP_COOKIE REMOTE_USER HTTPS REDIRECT_STATUS
+                      REDIRECT_URL} if $config{cgi};
        my $envsave="";
        foreach my $var (@envsave) {
-               $envsave.=<<"EOF"
+               $envsave.=<<"EOF";
        if ((s=getenv("$var")))
                addenv("$var", s);
 EOF
        }
-       
+
+       my $test_receive="";
+       if ($config{test_receive}) {
+               require IkiWiki::Receive;
+               $test_receive=IkiWiki::Receive::gen_wrapper();
+       }
+
+       my $check_commit_hook="";
+       my $pre_exec="";
+       if ($config{post_commit}) {
+               # Optimise checking !commit_hook_enabled() , 
+               # so that ikiwiki does not have to be started if the
+               # hook is disabled.
+               #
+               # Note that perl's flock may be implemented using fcntl
+               # or lockf on some systems. If so, and if there is no
+               # interop between the locking systems, the true C flock will
+               # always succeed, and this optimisation won't work.
+               # The perl code will later correctly check the lock,
+               # so the right thing will still happen, though without
+               # the benefit of this optimisation.
+               $check_commit_hook=<<"EOF";
+       {
+               int fd=open("$config{wikistatedir}/commitlock", O_CREAT | O_RDWR, 0666);
+               if (fd != -1) {
+                       if (flock(fd, LOCK_SH | LOCK_NB) != 0)
+                               exit(0);
+                       close(fd);
+               }
+       }
+EOF
+       }
+       elsif ($config{cgi}) {
+               # Avoid more than one ikiwiki cgi running at a time by
+               # taking a cgi lock. Since ikiwiki uses several MB of
+               # memory, a pile up of processes could cause thrashing
+               # otherwise. The fd of the lock is stored in
+               # IKIWIKI_CGILOCK_FD so unlockwiki can close it.
+               $pre_exec=<<"EOF";
+       {
+               int fd=open("$config{wikistatedir}/cgilock", O_CREAT | O_RDWR, 0666);
+               if (fd != -1 && flock(fd, LOCK_EX) == 0) {
+                       char *fd_s;
+                       asprintf(&fd_s, "%i", fd);
+                       setenv("IKIWIKI_CGILOCK_FD", fd_s, 1);
+               }
+       }
+EOF
+       }
+
        $Data::Dumper::Indent=0; # no newlines
        my $configstring=Data::Dumper->Dump([\%config], ['*config']);
        $configstring=~s/\\/\\\\/g;
        $configstring=~s/"/\\"/g;
        $configstring=~s/\n/\\n/g;
        
-       #translators: The first parameter is a filename, and the second is
-       #translators: a (probably not translated) error message.
-       open(OUT, ">$wrapper.c") || error(sprintf(gettext("failed to write %s: %s"), "$wrapper.c", $!));;
-       print OUT <<"EOF";
+       writefile(basename("$wrapper.c"), dirname($wrapper), <<"EOF");
 /* A wrapper for ikiwiki, can be safely made suid. */
 #include <stdio.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/file.h>
 
 extern char **environ;
-char *newenviron[$#envsave+5];
+char *newenviron[$#envsave+6];
 int i=0;
 
 addenv(char *var, char *val) {
@@ -67,8 +117,10 @@ addenv(char *var, char *val) {
 }
 
 int main (int argc, char **argv) {
-       /* Sanitize environment. */
        char *s;
+
+$check_commit_hook
+$test_receive
 $envsave
        newenviron[i++]="HOME=$ENV{HOME}";
        newenviron[i++]="WRAPPED_OPTIONS=$configstring";
@@ -86,6 +138,7 @@ $envsave
                exit(1);
        }
 
+$pre_exec
        execl("$this", "$this", NULL);
        perror("exec $this");
        exit(1);
@@ -118,6 +171,6 @@ EOF
        #translators: The parameter is a filename.
        printf(gettext("successfully generated %s"), $wrapper);
        print "\n";
-} #}}}
+}
 
 1
index 8c7ac70190ad26eba142abe79bb3a703036dd27e..0208131770ccc110ea306dc9be0bb45afe6ee98e 100755 (executable)
@@ -23,36 +23,63 @@ PROBABLE_INST_LIB=$(shell \\
        fi \\
 )
 
+# Additional configurable path variables.
+W3M_CGI_BIN?=$(PREFIX)/lib/w3m/cgi-bin
+
 tflag=$(shell if [ -n "$$NOTAINT" ] && [ "$$NOTAINT" != 1 ]; then printf -- "-T"; fi)
-extramodules=$(shell if [ "$$PROFILE" = 1 ]; then printf -- "-d:Profile"; fi)
+extramodules=$(shell if [ "$$PROFILE" = 1 ]; then printf -- "-d:NYTProf"; fi)
 
 ikiwiki.out: ikiwiki.in
        ./pm_filter $(PREFIX) $(VER) $(PROBABLE_INST_LIB) < ikiwiki.in > ikiwiki.out
        chmod +x ikiwiki.out
 
-extra_build: ikiwiki.out
-       $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -setup docwiki.setup -refresh
+ikiwiki.setup: ikiwiki.out
+       HOME=/home/me $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -dumpsetup ikiwiki.setup
+
+extra_build: ikiwiki.out ikiwiki.setup docwiki
        ./mdwn2man ikiwiki 1 doc/usage.mdwn > ikiwiki.man
        ./mdwn2man ikiwiki-mass-rebuild 8 doc/ikiwiki-mass-rebuild.mdwn > ikiwiki-mass-rebuild.man
        ./mdwn2man ikiwiki-makerepo 1 doc/ikiwiki-makerepo.mdwn > ikiwiki-makerepo.man
        ./mdwn2man ikiwiki-transition 1 doc/ikiwiki-transition.mdwn > ikiwiki-transition.man
        ./mdwn2man ikiwiki-update-wikilist 1 doc/ikiwiki-update-wikilist.mdwn > ikiwiki-update-wikilist.man
-       $(MAKE) -C po mo
+       $(MAKE) -C po
+       
+docwiki: ikiwiki.out
+       $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -setup docwiki.setup -refresh
 
 extra_clean:
        rm -rf html doc/.ikiwiki
-       rm -f *.man ikiwiki.out
-       rm -f plugins/*.pyc
+       rm -f *.man ikiwiki.out ikiwiki.setup plugins/*.pyc
        $(MAKE) -C po clean
 
-extra_install:
+underlay_install:
        install -d $(DESTDIR)$(PREFIX)/share/ikiwiki
        for dir in `cd underlays && find . -follow -type d ! -regex '.*\.svn.*'`; do \
                install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/$$dir; \
                for file in `find underlays/$$dir -follow -maxdepth 1 -type f`; do \
+                       cp -aL $$file $(DESTDIR)$(PREFIX)/share/ikiwiki/$$dir 2>/dev/null || \
                        install -m 644 $$file $(DESTDIR)$(PREFIX)/share/ikiwiki/$$dir; \
                done; \
        done
+
+       # The directive docs become their own special underlay.
+       install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/directives/ikiwiki/directive
+       for file in doc/ikiwiki/directive/*; do \
+               if [ -f "$$file" ]; then \
+                       install -m 644 $$file $(DESTDIR)$(PREFIX)/share/ikiwiki/directives/ikiwiki/directive; \
+               fi \
+       done
+       
+extra_install: underlay_install
+       # Install example sites.
+       for dir in `cd doc/examples; find . -type d ! -regex '.*\.svn.*'`; do \
+               install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/examples/$$dir; \
+       done
+       for file in `cd doc/examples; find . -type f ! -regex '.*\.svn.*'`; do \
+               cp -aL doc/examples/$$file $(DESTDIR)$(PREFIX)/share/ikiwiki/examples/$$file 2>/dev/null || \
+               install -m 644 doc/examples/$$file $(DESTDIR)$(PREFIX)/share/ikiwiki/examples/$$file; \
+       done
+
        for dir in `find templates -follow -type d ! -regex '.*\.svn.*'`; do \
                install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/$$dir; \
                for file in `find $$dir -follow -maxdepth 1 -type f`; do \
@@ -61,9 +88,12 @@ extra_install:
        done
        
        install -d $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins
-       for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\*`; do \
+       for file in `find plugins -maxdepth 1 -type f ! -path plugins/.\* ! -name \*demo\* -name \*.py`; do \
+               install -m 644 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+       done
+       for file in `find plugins -maxdepth 1 -type f ! -path plugins/.\* ! -name \*demo\* ! -name \*.py ! -name \*.pyc`; do \
                install -m 755 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
-       done; \
+       done
 
        install -d $(DESTDIR)$(PREFIX)/share/man/man1
        install -m 644 ikiwiki.man $(DESTDIR)$(PREFIX)/share/man/man1/ikiwiki.1
@@ -77,14 +107,21 @@ extra_install:
        install -d $(DESTDIR)$(PREFIX)/sbin
        install ikiwiki-mass-rebuild $(DESTDIR)$(PREFIX)/sbin
 
-       install -d $(DESTDIR)$(PREFIX)/lib/w3m/cgi-bin
-       install ikiwiki-w3m.cgi $(DESTDIR)$(PREFIX)/lib/w3m/cgi-bin
+       install -d $(DESTDIR)$(W3M_CGI_BIN)
+       install ikiwiki-w3m.cgi $(DESTDIR)$(W3M_CGI_BIN)
 
        install -d $(DESTDIR)$(PREFIX)/bin
        install ikiwiki.out $(DESTDIR)$(PREFIX)/bin/ikiwiki
        install ikiwiki-makerepo ikiwiki-transition ikiwiki-update-wikilist $(DESTDIR)$(PREFIX)/bin/
 
        $(MAKE) -C po install DESTDIR=$(DESTDIR) PREFIX=$(PREFIX)
+       
+       # These might fail if a regular user is installing into a home
+       # directory.
+       -install -d $(DESTDIR)/etc/ikiwiki
+       -install -m 0644 wikilist $(DESTDIR)/etc/ikiwiki
+       -install -m 0644 auto.setup $(DESTDIR)/etc/ikiwiki
+       -install -m 0644 auto-blog.setup $(DESTDIR)/etc/ikiwiki
 }
 }
 
@@ -94,16 +131,16 @@ WriteMakefile(
        PM_FILTER       => './pm_filter $(PREFIX) $(VER) $(PROBABLE_INST_LIB)',
        MAN1PODS        => {},
        PREREQ_PM       => {
-               'XML::Simple'           => 0,
-               'Text::Markdown'        => 0,
-               'Date::Parse'           => 0,
-               'HTML::Template'        => 0,
-               'HTML::Scrubber'        => 0,
-               'CGI::FormBuilder'      => 3.02.02,
-               'CGI::Session'          => 0,
-               'Mail::Sendmail'        => 0,
-               'HTML::Parser'          => 0,
-               'URI'                   => 0,
-               'Data::Dumper'          => 2.11,
+               'XML::Simple'           => "0",
+               'Text::Markdown'        => "0",
+               'Date::Parse'           => "0",
+               'HTML::Template'        => "0",
+               'HTML::Scrubber'        => "0",
+               'CGI::FormBuilder'      => "3.02.02",
+               'CGI::Session'          => "0",
+               'Mail::Sendmail'        => "0",
+               'HTML::Parser'          => "0",
+               'URI'                   => "0",
+               'Data::Dumper'          => "2.11",
        },
 );
diff --git a/README b/README
index d4be0455a6085c43c3ae5a5e387d811f93606933..a4dc0d641dbfd7a7bf13995f5ef111f0977563aa 100644 (file)
--- a/README
+++ b/README
@@ -1,16 +1,23 @@
 Use ./Makefile.PL to generate a Makefile, "make" will build the
 documentation wiki and a man page, and "make install" will install ikiwiki.
 
+All other documentation is in the ikiwiki documentation wiki, which is also
+available online at <http://ikiwiki.info/>
+
+
 A few special variables you can set while using the Makefile:
 
-PROFILE=1 turns on profiling for the build of the doc wiki. Uses Devel::Profile
+  PROFILE=1 turns on profiling for the build of the doc wiki.
+  (Uses Devel::NYTProf)
 
-NOTAINT=0 turns on the taint flag in the ikiwiki program. (Not recommended
-unless your perl is less buggy than mine -- see
-http://bugs.debian.org/411786)
+  NOTAINT=0 turns on the taint flag in the ikiwiki program. (Not recommended
+  unless your perl is less buggy than mine -- see
+  http://bugs.debian.org/411786)
 
-There are also other variables supported by MakeMaker, including PREFIX,
-INSTALL_BASE, and DESTDIR. See ExtUtils::MakeMaker(3).
+  There are also other variables supported by MakeMaker, including PREFIX,
+  INSTALL_BASE, and DESTDIR. See ExtUtils::MakeMaker(3).
 
-All other documentation is in the ikiwiki documentation wiki, which is also
-available online at <http://ikiwiki.info/>
+  In particular, INSTALL_BASE is very useful if you want to install ikiwiki
+  to some other location, as it configures it to see the perl libraries
+  there. See `doc/tips/nearlyfreespeech.mdwn` for an example of using this to
+  install ikiwiki and its dependencies in a home directory.
diff --git a/auto-blog.setup b/auto-blog.setup
new file mode 100644 (file)
index 0000000..3ef734b
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+# Ikiwiki setup automator -- blog version.
+# 
+# This setup file causes ikiwiki to create a wiki, containing a blog,
+# check it into revision control, generate a setup file for the new
+# wiki, and set everything up.
+#
+# Just run: ikiwiki -setup /etc/ikiwiki/auto-blog.setup
+#
+# By default, it asks a few questions, and confines itself to the user's home
+# directory. You can edit it to change what it asks questions about, or to
+# modify the values to use site-specific settings.
+
+require IkiWiki::Setup::Automator;
+
+our $wikiname=IkiWiki::Setup::Automator::ask(
+       gettext("What will the blog be named?"), gettext("blog"));
+our $rcs=IkiWiki::Setup::Automator::ask(
+       gettext("What revision control system to use?"), "git");
+our $admin=IkiWiki::Setup::Automator::ask(
+       gettext("What wiki user (or openid) will be admin?"), $ENV{USER});
+use Net::Domain q{hostfqdn};
+our $domain=hostfqdn() || ikiwiki::setup::automator::ask(
+       gettext("What is the domain name of the web server?"), "");
+
+IkiWiki::Setup::Automator->import(
+       wikiname => $wikiname,
+       adminuser => [$admin],
+       rcs => $rcs,
+       srcdir => "$ENV{HOME}/$wikiname",
+       destdir => "$ENV{HOME}/public_html/$wikiname",
+       repository => "$ENV{HOME}/$wikiname.".($rcs eq "monotone" ? "mtn" : $rcs),
+       dumpsetup => "$ENV{HOME}/$wikiname.setup",
+       url => "http://$domain/~$ENV{USER}/$wikiname",
+       cgiurl => "http://$domain/~$ENV{USER}/$wikiname/ikiwiki.cgi",
+       cgi_wrapper => "$ENV{HOME}/public_html/$wikiname/ikiwiki.cgi",
+       adminemail => "$ENV{USER}\@$domain",
+       add_plugins => [qw{goodstuff websetup comments blogspam}],
+       disable_plugins => [qw{}],
+       libdir => "$ENV{HOME}/.ikiwiki",
+       rss => 1,
+       atom => 1,
+       syslog => 1,
+       
+       example => "blog",
+       comments_pagespec => "posts/* and !*/Discussion",
+       blogspam_pagespec => "postcomment(*)",
+       discussion => 0,
+)
diff --git a/auto.setup b/auto.setup
new file mode 100644 (file)
index 0000000..b3d2513
--- /dev/null
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+# Ikiwiki setup automator.
+# 
+# This setup file causes ikiwiki to create a wiki, check it into revision
+# control, generate a setup file for the new wiki, and set everything up.
+#
+# Just run: ikiwiki -setup /etc/ikiwiki/auto.setup
+#
+# By default, it asks a few questions, and confines itself to the user's home
+# directory. You can edit it to change what it asks questions about, or to
+# modify the values to use site-specific settings.
+
+require IkiWiki::Setup::Automator;
+
+our $wikiname=IkiWiki::Setup::Automator::ask(
+       gettext("What will the wiki be named?"), gettext("wiki"));
+our $rcs=IkiWiki::Setup::Automator::ask(
+       gettext("What revision control system to use?"), "git");
+our $admin=IkiWiki::Setup::Automator::ask(
+       gettext("Which user (wiki account or openid) will be admin?"), $ENV{USER});
+use Net::Domain q{hostfqdn};
+our $domain=hostfqdn() || ikiwiki::setup::automator::ask(
+       gettext("What is the domain name of the web server?"), "");
+
+IkiWiki::Setup::Automator->import(
+       wikiname => $wikiname,
+       adminuser => [$admin],
+       rcs => $rcs,
+       srcdir => "$ENV{HOME}/$wikiname",
+       destdir => "$ENV{HOME}/public_html/$wikiname",
+       repository => "$ENV{HOME}/$wikiname.".($rcs eq "monotone" ? "mtn" : $rcs),
+       dumpsetup => "$ENV{HOME}/$wikiname.setup",
+       url => "http://$domain/~$ENV{USER}/$wikiname",
+       cgiurl => "http://$domain/~$ENV{USER}/$wikiname/ikiwiki.cgi",
+       cgi_wrapper => "$ENV{HOME}/public_html/$wikiname/ikiwiki.cgi",
+       adminemail => "$ENV{USER}\@$domain",
+       add_plugins => [qw{goodstuff websetup}],
+       disable_plugins => [qw{}],
+       libdir => "$ENV{HOME}/.ikiwiki",
+       rss => 1,
+       atom => 1,
+       syslog => 1,
+)
index 4aac33b809bf41080d4e1a3816141365664f74de..535708872993b5e4d8edb2a4be594dba6ca82c15 100644 (file)
@@ -1,3 +1,97 @@
+ikiwiki (3.1415926) UNRELEASED; urgency=low
+
+  In order to fix a performance bug, all wikis need to be rebuilt on
+  upgrade to this version. If you listed your wiki in
+  /etc/ikiwiki/wikilist this will be done automatically when the
+  Debian package is upgraded. Or use ikiwiki-mass-rebuild to force
+  a rebuild.
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 25 Aug 2009 17:24:43 -0400
+
+ikiwiki (3.13) unstable; urgency=low
+
+  The `ikiwiki-transition deduplinks` command introduced in the
+  last release was buggy. If you followed the NEWS file instructions
+  and ran it, you should run `ikiwiki -setup` to rebuild your wiki
+  to fix the problem.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 22 May 2009 13:04:02 -0400
+
+ikiwiki (3.12) unstable; urgency=low
+
+  You may want to run `ikiwiki-transition deduplinks your.setup`
+  after upgrading to this version of ikiwiki. This command will
+  optimise your wiki's saved state, removing duplicate information
+  that can slow ikiwiki down.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 06 May 2009 00:25:06 -0400
+
+ikiwiki (3.01) unstable; urgency=low
+
+  If your wiki uses git, and you have a `diffurl` configured in
+  its setup file, you should be aware that gitweb has stopped
+  supporting the url form commonly used for the `diffurl`.
+
+  You can change your setup to use the newer gitweb url form:
+
+    http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;f=[[file]];h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_commit]];hpb=[[sha1_parent]]
+
+  The changes from the old form are the addition of the `hpb` parameter,
+  and the change to the value used for the `hb` parameter.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 05 Jan 2009 18:18:05 -0500
+
+ikiwiki (3.00) unstable; urgency=low
+
+  The 3.0 release of ikiwiki changes several defaults and finishes
+  some transitions. You will need to modify your wikis to work with
+  ikiwiki 3.0. A document explaining the process is available
+  in </usr/share/doc/ikiwiki/html/tips/upgrade_to_3.0.html>
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 23 Dec 2008 16:14:18 -0500
+
+ikiwiki (2.62) unstable; urgency=low
+
+  TexImg standard preamble changed
+
+  The teximg plugin now has a configurable LaTeX preamble.
+  As part of this change the `mchem` LaTeX package has been removed from
+  the default LaTeX preamble as it wasn't included in many TeX installations.
+
+  The previous behaviour can be restored by adding the following to your
+  ikiwiki setup:
+
+        teximg_prefix => '\documentclass{scrartcl}
+                \usepackage[version=3]{mhchem}
+                \usepackage{amsmath}
+                \usepackage{amsfonts}
+                \usepackage{amssymb}
+                \pagestyle{empty}
+                \begin{document}',
+
+  In addition, the rendering mechanism has been changed to use `dvipng` by
+  default, if available.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 24 Aug 2008 15:00:40 -0400
+
+ikiwiki (2.60) unstable; urgency=low
+
+  Admin preferences are moving from the web interface to the setup file.
+  There are three new options in the setup file: `locked_pages`, `banned_users`,
+  and `allowed_attachments`. The admin prefs page can still be used, but
+  that's deprecated, and the prefs will be hidden if a value is not already
+  set. If a value is set in the web interface, you're encouraged to move that
+  setting to your setup file now, since version 3.0 will remove the deprecated
+  admin prefs web interface.
+
+  Also, the layout of the setup file has changed in a significant way in this
+  release. Old setup files will continue to work, but new features, like the
+  new websetup interface, require a new format setup file. You can convert
+  old setup files into the new format by running 
+  `ikiwiki-transition setupformat ikiwiki.setup`
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 01 Aug 2008 17:02:14 -0400
+
 ikiwiki (2.52) unstable; urgency=low
 
   All wikis need to be rebuilt on upgrade to this version. If you listed your
@@ -59,10 +153,7 @@ ikiwiki (2.40) unstable; urgency=low
   in their setup files.
 
   To convert your wiki to the new syntax, ikiwiki provides a new script
-  ikiwiki-transition.  It will convert preprocessor directives in
-  all files given on the command line.  To convert an entire wiki:
-
-  find wikidir/ -type f -name '*.mdwn' -print0 | xargs -0 ikiwiki-transition prefix_directives
+  ikiwiki-transition.
 
   Even with prefix_directives disabled, ikiwiki now allows an optional '!'
   prefix on preprocessor directives (but still requires a space).  Thus, a
index 8d404f32f1d8f51534a54d5500e843ad9e0883b0..8cd5032cde7b6775b69a5f679881a291c1fe1e10 100644 (file)
@@ -1,9 +1,834 @@
-ikiwiki (2.53) UNRELEASED; urgency=low
+ikiwiki (3.1415926) UNRELEASED; urgency=low
+
+  * po: Detect if nowrapi18n can't be passed to po4a, and warn about
+    the old version, but continue. Closes: #541205 
+  * inline: Avoid use of my $_ as it fails with older perls.
+    Closes: #541215
+  * Add discussionpage configuration setting.
+  * Several optimisations, including speedups to orphans and brokenlinks
+    calculation.
+  * meta, img: Fix bugs in dependency code. (smcv)
+  * Allow building ikiwiki on systems w/o po4a --
+    building of the translated underlays will be skipped in this case.
+  * Add basic styling of po plugin's languages list.
+  * inline: Display an error if feedpages is specified and fails to match
+    due to a problem such as created_before being told to check against
+    a page that does not exist.
+  * Remove deprecated ikiwiki/blog and ikiwiki/preprocessordirective
+    pages from the basewiki.
+  * Updated French program translation from Philippe Batailler.
+    Closes: #542036
+  * po: Fixed to run rcs_add ralative to srcdir.
+  * Italian program translation from Luca Bruno.
+  * Fix example blog's tags/life to not have a broken PageSpec.
+    Closes: #543510
+  * Optimize the dependencies list. This also fixes a bug
+    that could cause repeated refreshes of the wiki to grow
+    increasingly larger dependency lists, and get increasingly
+    slower. (smcv)
+  * Rebuild wikis on upgrade to this version to fix bloat caused
+    by the dependency bug.
+  * htmltidy: Return an error message if tidy fails. Closes: #543722
+  * po: Fix name of translated toplevel index page. (intrigeri)
+  * po: Fix display of links from a translated page to itself (ntrigeri)
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 12 Aug 2009 12:25:30 -0400
+
+ikiwiki (3.141592) unstable; urgency=low
+
+  * Add new hooks: canremove, canrename, rename. (intrigeri)
+  * rename: Refactor subpage rename handling code into rename hook. (intrigeri)
+  * po: New plugin<F11>, suporting translation of wiki pages using po files.
+    (intrigeri)
+  * Add build machinery to build po files to translate the underlay wikis,
+  * Add further build machinery to generate translated underlays from
+    the po file, for use by wikis whose primary language is not English.
+  * Add Danish basewiki translation by Jonas Smedegaard.
+  * img: Fix adding of dependency from page to the image.
+  * pagestats: add `among` parameter, which only counts links from specified
+    pages (smcv)
+  * pagestats: when making a tag cloud, don't emit links where the tag is
+    unused (smcv)
+  * map: Avoid emitting an unclosed ul element if the map is empty. (harishcm)
+  * inline: Add pagenames parameter that can be used to list a set of
+    pages to inline, in a specific order, without using a PageSpec. (smcv)
+  * Add getsource plugin (Will, smcv)
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 11 Aug 2009 14:59:31 -0400
+
+ikiwiki (3.14159) unstable; urgency=low
+
+  * svn: Fix rcs_rename to properly scope call to dirname.
+  * img: Pass the align parameter through to the generated img tag.
+  * Move OpenID pretty-printing from openid plugin to core (smcv)
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 16 Jul 2009 14:37:22 -0400
+
+ikiwiki (3.1415) unstable; urgency=low
+
+  * img: Fix extra double quote with alt text. (smcv)
+  * Updated French debconf templates translation. Closes: #535103
+  * openid: Support Net::OpenID 2.x when pretty-printing
+    openids. (smcv)
+  * highlight: Fix utf-8 encoding bug. Closes: #535028
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 07 Jul 2009 16:25:05 -0400
+
+ikiwiki (3.141) unstable; urgency=low
+
+  * comment: Make comment directives no longer use the internal "_comment"
+    form, and document the comment directive syntax.
+  * Avoid relying on translators preserving the case when translating
+    "discussion", which caused Discussion pages to get unwanted Discussion
+    links.
+  * Tighten up matching of bare words inside directives; do not
+    allow an unterminated """ string to be treated as a series
+    of bare words. Fixes runaway regexp recursion/backtracking
+    in strange situations.
+  * Setup automator: Check that each plugin added to the generated
+    setup file can be loaded and that its config is ok. If a plugin
+    fails for any reason, disable it in the generated file.
+    Closes: 532001
+  * pagecount: Fix broken optimisation for * pagespec.
+  * goto: Support being passed a page title that is not a valid page
+    name, to support several cases including mercurial's long user
+    names on the RecentChanges page, and urls with spaces being handled
+    by the 404 plugin.
+  * Optimise use of gettext, and avoid ugly warnings if Locale::gettext
+    is not available. Closes: #532285
+  * meta: Add openid delegate parameter to allow delegating only
+    openid or openid2.
+  * Disable the Preferences link if no plugin with an auth hook is enabled.
+  * Updated French translation. Closes: #532654
+  * aggregate: Fix storing of changed md5.
+  * aggregate: Avoid resetting ctime when an item md5 changes.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 12 Jun 2009 19:50:46 -0400
+
+ikiwiki (3.14) unstable; urgency=low
+
+  * highlight: New plugin supporting syntax highlighting of pretty much
+    anything.
+  * debian/control: Add suggests for libhighlight-perl, although
+    that package is not yet created by Debian's highlight source package.
+    (See #529869)
+  * format: Provide a htmlizefallback hook that other plugins
+    can use to handle formats that are not suitable for general-purpose
+    htmlize hooks. Used by highlight.
+  * Fix test suite to not rely on an installed copy of ikiwiki after
+    underlaydir change. Closes: #530502
+  * Danish translation update. Closes: #530877
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 01 Jun 2009 13:05:34 -0400
+
+ikiwiki (3.13) unstable; urgency=low
+
+  * ikiwiki-transition: If passed a nonexistant srcdir, or one not
+    containing .ikiwiki, abort with an error rather than creating it.
+  * Allow underlaydir to be overridden without messing up inclusion
+    of other underlays via add_underlay.
+  * More friendly display of markdown, textile in edit form selector
+    (jmtd)
+  * Allow curly braces to be used in pagespecs, and avoid a whole class
+    of potential security problems, by avoiding performing any string
+    interpolation on user-supplied data when translating pagespecs.
+  * ikiwiki-transition: Allow setup files to be passed to all subcommands
+    that need a srcdir.
+  * ikiwiki-transition: deduplinks was broken and threw away all
+    metadata stored by plugins in the index. Fix this bug.
+  * listdirectives: Avoid listing _comment directives and generally
+    assume any directive starting with _ is likewise internal.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 22 May 2009 14:10:56 -0400
+
+ikiwiki (3.12) unstable; urgency=low
+
+  * Re-enable python-support and add python:Depends to control file.
+  * ikiwiki-makerepo: Avoid using abs_path, as it apparently
+    fails on nonexistant directories with some broken perl
+    versions.
+  * inline: Minor optimisation.
+  * add_link: New function, which plugins should use rather than
+    modifying %links directly, to avoid it accumulating duplicates.
+  * ikiwiki-transition: Add a deduplinks action, that can be used
+    to remove duplicate links and optimise a wiki w/o rebuilding it.
+  * external: Fix pagespec_match and pagespec_match_list.
+    Closes: #527281
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 06 May 2009 00:31:16 -0400
+
+ikiwiki (3.11) unstable; urgency=low
+
+  * Avoid using python-support. Closes: #525086
+  * websetup: Display stderr in browser if ikiwiki setup fails.
+  * blogspam: Load RPC::XML library in checkconfig, so that an
+    error can be printed at that point if it's not available,
+    allowing the admin to see it during wiki setup.
+    Closes: #520015
+  * websetup: If setup fails, restore old setup file.
+  * relativedate: Deal with clock skew.
+  * Add IkiWiki::ErrorReason objects, and modify pagespecs to return
+    them in cases where they fail to match due to a configuration or syntax
+    error.
+  * pagespec_match_list: New API function, matches pages in a list
+    and throws an error if the pagespec is bad.
+  * inline, brokenlinks, calendar, linkmap, map, orphans, pagecount,
+    pagestate, postsparkline: Display a handy error message if the pagespec
+    is erronious.
+  * comments: Add link to comment post form to allow user to sign in
+    if they wish to, if the configuration makes signin optional
+    for commenting.
+  * Updated Danish translation from Jonas Smedegaard. Closes: #525751
+  * translation.mdwn: Typo fixes. Closes: #525753
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 04 May 2009 15:45:10 -0400
+
+ikiwiki (3.10) unstable; urgency=low
+
+  * darcs: Finally added support for this VCS, thanks to many
+    contributors:
+    - Thomas Schwinge wrote the original file, implementing only rcs_commit.
+    - Benjamin A'Lee contributed an alternative implementation.
+    - Tuomo Valkonen contributed rcs_getctime and stub rcs_recentchanges.
+    - Simon Michael contributed multiple changes.
+    - Petr Ročkai fixed rcs_recentchanges.
+    - Sven M. Hallberg merged the above and added missing features.
+  * Add missing newline to Confirm Password prompt.
+  * Add missing permalink support to archivepage and titlepage templates.
+  * debian/control: Wrap fields.
+  * inline: Add author info to archive display.
+  * Add a microblog template that is useful for inlining microblogging posts.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 18 Apr 2009 19:40:25 -0400
+
+ikiwiki (3.09) unstable; urgency=low
+
+  * inline: Add title_natural sort order, using Sort::Naturally
+    (chrysn)
+  * inline: Fix urls to feed when feedfile is used on an index page.
+  * git, mercurial: Fix --getctime to return file creation time,
+    not last commit time.
+  * Updated French translation (Jean-Luc Coulon). Closes: #521072
+  * css: Add clear: both to inlinefooter.
+  * comments: Fix too loose test for comments pages that matched
+    normal pages with "comment_" in their name. Closes: #521322
+  * comments: Fix anchor ids to be legal xhtml. Closes: #521339
+  * Fix documentation of anonok_pagespec. Closes: #521793
+  * Add missing suggests on libtext-textile-perl. Closes: #522039
+  * recentchanges: change to using do=goto links for user links.
+  * Fix git test suite to use a bare repo.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 04 Apr 2009 14:33:49 -0400
+
+ikiwiki (3.08) unstable; urgency=low
+
+  * git: Fix utf-8 encoding of author names.
+  * git: Manually decode git output from utf-8, avoids
+    warning messages on invalidly encoded output.
+  * Fix bug that caused weird things to appear as page types.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 15 Mar 2009 17:54:47 -0400
+
+ikiwiki (3.07) unstable; urgency=low
+  * Updated German translation (Kai Wasserbäch). Closes: #518377
+  * Updated French translation (Jean-Luc Coulon). Closes: #518510
+  * wmd: New plugin contributed by William Uther to support the WMD
+    Wysiwym markdown editor.
+  * smiley: Avoid infinite loop in smiley expansion triggered
+    by the template scan mode change in version 3.05. Closes: #518805
+  * template: When loading a template in scan mode, let preprocess
+    know it only needs to scan.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 08 Mar 2009 19:00:46 -0400
+
+ikiwiki (3.06) unstable; urgency=low
+
+  * Setup automator: Fix bug in password comparison. Closes: #517654
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 01 Mar 2009 15:02:30 -0500
+
+ikiwiki (3.05) unstable; urgency=low
+
+  * debhelper v7(.0.50); rules file minimisation.
+  * template: Load templates in scan mode.
+    This is potentially expensive, but is necessary so that meta and tag
+    directives, and other links on templates affect the page using the
+    template reliably.
+  * goto: Fix redirect to comments.
+  * Add noextension parameter to htmlize hooks to support, eg, Makefile.
+  * Add tagged() PageSpec.
+  * Updated German translation (Kai Wasserbäch). Closes: #516770
+  * Setup automator: Prompt for password twice. Closes: #516973
+  * bzr: Add missing rcs_diff. (liw)
+  * comments: Avoid showing comment moderation button in prefs to non-admins.
+  * goto: Fix typo that broke recentchanges_link compatibility.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 27 Feb 2009 15:48:39 -0500
+
+ikiwiki (3.04) unstable; urgency=low
+
+  * 404: New plugin which lets you use the IkiWiki CGI script as
+    an Apache 404 handler, to give the behaviour of various other wiki
+    engines where visiting a nonexistent page provides you with a link
+    to create it. (smcv)
+  * Factor out redundant code into goto plugin. (smcv)
+  * Work around XML::Atom strangeness that results in double-encoded posts.
+    (smcv) 
+  * Fix unusual --setup --post-commit command line option combo.
+  * Create any missing directory necessary to put the wrapper
+    file into. Closes: #514384
+  * shortcut: If default_pageext is set, first look for
+    shortcuts.default_pageext.
+  * Allow comments, rename, remove, and attachment plugins to be used
+    even if the editpage plugin is disabled.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 14 Feb 2009 02:27:14 -0500
+
+ikiwiki (3.03) unstable; urgency=low
+
+  * Avoid feeding decoded unicode to Term::ReadLine. Closes: 512169
+  * blogspam: Log spam info on failure in debug mode.
+  * Remove nonstandard css. Closes: #512378
+  * blogspam: Fix use of blogspam_options and blogspam_server config settings.
+  * comments: If comment content checks fail, store the comment
+    (in .ikiwiki/comments_pending) for moderator review.
+  * comments: Add a moderation web interface, which admins can
+    access via their Preferences page.
+  * git: Fix malformed utf8 received from git.
+  * meta: New "updated" metadata specifies a fake modification time for a
+    page, to be output into RSS and Atom feeds. (smcv)
+  * underlay: New plugin, allows pulling in additional files not
+    in version control. (smcv) 
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 29 Jan 2009 14:36:58 -0500
+
+ikiwiki (3.02) unstable; urgency=low
+
+  * blogspam: New plugin, adding spam filtering for page editing / comment
+    posting using the BlogSpam.net API.
+  * Add auto-blog.setup, which will set up an ikiwiki instance tuned for use
+    in blogging.
+  * checkcontent: New hook, can be used to implement arbitrary content
+    filters, including spam filters.
+  * table: Fix misparsed links in external files.
+  * table: Find links in external files in scan pass.
+  * rename: Show full names of affected pages.
+  * comments: Fix cache avoidance hack.
+  * repolist: New plugin to support the rel=vcs-* microformat.
+  * goodstuff: Include repolist by default. (But it does nothing until
+    configured with the repository locations.)
+  * comments: Add support for removing comments via web interface. (smcv)
+  * Consistently allow use of relative paths in all PageSpecs
+    that take a page name parameter. Previously, match_created_before(),
+    match_created_after(), match_sourcepage(), and match_destpage()
+    did not support that, and the docs were not clear.
+  * pinger: Get whole url, don't just head, avoids problems on
+    the nostromo web server.
+  * Recommend libterm-readline-gnu-perl since that makes auto.setup
+    behave better.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 17 Jan 2009 18:19:39 -0500
+
+ikiwiki (3.01) unstable; urgency=low
+
+  * ikiwiki-makerepo: Fix injecting of empty mercurial and bzr repositories.
+    Closes: #510518
+  * Fix documentation about git hook to use right name. Closes: #510393
+  * yesno: Always accept English even when localised.
+  * yesno: Also accept 1 and 0 as input.
+  * A recent change to gitweb removed support for the form of diffurl 
+    that many ikiwiki setups use. Document how to use the new url form.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 05 Jan 2009 18:53:50 -0500
+
+ikiwiki (3.00) unstable; urgency=low
+
+  * Remove support for GlobLists.
+  * Remove support for configuring allowed attachments, locked pages,
+    and banned users from the admin preferences page. These can only be
+    controlled via the setup file now.
+  * ikiwiki-transition moveprefs can be used to move the above
+    admin preferences into a setup file.
+  * prefix_directives and aggregate_internal are now turned on by default.
+  * ikiwiki-transition prefix_directives syntax changed
+  * googlecalendar: removed this deprecated plugin. Use htmlscrubber_skip
+    instead.
+  * embed: This plugin is deprecated, use htmlscrubber_skip instead.
+    Closes: ##462970.
+  * Version 3.00 of the plugin API.
+  * Replace blank OpenID placeholder logo with an unofficial OpenID
+    logo developed by Anna Hess. The official logo does not seem destined to
+    be free.
+  * comments: Add cache avoidance.
+  * htmlbalance: Demand-load HTML::TreeBuilder to avoid failing test suite
+    if it is not present.
+  * French translation update from Philippe Batailler. Closes: #510216
+  * websetup: Avoid a crash when a new array setup item has been added in 
+    a new ikiwiki release, and is thus not present in the setup file yet.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 31 Dec 2008 15:17:47 -0500
+
+ikiwiki (2.72) unstable; urgency=low
+
+  * Avoid comments in recentchanges being broken links (smcv)
+  * Add deprecation warning for GlobLists, which will stop working in 3.0.
+  * camelcase: Add camelcase_ignore setting.
+  * googlecalendar: Add runtime deprecation warning.
+  * comments: Deal with users entering unqualified or partial urls.
+  * inline: Run format hook first, to ensure other format hooks can affect
+    inlined content.  Closes: #509710
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 28 Dec 2008 15:01:02 -0500
+
+ikiwiki (2.71) unstable; urgency=low
+
+  * comments: Blog-style comment support, contributed by Simon McVittie.
+  * htmlbalance: New plugin contributed by Simon McVittie.
+  * Change deb dependencies to list Text::Markdown before markdown (really
+    this time).
+  * Improve escaping of wikilinks and preprocessor directives in content
+    produced by aggregate and recentchanges.
+  * French translation update from Philippe Batailler. Closes: #506250
+  * Spanish translation update from Victor Moral.
+  * Fix handling of wrappergroup option.
+  * Correct --dumpsetup to include the srcdir in the setup file.
+  * German translation update from Kai Wasserbäch. Closes: #507056
+  * inline: Support emptyfeeds=no option to skip generating empty feeds.
+  * inline: Support feedfile option to change the filename of the feed
+    generated.
+  * meta: Pass info to htmlscrubber so htmlscrubber_skip can take effect.
+  * htmlbalance: don't compact whitespace, and set misc other options (smcv)
+  * rename: Fix double-escaping of page name in edit box.
+  * monotone: When getting the log, tell monotone how many entries
+    we want, rather than closing the pipe, which it dislikes. (thm)
+  * Coding style change: Remove explcit vim folding markers.
+  * aggregate: If a feed fails to be downloaded, try again immediatly
+    next time aggregation is run, even if the usual time has not passed.
+    Closes: #508622 (Michael Gold)
+  * meta: Process meta date during scan pass so that the date will always
+    affect sorting in inlines.
+  * Improve display of some openids (smcv)
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 21 Dec 2008 16:22:05 -0500
+
+ikiwiki (2.70) unstable; urgency=low
+
+  * Avoid crash on malformed utf-8 discovered by intrigeri.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 12 Nov 2008 17:45:58 -0500
+
+ikiwiki (2.69) unstable; urgency=low
+
+  * Avoid multiple ikiwiki cgi processes piling up, eating all memory,
+    and thrashing, by making the cgi wrapper wait on a cgilock.
+    If you had to set apache's MaxClients low to avoid ikiwiki thrashing your
+    server, you can now turn it up to a high value.
+  * Stop busy-waiting in lockwiki, as this could delay ikiwiki from waking up
+    for up to one second. The bailout code is no longer needed after above
+    change.
+  * Remove support for unused optional wait parameter from lockwiki.
+  * aggregate: Try to query XML::Feed for the base url when derelevatising
+    links. Since this needs the just released XML::Feed 0.3, as well 
+    as a not yet released XML::RSS, it will fall back to the old method
+    if no xml:base info is available.
+  * meta: Plugin is now enabled by default since the basewiki uses it.
+  * txt: Do not encode quotes when filtering the txt, as that broke
+    later parsing of any directives on the page.
+  * Fix the link() pagespec to match links that are internally recorded as
+    absolute.
+  * Add rel=nofollow to recentchanges_links for the same (weak) reasons it
+    was earlier added to edit links.
+  * tag: Normalize tagbase so leading/trailing slashes in it don't break
+    things.
+  * bzr: Fix dates for recentchanges.
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 11 Nov 2008 20:35:55 -0500
+
+ikiwiki (2.68) unstable; urgency=low
+
+  * Add support for checking pushes from untrusted git committers. This can be
+    used to set up anonymous git pushes, and other similar things.
+  * format: New plugin, allows embedding differently formatted text inside a
+    page (ie, otl inside a mdwn page, or syntax highlighted code inside a
+    page).
+  * relativedate: New javascript-alicious plugin that makes all dates display
+    relative, in a very nice way, if I say so myself.
+  * Optimise the no-op post-commit hook, to speed up web edits by a fraction
+    of a second.
+  * git: Allow [[sha1_commit]] to be used in the diffurl, to support cgit.
+  * shortcut: Fix display of shortcuts while previewing.
+  * Plugins that used to override displaytime should instead override
+    formattime. displaytime will call that, and may wrap markup around the
+    formatted time.
+  * Add an underlay for javascript, and add ikiwiki.js containing some utility
+    code.
+  * toggle: Stop embedding the full toggle code on each page using it, and
+    move it to toggle.js in the javascript underlay.
+  * recentchanges: Make feed links point back to anchors on the recentchanges
+    page. (JasonBlevins)
+  * Fix issue with utf-8 in wikiname breaking session cookies, by
+    entity-encoding the wikiname in the session cookie.
+  * Use the pure perl Data::Dumper when generating setup files to ensure that
+    utf-8 characters are written out as such, and not as the encoded perl
+    strings the C Data::Dumper produces.
+  * inline: Only the last feed link was put on the page, fix this to include
+    all feed links. So rss will be included along with atom, and pages with
+    multiple feeds will get links added for all feeds.
+  * tag: When tagbase is set, force the links created by tagging to point at
+    the toplevel tagbase, and not closer subpages. The html links already went
+    there, but internally the links were not recorded as absolute, which could
+    cause confusing backlinks etc.
+  * Add an inject function, that can be used by plugins that want to
+    replace one of ikiwiki's functions with their own version.
+    (This is a scary thing that grubs through the symbol table, and replaces
+    all exported occurances of a function with the injected version.)
+  * external: RPC functions can be injected to replace exported functions.
+  * Updated French translation. Closes: #502694
+  * Updated Spanish translation from the ever vigilant Victor Moral.
+  * Updated Danish translation from Jonas Smedegaard. Closes: #503117
+  * Preserve syslog setting when doing `ikiwiki -setup foo -dumpsetup bar`
+  * Several fixes to --render mode.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 03 Nov 2008 16:31:11 -0500
+
+ikiwiki (2.67) unstable; urgency=low
+
+  * remove: Avoid $_ breakage. (Stupid, stupid perl.)
+  * Updated Spanish translation from Victor Moral.
+  * lockedit: Support specifying which users (and IP addresses) a page
+    is locked for. This supports most of the ACL type things users have been
+    wanting to be done. Closes: #443346 (It does not control who can read a
+    page, but that's out of scope for ikiwiki.)
+  * orphans: Fix unquoted page name in regexp.
+  * google: Plugin provides google site search, contributed by Peter Simons.
+  * Pass HTTPS variable through the wrapper so that CGI->https can be used
+    by plugins. Closes: #502047
+  * inline: Allow MTIME to be used in inlinepage.tmpl.
+  * inline: Use the feed's description in the rss and atom links.
+    Closes: #502113
+  * aggregate: Avoid bug that caused immediate expiration of items
+    with a date in the future.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 17 Oct 2008 13:13:41 -0400
+
+ikiwiki (2.66) unstable; urgency=low
+
+  * recentchanges: Fix redirects to non-page files. 
+  * aggregate: Avoid uninitialized value warnings for pages with no recorded
+    ctime.
+  * attachment: Add admin() pagespec to test if the uploading user is a wiki
+    admin.
+  * git: Fix handling of utf-8 filenames in recentchanges.
+  * tag: Make edit link for new tags ensure that the tags are created
+    inside tagbase, when it's set.
+  * template: Make edit link for new templates ensure the page is located
+    under toplevel templates directory.
+  * htmlscrubber: Add a config setting that can be used to disable the
+    scrubber acting on a set of pages.
+  * Expand usage message and add --help. Closes: #500344
+  * Beautify urls used in various places. (smcv)
+  * Export pagetitle, titlepage, linkpage.
+  * htmltidy: Avoid returning undef if tidy fails. Also avoid returning the
+    untidied content if tidy crashes. In either case, it seems best to tidy
+    the content to nothing.
+  * htmltidy: Avoid spewing tidy errors to stderr.
+  * Reorganize index file, add a format version field. Upgrades to the new
+    index format should be transparent.
+  * Add %wikistate, which is like %pagestate except not specific to a given
+    page, and is preserved across rebuilds.
+  * editpage: Be more aggressive (and less buggy) about cleaning up
+    temporary files rendered during page preview.
+  * Add an indexpages option, which causes foo/index.mdwn to be the source
+    for page foo when foo.mdwn doesn't exist. Also, when it's enabled,
+    creating a new page will save it to foo/index.mdwn by default.
+    Closes: #474611
+    (Sponsored by The TOVA Company.)
+  * httpauth: Document that ikiwiki.cgi has to be in a directory subject to
+    authentication. Closes: #500524 
+  * inline: Fix handling of rootpage that doesn't exist.
+  * attachment: Support adding attachments to pages even as they are being
+    created.
+  * remove, rename: Allow acting on attachments as a page is being created.
+  * Updated French translation. Closes: #500929
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 05 Oct 2008 19:11:08 -0400
+
+ikiwiki (2.65) unstable; urgency=low
+
+  * aggregate: Expire excess or old items on the same pass that adds them,
+    not only on subsequent passes.
+  * editdiff: Broken since 2.62 due to wrong syntax, now fixed.
+  * aggregate: Support atom feeds with only a summary element, and no content
+    elements.
+  * progress: Display an error if the progress cannot be parsed, and allow
+    the percent parameter to only optionally end with "%".
+  * Fix reversion in use of ikiwiki -verbose -setup with a setup file that
+    enables syslog. Setup output is once again output to stdout in this
+    case.
+  * edittemplate: Default new page file type to the same type as the template.
+    (willu)
+  * edittemplate: Add "silent" parameter. (Willu)
+  * edittemplate: Link to template, to allow creating it. (Willu)
+  * editpage: Add a missing check that the page name contains only legal
+    characters, in addition to the existing check for pruned filenames.
+  * Print a debug message if a page has multiple source files.
+  * Add keepextension parameter to htmlize hook. (Willu)
+  * rename, remove: Don't rely on a form parameter to tell whether the page
+    should be treated as an attachment.
+  * rename: Add support for moving SubPages of a page when renaming it.
+    (Sponsored by The TOVA Company.)
+  * rename: Hide type field from rename form when renaming attachments.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 24 Sep 2008 17:55:14 -0400
+
+ikiwiki (2.64) unstable; urgency=low
+
+  * Avoid uninitialised value when --dumpsetup is used and no srcdir/destdir
+    specified.
+  * ddate: Stop clobbering timeformat when not enabled.
+  * progress: New plugin to generate progress bars (willu)
+  * Add allow_symlinks_before_srcdir to config so websetup doesn't eat it.
+  * img: Support sizes like 200x. Closes: #475149
+  * goodstuff: Remove otl plugin from the bundle since it needs a significant
+    external dependency and is not commonly used. If you use otl, make sure
+    you explicitly enable it now.
+  * goodstuff: Add more, progress, and table plugins to the bundle.
+  * Improve error message if external plugin fails to load. Closes: #498458
+  * Directive documentation broken out of the plugin documentation and into 
+    pages suitable to be used as an underlay. Thanks to Willu for doing most
+    of the tedious work.
+  * Move the directive documentation into its own underlay, separate from
+    basewiki, since it's sorta large compared to the rest of basewiki.
+  * listdirectives: Enable use of the directives underlay.
+  * Removed the obsolete blog page from the basewiki. ikiwiki/blog still
+    remains, but is now deprecated too.
+  * Removed old redirecton pages from basewiki (helponformatting,
+    markdown, openid, pagespec, preprocessordirective, subpage, wikilink).
+  * inline: Treat rootpage as a link, so that it can refer to a subpage
+    without hardcoding the path.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 14 Sep 2008 16:58:25 -0400
+
+ikiwiki (2.63) unstable; urgency=low
+
+  * Set cookies HttpOnly.
+  * Typo. Closes: #497003
+  * Ignore failure to install files into /etc, in case install is running as
+    non-root.
+  * Work around perl $_ scoping nonsense that caused breakage when loading
+    external plugins.
+  * style.css: Add missing semicolon. Closes: #497176 
+  * filecheck: Fall back to testing for binary or plain text files
+    if no mime type is detected.
+  * table: Support header=column to make the table header be the first
+    column of the data. (AlexandreDupas)
+  * For fine control over what characters are allowed, unescaped in
+    source filenames, the wiki_file_chars setting is added. For example,
+    set to "-[:alnum:]+/._" to disable colons from being used in source files
+    (which can cause troubl om Windows).
+  * po/Makefile: update po files when the pot file has changed.
+    Closes: #497951
+  * editpage: New core plugin factoring out page editing to allow disabling it
+    if desired.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 08 Sep 2008 12:17:15 -0400
+
+ikiwiki (2.62.1) unstable; urgency=low
+
+  * filecheck: Fixed two bits broken in move from attachment.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 28 Aug 2008 13:04:47 -0400
+
+ikiwiki (2.62) unstable; urgency=low
+
+  * Avoid using cp -a (again). (HenrikBrixAndersen)
+  * Avoid using hostname -f for portability to eg, OS X, use Net::Domain
+    instead, and prompt if it fails.
+  * Fix bug in wikiname sanitisation in the setup automator.
+  * ikiwiki-makerepo: Added support for monotone. (Thomas Keller)
+  * map: The fix for #449285 was buggy and broke display of parents in certain
+    circumstances.
+  * teximg: The prefix is configurable, and has changed to not include the
+    nonstandard mhchem by default. (willu)
+  * teximg: dvipng is used if available to render images. Its output is
+    antialiased and better than dvips. If not available, the old dvips+convert
+    chain will be used. (willu)
+  * Drop suggests on texlive-science, add suggests on dvipng.
+  * listdirectives: New plugin. (willu)
+  * filecheck: New plugin factoring out the PageSpec additions that were
+    originally part of the attachment plugin.
+  * edittemplate: Don't wipe out edits on preview.
+  * color: New plugin from ptecza.
+  * autoindex: Avoid re-adding previously deleted (or renamed) pages.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 27 Aug 2008 15:14:09 -0400
+
+ikiwiki (2.61) unstable; urgency=low
+
+  * poll: Fix typo that broke plugin.
+  * graphviz: Fix breakage of the name of the preprocessor directive.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 14 Aug 2008 18:13:22 -0400
+
+ikiwiki (2.60) unstable; urgency=low
+  [ Joey Hess ]
+  * Starting with this version, "ikiwiki -setup /etc/ikiwiki/auto.setup"
+    can be used create a new wiki in seconds.
+  * websetup: New plugin providing a setup form on the web.
+  * ikiwiki --dumpsetup can generate a nice setup file snapshotting ikiwiki's
+    current configuration.
+  * The way wrappers are defined in the setup file has changed. Old setup
+    files will continue to work, for now.
+  * ikiwiki-transition setupformat can be used to convert a setup file to the
+    new format.
+  * Version control backends promoted to first-class plugins.
+  * ikiwiki-update-wikilist: Add -r switch to remove. Default behavior is now
+    always to add.
+  * Start moving admin preferences from the web interface to the setup file.
+  * Add getsetup hook, all plugins should use it to record information about
+    themselves and any fields they add to %config
+  * Large amounts of internal config data reorg.
+  * ikiwiki-makerepo: Bail if both srcdir and repository are not specified.
+    Closes: #493628
+  * Clarify some wording in the setup documentation that could maybe lead
+    users to putting paths with "~/" in the setup file, which doesn't work.
+    Closes: #493835
+  * autoindex: Ignore internal pages, and take underlay directories into
+    account. Also, avoid making index pages for directories that contain
+    no files.
+  * external: Fix support for hooks called in an array context.
+  * Options set in the setup file are now immediatly loaded by ikiwiki -setup.
+    This allows later switches to override them. Previously, setup file
+    options overrode most command line options.
+  * Added a small icon to the search input box.
+
+  [ Josh Triplett ]
+  * Add Suggests on texlive and texlive-science for the teximg plugin
+
+  [ Joey Hess ]
+  * inline: Ignore parent dirs when sorting pages by title.
+  * rename: Support changing page extensions. (willu)
+  * Danish update. Closes: #494632
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 12 Aug 2008 14:20:25 -0400
+
+ikiwiki (2.56) unstable; urgency=low
+
+  * autoindex: New plugin that generates missing index pages.
+    (Sponsored by The TOVA Company.)
+  * Escape HTML is rss and atom feeds instead of respectively using CDATA and
+    treating it as XHTML. This avoids problems with escaping the end of the
+    CDATA when the htmlscrubber is not used, and it avoids problems with atom
+    XHTML using named entity references that are not in the atom DTD.
+    (Simon McVittie)
+  * Add test for old versions of git that don't support --cleanup=verbatim,
+    and munge empty commit messages.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 31 Jul 2008 19:25:24 -0400
+
+ikiwiki (2.55) unstable; urgency=low
+
+  * remove: New plugin that adds the ability to remove pages via the web.
+    (Sponsored by The TOVA Company.)
+  * rename: New plugin that adds the ability to rename pages via the web.
+    (Sponsored by The TOVA Company.) (This one's for you, Kyle.)
+  * All rcs backends need to implement rcs_remove, rcs_commitstaged,
+    and rcs_rename. (Done for svn, git).
+  * This version adds renamepage hooks, which can be used to modify page
+    content, including links, during renames.
+  * prefix_directives enabled in doc wiki, all preprocessor directives
+    converted. (Simon McVittie)
+  * editpage: Don't show attachments link when attachments are disabled.
+  * tag: Allow tagbase to be overridden by starting a tag with "./" or "/".
+    (Simon McVittie)
+  * Really fix bug with links to pages with names containing colons. 
+    Previous fix mised a few cases.
+  * Avoid troublesome abs_path calls in wrapper setup.
+  * Add allow_symlinks_before_srcdir config setting that can be used to avoid
+    a security check that is a good safe default, but problimatic overkill in
+    some situations.
+  * Don't allow uploading an attachment with the same name as an existing
+    page, to avoid confusion.
+  * Split out error messages from editpage.tmpl into several separate
+    templates.
+  * attachment: Do not escape _ when determining attachment filenames.
+  * Rebuild pages that change their type. (Gabriel McManus)
+  * monotone: Add support for rename, delete, and also diff. (William Uther)
+  * toggle: Fix incompatability between javascript and webkit.
+  * bzr: Add support for rename and delete. (Jelmer Vernooij)
+  * attachment: Use relative paths when inserting links.
+  * toggle: Fix for when html got tidied. Closes: #492529 (Enrico Zini)
+  * cutpaste: New plugin by Enrico Zini
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 27 Jul 2008 11:23:13 -0400
+
+ikiwiki (2.54) unstable; urgency=low
+
+  [ Joey Hess ]
+  * Make it possible to load setup files w/o running them. Code
+    needing to do so can call IkiWiki::Setup::load, which will return
+    a hash of values.
+
+  [ Josh Triplett ]
+  * ikiwiki-transition: Fix command-line processing so the prefix_directives
+    transition works again.
+
+  [ Joey Hess ]
+  * template: Add support for a BASENAME variable.
+  * Fixes creation of pages when clicking on WikiLinks starting with "/".
+  * Change deb dependencies to list Text::Markdown before markdown, since
+    the former, while slower, has a much better html parser that avoids
+    numerous bugs.
+  * Move yesno function out of inline and into IkiWiki core, not exported.
+  * Error handling improvement for preprocess hooks. It's now safe to call
+    error() from such hooks; it will cause a nicely formatted error message
+    to be inserted into the page.
+  * Cut the size of the binary package in half by excluding pages for bugs
+    and todo items from the html shipped in it.
+  * parentlinks: New plugin, split out of ikiwiki core and enabled by default,
+    and several new fields added to allow for advanced styling. (intrigeri)
+  * smileys: Some fixes for escaped smileys.
+  * smileys: Note that smileys need to be double-escaped for the escaping to
+    work. Markdown removes one level of escaping.
+  * Add a postscan hook.
+  * search: Use postscan hook, avoid updating index when previewing.
+  * git: Put web committer name/openid/address in the git author field.
+    The committer's email address is not used (because leaking email addresses
+    is not liked by many users). Closes: #451023
+  * git: Fix parsing of git logs with no commit messages at all.
+  * search: Fixes for title stemming, and use better term for tags.
+    (Gabriel McManus)
+    (Rebuilding the wiki on upgrade to this version is recommended if you
+    use the search plugin.)
+
+  [ Simon McVittie ]
+  * meta, inline: Support guid options, to allow forcing a particular url or
+    uuid in feeds.
+  * meta: fix title() PageSpec
+  * Some footer style changes.
+  * aggregate: Add an `aggregateinternal` option, which allows storing
+    aggregated data to internal-use files, rather than wiki pages. This
+    can save disk space, and be faster.
+  * ikiwiki-transition: Add a `aggregateinternal` transition to rename
+    the aggregated files.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 21 Jul 2008 10:10:52 -0400
+
+ikiwiki (2.53) unstable; urgency=low
 
   * search: generate configuration files once only when rebuilding
     (Gabriel McManus)
+  * attachment: Fix an uninitialised value warning when editing a page
+    that currently has no attachments.
+  * Fix a bug with links to pages whose names contained colons.
+  * attachment: Support old versions of CGI.pm that lack an upload method.
+  * Include ikiwiki.setup in examples in the debian package.
+  * attachment: Support perl 5.8's buggy version of CGI.pm.
+  * otl: Support utf-8 files. (Recai Oktaş)
 
- -- Joey Hess <joeyh@debian.org>  Mon, 07 Jul 2008 01:52:48 -0400
+ -- Joey Hess <joeyh@debian.org>  Wed, 09 Jul 2008 16:45:33 -0400
 
 ikiwiki (2.52) unstable; urgency=low
 
@@ -102,7 +927,7 @@ ikiwiki (2.48) unstable; urgency=high
     pounding on the cgi following edit links.
   * passwordauth: If Authen::Passphrase is installed, use it to store
     password hashes, crypted with Eksblowfish.
-  * `ikiwiki-transiition hashpassword /path/to/srcdir` can be used to
+  * `ikiwiki-transition hashpassword /path/to/srcdir` can be used to
     hash existing plaintext passwords.
   * Passwords will no longer be mailed, but instead a password reset link.
   * The password_cost config setting is provided as a "more security" knob.
index 7ed6ff82de6bcc2a78243fc9c54d3ef5ac14da69..7f8f011eb73d6043d2e6db9d2c101195ae2801f2 100644 (file)
@@ -1 +1 @@
-5
+7
index b29d5ffbb2bc95610154d0b9e74fddbd50f79429..96ba221fffc865fc34bd5c54eefebe2d6fab8930 100644 (file)
@@ -1,20 +1,42 @@
 Source: ikiwiki
 Section: web
 Priority: optional
-Build-Depends: perl, debhelper (>= 5)
-Build-Depends-Indep: dpkg-dev (>= 1.9.0), libxml-simple-perl, markdown | libtext-markdown-perl, libtimedate-perl, libhtml-template-perl, libhtml-scrubber-perl, wdg-html-validator, libhtml-parser-perl, liburi-perl
+Build-Depends: perl, debhelper (>= 7.0.50)
+Build-Depends-Indep: dpkg-dev (>= 1.9.0), libxml-simple-perl,
+  libtext-markdown-perl | markdown, 
+  libtimedate-perl, libhtml-template-perl,
+  libhtml-scrubber-perl, wdg-html-validator,
+  libhtml-parser-perl, liburi-perl, perlmagick, po4a (>= 0.34)
 Maintainer: Joey Hess <joeyh@debian.org>
-Uploaders: Joey Hess <joeyh@debian.org>, Josh Triplett <josh@freedesktop.org>
-Standards-Version: 3.8.0
+Uploaders: Josh Triplett <josh@freedesktop.org>
+Standards-Version: 3.8.1
 Homepage: http://ikiwiki.info/
 Vcs-Git: git://git.ikiwiki.info/
 Vcs-Browser: http://git.ikiwiki.info/?p=ikiwiki
 
 Package: ikiwiki
 Architecture: all
-Depends: ${perl:Depends}, markdown | libtext-markdown-perl, libhtml-scrubber-perl, libhtml-template-perl, libhtml-parser-perl, liburi-perl
-Recommends: gcc | c-compiler, libc6-dev | libc-dev, subversion | git-core (>= 1:1.5.0) | tla | bzr (>= 0.91) | mercurial | monotone (>= 0.38), libxml-simple-perl, libnet-openid-consumer-perl, liblwpx-paranoidagent-perl, libtimedate-perl, libcgi-formbuilder-perl (>= 3.05), libcgi-session-perl (>= 4.14-1), libmail-sendmail-perl, libauthen-passphrase-perl
-Suggests: viewvc | gitweb | viewcvs, libsearch-xapian-perl, xapian-omega (>= 1.0.5), librpc-xml-perl, libtext-wikiformat-perl, python, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl, libcrypt-ssleay-perl, liblocale-gettext-perl (>= 1.05-1), libtext-typography-perl, libtext-csv-perl, libdigest-sha1-perl, graphviz, libnet-amazon-s3-perl
+Depends: ${misc:Depends}, ${perl:Depends}, ${python:Depends}, 
+  libtext-markdown-perl | markdown,
+  libhtml-scrubber-perl, libhtml-template-perl,
+  libhtml-parser-perl, liburi-perl
+Recommends: gcc | c-compiler, 
+  libc6-dev | libc-dev,
+  subversion | git-core (>= 1:1.5.0) | tla | bzr (>= 0.91) | mercurial | monotone (>= 0.38),
+  libxml-simple-perl, libnet-openid-consumer-perl,
+  liblwpx-paranoidagent-perl, libtimedate-perl,
+  libcgi-formbuilder-perl (>= 3.05), libcgi-session-perl (>= 4.14-1),
+  libmail-sendmail-perl, libauthen-passphrase-perl, libterm-readline-gnu-perl
+Suggests: viewvc | gitweb | viewcvs, libsearch-xapian-perl,
+  xapian-omega (>= 1.0.5), librpc-xml-perl, libtext-wikiformat-perl,
+  python, python-docutils, polygen, tidy, libhtml-tree-perl,
+  libxml-feed-perl, libmailtools-perl, perlmagick,
+  libfile-mimeinfo-perl, libcrypt-ssleay-perl,
+  liblocale-gettext-perl (>= 1.05-1), libtext-typography-perl,
+  libtext-csv-perl, libdigest-sha1-perl, graphviz, libnet-amazon-s3-perl,
+  sparkline-php, texlive, dvipng, libtext-wikicreole-perl,
+  libsort-naturally-perl, libtext-textile-perl, libhighlight-perl,
+  po4a (>= 0.35-1), gettext
 Conflicts: ikiwiki-plugin-table
 Replaces: ikiwiki-plugin-table
 Provides: ikiwiki-plugin-table
index d25e0861ac759779bd78126408ca79d1770a953d..b06d27f19f5c907c2461924cd0f6b22895c4c9d4 100644 (file)
@@ -4,7 +4,7 @@ License: GPL-2+
  The full text of the GPL is distributed as doc/GPL in ikiwiki's source,
  and is distributed in /usr/share/common-licenses/GPL-2 on Debian systems.
 
-Files: templates/*, underlays/basewiki/*, ikiwiki.setup
+Files: templates/*, underlays/basewiki/*, doc/ikiwiki/directive/*, ikiwiki.setup, po/underlay/*
 Copyright: © 2006-2008 Joey Hess <joey@ikiwiki.info>
 License: other
  Redistribution and use in source and compiled forms, with or without
@@ -24,14 +24,24 @@ Files: mercurial.pm
 Copyright: © 2006 Emanuele Aina
 License: GPL-2+
 
-Files: monotone.pm
-Copyright: © 2007 William Uther
+Files: monotone.pm, listdirectives.pm, progress.pm
+Copyright: © 2007, 2008 William Uther
 License: GPL-2+
 
 Files: tla.pm
 Copyright: © 2006 Clint Adams <schizo@debian.org>
 License: GPL-2+
 
+Files: darcs.pm
+Copyright:
+ © 2006  Thomas Schwinge <tschwinge@gnu.org>
+   2007  Benjamin A'Lee <bma@bmalee.eu>
+         Tuomo Valkonen <tuomov@iki.fi>
+   2008  Simon Michael <simon@joyful.com>
+         Petr Ročkai <me@mornfall.net>
+         Sven M. Hallberg <pesco@khjk.org>
+License: GPL-2+
+
 Files: teximg.pm
 Copyright: © 2007 Patrick Winnertz <patrick.winnertz@skolelinux.org>
 License: GPL-2+
@@ -76,7 +86,11 @@ Files: htmltidy.pm
 Copyright: © 2006 Faidon Liambotis
 License: GPL-2+
 
-Files: polygen.pm, pagestats.pm
+Files: htmlbalance.pm, underlay.pm
+Copyright: © 2008 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+License: GPL-2+
+
+Files: polygen.pm, pagestats.pm, cutpaste.pm
 Copyright: © 2006 Enrico Zini
 License: GPL-2+
 
@@ -100,6 +114,32 @@ Files: txt.pm
 Copyright: Copyright (C) 2008 Gabriel McManus <gmcmanus@gmail.com>
 License: GPL-2+
 
+Files: color.pm
+Copyright: Copyright (C) 2008 Paweł Tęcza <ptecza@net.icm.edu.pl>
+License: GPL-2+
+
+Files: google.pm
+Copyright: Copyright (C) 2008 Peter Simons <simons@cryp.to>
+License: GPL-2+
+
+Files: comments.pm
+Copyright: 
+ © 2006-2008 Joey Hess <joey@ikiwiki.info>
+ © 2008 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+License: GPL-2+
+
+Files: po.pm
+Copyright: © 2008-2009 intrigeri <intrigeri@boum.org>
+License: GPL-2+
+
+Files: 404.pm
+Copyright: © 2009 Simon McVittie <http://smcv.pseudorandom.co.uk/>
+License: GPL-2+
+
+Files: wmd.pm, getsource.pm
+Copyright: © 2009 William Uther
+License: GPL-2+
+
 Files: doc/logo/*
 Copyright: © 2006 Recai Oktaş <roktas@debian.org>
 License: GPL-2+
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..1936cc1
--- /dev/null
@@ -0,0 +1 @@
+html
diff --git a/debian/examples b/debian/examples
new file mode 100644 (file)
index 0000000..a1e6231
--- /dev/null
@@ -0,0 +1 @@
+ikiwiki.setup
diff --git a/debian/link b/debian/link
new file mode 100644 (file)
index 0000000..cb37931
--- /dev/null
@@ -0,0 +1,2 @@
+usr/share/ikiwiki/examples usr/share/doc/ikiwiki/examples
+usr/share/common-licenses/GPL-2 usr/share/doc/ikiwiki/html/GPL
index 0a836a0b2a0a071e9ceaa194766674f96c731b2b..2ba26e5b65010cee1649390240228a3d939b7afb 100755 (executable)
@@ -4,7 +4,7 @@ set -e
 
 # Change this when some incompatible change is made that requires
 # rebuilding all wikis.
-firstcompat=2.52
+firstcompat=3.1415926
 
 if [ "$1" = configure ] && \
    dpkg --compare-versions "$2" lt "$firstcompat"; then
index 12d3d83afaa34d38faa9f9a8445080a52446c049..4158b2ae6636667d9b86583e7720cbe4153164b0 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-
+set -e
 #DEBHELPER#
 
 if [ "$1" = upgrade ] && dpkg --compare-versions "$2" lt 1.2; then
@@ -14,3 +14,7 @@ if [ "$1" = upgrade ] && dpkg --compare-versions "$2" lt 1.2; then
                fi
        fi
 fi
+if [ "$1" = upgrade ] && dpkg --compare-versions "$2" lt 3.02; then
+       # replaced by symlink
+       rm -rf /usr/share/doc/ikiwiki/examples
+fi
index 2af69a5f793753418b8a31a4e6376ccb41479f90..0a7ce7a267e43c0999d6e468f7e6844abbc8d660 100755 (executable)
@@ -1,45 +1,19 @@
 #!/usr/bin/make -f
+%:
+       dh $@
 
-build: build-stamp
-build-stamp:
-       dh_testdir
-       perl Makefile.PL PREFIX=/usr INSTALLDIRS=vendor
-       $(MAKE) -C po
-       $(MAKE)
-       $(MAKE) test
-       touch build-stamp
+override_dh_auto_configure:
+       # keeps it out of /usr/local
+       dh_auto_configure -- PREFIX=/usr
 
-clean:
-       dh_testdir
-       dh_testroot
-       rm -f build-stamp
-       perl Makefile.PL
-       if [ -e Makefile ]; then $(MAKE) realclean; fi
-       dh_clean
-
-binary-arch: build
+override_dh_compress:
+       # avoid compressing files in the doc wiki
+       dh_compress -Xhtml
 
-binary-indep: build
-       dh_testdir
-       dh_testroot
-       dh_clean -k
-       $(MAKE) pure_install DESTDIR=$(shell pwd)/debian/ikiwiki
-       dh_install wikilist etc/ikiwiki
-       dh_installdocs html
-       dh_installexamples doc/examples/*
-       dh_link usr/share/common-licenses/GPL-2 usr/share/doc/ikiwiki/html/GPL
-       dh_installchangelogs
-       dh_compress -X html
-       dh_fixperms
-       dh_perl
-       dh_installdeb
-       dh_gencontrol
-       dh_md5sums
-       dh_builddeb
+override_dh_auto_clean:
+       # distclean moans about MANIFEST, this is quieter
+       if [ -e Makefile ]; then $(MAKE) realclean; fi
 
 # Not intended for use by anyone except the author.
 announcedir:
        @echo ${HOME}/src/ikiwiki/doc/news
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary
index 8276c08334bef4645f242325af7a99ecd619941e..8e382bd773dba1f5fc6db1e03414bef214a4d884 100644 (file)
@@ -6,7 +6,7 @@ This wiki serves as the home for the ikiwiki wiki engine, providing collaborativ
 
 * Rather than inventing yet another simplistic, linear version control system, ikiwiki uses a standard version control system such as [[Subversion|rcs/svn]] or [[rcs/Git]].  You can edit a wiki by committing to your repository, as well as through a traditional web interface.  This makes ikiwiki ideal for collaborative software development; just keep your wiki in version control next to your software.  You can also take full advantage of the features of these systems; for instance, you can keep a local branch of your wiki via [[rcs/Git]].
 
-* You can turn any set of pages into a [[ikiwiki/blog]] or similar news feed,
+* You can turn any set of pages into a [[blog]] or similar news feed,
 * complete with RSS and Atom support.  You can run your weblog on ikiwiki (and [[many_people_do|ikiwikiusers]]), run a Planet-like [[aggregator|plugins/aggregate]] for external feeds, or keep a [[TODO]] and [[bug|bugs]] list with tags for completed items.
 
 * ikiwiki provides a wiki compiler, designed to transform your wiki content into a set of static pages.  You can then serve these pages as static content.  ikiwiki will not fall over during a Slashdotting, because page views don't require the ikiwiki CGI; as long as your web server can keep up, your site will survive.  Furthermore, you can choose whether you want to run the ikiwiki CGI for web edits or only handle commits to the underlying version control system; you can even run ikiwiki privately and just manually copy the content to another server.  So if you want to put a wiki up on a server without installing any software on that server, try ikiwiki.
@@ -19,7 +19,7 @@ Bus connections
 * Bus Nr. 02 - **Wiki Developers Tour** - next stop: [MeatballWiki TourBusStop](http://www.usemod.com/cgi-bin/mb.pl?TourBusStop)
 * Bus Nr. 42 - **Software Developers Tour** - next stop: [Ward's Wiki TourBusStop](http://c2.com/cgi/wiki?TourBusStop)
 
-[[meatballwiki TourBusMap]]
+[[!meatballwiki TourBusMap]]
 
 Famous sights to visit here at **ikiwiki**
 ==========================================
diff --git a/doc/anchor.mdwn b/doc/anchor.mdwn
new file mode 100644 (file)
index 0000000..012e52f
--- /dev/null
@@ -0,0 +1,3 @@
+ikiwiki works with anchors in various situations.
+
+This page accumulates links to the concept of anchors.
index 11e744b109ad927efb8c58fa55e856dd9125035a..d2bec90f0459d9016461293bb4c68fa8849f078c 100644 (file)
@@ -1,6 +1,4 @@
-Wiki admins can ban users via their Preferences.
-
-The list of banned users is space delimited.
+Banned users can be configured in the setup file.
 
 If a banned user attempts to use the ikiwiki CGI, they will receive a 403
 Forbidden webpage indicating they are banned.
index 29f632375729735a650cda14599d5d1c6dd8dae9..8392884ebc6c62d9d58a5819f35c1efaadeb9be8 100644 (file)
@@ -8,14 +8,19 @@ It currently includes these pages:
 * [[sandbox]]
 * [[shortcuts]]
 * [[templates]]
-* [[ikiwiki/blog]]
 * [[ikiwiki/formatting]]
 * [[ikiwiki/markdown]]
 * [[ikiwiki/openid]]
 * [[ikiwiki/pagespec]]
-* [[ikiwiki/PreprocessorDirective]]
+* [[ikiwiki/directive]]
 * [[ikiwiki/subpage]]
 * [[ikiwiki/wikilink]]
 
 As well as a few other files, like [[favicon.ico]], [[local.css]],
 [[style.css]], and some icons.
+
+Note that an important property of the basewiki is that it should be
+self-contained. That means that the pages listed above cannot link
+to pages outside the basewiki. Ikiwiki's test suite checks that the
+basewiki is self-contained, and from time to time links have to be
+removed (or replaced with `iki` [[shortcuts]]) to keep this invariant.
index 05834e0794bc3329c82c0dbb0f8e5d880953e1ff..4187c1162e30e34021ffe06ae1de31bd45b5b11b 100644 (file)
@@ -4,4 +4,4 @@ All wikis are supposed to have a [[SandBox]], so this one does too.
 
 ----
 
-This wiki is powered by [ikiwiki](http://ikiwiki.info/).
+This wiki is powered by [[ikiwiki]].
diff --git a/doc/blog.mdwn b/doc/blog.mdwn
new file mode 100644 (file)
index 0000000..c4a379f
--- /dev/null
@@ -0,0 +1,4 @@
+Ikiwiki allows turning any page into a weblog, by using the
+[[ikiwiki/directive/inline]] [[ikiwiki/directive]]. For example:
+
+       \[[!inline pages="blog/* and !*/Discussion" show="10" rootpage="blog"]]
index 8886856252c8e233a5d59d63ef90381bea7940cd..f634b6e78a904b6d9ab0e2ecb70db818ef2ef423 100644 (file)
@@ -3,7 +3,7 @@ elsewhere. Link items to [[bugs/done]] when done.
 
 Also see the [Debian bugs](http://bugs.debian.org/ikiwiki).
 
-[[inline pages="bugs/* and !bugs/done and !bugs/discussion and 
+[[!inline pages="bugs/* and !bugs/done and !bugs/discussion and 
 !link(patch) and !link(bugs/done) and !bugs/*/*"
 feedpages="created_after(bugs/no_commit_mails_for_new_pages)"
 actions=yes rootpage="bugs" postformtext="Add a new bug titled:" show=0]]
diff --git a/doc/bugs/Aggregated_Atom_feeds_are_double-encoded.mdwn b/doc/bugs/Aggregated_Atom_feeds_are_double-encoded.mdwn
new file mode 100644 (file)
index 0000000..fbdc58d
--- /dev/null
@@ -0,0 +1,22 @@
+The Atom feed from <http://planet.collabora.co.uk/>
+get "double-encoded" (UTF-8 is decoded as Latin-1 and re-encoded as
+UTF-8) when aggregated with IkiWiki on Debian unstable. The RSS 1.0
+and RSS 2.0 feeds from the same Planet are fine. All three files
+are in fact correct UTF-8, but IkiWiki mis-parses the Atom.
+
+This turns out to be a bug in XML::Feed, or (depending on your point
+of view) XML::Feed failing to work around a design flaw in XML::Atom.
+When parsing RSS it returns Unicode strings, but when parsing Atom
+it delegates to XML::Atom's behaviour, which by default is to strip
+the UTF8 flag from strings that it outputs; as a result, they're
+interpreted by IkiWiki as byte sequences corresponding to the UTF-8
+encoding. IkiWiki then treats these as if they were Latin-1 and
+encodes them into UTF-8 for output.
+
+I've filed a bug against XML::Feed on CPAN requesting that it sets
+the right magical variable to change this behaviour. IkiWiki can
+also apply the same workaround (and doing so should be harmless even
+when XML::Feed is fixed); please consider merging my 'atom' branch,
+which does so. --[[smcv]]
+
+[[!tag patch done]]
diff --git a/doc/bugs/Allow_overriding_of_symlink_restriction.mdwn b/doc/bugs/Allow_overriding_of_symlink_restriction.mdwn
new file mode 100644 (file)
index 0000000..efdd900
--- /dev/null
@@ -0,0 +1,139 @@
+There is currently a restriction in ikiwiki that there cannot be any symlinks in the source path.  This is to deal with a security issue discussed [[here|security#index29h2]].  The issue, as I understand it, is that someone might change a symlink and so cause things on the server to be published when the server admin doesn't want them to be.
+
+I think there are two issues here:
+
+ - Symlinks with the source dir path itself, and
+ - Symlinks inside the source directory.
+
+The first appears to me to be less of a security issue.  If there is a way for a malicious person to change where that path points, then you have problems this check isn't going to solve.  The second is quite clearly a security issue - if someone were to commit a symlink into the source dir they could cause lots of stuff to be published that shouldn't be.
+
+> Correct. However, where does the revision controlled source directory end? Ikiwiki has no way
+> of knowing. It cannot assume that `srcdir` is in revision control, and
+> everything outside is not. For example, ikiwiki's own source tree has the
+> doc wiki source inside `ikiwiki/doc`. So to fully close the source dir
+> symlink issue, it's best to, by default, assume that the revision
+> controlled directories could go down arbitrarily deep, down to the root of
+> the filesystem. --[[Joey]]
+
+>> Fair point.
+
+The current code seems to check this constraint at the top of IkiWiki/Render.pm at the start of refresh().  It seems to only check the source dir itself, not the subdirs.  Then it uses File::Find to recuse which doesn't follow symlinks.
+
+Now my problem:  I have a hosted server where I cannot avoid having a symlink in the source path.  I've made a patch to optionally turn off the symlink checking in the source path itself.  The patch would still not follow symlinks inside the source dir.  This would seem to be ok security-wise for me as I know that path is ok and it isn't going to change on me.
+
+> BTW, if you have a problem, please file it in [[todo]] or [[bugs]] in the
+> future. Especially if you also have a patch. :-) --[[Joey]]
+
+>> Well, I was unsure I wasn't missing something.  I wanted to discuss the concept of the patch as much as submit the patch.  But, ok :)
+
+Is there a huge objection to this patch?
+
+>>> [[patch]] updated.
+
+    diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
+    index 990fcaa..0fb78ba 100644
+    --- a/IkiWiki/Render.pm
+    +++ b/IkiWiki/Render.pm
+    @@ -260,13 +260,15 @@ sub prune ($) {
+     
+     sub refresh () {
+       # security check, avoid following symlinks in the srcdir path
+    -  my $test=$config{srcdir};
+    -  while (length $test) {
+    -          if (-l $test) {
+    -                  error("symlink found in srcdir path ($test)");
+    -          }
+    -          unless ($test=~s/\/+$//) {
+    -                  $test=dirname($test);
+    +  if (! $config{allow_insecure_symlinks_in_path_to_srcdir}) {
+    +          my $test=$config{srcdir};
+    +          while (length $test) {
+    +                  if (-l $test) {
+    +                          error("symlink found in srcdir path ($test)");
+    +                  }
+    +                  unless ($test=~s/\/+$//) {
+    +                          $test=dirname($test);
+    +                  }
+               }
+       }
+       
+    diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup
+    index 10cb3da..eb86e49 100644
+    --- a/doc/ikiwiki.setup
+    +++ b/doc/ikiwiki.setup
+    @@ -203,4 +203,10 @@ use IkiWiki::Setup::Standard {
+       # For use with the attachment plugin, a program that returns
+       # nonzero if its standard input contains an virus.
+       #virus_checker => "clamdscan -",
+    +  
+    +  # The following setting allows symlinks in the path to your
+    +  # srcdir.  Symlinks are still not followed within srcdir.
+    +  # Allowing symlinks to be followed, even in the path to srcdir,
+    +  # will make some setups insecure.
+    +  #allow_insecure_symlinks_in_path_to_srcdir => 0,
+     }
+
+> No, I don't have a big objection to such an option, as long as it's
+> extremely well documented that it will make many setups insecure.
+> It would be nice to come up with an option name that makes clear that
+> it's allowing symlinks in the path to the `srcdir`, but still not inside
+> the `srcdir`.
+> --[[Joey]]
+
+>> Slightly modified version of patch applied. --[[Joey]]
+
+>> Ok, I'll try to get it cleaned up and documented.
+
+There is a second location where this can be an issue.  That is in the
+front of the wrapper.  There the issue is that the path to the source dir
+as seen on the cgi server and on the git server are different - each has
+symlinks in place to support the other.  The current wrapper gets the
+absolute path to the source dir, and that breaks things for me.  This is a
+slightly different, albeit related, issue to the one above.  The following
+patch fixes things.  Again, patch inline.  Again, this patch could be
+cleaned up :).  I just wanted to see if there was any chance of a patch
+like this being accepted before I bothered.
+
+>>> Patch updated:
+
+    index 79b9eb3..ce1c395 100644
+    --- a/IkiWiki/Wrapper.pm
+    +++ b/IkiWiki/Wrapper.pm
+    @@ -4,14 +4,14 @@ package IkiWiki;
+     
+     use warnings;
+     use strict;
+    -use Cwd q{abs_path};
+     use Data::Dumper;
+     use IkiWiki;
+    +use File::Spec;
+     
+     sub gen_wrapper () {
+    -       $config{srcdir}=abs_path($config{srcdir});
+    -       $config{destdir}=abs_path($config{destdir});
+    -       my $this=abs_path($0);
+    +       $config{srcdir}=File::Spec->rel2abs($config{srcdir});
+    +       $config{destdir}=File::Spec->rel2abs($config{destdir});
+    +       my $this=File::Spec->rel2abs($0);
+            if (! -x $this) {
+                    error(sprintf(gettext("%s doesn't seem to be executable"), $this
+            }
+
+> ikiwiki uses absolute paths for `srcdir`, `destdir` and `this` because
+> the wrapper could be run from any location, and if any of them happen to
+> be a relative path, it would crash and burn.
+
+>> Which makes perfect sense.  It is annoying that abs_path() is also
+>> expanding symlinks.
+
+> I think the thing to do might be to make it check if `srcdir` and
+> `destdir` look like an absolute path (ie, start with "/"). If so, it can
+> skip running `abs_path` on them.
+
+>> I'll do that.  I assume something like <code> File::Spec->file_name_is_absolute( $path ); </code> would have more cross-platformy goodness.
+>> hrm.  I might see if <code> File::Spec->rel2abs( $path ) ; </code> will give absolute an path without expanding symlinks.
+>>> Patch using rel2abs() works well - it no longer expands symlinks.
+
+>>>> That patch is applied now. --[[Joey]]
+
+[[!tag done]]
index b5bcd30d2ab51c98bf6db28dc87d937dee293a17..031576f0075fb7421d2a20a69942b545e62b4caa 100644 (file)
@@ -10,4 +10,4 @@ with my pretty standard Ubuntu gutsy Firefox installation?  --[[tschwinge]]
 > is already valid utf-8, when in fact it's not yet been decoded. So I
 > removed that line to fix it. --[[Joey]]
 
-[[tag done]]
+[[!tag done]]
diff --git a/doc/bugs/Broken_URL_to_your_blog_script.mdwn b/doc/bugs/Broken_URL_to_your_blog_script.mdwn
new file mode 100644 (file)
index 0000000..3d6661d
--- /dev/null
@@ -0,0 +1,10 @@
+Joey, I would like to see your blog script I've found
+at [[Tips|tips/blog_script]] page, but it seems that the URL
+(http://git.kitenet.net/?p=joey/home;a=blob_plain;f=bin/blog)
+to its Git repo is broken:
+
+    403 Forbidden - No such project
+
+--[[Paweł|ptecza]]
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/Broken_access_to_Ikiwiki_gitweb.mdwn b/doc/bugs/Broken_access_to_Ikiwiki_gitweb.mdwn
new file mode 100644 (file)
index 0000000..fed6cd0
--- /dev/null
@@ -0,0 +1,19 @@
+I can't check the last changes in Ikiwiki using
+[gitweb](http://git.ikiwiki.info/?p=ikiwiki). It looks like XML
+validation problem with HTML entity.
+
+When I click a appropriate link on a [[git]] page, then I can only
+see the following error message. --[[Paweł|ptecza]]
+
+    <div class="title">&nbsp;</div>
+    -------------------^
+
+> I don't see or understand the problem. I've tried History links as well
+> as the diff links in RecentChanges, both seem to be working. --[[Joey]]
+
+>> Hm. It's strange. I really could see the error message like above
+>> when I sent my report. It seems that <http://git.ikiwiki.info/?p=ikiwiki>
+>> URL works now. So, we should be happy that it was self-fixed bug ;)
+>> --[[Paweł|ptecza]]
+
+>>> If it happens again, maybe take a full dump of the page? [[done]]
diff --git a/doc/bugs/CGI__44___formbuilder__44___non-existent_field_address.mdwn b/doc/bugs/CGI__44___formbuilder__44___non-existent_field_address.mdwn
new file mode 100644 (file)
index 0000000..ef74deb
--- /dev/null
@@ -0,0 +1,59 @@
+Error received when clicking on the "edit" link:
+
+> `Error: [CGI::FormBuilder::AUTOLOAD] Fatal: Attempt to address
+> non-existent field 'text' by name at
+> /home/tealart/bin/share/perl/5.8.4/IkiWiki/CGI.pm line 112`
+
+Error received when following a "Create New Page" (eg. ?) link: 
+
+> `Error: [CGI::FormBuilder::AUTOLOAD] Fatal: Attempt to address
+> non-existent field 'param' by name at
+> /home/tealart/bin/share/perl/5.8.4/IkiWiki/Plugin/editpage.pm line 122`
+
+I could probably find several other flavors of this error if I went
+looking, but I trust you get the idea. 
+
+The CGI starts to render (this isn't the "you forgot to set the
+permissions/turn on the CGI" error) and then fails. 
+
+Further details:
+
+- Running on shared hosting (dreamhost; but everything compiles,
+  dependencies installed, the site generates perfectly, other CGIs
+  work, the file permissions work).
+
+- It's running perl 5.8.4, but I did upgrade gettext to 0.17
+
+- the server is running gcc v3.3.5 (at this point, this is the main
+  difference between the working system and my box.)
+
+- I've removed the locale declarations from both the config file and
+  the environment variable.
+
+- I've also modified the page template and have my templates in a non
+  standard location. The wiki compiles fine, with the template, but
+  might this be an issue? The CGI script doesn't (seem) to load under
+  the new template, but I'm not sure how to address this issue.
+
+- All of the required/suggested module dependencies are installed
+  (finally) to the latest version including (relevantly)
+  CGI::FormBuilder 3.0501.
+
+- I'm running ikiwiki v3.08. Did I mention that it works perfectly in
+  nearly every other way that I've managed to test thusfar?
+
+----
+
+> I suspect that your perl is too old and is incompatible with the version of CGI::FormBuilder you have installed.
+> 
+> Is so, it seems likely that the same error message can be reproduced by running a simple command like this at the command line:
+> 
+>     perl -e 'use warnings; use strict; use CGI::FormBuilder; my $form=CGI::FormBuilder->new; $form->text("boo")'
+> 
+> --[[Joey]]
+
+> > nope, that command produces no output. :/
+> > 
+> > I considered downgrading CGI::FormBuilder but I saw evidence of previous versions being incompatible with ikiwiki so I decided against that.
+> > 
+> > -- [[tychoish]]
index 1b09608c6c5b380c95f22a3caae7597a99b9ee38..e4b0fd4482da3fd33fa52af82b1b2e18b943784c 100644 (file)
@@ -1,5 +1,5 @@
 The "ikwiki.cgi?page=index&do=edit" function has a problem
-when running with [[debpkg thttpd]] or [[debpkg mini-httpd]]:
+when running with [[!debpkg thttpd]] or [[!debpkg mini-httpd]]:
 for some reason the headers ikiwiki outputs are transmitted
 as the page content. Surprisingly, the "do=prefs" function
 works as expected.
@@ -15,7 +15,7 @@ Here is what it looks like in iceweasel:
     <html>
     (...)
 
-Ikiwiki runs fine with [[debpkg boa]].
+Ikiwiki runs fine with [[!debpkg boa]].
 
 --[[JeremieKoenig]]
 
@@ -64,6 +64,45 @@ Why do they appear two times with conflicting values in the very same hashes?
 >>> where ikiwiki might output to stderr, and that's the right thing to do.
 >>> So I don't see any way to address this in ikiwiki. --[[Joey]]
 
->>>> (reported as [[debbug 437927]] and [[debbug 437932]]) --[[JeremieKoenig]]
+>>>> (reported as [[!debbug 437927]] and [[!debbug 437932]]) --[[JeremieKoenig]]
 
 Marking [[done]] since it's not really an ikiwiki bug. --[[Joey]]
+
+----
+
+I'm using boa and getting some odd behaviour if I don't set the `umask`
+option in the config file.  Editing a page through the web interface and
+hitting "Save Page" regenerates the `index.html` file with no world-read
+permissions.  As a result, the server serves a "403 - Forbidden" error page
+instead of the page I was expecting to return to.
+
+There are only two ways I found to work around this: adding a `umask 022`
+option to the config file, or re-compiling the wiki from the command line
+using `ikiwiki --setup`.  Setting up a git back-end and re-running `ikiwiki
+--setup` from inside a hook had no effect; it needed to be at the terminal.
+--Paul
+
+> Since others seem to have gotten ikiwiki working with boa, 
+> I'm guessing that this is not a generic problem with boa, but that
+> your boa was started from a shell that had an unusual umask and inherited
+> that. --[[Joey]] 
+
+>> That's right; once I'd worked out what was wrong, it was clear that any
+>> webserver should have been refusing to serve the page.  I agree about the
+>> inherited umask; I hadn't expected that.  Even if it's unusual, though, it
+>> probably won't be uncommon - this was a stock Ubuntu 9.04 install.  --Paul
+
+(I'm new to wiki etiquette - would it be more polite to leave these details
+on the wiki, or to remove them and only leave a short summary?  Thanks.
+--Paul)
+
+> Well, I just try to keep things understandable and clear, whether than
+> means deleting bad old data or not. That said, this page is a bug report,
+> that was already closed. It's generally better to open a new bug report
+> rather than edit an old closed one. --[[Joey]] 
+                                      
+>> Thanks for the feedback, I've tidied up my comment accordingly.  I see
+>> your point about the bug; sorry for cluttering the page up.  I doubt it's
+>> worth opening a new page at this stage, but will do so if there's a next
+>> time.  The solution seems worth leaving, though, in case anyone else in my
+>> situation picks it up.  --Paul
index 11be2b7b77cf6b0d6f316141fe33bb5aab1a8ff9..91c2eae60a046d16c5e37aeb6689f4ed3307f40b 100644 (file)
@@ -5,3 +5,65 @@ When you click on the question mark to create the page, you get *Error: bad page
 > Is it a valid wikilink?  Should Iki prevent the page from being created? --[[sabr]], 2 months later
 
 This type of page name (with leading slash) also gets created by the aggregate plugin: /cgi-bin/ikiwiki.cgi?page=%2FCalculated_Risk&from=news%2FAll_Stories&do=create  I'm now pretty convinced that Iki should handle this without error.  I'll investigate if I can find the time.
+
+> As documented on [[ikiwiki/subpage/linkingrules]], such an absolute
+> link works perfectly when the linked page already exists.
+>
+> The CGI behaviour is thus not consistent with the general linking
+> rules, which is annoying for me : I'm using templates to generate
+> links to pages that may not exist yet, and I would like the "right"
+> path to be selected by default, instead of the usual
+> <current>/subdir/subpage, when a user clicks the "?" link to create
+> the missing page ; that's why I'm using absolute paths.
+>
+>> Totally agree, this had only not been addressed due to lack of time on
+>> my part. (I have about 50 ikiwiki things on my todo list.) --[[Joey]]
+>
+> Anyway, having the CGI consider invalid an otherwise valid wikilink
+> seems a bit weird to me, so I had a look to the code, and here is a
+> patch that should fix this issue ; I proceeded the only way I could
+> find to prevent side-effects : the only place where I use `$origpage`
+> is a match, so no function at all is fed with a `$page` with 
+> leading slash :
+>
+> -- intrigeri
+
+
+       diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
+       index 99cead6..23d9616 100644
+       --- a/IkiWiki/CGI.pm
+       +++ b/IkiWiki/CGI.pm
+       @@ -305,9 +305,11 @@ sub cgi_editpage ($$) {
+               my $page=$form->field('page');
+               $page=possibly_foolish_untaint($page);
+               if (! defined $page || ! length $page ||
+       -           file_pruned($page, $config{srcdir}) || $page=~/^\//) {
+       +           file_pruned($page, $config{srcdir})) {
+                       error("bad page name");
+               }
+       +       my $origpage=$page;
+       +       $page =~ s#^/##;
+        
+               my $baseurl=$config{url}."/".htmlpage($page);
+               
+       @@ -425,6 +427,7 @@ sub cgi_editpage ($$) {
+                                   $from ne $form->field('from') ||
+                                   file_pruned($from, $config{srcdir}) ||
+                                   $from=~/^\// ||
+       +                           $origpage=~/^\// ||
+                                   $form->submitted eq "Preview") {
+                                       @page_locs=$best_loc=$page;
+                               }
+
+
+> [[Applied|done]]. BTW, I also accept full git changesets, if you like
+> having your name in commit logs. :-)
+
+>> Thanks. I'm considering setting up a public Git repository with topic branches, so that :
+
+>> - I can simply ask you to pull from there, next time
+>> - I have a tool to go on learning the beast (i.e. Git)
+
+>> -- intrigeri
+
+[[!tag patch]]
diff --git a/doc/bugs/Cannot_inline_pages_with_apostrophes_in_title.mdwn b/doc/bugs/Cannot_inline_pages_with_apostrophes_in_title.mdwn
new file mode 100644 (file)
index 0000000..7daf52f
--- /dev/null
@@ -0,0 +1,5 @@
+If I create a page whose title contains an apostrophe, then inlining that
+page produces nothing.  It looks like the inline plugin is failing to do
+the translation from apostrophe to `_39_` that other parts of the system do, so although one can make wikilinks to such pages and have them detected as existing (for instance, by the conditional plugin), inline looks in the wrong place and doesn't see the page.
+
+> I can't reproduce that (btw, an apostrophe would be `__39__`) --[[Joey]]
index f1ccf589689c1c95ede9d83423c597d05429a69f..22b1c2cb5e2e5e5c23e2b9135a5933391d45df56 100644 (file)
@@ -1,5 +1,5 @@
 In setting up my wiki I followed the [[setup]] instruction which point
-to an [[ikiwiki.setup]] file that contains "verbose => 0".
+to an ikiwiki.setup file that contains "verbose => 0".
 
 I hadn't noticed that setting in there, but later when I changed my
 standard command of:
diff --git a/doc/bugs/Comments_link_is_to_index.html_if_usedirs_is_on.mdwn b/doc/bugs/Comments_link_is_to_index.html_if_usedirs_is_on.mdwn
new file mode 100644 (file)
index 0000000..6df3ccd
--- /dev/null
@@ -0,0 +1,5 @@
+When a page links to its own #comments anchor you get a link like
+"index.html#comments" rather than "./#comments". Fixed in commit 0844bd0b
+on my 'comments' branch. --[[smcv]]
+
+[[!tag patch done]]
diff --git a/doc/bugs/Does_IkiWiki::Setup::load__40____41___really_return_a_hash__63__.mdwn b/doc/bugs/Does_IkiWiki::Setup::load__40____41___really_return_a_hash__63__.mdwn
new file mode 100644 (file)
index 0000000..6facec8
--- /dev/null
@@ -0,0 +1,10 @@
+Yes, it's me again :-)
+
+Shouldn't this print a bunch of output (admittedly not very nicely formatted).
+<pre>
+[ 10 rocinante  ~/tmp ]  ikiwiki --dumpsetup foo.setup
+[ 11 rocinante  ~/tmp ]  perl -M'IkiWiki::Setup' -e 'print IkiWiki::Setup::load("foo.setup");'
+</pre>
+I get nothing with ikiwiki 2.63 [[DavidBremner]]
+
+> The docs were wrong, it populates `%config`. --[[Joey]] [[done]]
diff --git a/doc/bugs/Dupe_entry_in_Bundle::IkiWiki::Extras.pm.mdwn b/doc/bugs/Dupe_entry_in_Bundle::IkiWiki::Extras.pm.mdwn
new file mode 100644 (file)
index 0000000..2361127
--- /dev/null
@@ -0,0 +1,5 @@
+Authen::Passphrase
+
+is entered twice in the .pm file.
+
+[[done]]
diff --git a/doc/bugs/Error:_Your_login_session_has_expired._.mdwn b/doc/bugs/Error:_Your_login_session_has_expired._.mdwn
new file mode 100644 (file)
index 0000000..046d6e1
--- /dev/null
@@ -0,0 +1,44 @@
+I keep getting:
+
+       Error: Your login session has expired.
+
+Whilst trying to edit http://hugh.vm.bytemark.co.uk/ikiwiki.cgi via OpenID. Any ideas?
+
+
+       iki@hugh:~$ dpkg -l | grep openid
+       ii  libnet-openid-consumer-perl     0.14-4                library for consumers of OpenID iden
+       tities
+       iki@hugh:~$
+
+> This error occurs if ikiwiki sees something that looks like a CSRF
+> attack. It checks for such an attack by embedding your session id on the
+> page edit form, and comparing that id with the session id used to post
+> the form.
+> 
+> So, somehow your session id has changed between opening the edit form and
+> posting it. A few ways this could happen:
+> 
+> * Genuine CSRF attack (unlikely)
+> * If you logged out and back in, in another tab, while the edit form was
+>   open.
+> * If `.ikiwiki/sessions.db` was deleted/corrupted while you were in the
+>   midst of the edit.
+> * If some bug in CGI::Session caused your session not to be saved to the
+>   database somehow.
+> * If your browser didn't preserve the session cookie across the edit
+>   process, for whatever local reason.
+> * If you were using a modified version of `editpage.tmpl`, and 
+>   it did not include `FIELD-SID`.
+> * If you upgraded from an old version of ikiwiki, before `FIELD-SID` was
+>   added (<= 2.41), and had an edit form open from that old version, and
+>   tried to save it using the new.
+>  
+> I don't see the problem editing the sandbox there myself, FWIW.
+> (BTW, shouldn't you enable the meta plugin so RecentChanges displays
+> better?)
+> --[[joey]]
+
+
+Thanks for you excellent analysis. The bug was due to old pre-3.0 **templates** laying about. After deleting them, ikiwiki defaults to its own templates. Clever. :-)
+
+[[bugs/done]]
index 54f1f3d810e906d20eb4121086685420e4424414..7559e6d0a24485c1c0585791f271708dc7c1cab2 100644 (file)
@@ -7,4 +7,69 @@ Windows does not support filenames containing any of these characters: `/ \ * :
 > I take it this is a problem when checking out a wiki in windows, not when
 > browsing to urls that have colons in them from windows? --[[Joey]]
 
->> Correct.  You can't directly check out a wiki's repository from Windows if it includes filenames with those characters; you will get errors on those filenames.
\ No newline at end of file
+>> Correct.  You can't directly check out a wiki's repository from Windows if it includes filenames with those characters; you will get errors on those filenames.
+
+>>> Ok, first, if a windows user fails to check out ikiwiki's own svn^Wgit
+>>> repo on windows due to the colons, that seems to be a bug in svn^Wgit
+>>> on windows -- those programs should deal with colons in filenames being
+>>> checked in/out somehow. Like they deal with windows using backslash
+>>> rather than slash, presumably. And there's nothing ikiwiki can do if
+>>> the source repo it's working on has a file with a problem character
+>>> added to it, since the breakage will happen at the revision control
+>>> system level.
+
+>>>> Just a quick note that the version control community generally doesn't
+>>>> agree with that view.  They'll store what you ask them to store.  If you
+>>>> want to work cross platform, then you need to make sure that all
+>>>> your file names work on all the platforms you're interested in.  (Note: many systems will
+>>>> warn on commit, but not all.  Many systems also have a way to fix
+>>>> the problem without checking out, but not all.)  Another common place for this to
+>>>> arise is case insensitive file systems.  If you have two files committed
+>>>> that differ only in case, then you cannot check out on a Mac in most systems.
+
+>>> OTOH, there are some simple mods to ikiwiki that can make it escape
+>>> colons etc the same way it already escapes other problem characters
+>>> like "*", "?", etc. Without actually testing it, it should suffice to
+>>> edit `IkiWiki.pm` and modify `titlepage` and `linkpage`, removing the
+>>> colon from the character class in each. Also modify the
+>>> `wiki_file_regexp` similarly. Then ikiwiki will read and
+>>> write files with escaped colons, avoiding the problem.
+>>>
+>>> So that's a simple fix, but on the gripping hand, I can't just make
+>>> that change, because it would break all existing unix-based
+>>> wikis that actually contain colons in their filenames, requiring an
+>>> annoying transition. I could do a OS test and do it in Windows, but then
+>>> there would be interop problems if a Windows and non-windows system both
+>>> acted on the same wiki source.
+
+>>>> I haven't checked the source, but need this break existing wikis?
+>>>> I can imagine a system where a colon gets converted to something safe,
+>>>> and the safe encoding gets converted back to a colon.  But if you
+>>>> already have a colon, that doesn't get converted and stays a colon, and
+>>>> so it should still work shouldn't it?  The only
+>>>> problem would be with pages that already have the 'safe encoding for a colon'.
+>>>> They'll suddenly change names. Well, I should finish frying my current fish
+>>>> before taking on something new, so I'll shut up now :). -- [[Will]]
+
+>>>>> If `linkpage()` is changed to escape colons, then links to pages 
+>>>>> with literal colons in their names will stop working; ikiwiki will
+>>>>> instead look for page names with escaped colons. --[[Joey]]
+
+>>> So, I guess it has to be a config option, possibly defaulting on
+>>> when the OS is Windows. And if being able to checkout/etc the wiki
+>>> source on windows systems is desired, you'd have to remember to turn
+>>> that on when setting up a wiki, even if the wiki was hosted on unix.
+>>>
+>>> Ok, `wiki_file_chars` config option added, set to 
+>>> `"-[:alnum:]+/._"` to exclude colons from filenames read or written by
+>>> ikiwiki. [[done]]
+>>> 
+>>> BTW, I suspect there are lots of other problems with actually running
+>>> ikiwiki on windows, including its assumption that the directory
+>>> separator is "/". Windows will be supported when someone sends me a
+>>> comprehansive and not ugly or performance impacting patch. :-) --[[Joey]]
+
+> Speaking of Windows filename problems, how do I keep directories ending in a
+> period from being created? The following didn't seem to work.
+> `wiki_file_chars => "-[:alnum:]+/._",`
+> `wiki_file_regex => '[-[:alnum:]+_]$',`
diff --git a/doc/bugs/Git:_web_commit_message_not_utf-8.mdwn b/doc/bugs/Git:_web_commit_message_not_utf-8.mdwn
new file mode 100644 (file)
index 0000000..08247dd
--- /dev/null
@@ -0,0 +1,17 @@
+The message generated for web commits:
+
+> web commit by mädduck
+
+is not utf-8 encoded before passed to Git (which uses utf-8 as default encoding for commit messages). This causes a wrongly-encoded log entry, and makes ikiwiki spew warnings as it creates `recentchanges`:
+
+    utf8 "\xF6" does not map to Unicode at /usr/share/perl5/IkiWiki/Rcs/git.pm line 36, <$OUT> line 57.
+    Malformed UTF-8 character (unexpected non-continuation byte 0x6e, immediately after start byte 0xf6) in pattern match (m//) at /usr/share/perl5/IkiWiki/Rcs/git.pm line 393.
+    utf8 "\xF6" does not map to Unicode at /usr/share/perl5/IkiWiki/Rcs/git.pm line 36, <$OUT> line 5.
+
+(This is version 2.53.3~bpo40+1 for lack of a newer backport for sarge)
+
+Please make sure that commit messages for Git are always utf-8.
+
+This is a change by user `mädduck` to trigger the error.
+
+> [[Fixed|done]] both on the commit and log sides. --[[Joey]] 
diff --git a/doc/bugs/Graphviz_plug-in_directive_changed_in_2.60.mdwn b/doc/bugs/Graphviz_plug-in_directive_changed_in_2.60.mdwn
new file mode 100644 (file)
index 0000000..2924951
--- /dev/null
@@ -0,0 +1,11 @@
+The directive for the graphviz plug-in changed from 'graph' to 'graphviz' in ikiwiki-2.60. Was this intentional?
+
+If yes, the [[plugins/graphviz]] plug-in documentation needs updating, and a heads-up on the news page might not be a bad idea either.
+
+Personally, I like the new directive name better since it will allow us to add other graph plug-ins later.
+
+  -- [[HenrikBrixAndersen]]
+
+> No, that change was not made intentionally. I don't want to bother people
+> with such a transition. Though it would be nice if it had a less generic
+> name. Changed back. [[!tag done]] --[[Joey]]
diff --git a/doc/bugs/HTML-escaped_titles_in_Atom__44___RSS_feeds_don__39__t_validate.mdwn b/doc/bugs/HTML-escaped_titles_in_Atom__44___RSS_feeds_don__39__t_validate.mdwn
deleted file mode 100644 (file)
index 48c1689..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-The Atom and RSS templates use `ESCAPE=HTML` in the title elements. However, HTML-escaped characters aren't valid according to <http://feedvalidator.org/>.
-
-Removing `ESCAPE=HTML` works fine, but I haven't checked to see if there are any characters it won't work for.
-
-For Atom, at least, I believe adding `type="xhtml"` to the title element will work. I don't think there's an equivalent for RSS.
-
-> Removing the ESCAPE=HTML will not work, feed validator hates that just as
-> much. It wants rss feeds to use a specific style of escaping that happens
-> to work in some large percentage of all rss consumers. (Most of which are
-> broken).
-> <http://www.rssboard.org/rss-profile#data-types-characterdata>
-> There's also no actual spec about how this should work.
-> 
-> This will be a total beast to fix. The current design is very clean in
-> that all (well, nearly all) xml/html escaping is pushed back to the
-> templates. This allows plugins to substitute fields in the templates
-> without worrying about getting escaping right in the plugins -- and a
-> plugin doesn't even know what kind of template is being filled out when
-> it changes a field's value, so it can't do different types of escaping
-> for different templates.
->
-> The only reasonable approach seems to be extending HTML::Template with an
-> ESCAPE=RSS and using that. Unfortunately its design does not allow doing
-> so without hacking its code in several places. I've contacted its author
-> to see if he'd accept such a patch.
->
-> (A secondary bug is that using meta title currently results in unnecessry
-> escaping of the title value before it reaches the template. This makes
-> the escaping issues show up much more than they need to, since lots more
-> characters are currently being double-escaped in the rss.)
-> 
-> --[[Joey]]
-
-> Update: Ok, I've fixed this for titles, as a special case, but the
-> underlying problem remains for other fields in rss feeds (such as
-> author), so I'm leaving this bug report open. --[[Joey]]
diff --git a/doc/bugs/HTML_for_parentlinks_makes_theming_hard.mdwn b/doc/bugs/HTML_for_parentlinks_makes_theming_hard.mdwn
new file mode 100644 (file)
index 0000000..0cbef40
--- /dev/null
@@ -0,0 +1,45 @@
+I'm trying to make a pretty theme for ikiwiki and I'm making progress (or at least I think I am :-).  However I've noticed an issue when it comes to theming.  On the front page the wiki name is put inside the "title" span and on all the other pages, it's put in the "parentlinks" span.  See here:
+
+From [my dev home page](http://adam.shand.net/iki-dev/):
+
+<code>
+&lt;div class="header">  
+&lt;span>  
+&lt;span class="parentlinks">  
+&lt;/span>  
+&lt;span class="title">  
+adam.shand.net/iki-dev  
+&lt;/span>  
+&lt;/span>&lt;!--.header-->  
+&lt;/div>  
+</code>
+
+From a sub-page of [my dev home page](http://adam.shand.net/iki-dev/recipes/navajo_fry_bread/):
+
+<code>
+&lt;div class="header">  
+&lt;span>  
+&lt;span class="parentlinks">  
+&lt;a href="../">adam.shand.net/iki-dev</a>/  
+&lt;/span>  
+&lt;span class="title">  
+recipes 
+&lt;/span>   
+&lt;/span>&lt;!--.header-->  
+&lt;/div>  
+</code>
+
+I understand the logic behind doing this (on the front page it is the title as well as the name of the wiki) however if you want to do something different with the title of a page vs. the name of the wiki it makes things pretty tricky.
+
+I'll just modify the templates for my own site but I thought I'd report it as a bug in the hopes that it will be useful to others.
+
+Cheers,  
+Adam.
+
+----
+> I just noticed that it's also different on the comments, preferences and edit pages.  I'll come up with a diff and see what you guys think.  -- Adam.
diff --git a/doc/bugs/HTML_inlined_into_Atom_not_necessarily_well-formed.mdwn b/doc/bugs/HTML_inlined_into_Atom_not_necessarily_well-formed.mdwn
new file mode 100644 (file)
index 0000000..d2f8ca3
--- /dev/null
@@ -0,0 +1,35 @@
+If a blog entry contains a HTML named entity, such as the `&mdash;` produced by [[plugins/rst]] for blockquote citations, it's pasted into the Atom feed as-is. However, Atom feeds don't have a DTD, so named entities beyond `&lt;`, `&gt;`, `&quot;`, `&amp;` and `&apos;` aren't well-formed XML.
+
+Possible solutions:
+
+* Put HTML in Atom feeds as type="html" (and use ESCAPE=HTML) instead
+
+> Are there any particular downsides to doing that ..? --[[Joey]]
+
+>> It's the usual XHTML/HTML distinction. type="html" will always be interpreted as "tag soup", I believe - this may lead to it being rendered differently in some browsers. In general ikiwiki seems to claim to produce XHTML (at least, the default page.tmpl makes it claim to be XHTML Strict). On the other hand, this is a much simpler solution... see escape-feed-html branch in my repository, which I'm now using instead --[[smcv]]
+
+>>> Of course, browsers [probably don't treat xhtml pages as xhtml anyway](http://hixie.ch/advocacy/xhtml).
+>>> And the same content will be treated as html (probably as tag soup) if it's
+>>> in a rss feed.
+
+>>> [[merged|done]]
+
+* Keep HTML in Atom feeds as type="xhtml", but replace named entities with numeric ones,
+  like in the re-escape-entities branch in my repository ([diff here](http://git.debian.org/?p=users/smcv/ikiwiki.git;a=commitdiff;h=c0eb041c65d0653bacf0d4acb7a602e9bda8888e))
+
+>> I can see why you think this is excessively complex! --[[smcv]]
+
+(Also, the HTML in RSS feeds would probably get better interoperability if it was escaped with ESCAPE=HTML rather than being in a CDATA section?)
+
+> Can't see why? --[[Joey]]
+
+>> For a start, `]]>` in content wouldn't break the feed :-) but I was really thinking of non-XML, non-SGML parsers (more tag soup) that don't understand CDATA (I've suffered from CDATA damage when feeding generated code through gtkdoc, for instance). --[[smcv]]
+
+>>> FWIW, the htmlscrubber escapes the `]]>`. (Wouldn't hurt to make that
+>>> more robust tho.)
+>>> 
+>>> ikiwiki has used CDATA from the beginning -- this is the first time
+>>> I've heard about rss 2.0 parsers that didn't know about CDATA.
+>>>
+>>> (IIRC, I used CDATA because the result is more space-efficient and less
+>>> craptacular to read manually.)
index aec5dbc3fef1525e9fa417320d12369efba58b09..7830065356adb1cdfc415a787c435ac1445781b7 100644 (file)
@@ -51,4 +51,5 @@ The patch below fixes this issue:
 [[bugs/done]] ; thanks for the patch. Suprised it worked at all since the
 bad code was added (did it?) --[[Joey]]
 
-Thank you for accepting my patch. I can't see how it could ever have worked with the previous code, no. --[[Brix]]
\ No newline at end of file
+Thank you for accepting my patch. I can't see how it could ever have worked
+with the previous code, no. --[[Brix|HenrikBrixAndersen]]
diff --git a/doc/bugs/INC_location_not_set_correctly_in_make_test.mdwn b/doc/bugs/INC_location_not_set_correctly_in_make_test.mdwn
new file mode 100644 (file)
index 0000000..1d396c8
--- /dev/null
@@ -0,0 +1,24 @@
+'make test' has the following errors:
+
+Can't locate Locale/gettext.pm in @INC (@INC contains: /home/turian/utils//lib/perl5/site_perl/5.8.8/i386-linux-thread-multi /home/turian/utils//lib/perl5/site_perl/5.8.8 . /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.7/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/site_perl/5.8.8 /usr/lib/perl5/site_perl/5.8.7 /usr/lib/perl5/site_perl/5.8.6 /usr/lib/perl5/site_perl/5.8.5 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.7/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.6/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.5/i386-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.8 /usr/lib/perl5/vendor_perl/5.8.7 /usr/lib/perl5/vendor_perl/5.8.6 /usr/lib/perl5/vendor_perl/5.8.5 /usr/lib/perl5/vendor_perl /usr/lib/perl5/5.8.8/i386-linux-thread-multi /usr/lib/perl5/5.8.8) at (eval 254) line 2.
+
+What's weird is that I already have gettext.pm:
+   /home/turian/utils/lib/perl5/lib/i386-linux-thread-multi/Locale/gettext.pm
+
+That directory should be part of @INC, because I have:
+  export PERL5LIB="$PERL5LIB:$UTILS/lib/perl5/lib/i386-linux-thread-multi/"
+in my .bashrc. However, /home/turian/utils/lib/perl5/lib/i386-linux-thread-multi/ does not appear in that @INC line.
+
+How do I get the proper @INC locations set?
+
+> Nothing in ikiwiki touches whatever PERL5DIR setting you may have,
+> so AFAICS, this must be some sort of local configuration problem.
+> How do
+> `/home/turian/utils//lib/perl5/site_perl/5.8.8/i386-linux-thread-multi`
+> and `/home/turian/utils//lib/perl5/site_perl/5.8.8` get into the
+> displayed `@INC`? The likely way seems to be that something in your
+> system sets PERL5LIB to contain those directories, clobbering 
+> the earlier setting in your `.bashrc`.
+> --[[Joey]] 
+
+[[!tag done]]
diff --git a/doc/bugs/IkiWiki::Setup::load__40____41___broken_outside_ikiwiki__63__.mdwn b/doc/bugs/IkiWiki::Setup::load__40____41___broken_outside_ikiwiki__63__.mdwn
new file mode 100644 (file)
index 0000000..e1e29f0
--- /dev/null
@@ -0,0 +1,20 @@
+Hmm, according to the docs, shouldn't the following work?
+<pre>
+[ 74 ikipostal/test ]  ikiwiki --dumpsetup out.setup foo bar
+[ 75 ikipostal/test ]  perl -MIkiWiki::Setup -e'IkiWiki::Setup::load("out.setup");'
+out.setup: Can't use an undefined value as an ARRAY reference at /usr/share/perl5/IkiWiki/Setup.pm line 37.
+BEGIN failed--compilation aborted at (eval 15) line 233.
+</pre>
+
+From looking at the code, it seems that a global hash %config should be 
+initialized somehow.
+
+This is in ikiwiki 2.62.1. I think this call used to work in 2.54 (when you first refactored the setup IIRC)
+
+[[DavidBremner]]
+>> Updated:
+>> It seems that `%config = IkiWiki::defaultsetup();IkiWiki::Setup::load("file");`
+>> works (after `use IkiWiki; use IkiWiki::Setup;`). Of course the other api 
+>> is nicer.      
+
+[[done]], sorry for trouble --[[Joey]]
diff --git a/doc/bugs/IkiWiki::Wrapper_should_use_destdir.mdwn b/doc/bugs/IkiWiki::Wrapper_should_use_destdir.mdwn
new file mode 100644 (file)
index 0000000..6b02c41
--- /dev/null
@@ -0,0 +1,23 @@
+In IkiWiki/Wrapper.pm, the gen_wrapper function finds out what srcdir and
+destdir are set to in the config, but does not use them.
+
+Later in the sub, when a new wiki.cgi wrapper is being created when calling
+ikiwiki --setup /path/to/setup, it will only work if cgi\_wrapper in the
+config file is set to the full path. Otherwise, it creates wiki.cgi in the
+current working directory.  It works with the other wrapper it sets up in
+my config - post\_update (using git), as that shows in the config with a
+full path.
+
+One workaround would be to mention in the setup file that cgi_wrapper has
+to be the full path, not just the file name, but that seems silly when
+destdir is also specified in that file and that's where it should go, and
+$config{destdir} is a known value in the Wrapper.pm file.
+
+> Nowhere in any documentation does
+> it say that cgi\_wrapper is relative to the destdir. 
+> As noted in [[discussion]], there are web server setups
+> that require the cgi be located elsewhere.
+> [[done]] --[[Joey]] 
+
+>> A comment in the generated setup file that all paths should be full
+>> would prevent my (admittedly dumb) error without any drawbacks.
diff --git a/doc/bugs/IkiWiki::Wrapper_should_use_destdir/discussion.mdwn b/doc/bugs/IkiWiki::Wrapper_should_use_destdir/discussion.mdwn
new file mode 100644 (file)
index 0000000..870fa7a
--- /dev/null
@@ -0,0 +1,4 @@
+Just as a point of information, I do not put my cgi wrapper in the dest
+directory. Instead I configure Apache to relate a specific URI to the cgi via
+ScriptAlias. I would not like things to be changed so that the cgi was put in
+the destdir, so I'd vote instead to comment in the `setup\_file`. -- [[Jon]]
diff --git a/doc/bugs/Index_files_have_wrong_permissions.mdwn b/doc/bugs/Index_files_have_wrong_permissions.mdwn
new file mode 100644 (file)
index 0000000..7493772
--- /dev/null
@@ -0,0 +1,14 @@
+ikiwiki has files that are not group-readable:
+
+    -rw------- 1 joseph users  541 Aug 18 12:02 index.atom
+    -rw------- 1 joseph users 2328 Aug 18 12:02 index.html
+    -rw------- 1 joseph users  282 Aug 18 12:02 index.rss
+
+I chmod a+r them, but then when I edit something through the web, its permissions are reverted to only user-readable. How do I resolve this? 
+
+ -- [[JosephTurian]]
+
+> My index files have the correct permissions. Have you tried setting 'umask => 022' in your ikiwiki.setup file?
+>   -- [[HenrikBrixAndersen]]
+
+> > Thanks Henrik, that worked. Bug is [[bugs/done]]. -- [[JosephTurian]]
diff --git a/doc/bugs/Inline_doesn__39__t_wikilink_to_pages.mdwn b/doc/bugs/Inline_doesn__39__t_wikilink_to_pages.mdwn
new file mode 100644 (file)
index 0000000..32f9f12
--- /dev/null
@@ -0,0 +1,100 @@
+It seems that the [[ikiwiki/directive/inline]] directive doesn't generate wikilinks to the pages it includes.  For example I would expect the following to inline all bugs inside this bug report:
+
+\[[!inline pages="bugs/* and !*/discussion and backlink(bugs)" feeds=no postform=no archive=yes show="10"]]
+
+But here it is:
+
+[[!inline pages="bugs/* and !*/discussion and backlink(bugs)" feeds=no postform=no archive=yes show="10"]]
+
+and note that it only included the 'normal' wikilinks (and also note that this page is not marked done even though the done page is inlined).
+One might also wonder if inline would make this page link to any internal links on those inlined pages too, but I think
+that would be overkill.
+
+I'm not even really sure if this is a bug or defined behaviour, but I thought it might work and it didn't.  Regardless,
+the correct behaviour, whichever is decided, should be documented.  -- [[Will]]
+
+It appears that [[ikiwiki/directive/map]] also doesn't wikilink to the pages it links.  Perhaps in each of these
+cases there should be another parameter to the directive that allows linking to switched on.  Just switching
+it on universally at this point might break a number of people's pagespecs.  -- [[Will]]
+
+> There's a simple reason why these directives don't generate a record of a
+> wikilink between them and the pages they include: Semantically, inlining
+> a page is not the same as writing a link to it. Nor is generating a map that
+> lists a page the same as linking to it. I don't think this is a bug.
+> --[[Joey]] 
+
+>> Fair enough.  I guess we can mark this as [[done]] then.
+>>
+>> Just a bit of background on where I was going here... I was looking for
+>> a simpler way of attacking [[todo/tracking_bugs_with_dependencies]].
+>> In particular, rather than introducing changes to the pagespec definition,
+>> I wondered if you could use wiki pages as the defined pagespec and 
+>> introduce a 'match_mutual' function which matches whenever two pages
+>> link to the same third page, then you don't need to alter the pagespec
+>> handling code.
+>>
+>> But that requires being able use use a pagespec to decide what pages
+>> are linked to.  e.g. I want to make an 'openbugs' page that links to all
+>> open bugs.  Then I could make a 'readybugs' page that links to
+>> `backlink(openbugs) and !mutualLink(openbugs)`.  That is, all bugs
+>> that are open and do not themselves link to an open bug.
+>>
+>> The problem with all this is that it introduces an ordering dependency,
+>> as I noted below.  I think the original proposal is better, because it
+>> handles that ordering dependency in the definition of the pagespecs.
+>> --[[Will]]
+
+Here is a patch to make map link to its linked pages (when passed `link="yes"`).  It is a bit problematic in that it uses a pagespec
+to decide what to link to (which is why I wanted it).  However, at the time the pagespec is used the links
+for each page haven't finished being calculated (we're using the pagespec to figure out those links,
+remember).  This means that some pagespec match functions may not work correctly.  Sigh.  
+It would be nice to find a topological ordering of the pages and scan them in that order
+so that everything we need is found before we need it, but this patch doesn't do that (it would be
+complex).
+
+If you just use simple pagespecs you'll be fine.  Unfortunately I really wanted this for more complex
+pagespecs.  -- [[Will]]
+
+    diff --git a/IkiWiki/Plugin/map.pm b/IkiWiki/Plugin/map.pm
+    index 3284931..57c0a7a 100644
+    --- a/IkiWiki/Plugin/map.pm
+    +++ b/IkiWiki/Plugin/map.pm
+    @@ -13,7 +13,7 @@ use IkiWiki 3.00;
+     
+     sub import {
+       hook(type => "getsetup", id => "map", call => \&getsetup);
+    -  hook(type => "preprocess", id => "map", call => \&preprocess);
+    +  hook(type => "preprocess", id => "map", call => \&preprocess, scan => 1);
+     }
+     
+     sub getsetup () {
+    @@ -27,7 +27,9 @@ sub getsetup () {
+     sub preprocess (@) {
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+    -  
+    +
+    +  return if (!defined wantarray && !IkiWiki::yesno($params{link}));
+    +
+       my $common_prefix;
+     
+       # Get all the items to map.
+    @@ -42,6 +44,9 @@ sub preprocess (@) {
+                       else {
+                               $mapitems{$page}='';
+                       }
+    +                  if (!defined wantarray && IkiWiki::yesno($params{link})) {
+    +                          push @{$links{$params{page}}}, $page;
+    +                  }
+                       # Check for a common prefix.
+                       if (! defined $common_prefix) {
+                               $common_prefix=$page;
+    @@ -62,6 +67,8 @@ sub preprocess (@) {
+               }
+       }
+       
+    +  return if ! defined wantarray;
+    +  
+       # Common prefix should not be a page in the map.
+       while (defined $common_prefix && length $common_prefix &&
+              exists $mapitems{$common_prefix}) {
index 28b48e2c6794cd5792eb39a8d53259b0094b5dc5..c3beb82199fc581fb5704d89a4ede7036fe7a8bd 100644 (file)
@@ -53,7 +53,7 @@ I didn't apply your following old patch against `Ikiwiki.pm` file:
     +   }
     +
     +   return eval $newpagespec;
-     } #}}}
+     }
  
      package IkiWiki::PageSpec;
 
@@ -83,7 +83,7 @@ to break the code I distribute in my backport ;)
        +       my $ret=eval possibly_foolish_untaint(pagespec_translate($spec));
                return IkiWiki::FailReason->new("syntax error") if $@;
                return $ret;
-        } #}}}
+        }
 
 >> Thanks a lot, Joey! It works :)
 >>
index 67b30e6876c4ba24c4327798d64c5446c66adeea..46011a7e833cb5844009ad67f60208e4a4c5b8d6 100644 (file)
@@ -82,3 +82,79 @@ I can't see any related entries. Any ideas?
 
 >>> Ubuntu Gutsy also has Perl 5.8.8-7, so probably it has the bug too.
 >>> --[[Paweł|ptecza]]
+
+>>>> I just got it while building my latest version of git.ikiwiki.info + my stuff.
+>>>> Only thing different in my version in IkiWiki.pm is that I moved a &lt;/a> over
+>>>> a word (for createlink), and disabled the lowercasing of created pages. Running
+>>>> Lenny's Perl. --[[simonraven]]
+
+>>>> Simon, I'm not clear what version of ikiwiki you're using.
+>>>> Since version 2.40, taint checking has been disabled by
+>>>> default due to the underlying perl bug. Unless you
+>>>> build ikiwiki with NOTAINT=0. --[[Joey]] 
+
+>>>> Hi, nope not doing this. Um, sorry, v. 3.13. I've no idea why it suddenly started doing this.
+>>>> It wasn't before. I've been messing around IkiWiki.pm to see if I can set
+>>>> a umask for `mkdir`.
+
+line 775 and down:
++                              umask ($config{umask} || 0022);
+
+>>>> I figured it *might* be the `umask`, but I'll see in a few when / if it gets past that in the build. No; I keep getting garbage during the brokenlinks test
+
+<pre>
+t/basewiki_brokenlinks.....Insecure dependency in mkdir while running with -T switch at IkiWiki.pm line 776.
+
+#   Failed test at t/basewiki_brokenlinks.t line 11.
+
+#   Failed test at t/basewiki_brokenlinks.t line 19.
+
+
+broken links found
+&lt;li>shortcut from &lt;a href="./shortcuts/">shortcuts&lt;/a>&lt;/li>&lt;/ul>
+
+
+
+#   Failed test at t/basewiki_brokenlinks.t line 25.
+Insecure dependency in mkdir while running with -T switch at IkiWiki.pm line 776.
+
+#   Failed test at t/basewiki_brokenlinks.t line 11.
+
+#   Failed test at t/basewiki_brokenlinks.t line 25.
+# Looks like you failed 5 tests of 12.
+dubious
+        Test returned status 5 (wstat 1280, 0x500)
+</pre>
+
+>>>> I get this over and over... I haven't touched that AFAICT, at all. --[[simonraven]]
+
+>>>>> Take a look at your `/usr/bin/ikiwiki`. The first
+>>>>> line should not contain -T. If it does, remove it,
+>>>>> and maybe try to work out or give details about how
+>>>>> you installed ikiwiki and why it got the -T in there,
+>>>>> which certianly doesn't happen by default when ikiwiki
+>>>>> is installed by the Makefile.PL or by any package I know of.
+>>>>> (If there's
+>>>>> no -T, then something *really* weird is going on..)
+>>>>> --[[Joey]] 
+
+>>>>>> nope, no -T in the hashbang line at all. Haven't added any;
+>>>>>> only thing I did there was change `use lib` to `/usr/share/perl5`,
+>>>>>> otherwise I'd get bogus errors about CGI::Cookie_al or some such thing.
+>>>>>>
+>>>>>> How I installed it was in non-public directories in various sites, then
+>>>>>> make it publish stuff to a public dir in the relevant site. Or do you
+>>>>>> mean installed, as in the whole thing? From a .deb I made based on the git tree, with `git-buildpackage`.
+>>>>>>
+>>>>>> This issue is recent, after a `git pull` IIRC. It has never happened before. It's also puzzling me.
+>>>>>>
+>>>>>> You can check it out for yourself by pulling my fork of this, at github or my local repo.
+>>>>>> github will probably be faster for you: git://github.com/kjikaqawej/ikiwiki-simon.git --[[simonraven]]
+
+>>>>>>> I don't know what I'm supposed to see in your github tree.. it
+>>>>>>> looks identical to an old snapshot of ikiwiki's regular git repo?
+>>>>>>> If you want to put up the .deb you're using, I could examine that.
+>>>>>>>
+>>>>>>> I was in fact able to reproduce the insecure dependency in mkdir
+>>>>>>> message -- but only if I run 'perl -T ikiwiki'.
+>>>>>>> --[[Joey]] 
index de20385f61cea7f519ec92017a53cab62228031b..330479d224bbafd9c334ac52869900104abb163d 100644 (file)
@@ -11,4 +11,4 @@ I worked-around this by doing:
 > apparently all versions of perl, apparently leaking taint flags at random.
 > See [[Insecure_dependency_in_mkdir]] --[[Joey]]
 
-[[tag done]]
+[[!tag done]]
diff --git a/doc/bugs/Links_with_symbols_can__39__t_be_edited.mdwn b/doc/bugs/Links_with_symbols_can__39__t_be_edited.mdwn
new file mode 100644 (file)
index 0000000..b9fe734
--- /dev/null
@@ -0,0 +1,22 @@
+We just installed 2.52 on debian testing, and all edit links with symbols (including spaces) are coming up with empty text fields because the URL to the mdwn file is wrong.
+
+For example, the existing page:
+
+    wiki/bugs/__39__Existing_Subject__39___vs.___39__Browse__39__/
+
+displays the bug "'Existing Subject' vs. 'Browse'".  But if we click 'Edit' on that page, we get:
+
+    wiki/ikiwiki.cgi?page=bugs%2F'Existing%20Subject'%20vs.%20'Browse'&do=edit
+
+.. which of course opens with a blank edit box. Note that manually typing in the correct URL:
+
+    wiki/ikiwiki.cgi?page=bugs%2F__39__Existing_Subject__39___vs.___39__Browse__39__&do=edit
+
+does work.
+
+> You need to rebuild your wiki on upgrade to 2.52. The *old* edit links
+> looked like the first link above, and ikiwiki has changed so that it
+> needs the new link above. To get those links on static pages, you need to
+> rebuild the wiki, like the [[news]] says to.
+> 
+> [[closing|done]] as user error --[[Joey]]
diff --git a/doc/bugs/MTIME_not_set_for_inline_or_archive_entries.mdwn b/doc/bugs/MTIME_not_set_for_inline_or_archive_entries.mdwn
new file mode 100644 (file)
index 0000000..89947b5
--- /dev/null
@@ -0,0 +1,22 @@
+My <code>page.tmpl</code> can contain:
+
+    Created <TMPL_VAR CTIME>.  Last edited <TMPL_VAR MTIME>.
+and that works.  However, if I have the same line in <code>inlinepage.tmpl</code> 
+or <code>archivepage.tmpl</code>, then only the <code>CTIME</code> works - the <code>MTIME</code> is blank.
+This leads to an annoying inconsistency.
+
+Update - even though I'm not a Perl programmer, this patch seems right:
+
+    --- /home/bothner/ikiwiki/ikiwiki/IkiWiki/Plugin/inline.pm 2008-10-01 14:29:11.000000000 -0700
+    +++ ./inline.pm    2008-10-12 13:26:11.000000000 -0700
+    @@ -316,6 +316,7 @@
+                               $template->param(pageurl => urlto(bestlink($params{page}, $page), $params{destpage}));
+                               $template->param(title => pagetitle(basename($page)));
+                               $template->param(ctime => displaytime($pagectime{$page}, $params{timeformat}));
+    +                          $template->param(mtime => displaytime($pagemtime{$page}, $params{timeformat}));
+                               $template->param(first => 1) if $page eq $list[0];
+                               $template->param(last => 1) if $page eq $list[$#list];  
+
+
+> [[done]], thanks
index 444de431b8bbf58229defab80485b973f69303d1..fe634e9c115733cc519cc249f37806128854d32a 100644 (file)
@@ -16,7 +16,7 @@ I have a few tags starting with `a` (abridged list):
 
 In `wiki-wc/factors/tag.mdwn`, I have a map for these tags:
 
-    \[[map pages="factors/tag/*"]]
+    \[[!map pages="factors/tag/*"]]
 
 and this works, except that for *whatever* reason, it actually sorts the three
 `affects/*` tags under `active`:
diff --git a/doc/bugs/Meta_plugin_does_not_respect_htmlscrubber__95__skip_setting.___40__patch__41__.mdwn b/doc/bugs/Meta_plugin_does_not_respect_htmlscrubber__95__skip_setting.___40__patch__41__.mdwn
new file mode 100644 (file)
index 0000000..0e40da5
--- /dev/null
@@ -0,0 +1,11 @@
+I have been trying to include some meta info using the link setting something like the below
+
+ meta link="http://www.example.com/" rel="command" name="Example"    
+
+This gets removed by the htmlscrubber as you would expect.
+
+Setting htmlscrubber_skip to the pagespec should stop this getting scrubbed but it does not.
+
+Below is a patch to fix that. It seams to work but I am not sure of it is the correct thing to do.
+
+> [[done]], thanks for the patch --[[Joey]]
diff --git a/doc/bugs/Missing_build-dep_on_perlmagick__63__.mdwn b/doc/bugs/Missing_build-dep_on_perlmagick__63__.mdwn
new file mode 100644 (file)
index 0000000..f6c0266
--- /dev/null
@@ -0,0 +1,14 @@
+Trying to build current Git master in a (two weeks old - no DSL here) sid chroot triggers :
+
+        rendering news.mdwn
+        Can't locate Image/Magick.pm in @INC (@INC contains: . blib/lib /etc/perl /usr/local/lib/perl/5.10.0 /usr/local/share/perl/5.10.0 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at (eval 175) line 2.
+        BEGIN failed--compilation aborted at (eval 175) line 2.
+
+        make[1]: *** [extra_build] Error 2
+        make[1]: Leaving directory `/tmp/buildd/ikiwiki-2.54'
+        make: *** [build-stamp] Error 2
+
+Adding perlmagick to the build-deps fixes it. I read somewhere in debian/changelog that this build-deb was not needed, but...
+
+> It's not needed by the test suite, but once I added a img to the source
+> wiki, it became needed. [[done]] --[[Joey]]
index 103e3100134da0695052950b4c0dd58bdcbd7963..8687e7983c7a506ef736082e92bfe5be44ac3e2d 100644 (file)
@@ -4,14 +4,14 @@ so commits made via monotone will not automatically update the wiki.
 Here for future reference is the most recent version of support for 
 that I've been sent. It's not yet working; there are path issues. --[[Joey]]
 
-> I think this was fixed in version 2.40. --[[Joey]] [[tag done]]
+> I think this was fixed in version 2.40. --[[Joey]] [[!tag done]]
 
 <pre>
 diff --git a/IkiWiki/Rcs/monotone.pm b/IkiWiki/Rcs/monotone.pm
 index cde6029..34f8f96 100644
 --- a/IkiWiki/Rcs/monotone.pm
 +++ b/IkiWiki/Rcs/monotone.pm
-@@ -186,8 +186,9 @@ sub rcs_update () { #{{{
+@@ -186,8 +186,9 @@ sub rcs_update () {
        check_config();
  
        if (defined($config{mtnsync}) && $config{mtnsync}) {
index 37f745047dc576dfd80416c1944b1779efdab42a..06bbce91a0b0f04874560fae8d5807fb14daeca3 100644 (file)
@@ -36,4 +36,4 @@ View source of editing page or preview+edit page shows no "sid" input value. (I
        </TMPL_IF>
 
 > Well, that don't look like as good an idea today.. I've documented the
-> recent template change. --[[Joey]] [[tag done]]
+> recent template change. --[[Joey]] [[!tag done]]
index ac6d6db1e8cde9b253fe1c4647541baca77ec74f..bb3f92f9c60db83efb86222135ede6d22e1ee20c 100644 (file)
@@ -6,7 +6,7 @@ EDIT: I just found that in this wiki under <http://ikiwiki.info/bugs/done/> the
 enabled, then `$safe_url_regexp` determines the URL unsafe because of the
 colon and hence removes the `src` attribute.
 
-Digging into this, I find that [[rfc 3986]] pretty much discourages colons in
+Digging into this, I find that [[!rfc 3986]] pretty much discourages colons in
 filenames:
 
 > A path segment that contains a colon character (e.g., "this:that") cannot be
@@ -22,4 +22,55 @@ In any case, `htmlscrubber` should get a new regexp, courtesy of dato:
 [Commit/patch
 be0b4f60](http://git.madduck.net/v/code/ikiwiki.git?a=commit;h=be0b4f603f918444b906e42825908ddac78b7073) fixes this.
 
-[[done]]
+
+**July 21 2008:** I update this bug report as it still seems to be an issue: E.g. when creating a subpage whose name contains
+a colon by inserting an appropriate wikilink in the parent page: the new page can be created using that link, but afterwards
+there won't be a link to this page. Like madduck said above it seems to be htmlscrubber removing this link. However everything
+works fine if the same page is being linked to from another subpage because in that case the resulting link starts with `../`.
+
+At the moment I see two possible solutions:
+
+1. let all relative links at least start with `./`. I haven't tested this.
+
+2. Escape the colon in page titles. I created the following patch which worked for me:
+
+        --- IkiWiki.pm.2.53-save        2008-07-08 15:56:38.000000000 +0200
+        +++ IkiWiki.pm  2008-07-21 20:41:35.000000000 +0200
+        @@ -477,13 +477,13 @@
+
+         sub titlepage ($) {
+                my $title=shift;
+        -       $title=~s/([^-[:alnum:]:+\/.])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+        +       $title=~s/([^-[:alnum:]+\/.])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+                return $title;
+         }
+
+         sub linkpage ($) {
+                my $link=shift;
+        -       $link=~s/([^-[:alnum:]:+\/._])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+        +       $link=~s/([^-[:alnum:]+\/._])/$1 eq ' ' ? '_' : "__".ord($1)."__"/eg;
+                return $link;
+         }
+
+What do you think about that? Does the patch have any side-effects I didn't see?
+
+> I almost really fixed this in 2.53, but missed one case. All fixed now
+> AFAICS. --[[Joey]]
+
+>> Hmm, did you fix it now in 2.54? If so, I suspect there is still one little case left (might well be the last one,
+>> at least I hope so ;-) ): I just created a test post in the sandbox here: [[sandbox/test: with a colon in its name]]
+>> (btw, why doesn't this get a hyperlink here?).
+>>
+>>> Because wikilinks cannot have spaces, convert to underscores.
+>>> --[[Joey]]
+>>
+>> As it is put in the list of blog posts as a relative link, it starts
+>> with `<word><colon>` -- this makes the browser think that "test" is a protocol specification which is to replace `http`,
+>> so it complains (at least Opera and Firefox/Iceweasel on my Debian Etch do). What I described above for subpages
+>> with this name pattern also still happens on my local install (ikiwiki 2.54 on Debian Etch), but this is basically
+>> the same problem.
+>>
+>> I think the cleanest solution would be to quote colons in page names (like it is currently done for slashes)?
+>> Starting the links with "`./`", as I proposed above, now seems a bit ugly to me...  --Mathias
+
+>>> No, it's all [[done]] in 2.55. --[[Joey]]
diff --git a/doc/bugs/No_progress_in_progress_bar.mdwn b/doc/bugs/No_progress_in_progress_bar.mdwn
new file mode 100644 (file)
index 0000000..d67c55c
--- /dev/null
@@ -0,0 +1,43 @@
+I've just upgraded my Ikiwiki to backported version 2.64 for Ubuntu Hardy
+and wanted to see progress bar in action. Unfortunately, I can't see any progress.
+
+This is my example Ikiwiki syntax:
+
+    [[!progress percent=75]]
+
+A here is a HTML result:
+
+    <div class="progress">
+      <div class="progress-done"></div>
+    </div>
+
+It seems that progress plugin works at all, but it's a problem with passing
+progress value.
+
+Anyone can confirm the bug? --[[Paweł|ptecza]]
+
+> You are correct.  The above example does generate the HTML you suggest.  The
+> plugin requires a % sign:
+
+[[!progress percent="75%"]]
+
+>  This could probably be improved.  Certainly the documentation could be. -- [[Will]]
+
+>> Thanks for the hint, Will! I could check better the code... However, in my opinion
+>> that '%' sign is confusing here and should be dropped. I hope it's clear for all
+>> people that "percent" parameter passes values in percentages. --[[Paweł|ptecza]]
+
+>>> [[fixed|done]] --[[Joey]]
+
+>>> I've forgotten to add that now the HTML code is OK, but I can see only
+>>> "75%" string on white background wihout any border. I need to look closer
+>>> at CSS styles for the progress bar. --[[Paweł|ptecza]]
+
+>>>> You need the `div.progress` and `div.progress-done` from ikiwiki's
+>>>> default `style.css`. --[[Joey]]
+
+>>>>> Thank you for the fix, Joey!
+
+>>>>> I had `div.progress*` in the `style.css` file, but my Epiphany didn't want
+>>>>> to display the progress bar... Now it's OK and I can see beautiful progress,
+>>>>> though I've not changed anything. --[[Paweł|ptecza]]
diff --git a/doc/bugs/Obsolete_templates__47__estseek.conf.mdwn b/doc/bugs/Obsolete_templates__47__estseek.conf.mdwn
new file mode 100644 (file)
index 0000000..99330a1
--- /dev/null
@@ -0,0 +1,3 @@
+The templates/estseek.conf file can safely be removed now that ikiwiki has switched to using xapian-omega.
+
+> Thanks for the reminder, [[done]] --[[Joey]]
diff --git a/doc/bugs/OpenID_delegation_fails_on_my_server.mdwn b/doc/bugs/OpenID_delegation_fails_on_my_server.mdwn
new file mode 100644 (file)
index 0000000..25cc47b
--- /dev/null
@@ -0,0 +1,53 @@
+When I use my OpenID, http://thewordnerd.info, I am redirected to
+http://thewordnerd.myopenid.com, the identity to which thewordnerd.info
+delegates. That is, I'm redirected to the exact identity URL, not to an
+authorization link.
+
+I am successfully using thewordnerd.info as my identity on many sites, so I
+know the delegation is pretty standard. It's stock WordPress with the
+delegation plugin. I also just attempted registration on http://identi.ca
+and successfully exchanged sreg data. So it seems like something is broken
+when using a delegate specifically with ikiwiki, and while I can use
+thewordnerd.myopenid.com, I'd rather use my delegate and free myself to
+switch to other providers in the future.
+
+> Hmm, I entered http://thewordnerd.info as the openid, and ended up at
+> http://thewordnerd.myopenid.com/ , which seems right? --[[Joey]]
+
+Sorry, didn't notice this edit. But, no, that is incorrect. Entering http://thewordnerd.info or thewordnerd.info should do the exact same thing that entering http://thewordnerd.myopenid.com does--in your case, prompt you to log in, in mine, ask if I want to verify the request. It's redirecting to the page itself, not using it as an OpenID provider.
+
+Unfortunately I don't speak or understand enough Perl to fix this, nor do I understand how to use its debugger, but it looks as if the consumer should support delegation. Not sure why it's behaving incorrectly here.
+
+> Your openid delegation is wrong.
+> 
+> Here is a working openid delegation (from http://joey.kitenet.net:)
+>      <link href="http://www.myopenid.com/server" rel="openid.server" />
+>      <link href="http://www.myopenid.com/server" rel="openid2.provider" />
+>      <link href="https://joeyh.myopenid.com/" rel="openid.delegate" />
+>      <link href="https://joeyh.myopenid.com/" rel="openid2.local_id" />
+> 
+> The above is generated by ikiwiki, using the meta openid directive:
+> 
+>      \[[meta openid="https://joeyh.myopenid.com/" server="http://www.myopenid.com/server"]]
+> 
+> Here is your delegation:
+> 
+>      <meta http-equiv="X-XRDS-Location" content="http://thewordnerd.myopenid.com/xrds" />
+>      <link rel="openid.server" href="http://thewordnerd.myopenid.com" />
+>      <link rel="openid.delegate" href="http://thewordnerd.myopenid.com" />
+> 
+> So, your openid.server is set wrong; when loging in ikiwiki redirects to
+> the specified url, which is not behaving as an openid server at all. If it's changed
+> to use http://www.myopenid.com/server, it would work the same as mine.  
+> 
+> I suspect that it was working for you on other sites that support openid
+> 2.0 and XRDS, since the xrds file on your site seems to have the correct
+> http://www.myopenid.com/server url in it. Ikiwiki, however, uses perl
+> modules that do not support openid 2.0 or XRDS, and so the incorrect
+> openid 1.0 delegation is used. --[[Joey]]
+
+[[done]]
+
+Seems so, thanks.
+
+For future reference, and in case anyone has a similar problem and searches here first as I did, I set my OpenID settings using the examples shown for the WordPress OpenID delegation plugin, which seem to work fine on a whole bunch of other sites but a) not here and b) are inaccurate according to the MyOpenID FAQ. I'll file a bug against that plugin to either update its example or remove it entirely. So not an ikiwiki bug, but someone's bug nonetheless.
diff --git a/doc/bugs/PNG_triggers_UTF-8_error_in_MimeInfo.pm.mdwn b/doc/bugs/PNG_triggers_UTF-8_error_in_MimeInfo.pm.mdwn
new file mode 100644 (file)
index 0000000..0a12999
--- /dev/null
@@ -0,0 +1,25 @@
+If a PNG image matches the [[ikiwiki/PageSpec]] of an [[ikiwiki/directive/inline]] directive, the page throws the following error:
+
+> \[[!inline Error: Malformed UTF-8 character (fatal) at /usr/local/lib/perl5/site_perl/5.8.8/File/MimeInfo.pm line 120.]]
+
+Individual posts display fine, and moving the offending image outside the scope of the [[ikiwiki/directive/inline]] directive's PageSpec eliminates the error.
+
+> I tried to reproduce this with a random png and File::MimeInfo 
+> version 0.15, but could not. The png was included in the generated feed
+> via an enclosure, as it should be; no warnings or errors.
+> 
+> Looking at the source to File::MimeInfo and its changelog,
+> I'm pretty sure that this problem was fixed in version
+> 0.14:
+>>       - Fixed bug with malformed utf8 chars in default() method
+> 
+> The code involved in that fix looks like this:
+>
+>>                 no warnings; # warnings can be thrown when input not ascii
+>>                if ($] < 5.008 or ! utf8::valid($line)) {
+>>                        use bytes; # avoid invalid utf8 chars
+>
+> I guess that your locally installed version of File::MimeInfo is older than
+> this. So closing this bug [[done]]. If you still see the problem with a current
+> version of File::MimeInfo, please reopen and include where I can get a png file
+> that triggers the problem. --[[Joey]] 
diff --git a/doc/bugs/Please_avoid_using___39__cp_-a__39___in_Makefile.PL.mdwn b/doc/bugs/Please_avoid_using___39__cp_-a__39___in_Makefile.PL.mdwn
new file mode 100644 (file)
index 0000000..8a83081
--- /dev/null
@@ -0,0 +1,77 @@
+In ikiwiki-2.60, external plug-ins are yet again installed using 'cp -a' instead of 'install -m 755'. This poses a problem on at least FreeBSD 6.x, since the cp(1) command doesn't support the '-a' flag.
+
+The change in question (from 2.56 to 2.60) can be seen here:
+
+    -       for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\*`; do \
+    -               install -m 755 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+    -       done; \
+    +       for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\* | grep -v demo`; do \
+    +               cp -a $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+    +       done \
+
+Please restore the old behaviour of using 'install' :-)
+
+  -- [[HenrikBrixAndersen]]
+
+> I use cp -a because I don't want non-executable files to be installed
+> executable. (Causes breakage with setup file creation code) I really
+> wish *BSD could get out of the 70's in this area..
+> --[[Joey]]
+
+>> Well, really what's happening here is that *BSD (along with, for
+>> example, Solaris) is adhering rather closely to the Single UNIX
+>> Specification, whereas `-a` is a nonstandard option added to the
+>> GNU variant of `cp` (a habit Richard Stallman never really got under
+>> control). To install ikiwiki on Solaris I had to replace all uses not
+>> only of `cp` but also of `install` and `xgettext` with the GNU
+>> embrace-and-extend variants, and make sure I had those installed.
+>> That really is a bit of a PITA.
+
+>> I think there's an opportunity here for a really clean solution, though.
+
+>> Why not do the installation in pure Perl?
+
+>> The file manipulations being done by `cp` and `install` would be
+>> straightforward to code in Perl, and there really isn't a complicated
+>> build requiring the full functionality of `gmake`. `gxgettext` I'm
+>> not so sure about, but even getting rid of _almost_ all the
+>> nonstandard-utility dependencies would be a win.
+
+>> The idea is that if you're distributing a Perl-based app, one thing
+>> you'll always be absolutely certain of in the target environment is a
+>> working Perl. The fact that the current build starts out in Perl, but
+>> uses it to write a Makefile and then hand off to other utilities that
+>> are less dependably compatible across platforms is a disadvantage.
+
+>> A pure-Perl install can also query the very Perl it's running in to
+>> determine the proper places to install files, and that will be less
+>> error-prone that making a human edit the right paths into some files.
+>> It would be quite useful here, actually, where we have several distinct
+>> Perl builds installed at different paths, and ikiwiki could be correctly
+>> installed for any one of them simply by using the chosen Perl to run the
+>> install. That means this would also be a complete solution to
+>> [[todo/assumes_system_perl|todo/assumes_system_perl]].
+>> --ChapmanFlack
+
+>>> Joey: How about the following patch, then? -- [[HenrikBrixAndersen]]
+
+    --- Makefile.PL.orig       2008-08-16 14:57:00.000000000 +0200
+    +++ Makefile.PL    2008-08-16 15:03:45.000000000 +0200
+    @@ -67,9 +67,12 @@ extra_install:
+       done
+       
+       install -d $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins
+    -  for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\* | grep -v demo`; do \
+    -          cp -a $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+    -  done \
+    +  for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\* ! -name \*demo\* -name \*.py`; do \
+    +          install -m 644 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+    +  done
+    +  for file in `find plugins -maxdepth 1 -type f ! -wholename plugins/.\* ! -name \*demo\* ! -name \*.py`; do \
+    +          install -m 755 $$file $(DESTDIR)$(PREFIX)/lib/ikiwiki/plugins; \
+    +  done
+     
+       install -d $(DESTDIR)$(PREFIX)/share/man/man1
+       install -m 644 ikiwiki.man $(DESTDIR)$(PREFIX)/share/man/man1/ikiwiki.1
+
+[[!tag done]]
index f756bf8f590ddcac609a6c71c0d0bd07353cb758..6be5f89b5b9ce62b55d0b922924d5646b435eda9 100644 (file)
@@ -5,11 +5,11 @@ Here is a patch for toc.pm for producing non-empty 'a' elements.
 > Thanks for the patch, but I already fixed this in 2.4 using a different
 > approach. I think your patch is slightly broken, an anchor tag isn't
 > really meant to enclose all the html it anchors to, but just be stuck in
-> front of it. --[[Joey]] [[tag done]]
+> front of it. --[[Joey]] [[!tag done]]
 
     --- IkiWiki/Plugin/toc.pm.orig     Thu Jun  7 11:53:53 2007
     +++ IkiWiki/Plugin/toc.pm  Thu Jun  7 13:00:00 2007
-    @@ -47,7 +47,7 @@ sub format (@) { #{{{
+    @@ -47,7 +47,7 @@ sub format (@) {
                if ($tagname =~ /^h(\d+)$/i) {
                        my $level=$1;
                        my $anchor="index".++$anchors{$level}."h$level";
@@ -18,7 +18,7 @@ Here is a patch for toc.pm for producing non-empty 'a' elements.
        
                        # Take the first header level seen as the topmost level,
                        # even if there are higher levels seen later on.
-    @@ -90,6 +90,16 @@ sub format (@) { #{{{
+    @@ -90,6 +90,16 @@ sub format (@) {
                                        "</a>\n";
                                $p->handler(text => undef);
                        }, "dtext");
index 9a26e505af2df9f4b9a0dd47e5d57c4da31a76f8..c9f6981589fae57958abdb774034175adb83b385 100644 (file)
@@ -15,7 +15,7 @@ It also generates image URLs relative to the page being rendered, which means th
 
     --- IkiWiki/Plugin/graphviz.pm.orig        2007-07-27 11:35:05.000000000 +0200
     +++ IkiWiki/Plugin/graphviz.pm     2007-07-27 11:36:02.000000000 +0200
-    @@ -69,7 +69,12 @@ sub render_graph (\%) { #{{{
+    @@ -69,7 +69,12 @@ sub render_graph (\%) {
                }
        }
      
@@ -26,9 +26,9 @@ It also generates image URLs relative to the page being rendered, which means th
     +  else {
     +          return "<img src=\"".urlto($dest, $params{page})."\" />\n";
     +  }
-     } #}}}
+     }
      
-     sub graph (@) { #{{{
+     sub graph (@) {
 
 
 >> --[[HenrikBrixAndersen]]
@@ -38,7 +38,7 @@ The patch below fixes these two issues.
 
     --- graphviz.pm.orig       Thu Jun  7 15:45:16 2007
     +++ graphviz.pm    Fri Jun  8 12:03:38 2007
-    @@ -41,7 +41,6 @@ sub render_graph (\%) { #{{{
+    @@ -41,7 +41,6 @@ sub render_graph (\%) {
                $pid=open2(*IN, *OUT, "$params{prog} -Tpng");
      
                # open2 doesn't respect "use open ':utf8'"
@@ -46,7 +46,7 @@ The patch below fixes these two issues.
                binmode (OUT, ':utf8');
      
                print OUT $src;
-    @@ -70,7 +69,12 @@ sub render_graph (\%) { #{{{
+    @@ -70,7 +69,12 @@ sub render_graph (\%) {
                }
        }
      
@@ -57,6 +57,6 @@ The patch below fixes these two issues.
     +  else {
     +          return "<img src=\"".urlto($dest, $params{page})."\" />\n";
     +  }
-     } #}}}
+     }
      
-     sub graph (@) { #{{{
+     sub graph (@) {
index 836c39a71da6f86c29c2b5f88488bd0087d0022d..c852df5e93e5bfdcf63aa414fe53e0206d8a8903 100644 (file)
@@ -13,7 +13,7 @@ I can not see why this check is needed in the first place, so here's a patch for
     diff -upr ikiwiki-1.49.orig/IkiWiki/Rcs/svn.pm ikiwiki-1.49/IkiWiki/Rcs/svn.pm
     --- ikiwiki-1.49.orig/IkiWiki/Rcs/svn.pm   Mon Apr 16 15:15:09 2007
     +++ ikiwiki-1.49/IkiWiki/Rcs/svn.pm        Mon Apr 16 15:15:47 2007
-    @@ -176,7 +176,6 @@ sub rcs_recentchanges ($) { #{{{
+    @@ -176,7 +176,6 @@ sub rcs_recentchanges ($) {
                }
      
                foreach (keys %{$logentry->{paths}}) {
index f283bfa65fa7fcf7776156398cdf734058f03368..aeeb9e21bae73ab8d8e0103fcf0bde35878a5753 100644 (file)
@@ -53,4 +53,4 @@ the smiley issue remains open. --[[JasonBlevins]]
 
 > This bug is [[done]], all issues are fixed. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
diff --git a/doc/bugs/RecentChanges_links_to_deleted_pages.mdwn b/doc/bugs/RecentChanges_links_to_deleted_pages.mdwn
new file mode 100644 (file)
index 0000000..0eaeafb
--- /dev/null
@@ -0,0 +1,15 @@
+[[RecentChanges]] should not link to pages that are being deleted. For as
+example, see the change with the title 'add news item for ikiwiki 2.60'
+which includes the deletion of "news/version 2.52". Maybe it should be made
+clear in RecentChanges that the change to the file is it being deleted.
+
+> It needs to link to the deleted page so that you can recreate the page if
+> desired.
+> 
+> The link is not of the normal form used for a link to a nonexistant page,
+> instead it redirects through a CGI. This is done because updating the
+> links would require rebuilding all change pages each time, which would be
+> 100x as slow as the current method.
+> 
+> I don't feel that being 100 times faster at the expense of a marginally
+> inconsistent, but still usable interface is a bug. --[[Joey]] [[done]]
diff --git a/doc/bugs/Renaming_a_file_via_the_web_is_failing_when_using_subversion.mdwn b/doc/bugs/Renaming_a_file_via_the_web_is_failing_when_using_subversion.mdwn
new file mode 100644 (file)
index 0000000..1a737df
--- /dev/null
@@ -0,0 +1,28 @@
+I'm using ikiwiki 3.12 on Mac OS X (installed via mac ports)
+
+When trying to rename a file via the web interface (using the rename plugin) I get the following error:
+
+Error: Undefined subroutine &IkiWiki::Plugin::svn::dirname called at /opt/local/lib/perl5/vendor_perl/5.8.9/IkiWiki/Plugin/svn.pm line 246.
+
+Applying the following patch fixed it:
+
+    --- IkiWiki/Plugin/svn.pm.orig  2009-07-08 12:25:23.000000000 -0400
+    +++ IkiWiki/Plugin/svn.pm       2009-07-08 12:28:36.000000000 -0400
+    @@ -243,10 +243,10 @@
+     
+            if (-d "$config{srcdir}/.svn") {
+                    # Add parent directory for $dest
+    -               my $parent=dirname($dest);
+    +               my $parent=IkiWiki::dirname($dest);
+                    if (! -d "$config{srcdir}/$parent/.svn") {
+                            while (! -d "$config{srcdir}/$parent/.svn") {
+    -                               $parent=dirname($dest);
+    +                               $parent=Ikiwiki::dirname($dest);
+                            }
+                            if (system("svn", "add", "--quiet", "$config{srcdir}/$parent") != 0) {
+                                    warn("svn add $parent failed\n");
+
+
+> Thank you very much for the patch, which I've applied. I wonder how
+> that snuck in (aside from the obvious, that the svn plugin is not often
+> used and the code was added w/o being tested..). [[done]] --[[Joey]] 
diff --git a/doc/bugs/SSI_include_stripped_from_mdwn.mdwn b/doc/bugs/SSI_include_stripped_from_mdwn.mdwn
new file mode 100644 (file)
index 0000000..5519e45
--- /dev/null
@@ -0,0 +1,21 @@
+If I have a &lt;--#include virtual="foo" --&gt; in some file, it gets stripped, even though other HTML comments don't get stripped. I imagine it's some plugin doing it, or IkiWiki itself, or an IkiWiki dependency, but I haven't found where this is happening. I'm trying to implement a workaround for my sidebars forcing a rebuild of the wiki every day - I use the calendar plugin - when the day changes, by using SSI.
+
+> It is probably the [[plugins/htmlscrubber]] plugin. -- [[Jon]]
+
+> htmlscrubber does strip these, because they look like
+> a html tag to it, not a html comment. (html comments start
+> with `<!--` .. of course, they get stripped too, because
+> they can be used to hide javascript..)
+> 
+> Anyway, it makes sense for the htmlscrubber to strip server-side
+> includes because otherwise your wiki could be attacked
+> by them being added to it. If you want to use both the htmlscrubber and
+> SSI together, I'd suggest you modify the [[wikitemplates]]
+> and put the SSI on there.
+> 
+> Ie, `page.tmpl` has a 
+> div that the sidebar is put into; if you just replace
+> that with the SSI that includes your static sidebar,
+> you should be good to go. --[[Joey]]
+
+[[done]]
diff --git a/doc/bugs/SVG_files_not_recognized_as_images.mdwn b/doc/bugs/SVG_files_not_recognized_as_images.mdwn
new file mode 100644 (file)
index 0000000..207edd4
--- /dev/null
@@ -0,0 +1,29 @@
+In ikiwiki 2.66, SVG images are not recognized as images. In ikiwiki.pm,
+the hardcoded list of image file extensions does not include ".svg", which
+it probably should unless there's some other issue about rendering SVGs?
+
+The 'img' plugin also seems to not support SVGs.
+
+> SVG images can only be included via an `<object>`, `<embed>`, or
+> `<iframe>` tag. Or, perhaps as [inline SVG](http://wiki.svg.org/Inline_SVG). 
+> The [[plugins/htmlscrubber]] strips all three tags since they can easily
+> be used maliciously. If doing inline SVG, I'd worry that the svg file
+> could be malformed and mess up the html, or even inject javascript. So,
+> the only options seem to be only supporting svgs on wikis that do not
+> sanitize their html, or assuming that svgs are trusted content and
+> embedding them inline. None of which seem particularly palatable.
+> 
+> I suppose the other option would be converting the svg file to a static
+> image (png). The img plugin could probably do that fairly simply.
+> --[[Joey]]
+
+>> I'm working on inline SVG and MathML support in ikiwiki and I've
+>> modified my htmlscrubber to sanitize SVG and MathML using the
+>> whitelists from html5lib.  Here's a [patch][].  I've also made some
+>> notes about this here: [[todo/svg]].
+>> 
+>> I suspect that this bug may have caught the eye of anyone interested
+>> in this sort of thing.  I'll elaborate a bit on my user page to avoid
+>> getting off-topic here. --[[JasonBlevins]], October 21, 2008
+
+ [patch]: http://xbeta.org/gitweb/?p=xbeta/ikiwiki.git;a=blobdiff;f=IkiWiki/Plugin/htmlscrubber.pm;h=3c0ddc8f25bd8cb863634a9d54b40e299e60f7df;hp=3bdaccea119ec0e1b289a0da2f6d90e2219b8d66;hb=fe333c8e5b4a5f374a059596ee698dacd755182d;hpb=be0b4f603f918444b906e42825908ddac78b7073
index 56cda026f606047ef67539287c8f5c22bf22f7b5..8aea5cd29d19bd401e53ee1a27515da99cc91e30 100644 (file)
@@ -1,7 +1,7 @@
 Versions 2.0 and 2.1 of ikiwiki, and I think earlier versions as well,
-allowed wiki links to have spaces in the link text. For example, [[ikiwiki
+allowed wiki links to have spaces in the link text. For example, [[!ikiwiki
 logo page|logo]] should create an anchor tag referencing the logo page, and
-[[ikiwiki logo|logo/ikiwiki.png]] should create an image tag referencing
+[[!ikiwiki logo|logo/ikiwiki.png]] should create an image tag referencing
 the logo.
 
 As of version 2.2, this no longer works. I think the pattern \\[[...|...]]
@@ -16,7 +16,7 @@ reported in [[index/discussion#index11h1]].
 > want multiple words.
 >
 > This was a decision I made a long time ago due to the ambiguity between a
-> WikiLink and a [[ikiwiki/PreProcessorDirective]]. Is "\[[foo bar|baz]]" a wikilink to
+> WikiLink and a [[ikiwiki/Directive]]. Is "\[[foo bar|baz]]" a wikilink to
 > baz with a link text of "foo bar", or an instance of preprocessor
 > directive "foo" with a parameter of "bar|baz"? If it's interpreted as a 
 > wikilink today, that could change tomorrow if a new preprocessor directive
@@ -44,7 +44,7 @@ reported in [[index/discussion#index11h1]].
 >> 
 >> If there was ever a future, syntax-breaking major release of ikiwiki
 >> (similar to python3000) I'd like to see this fixed as part of that.
->> --[[JonDowland]]
+>> --[[users/Jon]]
 
 >>> You can enable `prefix_directives` and get the disambiguated behavior
 >>> and spaces in wikilinks today. It will become the default in 3.0.
index c59a6ba40ab8ce19639d7a3dde598af17b3544c8..e3b1d858dff019cea76b5f6485904281bdb751dc 100644 (file)
@@ -1,4 +1,4 @@
-[[tag patch]]
+[[!tag patch]]
 
 When a page containing tags and using the [[syntax_(3rd_party)_plugin|plugins/contrib/syntax]] (though pages using other preprocessors may also be affected) is rendered as an inline page, some extra `<p>` elements are added.
 
index cc53c0aeaba72b312837a21bc036129f15832eee..0594158194b23b9fcdd4be911c4ce2022b5dd704 100644 (file)
@@ -4,17 +4,19 @@ If I click on "Czars in Russia", I'd like Ikiwiki to create "Czars\_in\_Russia.m
 
 > There's a simple patch that can do this:
 
-> --- a/IkiWiki.pm
-> +++ b/IkiWiki.pm
-> @@ -584,7 +584,7 @@ sub htmllink ($$$;@) { #{{{
->                      return "<span class=\"createlink\"><a href=\"".
->                              cgiurl(
->                                      do => "create",
-> -                                    page => pagetitle(lc($link), 1),
-> +                                    page => pagetitle($link, 1),
->                                      from => $lpage
->                              ).
->                              "\">?</a>$linktext</span>"
+<pre>
+-- a/IkiWiki.pm
++++ b/IkiWiki.pm
+@@ -584,7 +584,7 @@ sub htmllink ($$$;@) {
+                       return "&lt;span class=\"createlink\">&lt;a href=\"".
+                               cgiurl(
+                                       do => "create",
+-                                      page => pagetitle(lc($link), 1),
++                                      page => pagetitle($link, 1),
+                                       from => $lpage
+                               ).
+                               "\">?&lt;/a>$linktext&lt;/span>"
+</pre>
 
 > This is fine if you don't mind mixed or randomly cased filenames getting
 > created. Otoh, if the link happened to start a sentence and so had its
diff --git a/doc/bugs/Toc_map_and_template_plugins_do_not_play_well_together.mdwn b/doc/bugs/Toc_map_and_template_plugins_do_not_play_well_together.mdwn
new file mode 100644 (file)
index 0000000..4849edd
--- /dev/null
@@ -0,0 +1,30 @@
+The following renders incorrectly:
+
+       \[[!toc ]]
+
+       # header1
+
+       content1
+
+       # header2
+
+       \[[!map pages="sandbox"]]
+
+
+Removing the `\[[!toc]]` directive or moving it at the end of the page
+makes the whole wiki page be rendered as expected.
+
+Hint : in all cases, the non-interpreted markdown code is copied as-is
+in the HTML output, without any leading `<p>` or any HTML formatting.
+
+> You're using the old version of `markdown`, that is known to have a broken block
+> html parser, that will get confused if markdown is present between two
+> separate html blocks, and not format the markdown.
+> 
+> This is fixed in [[!cpan Text::MarkDown]] 1.0.19. markdown 1.0.2 also
+> fixes the problem. Install either one. I'm going to make ikiwiki's
+> dependencies list Text::Markdown before markdown, since people keep
+> stumbling over this. (The downside is that the old broken markdown is
+> faster). --[[Joey]]
+
+[[done]]
diff --git a/doc/bugs/URLs_with_parentheses_displayed_badly.mdwn b/doc/bugs/URLs_with_parentheses_displayed_badly.mdwn
new file mode 100644 (file)
index 0000000..59b67d4
--- /dev/null
@@ -0,0 +1,19 @@
+I've noticed that Ikiwiki displays URLs with parentheses badly. The problem occurs
+in the latest version 3.00 and older versions. Please look at the link to following
+Polish entry about C programming language at Wikipedia (it seems that URLs with
+parentheses are popular there):
+
+[Język programowania C](http://pl.wikipedia.org/wiki/C_(j%C4%99zyk_programowania))
+
+I need to escape a closing parenthesis of the URL to fix the problem.
+
+[Język programowania C](http://pl.wikipedia.org/wiki/C_(j%C4%99zyk_programowania\))
+
+--[[Paweł|users/ptecza]]
+
+> This is a bug in markdown version 1. It is fixed in [[!cpan Text::Markdown]],
+> which ikiwiki will use if it's installed. [[done]] --[[Joey]] 
+
+>> Thanks a lot for the hint, Joey! I've installed `libtext-markdown-perl` package
+>> (Aptitude has removed `markdown` package to satisfy dependencies) and now
+>> I don't need to escape Wikipedia URLs with parentheses :) --[[Paweł|users/ptecza]]
diff --git a/doc/bugs/Undefined_subroutine_IkiWiki::refresh.mdwn b/doc/bugs/Undefined_subroutine_IkiWiki::refresh.mdwn
new file mode 100644 (file)
index 0000000..c0cc3fd
--- /dev/null
@@ -0,0 +1,7 @@
+After building a fresh deb from current Git master (9b62dac4bcf62f3a1f76ec5a7ed5a90db16ea1c8) :
+
+        $ ikiwiki --setup ~/ikiwiki.setup  --rebuild
+        Undefined subroutine &IkiWiki::refresh called at /usr/share/perl5/IkiWiki/Setup.pm line 113.
+
+> [[done]], it just needed "require IkiWiki::Render" before it started
+> rendering. --[[smcv]]
index 88a187dfc220a1d5a2f8a6bc1f186df184352fa1..12c0ad07fa12e30e4add15b5ee6c57f3f701f817 100644 (file)
@@ -24,4 +24,9 @@ Here is a patch against ikiwiki-1.51 for using find(1) and install(1) instead of
 
 >> No, apparently FreeBSD `install` does not support `-D`.  See [the FreeBSD install manpage](http://www.freebsd.org/cgi/man.cgi?query=install&apropos=0&sektion=0&manpath=FreeBSD+6.2-RELEASE&format=html). --[[JoshTriplett]]
 
->> Patch applied; [[bugs/done]]. --[[JoshTriplett]]
+>> Patch applied; [[done]]. --[[JoshTriplett]]
+
+There are still/again "cp -a"s in the Makefile as of 3.00
+
+> It's a cp -a || install. Is that causing you a problem somehow?
+> --[[Joey]] 
diff --git a/doc/bugs/Warns_about_use_of_uninitialized_value_if_prefix__95__directives_is_on_and_a_directive_does_not_contain_a_space.mdwn b/doc/bugs/Warns_about_use_of_uninitialized_value_if_prefix__95__directives_is_on_and_a_directive_does_not_contain_a_space.mdwn
new file mode 100644 (file)
index 0000000..efb5c70
--- /dev/null
@@ -0,0 +1,19 @@
+In `IkiWiki::preprocess`, the last capturing group in the regex used to parse directives in prefix_directives mode is of the form `(\s+...)?\]\]`, which will not be matched if the directive is something without arguments or whitespace, like `\[[!orphans]]`. As a result, its value is undef instead of being an empty string, causing a warning when it is used in the anonymous sub `$handle`. A trivial fix is to treat it as "" if it is undef.
+
+[[patch]] in the master branch of my git repository, and quoted here. --[[smcv]]
+
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index 241a7c0..d2c35a2 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -1167,7 +1167,8 @@ sub preprocess ($$$;$$) {
+                    }sx;
+            }
+     
+    -       $content =~ s{$regex}{$handle->($1, $2, $3, $4)}eg;
+    +       # $4 can be undef if the directive was \[[!foo]]
+    +       $content =~ s{$regex}{$handle->($1, $2, $3, ($4 or ""))}eg;
+            return $content;
+     }
+[[cherry-picked|done]] --[[Joey]]
index c2a844c42d72b5183bbbaf09eb9b97a2ff8a0272..f9a03ff01fac475d18e6eff50ef76db06c495b10 100644 (file)
@@ -7,4 +7,4 @@ The following four PNG files have permissions 600 instead of 644 in the source t
 
 [[bugs/done]] in my sources --[[Joey]]
 
-Thank you --[[Brix]]
\ No newline at end of file
+Thank you --[[Brix|HenrikBrixAndersen]]
diff --git a/doc/bugs/__34__more__34___doesn__39__t_work.mdwn b/doc/bugs/__34__more__34___doesn__39__t_work.mdwn
new file mode 100644 (file)
index 0000000..b2d929f
--- /dev/null
@@ -0,0 +1,17 @@
+As one can see at [[plugins/more/discussion]], the [[plugins/more]] plugin doesn't work --- it renders as:
+
+    <p><a name="more"></a></p>
+    
+    <p>This is the rest of my post. Not intended for people catching up on
+    their blogs at 30,000 feet. Because I like to make things
+    difficult.</p>
+
+No way to toggle visibility.
+-- Ivan Z.
+
+> More is not about toggling visibility. Perhaps you want
+> [[plugins/toggle]] More is about displaying the whole page
+> content when it's a standalone page, and only displaying a fragment when
+> it's inlined into a blog. --[[Joey]] [[done]]
+
+>> I see, thanks for bothering with the reply, I didn't understand this. --Ivan Z.
index 94a0e544531426d2f35f80232fa774bfd495999c..eb3450a7e39a6715e4f788a99da4b6432046acf4 100644 (file)
@@ -44,3 +44,4 @@ unless that has security implications.
 >>
 >> I hope that's just a minor blemish. --liw
 
+>>> Sounds like this is [[done]] --[[Joey]]
index 3f65b01b982901bd397df229d95690f395bfdb72..2c3fdea3e38ac97156d9c08c9e7e63e3d836f3cc 100644 (file)
@@ -23,8 +23,8 @@ I tried searching the web and wiki but could not find any information on why <br
 
 > > `<br/>` is also valid, so this is a bug still. --[[madduck]]
 
->>> It _is_ the htmlscrubber that removes that. It's due to [[debbug 365971]], 
->>> basically the [[cspan HTML::Scrubber]] doesn't understand xhtml tags
+>>> It _is_ the htmlscrubber that removes that. It's due to [[!debbug 365971]], 
+>>> basically the [[!cspan HTML::Scrubber]] doesn't understand xhtml tags
 >>> of this sort at all, I hacked it to support `<br />` by tellig it to treak 
 >>> the "/" as an attribute, but if there's no space, it doesn't see it as 
 >>> an attribute. Hmm, I could also add `br` as a tag name, that would catch both cases.
index e389ce3ed23699a95dd929cfbdb79fa6a3ca5e98..a1b5ba94acb1ec1185147ee2a7a931e5816e38a9 100644 (file)
@@ -15,3 +15,21 @@ adding this `clear: both`?
 > before the modification date. So all of them have to clear both above and
 > below. I'm sure there are better ways for the CSS to handle that.
 > --[[Joey]] 
+
+>> There is indeed a better way - all the optional things below the
+>> content are wrapped in `<div id="footer">`, so to have the browser wait
+>> until all floating boxes have finished before rendering the footer, it
+>> would be sufficient to have `#footer { clear: both; }` and remove all
+>> the other footer-related `clear` attributes. I'm not sure what you mean
+>> by "clear above and below" - the clear attribute takes values none, left,
+>> right or both, and its purpose is to stop floating boxes (sidebars,
+>> mainly) from overlapping with footers.
+>>
+>> ... oh, I see what you mean - this affects inlines too. In inlinepage.tmpl
+>> we could wrap the "pseudo-footer" in `<div class="inlinefooter">` too?
+>> Then sites could choose whether to set clear:both on the inlinefooter
+>> or not, and this would be separate from the same styling on whole pages.
+>>
+>> [[done]] --[[smcv]]
+
+[[patch]]
diff --git a/doc/bugs/aggregate_global_feed_names.mdwn b/doc/bugs/aggregate_global_feed_names.mdwn
new file mode 100644 (file)
index 0000000..27127ce
--- /dev/null
@@ -0,0 +1,13 @@
+[[plugins/aggregate]] takes a name parameter that specifies a global name
+for a feed. This causes some problems:
+
+* If a site has multiple pages that aggregate, and they use the same
+  name, one will win and get the global name, the other will claim it's
+  working, but it's really showing what the other aggregated.
+* If an aggregate directive is moved from page A to page B, and the wiki
+  refreshed, aggregate does not realize the feed moved, and so it will
+  keep aggregated pages under `A/feed_name/*`. To work around this bug,
+  you have to delete A, refresh (maybe with --aggregate?), and then add B.
+
+Need to find a way to not make the name be global. Perhaps it needs to
+include the name of the page that contains the directive?
index e62b7852e6673332f5bbfd4f096627249952e1ef..aa36bdd09895501efb1e080e1654a61b3ac01d09 100644 (file)
@@ -23,11 +23,11 @@ feed I'm seeing this with is http://www.wirelesscommons.org/feed.php
 > This is a bug in XML::Parser. Unfortunately, perl does not have a feed
 > parser that handles invalid feeds, and in particular, XML::Parser has
 > issues with feeds that claim to be encoded in utf-8 and contain invalid
-> utf sequences, as well as other encoding issues. See also [[debbug 380426]].
+> utf sequences, as well as other encoding issues. See also [[!debbug 380426]].
 > Note though that this invalid feed does not really crash the aggregate plugin,
 > it just notes that XML::Parser crashed on it and continues. This is the
 > best I can do in ikiwiki. I have filed a bug on XML::Parser about this,
-> it's [[debbug 420636]].  I've also put in a workaround, so [[done]].
+> it's [[!debbug 420636]].  I've also put in a workaround, so [[done]].
 
 **Wonderful**, thanks Joey! -- Adam.
 
index 61f6f733a5fa1bcdbea606559e77cae56359f0ad..865637ea4428c7204965b51c0c71699ef50e571e 100644 (file)
@@ -11,3 +11,5 @@ appropriately, so that ikiwiki reflects the actual time of the post via the
                if defined $mtime && $mtime <= time;
 
 >> I'll have to debug this, it's not working here... and this is an ikiwiki aggregator scraping another ikiwiki site.
+
+>>> Any news about this? --[[Joey]]
index e722e9d73bcf7740c709621118a87402584b62ec..58c247631276fab0e7298c7432d811d6fc314cc6 100644 (file)
@@ -1,6 +1,17 @@
 [[!meta title="aggregate/inline planets wrongly link to posts"]]
 
 Please see 
-<http://vcs-pkg.org/planet/>. The headers of posts link to the HTML pages, which ikiwiki scraped. Also, the `\[[meta]]` titles and author directives aren't processed, but included inline. I believe that the headers should link to the posts directly, not the "cached" copies ikiwiki keeps around.
+<http://vcs-pkg.org/planet/>. The headers of posts link to the HTML pages, which ikiwiki scraped.
+I believe that the headers should link to the posts directly, not the "cached" copies ikiwiki keeps around.
+
+> As far as I can see, that problem no longer exists.
+
+Also, the `\[[meta]]` titles and author directives aren't processed, but included inline. 
+
+> Hmm, I don't see that either.
 
 What's also not ideal is that the cached copies can be edited. Any edits there will never make it to the VCS and thus won't show up in recentchanges.
+
+> That can be disabled now by enabling `aggreageinternal` --[[Joey]]
+
+> Calling this [[done]], please let me know if I missed something.
diff --git a/doc/bugs/attachment:_escaping_underscores_in_filename__63__.mdwn b/doc/bugs/attachment:_escaping_underscores_in_filename__63__.mdwn
new file mode 100644 (file)
index 0000000..4ce4ac5
--- /dev/null
@@ -0,0 +1,22 @@
+I've just noticed that `attachment` plugin escapes the underscore
+characters in attached filenames. For example, when I wanted to add
+`foo_bar_baz.txt` file, then Ikiwiki added file `foo__95__bar__95__baz.txt`
+to my Subversion repo. I hope that the filename is terribly ugly not only
+for me ;)
+
+Is it a bug or security feature? --[[Paweł|ptecza]]
+
+>> Update: It's not only problem with attached filenames. I have
+>> `mysql/myisam_vs_ndb.mdwn` page in my wiki and attached two
+>> images (`myisam_vs_ndb_sql.png` and `myisam_vs_ndb_cpu.png`)
+>> and one OpenDocument file (`myisam_vs_ndb.ods`). Ikiwiki placed
+>> them into `myisam__95__vs__95__ndb` subdirectory as
+>> `myisam__95__vs__95__ndb__95__sql.png`, `myisam__95__vs__95__ndb__95__cpu.png`
+>> and `myisam__95__vs__95__ndb.ods` files. When I click "Attachments" link,
+>> I can't see my uploaded files, because there are in another subdirectory
+>> (`myisam__95__vs__95__ndb` instead of `myisam_vs_ndb`).  --[[Paweł|ptecza]]
+
+> [[done]], uses `linkpage` now.
+
+>> It's seems that now Ikiwiki doesn't escape the filenames with underscore(s).
+>> Thank you very much for the fast fix! --[[Paweł|ptecza]]
diff --git a/doc/bugs/attachment:_failed_to_get_filehandle.mdwn b/doc/bugs/attachment:_failed_to_get_filehandle.mdwn
new file mode 100644 (file)
index 0000000..54f31a9
--- /dev/null
@@ -0,0 +1,115 @@
+I can't add any attachment to my wiki. When I select file using "Browse"
+button and click "Upload Attachment", then `ikiwiki.cgi` file displays
+the error message like below:
+
+    Błąd: failed to get filehandle
+
+> Can you do some debugging? If you edit attachment.pm line 136, to print
+> out what it did get, and show me what that yields, maybe I can figure
+> this out.
+
+       error("failed to get filehandle ($fh)");
+
+>> Sure. I've done the change and it seems that $fh variable is undefined:
+
+>>     Use of uninitialized value in concatenation (.) or string at /usr/share/perl5/IkiWiki/Plugin/attachment.pm line 135.
+>>     failed to get filehandle ()
+
+> Also, what web server and version of perl is this? --[[Joey]]
+
+>> It's Apache2 2.2.8-1ubuntu0.3 and Perl 5.8.8-12 from Ubuntu Hardy. --[[Paweł|ptecza]]
+
+>>> Hmm, is your CGI.pm perhaps creating the attachment temp file, but
+>>> not providing an open filehandle to it via the `upload` method?
+>>> Change the debugging line to this: --[[Joey]]
+
+       error("failed to get filehandle:$fh ; file:$filename ; is ref:".ref($q->param('attachment')));
+
+>>>> Now my Ikiwiki returns:
+
+>>>>     failed to get filehandle: ; file:sandbox/test.txt ; is ref:
+
+>>>> Is it helpful for you? --[[Paweł|ptecza]]
+
+>>>>> Yes, this suggests that CGI.pm's `upload` function is not working,
+>>>>> but that it *is* returning a filehandle pointing at the attachment
+>>>>> using the old method. Hmm, so I'll bet you have a CGI.pm version
+>>>>> older than 2.47. Can you find your system's CGI.pm and grep for
+>>>>> "VERSION" in it to determine the version? I checked debian stable.
+>>>>> and its perl 5.8.8 has version 3.15, so is not affected, I think.
+
+>>>>>> I have CGI.pm 3.15 too: 
+
+>>>>>>     $ grep VERSION= /usr/share/perl/5.8.8/CGI.pm
+>>>>>>     $CGI::VERSION='3.15';
+
+>>>>> I've just checked in a fix that should work, can you test it?
+>>>>> [diff](http://git.ikiwiki.info/?p=ikiwiki;a=commitdiff;h=71f10579c00a8ddc20ada1a1efd33aac25a3da7e) --[[Joey]]
+
+>>>>>> I've patched `attachment.pm` module, but the bug still occurs.
+>>>>>> However I can see a little progress. I changed invoking `error()`
+>>>>>> subroutine like you showed me before and now Ikiwiki prints
+
+>>>>>>     failed to get filehandle:test.txt ; file:sandbox/test.txt ; is ref:
+
+>>>>>> --[[Paweł|ptecza]]
+
+>>>>>>> Well then, your CGI.pm is somehow not behaving as its documentation
+>>>>>>> describes, in two ways:
+>>>>>>> 1. `upload()` is not returning a reference to the filehandle
+>>>>>>> 2. The filename returned by `param("attachment")` is not also
+>>>>>>>    a file handle.
+>>>>>>> That seems very broken. I can try to work around it some more
+>>>>>>> though. I've checked in a second try at dealing with things, can
+>>>>>>> you try it? --[[Joey]]
+
+>>>>>>>> Do you mean that [diff](http://git.ikiwiki.info/?p=ikiwiki;a=commitdiff;h=66f35e30dcea03c631a293e2341771277543b4ae)?
+>>>>>>>> If so, then it causes "Internal Server Error" for me:
+
+>>>>>>>>     Can't use string ("test.txt") as a symbol ref while "strict refs" in use at /usr/share/perl5/IkiWiki/Plugin/attachment.pm line 144.
+
+>>>>>>>> I can rebuild Debian stable source package with CGI for Perl. Maybe it will help me? What do you think? --[[Paweł|ptecza]]
+
+>>>>>>>>> Silly thinko on my part, fixed that in git.. --[[Joey]]
+
+>>>>>>>>>> Thanks for the fix, Joey! Now CGI doesn't fails, but still no success with attaching file:
+
+>>>>>>>>>>     failed to open : No such file or directory
+
+>>>>>>>>>> Do you have any another idea how to resolve that problem? I can try with rebuilding
+>>>>>>>>>> package `perl-modules` if it's necessary in that situation. --[[Paweł|ptecza]]
+
+>>>>>>>>>>> If CGI.pm is not creating a temp file, not providing a
+>>>>>>>>>>> filehandle by either of its documented methods, then it's just
+>>>>>>>>>>> broken; ikiwiki can't deal with that level of brokennecess.
+>>>>>>>>>>> I need to find out if this affects stable in general, or just
+>>>>>>>>>>> you/ubuntu. --[[Joey]]
+
+>>>>>>>>>>>> Same thing on FreeBSD using CGI.pm 3.15. Looks like $self->{'.tmpfiles'} in CGI.pm
+>>>>>>>>>>>> is not populated with the information about the uploaded file, causing tmpFileName()
+>>>>>>>>>>>> to return '' (unloadInfo(), which uses the same lookup method fails in the same manner),
+>>>>>>>>>>>> but I have yet to find out why this happens. --[[HenrikBrixAndersen]]
+
+The same message I can see in the Apache log file. There is also
+following warning:
+
+    Use of uninitialized value in length at /usr/share/perl5/IkiWiki/Plugin/attachment.pm line 36.
+
+> This is unrelated, I've fixed the warning message. --[[Joey]]
+
+Is it Ikiwiki bug or my attachment plugin is misconfigured? --[[Paweł|ptecza]]
+
+> I've reproduced the bug, and it does seem to be a bug with the perl in
+> debian stable/ubuntu hardy. Trying to figure it out --[[Joey]]
+
+> This was amazingly disgusting, see commit message for the full horror of
+> the details. I think it's [[done]] -- at least it works on debian stable
+> now. --[[Joey]]
+
+>> Wow! It's probably the biggest Ikiwiki commit message I've ever seen :)
+
+>> Yes, I can confirm that now the plugin works for me and I'm able to add
+>> attachments to my wiki. Yupiii! :D
+>> Thanks a lot, Joey! You're really great! :) --[[Paweł|ptecza]]
+
+>> Thank you very much for your effort, Joey! :) --[[Paweł|ptecza]]
index bcfd9774cb9eab7e8cc35dcf306129f90c1b4e0a..0b6d7330000f6837d7b7427fbebdc09144e34acc 100644 (file)
@@ -1,9 +1,11 @@
 At [[attachment|plugins/attachment]] plugin page I can see
 that it's enabled by default in Ikiwiki. Is it true?
 
-> No, typo. I don't want to enable it by default because it requires
+> No, typo ([[done]]). I don't want to enable it by default because it requires
 > site-specific configuration to be made secure. --[[Joey]]
 
+>> Thanks for your reply! I was guessing it :) --[[Paweł|ptecza]]
+
 I have backported Ikiwiki 2.52 and I need to add that plugin to
 `add_plugins` variable in my `ikiwiki.setup` file (and rebuild
 my wiki, of course) to see new upload buttons when I edit a page
@@ -11,5 +13,7 @@ and click "Attachments" link.
 
 > FWIW, you don't need to rebuild the whole wiki, --refresh --wrappers is enough.
 
+>> It's good to know. Thank you for the hint! 
+
 Maybe should I enable attachment handling in different way?
 --[[Paweł|users/ptecza]]
diff --git a/doc/bugs/backlinks_onhover_thing_can_go_weird.mdwn b/doc/bugs/backlinks_onhover_thing_can_go_weird.mdwn
new file mode 100644 (file)
index 0000000..415e6af
--- /dev/null
@@ -0,0 +1,43 @@
+I was just hovering over the '...' next to the backlinks on a page on
+<http://ikiwiki.info/>. In terms of the size of my browser window, this was
+towards the bottom-right of the screen.
+
+When I hovered over the '...', the additional backlinks float appeared. This
+caused the page length to grow down, meaning a horizontal scrollbar was added
+to the page. This meant the text reflowed, and the '...' moved outside of my
+mouse pointer region.
+
+This caused an infinite loop of box appears... text moves, box disappears...
+box re-appears.. which was not very visually pleasant.
+
+In general I think that the onhover float is a bit of bad UI. Even a truncated
+list of backlinks looks cluttered due to there being no delimiters. I moved to
+having an always-complete list of backlinks and having them as LI elements
+inside a UL to make it look neater, although I appreciate that would make some
+pages very long indeed.
+
+How about doing something a little like [[plugins/toggle]] for the excess
+items instead?
+
+-- [[Jon]]
+
+----
+
+An additional, related issue: if the box expands beyond the bottom of the
+page, you might move your mouse pointer to the scrollbar in order to move
+further down the list, but of course then you are outside the hover region.
+
+-- [[Jon]]
+
+> I agree, browser handling of this CSS is often not good.
+> 
+> A toggle would be the perfect UI, but the heaviness of needing
+> to include 30 lines of javascript to do it, plus then it only working
+> with javascript enabled, is also not optimal.
+> 
+> Another idea would be to make the "..." a link to the ikiwiki cgi. 
+> The cgi could then have a mode that displays all the backlinks of a page
+> in a list.
+> 
+> Yet another idea: Find some more refined CSS for handling a variable
+> size popup.. --[[Joey]] 
diff --git a/doc/bugs/barfs_on_recentchange_entry_for_a_change_removing_an_invalid_pagespec.mdwn b/doc/bugs/barfs_on_recentchange_entry_for_a_change_removing_an_invalid_pagespec.mdwn
new file mode 100644 (file)
index 0000000..42e6b9e
--- /dev/null
@@ -0,0 +1,41 @@
+I have a commit doing
+
+    -\[[map pages="link(tag/<TMPL_VAR name>) and !papers/*"]]
+    +\[[map pages="link(sourcepage()) and !papers/*"]]
+
+ikiwiki now fails to compile the site, barfing:
+
+    Use of uninitialized value in subroutine entry at /usr/share/perl5/IkiWiki.pm line 1288.
+    ikiwiki.setup: Can't use string ("") as a subroutine ref while "strict refs" in use at /usr/share/perl5/IkiWiki.pm line 1288.
+    BEGIN failed--compilation aborted at (eval 6) line 200.
+
+after forcefully entering the Perl mode of thinking, I reduced this to line
+1285 of IkiWiki.pm (2.53), which apparently returns `undef`:
+
+    my $sub=pagespec_translate($spec);
+
+Why does it even bother parsing the diffs of `recentchanges`?
+
+I have not recompiled this site in ages, so I am not sure when this problem
+was introduced, but it wasn't there when I worked on the site last about
+a year ago in September 2007.
+
+-- [[madduck]]
+
+> I can't reproduce this problem. When I try, the generated
+> `recentchanges/change_$sha1._change` file has the diff properly escaped,
+> so that the map is not expanded at all.
+> 
+> I also tried de-escaping that, and still failed to reproduce any crash.
+> The bogus pagespec simply expands to nothing. The line directly after the
+> line you quoted checks for syntax errors in the pagespec translation
+> eval and seems to be working fine:
+> 
+>      joey@kodama:~>perl -e 'use IkiWiki; my
+>      $sub=IkiWiki::pagespec_translate("link(tag/<TMPL_VAR name>) and !papers/*"); print "caught failure:".$@'
+>      caught failure:syntax error at (eval 14) line 1, near "|| &&"
+> 
+> Based on your line numbers, you are not running a current version of
+> ikiwiki. (Doesn't quite seem to be version 2.53.x either) Try with a current
+> version, and see if you can send me a source tree that can reproduce the
+> problem? --[[Joey]]
diff --git a/doc/bugs/basewiki_uses_meta_directives_but_meta_is_not_enabled_by_default.mdwn b/doc/bugs/basewiki_uses_meta_directives_but_meta_is_not_enabled_by_default.mdwn
new file mode 100644 (file)
index 0000000..62931d8
--- /dev/null
@@ -0,0 +1,5 @@
+[[plugins/meta]] is not enabled by default, yet some pages in the default basewiki include [[the_meta_directive|ikiwiki/directive/meta]], notably the [[ikiwiki]] heirarchy.
+
+This means that the default output of "ikiwiki src dest", for two empty directories src and dest, result in the meta directive being displayed inline with the page text.
+
+> [[done]], meta now enabled by default.
diff --git a/doc/bugs/beautify__95__urlpath_will_add_.__47___even_if_it_is_already_present.mdwn b/doc/bugs/beautify__95__urlpath_will_add_.__47___even_if_it_is_already_present.mdwn
new file mode 100644 (file)
index 0000000..8e96b1f
--- /dev/null
@@ -0,0 +1,3 @@
+beautify_urlpath will prepend a useless "./" to the URL "./foo". Fixed in commit 5b1cf21a on my comments branch. --[[smcv]]
+
+[[!tag patch done]]
index c57c200651dfd2ea21b113e0d7d8cbb9db86cc3d..eead716d53011642f27b237307f6aa47d03005c7 100644 (file)
@@ -28,3 +28,23 @@ If I then edit the blog post, **then** the file gets commited and I can see the
 >>>> However, the part that seems a bit wrong to me, is this: even if my locale is utf8, I have to explicitly set a utf8 locale in the wiki's setup file, or the commit fails. It looks like ikiwiki is not using this machine's default locale, which is utf8. Also, I'm not getting any errors on apache's error log.
 
 >>>> Wouldn't it make sense to use the machine's default locale if 'locale' is commented out in the setup file?
+
+>>>>> Ikiwiki wrappers only allow whitelisted environment variables
+>>>>> through, and the locale environment variables are not included
+>>>>> currently.
+>>>>>
+>>>>> But that's not the whole story, because "machine's default locale"
+>>>>> is not very well defined. For example, my laptop is a Debian system.
+>>>>> It has a locale setting in /etc/environment (`LANG="en_US.UTF-8"`).
+>>>>> But even if I start apache, making sure that LANG is set and exported
+>>>>> in the environment, CGI scripts apache runs do not see LANG in their 
+>>>>> environment. (I notice that `/etc/init.d/apache` explocitly
+>>>>> forces LANG=C. But CGI scripts don't see the C value either.)
+>>>>> Apache simply does not propigate its runtime environment to CGI
+>>>>> scripts, and this is probably to comply with the CGI specification
+>>>>> (although it doesn't seem to completly rule out CGI's being passed
+>>>>> other variables).
+>>>>>
+>>>>> If mercurial needs a utf-8 locale, I guess the mercurial plugin needs
+>>>>> to check if it's not in one, and do something sane (either fail
+>>>>> earlier, or complain, or strip utf-8 out of comments). --[[Joey]]
diff --git a/doc/bugs/bugfix_for:___34__mtn:_operation_canceled:_Broken_pipe__34_____40__patch__41__.mdwn b/doc/bugs/bugfix_for:___34__mtn:_operation_canceled:_Broken_pipe__34_____40__patch__41__.mdwn
new file mode 100644 (file)
index 0000000..b7f38fd
--- /dev/null
@@ -0,0 +1,24 @@
+When using monotone as revision control system, a "mtn: operation canceled: Broken pipe" message is printed. Reason is that, in a call to mtn, the pipe is closed before mtn has done all its output. This patch fixes the problem.
+
+    diff -up ikiwiki/IkiWiki/Plugin/monotone.pm.orig ikiwiki/IkiWiki/Plugin/monotone.pm
+    --- ikiwiki/IkiWiki/Plugin/monotone.pm.orig        2008-11-12 23:45:24.000000000 +0100
+    +++ ikiwiki/IkiWiki/Plugin/monotone.pm     2008-12-16 12:41:38.000000000 +0100
+    @@ -525,13 +525,12 @@ sub rcs_recentchanges ($) {
+       my $child = open(MTNLOG, "-|");
+       if (! $child) {
+               exec("mtn", "log", "--root=$config{mtnrootdir}", "--no-graph",
+    -               "--brief") || error("mtn log failed to run");
+    +               "--brief", "--last=$num") || error("mtn log failed to run");
+       }
+     
+    -  while (($num >= 0) and (my $line = <MTNLOG>)) {
+    +  while (my $line = <MTNLOG>) {
+               if ($line =~ m/^($sha1_pattern)/) {
+                       push @revs, $1;
+    -                  $num -= 1;
+               }
+       }
+       close MTNLOG || debug("mtn log exited $?");
+
+> Thanks for the patch, and for testing the monotone backend.
+> applied [[done]] --[[Joey]]
diff --git a/doc/bugs/bzr_RecentChanges_dates_start_from_1969.mdwn b/doc/bugs/bzr_RecentChanges_dates_start_from_1969.mdwn
new file mode 100644 (file)
index 0000000..fa6e45b
--- /dev/null
@@ -0,0 +1,16 @@
+Using bzr, the dates for changes on the RecentChanges page all start
+slightly before the Unix epoch.
+
+Changing line 249 of bzr.pm from
+
+`                        when       => time - str2time($info->{"timestamp"}),`
+
+to
+
+`                        when       => str2time($info->{"timestamp"}),`
+
+fixed this for me.
+
+> Weird, I wonder why it was written to return an absolute time like that
+> in the first place? Can't have ever been right. Fixed, thanks. --[[Joey]]
+> [[done]]
diff --git a/doc/bugs/bzr_plugin_does_not_define_rcs__95__diff.mdwn b/doc/bugs/bzr_plugin_does_not_define_rcs__95__diff.mdwn
new file mode 100644 (file)
index 0000000..0294ec6
--- /dev/null
@@ -0,0 +1,27 @@
+The bzr plugin does not seem to define the rcs_diff subroutine.
+I got the follow error after enabling recentchangesdiff:
+
+"Undefined subroutine &IkiWiki::Plugin::bzr::rcs_diff called at /usr/share/perl5/IkiWiki.pm line 1590."
+
+Grepping to verify absence of rcs_diff:
+
+    $ grep rcs_diff /usr/share/perl5/IkiWiki/Plugin/{git,bzr}.pm
+    /usr/share/perl5/IkiWiki/Plugin/git.pm:    hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+    /usr/share/perl5/IkiWiki/Plugin/git.pm:sub rcs_diff ($) {
+    /usr/share/perl5/IkiWiki/Plugin/bzr.pm:    hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
+
+> I've added the minimal stub needed to avoid the crash, but for
+> recentchangesdiff to work, someone needs to implement `rcs_diff` for bzr.
+> This should be trivial if you know and use bzr. The function
+> is passed as a parameter the revno of interest and just needs
+> to ask bzr for the diff between that and the previous version. --[[Joey]] 
+
+>> I'll see if I can make a patch. The bzr command to get the revision would
+>> look like this: bzr diff -r revno:$PREV:/path/to/src..revno:$REVNO:/path/to/src
+>> (where $PREV would be $REVNO minus one). --liw
+
+>> Sorry, that was not entirely correct, for some reason. I'll add a patch below that
+>> seems to work. I am unfortunately not ready to set up a git repository that you
+>> can pull from. --liw
+
+[[done]] --[[Joey]] 
diff --git a/doc/bugs/cannot_preview_shortcuts.mdwn b/doc/bugs/cannot_preview_shortcuts.mdwn
new file mode 100644 (file)
index 0000000..d7045b2
--- /dev/null
@@ -0,0 +1,17 @@
+Shortcuts such as \[[!google foo]] do not work when previewing pages.
+--[[JasonBlevins]]
+
+> Broken during the setup dumping changes, now fixed. --[[Joey]] [[done]]
+
+>> Just a quick note that this fix interacts with the way the `listdirectives`
+>> directive gets its list of non-shortcut directives.  At the moment it
+>> still works, but it relies on the fact that the `listdirectives` `checkconfig`
+>> hook is called before the `shortcut` `checkconfig` hook.
+>> -- [[Will]]
+
+>> The order plugins are loaded is effectively random. (`keys %hooks`).
+>> So I've made shortcuts pass a 'shortcut' parameter when registering
+>> them, which listdirectives can grep out of the full list of directives.
+>> That may not be the best name to give it, especially if other plugins
+>> generate directives too. Seemed better than forcing shortcut's
+>> checkconfig hook to run last tho. --[[Joey]]
diff --git a/doc/bugs/cannot_reliably_use_meta_in_template.mdwn b/doc/bugs/cannot_reliably_use_meta_in_template.mdwn
new file mode 100644 (file)
index 0000000..de6c227
--- /dev/null
@@ -0,0 +1,18 @@
+meta title cannot reliably be put inside a template used by the
+[[plugins/template]] plugin. Since meta title info is gathered in the scan
+pass, which does not look at the template a page includes, it will not be
+seen then, and so other pages that use the page title probably won't use
+it. (Barring luck with build order.)
+
+Update: This also affects using tags from templates.
+
+There is a simple fix for this, just add `scan => 1` when registering the
+preprocess hook for the template plugin.
+
+However, the overhead of this has to be considered. It means that, on every
+scan pass, every page containing a template will cause the template to be
+loaded and filled out. This can be some serious additional overhead.
+
+--[[Joey]] 
+
+[[done]]
diff --git a/doc/bugs/colon:problem.mdwn b/doc/bugs/colon:problem.mdwn
new file mode 100644 (file)
index 0000000..41f1624
--- /dev/null
@@ -0,0 +1,12 @@
+> Joey, please fix the colon in page name of my report. Ikiwiki sets
+> "attachment:\_failed\_to\_get\_filehandle/" URL on "Bugs" page and
+> the report is not clickable in my Epiphany browser:
+
+>     Firefox doesn't know how to open this address, because the protocol
+>     (attachment) isn't associated with any program.
+
+> I can only edit it :) Bad handling ':' character by Ikiwiki is probably
+> its another bug.
+> --[[Paweł|ptecza]]
+
+> [[fixed|done]] in git (but fix is not live on here as of this writing) --[[Joey]]
diff --git a/doc/bugs/colon:problem/discussion.mdwn b/doc/bugs/colon:problem/discussion.mdwn
new file mode 100644 (file)
index 0000000..e2856ed
--- /dev/null
@@ -0,0 +1 @@
+testing a link to [[colon:problem]]
diff --git a/doc/bugs/comments_produce_broken_links_in_RecentChanges.mdwn b/doc/bugs/comments_produce_broken_links_in_RecentChanges.mdwn
new file mode 100644 (file)
index 0000000..dae0085
--- /dev/null
@@ -0,0 +1,9 @@
+Comments produce links like `sandbox/comment_1` in [[RecentChanges]], which,
+when clicked, redirect to a page that does not exist.
+
+The `recentchanges` branch in my repository contains one possible [[patch]],
+which causes the CGI to go to the [[ikiwiki/directive/meta]] `permalink`, if
+any, if the page is internal (comments do have a permalink).
+
+> [[done]].. I I had thought about not showing internal page changes at
+> all, but I like your approach better --[[Joey]] 
diff --git a/doc/bugs/complex_wiki-code___40__braces__41___in_wikilink-text_breaks_wikilinks.mdwn b/doc/bugs/complex_wiki-code___40__braces__41___in_wikilink-text_breaks_wikilinks.mdwn
new file mode 100644 (file)
index 0000000..364fae3
--- /dev/null
@@ -0,0 +1,9 @@
+Example (from [here](http://git.ikiwiki.info/?p=ikiwiki;a=blobdiff;f=doc/todo/matching_different_kinds_of_links.mdwn;h=26c5a072bf3cb205b238a4e6fd0882583a0b7609;hp=1d7c78d9065d78307b43a1f58a53300cde4015fa;hb=9b4c83127fdef0ceb682c104db9bfb321b17022e;hpb=df4cc4c16ca230ee99b80c80043ba54fb95f6e71)):
+<pre>
+[[`\[[!taglink TAG\]\]`|plugins/tag]]
+</pre>
+gives:
+
+[[`\[[!taglink TAG\]\]`|plugins/tag]]
+
+Expected: there is a [[ikiwiki/wikilink]] with the complex text as the displayed text. --Ivan Z.
index 082f0800c6c84a926476e0f09f72960f300408ff..565f3b16c9a35a788dfc85c88f579591ddbcfa72 100644 (file)
@@ -110,4 +110,4 @@ Index: IkiWiki/Plugin/inline.pm
 
 [[done]] --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
diff --git a/doc/bugs/ddate_plugin_causes_websetup_to_change_timeformat__44___even_when_disabled.mdwn b/doc/bugs/ddate_plugin_causes_websetup_to_change_timeformat__44___even_when_disabled.mdwn
new file mode 100644 (file)
index 0000000..a74f6fc
--- /dev/null
@@ -0,0 +1,7 @@
+If the timeformat option is '%c', every time websetup rewrites the setup file, it changes to a ddate-style time format (but if ddate is not actually enabled, some of the format codes aren't understood by strftime, so they get passed through).
+
+Presumably this is because websetup loads all plugins, so IkiWiki::plugin::ddate::checkconfig is run...
+
+(This bug seems oddly appropriate. Hail Eris)
+
+[[done_fnord|done]]
index 22a1c149c1aa4b0ff02b2303cb0d3303a02c9e2c..d34c40244f56874afbad6dc9ce16541b815a1f3b 100644 (file)
@@ -1,4 +1,4 @@
-`\[[debbug 123456]]` expands to "bug #123456", which is hyperlinked. Could you please drop the leading "bug", for two reasons?
+`\[[!debbug 123456]]` expands to "bug #123456", which is hyperlinked. Could you please drop the leading "bug", for two reasons?
 
 First, #123456 is not a bug, it's a bug report. And second, #123456 suffices, doesn't it? By hardcoding the "bug" in there, you make it impossible to start a sentence with a bug number, e.g.:
 
diff --git a/doc/bugs/defintion_lists_appear_to_be_disabled.mdwn b/doc/bugs/defintion_lists_appear_to_be_disabled.mdwn
new file mode 100644 (file)
index 0000000..6dac9c8
--- /dev/null
@@ -0,0 +1,54 @@
+Adding text of the format 
+
+    Apple
+    :   Pomaceous fruit of plants of the genus Malus in 
+        the family Rosaceae.
+    :   An american computer company.
+
+    Orange
+    :   The fruit of an evergreen tree of the genus Citrus.
+
+Does not result in expected HTML as described in the [MultiMarkdown Syntax Guide](http://fletcherpenney.net/multimarkdown/users_guide/multimarkdown_syntax_guide/):
+
+Should be 
+
+    <dl xmlns="http://www.w3.org/1999/xhtml">
+    <dt>Apple</dt>
+     <dd>
+       <p>Pomaceous fruit of plants of the genus Malus in 
+          the family Rosaceae.</p>
+     </dd>
+     <dd>
+       <p>An american computer company.</p>
+    </dd>
+    <dt>Orange</dt>
+     <dd>
+      <p>The fruit of an evergreen tree of the genus Citrus.</p>
+     </dd>
+    </dl>
+
+But instead it gives:
+
+    <p>Apple
+     :   Pomaceous fruit of plants of the genus Malus in 
+         the family Rosaceae.
+     :   An american computer company.</p>
+
+    <p>Orange
+    :   The fruit of an evergreen tree of the genus Citrus.</p>
+
+> ikiwiki's markdown support does not include support for multimarkdown by
+> default. If you want to enable that, you can turn on the `multimarkdown`
+> option in the setup file. --[[Joey]]
+
+>> Sorry, I should have indicated, I have multimarkdown enabled:
+
+    # mdwn plugin
+    # enable multimarkdown features?
+    multimarkdown => 1,
+
+>>Other features appear to be working, tables and footnotes for instance. See current install: <http://wiki.infosoph.org>
+
+>>> Ok, in that case it's a bug in the perl module. Forwarded to
+>>> <http://github.com/bobtfish/text-markdown/issues#issue/6> --[[Joey]]
+>>> [[!tag done]]
index 74b25f0f072a82284a7b3fcf66d75035c67c609c..415708a504c8483563aa5572f08d97c25a214b3a 100644 (file)
@@ -12,3 +12,21 @@ My first reading (and second and third) of this was that backlinks would be disa
 > Yes, it only controls the number of backlinks that are shown at the
 > bottom of the page vs how many are moved to the popup. I've tried to
 > improve the documentation for this. [[done]] --[[Joey]]
+
+
+I notice that there is quite a bit of redundancy when both tags and
+backlinks are used extensively. On most pages, the set of links features in
+both categories is almost identical because a tag's index page is shown
+both as a tag link and as a backlink. Is there a way to improve that
+situation somehow? I realise that backlinks aren't generated when the tag
+index page refers to its contents by \[\[!map ...]], etc., but sometimes an
+auto-generated index is insufficient.
+
+ --Peter
+
+> Um, if you're manually linking from the tag's page to each page so
+> tagged, I think you have larger problems than tags and backlinks being
+> the same. Like keeping that list of links up to date as tags are added
+> and changed. --[[Joey]]
+
+I see your point, Joey. I need to maintain that list manually, though, because the automatically generated list is too brief. \[[!map ...]] generates just a list of titles or descriptions. I need a list that contains both. See [[this_posting|ikiwiki/directive/map/discussion]] for more details. Until \[[!map]] can do that, I'm stuck with a manually maintained list. Which means that every link shows up in the backlinks.
index 2821220019dfbddd22d4431fea2accb8ed590549..0a666ab11ca95b7f6bd5a83fc2b8db06d6a00c97 100644 (file)
@@ -1,3 +1,3 @@
 recently fixed [[bugs]]
 
-[[inline pages="link(bugs/done) and !bugs and !*/Discussion" sort=mtime show=10]]
+[[!inline pages="link(bugs/done) and !bugs and !*/Discussion" sort=mtime show=10]]
diff --git a/doc/bugs/dumpsetup_does_not_save_destdir.mdwn b/doc/bugs/dumpsetup_does_not_save_destdir.mdwn
new file mode 100644 (file)
index 0000000..768c3fc
--- /dev/null
@@ -0,0 +1,3 @@
+Calling ikiwiki with a bunch of options, including the --dumpsetup somefile.setup option creates somefile.setup for later reuse with the --setup option. The destination dir however is not saved in the setup file, it has destdir => ''.
+
+> that broke in version 2.64 .. fixed [[done]] --[[Joey]]
diff --git a/doc/bugs/edit_preview_resolves_links_differently_from_commit.mdwn b/doc/bugs/edit_preview_resolves_links_differently_from_commit.mdwn
new file mode 100644 (file)
index 0000000..320eca6
--- /dev/null
@@ -0,0 +1,23 @@
+I'm editing /posts/foo. If I create a link to a subpage (in my case,
+"discussion"), and hit preview, it gets resolved to /discussion, not
+/posts/foo/discussion. If I hit commit, the latter happens. This seems like
+a bug. --liw
+
+> That would be a bug, but I cannot reproduce it. For example, I edited
+> <http://kitenet.net/~joey/blog/entry/wikis_out_of_disk/> and added a
+> discussion link and on preview it went to the page's discussion page. I
+> don't normally have a toplevel /discussion page, but I also tried adding
+> one, and the link still doesn't link to it. Testcase? --[[Joey]] 
+
+>> I can reproduce this on <http://blog.liw.fi/posts/distributed-internet-witness-service/>:
+>> if I edit the page, then preview (no changes made), the "discussion" link at the bottom
+>> of the page points in the preview
+>> to <http://blog.liw.fi/discussion/>,
+>> whereas the saved page has it pointing to
+>> <http://blog.liw.fi/posts/distributed-internet-witness-service/discussion/>.
+>> I'll arrange so that you can edit the page to test this.
+>> --liw
+
+>> Joey suggested my wiki might be missing the FORCEBASEURL snippet from the misc.tmpl
+>> template, and he's right. Mea culpa: I had not diffed the various templates when upgrading
+>> and had missed that updated. [[done]] --liw
diff --git a/doc/bugs/entirely_negated_pagespec_matches_internal_pages.mdwn b/doc/bugs/entirely_negated_pagespec_matches_internal_pages.mdwn
new file mode 100644 (file)
index 0000000..a9b223a
--- /dev/null
@@ -0,0 +1,30 @@
+A [[PageSpec]] that is entirely negated terminals, such as "!foo and !bar"
+matches all other pages, including all internal pages. This can lead to
+unexpected results, since it will match a bunch of recentchanges pages,
+etc.
+
+Recall that internal-use pages are not matched by a glob. So "\*" doesn't
+match them. So if the pagespec is "\* and !foo and !bar", it won't match
+them. This is the much more common style.
+
+There's an odd inconsistency with entirely negated pagespecs. If "!foo"
+matches page bar, shouldn't "" also match bar? But, the empty pagespec is
+actually special-cased to not match anything.
+
+Indeed, it seems what would be best would be for "!foo" to not match any
+pages, unless it's combined with a terminal that positively matches pages
+("* and !foo"). Although this would be a behavior change, with transition
+issues.
+
+Another approach would be to try to detect the case of an entirely negated
+pagespec, and implicitly add "and !internal()" to it.
+
+Either approach would require fully parsing the pagespec. And consider cases
+like "!(foo and !bar)". Doesn't seem at all easy to solve. --[[Joey]]
+
+> It occurs to me that at least one place in ikiwiki optimizes by assuming
+> that pagespecs not mentioning the word "internal" never match internal
+> pages. I wonder whether this bug could be solved by making that part of
+> the definition of a pagespec, rather than a risky optimization
+> like it is now? That seems strange, though - having this special case
+> would make pagespecs significantly harder to understand. --[[smcv]]
diff --git a/doc/bugs/errors_with_ampersand_in_filename.mdwn b/doc/bugs/errors_with_ampersand_in_filename.mdwn
new file mode 100644 (file)
index 0000000..6b459d4
--- /dev/null
@@ -0,0 +1,21 @@
+I created an image and a mdwn with an ampersand in the filename.
+This gaves me some error messages.
+I renamed the files and committed.
+
+> Ikiwiki does not allow files containing ampersands or most other non-alphanumeric characters.
+> It will display a "skipping bad filename" warning if you have such files. --[[Joey]]
+
+Even now, I still get the following error messages:
+
+    Use of uninitialized value in substitution (s///) at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 764.
+    Use of uninitialized value in substitution (s///) at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 768.
+    Use of uninitialized value in concatenation (.) or string at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 773.
+    Use of uninitialized value in concatenation (.) or string at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 773.
+    Use of uninitialized value in concatenation (.) or string at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 773.
+    Use of uninitialized value in concatenation (.) or string at /usr/lib64/perl5/vendor_perl/5.8.8/IkiWiki.pm line 773.
+
+> To help with this I'd need to know, at a minimum, what version of ikiwiki you're using,
+> and I'd really also probably need a copy of the source of the wiki you are trying to
+> build with it. (If you'd like to email me a tarball, send it to joey@kitenet.net) --[[Joey]]
+
+> > Hmm... the most recent ikiwiki seems to fix the issue, so I will mark it as [[done]]. --[[JosephTurian]]
diff --git a/doc/bugs/external_links_inside_headings_don__39__t_work.mdwn b/doc/bugs/external_links_inside_headings_don__39__t_work.mdwn
new file mode 100644 (file)
index 0000000..5bab283
--- /dev/null
@@ -0,0 +1,24 @@
+The standalone 'markdown' utility is perfectly happy with an external link inside a `<h1>`, e.g.:
+
+    # Review of [Dwarf Fortress][]
+    ...
+    [Dwarf Fortress]: http://www.bay12games.com/dwarves/
+
+produces
+
+    <h1>Review of <a href="http://www.bay12games.com/dwarves/">Dwarf Fortress</a></h1>
+
+but when I try to use this construct in an ikiwiki page, I get 
+
+    <h1>Review of [Dwarf Fortress][]</h1>
+
+It works fine with h2 and deeper.  The square brackets also appear in the output of an [[ikiwiki/directive/inline]] directive in archive mode, I haven't tried non-archive mode.
+
+> I think you were confused by markdown's slightly wacky mix of square brackets and parens.
+> The url in a markdown link goes in parens, not square brackets. For example:
+
+# [Google](http://google.com/)
+
+> [[done]] --[[Joey]]
+
+>> It works here but it definitely does *not* work on my wiki; but on further experimentation, I believe my problem is being caused by JasonBlevins' [h1title](http://code.jblevins.org/ikiwiki/plugins.git/plain/h1title.pm) plugin.
diff --git a/doc/bugs/feedfile_does_the_wrong_thing_from_index.mdwn2.mdwn b/doc/bugs/feedfile_does_the_wrong_thing_from_index.mdwn2.mdwn
new file mode 100644 (file)
index 0000000..6b8781a
--- /dev/null
@@ -0,0 +1,7 @@
+[[!meta title="feedfile does the wrong thing from index"]]
+
+When I put the following !inline in my index.mdwn, it generate a file called index/graphics.rss.  However, the link in the RSS button is to graphics.rss (i.e., not in the index/ directory).
+
+`\[[!inline pages="link(tags/graphics) and ./posts/* and !*/Discussion" show="10" feedfile=graphics feedonly=yes]]`
+
+[[done]] --[[Joey]] 
diff --git a/doc/bugs/firefox_doesn__39__t_want_to_load_updated_pages_at_ikiwiki.info.mdwn b/doc/bugs/firefox_doesn__39__t_want_to_load_updated_pages_at_ikiwiki.info.mdwn
new file mode 100644 (file)
index 0000000..8cb47f8
--- /dev/null
@@ -0,0 +1,5 @@
+I'm using firefox-3.0.8-alt0.M41.1 (Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4pre) Gecko/2008100921 Firefox/3.0). I have noticed that quite often it shows an old state of a page at http://ikiwiki.info, e.g., [[recentchanges]] without my last edits, or the last page I edited (say, 50 min ago) in the state it was before I edited it.
+
+Only explicitly pressing "reload" helps.
+
+Is it a bug? I haven't been noticing such problems usually on other sites. --Ivan Z.
index 3d4b4a94e0edf45962a3943109ae95f69c0e42bf..dc9a09ebb6f3ddb68e46acdba33e0b47dcb4ecfa 100644 (file)
@@ -15,7 +15,7 @@ encouraging.
 
 > This is a bug in markdown, not in ikiwiki. Markdown often has issues with
 > one sort of list followed by a second sort. I've filed a bug report on
-> markdown about this ([[debbug 432152]])
+> markdown about this ([[!debbug 432152]])
 
 > (BTW, this bug was filed by editing the bugs page directly. Please don't
 > do that, use the form to generate a new per-bug page..)
index fdd1df5339ff70111aa97f5dc8334cec6a6dda9d..25aa417d0e5507897f5b84c8ebb5f63069ad354a 100644 (file)
@@ -28,3 +28,5 @@ Thanks.
 >>> setting, or one in the environment will be ignored. (This is done for
 >>> security since ikiwiki can be run setuid.) If you need to use
 >>> a nonstandard path, you'll need to edit that. --[[Joey]]
+
+[[!tag done]]
diff --git a/doc/bugs/git_stderr_output_causes_problems.mdwn b/doc/bugs/git_stderr_output_causes_problems.mdwn
new file mode 100644 (file)
index 0000000..c25ef69
--- /dev/null
@@ -0,0 +1,42 @@
+I've just been getting ikiwiki running on a hosted server.  The server is wrapping all cgi scripts to 'harden' them.  Unfortunately, that script is sensitive to what a cgi script outputs on stderr.
+
+Ikiwiki's git handling is sending a bunch of output to stderr.  The following patch closes stderr in the child process that ikiwiki forks to run git.  This allows me to use ikiwiki on this hosted server.  (patch inline - check source to get it)
+
+    diff --git a/IkiWiki/Rcs/git.pm b/IkiWiki/Rcs/git.pm
+    index 425536f..5734bb2 100644
+    --- a/IkiWiki/Rcs/git.pm
+    +++ b/IkiWiki/Rcs/git.pm
+    @@ -24,6 +24,7 @@ sub _safe_git (&@) {
+            if (!$pid) {
+                    # In child.
+                    # Git commands want to be in wc.
+    +               open STDERR, '>/dev/null';
+                    chdir $config{srcdir}
+                        or error("Cannot chdir to $config{srcdir}: $!");
+                    exec @cmdline or error("Cannot exec '@cmdline': $!");
+
+> This sounds like rather counter-productive "hardening" (making life harder
+> for real users without any security improvement that I can think of),
+> but if you have to suppress standard error of the CGI,
+> can't you just replace ikiwiki.cgi with this...
+>
+>     #!/bin/sh
+>     exec /some/where/else/ikiwiki.cgi "$@" 2>/dev/null
+>
+> or (if you're constrained to Perl) this?
+>
+>     #!/usr/bin/perl
+>     open STDERR, '>/dev/null';
+>     exec ("/some/where/else/ikiwiki.cgi", @ARGV);
+>
+> (Also indented all the lines of your patch so markdown won't eat it :-) )
+> --[[smcv]]
+
+> Right, I don't like throwing stderr away because stderr is supposed to be
+> logged to error.log for a reason: To allow debugging problems.
+> It's unfortunate that git [abuses atderr](http://bugs.debian.org/447395),
+> outputting non-errors to it. That doesn't mean that git might not also
+> output actual error messages there. --[[Joey]]
+
+>> I'm happy with the wrapper script solution, so this is [[done]].
+>> And this report is now here to point others to that solution.
index c465bdd4ab7c579aa60db318bc3d81ae83ef08a7..564982ff34e7f7f2715c7796e613c51aac57282b 100644 (file)
@@ -8,3 +8,7 @@ cases of the one which was installed directly before the current commit.
 > I don't see one, except for diffs that show all changes in the commit,
 > rather than only changes to a single file. This feels like a bug in
 > gitweb. --[[Joey]]
+
+This is fixed by using the new gitweb style urls. Which new gitweb
+requires, but is a manual change you have to make in your setup. So,
+[[done]] --[[Joey]] 
index 255d9cee774ad523d0bdbf33b75eceafbc514120..0b4d70596a2445d268db36958fb0156e1fe08dd2 100644 (file)
@@ -8,3 +8,6 @@ Going from *RecentChanges*, when viewing the diffs of newly created pages
 > I don't see any way to make gitweb do that. You can click on the filename
 > after the "diff -cc" to see the whole file output, but gitweb won't show
 > a diff for a newly added file. --[[Joey]]
+
+>> happily this, too, is fixed by using the new style gitweb urls. [[done]]
+>> --[[Joey]] 
diff --git a/doc/bugs/goto_with_bad_page_name.mdwn b/doc/bugs/goto_with_bad_page_name.mdwn
new file mode 100644 (file)
index 0000000..bc462c8
--- /dev/null
@@ -0,0 +1,25 @@
+If goto is passed a page name that 
+contains spaces or is otherwise not a valid page name,
+it will display a "page does not exist", with a create link. But,
+clicking on the link will result in "bad page name".
+
+I have found at least two ways it can happen:
+
+* If 404 is enabled, and the user goes to "http://wiki/some page with spaces"
+* If mercurial is used, it pulls the user's full name, with spaces,
+  out for `rcs_recentchanges` and that ends up on RecentChanges.
+
+When fixing, need to keep in mind that we can't just run the input through
+titlepage, since in all other circumstances, the page name is already valid
+and we don't want to doubly-encode it.
+
+Seems like the goto plugin needs to check if the page name is valid and
+pass it through titlepage if not.
+
+(As a side effect of this, 404 will start redirecting "http://wiki/some page
+with spaces" to "http://wiki/some_page_with_spaces", if the latter exists.
+That seems like a fairly good thing.)
+
+[[done]]
+
+--[[Joey]] 
diff --git a/doc/bugs/html5_support.mdwn b/doc/bugs/html5_support.mdwn
new file mode 100644 (file)
index 0000000..2394742
--- /dev/null
@@ -0,0 +1,47 @@
+Some elements of
+[HTML5](http://www.whatwg.org/specs/web-apps/current-work/multipage/) can be
+safely supported by ikiwiki. There are [several differences between HTML4 and
+HTML5](http://www.w3.org/TR/html5-diff/).
+
+[[!template id=gitbranch branch=hendry/html5 author="[[Kai_Hendry|hendry]]"]]
+
+* [HTML5 branch](http://git.webconverger.org/?p=ikiwiki;h=refs/heads/html5)
+* [ikiwiki instance with HTML5 templates](http://natalian.org)
+* [HTML5 outliner tool](http://gsnedders.html5.org/outliner/) -- to check you have the structure of your markup correct
+
+# htmlscrubber.pm needs to not scrub new HTML5 elements
+
+* [new elements](http://www.w3.org/TR/html5-diff/#new-elements)
+
+# HTML5 Validation and t/html.t
+
+[validator.nu](http://validator.nu/) is the authorative HTML5 validator,
+however it is almost impossible to sanely introduce as a build dependency
+because of its insane Java requirements. :( I test locally via
+[cURL](http://wiki.whatwg.org/wiki/IDE), though Debian packages cannot be built
+with a network dependency.
+
+In the future, hopefully ikiwiki can test for valid HTML5 using [Relax NG
+schema](http://syntax.whattf.org/) using a Debian package tool
+[rnv](http://packages.qa.debian.org/r/rnv.html).
+
+# HTML5 migration issues
+
+# [article](http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-article-element) element
+
+This element is poorly supported by browsers. As a workaround, `style.css` needs:
+
+       article {
+               display: block;
+       }
+
+Internet Explorer will display it as a block, though you can't seem to be able to further control the style.
+
+## Time element
+
+The [time element](http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-time-element) ideally needs the datatime= attribute set by a template variable with what [HTML5 defines as a valid datetime string](http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#valid-global-date-and-time-string).
+
+As a workaround:
+
+       au:~% grep timeformat natalian.setup
+       timeformat => '%Y-%m-%d',
index 5a60e0449caef7372f7fddfb6bfee72fbcfaec8e..aef2f7f71dc4e364b65e52a90a4d3cc50e135945 100644 (file)
@@ -1,2 +1,5 @@
 ikiwiki will generate html formatted error messages to the command
 line if --cgi is set, even if it's not yet running as a cgi
+
+> [[done]], at last. Oldest open bug.. just thought of an elegant fix!
+> --[[Joey]]
diff --git a/doc/bugs/htmlscrubber_undoes_email_obfuscation_by_Text::Markdown.mdwn b/doc/bugs/htmlscrubber_undoes_email_obfuscation_by_Text::Markdown.mdwn
new file mode 100644 (file)
index 0000000..12018d5
--- /dev/null
@@ -0,0 +1,37 @@
+From the source of [[usage]]:
+
+    <a href="mailto:joey@ikiwiki.info">&#x6A;&#111;&#101;&#x79;&#64;i&#107;&#105;w&#105;&#107;&#x69;&#46;&#105;n&#x66;&#x6F;</a>
+
+Text::Markdown obfuscates email addresses in the href= attribute and in the text.
+Apparently this can't be configured.
+
+HTML::Scrubber doesn't set `attr_encoded` for its HTML::Parser, so the href= attribtute is decoded.
+Currently it seems it doesn't set `attr_encoded` for good reason: so attributes can be sanitized easily,
+e.g. as in htmlscrubber with `$safe_url_regexp`.
+This apparently can't be configured either.
+
+So I can't see an obvious solution to this.
+Perhaps improvements to Text::Markdown or HTML::Scrubber can allow a fix.
+
+One question is: how useful is email obfuscation?
+Don't spammers use HTML parsers?
+
+> I now see this was noted in the formatting [[/ikiwiki/formatting/discussion]], and won't/can't be fixed.
+> So I guess this is [[done]]. --Gabriel
+
+I've [[patch]]ed mdwn.pm to prevent Text::Markdown from obfuscating the emails.
+The relevant commits are on the master branch of [my "fork" of ikiwiki on Github] [github]:
+
+- 7d0970adbcf0b63e7e5532c239156f6967d10158
+- 52c241e723ced4d7c6a702dd08cda37feee75531
+
+--Gabriel.
+
+[github]: http://github.com/gmcmanus/ikiwiki/
+
+> Thanks for coming up with a patch, but overriding
+> `Text::Markdown::_EncodeEmailAddress` gets into its internals more than
+> I'm comfortable with.
+> 
+> It would probably be best to add an option to [[!cpan Text::Markdown]] to
+> let the email address munging be disabled. --[[Joey]]
index ec02ddb898bd4916861c701e4a72960855938b39..2882eeb12711dd01733464644847331370b3267c 100644 (file)
@@ -23,4 +23,4 @@ I see two possibilities how to fix this:
 > to be no way to override it reading /etc/tidy.conf, so options there can
 > still screw things up. I guess I'll pass --markup yes and deal with
 > overriding other problem settings from config files if they're found
-> later. --[[Joey]] [[tag done]]
+> later. --[[Joey]] [[!tag done]]
index e8f87f9c4dc0956097be2c04b6daf4ab876cc37e..3d0c99b83bb7ecc5c484b25c2eb0ea7c76921e65 100644 (file)
@@ -6,10 +6,42 @@ I have found if I add:
 
     newenviron[i++]="HTTPS_PROXY=http://host.domain.com:3128";
 
-to IkiWiki/Wrapper.pm it solves the problem for https requests, however it obviously would be preferred if the proxy name is not configured.
+to IkiWiki/Wrapper.pm it solves the problem for https requests, however it obviously would be preferred if the proxy name is not hard coded.
 
 Also, the ability to set HTTPS\_CA\_FILE and HTTPS\_CA\_DIR might benefit some people. Then again, it I can't see any evidence that the SSL certificate of the server is being checked. See the [[bug_report|ssl_certificates_not_checked_with_openid]] I filed on this separate issue.
 
 Unfortunately, HTTP\_PROXY doesn't work for http requests, it looks like that library is different.
 
+---
+
+Update 2008-10-26:
+
+Better solution, one that works for both http and https, and uses config options. It appears to work...
+
+Note that using $ua->proxy(['https'], ...); won't work, you get a "Not Implemented" error, see <http://community.activestate.com/forum-topic/lwp-https-requests-proxy>. Also see [[!debbug 129528]].
+
+Also note that the proxy won't work with liblwpx-paranoidagent-perl, I had to remove liblwpx-paranoidagent-perl first.
+
+Please get the patch from the *.mdwn source.
+
+louie:/usr/share/perl5/IkiWiki/Plugin# diff -u openid.pm.old openid.pm
+--- openid.pm.old      2008-10-26 12:18:58.094489360 +1100
++++ openid.pm  2008-10-26 12:40:05.763429880 +1100
+@@ -165,6 +165,14 @@
+               $ua=LWP::UserAgent->new;
+       }
++      if (defined($config{"http_proxy"})) {
++              $ua->proxy(['http'], $config{"http_proxy"});
++      }
++
++      if (defined($config{"https_proxy"})) {
++              $ENV{HTTPS_PROXY} = $config{"https_proxy"};
++      }
++
+       # Store the secret in the session.
+       my $secret=$session->param("openid_secret");
+       if (! defined $secret) {
+
+
 Brian May
diff --git a/doc/bugs/ikiwiki_is_not_truly_localizable.mdwn b/doc/bugs/ikiwiki_is_not_truly_localizable.mdwn
deleted file mode 100644 (file)
index 11bf1ca..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-A lot of strings in ikiwiki are hardcoded and not taken for locales resources through gettext. This is bad because ikiwiki is thus difficult to spread for non-english users.
-
-I mean that, for instance in CGI.pm, line like:
-
-`my @buttons=("Save Page", "Preview", "Cancel");`
-
-should be written as
-
-`my @buttons=(gettext("Save Page"), gettext("Preview"), gettext("Cancel"));`
-
-> Yes, these need to be fixed. But note that the localised texts come back
-> into ikiwiki and are used in various places, including plugins.
-> Including, possibly, third-party plugins. So localising the buttons would
-> seem to require converting from the translations back into the C locale
-> when the form is posted. --[[Joey]]
-
-In standards templates things seems wrongly written too. For instance in page.tmpl line like:
-
-`<li><a href="<TMPL_VAR EDITURL>" rel="nofollow">Edit</a></li>`
-
-should be written as
-
-`<li><a href="<TMPL_VAR EDITURL>" rel="nofollow"><TMPL_VAR EDITURL_TEXT</a></li>`
-
-with EDITURL_TEXT variable initialized in Render.pm through a gettext call. 
-
-Am I wrong ?
-
-> No, that's not a sane way to localise the templates. The templates can be
-> translated by making a copy and modifying it, or by using a tool to
-> generate .mo files from the templates, and generate translated templates
-> from .po files. (See [[todo/l10n]] for one attempt.) But pushing the
-> localisation of random strings in the templates through the ikiwiki
-> program defeats the purpose of having templates at all. --[[Joey]]
-
-If not I can spend some time preparing patches for such corrections if it can help.
-
--- [[/users/bbb]]
diff --git a/doc/bugs/images_in_inlined_pages_have_wrong_relative_URL.mdwn b/doc/bugs/images_in_inlined_pages_have_wrong_relative_URL.mdwn
new file mode 100644 (file)
index 0000000..8cda7a7
--- /dev/null
@@ -0,0 +1,15 @@
+I can make an image link, such as:
+
+    ![image](image.jpg)
+
+That will render as ![image](image.jpg).
+
+If I then inline that page, the (relative) URL no longer points to the right place.  The fix for this promises to be hairy.
+
+> Similarly, if you insert a relative link using the markdown link syntax,
+> it will tend to break when the page is inlined.
+> 
+> However, there is a simple way to avoid both problems: Use WikiLinks
+> and/or the [[img_directive|ikiwiki/directive/img]]. --[[Joey]]
+
+[[!tag done]]
index e2b85e4983e32133a049d6bfd7f152ee27a49348..14de1755784327a0a7cefa75740c081b901ce2a8 100644 (file)
@@ -1,6 +1,6 @@
 The img plugin causes a taint failure if one tries to link a scaled image, e.g.
 
-    \[[img foo.png size=64x64]]
+    \[[!img foo.png size=64x64]]
 
     .ikiwiki.setup: Insecure dependency in mkdir while running with -T switch at /usr/lib/perl5/vendor_perl/5.8.8/IkiWiki.pm line 360.
     BEGIN failed--compilation aborted at (eval 5) line 109.
index f7883dbb7ab9d83af3325a791192df16cb00930f..6b861c39772cb76045e07929345f9a0b510c4b2a 100644 (file)
@@ -33,4 +33,4 @@ I have been unable to reproduce this outside of the `madduck.net` website...
 
 **Update**: this is the same bug as [[the_colon-in-links_bug|No_link_for_blog_items_when_filename_contains_a_colon]]
 
-[[tag done]]
+[[!tag done]]
index 2e67d63574788acb5736da313d3d4e9808d688aa..f72ecade2b41cfebfb6fa1f52af3552f4dca59d8 100644 (file)
@@ -26,7 +26,7 @@ And here's a patch to implement it. Will this survive markdown munging? It seems
     index 7226231..3eb1ae7 100644
     --- a/Plugin/img.pm
     +++ b/Plugin/img.pm
-    @@ -93,9 +93,15 @@ sub preprocess (@) { #{{{
+    @@ -93,9 +93,15 @@ sub preprocess (@) {
                     $imgurl="$config{url}/$imglink";
             }
      
@@ -42,7 +42,7 @@ And here's a patch to implement it. Will this survive markdown munging? It seems
     +        $result .= '/></a>';
     +
     +        return $result;
-     } #}}}
+     }
      
      1
     -- 
diff --git a/doc/bugs/img_with_alt_has_extra_double_quote.mdwn b/doc/bugs/img_with_alt_has_extra_double_quote.mdwn
new file mode 100644 (file)
index 0000000..81bbe7f
--- /dev/null
@@ -0,0 +1,32 @@
+The [[ikiwiki/directive/img]] directive emits an extra double quote if alt=x is
+specified (as is necessary for valid HTML). This results in malformed HTML,
+like this:
+
+    <img src="U" width="W" height="H"" alt="A" />
+                                     ^
+
+This [[patch]] is available from the img-bugfix branch in my git repository:
+
+    commit a648c439f3467571374daf597e9b3a659ea2008f
+    Author: Simon McVittie <smcv@ http://smcv.pseudorandom.co.uk/>
+    Date:   2009-06-16 17:15:06 +0100
+    
+        img plugin: do not emit a redundant double-quote before alt attribute
+    
+    diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm
+    index a697fea..a186abd 100644
+    --- a/IkiWiki/Plugin/img.pm
+    +++ b/IkiWiki/Plugin/img.pm
+    @@ -121,7 +121,7 @@ sub preprocess (@) {
+            my $imgtag='<img src="'.$imgurl.
+                    '" width="'.$im->Get("width").
+                    '" height="'.$im->Get("height").'"'.
+    -               (exists $params{alt} ? '" alt="'.$params{alt}.'"' : '').
+    +               (exists $params{alt} ? ' alt="'.$params{alt}.'"' : '').
+                    (exists $params{title} ? ' title="'.$params{title}.'"' : '').
+                    (exists $params{class} ? ' class="'.$params{class}.'"' : '').
+                    (exists $params{id} ? ' id="'.$params{id}.'"' : '').
+
+--[[smcv]]
+
+[[done]] --[[Joey]] 
index e56bd7941cea8557b88a5e380bc597c3a3d540b5..2f20d66bb0af9d2d2bc3b6b814850c74b21cda42 100644 (file)
@@ -10,6 +10,6 @@ After editing a page `pagename`, ikiwiki redirects to `pagename/index.html?updat
 > said broken software will then display its old out of date cached
 > version.
 > 
-> So, not changing this. [[tag done]]
+> So, not changing this. [[!tag done]]
 > 
 > --[[Joey]]
diff --git a/doc/bugs/index.html_is_made_visible_by_various_actions.mdwn b/doc/bugs/index.html_is_made_visible_by_various_actions.mdwn
new file mode 100644 (file)
index 0000000..5618015
--- /dev/null
@@ -0,0 +1,16 @@
+When you do various CGI actions, "index.html" is visible in the redirection URL. It's desirable that this is avoided, so there is only one visible URL for each page (search engines don't think that /foo/index.html is equivalent to /foo/, since this is not necessarily true for all servers and configurations).
+
+[The beautify branch in my repository](http://git.debian.org/?p=users/smcv/ikiwiki.git;a=shortlog;h=refs/heads/beautify) contains [[patches|patch]] for all the cases I found by grepping for "htmlpage", which are:
+
+* [[plugins/editpage]] redirects you to the page under various circumstances, most visibly after you finish editing it
+* [[plugins/poll]] redirects you to the poll after voting
+* [[plugins/recentchanges]] redirects you to the relevant page when you click a link
+* [[plugins/remove]] redirects you to the parent of the removed page
+
+I think the coding standard in future should be: use htmlpage when you want a local file, or urlto if you want a URL.
+
+> Agreed, and I've updated the docs accordingly. Merged your changes. BTW,
+> did you notice they included a fix in passing for a bug in the recentchanges
+> redirection? [[done]] --[[Joey]]
+
+>> No, I suppose I must have assumed htmlpage already did the pagetype check... --[[smcv]]
index 1c715221e17ef1759c3cc6eb5dd7ea33b5a090a1..a99f8d6dafae60f0fd02157a4a7faaaba7849e55 100644 (file)
@@ -1,7 +1,7 @@
 Hi, I try to make an example to reproduce some bug with inline and toc plugins.
 My friend uses
 
-    \[[inline pages="users/joey" raw="yes"]]
+    \[[!inline pages="users/joey" raw="yes"]]
 
 to include common snippets in various pages, and it works as advertised, but if toc plugin is used, page is messed up.
 
@@ -26,7 +26,7 @@ All this is displayed correctly if toc is removed.
 > [here](http://bugs.debian.org/421843).
 > 
 > I'm going to close this bug report since it's a markdown bug. --[[Joey]]
-[[tag done]]
+[[!tag done]]
 
 >> thanks, that fixes it.
 
@@ -42,11 +42,11 @@ bla bla bla
  * bl bla
  * aadsd
 
-[[toc levels=2]]
+[[!toc levels=2]]
 
 bla bla
 
-[[table data="""
+[[!table data="""
 Customer|Amount
 Fulanito|134,34
 Menganito|234,56
@@ -59,6 +59,6 @@ Menganito|234,56
 Here's a paragraph.
 
 
-[[inline pages="users/joey" raw="yes"]]
+[[!inline pages="users/joey" raw="yes"]]
 
 bla bla
diff --git a/doc/bugs/inline_from_field_empty_if_rootpage_doesn__39__t_exist.mdwn b/doc/bugs/inline_from_field_empty_if_rootpage_doesn__39__t_exist.mdwn
new file mode 100644 (file)
index 0000000..61aeff2
--- /dev/null
@@ -0,0 +1,20 @@
+If I put something like the below in my index.mdwn
+
+    <<!inline pages="posts/* and !*/discussion" rootpage="posts" show="10">>
+
+But posts doesn't exist, I get the following in index.html
+
+    <input type="hidden" name="do" value="blog" />
+    <input type="hidden" name="from" value="" />
+    <input type="hidden" name="subpage" value="1" />
+
+When I create posts (touch posts.mdwn), I get the following in index.html
+
+    <input type="hidden" name="do" value="blog" />
+    <input type="hidden" name="from" value="posts" />
+    <input type="hidden" name="subpage" value="1" />
+
+Bug?
+
+> Yes, thanks for reminding me I need to do something about that... [[done]]
+> --[[Joey]]
index e8f033aa4e775afb654841f58e14119f10777e9f..8ef1281171a0c6f322db5de5286437f2090d9ca7 100644 (file)
@@ -6,4 +6,4 @@ But maybe this is intended behavior? --rdennis
 > filesystem. It just avoids you having to get the case right when
 > referring to existing files, by wikilinks or pagespecs --[[Joey]] 
 
-[[tag done]]
+[[!tag done]]
diff --git a/doc/bugs/inline_sort-by-title_issues.mdwn b/doc/bugs/inline_sort-by-title_issues.mdwn
new file mode 100644 (file)
index 0000000..ff45550
--- /dev/null
@@ -0,0 +1,57 @@
+The [[plugins/inline]] plugin has a `sort="title"` option that causes the pages in the list to be sorted by title rather than creation time.  The [[plugins]] list on this wiki was recently changed to use this option.  If you look at the plugin page, you'll notice that it doesn't look correctly sorted.  e.g. `attach (third party plugin)` falls between `conditional` and `default content for *copyright* and *license*`.
+
+I think the problem here is that the pages are being sorted by their path, whereas only the basename is displayed.  This makes the example above:
+
+ * plugins/conditional
+ * plugins/contrib/attach
+ * plugins/contrib/default content for *copyright* and *license*
+
+and now you can see why it is ordered that way, and why later on we get:
+
+ * plugins/contrib/unixauth (third party plugin)
+ * plugins/creole
+
+which appears to list `unixauth` before `creole`.
+
+I'm not sure what the best fix is.  One fix would be to add another sort option, `sort="path"`, that would use the current (broken) sort by title.  Then add a true `sort="title"` that actually sorts on the title.  It might also be interesting to modify the sort=path to actually list the full path in the links - that way it would be obvious how it is sorted.  Or you could ignore the idea for `sort="path"`, and tell people to use [[plugins/map]] for that.
+
+--[[users/Will]]
+
+And here is a [[patch]] for this.  It makes `sort=title` actually sort on the title, and adds `sort=path` if you really want to sort on the path.  `sort=path` still only displays titles.  Just use map if you want more.
+
+    diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
+    index 9c336e7..99f6de3 100644
+    --- a/IkiWiki/Plugin/inline.pm
+    +++ b/IkiWiki/Plugin/inline.pm
+    @@ -185,9 +185,12 @@ sub preprocess_inline (@) {
+               }
+       }
+     
+    -  if (exists $params{sort} && $params{sort} eq 'title') {
+    +  if (exists $params{sort} && $params{sort} eq 'path') {
+               @list=sort @list;
+       }
+    +  elsif (exists $params{sort} && $params{sort} eq 'title') {
+    +          @list=sort { lc(pagetitle(basename($a))) cmp lc(pagetitle(basename($b))) } @list;
+    +  }
+       elsif (exists $params{sort} && $params{sort} eq 'mtime') {
+               @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
+       }
+    diff --git a/doc/ikiwiki/blog.mdwn b/doc/ikiwiki/blog.mdwn
+    index 19ec7ac..7608628 100644
+    --- a/doc/ikiwiki/blog.mdwn
+    +++ b/doc/ikiwiki/blog.mdwn
+    @@ -89,7 +89,8 @@ Here are some less often needed parameters:
+       inlining page.
+     * `sort` - Controls how inlined pages are sorted. The default, "age" is to
+       sort newest created pages first. Setting it to "title" will sort pages by
+    -  title, and "mtime" sorts most recently modified pages first.
+    +  title, "path" sorts by the path to the page, and "mtime" sorts most
+    +  recently modified pages first.
+     * `reverse` - If set to "yes", causes the sort order to be reversed.
+     * `feedshow` - Specify the maximum number of matching pages to include in
+       the rss/atom feeds. The default is the same as the `show` value above.
+
+> Thanks for the patch. [[done]], but I left off the sort=path. Also left
+> off the lc (if you ask your locale to sort case-sensatively, it should, I
+> think). --[[Joey]]
diff --git a/doc/bugs/inline_sort_order_and_meta_date_value.mdwn b/doc/bugs/inline_sort_order_and_meta_date_value.mdwn
new file mode 100644 (file)
index 0000000..d4ec8f3
--- /dev/null
@@ -0,0 +1,314 @@
+I have a directory containing two files. f1 (<http://alcopop.org/~jon/repro2/src/blog/debgtd.html>) has 
+
+    meta date="2008-07-02 14:13:17"
+
+f2 (<http://alcopop.org/~jon/repro2/src/blog/moving.html>) has
+
+    meta date="2008-07-02 21:04:21"
+
+They have both been modified recently:
+
+    >>> stat(f1)
+    (33188, 459250L, 65027L, 1, 1000, 1000, 1686L, 1227967177, 1227966706, 1227966706)
+    >>> stat(f2)
+    (33188, 458868L, 65027L, 1, 1000, 1000, 938L, 1227967187, 1227966705, 1227966705)
+
+Note that f1 is fractionally newer than f2 in terms of ctime and mtime, but f2 is much newer in terms of the meta information.
+
+Another page includes them both via inline:
+
+    inline pages="blog/*" show=5
+
+The resulting page is rendered with f1 above f2, seemingly not using the meta directive information: <http://alcopop.org/~jon/repro2/dest/blog/>. The footer in the inline pages does use the correct time e.g. <em>Posted Wed 02 Jul 2008 14:13:17 BST</em>.
+
+If I instead include them using creation_year in the pagespec, they are ordered correctly.
+
+<http://alcopop.org/~jon/repro2/> contains the src used to reproduce this, the precise ikiwiki invocation (inside Makefile) and the results (dest).
+
+-- [[users/Jon]]
+
+
+> On Ikiwiki 2.53.3 (Debian Lenny), my inlines are also sorted using mtime
+> by default -- despite what the [[documentation|/ikiwiki/directive/inline]]
+> says -- but setting the supposed default sort order manually produces the
+> correct results.  For example, the following inline sorts my blog
+> entires using their meta date or ctime:
+> 
+>     inline pages="blog/*" show="10" sort="age"
+> 
+> I'll try to look at the code this weekend and see if age is really the
+> default sort order.
+> 
+> -- [David A. Harding](http://dtrt.org), 2008-12-20
+
+Here is the code. As you can see, sort="age" is equivilant to leaving
+out the sort option. --[[Joey]] 
+
+       if (exists $params{sort} && $params{sort} eq 'title') {
+               @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
+       }
+       elsif (exists $params{sort} && $params{sort} eq 'mtime') {
+               @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
+       }
+       elsif (! exists $params{sort} || $params{sort} eq 'age') {
+               @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+       }
+       else {
+               return sprintf(gettext("unknown sort type %s"), $params{sort});
+       }
+
+> On further testing, I find that the bug is limited to the first time
+> creation time should be used and has nothing to do with setting the sort
+> parameter. Revised steps to reproduce: --[David A.  Harding](http://dtrt.org), 2008-12-20
+> 
+> 1. Create pages that sort different by mtime and ctime
+> 
+> 2. inline pages="somepages/*"
+> 
+> 3. ikiwiki --setup setup_file
+> 
+> 4. Pages are output incorrectly in mtime order
+> 
+> 5. ikiwiki --setup setup_file
+> 
+> 6. Pages are output correctly in ctime order
+> 
+> 7. Create new page in somepages/, set its ctime to earlier than another
+>    page in sompages/
+> 
+> 8. ikiwiki --setup setup_file
+> 
+> 9. All previously sorted pages output correctly in ctime order but new
+>    page is output incorrectly at the top as if its mtime was its ctime
+> 
+> 10. ikiwiki --setup setup_file
+> 
+> 11. All pages, including new page, are output correctly in ctime order
+
+You're confusing ctime and creation time. This is perhaps not suprising, as
+ikiwiki uses the term 'ctime' to refer to creation time. However, the unix
+ctime value is not the same thing. Unix ctime can change if a file changes
+owner, or in some cases, permissions. Unix ctime also always changes
+when the file is modified. Ikiwiki wants a first creation date of the file,
+and it accomplishes this by recording the initial ctime of a file the first
+time it processes it, and *preserving* that creation time forever, ignoring
+later ctime changes.
+
+I suspect that this, coupled with the fact that ikiwiki sorts newest pages
+first, explains everything you describe. If not, please send me a shell script
+test case I can run, as instructions like "Create pages that sort different by
+mtime and ctime" are not ones that I know how to follow (given that touch sets
+*both*). --[[Joey]] 
+
+> Sorry. I conflated Unix ctime and ikiwiki's creation time because I
+> didn't think the difference was important to this case. I'm a writer,
+> and I should have known better -- I appologize. Revised steps to
+> reproduce are below; feel free to delete this whole misunderstanding
+> to make the bug report more concise.
+>
+> 1. Create pages in the srcdir that should sort in one order by
+>    last-modification time and in a diffent order by original creation
+>    time.  For example:
+> 
+>         $ echo -e '\[[!meta date="2007-01-01"]]\nNew.' > test/new.mdwn
+>         $ echo -e '\[[!meta date="2006-01-01"]]\nOld.' > test/old.mdwn
+> 
+> 2. Create a page that includes the files.  For example:
+> 
+>
+>         $ echo '\[[!inline pages="test/*"]]' > sort-test.mdwn
+> 
+> 3. Run ikiwiki.  For example `ikiwiki --setup setup_file`
+> 
+> 4. Pages are output incorrectly in modification time order. For example,
+>    actual partial HTML of the sort-test/index.html from commands used
+>    above (whitespace-only lines removed; one whitespace-only line
+>    added):
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/old/">old</a>
+>         </span>
+>         <p>Old.</p>
+>         <span class="pagedate">
+>         Posted Sun 01 Jan 2006 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/new/">new</a>
+>         </span>
+>         <p>New.</p>
+>         <span class="pagedate">
+>         Posted Mon 01 Jan 2007 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+> 5. Run ikiwiki again with the same command line.  For example: `ikiwiki --setup setup_file`
+> 
+> 6. Pages are output correctly in creation time order. For example,
+>    actual partial HTML of the sort-test/index.html from commands used
+>    above (whitespace-only lines removed; one whitespace-only line
+>    added):
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/new/">new</a>
+>         </span>
+>         <p>New.</p>
+>         <span class="pagedate">
+>         Posted Mon 01 Jan 2007 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/old/">old</a>
+>         </span>
+>         <p>Old.</p>
+>         <span class="pagedate">
+>         Posted Sun 01 Jan 2006 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+> 7. Create a new page with the current Unix mtime and Unix ctime, but a
+>    !meta date before the most recent creation date of another page.
+>    For example:
+> 
+>         $ echo -e '\[[!meta date="2005-01-01"]]\nOlder.' > test/older.mdwn
+> 
+> 8. Run ikiwiki again with the same command line.  For example: `ikiwiki --setup setup_file`
+> 
+> 9. All previously sorted pages output correctly in order of their
+>    creation time, but the new page is output incorrectly at the top as
+>    if its modification time was its creation time.  For example,
+>    actual partial HTML of the sort-test/index.html from commands used
+>    above (whitespace-only lines removed; two whitespace-only
+>    lines added):
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/older/">older</a>
+>         </span>
+>         <p>Older.</p>
+>         <span class="pagedate">
+>         Posted Sat 01 Jan 2005 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/new/">new</a>
+>         </span>
+>         <p>New.</p>
+>         <span class="pagedate">
+>         Posted Mon 01 Jan 2007 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/old/">old</a>
+>         </span>
+>         <p>Old.</p>
+>         <span class="pagedate">
+>         Posted Sun 01 Jan 2006 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+> 10. Run ikiwiki again with the same command line.  For example: `ikiwiki --setup setup_file`
+> 
+> 11. All pages, including new page, are output correctly in creation time
+>     order. For example, actual partial HTML of the sort-test/index.html
+>     from commands used above (whitespace-only lines removed; two
+>     whitespace-only lines added): 
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/new/">new</a>
+>         </span>
+>         <p>New.</p>
+>         <span class="pagedate">
+>         Posted Mon 01 Jan 2007 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/old/">old</a>
+>         </span>
+>         <p>Old.</p>
+>         <span class="pagedate">
+>         Posted Sun 01 Jan 2006 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+>         <div class="inlinepage">
+>         <span class="header">
+>         <a href="./../test/older/">older</a>
+>         </span>
+>         <p>Older.</p>
+>         <span class="pagedate">
+>         Posted Sat 01 Jan 2005 12:00:00 AM EST
+>         </span>
+>         </div>
+> 
+> File status after all the above actions:
+> 
+>         $ stat test/*
+>           File: `test/new.mdwn'
+>           Size: 33              Blocks: 8          IO Block: 4096   regular file
+>         Device: ca20h/51744d    Inode: 684160      Links: 1
+>         Access: (0644/-rw-r--r--)  Uid: ( 1000/ harding)   Gid: ( 1000/ harding)
+>         Access: 2008-12-20 21:48:32.000000000 -0500
+>         Modify: 2008-12-20 21:27:03.000000000 -0500
+>         Change: 2008-12-20 21:27:03.000000000 -0500
+>           File: `test/older.mdwn'
+>           Size: 35              Blocks: 8          IO Block: 4096   regular file
+>         Device: ca20h/51744d    Inode: 684407      Links: 1
+>         Access: (0644/-rw-r--r--)  Uid: ( 1000/ harding)   Gid: ( 1000/ harding)
+>         Access: 2008-12-20 21:48:32.000000000 -0500
+>         Modify: 2008-12-20 21:42:10.000000000 -0500
+>         Change: 2008-12-20 21:42:10.000000000 -0500
+>           File: `test/old.mdwn'
+>           Size: 33              Blocks: 8          IO Block: 4096   regular file
+>         Device: ca20h/51744d    Inode: 684161      Links: 1
+>         Access: (0644/-rw-r--r--)  Uid: ( 1000/ harding)   Gid: ( 1000/ harding)
+>         Access: 2008-12-20 21:48:32.000000000 -0500
+>         Modify: 2008-12-20 21:27:09.000000000 -0500
+>         Change: 2008-12-20 21:27:09.000000000 -0500
+> 
+> My ikiwiki configuration file (being used to port a blog from pyblosxom
+> to ikiwiki):
+> 
+>         harding@mail:~$ sed 's/#.*//; /^[       ]*$/d' .ikiwiki/gnuisance.setup 
+>         use IkiWiki::Setup::Standard {
+>               wikiname => "HardingBlog",
+>               adminemail => 'dave@dtrt.org',
+>               srcdir => "/srv/backup/git/gnuisance.net",
+>               destdir => "/srv/test.dtrt.org",
+>               url => "http://srv.dtrt.org",
+>               wrappers => [
+>               ],
+>               atom => 1,
+>               syslog => 0,
+>               prefix_directives => 1,
+>               add_plugins => [qw{goodstuff tag}],
+>               disable_plugins => [qw{passwordauth}],
+>               tagbase => "tag",
+>         }
+>
+> --[David A. Harding](http://dtrt.org/), 2008-12-20
+
+Thank you for a textbook excellent reproduction recipe.
+
+What appears to be going on here is that meta directives are not processed
+until the leaf pages are rendered, and thus the ctime setting is not
+available at the time that they are inlined, and the newer unix ctime is
+used. On the second build, the meta data has already been recorded.
+
+This can probably be avoided by processing meta date at scan time.
+
+Verified, fix works. [[done]]
+--[[Joey]] 
diff --git a/doc/bugs/install_into_home_dir_fails.mdwn b/doc/bugs/install_into_home_dir_fails.mdwn
new file mode 100644 (file)
index 0000000..e08b748
--- /dev/null
@@ -0,0 +1,57 @@
+dunno if it just me, but I had to add PREFIX a few places to get 'perl INSTALL_BASE=$HOME' to work
+
+> That will cause the files to be installed into a place that ikiwiki
+> doesn't look for them. It will also cause them to be installed into
+> /usr/etc by default, where ikiwiki also won't find them. 
+> 
+> Thomas Keller also ran into some sort of problem with the MacPort
+> involving the installation into /etc. From that discussion:
+> 
+> Both ikiwiki-update-wikilist and ikiwiki-mass-rebuild hardcode /etc; so
+> do several pages in the doc wiki.
+> 
+> The real problem though is that MakeMaker does not have a standard way
+> of specifying where /etc files go. In Debian we want everything to go
+> into /usr, rather than the default /usr/local, so set PREFIX=/usr -- but
+> we still want config files in /etc, not /usr/etc. The only way I can see
+> around this is to add a nonstandard variable to control the location of
+> /etc, that would override the PREFIX.
+> 
+> Which implies that you can't just use "$installdir/etc/" in the /etc
+> hardcoding scripts, and would instead need to record the new variable
+> at build time, like PREFIX is recorded in $installdir.
+>
+> Instead, let's ignore failure of the lines. [[done]]
+> 
+> --[[Joey]]
+
+<pre>
+From a1e02fbdaba3725730418a837b506e713904ada5 Mon Sep 17 00:00:00 2001
+From: David Bremner <bremner@pivot.cs.unb.ca>
+Date: Fri, 29 Aug 2008 15:18:24 -0300
+Subject: [PATCH] add missing $(PREFIX) to install path
+
+---
+ Makefile.PL |    6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/Makefile.PL b/Makefile.PL
+index 979483c..1f27394 100755
+--- a/Makefile.PL
++++ b/Makefile.PL
+@@ -50,9 +50,9 @@ extra_clean:
+        $(MAKE) -C po clean
+
+ extra_install:
+-       install -d $(DESTDIR)/etc/ikiwiki
+-       install -m 0644 wikilist $(DESTDIR)/etc/ikiwiki
+-       install -m 0644 auto.setup $(DESTDIR)/etc/ikiwiki
++       install -d $(DESTDIR)$(PREFIX)/etc/ikiwiki
++       install -m 0644 wikilist $(DESTDIR)$(PREFIX)/etc/ikiwiki
++       install -m 0644 auto.setup $(DESTDIR)$(PREFIX)/etc/ikiwiki
+
+        install -d $(DESTDIR)$(PREFIX)/share/ikiwiki
+        for dir in `cd underlays && find . -follow -type d ! -regex '.*\.svn.*'`; do \
+--
+1.5.6.3
+</pre>
diff --git a/doc/bugs/links_misparsed_in_CSV_files.mdwn b/doc/bugs/links_misparsed_in_CSV_files.mdwn
new file mode 100644 (file)
index 0000000..27d2b7b
--- /dev/null
@@ -0,0 +1,27 @@
+If a link inside a CSV file contains two or more underscores (\_), then it will get mis-parsed by the table plugin.
+
+e.g. \[[single\_track\_lines]] becomes "em>lines".
+
+Links with only one underscore are OK.
+
+Update 2008-11-24: The problem only occurs if the CSV data is in an external file. If I load it using data="""...""" then it works fine.
+
+The problem appears to be the call to htmlize inside genrow. If the data is inline, then wikilinks get expanded before they get here, and are OK. If the data is from an external file, the wikilinks aren't expanded, and htmlize will expand \[[single\_track\_lines]] into \[[single&lt;em&gt;track&lt;/em&gt;lines]].
+
+Oh, wait, I see the problem. IkiWiki::linkify is only called if the external file doesn't exist. If I remove this check and always call IkiWiki::linkify, then the problem is solved.
+
+(this is inside /usr/share/perl5/IkiWiki/Plugin/table.pm).
+
+> To reproduce this bug, I had to install the old, broken markdown 1.0,
+> instead of the now-default Text::Markdown.
+> 
+> Why is linkify not called for external files? Well, I checked the
+> history, and it's probably best to say "for historical reasons that no
+> longer apply". So, changed as you suggest. [[done]] --[[Joey]] 
+
+I am rather confused what this check does, and the fact the comments are very different for CSV and DSV when the code is the same doesn't seem to help.
+
+> The code is not the same; two operations are run in different orders for
+> CSV and DSV, as the comments note. --[[Joey]] 
+
+-- Brian May
index 63c5b5e0850d97d6251206a2e3f047ad652008bf..b8023ce87bb265220641022310b24c09f93734a4 100644 (file)
@@ -1,3 +1,21 @@
-[[plugins/lockedit]] adds the form fields for a [[pagespec]] to preferences. This pagespec should be supplied "raw"; i.e., without quotes around it. Inexperienced users (such as [[myself|jondowland]]) may provide an invalid pagespec, such as one with quotes on it. This will be merrily accepted by the form, but will cause no locking to take place.
+[[plugins/lockedit]] adds the form fields for a [[pagespec]] to preferences. This pagespec should be supplied "raw"; i.e., without quotes around it. Inexperienced users (such as [[myself|users/jon]]) may provide an invalid pagespec, such as one with quotes on it. This will be merrily accepted by the form, but will cause no locking to take place.
 
 Perhaps some validation should be performed on the pagespec and the form-submission return include "warning: this pagespec is invalid" or "warning: this pagespec does not match any existing pages" or similar.
+
+> The pagespec is no longer in the preferences and instead in the setup
+> file now. That makes warning about a problem with it harder.
+> 
+> Ikiwiki could try to detect this problem and warn at setup time to
+> stderr, I guess.
+> 
+> Main problem is I see little way to actually detect the problem you
+> described. A pagespec with quotes around it is valid. For example, the
+> pagespec `"foo or bar"` matches a page named `"foo` or a page named `bar"`.
+>
+> There are small classes of invalid pagespecs. For example, `(foo or bar`
+> is invalid due to having unbalanced parens, while `foo or and bar` 
+> has invalid syntax. It's possible to detect these, I guess ... --[[Joey]]
+
+>> Having moved it to the .setup file makes things more obvious I think.
+>> Anyway I consider this [[done]], please de-done this if you disagree.
+>> --[[Jon]]
diff --git a/doc/bugs/login_page_should_note_cookie_requirement.mdwn b/doc/bugs/login_page_should_note_cookie_requirement.mdwn
new file mode 100644 (file)
index 0000000..9668605
--- /dev/null
@@ -0,0 +1,33 @@
+At the moment, you go through the login shuffle and then are told that cookies are needed, so you lose all your data and login again.  It would be much slicker to note by the edit link, or at least on the login page, that cookies are required.
+
+> Hmm, it seems to me to be fairly obvious, since the vast majority of
+> websites that have a login require cookies. Such warnings used to be
+> common, but few sites bother with them anymore. --[[Joey]]
+
+>> Very few websites break without cookies.  Even fewer lose data.
+>> Can ikiwiki avoid being below average by default? --[MJR](http://mjr.towers.org.uk)
+
+>>> Can we avoid engaging in hyperbole? (Hint: Your browser probably has a
+>>> back button. Hint 2: A username/password does not count as "lost data".
+>>>  Hint 3: Now we're arguing, which is pointless.) --[[Joey]]
+
+Even better would be to only display the cookie note as a warning if the login page doesn't receive a session cookie.
+
+> I considered doing this before, but it would require running the cgi once
+> to attempt to set the cookie and then redirecting to the cgi a second
+> time to check if it took, which is both complicated and probably would
+> look bad.
+
+>> Might this be possible client-side with javascript? A quick google suggests it is possible:
+>> <http://www.javascriptkit.com/javatutors/cookiedetect.shtml>. MJR, want to try adding
+>> that?  -- [[Will]]
+
+Best of all would be to use URL-based or hidden-field-based session tokens if cookies are not permitted.
+
+> This is not very doable since most of the pages the user browses are
+> static pages in a static location.
+
+>> The pages that lose data without cookies (the edit pages, primarily)
+>> don't look static. Are they really? --[MJR](http://mjr.towers.org.uk)
+
+>>> As soon as you post an edit page, you are back to a static website.
index 5d6c6ad6d4e16729cf3bb6e8a4c8f1c74b9253ea..e8392a80dc49a291d7a527846e91bbf52eadbc0e 100644 (file)
@@ -1,5 +1,5 @@
-[[meta title="mailto: links not properly generated in rss/atom feeds"]]
+[[!meta title="mailto: links not properly generated in rss/atom feeds"]]
 
 A link like \[this](mailto:foo@bar.org) will not be converted correctly to a mailto link in the rss/atom feeds, but an absolute link instead. See e.g. the logitech post on http://madduck.net/blog/feeds/planet-lca2008/index.rss
 
-> fixed --[[Joey]] [[tag done]]
+> fixed --[[Joey]] [[!tag done]]
index afc5d90cc7212db35dd2718826e98b7d5a7740d0..d197cdb6c41da17e4e3091b7ff8c56e0c87c659e 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="map does not link entries which are equal to basename(current_page)"]]
+[[!meta title="map does not link entries which are equal to basename(current_page)"]]
 
 On <http://phd.martin-krafft.net/wiki/tag/factors/>, the top-level `factors` entry is not linked to the corresponding page. Looking at <http://phd.martin-krafft.net/wiki/tag/factors/language/>, this must be because the page name is the same as the entry name, and ikiwiki probably doesn't take the complete path of subpages into account.
 
index d6923605d157fce7551959874191c4d5277aaeba..df00621d8459241af07f04ef364a21b39cbcc22f 100644 (file)
@@ -4,7 +4,7 @@ Problem with [[plugins/map]]:
 
 ## given map:
 
-\[[map pages="blog/tags/*"]]
+\[[!map pages="blog/tags/*"]]
 
 ## received map:
 
diff --git a/doc/bugs/map_fails_to_close_ul_element_for_empty_list.mdwn b/doc/bugs/map_fails_to_close_ul_element_for_empty_list.mdwn
new file mode 100644 (file)
index 0000000..5e842ca
--- /dev/null
@@ -0,0 +1,95 @@
+[[!tag plugins/map patch]]
+
+input:
+
+    before.
+    \[[!map pages="sdfsdfsdfsd/*"]]
+    after.
+
+Presuming that the pagespec does not match, output:
+
+    <p>before.
+    <div class="map">
+    <ul>
+    </div></p>
+
+The UL element is not closed.
+
+Patch:
+
+    --- /usr/share/perl5/IkiWiki/Plugin/map.pm  2009-05-06 00:56:55.000000000 +0100
+    +++ IkiWiki/Plugin/map.pm   2009-06-15 12:23:54.000000000 +0100
+    @@ -137,11 +137,11 @@
+            $openli=1;
+            $parent=$item;
+        }
+    -   while ($indent > 0) {
+    +   while ($indent > 1) {
+            $indent--;
+            $map .= "</li>\n</ul>\n";
+        }
+    -   $map .= "</div>\n";
+    +   $map .= "</ul>\n</div>\n";
+        return $map;
+     }
+     
+
+-- [[Jon]]
+
+> Strictly speaking, a `<ul>` with no `<li>`s isn't valid HTML either...
+> could `map` instead delay emitting the first `<ul>` until it determines that
+> it will have at least one item? Perhaps refactoring that function into
+> something easier to regression-test would be useful. --[[smcv]]
+
+>> You are right (just checked 4.01 DTD to confirm). I suspect refactoring
+>> the function would be wise. From my brief look at it to formulate the
+>> above I thought it was a bit icky.  I'm not a good judge of what would
+>> be regression-test friendly but I might have a go at reworking it. With
+>> this variety of problem I have a strong inclination to use HOFs like map,
+>> grep. - [[Jon]]
+
+>>> The patch in [[map/discussion|plugins/map/discussion]] has the same
+>>> problem, but does suggest a simpler approach to solving it (bail out
+>>> early if the map has no items at all). --[[smcv]]
+
+>>>> Thanks for pointing out the problem. I guess this patch should solve it.
+>>>> --[[harishcm]]
+
+>>>>> Well, I suppose that's certainly a minimal patch for this bug :-)
+>>>>> I'm not the IkiWiki maintainer, but if I was, I'd apply it, so I've put
+>>>>> it in a git branch for Joey's convenience. Joey, Jon: any opinion?
+>>>>>
+>>>>> If you want to be credited for this patch under a name other than
+>>>>> "harishcm" (e.g. your real name), let me know and I'll amend the branch.
+>>>>> (Or, make a git branch of your own and replace the reference just below,
+>>>>> if you prefer.) --[[smcv]]
+
+>>>>>> The current arrangement looks fine to me. Thanks. --[[harishcm]]
+
+[[!template id=gitbranch author="[[harishcm]]" branch=smcv/ready/harishcm-map-fix]]
+
+> [[merged|done]] --[[Joey]] 
+
+Patch:
+
+    --- /usr/local/share/perl/5.8.8/IkiWiki/Plugin/map.pm
+    +++ map.pm
+    @@ -80,7 +80,17 @@
+       my $indent=0;
+       my $openli=0;
+       my $addparent="";
+    -  my $map = "<div class='map'>\n<ul>\n";
+    +  my $map = "<div class='map'>\n";
+    +
+    +  # Return empty div if %mapitems is empty
+    +  if (!scalar(keys %mapitems)) {
+    +          $map .= "</div>\n";
+    +          return $map; 
+    +  } 
+    +  else { # continue populating $map
+    +          $map .= "<ul>\n";
+    +  }
+    +
+       foreach my $item (sort keys %mapitems) {
+               my @linktext = (length $mapitems{$item} ? (linktext => $mapitems{$item}) : ());
+               $item=~s/^\Q$common_prefix\E\///
diff --git a/doc/bugs/map_is_inconsistent_about_bare_directories.mdwn b/doc/bugs/map_is_inconsistent_about_bare_directories.mdwn
new file mode 100644 (file)
index 0000000..a53296d
--- /dev/null
@@ -0,0 +1,86 @@
+The [[plugins/map]] plugin has inconsistent behaviour.  In particular, I have in my wiki some directory structures holding files without wikitext pointers (I point directly to the files from elsewhere).  For example, imagine the following file structure in the source dir:
+
+    ; ls -R dirA dirB
+    dirA:
+    subA       subB
+    
+    dirA/subA:
+    filea.mdwn fileb.mdwn
+    
+    dirA/subB:
+    filec.mdwn filed.mdwn
+    
+    dirB:
+    subA       subC
+    
+    dirB/subA:
+    filea.mdwn
+    
+    dirB/subC:
+    fileb.mdwn filec.mdwn
+
+When I use map to make a map of this, the result looks more like this:
+
+<ul>
+<li><span class="createlink">? dirA</span>
+<ul>
+<li><span class="createlink">? subA</span>
+<ul>
+<li>filea
+</li>
+</ul>
+<ul>
+<li>fileb
+</li>
+</ul>
+<ul>
+<li>filec
+</li>
+<li>filed
+</li>
+</ul>
+</li>
+</ul>
+</li>
+<li><span class="createlink">? dirB</span>
+<ul>
+<li><span class="createlink">? subA</span>
+<ul>
+<li>filea
+</li>
+</ul>
+</li>
+</ul>
+<ul>
+<li><span class="createlink">? subC</span>
+<ul>
+<li>fileb
+</li>
+</ul>
+<ul>
+<li>filec
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
+Note that while the dirA/subA directory exists with a create link, the dirA/subB directory is missing from the map.  Interestingly, dirB/subC is shown in the map.  If you add a second file to dirB/subA then dirB/subC disappears as well.
+
+I could imagine including all 'bare' directories in the map, and I could imagine including no 'bare' directories in the map.  Just including the first bare directory seems a strange intermediate point.
+
+Attached is a [[patch]] that fixes the issue.  The current map code makes one pass over the sorted list of pages.  This adds an initial pass that goes through and makes sure that all parent directories are included.  With this initial pass added, the following pass could probably be simplified.
+
+One solution could also use the [[plugins/autoindex]] plugin to make sure that parent pages actually exist.  This is really only a stop-gap solution until the patch is applied - map still needs to be made bug-free.
+
+Note: This patch adds items to a map while it is in a foreach loop over a sorted list of keys from that same map.  Changing a map while iterating through it is normally problematic.  I'm assuming the sort insulates the code from this - I do not need to iterate over any of the newly added elements.
+
+-- [[users/Will]]
+
+> The patch is subtly buggy and just papers over the actual bug with a
+> lot of extra code. Thanks for trying to come up with a patch for this
+> annyoingly complicated bug.. I think I've fixed the underlying bug now.
+> --[[Joey]]
+> 
+> [[!tag done]]
diff --git a/doc/bugs/markdown_bug:_email_escaping_and_plus_addresses.mdwn b/doc/bugs/markdown_bug:_email_escaping_and_plus_addresses.mdwn
new file mode 100644 (file)
index 0000000..6fccc5c
--- /dev/null
@@ -0,0 +1,37 @@
+compare:
+
+    * <jon+markdownbug@example.org>
+    * <jon.markdownbug@example.org>
+
+* <jon+markdownbug@example.org>
+* <jon.markdownbug@example.org>
+
+It seems putting a '+' in there throws it. Maybe it's a markdown bug, or maybe the obfuscation markdown applies to email-links is being caught by the HTML sanitizer.
+
+ -- [[users/Jon]]
+
+> It's a markdown bug. For some reason, markdown doesn't recognize the email with a '+' as an email:
+>
+>     $ echo '<a+b@c.org>' | markdown
+>     <p><a+b@c.org></p>
+>
+> htmlscrubber then (rightly) removes this unknown tag.
+>
+
+>> Filed [in CPAN](http://rt.cpan.org/Ticket/Display.html?id=37909)
+>> --[[Joey]] [[!tag done]]
+
+> But I've noticed some other Text::Markdown bugs that, even with htmlscrubber, produce
+> [ill-formed (X)HTML](http://validator.w3.org/check?uri=http%3A%2F%2Fikiwiki.info%2Fbugs%2Fmarkdown_bug%3A_email_escaping_and_plus_addresses%2F).
+> (View the markdown source of this page.)
+>
+> --Gabriel
+
+>> The htmlscrubber does not attempt to produce valid html from invalid. It
+>> attempts to prevent exploits in html. The tidy plugin can force html to
+>> valid. --[[Joey]]
+
+<tt>
+
+- 
+>
index dab40d684fccec2ccb221c7b006c7d4fc4170e14..3bbf4e5fd5ffe2e5c9f68c2792b2b26c88c56e94 100644 (file)
@@ -6,7 +6,7 @@ Here is a patch that's seems to work, although I'm not quite sure what's wrong w
     --- mercurial.pm        2007-03-24 16:14:35.000000000 +0100
     +++ /home/hbernard/mercurial.pm 2007-04-19 19:05:47.000000000 +0200
     @@ -95,7 +95,7 @@
-     sub rcs_add ($) { # {{{
+     sub rcs_add ($) {
             my ($file) = @_;
      
     -       my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "add", "$file");
diff --git a/doc/bugs/messed_up_repository.mdwn b/doc/bugs/messed_up_repository.mdwn
new file mode 100644 (file)
index 0000000..e245b84
--- /dev/null
@@ -0,0 +1,21 @@
+I messed up my local clone of my repository.
+
+It appears that there is a special clone, which contains .ikiwiki, local.css, recentchanges, and the like.
+
+How can I create a new version of this clone?
+
+> No, there's the srcdir, which ikiwiki populates with some of those files
+> when run. Notably the .ikiwiki directory and all its contents, and the
+> recentchanges directory and its contents. But not local.css.
+> 
+> If you've lost .ikiwiki and it contained user registration info
+> (passwords etc), you've lost that info. Everything else can be 
+> regenerated by running `ikiwiki -setup your.setup`
+> 
+> If you still have .ikiwiki, but the git clone is messed up somehow, you
+> can just make a new clone and move .ikiwiki into it before running
+> ikiwiki. --[[Joey]]
+
+> > Great, that worked. Thanks Joey!
+
+[[!tag done]]
diff --git a/doc/bugs/methodResponse_in_add__95__plugins.mdwn b/doc/bugs/methodResponse_in_add__95__plugins.mdwn
new file mode 100644 (file)
index 0000000..c82b532
--- /dev/null
@@ -0,0 +1,41 @@
+**problem description:** when using an external plugin like rst, the cgi script (but not the build process) fails with the following words:
+
+    Unsuccessful stat on filename containing newline at /usr/share/perl5/IkiWiki.pm line 501.
+    Unsuccessful stat on filename containing newline at /usr/share/perl5/IkiWiki.pm line 501.
+    Failed to load plugin IkiWiki::Plugin::</methodResponse>
+    : Can't locate IkiWiki/Plugin/.pm in @INC (@INC contains: /home/ikiwiki/.ikiwiki /etc/perl \
+    /usr/local/lib/perl/5.10.0 /usr/local/share/perl/5.10.0 /usr/lib/perl5 /usr/share/perl5 \
+    /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at (eval 44) line 3. 
+    BEGIN failed--compilation aborted at (eval 44) line 3.
+
+**setup used:** blank debian sid with ikiwiki 2.61 (but as the patch can be cleanly merged to git HEAD, i suppose this would happen on HEAD as well). perl version is 5.10.0-13.
+
+**problem analysis:** `strings ikiwiki.cgi` tells that the stored WRAPPED\_OPTIONS contain the string "&lt;/methodResponse&gt;\n" where i'd expect "rst" in `config{add_plugins}`. this seems to originate in the use of `$_` in the plugin loading function.
+
+**patch comment:** solves the problem on 2.61. as these are the first lines of perl i've knowingly written, i can not explain what exactly was happening there.
+
+> Perl's `$_` handling is the worst wart on it, or possibly any language.
+> Here it's an alias to the actual value in the array, and when deep
+> in the external plugin load code something resets `$_` to a different
+> value, the alias remains and it changes the value at a distance.
+> 
+> Thanks for the excellent problem report, [[fixed|done]]. --[[Joey]]
+
+------------------------------------------------------------------------------
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index e476521..d43abd4 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -471,7 +471,11 @@ sub loadplugins () {
+                    unshift @INC, possibly_foolish_untaint($config{libdir});
+            }
+     
+    -       loadplugin($_) foreach @{$config{default_plugins}}, @{$config{add_plugins}};
+    +       my $pluginname;
+    +       foreach $pluginname (@{$config{default_plugins}}, @{$config{add_plugins}})
+    +       {
+    +               loadplugin($pluginname);
+    +       }
+     
+            if ($config{rcs}) {
+                    if (exists $IkiWiki::hooks{rcs}) {
diff --git a/doc/bugs/multiple_pages_with_same_name.mdwn b/doc/bugs/multiple_pages_with_same_name.mdwn
new file mode 100644 (file)
index 0000000..20c38c0
--- /dev/null
@@ -0,0 +1,76 @@
+I'm just working on an updated solution to [[todo/automatic_use_of_syntax_plugin_on_source_code_files]] (see also [[plugins/contrib/highlightcode]] or [[plugins/contrib/sourcehighlight]]).
+
+I realised that this is going to have problems when you ask it to process `.c` and `.h` files with the same base name.  e.g. `hello.c` and `hello.h`.
+
+I tested it briefly with `test.java` and `test.mdwn` just to see what would happen.  Things got quite strange.  The source-highlighting plugin was called (probably for the java file), but then when it calls `pagetype($pagesources{$page})` to figure out the file type, that function returns `mdwn`, which confuses things somewhat.
+
+> This is a known possible point of confusion. If there are multiple source
+> files, it will render them both, in an arbitrary sequence, so one "wins".
+> --[[Joey]]
+
+Anyway, I'm thinking about possible solutions.  The best option I've come up with so far is: when registering an htmlize hook, add a new optional paramter 'keep_extension'.  This would make a source file of `hello.c` generate a page with name `hello.c` rather than the current `hello`.  This would keep the pages unique (until someone makes `hello.c.mdwn`...).
+
+Suggestions welcome.
+
+-- [[Will]]
+
+> Ok, this turned out not to be a hard change.  [[patch]] is below.  With this patch you can tell IkiWiki not to drop the suffix when you register a hook: `hook(type => "htmlize", id => $lang, call => \&htmlize, leavesuffix => 1);`
+
+>> I think that's a good solution to the problem that most syntax plugins
+>> have struggled with. It makes sense. It doesn't solve the case where
+>> you have source files without any extension (eg `Makefile`), but at
+>> least it covers the common cases.
+>>
+>> I'm going to be annoying and call it "keepextension", otherwise, applied
+>> as-is. --[[Joey]] [[done]]
+
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index 4e4da11..853f905 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -618,7 +618,7 @@ sub pagename ($) {
+     
+       my $type=pagetype($file);
+       my $page=$file;
+    -  $page=~s/\Q.$type\E*$// if defined $type;
+    +  $page=~s/\Q.$type\E*$// if defined $type && !$hooks{htmlize}{$type}{leavesuffix};
+       return $page;
+     }
+     
+    diff --git a/t/pagename.t b/t/pagename.t
+    index 96e6a87..58811b9 100755
+    --- a/t/pagename.t
+    +++ b/t/pagename.t
+    @@ -6,7 +6,7 @@ use Test::More tests => 5;
+     BEGIN { use_ok("IkiWiki"); }
+     
+     # Used internally.
+    -$IkiWiki::hooks{htmlize}{mdwn}=1;
+    +$IkiWiki::hooks{htmlize}{mdwn}{call}=1;
+     
+     is(pagename("foo.mdwn"), "foo");
+     is(pagename("foo/bar.mdwn"), "foo/bar");
+
+----
+
+I wonder if this patch will also be useful:
+
+> Reasonable, applied.
+
+    diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
+    index 752d176..3f1b67b 100644
+    --- a/IkiWiki/Render.pm
+    +++ b/IkiWiki/Render.pm
+    @@ -279,7 +279,11 @@ sub refresh () {
+                               else {
+                                       $f=~s/^\Q$config{srcdir}\E\/?//;
+                                       push @files, $f;
+    -                                  $exists{pagename($f)}=1;
+    +                                  my $pagename = pagename($f);
+    +                                  if ($exists{$pagename}) {
+    +                                          warn(sprintf(gettext("Page %s has multiple possible source pages"), $pagename)."\n");
+    +                                  }
+    +                                  $exists{$pagename}=1;
+                               }
+                       }
+               },
diff --git a/doc/bugs/nested_raw_included_inlines.mdwn b/doc/bugs/nested_raw_included_inlines.mdwn
new file mode 100644 (file)
index 0000000..33433e2
--- /dev/null
@@ -0,0 +1,34 @@
+I have the following structure:
+
+## page0
+    # Page 0
+    \[[!inline raw="yes" pages="page1"]]
+
+## page1
+    # Page 1
+    \[[!inline pages="page2"]]
+
+## page2
+    # Page 2
+    test
+
+In this situation, a change in page 2 will trigger a rebuild of page1 but not of page0.
+
+    refreshing wiki..
+    scanning page2.mdwn
+    rendering page2.mdwn
+    rendering page1.mdwn, which depends on page2
+    done
+
+In my real world situation, page1 is actually listing all pages that match a certain tag and page0 is the home page.
+Whenever a page got tagged, it will appear on page1 but not on page0.
+
+Am I missing something? Is this a bug or Ikiwiki not supposed to support this use case?
+
+> Perhaps the inline plugin isn't being clever enough about dependencies -
+> strictly speaking, when a page is inlined with full content, the inlining
+> page should probably inherit all the inlined page's dependencies.
+> That might be prohibitively slow in practise due to the way IkiWiki
+> currently merges pagespecs, though - maybe the patches I suggested for
+> [[separating_and_uniquifying_pagespecs|todo/should_optimise_pagespecs]]
+> would help? --[[smcv]]
diff --git a/doc/bugs/no_easy_way_to_wrap_HTML_container_around_a_set_of_inlined_pages.mdwn b/doc/bugs/no_easy_way_to_wrap_HTML_container_around_a_set_of_inlined_pages.mdwn
new file mode 100644 (file)
index 0000000..1c1cbbb
--- /dev/null
@@ -0,0 +1,23 @@
+The [[ikiwiki/directive/inline]] directive applies a template to each page-to-be-inlined, but the loop over the pages is in the Perl, not the template itself.  This means if I want to wrap a container `<div>` or a `<table>` or whatever around the entire set of inlined pages, I can't do it by just editing the template.  In fact, I think the only way to do it without hacking any Perl is with a wrapper template directive, e.g.
+
+    \[[!template id="wrapinline" pages="..."]]
+
+with a template definition like
+
+    <div id="foo">\[[!inline ... pages="<TMPL_VAR raw_pages>"]]</div>
+
+It would be much more convenient if the loop over pages happened in the template, allowing me to just stick whatever markup I want around the loop.
+
+> Unfortunatly, I don't think this can be changed at this point,
+> it would probably break a lot of stuff that relies on the current
+> template arrangement, both in ikiwiki's internals and in
+> people's own, customised inline templates. (Also, I have some plans
+> to allow a single inline to use different templates for different
+> sorts of pages, which would rely on the current one template per
+> page approach to work.)
+> 
+> But there is a simple workaround.. the first template in
+> an inline has FIRST set, and the last one has LAST set.
+> So you can use that to emit your div or table top and bottom.
+> 
+> [[done]] --[[Joey]] 
diff --git a/doc/bugs/openid_no_longer_pretty-prints_OpenIDs.mdwn b/doc/bugs/openid_no_longer_pretty-prints_OpenIDs.mdwn
new file mode 100644 (file)
index 0000000..85a206b
--- /dev/null
@@ -0,0 +1,17 @@
+The git commit (in my `openid` branch) says it all:
+
+    Update IkiWiki::openiduser to work with Net::OpenID 2.x
+    
+    openiduser previously used a constructor that no longer works in 2.x.
+    However, all we actually want is the (undocumented) DisplayOfURL function
+    that is invoked by the display method, so try to use that.
+
+This bug affects ikiwiki.info (my commits show up in [[RecentChanges]] as http://smcv.pseudorandom.co.uk/ rather than smcv [pseudorandom.co.uk]).
+
+> Cherry picked, thanks. --[[Joey]]
+
+Relatedly, the other commit on the same branch would be nice to have
+(edited to add: I've now moved it, and its discussion, to
+[[todo/pretty-print_OpenIDs_even_if_not_enabled]]). --[[smcv]]
+
+[[!tag done]]
diff --git a/doc/bugs/output_of_successful_rename_should_list_the_full_path_to_affected_pages.mdwn b/doc/bugs/output_of_successful_rename_should_list_the_full_path_to_affected_pages.mdwn
new file mode 100644 (file)
index 0000000..132d234
--- /dev/null
@@ -0,0 +1,14 @@
+I've just renamed a page and received the following as a result:
+
+<p>
+<b>Successfully renamed users/jondowland.mdwn to users/jon.mdwn.</b>
+</p>
+<p>
+
+The following pages have been automatically modified to update their links to users/jon.mdwn:
+<ul>
+<li><a href="./../../tips/convert_mediawiki_to_ikiwiki/discussion/">discussion</a></li><li><a href="./../../tips/untrusted_git_push/discussion/">discussion</a></li></ul>...
+
+In this situation I think the link to pages should be expanded to show the entire path, since there is quite likely to be a lot of things like "discussion". -- [[users/Jon]]
+
+[[done]]
diff --git a/doc/bugs/package_build_fails_in_non-English_environment.mdwn b/doc/bugs/package_build_fails_in_non-English_environment.mdwn
new file mode 100644 (file)
index 0000000..521ba62
--- /dev/null
@@ -0,0 +1,11 @@
+basewiki_brokenlinks.t fails when running dpkg-buildpackage in non-English environment : it greps for an (non-)error message that is i18n'd. This of course does not happen when building in a proper chroot environment... which happens to fail as well, for other reasons, but this will be for another bug.
+
+The `LANG=` on line 9 does not seem to do what it's supposed to, go figure.
+
+I've never had to understand the Unix locales, so I randomly tried to replace `LANG=` in basewiki_brokenlinks.t with :
+
+- `LANG=C` : fails
+- `LANGUAGE=` : fails
+- `LANGUAGE=C` : works!
+
+> For maximum precedence it should have been LC_ALL=C. [[done]], I think... --[[smcv]]
diff --git a/doc/bugs/page_is_not_rebuilt_if_it_changes_extension.mdwn b/doc/bugs/page_is_not_rebuilt_if_it_changes_extension.mdwn
new file mode 100644 (file)
index 0000000..e47be8d
--- /dev/null
@@ -0,0 +1,27 @@
+Suppose a wiki has a source page a.mdwn, which is then moved to a.wiki.
+(Suppose both the mdwn and wikitext plugins are enabled, so this changes how "a" is rendered.)
+Currently, when the wiki is refreshed, ikiwiki doesn't notice the change
+and the page is not rebuilt.
+
+I have a [[patch]] that fixes this.
+The relevant commit on [my Github fork of ikiwiki](http://github.com/gmcmanus/ikiwiki/) is:
+
+    b6a3b8a683fed7a7f6d77a5b3f2dfbd14c849843
+
+The patch (ab)uses`%forcerebuild`, which is meant for use by plugins.
+If, for some reason, a plugin deletes the page's entry in `%forcerebuild`, it won't be rebuilt.
+
+This patch uncovers another problem.
+Suppose a wiki has a source page "a" (no extension)
+which is then moved to "a.mdwn" (or vice versa).
+ikiwiki fails when trying to create a directory "a" where there is a file "a"
+(or vice versa).
+
+The same problem occurs if both "a" and "a.mdwn" exist in the wiki.
+
+> Thank you for looking into it!
+> 
+> On the use of forcerebuild, I think it's acceptable; plugins that unset
+> it would break other plugins that set it, too. 
+> 
+> [[cherry-picked|done]] --[[Joey]]
diff --git a/doc/bugs/pagecount_is_broken.mdwn b/doc/bugs/pagecount_is_broken.mdwn
new file mode 100644 (file)
index 0000000..57df6b7
--- /dev/null
@@ -0,0 +1,4 @@
+The [[plugins/pagecount]] plugin seems to be broken, as it claims there are
+\[[!pagecount ]] pages in this wiki. (if it's not 0, the bug is fixed)
+
+[[fixed|done]] --[[Joey]] 
diff --git a/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn b/doc/bugs/pagespec_can__39__t_match___123__curly__125___braces.mdwn
new file mode 100644 (file)
index 0000000..dee1e98
--- /dev/null
@@ -0,0 +1,44 @@
+I want match pages which have actually curly braces in the names (like this one), but this matches a lot of pages without the braces in their names :( :
+
+[[!inline show="3" feeds="no" archive="yes" pages="*_{*}_*"]]
+
+(note: the inline above has been restricted to 3 matches to keep this page
+concise. Hopefully it is still clear that this page is not in the output set,
+and the 3 pages in the output set do not contain curly braces in their
+titles).
+
+When escaped, it doesn't work at all:
+
+[[!inline show="3" feeds="no" archive="yes" pages="*_\{*}_*"]]
+
+[[!inline show="3" feeds="no" archive="yes" pages="*_{*\}_*"]]
+
+More tests:
+
+"\*{\*":
+
+[[!inline show="3" feeds="no" archive="yes" pages="*{*"]]
+
+"\*\\{\*":
+
+[[!inline show="3" feeds="no" archive="yes" pages="*\{*"]]
+
+> This is due to the current handling of quoting and escaping issues
+> when converting a pagespec to perl code. `safequote` is used to
+> safely quote an input string as a `q{}` quote, and it strips
+> curlies when doing so to avoid one being used to break out of the `q{}`.
+> 
+> Alternative ways to handle it would be:
+>
+> * Escape curlies. But then you have to deal with backslashes
+>   in the user's input as they could try to defeat your escaping.
+>   Gets tricky.
+>
+> * Avoid exposing user input to interpolation as a string. One
+>   way that comes to mind is to have a local string lookup hash,
+>   and insert each user specified string into it, then use the hash
+>   to lookup the specified strings at runtime. [[done]]
+> 
+> --[[Joey]] 
+
+Thank you! I'll try it. --Ivan Z.
index a2eba694cfe9682cc975e3247d1cb0e36c262047..78fed0e5db5eae2a9b4e73aee89bfa8910136a67 100644 (file)
@@ -54,7 +54,7 @@ case the user is given to rebuilding the wiki by hand. --Ethan
 +      }
        return IkiWiki::FailReason->new("syntax error") if $@;
        return $ret;
- } #}}}
+ }
 </pre>
 
 > Thanks, [[done]] --[[Joey]]
index a30ab0fa377508c9a0f9f9bac611980732f4672e..be14e5126eae8d2d67168741222b6c525bddd5c4 100644 (file)
@@ -1,3 +1,281 @@
+[[!tag patch plugins/inline patch/core]]
+
 The `IkiWiki::pagetitle` function does not respect title changes via `meta.title`. It really should, so that links rendered with `htmllink` get the proper title in the link text.
 
 --[[madduck]]
+
+----
+
+It is possible to set a Page-Title in the meta-plugin, but that one isn't
+reused in parentlinks. This patch may fix it.
+
+<ul>
+<li> I give pagetitle the full path to a page.
+<li> I redefine the 'pagetitle'-sub to deal with it.
+<li> to maintain compatibility for IkiWikis without the meta-plugin, i added a 'basename' to the Original-pagetitle.
+</ul>
+
+<pre>
+diff -c /usr/share/perl5/IkiWiki/Render.pm.distrib /usr/share/perl5/IkiWiki/Render.pm
+*** /usr/share/perl5/IkiWiki/Render.pm.distrib  Wed Aug  6 07:34:55 2008
+--- /usr/share/perl5/IkiWiki/Render.pm  Tue Aug 26 23:29:32 2008
+***************
+*** 102,108 ****
+        $template->param(
+                title => $page eq 'index' 
+                        ? $config{wikiname} 
+!                       : pagetitle(basename($page)),
+                wikiname => $config{wikiname},
+                content => $content,
+                backlinks => $backlinks,
+--- 102,108 ----
+        $template->param(
+                title => $page eq 'index' 
+                        ? $config{wikiname} 
+!                       : pagetitle($page),
+                wikiname => $config{wikiname},
+                content => $content,
+                backlinks => $backlinks,
+
+diff -c /usr/share/perl5/IkiWiki/Plugin/parentlinks.pm.distrib /usr/share/perl5/IkiWiki/Plugin/parentlinks.pm
+*** /usr/share/perl5/IkiWiki/Plugin/parentlinks.pm.distrib      Wed Aug  6 07:34:55 2008
+--- /usr/share/perl5/IkiWiki/Plugin/parentlinks.pm      Tue Aug 26 23:19:43 2008
+***************
+*** 44,50 ****
+                        "height_$height" => 1,
+                };
+                $path.="/".$dir;
+!               $title=IkiWiki::pagetitle($dir);
+                $i++;
+        }
+        return @ret;
+--- 44,50 ----
+                        "height_$height" => 1,
+                };
+                $path.="/".$dir;
+!               $title=IkiWiki::pagetitle($path);
+                $i++;
+        }
+        return @ret;
+
+diff -c /usr/share/perl5/IkiWiki.pm.distrib /usr/share/perl5/IkiWiki.pm
+*** /usr/share/perl5/IkiWiki.pm.distrib Wed Aug  6 07:48:34 2008
+--- /usr/share/perl5/IkiWiki.pm Tue Aug 26 23:47:30 2008
+***************
+*** 792,797 ****
+--- 792,799 ----
+        my $page=shift;
+        my $unescaped=shift;
+  
++       $page=basename($page);
++ 
+        if ($unescaped) {
+                $page=~s/(__(\d+)__|_)/$1 eq '_' ? ' ' : chr($2)/eg;
+       }
+
+diff -c /usr/share/perl5/IkiWiki/Plugin/meta.pm.distrib /usr/share/perl5/IkiWiki/Plugin/meta.pm
+*** /usr/share/perl5/IkiWiki/Plugin/meta.pm.distrib     Wed Aug  6 07:34:55 2008
+--- /usr/share/perl5/IkiWiki/Plugin/meta.pm     Tue Aug 26 23:30:58 2008
+***************
+*** 3,8 ****
+--- 3,9 ----
+  package IkiWiki::Plugin::meta;
+  
+  use warnings;
++ no warnings 'redefine';
+  use strict;
+  use IkiWiki 2.00;
+  
+***************
+*** 289,294 ****
+--- 290,319 ----
+        }
+  }
+  
++ sub IkiWiki::pagetitle ($;$) {
++       my $page=shift;
++       my $unescaped=shift;
++ 
++       if ($page =~ m#/#) {
++               $page =~ s#^/##;
++               $page =~ s#/index$##;
++               if ($pagestate{"$page/index"}{meta}{title}) {
++                       $page = $pagestate{"$page/index"}{meta}{title};
++               } else {
++                       $page = IkiWiki::basename($page);
++               }
++       }
++ 
++       if ($unescaped) {
++               $page=~s/(__(\d+)__|_)/$1 eq '_' ? ' ' : chr($2)/eg;
++       }
++       else {
++               $page=~s/(__(\d+)__|_)/$1 eq '_' ? ' ' : "&#$2;"/eg;
++       }
++ 
++       return $page;
++ }
++ 
+  package IkiWiki::PageSpec;
+  
+  sub match_title ($$;@) {
+
+</pre>
+
+----
+
+> A few quick notes about it:
+
+> - Using <code>inline</code> would avoid the redefinition + code duplication.
+> - A few plugins would need to be upgraded.
+> - It may be necessary to adapt the testsuite in `t/pagetitle.t`, as well.
+>
+> --[[intrigeri]]
+>
+>> It was actually more complicated than expected. A working prototype is
+>> now in my `meta` branch, see my userpage for the up-to-date url.
+>> Thus tagging patch. --[[intrigeri]]
+>>
+>>> Joey, please consider merging my `meta` branch. --[[intrigeri]]
+
+So, looking at your meta branch: --[[Joey]] 
+
+* Inter-page dependencies. If page A links to page B, and page B currently
+  has no title, then A will display the link as "B". Now page B is modified
+  and a title is added. Nothing updates "A".
+  The added overhead of rebuilding every page that links to B when B is
+  changed (as the `postscan` hook of the po plugin does) is IMHO a killer.
+  That could be hundreds or thousands of pages, making interactive editing
+  way slow. This is probably the main reason I had not attempted this whole
+  thing myself. IMHO this calls for some kind of intellegent dependency
+  handler that can detect when B's title has changed and only rebuild pages
+  that link to B in that case.
+* Looks like some plugins that use `pagetitle` to format it for display
+  were not changed to use `nicepagetitle` (for example, rename).
+  But most of those callers intend to display the page name
+  as a title, but including the parent directories in the path. (Ie,
+  "renaming foo/page title to bar/page title" -- 
+  you want to know it's moved from foo to bar.) `nicepagetitle` does not
+  allow doing that since it always takes the `basename`.
+* I don't like the name `nicepagetitle`. It's not very descriptive, is it?
+  And it seems very confusing to choose whether to use the "nice" or original
+  version. My hope is that adding a second function is unnecessary.
+  As I understand it, you added a new function for two reasons: 
+  1) It needs the full page name, not basename.
+  2) `titlepage(pagetitle($page))` reversability.
+  
+  1) If you look at all the callers
+  Of `pagetitle` most of them pass a complete page name, not just the
+  basename. In most cases `pagetitle` is used to display the full name
+  of the page, including any subdirectory it's in. So why not just make
+  it consitently be given the full name of the page, with another argument
+  specifying if we want to get back just the base name.
+
+  2) I can't find any code that actually uses the reversability like that.
+  The value passed to `titlepage` always comes from some external
+  source. Unless I missed one.
+* The use of `File::Spec->rel2abs` is a bit scary.
+* Does it really make sense to call `pagetitle` on the meta title
+  in meta's `nicepagetitle`? What if the meta title is something like
+  "foo_bar" -- that would be changed to "foo bar".
+* parentlinks is changed to use `nicepagetitle(bestlink($page, $path))`.
+  Won't `bestlink` return "" if the parent page in question does not exist?
+* `backlinks()` is changed to add an additional `title` field
+  to the hash returned, but AFAICS this is not used in the template.
+* Shouldn't `Render.pm` use nicepagetitle when getting the title for the
+  page template? Then meta would not need to override the title in the
+  `pagetemplate` hook. (Although this would eliminate handling of
+  `title_overridden` -- but that is little used and would not catch
+  all the other ways titles can be overridden with this patch anyway.)
+
+> I'm not a reviewer or anything, but can I chime in on changes to pagetitle?
+> I don't think having meta-titles in wikilinks and the parentlinks path by
+> default is necessarily a good thing. I don't consider the meta-title of a page
+> as used in `<title>` to be the same thing as the short title you
+> want in those contexts - IMO, the meta-title is the "formal" title of the page,
+> enough to identify it with no other context, and frequently too long to be used
+> as a link title or a parentlink, whereas the parentlinks title in particular
+> should be some abbreviated form that's enough to identify it in context.
+> [tbm](http://www.cyrius.com/) expressed a similar opinion when I was discussing
+> ikiwiki with him at the weekend.
+>
+> It's a matter of taste whether wikilinks are "like a parentlink" or "like a
+> `<title>`"; I could be persuaded either way on that one.
+>
+> An example from my site: [this page](http://www.pseudorandom.co.uk/2004/debian/ipsec/)
+> is the parent of [this page](http://www.pseudorandom.co.uk/2004/debian/ipsec/wifi/)
+> with a title too long to use in the latter's parentlinks; I think the titles of
+> both those pages are too long to use as wikilink text too. Similarly, tbm's page
+> about [Debian on Orion devices from Buffalo](http://www.cyrius.com/debian/orion/buffalo/)
+> can simply be called "Buffalo" in context.
+>
+> Having a `\[[!meta abbrev="..."]]` that took precedence over title
+> in parentlinks and possibly wikilinks might be a good way to fix this? Or if your
+> preference goes the other way, perhaps a `\[[!meta longtitle=""]]` could take
+> precedence when generating the `<title>` and the title that comes after the
+> parentlinks. --[[smcv]]
+
+>> I think you've convinced me. (I had always had some doubt in my mind as
+>> to whether using titles in all these other places would make sense.)
+>> 
+>> Instead of meta abbrev, you could have a meta pagename that
+>> overrides the page name displayed everywhere (in turn overridden by
+>> meta title iff the page's title is being displayed). But is this complexity
+>> needed? We have meta redir, so if you want to change the name of a page,
+>> you can just rename it, and put in a stub redirection page so links
+>> still work.
+>> 
+>> This leaves the [[plugins/contrib/po]] plugin, which really does need
+>> a way to change the displayed page name everywhere, and at least a
+>> subset of the changes in the meta branch are needed to support that.
+>> 
+>> (This would also get around my concern about inter-page dependency
+>> handling, since po contains a workaround for that, and it's probably
+>> acceptable to use potentially slow methods to handle this case.)
+>> --[[Joey]] 
+
+>>> I'm glad to implement whatever decision we'll make, but I don't
+>>> clearly understand what this discussion's conclusion is. It seems
+>>> like we agree at least on one point: meta page titles shall not be
+>>> displayed all over the place by default; I have therefore disabled
+>>> `meta_overrides_page_title` by default in my `meta` branch.
+>>> 
+>>> My next question is then: do we only want to satisfy the `po`
+>>> plugin needs? Or do we want to allow people who want this, such as
+>>> [[madduck]], to turn on a config switch so that meta page titles
+>>> are displayed as wikilinks titles? In the latter case, what level
+>>> of configurability do we want? I can think of a quite inelegant
+>>> way to implement full configurability, and provide a configuration
+>>> switch for every place where links are displayed, such as
+>>> wikilinks, parentlinks, etc., but I don't think the added bonus is
+>>> worth the complexity of it.
+>>> 
+>>> I think we can roughly split the needs into three categories:
+>>> 
+>>> 1. never display any modified page title in links; this is the
+>>>    current behaviour, and we should keep it as the default one
+>>> 2. display modified page titles only at well chosen places; that
+>>>    could be "manual" wikilinks, I mean those generated by the
+>>>    `link`, `camelcase` & al. plugins, the recentchanges page, and
+>>>    maybe a few other places; keep the usual pagename-based title
+>>>    for every other link, such as the parentlinks ones.
+>>>    The inter-page dependency problem remains, though. As a first
+>>>    step, I'm in favour of the "slow, but correct" implementation,
+>>>    with a big warning stating that enabling this option can make
+>>>    a wiki really sluggish; if someone really wants this to work
+>>>    fast, he/she'll implement a clever dependency handler :)
+>>> 3. display modified page titles all over the place; IMHO, we
+>>>    should implement only the bits needed so that the `po` plugin
+>>>    can set this up, rather than provide this as
+>>>    a user-configurable option.
+>>> 
+>>> So my question is: do we want to implement the #2 case, or not?
+>>> I propose myself to only implement #1 and #3 to start with, but do
+>>> it in a way that leaves room for #2.
+>>> 
+>>> --[[intrigeri]]
+>>>
+>>>> I agree, we should concentrate on getting just enough functionality
+>>>> for the po plugin, because I want to merge the po plugin soon.
+>>>> If #2 gets tackled later, we will certianly have all kinds of fun.
+>>>> no matter what is done for the po plugin. --[[Joey]] 
diff --git a/doc/bugs/pipe-symbol_in_taglink_target.mdwn b/doc/bugs/pipe-symbol_in_taglink_target.mdwn
new file mode 100644 (file)
index 0000000..e467959
--- /dev/null
@@ -0,0 +1,25 @@
+[[!tag bugs wishlist]]
+
+Escaping pipe-symbol in [[taglink|ikwiki/directive/taglink]] targets doesn't work as I wanted:
+
+[[!taglink smth_with_a_pipe|about_the_\|-symbol]]
+[[!taglink smth_with_a_pipe|about_the_|-symbol]]
+
+as opposed to simple wikilinks:
+
+[[a link to smth with a pipe|about the \|-symbol]]
+[[a link to smth with a pipe|about the |-symbol]]
+
+And it seems to work in pagespecs:
+
+tagged:
+
+[[!map pages="tagged(about the |-symbol)"]]
+
+[[!map pages="tagged(about the \|-symbol)"]]
+
+link:
+
+[[!map pages="link(about the |-symbol)"]]
+
+[[!map pages="link(about the \|-symbol)"]]
index d9c080a65180947a103d93069c3a65c526b8b81f..12d5e1597394322ee6d2d3f1a5de07af57b03a2a 100644 (file)
@@ -10,7 +10,7 @@ Seems tables are disabled here ?
 
 See this example:
 
-[[table class=table1 data="""
+[[!table class=table1 data="""
 aaaaaaaaaaaaaaa|b|c
 --\|\|--|e|f
 """]]
diff --git a/doc/bugs/po_plugin_adds_new_dependency.mdwn b/doc/bugs/po_plugin_adds_new_dependency.mdwn
new file mode 100644 (file)
index 0000000..3ddcc30
--- /dev/null
@@ -0,0 +1,38 @@
+Was it intended that the po plugin add a new dependency?
+
+> Yes; see debian/control Build-Depends. However, I have made it disable
+> building that is po4a is not available. [[done]] --[[Joey]] 
+
+    PERL5LIB=.. ./po2wiki underlay.setup
+    Failed to load plugin IkiWiki::Plugin::po: Can't locate Locale/Po4a/Common.pm in @INC (@INC contains: .. /Library/Perl/Updates/5.8.8 /System/Library/Perl/5.8.8/darwin-thread-multi-2level /System/Library/Perl/5.8.8 /Library/Perl/5.8.8/darwin-thread-multi-2level /Library/Perl/5.8.8 /Library/Perl /Network/Library/Perl/5.8.8/darwin-thread-multi-2level /Network/Library/Perl/5.8.8 /Network/Library/Perl /System/Library/Perl/Extras/5.8.8/darwin-thread-multi-2level /System/Library/Perl/Extras/5.8.8 /Library/Perl/5.8.6 /Library/Perl/5.8.1 /sw/lib/perl5/5.8.8/darwin-thread-multi-2level /sw/lib/perl5/5.8.8 /sw/lib/perl5/darwin-thread-multi-2level /sw/lib/perl5 /sw/lib/perl5/darwin /usr/local/lib/perl5/site_perl/5.8.8/darwin-thread-multi-2level /usr/local/lib/perl5/site_perl/5.8.8 /usr/local/lib/perl5/site_perl .) at ../IkiWiki/Plugin/po.pm line 13.
+    BEGIN failed--compilation aborted at ../IkiWiki/Plugin/po.pm line 13.
+    Compilation failed in require at (eval 27) line 2.
+    BEGIN failed--compilation aborted at (eval 27) line 2.
+    
+    make[1]: *** [po2wiki_stamp] Error 2
+    make: *** [extra_build] Error 2
+
+And it looks like this dependency is not easy to work around.  The issue is that the newly translated base wiki means that the po plugin is being used by the build system.  It is no longer optional.  I've turned it off in my workspace like this: (heavy handed, but it lets me keep going until a proper fix is available)
+
+    diff --git a/Makefile.PL b/Makefile.PL
+    index 602d8fb..68728b7 100755
+    --- a/Makefile.PL
+    +++ b/Makefile.PL
+    @@ -42,7 +42,7 @@ extra_build: ikiwiki.out ikiwiki.setup docwiki
+       ./mdwn2man ikiwiki-makerepo 1 doc/ikiwiki-makerepo.mdwn > ikiwiki-makerepo.man
+       ./mdwn2man ikiwiki-transition 1 doc/ikiwiki-transition.mdwn > ikiwiki-transition.man
+       ./mdwn2man ikiwiki-update-wikilist 1 doc/ikiwiki-update-wikilist.mdwn > ikiwiki-update-wikilist.man
+    -  $(MAKE) -C po
+    +  # $(MAKE) -C po
+       
+     docwiki: ikiwiki.out
+       $(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -setup docwiki.setup -refresh
+    @@ -114,7 +114,7 @@ extra_install: underlay_install
+       install ikiwiki.out $(DESTDIR)$(PREFIX)/bin/ikiwiki
+       install ikiwiki-makerepo ikiwiki-transition ikiwiki-update-wikilist $(DESTDIR)$(PREFIX)/bin/
+     
+    -  $(MAKE) -C po install DESTDIR=$(DESTDIR) PREFIX=$(PREFIX)
+    +  # $(MAKE) -C po install DESTDIR=$(DESTDIR) PREFIX=$(PREFIX)
+       
+       # These might fail if a regular user is installing into a home
+       # directory.
diff --git a/doc/bugs/po_plugin_cannot_add_po_files_into_git.mdwn b/doc/bugs/po_plugin_cannot_add_po_files_into_git.mdwn
new file mode 100644 (file)
index 0000000..8e33996
--- /dev/null
@@ -0,0 +1,34 @@
+po files are not added to git (error: /path/to/po/file not in repository tree) in my setup.
+
+I have set absolute path for srcdir = '/path/to/repo/doc/'. The root of my git repository is '/path/to/repo/'. When I enable the po plugin, it creates all po files and produces an error when it try to add the file saying that the /path/to/repo/doc/index.fr.po is not in the repository tree.
+
+I have no problem when I use an relative path like srcdir = '.'.
+
+I have an other issue with the po plugin when I set the srcdir to './doc/' (provided that my config file is in /path/to/repo). In this case the po plugin try to add 'doc/doc/index.fr.po' which does not exists (seems like the srcdir path is prepended twice).
+
+> You should never use a relative srcdir path with ikiwiki.
+> 
+> I wonder what version of git you have there, since it works ok with the
+> version I have here. But, the po plugin is definitly doing the wrong
+> thing; it's telling git to add the po file with the full scrdir path
+> rather than relative to its root. Fixed that. [[done]] --[[Joey]] 
+
+>> Yeah, I figured for the relative path
+>> Git version 1.6.3.3 (on both my dev and server machines)
+>>
+>> Here is an example of what I get when I update the po file on my laptop and I push to the master repository:
+
+     From /srv/git/sb
+       5eb4619..ecac4d7  master     -> origin/master
+    scanning doc.fr.po
+    building doc.fr.po
+    building doc.mdwn, which depends on doc.fr
+    building recentchanges.mdwn, which depends on recentchanges/change_ecac4d7311b15a3a3ed03102b9250487315740bc
+    fatal: '/srv/www/sb.l.n/new/doc/doc.fr.po' is outside repository
+    'git add /srv/www/sb.l.n/new/doc/doc.fr.po' failed:  at /usr/share/perl5/IkiWiki/Plugin/git.pm line 161.
+    done
+    To ssh://git.lohrun.net/var/cache/git/songbook.git
+       5eb4619..ecac4d7  master -> master
+  
+>> The root repository used to run ikiwiki is `/srv/www/sb.l.n/new/` 
+>> -- [[AlexandreDupas]]
diff --git a/doc/bugs/post-commit_hangs.mdwn b/doc/bugs/post-commit_hangs.mdwn
new file mode 100644 (file)
index 0000000..32820d8
--- /dev/null
@@ -0,0 +1,47 @@
+# post-commit hangs
+
+I installed ikiwiki v3.14159 in /usr/local from tarball (/usr contains an older version). Having done so, and used ikiwiki-transition to update setup file, the post commit hook is now blocking in flock (as seen by ps). I should also mention that I added the goodstuff, attachment and remove plugins (which was the purpose of upgrading to v3). Any clues as how to debug/fix gratefully received. The wiki is publically viewable at wiki.sgcm.org.uk if that helps.
+
+> It's blocking when you do what? Save a page from the web? Make a commit
+> to the underlaying VCS? Which VCS? These are all different code paths..
+> --[[Joey]] 
+
+>> It's blocking when I run "ikiwiki --setup ikiwiki.setup" (which calls hg update, which calls ikiwiki --post-commit).
+>> Hmm, maybe it's the recursive call to ikiwiki which is the problem.
+>> The underlying VCS is mercurial. --Ali
+
+>>> You're not supposed to run ikiwiki -setup manually in your post commit hook.
+>>> Doing so will certianly lead to a locking problem; it also forces ikiwiki to rebuild
+>>> the entire wiki anytime a single page changes, which is very inefficient!
+>>>
+>>> Instead, you should use the `mercurial_wrapper` setting
+>>> in the setup file, which will make ikiwiki generate a small
+>>> executable expressly designed to be run at post commit time.
+>>> Or, you can use the `--post-commit` option, as documented
+>>> in [[rcs/mecurial]] --[[Joey]] 
+
+>>>> I don't run ikiwiki --setup in the commit hook; I run ikiwiki --post-commit (as mentioned above).
+>>>> I'm trying to run ikiwiki --setup from the command line after modifying the setup file.
+>>>> ikiwiki --setup is calling hg update, which is calling ikiwiki --post-commit. Am I not supposed to do that? --Ali
+
+>>>>> No, I don't think that hg update should call ikiwiki anything. The
+>>>>> [[hgrc_example|rcs/mercurial]] doesn't seem to configure it to do that? --[[Joey]] 
+
+>>>>>> Ok, I'm not sure I understand what's going on, but my problem is solved.
+>>>>>>
+>>>>>> My hgrc used to say:
+>>>>>>
+>>>>>> [hooks]
+>>>>>>
+>>>>>> incoming.update = hg up
+>>>>>>
+>>>>>> update.ikiwiki = ikiwiki --setup /home/ikiwiki/ikiwiki.setup --post-commit
+>>>>>>
+>>>>>> I've now changed it to match the example page and it works. Thanks --Ali.
+
+>>>>>>> [[done]]
+
+> Also, how have you arranged to keep it from seeing the installation in /usr? Perl could well be loading
+> modules from the old installation, and if it's one with a different locking strategy that would explain your problem. --[[Joey]] 
+
+>> Good point. Not knowing perl, I just assumed /usr/local would take precedence. I've now used "dpkg -r ikiwiki" to remove the problem. --Ali
diff --git a/doc/bugs/prettydate_with_weekday-date_inconsistency.mdwn b/doc/bugs/prettydate_with_weekday-date_inconsistency.mdwn
new file mode 100644 (file)
index 0000000..430d65a
--- /dev/null
@@ -0,0 +1,32 @@
+Prettydate creates strings like this: _Last edited in the wee hours of Tuesday night, July 1st, 2009_. However, July 1st is a Wednesday, so either date or Weekday should be modified. In the spirit is probably _Tuesday night, June 30th_. --ulrik
+
+> The default prettydate times are fairly idiosyncratic to
+> how [[Joey]] thinks about time. Specifically, it's still
+> Tuesday night until he wakes up Wednesday morning -- which
+> could be in the afternoon. :-P But, Joey also realizes
+> that dates change despite his weird time sense, and so
+> July 1st starts at midnight on Tuesday and continues
+> through Tuesday night and part of Wednesday.
+> 
+> (This might not be as idiosyncratic as I make it out to be..
+> I think that many people would agree that in the wee hours
+> of New Years Eve, when they're staggering home ahead of
+> the burning daylight, the date is already January 1st.)
+> 
+> I think the bug here is that prettydate can't represent
+> all views of time. While the times
+> of day can be configured, and it's possible to configure it
+> to call times after midnight "Wednesday morning, July 1st",
+> it is not possible to configure the date or weekday based
+> on the time of day.
+> 
+> In order to do so, prettydate's timetable would need to be
+> extended to include the "%B %o, %Y" part, and that extended
+> to include "%B-", "%o-", and "%Y-" to refer to the day
+> before.
+> 
+> --[[Joey]]
+
+>> fair enough, I think I can get converted to a warped time perspective. --ulrik
+
+>>> Perhaps we can consider this [[done]], then? --[[smcv]]
diff --git a/doc/bugs/previewing_new_page_can_leave_files_dangling.mdwn b/doc/bugs/previewing_new_page_can_leave_files_dangling.mdwn
new file mode 100644 (file)
index 0000000..22df485
--- /dev/null
@@ -0,0 +1,53 @@
+Steps to reproduce:
+
+1. Make a new post via web interface.
+2. Use a directive that generates extra files (say, teximg).
+3. Click cancel.
+
+What I expect:
+
+The files that teximg created should (eventually) be removed, along with the whole directory of the non-existant new post.
+
+What I got:
+
+I refresh and rebuild a few times, and the files are still dangling there.  If I then try to create a post with the same name and same content, I get a "file independently created, not overwriting" error.
+
+> This is specific to previewing when creating a new page. If the page
+> previously existed, the next update to the page will remove the stale
+> preview files.
+> 
+> Problem is that ikiwiki doesn't store state about files rendered by a
+> page if the page doesn't exist yet.
+> 
+> However, just storing that state wouldn't entirely solve the problem,
+> since it would still not delete the leftovers until the page is updated,
+> which it never is if it's previewed and then canceled. And requiring the
+> cancel button be hit doesn't solve this, because people won't.
+> 
+> Also, it's not really ideal that an existing page has to be updated to
+> remove stale files, because if the edit is aborted, the page might not be
+> updated for a long time.
+> 
+> One fix would be to stash a copy of `%renderedfiles` before generating
+> the preview, then compare it afterwards to see how it changed and
+> determine what files were added, and record those someplace, and delete
+> them on a future refresh (after some reasonable time period). [[done]]
+> 
+> Another approach would be to make previewing always render files with
+> some well-known temporary name. Then all such temp files could be removed
+> periodically. This would need changes to all plugins that write files
+> during preview though. For example, `will_render` might be changed to
+> return the actual filename to write to. --[[Joey]]
+
+For teximg, I think this can be fixed by using data url like graphviz, but
+I think plugins in general should be allowed to create files during preview
+and have them be cleaned up when the user presses cancel.  This segues into
+what my actual problem is: I wrote a htmlize plugin to format .tex files as
+page images (following hnb and teximg, since I was completely unfamiliar
+with perl until yesterday (and ikiwiki until a few days ago)), and there is
+no way to tell if I'm in preview mode (so I can use data url and not leave
+files dangling) or commit mode (so I can use real images and not have
+bloated html).
+
+> It seems too ugly to thread an indicator to preview mode through to
+> htmlize, so I'd prefer to not deal with the problem that way.
diff --git a/doc/bugs/previewing_with_an_edittemplate_reverts_edit_box.mdwn b/doc/bugs/previewing_with_an_edittemplate_reverts_edit_box.mdwn
new file mode 100644 (file)
index 0000000..4405a7a
--- /dev/null
@@ -0,0 +1,5 @@
+The 'editcontent' textarea that should be saved across previews is being overridden whenever an edittemplate is in use, 'losing' edits on preview unless the browser maintains them in history.
+
+  --[[JoeRayhawk]]
+
+> ugly one... [[done]] --[[Joey]]
index e698cbed7e6035fbcb3833c352c25ce1dc27fbdb..5fc1d8b75d379ebc71c1f2b53d6452c225b1b1ab 100644 (file)
@@ -11,7 +11,7 @@ I've no idea what's happening (hey, I'm a C programmer), but I've hacked prune()
 <pre>
 use Scalar::Util qw(tainted);
 
-sub prune ($) { #{{{
+sub prune ($) {
         my $file=shift;
 
         unlink($file);
@@ -25,11 +25,11 @@ sub prune ($) { #{{{
                         $dir = $1;
                 }
         }
-} #}}}
+}
 </pre>
 
 > Old versions of perl are known to have bugs with taint checking.
 > I don't really support using ikiwiki with the perl 5.8.4 in debian
 > oldstable, and would recommend upgrading. --[[Joey]]
 
-[[tag patch done]]
+[[!tag patch done]]
index 26f833e5f4f3e8915dcd305c163c61dbe3d67a2a..3fd75ea1b9b86ef306c28792a85a541a36806f00 100644 (file)
@@ -6,7 +6,7 @@ messages which are then taken for CGI output, causing errors and general trouble
     @@ -55,7 +55,7 @@
      }
  
-     sub rcs_update () { #{{{
+     sub rcs_update () {
     -  my @cmdline = ("hg", "-R", "$config{srcdir}", "update");
     +  my @cmdline = ("hg", "-q", "-R", "$config{srcdir}", "update");
        if (system(@cmdline) != 0) {
@@ -22,7 +22,7 @@ messages which are then taken for CGI output, causing errors and general trouble
        if (system(@cmdline) != 0) {
                warn "'@cmdline' failed: $!";
     @@ -92,7 +92,7 @@
-     sub rcs_add ($) { # {{{
+     sub rcs_add ($) {
        my ($file) = @_;
      
     -  my @cmdline = ("hg", "-R", "$config{srcdir}", "add", "$file");
index 607326c97ca90fbfbfd216426daaabfc9978b89a..5860d330a916b32e97cc456b4c4ea4c051446530 100644 (file)
@@ -8,9 +8,9 @@ This should work, but html code (listing 1) shows up with a hash replaced for th
 
 I have to suspect that replacing html with some hash is a bug.
 
-> Congrats, you're another person to fall afoul of markdown [[debbug 380212]].
+> Congrats, you're another person to fall afoul of markdown [[!debbug 380212]].
 > The fix is to use Text::Markdown, or markdown 1.0.2 instead of buggy
-> old markdown 1.0.1. --[[Joey]] [[tag done]]
+> old markdown 1.0.1. --[[Joey]] [[!tag done]]
 
 ## inlining raw html
 
diff --git a/doc/bugs/recentchanges_escaping.mdwn b/doc/bugs/recentchanges_escaping.mdwn
new file mode 100644 (file)
index 0000000..1ad16d1
--- /dev/null
@@ -0,0 +1,5 @@
+When committing a page like this one, with an escaped toc directive in it:
+
+       \[[!toc ]]
+
+The recentchangesdiff comes back with it unescaped. Which can be confusing.
index eb543587c1b56537ce22fad843bc5a6bd9989828..ef0f9d1c427933e5a78e60ec257fe5b5aadadb07 100644 (file)
@@ -27,8 +27,81 @@ to turn on? --Chapman Flack
 >>> todo about [[todo/ability_to_force_particular_UUIDs_on_blog_posts]],
 >>> and then by just using that new ability in the page. --[[Joey]]
 
->>>> Ah. The prerequisite todo looks like more than I'd like to take on.
+>>>> <del title="Prerequisite done now?">Ah. The prerequisite todo looks like more than I'd like to take on.
 >>>> In the meantime, would it be very involved to change whatever bug now
 >>>> optimizes away the change pages, or to simply have all the links in the
 >>>> feed point to the recentchanges page itself, with no fragment id?
->>>> Either would be a bit nicer than having broken links in the feed. --Chap
+>>>> Either would be a bit nicer than having broken links in the feed. --Chap</del>
+
+>>>> Does the completion of that todo mean it would be straightforward to get
+>>>> recentchanges working now?  Is it just that the recentchanges plugin
+>>>> needs to generate `\[[!meta guid=something]]` into the internal files,
+>>>> and the inline plugin would then generate working links in feeds?  How should
+>>>> the guid be constructed? Something based on the rcs revision number?  I guess
+>>>> I'm still not completely clear on your vision for how it ought to work. --Chap
+
+>>>> My idea is to use `\[[meta guid="http://url/recentchanges#rev"]]`, with the
+>>>> `#rev` anchor also included in the change file, and being the rcs's
+>>>> internal revision id. Then the guid is globally unique, and actually
+>>>> links to the change in the recentchanges page. And, when the change
+>>>> has fallen off the page, the link will still go to the recentchanges page.
+>>>> 
+>>>> First, need to check that guids in rss and atom feeds can have anchors in
+>>>> them, and that the anchor is treated as part of the guid. (If the guid
+>>>> is interpreted as just "http://url/recentchanges", then it's
+>>>> not a very good guid.) If using an anchor for a guid is a problem,
+>>>> it could instead generate a random uuid, and use `\[[meta
+>>>> guid="urn:uuid:<foo>" permalink="http://url/recentchanges"]]`
+
+>>>>> I had a quick look into this after fixing the "prerequisite", but got
+>>>>> bogged down in minor details. Anyway, I'd be happy to help.
+>>>>> I think the guid stuff is actually fairly irrelevant, you just need
+>>>>> `\[[!meta permalink]]` (and in fact you're using guid incorrectly, by
+>>>>> expecting it to be treated as a link).
+>>>>>
+>>>>> My advice would be: first, fix the bug as reported, by
+>>>>> using `\[[!meta permalink="http://blah/blah/blah#change-$rev"]]` (starting
+>>>>> anchor names with a number isn't syntactically valid, if I remember
+>>>>> correctly, so do have a prefix like "change-" or "rev-" or something).
+>>>>>
+>>>>> Then, optionally, force the guid too (although it defaults to the permalink
+>>>>> anyway, so this shouldn't actually be necessary).
+>>>>>
+>>>>> Some more explanation of how guids work: it's actually easier to think
+>>>>> about them in Atom terms than in RSS terms, since Atom has a clearer
+>>>>> conceptual model.
+>>>>>
+>>>>> The `\[[!meta permalink]]` becomes the `<link>`
+>>>>> element in Atom, which contains a link that users can follow; if it's not
+>>>>> explicitly given, ikiwiki uses its idea of the page's URL.
+>>>>>
+>>>>> The `\[[!meta guid]]` becomes the `<id>` element in Atom, which contains an
+>>>>> opaque, not-necessarily-resolvable identifier; if it's
+>>>>> not explicitly given, ikiwiki uses the same URL as the `<link>`.
+>>>>>
+>>>>> In RSS the semantics aren't so clear-cut (which is part of why Atom exists!),
+>>>>> but the way ikiwiki interprets them is:
+>>>>>
+>>>>> * `<link>` is the same as in Atom
+>>>>> * if `\[[!meta guid]]` is explicitly given, put it in `<guid permalink="no">`
+>>>>>   (the assumption in this case is that it's a UUID or something)
+>>>>> * if `\[[!meta guid]]` is not explicitly given, copy the `<link>` into the `<guid>`
+>>>>>
+>>>>> I believe RSS aggregators (are meant to) compare `<guid>`s as opaque
+>>>>> strings, so using an anchor there should be fine. Atom aggregators are certainly
+>>>>> required to compare `<id>`s as opaque strings.
+>>>>>
+>>>>> --[[smcv]]
+
+>>>>>> Here's my attempt at a [[patch]] for anchor-based change permalinks:
+>>>>>> <http://pastie.org/295016>.
+>>>>>> --[[JasonBlevins]], 2008-10-17
+
+[[JasonBlevins]] nailed it, [[done]] --[[Joey]]
+
+> Thanks for applying the patch (and improving it).  There's still one small issue:
+> the old opening div tag still needs to be removed (it's hard to see the removed line
+> with the pastie color scheme).
+> --[[JasonBlevins]], 2008-10-18
+
+>> Thanks, missed that when I had to hand-apply the patch. --[[Joey]]
index f646143d3ffe332da9738ceb5536df66811b55ef..b3578f26ab107d919487631b14e2e93531a9285a 100644 (file)
@@ -40,7 +40,7 @@ The tarball is at http://scratch.madduck.net/__tmp__recentchanges-segfault.tgz -
 > I only see it with 1.0.1. (Bad news: Newer versions of markdown are
 > slooooooow, especially on such large files.)
 
-> I'm calling this [[done]] since I've filed [[debbug 470676]] on perl, and
+> I'm calling this [[done]] since I've filed [[!debbug 470676]] on perl, and
 > also have modified recentchangesdiff to only show the first 200 lines of
 > diff, which should be enough without bloating the recentchanges into
 > perl-crashing territory. --[[Joey]]
diff --git a/doc/bugs/relative_date_weird_results.mdwn b/doc/bugs/relative_date_weird_results.mdwn
new file mode 100644 (file)
index 0000000..9f35e47
--- /dev/null
@@ -0,0 +1,4 @@
+I just submitted a new bug, and... after clicking "save", my brand new bug page displays, at the bottom: "Last edited 6 hours and 3 minutes ago". Timezone issue, I guess? (Hint: I'm in France) -- [[intrigeri]]
+
+> Yep, it wasn't including a timezone in the machine parseable time.
+> [[done]] --[[Joey]]
diff --git a/doc/bugs/relative_links.mdwn b/doc/bugs/relative_links.mdwn
deleted file mode 100644 (file)
index a1dc8f3..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-It looks like all links in websites are absolute paths, this has some limitations:
-
-* If connecting to website via https://... all links will take you back to http://
-* Makes it harder to mirror website via HTML version, as all links have to be updated.
-
-It would be good if relative paths could be used instead, so the transport method isn't changed unless specifically requested.
-
--- Brian May
-
-> Er, which absolute links are you talking about? If you view the source
-> to this page, you'll find links such as "../favicon.ico", "../style.css",
-> "../../", and "../". The only absolute links are to CGIs and the w3c DTD.
-> --[[Joey]]
-
->> The problem is within the CGI script. The links within the HTML page are all absolute, including links to the css file.
->> Having a http links within a HTML page retrieved using https upset most browsers (I think). Also if I push cancel on the edit page in https, I end up at at http page. -- Brian May
-
->>> Ikiwiki does not hardcode http links anywhere. If you don't want
->>> it to use such links, change your configuration to use https
->>> consistently. --[[Joey]]
-
-Errr... That is not a solution, that is a work around. ikiwiki does not hard code the absolute paths, but absolute paths are hard coded in the configuration file. If you want to serve your website so that the majority of users can see it as http, including in rss feeds (this allows proxy caches to cache the contents and has reduced load requirements), but editing is done via https for increased security, it is not possible. I have some ideas how this can be implemented (as ikiwiki has the absolute path to the CGI script and the absolute path to the destination, it should be possible to generate a relative path from one to the other), although some minor issues still need to be resolved. -- Brian May
-
-I noticed the links to the images on <http://ikiwiki.info/recentchanges/> are also absolute, that is <http://ikiwiki.info/wikiicons/diff.png>; this seems surprising, as the change.tmpl file uses &lt;TMPL_VAR BASEURL&gt;
-which seems to do the right thing in page.tmpl, but not for change.tmpl. Where is BASEURL set? -- Brian May
-
-> The use of an absolute baseurl in change.tmpl is a special case. --[[Joey]]
diff --git a/doc/bugs/remove_orphaned_sparkline-php_from_Suggests.mdwn b/doc/bugs/remove_orphaned_sparkline-php_from_Suggests.mdwn
new file mode 100644 (file)
index 0000000..b4e2a15
--- /dev/null
@@ -0,0 +1,20 @@
+Hi!
+
+How about to replace sparkline-php from Suggests by a better alternative?
+
+I would like to file a RM bug to get it out of archive. Do you have a better alternative for it? PHP has a lot of them..
+
+Thanks
+
+> sparline-php is orphaned *in Debian*. Upstream, is has seen activity as
+> recently as 11 months ago.
+>
+> I don't know of a better alternative. I looked at the perl sparkline
+> stuff in CPAN and is was bad enough that the pain of using php from this
+> perl program was a better alternative.
+> 
+> Anyway, it works great; maintaining the sparkline-php package in Debian
+> would certianly be much less work than finding some alternative and
+> rewriting the ikiwiki code to use it, *and* packaging that alternative
+> and maintaining it in Debian. So your suggestion doesn't make a lot of
+> sense; Debian should just find a maintainer for sparkline-php. --[[Joey]]
diff --git a/doc/bugs/remove_plugin_and_untracked_files.mdwn b/doc/bugs/remove_plugin_and_untracked_files.mdwn
new file mode 100644 (file)
index 0000000..07408c3
--- /dev/null
@@ -0,0 +1,6 @@
+The [[plugins/remove]] plugin does not report an error if git rm fails. (It
+probably doesn't if other VCS backends fail too). This can happen for example
+if a page in your source directory is not a tracked file for whatever reason
+(in my case, due to renaming the files and forgetting to commit that change).
+
+ -- [[Jon]]
diff --git a/doc/bugs/rss_feeds_do_not_use_recommended_encoding_of_entities_for_some_fields.mdwn b/doc/bugs/rss_feeds_do_not_use_recommended_encoding_of_entities_for_some_fields.mdwn
new file mode 100644 (file)
index 0000000..48c1689
--- /dev/null
@@ -0,0 +1,36 @@
+The Atom and RSS templates use `ESCAPE=HTML` in the title elements. However, HTML-escaped characters aren't valid according to <http://feedvalidator.org/>.
+
+Removing `ESCAPE=HTML` works fine, but I haven't checked to see if there are any characters it won't work for.
+
+For Atom, at least, I believe adding `type="xhtml"` to the title element will work. I don't think there's an equivalent for RSS.
+
+> Removing the ESCAPE=HTML will not work, feed validator hates that just as
+> much. It wants rss feeds to use a specific style of escaping that happens
+> to work in some large percentage of all rss consumers. (Most of which are
+> broken).
+> <http://www.rssboard.org/rss-profile#data-types-characterdata>
+> There's also no actual spec about how this should work.
+> 
+> This will be a total beast to fix. The current design is very clean in
+> that all (well, nearly all) xml/html escaping is pushed back to the
+> templates. This allows plugins to substitute fields in the templates
+> without worrying about getting escaping right in the plugins -- and a
+> plugin doesn't even know what kind of template is being filled out when
+> it changes a field's value, so it can't do different types of escaping
+> for different templates.
+>
+> The only reasonable approach seems to be extending HTML::Template with an
+> ESCAPE=RSS and using that. Unfortunately its design does not allow doing
+> so without hacking its code in several places. I've contacted its author
+> to see if he'd accept such a patch.
+>
+> (A secondary bug is that using meta title currently results in unnecessry
+> escaping of the title value before it reaches the template. This makes
+> the escaping issues show up much more than they need to, since lots more
+> characters are currently being double-escaped in the rss.)
+> 
+> --[[Joey]]
+
+> Update: Ok, I've fixed this for titles, as a special case, but the
+> underlying problem remains for other fields in rss feeds (such as
+> author), so I'm leaving this bug report open. --[[Joey]]
index facc4fba55a1108a1c0f8e07e58148589c21abdc..dab3b7e5bf58059947e433fcb5e5594ed5a3e3e1 100644 (file)
@@ -21,8 +21,6 @@ throwing code..):
 
         @staticmethod
 
-[[tag patch]]
-
 > No, still the same failure. I think it's failing parsing the input data,
 > (which perl probably transmitted as an int due to perl internals)
 > not writing out its response. --[[Joey]]
index 5121f037926d0bcd31395a7c2569126a9724268a..b0f417209b77bc48ecd52d1c8e757e6c22163c57 100644 (file)
@@ -17,4 +17,4 @@ markdown plugin also has no problems rendering the same file, so I'm guessing
 it's a problem with the XML-RPC interface.
 
 Sorry for the delay, this is now fixed! --[[Joey]]
-[[tag done]]
+[[!tag done]]
index 8348ed470c5df2be00d163564ef08271a5ece665..9d433e24e1a41b82a60c4b3bdae709dca66f5b25 100644 (file)
@@ -20,3 +20,24 @@ Index: IkiWiki/Plugin/rst.pm
  print html[html.find('<body>')+6:html.find('</body>')].strip();
  ";
 </pre>
+
+----
+
+Does the Perl version of this plugin still exist?  There appears to be no "rst.pm" in the current distribution; all there is is the python version. --Peter
+
+> No, only the python version exists. It does have `raw_enabled` set.
+> --[[Joey]]
+
+I am sorry, but I am confused. Does this mean that I can use Ikiwiki
+features that translate to HTML in rst files? For example, when I use a
+\[[pagename]]-style link in a rst file, the page generated by Ikiwiki's rst
+plugin says &lt;a href="./../pagename/">pagename&lt;/a> as text. The link
+is expanded correctly, but the result isn't interpreted as HTML. Is that
+what is supposed to happen? --Peter
+
+> `raw_enabled` allows you to use the
+> [raw directive](http://docutils.sourceforge.net/docs/ref/rst/directives.html),
+> but this is not used by ikiwiki for wikilinks or anything else. 
+> That's why the [[plugin_page|plugins/rst]] has its note about 
+> issues with wikilinks and directives. You'd have to put those inside
+> raw directives yourself to avoid rst escaping their result. --[[Joey]]
diff --git a/doc/bugs/search:___34__link__34___and___34__title__34___fields_are_incorrectly_specified.mdwn b/doc/bugs/search:___34__link__34___and___34__title__34___fields_are_incorrectly_specified.mdwn
new file mode 100644 (file)
index 0000000..c088d1e
--- /dev/null
@@ -0,0 +1,29 @@
+Currently, ikiwiki indexes the "title" and "link" fields of a page
+using the prefix "Z".
+This is incorrect.
+"Z" is for stemmed terms,
+which xapian inserts itself.
+Furthermore, the custom field "LINK" should use the "X" prefix.
+(This is according to the [xapian-omega documentation] [xapian].)
+
+I have a [patch][] that fixes this.
+Once it is applied,
+the wiki should be rebuilt to fix the search index.
+
+What problems does the current behaviour cause?
+Consider the [[tags]] page.
+ikiwiki indexes the term "ZStags" for its title.
+xapian stems this and also indexes "ZZStag".
+(Notice the additional "Z".)
+Now when [searching for "title:tags"] [search],
+xapian stems this and searches for "ZStag",
+and so only finds pages which were indexed by _ikiwiki_ with "ZStag"
+(i.e. those pages with the singular "tag" in the title).
+
+--Gabriel.
+
+[xapian]: http://xapian.org/docs/omega/termprefixes.html
+ [patch]: http://www.gmcmanus.org/0001-Use-correct-term-prefixes-when-searching.patch
+[search]: http://ikiwiki.info/ikiwiki.cgi?P=title%3Atags
+
+[[!tag done]]
index a7fab55713a5766ca6ea9ad1f0b4f35b25d56fce..08af5fe2caa7a1ff5f3b87fa10e08574ff2b030b 100644 (file)
@@ -2,7 +2,7 @@ It seems like gettext only searches for locale information in /usr/share/locale,
 
     --- a/IkiWiki.pm
     +++ b/IkiWiki.pm
-    @@ -1057,6 +1057,7 @@ sub gettext { #{{{
+    @@ -1057,6 +1057,7 @@ sub gettext {
                                     $gettext_obj=undef;
                                     return shift;
                             }
@@ -11,7 +11,7 @@ It seems like gettext only searches for locale information in /usr/share/locale,
                     return $gettext_obj->get(shift);
             }
 
-[[tag patch]]
+[[!tag patch patch/core]]
 -- [[ThomasBleher]]
 
 > According to my testing, this patch makes ikiwiki's localisation fail for
diff --git a/doc/bugs/search_plugin_and_CGI_preview.mdwn b/doc/bugs/search_plugin_and_CGI_preview.mdwn
new file mode 100644 (file)
index 0000000..2a3d270
--- /dev/null
@@ -0,0 +1,19 @@
+Text on a page gets indexed when you preview.
+
+I discovered this by using (perhaps this is weird) the Sandbox to
+preview my markup in a file that I was preparing to check in through svn.
+I just deleted the original Sandbox text in the edit form, pasted in my
+file, hit Preview, then cancelled the edit, leaving the Sandbox unchanged.
+
+After that, the Sandbox was one of the search hits for terms in the new
+page, and the Sandbox excerpt in the search results showed text taken
+from the new page, that was never really in the Sandbox page at all.
+
+Clicking Edit and then Preview on the original Sandbox page corrected
+the problem, of course.
+
+Making the indexing only happen on a real commit might also speed the
+Preview up a small amount.
+--Chapman Flack
+
+[[!tag done]]
index 9eeb3c37444c3c4f619b165b62848a31205bbc8c..688d51ee6fc172b15f5ace53b147742fa205ef4a 100644 (file)
@@ -11,4 +11,4 @@ variable which points always to the base of the wiki.
 e.g. use "wikibase" for css and favicon and "baseurl" for the &lt;base&gt; tag.
 
 > thanks for pointing this bug out, I've fixed it --[[Joey]].
-[[tag done]]
+[[!tag done]]
index bb335906ab3742e92c9e35eae0fe489208579311..66fd810233ffcb42ec98ed652eae98008755618e 100644 (file)
@@ -4,7 +4,7 @@
     Might this be a problem of the web server?
 
 Also, I'd like to put the shortcut usages into backticks
--- `[[iki shortcuts]]` --
+-- `[[!iki shortcuts]]` --
 to have them displayed in the usual backtick-formatting.
 That also doesn't work, but this is an already-reported issue, as far as I know.
 
diff --git a/doc/bugs/shortcut_plugin_will_not_work_without_shortcuts.mdwn.mdwn b/doc/bugs/shortcut_plugin_will_not_work_without_shortcuts.mdwn.mdwn
new file mode 100644 (file)
index 0000000..5cc6691
--- /dev/null
@@ -0,0 +1,33 @@
+On my initial ikiwiki -setup auto.setup, I get the following error:
+
+    shortcut plugin will not work without shortcuts.mdwn
+    /home/turian/utils/etc/ikiwiki/auto.setup: ikiwiki --refresh --setup /home/turian/iki.setup failed at IkiWiki/Setup/Automator.pm line 105.
+
+
+This is using the latest git pull of ikiwiki.
+I am not sure why it is not finding shortcuts.mdwn. -- [[JosephTurian]]
+
+> The error, and the weird paths suggest to me that you
+> have installed ikiwiki in a strange way, and it is failing
+> to find its basewiki underlay. The `$installdir` is
+> hardcoded into IkiWiki.pm at build time, based on the PREFIX
+> setting (see README).
+>
+> If that's not set right, you'll have other problems than just this one,
+> so I suggest you check how you installed ikiwiki.
+> 
+> Anyway, I've made the shortcut plugin only warn about this..
+> --[[Joey]] 
+
+> > I have
+> >    $installdir="/home/turian/utils/"
+> > and the underlay dir is set to:
+> >    "$installdir/share/ikiwiki/basewiki",
+> > which does contain shortcuts.mdwn. So I am not sure why it is not finding it.
+> > I am grappling with installing ikiwiki in a user account, and would like to get the directories set up correctly.
+> > How can I debug this issue further?
+
+>>>> Why don't you strace it and look at where it's looking for
+>>>> shortcuts.mdwn. --[[Joey]] 
+
+>>>>>> Hmm, so change the PERL5LIB seemed to fix this. [[Done]].
index f977dc354a543c4d80c06d0c19e360fde2ec0a50..022987efbf175e56e6a7542a9c9240af74593b50 100644 (file)
@@ -1,6 +1,6 @@
-Writing [[wikipedia Low_frequency_oscillation]] causes the word "frequency" 
+Writing [[!wikipedia Low_frequency_oscillation]] causes the word "frequency" 
 to show up in italics, since underscores are Markdown for italics. Using
-[[wikipedia low frequency oscillation]] works in this case, because Wikipedia
+[[!wikipedia low frequency oscillation]] works in this case, because Wikipedia
 will redirect, but it's hardly clean. Maybe the shortcuts plugin should
 run pagetitle() on the text of its link? --Ethan
 
diff --git a/doc/bugs/sidebar_is_obscured_by_recentchanges.mdwn b/doc/bugs/sidebar_is_obscured_by_recentchanges.mdwn
new file mode 100644 (file)
index 0000000..6acc13b
--- /dev/null
@@ -0,0 +1,59 @@
+I've set up a simple sidebar on an otherwise fairly default wiki.  The sidebar uses css float:right and sits above most pages quite nicely.
+
+For example, my wiki's [front](http://www.cse.unsw.edu.au/~cs3431/wiki/) and [news](http://www.cse.unsw.edu.au/~cs3431/wiki/news/) pages show the sidebar nicely floating on top of the background.  (As a side note, I had to add:
+
+    #sidebar {
+       border: 1px solid;
+       background: white;
+    }  
+
+to <code>local.css</code> to get the border and make sure that the RSS feed's grey title didn't show through on the news page.)
+
+> Hmm the background color setting seems like a change it makes sense to make to
+> style.css .. done.
+> --[[Joey]]
+
+Unfortunately, the [recentchanges](http://www.cse.unsw.edu.au/~cs3431/wiki/recentchanges/) page doesn't look so nice - the sidebar appears below the recentchanges list.
+
+I don't understand why the sidebar is appearing below the recentchanges inline, but above the news inline.
+
+> I don't see the problem here in firefox 3. The sidebar is at the top of
+> both pages. However, it might have to do with the recentchanges page
+> itself using floating elements to build up the table-like display. --[[Joey]]
+
+>> I didn't test in firefox.  I now have screenshots for both firefox and safari.  It is still interesting to compare the layout.  The first is quite broken.  The second is only a little broken.  The third is what I was expecting.
+
+Here is a screenshot of the broken behaviour in Safari:
+
+<img src="http://www.cse.unsw.edu.au/~willu/screenshots/safari-1.png" alt="screenshot of broken behaviour in Safari" width="50%" />
+
+Here is a screenshot of the same thing in FireFox.  Notice that while there are no overlaps, there is still a large gap in the layout.
+
+<img src="http://www.cse.unsw.edu.au/~willu/screenshots/firefox-1.png" alt="screenshot of semi-working behaviour in Firefox" width="50%" />
+
+Here is an inline news page (in Safari, but it looks similar in firefox).  I was expecting both of the previous layouts to look like this.
+
+<img src="http://www.cse.unsw.edu.au/~willu/screenshots/safari-2.png" alt="screenshot of working behaviour in Safari" width="50%" />
+
+What really surprises me is WHY this looks any different.  And when you look at style.css you see that recentchanges and sidebar both use float, whereas normal inline pages do not.
+Note that in the third (working) screenshot, the top bullet point is wrapped.  This is because the sidebar is floated.
+
+I think there is:
+
+  * A display bug in safari, and
+  * It would be nice to clean up the way recentchanges are displayed so that there isn't a vertical gap for the sidebar.  I'll play with this and see what I can do.
+
+Looked at this a little more.  I've found the following.  Here is my current local.css:
+
+    div.recentchanges {
+       clear: both;
+       overflow: visible;
+    }
+
+Adding "clear: both;" makes the recentchanges div start below (as in further down the page) the sidebar.  This makes safari behave like firefox above (changes the 1st screenshot to look more like the 2nd screenshot).
+
+Adding "overflow: visible;"  (or removing "overflow: auto" from style.css) makes the sidebar appear above (as in printed over the top of, not higher up the page) the recentchanges (similar to the third screen shot above).  Unfortunately because ".recentchanges .pagelinks" uses "float: right;" it looks strange in other ways.  For this reason I use the "clear:both;" as well.
+
+-- [[users/Will]]
+
+>> Looks like [[Joey]] has added `clear:both;` to style.css, so this is [[bugs/done]]. -- [[Will]]
diff --git a/doc/bugs/some_strings_are_not_internationalized.mdwn b/doc/bugs/some_strings_are_not_internationalized.mdwn
new file mode 100644 (file)
index 0000000..a1b3825
--- /dev/null
@@ -0,0 +1,47 @@
+A lot of strings in ikiwiki are hardcoded and not taken for locales resources through gettext. This is bad because ikiwiki is thus difficult to spread for non-english users.
+
+I mean that, for instance in CGI.pm, line like:
+
+`my @buttons=("Save Page", "Preview", "Cancel");`
+
+should be written as
+
+`my @buttons=(gettext("Save Page"), gettext("Preview"), gettext("Cancel"));`
+
+> Yes, these need to be fixed. But note that the localised texts come back
+> into ikiwiki and are used in various places, including plugins.
+> Including, possibly, third-party plugins. So localising the buttons would
+> seem to require converting from the translations back into the C locale
+> when the form is posted. --[[Joey]]
+
+>> Wouldn't it be more easy to change all calls to the corrects ones (including in plugins) ?
+>> For instance in the same file (CGI.pm): `elsif ($form->submitted eq gettext("Save Page")) {`.
+>> That way no conversion to the C locale is needed.
+>> gettext use should just be publicized in documentation (at least in [[plugins/write]]). --[[bbb]]
+
+>>> It would be easy, but it could break third-party plugins that hardcode
+>>> the english strings. It's also probably less efficient to run gettext
+>>> over and over. --[[Joey]]
+
+In standards templates things seems wrongly written too. For instance in page.tmpl line like:
+
+`<li><a href="<TMPL_VAR EDITURL>" rel="nofollow">Edit</a></li>`
+
+should be written as
+
+`<li><a href="<TMPL_VAR EDITURL>" rel="nofollow"><TMPL_VAR EDITURL_TEXT</a></li>`
+
+with EDITURL_TEXT variable initialized in Render.pm through a gettext call. 
+
+Am I wrong ?
+
+> No, that's not a sane way to localise the templates. The templates can be
+> translated by making a copy and modifying it, or by using a tool to
+> generate .mo files from the templates, and generate translated templates
+> from .po files. (See [[todo/l10n]] for one attempt.) But pushing the
+> localisation of random strings in the templates through the ikiwiki
+> program defeats the purpose of having templates at all. --[[Joey]]
+
+If not I can spend some time preparing patches for such corrections if it can help.
+
+-- [[/users/bbb]]
index 5ed975f1200a55df90b6b4f1ac6680c1165b2d27..39f5d891e22a67cfb5d0dcbfcbe630977a3f4d38 100644 (file)
@@ -1,15 +1,15 @@
 I attempted to make a new webpage by having wiki code with
-    [[new page]]
+    [[!new page]]
     [newpage]
 
 This was converted to literal:
-    [[new page]]
+    [[!new page]]
 and the correct hyperlink:
     ?newpage
 
 So when has a space it doesn't let you create a new page. I am using 1.35. Let's see what happens here:
 
-[[new page]]
+[[!new page]]
 
 A moment later ... same thing ... it is not a link (no question mark to create).
 
index 1a43ec3fcea98ef5583af48ae03ca515960f2913..4ff6763a33c21890958e7e7ce6952b2f615e0d01 100644 (file)
@@ -1,3 +1,3 @@
-Having read i18n_characters_in_post_title, I have a page named `St John's` in a file named `St_John__39__s.mdwn`.  Regular wikilinks like `\\[[St_John's]]` successfully point to that page.  However, if I tag a page with `\[[tag St_John's]]`, that link is shown as pointing to a non-existant page.  Modify the tag to read `\[[tag St_John__39__s]]` works around the problem.
+Having read i18n_characters_in_post_title, I have a page named `St John's` in a file named `St_John__39__s.mdwn`.  Regular wikilinks like `\\[[St_John's]]` successfully point to that page.  However, if I tag a page with `\[[!tag St_John's]]`, that link is shown as pointing to a non-existant page.  Modify the tag to read `\[[!tag St_John__39__s]]` works around the problem.
 
 [[done]] in 1.49 --[[Joey]]
index 1d1e620926bc6782139aaaaa37b7f0584b2b663e..04ece0ae84ee1c2a9df0c6db597703bde5213c3e 100644 (file)
@@ -12,6 +12,10 @@ For now, I want to try and resolve the issues with net\_ssl\_test, and run more
 > ikiwiki) performing any sanity checking of the openid server. All the
 > security authentication goes on between your web browser and the openid
 > server. This may involve ssl, or not.
+>
+>> Note that I'm not an openid expert, and the above may need to be taken
+>> with a grain of salt. I also can make no general statements about openid
+>> being secure. ;-) --[[Joey]]
 > 
 > For example, my openid is "http://joey.kitenet.net/". If I log in with
 > this openid, ikiwiki connects to that http url to determine what openid
@@ -22,4 +26,60 @@ For now, I want to try and resolve the issues with net\_ssl\_test, and run more
 > is good.
 > --[[Joey]]
 
-[[tag done]]
+>> Ok, so I guess the worst that could happen when ikiwiki talks to the http
+>> address is that it gets intercepted, and ikiwiki gets the wrong address.
+>> ikiwiki will then redirect the browser to the wrong address. An attacker could
+>> trick ikiwiki to redirect to their site which always validates the user
+>> and then redirects back to ikiwiki. The legitimate user may not even notice.
+>> That doesn't so seem secure to me...
+
+>> All the attacker needs is access to the network somewhere between ikiwiki
+>> and http://joey.kitenet.net/ or the ability to inject false DNS host names
+>> for use by ikiwiki and the rest is simple.
+
+>> -- Brian May
+
+>>> I guess that the place to add SSL cert checking would be in either
+>>> [[!cpan LWPx::ParanoidAgent]] or [[!cpan Net::OpenID::Consumer]]. Adding
+>>> it to ikiwiki itself, which is just a user of those libraries, doesn't
+>>> seem right.
+>>> 
+>>> It's not particularly clear to me how a SSL cert can usefully be
+>>> checked at this level, where there is no way to do anything but
+>>> succeed, or fail; and where the extent of the check that can be done is
+>>> that the SSL cert is issued by a trusted party and matches the domain name
+>>> of the site being connected to. I also don't personally think that SSL
+>>> certs are the right fix for DNS poisoning issues. --[[Joey]]
+
+I was a bit vague myself on the details on openid. So I looked up the standard.
+I was surprised to note that they have already considered these issues, in
+section 15.1.2, <http://openid.net/specs/openid-authentication-2_0.html#anchor41>.
+
+It says:
+
+"Using SSL with certificates signed by a trusted authority prevents these kinds of
+attacks by verifying the results of the DNS look-up against the certificate. Once
+the validity of the certificate has been established, tampering is not possible.
+Impersonating an SSL server requires forging or stealing a certificate, which is
+significantly harder than the network based attacks."
+
+With regards to implementation, I am surprised that the libraries don't seem to
+do this checking, already, and by default. Unfortunately, I am not sure how to test
+this adequately, see [[!debbug 466055]]. -- Brian May
+
+--- 
+
+I think [[!cpan Crypt::SSLeay]] already supports checking the certificate. The trick
+is to get [[!cpan LWP::UserAgent]], which is used by [[!cpan LWPx::ParanoidAgent]] to
+enable this checking.
+
+I think the trick is to set one of the the following environment variables before retrieving
+the data:
+
+$ENV{HTTPS\_CA\_DIR} = "/etc/ssl/certs/";  
+$ENV{HTTPS\_CA\_FILE} = "/etc/ssl/certs/file.pem";  
+
+Unfortunately I get weird results if the certificate verification fails, see [[!debbug 503440]].
+It still seems to work though, regardless.
+
+-- Brian May
diff --git a/doc/bugs/stray___60____47__p__62___tags.mdwn b/doc/bugs/stray___60____47__p__62___tags.mdwn
new file mode 100644 (file)
index 0000000..6e508ff
--- /dev/null
@@ -0,0 +1,15 @@
+When using the [[plugins/htmltidy]] plugin (and possibly in other circumstances), ikiwiki sometimes creates more `</p>` tags than `<p>` tags, causing unbalanced markup. I've previously noticed unbalanced tags when a `\[[!map]]` matches no pages. This is part of the reason I developed [[plugins/htmlbalance]].
+
+This is particularly noticeable if htmltidy is enabled when building the docwiki: on the 'contrib' plugin pages, the title becomes `foo </p> (third-party plugin)` (with the angle-brackets escaped - it seems the text gets sanitized but is then escaped anyway).
+
+I believe that this snippet in `IkiWiki.pm` might be the reason for the imbalance:
+
+        if ($oneline) {
+                # hack to get rid of enclosing junk added by markdown
+                # and other htmlizers
+                $content=~s/^<p>//i;
+                $content=~s/<\/p>$//i;
+                chomp $content;
+        }
+
+The fact that HTML in a `\[[!meta title]]` is added but then escaped might indicate that some other bug is involved.
diff --git a/doc/bugs/support_for_openid2_logins.mdwn b/doc/bugs/support_for_openid2_logins.mdwn
new file mode 100644 (file)
index 0000000..139a537
--- /dev/null
@@ -0,0 +1,22 @@
+I have several complaints that users cannot contribute to my ikiwiki instances since they only have OpenID logins that support OpenID2. E.g. Yahoo!'s OpenID only supports 2.0+ 
+
+This is not the fault of ikiwiki, though the problem lies within the [perl openid consumer](http://packages.qa.debian.org/libn/libnet-openid-consumer-perl.html) in Debian which is a 1.x implementation AFAIK.
+
+I've contacted JanRain who have pointed me to:
+
+* [OpenID4Perl](http://code.sxip.com/openid4perl/)
+* Some [work](http://code.sixapart.com/svn/openid/trunk/perl/) by David Recordon
+
+However both Perl OpenID 2.x implementations have not been released and are incomplete implementations. :(
+
+> Both of the projects referenced above have since been released.
+> Net::OpenID::Consumer 0.x in Debian is indeed only an OpenID 1
+> implementation. However, Net::OpenID::Consumer 1.x claims to be
+> an OpenID 2 implementation (it's the second of the projects
+> above). I've filed a bug in Debian asking for the package to be
+> updated. --[[smcv]]
+
+> Net::OpenID::Consumer 1.x is now in Debian unstable --[[dom]]
+
+> I've tested with yahoo, and it works with the updated module. Sweet and
+> [[done]] --[[Joey]] 
diff --git a/doc/bugs/syntax_error_in_aggregate.mdwn b/doc/bugs/syntax_error_in_aggregate.mdwn
new file mode 100644 (file)
index 0000000..1e69e7f
--- /dev/null
@@ -0,0 +1,11 @@
+Current git :
+
+        $ perl -c IkiWiki/Plugin/aggregate.pm  
+        syntax error at IkiWiki/Plugin/aggregate.pm line 427, near "24;"
+        IkiWiki/Plugin/aggregate.pm had compilation errors.
+
+This prevents a Debian package build (due to `t/syntax.t`).
+
+Not knowing the units being used, I don't know where to add the missing parenthesis.
+
+[[done]]
diff --git a/doc/bugs/table_external_file_links.mdwn b/doc/bugs/table_external_file_links.mdwn
new file mode 100644 (file)
index 0000000..7b35383
--- /dev/null
@@ -0,0 +1,9 @@
+If wikilinks are put in an external table file, those links are not seen at
+scan time, and so ikiwiki does not know to update the page containing the
+table when the pages the links point to change (are added, removed, etc).
+
+There seem only two solutions to that bug -- either really make wikilinks
+in an external table file not work (probably by escaping them), 
+or run the preprocess code also in scan (expensive!). --[[Joey]]
+
+[[done]]
diff --git a/doc/bugs/tagged__40____41___matching_wikilinks.mdwn b/doc/bugs/tagged__40____41___matching_wikilinks.mdwn
new file mode 100644 (file)
index 0000000..e7e4af7
--- /dev/null
@@ -0,0 +1,33 @@
+It may be that I'm simply misunderstanding something, but what is the rationale
+for having `tagged()` also match normal wikilinks?
+
+> It simply hasn't been implemented yet -- see the answer in
+> [[todo/tag_pagespec_function]]. Tags and wikilinks share the same
+> underlying implementation, although ab reasonable expectation is that
+> they are kept separate. --Ivan Z.
+
+The following situation.  I have `tagbase => 'tag'`.  On some pages, scattered
+over the whole wiki, I use `\[[!tag open_issue_gdb]]` to declare that this page
+contains information about an open issue with GDB.  Then, I have a page
+`/tag/open_issues_gdb.mdwn` that essentially contains `\[[!map
+pages="tagged(open_issue_gdb)"]]`.  So far, so good: this page indeed does list
+all pages that are tagged like this.  But now, when I add in `/gdb.mdwn` a link
+to this page, like `\[[Open Issues|tag/open_issue_gdb]]`, then `/gdb.mdwn`
+itself shows up in the map on `tag/open_issues_gdb.mdwn`.  In my understanding
+this is due to the wikilink being equal to a `\[[!tag ...]]`.  What's the
+rationale on this, or what am I doing wrong, and how to achieve what I want?
+
+--[[tschwinge]]
+
+> What you are doing "wrong" is putting non-tag pages (i.e.
+> `/tag/open_issues_gdb.mdwn`) under your tagbase. The rationale for
+> implementing tag as it has been, I think, is one of simplicity and
+> conciseness. -- [[Jon]]
+
+>> No, he has no pages under tagbase that aren't tags. This bug
+>> is valid. [[todo/matching_different_kinds_of_links]] is probably
+>> how it will eventually be solved. --[[Joey]] 
+
+> And this is an illustration why a clean work-around (without changing the software) is not possible: while thinking about [[todo/matching_different_kinds_of_links]], I thought one could work around the problem by simply explicitly including the kind of the relation into the link target (like the tagbase in tags), and by having a separate page without the "tagbase" to link to when one wants simply to refer to the tag without tagging. But this won't work: one has to at least once refer to the real tag page if one wants to talk about it, and this reference will count as tagging (unwanted). --Ivan Z.
+
+> But well, perhaps there is a workaround without introducing different kinds of links. One could modify the [[tag plugin|plugins/tag]] so that it adds 2 links to a page: for tagging -- `tagbase/TAG`, and for navigation -- `tagdescription/TAG` (displayed at the bottom). Then the `tagdescription/TAG` page would hold whatever list one wishes (with `tagged(TAG)` in the pagespec), and whenever one wants to merely refer to the tag, one should link to `tagdescription/TAG`--this link won't count as tagging. So, `tagbase/TAG` would become completely auxiliary (internal) link targets for ikiwiki, the users would edit or link to only `tagdescription/TAG`. --Ivan Z.
diff --git a/doc/bugs/tags__44___backlinks_and_3.x.mdwn b/doc/bugs/tags__44___backlinks_and_3.x.mdwn
new file mode 100644 (file)
index 0000000..4fe9a47
--- /dev/null
@@ -0,0 +1,34 @@
+I think there might be an issue in the backlinks calculation in ikiwiki 3.04.
+
+I've just migrated to 3.04. In doing so, the following pagespec
+
+> "log/* and !link(tag/aggregation) and !link(tag/draft) and !*/Discussion"
+
+...started matching pages which contained
+
+> \[\[!template draft\]\]
+
+The page templates/draft.mdwn contains (amongst some markup)
+
+> \[\[!tag draft \]\]
+
+Prior to migration, the pagespec definitely took effect post-transclusion.
+
+An example: <http://jmtd.net/log/too_much_debconf_a_bad_thing/> contains the
+template inclusion, which can be seen to have worked due to markup at the
+bottom of the page. It even includes a "Tags: draft" link at the bottom.
+
+Strangely, <http://jmtd.net/tag/draft/> does not contain backlinks to pages
+which are tagged using the procedure above.
+
+After the first rebuild, it's broken, after a subsequent refresh, it is fixed.
+I've reproduced this twice (but assumed I'd done something wrong the first
+time, so went ahead and migrated live, spamming planet debian in the process
+:(). I will try and put together a testcase. -- [[users/Jon]], 2009/02/17
+
+> Looks like the same problem as
+> [[cannot_reliably_use_meta_in_template]]. AFAIK, this has never worked
+> reliably, although the linked page has a simple, though potentially
+> expensive fix. --[[Joey]] 
+
+> fix made, [[done]] --[[Joey]] 
index 71a9ece339cf58d24e2661e8e76b0272baa46e5c..f2243ab2d31f6b1817a46f604c7ab7d29b50a418 100644 (file)
@@ -3,7 +3,7 @@ I'm using the tags plugin with tagbase="tags".
 Already existing tags, corresponding to pages like tags/foo.html work just
 fine.
 
-If I add to a page a tag which is not existing (e.g. with [[tag newtag]])
+If I add to a page a tag which is not existing (e.g. with [[!tag newtag]])
 the just modified page will have a link which point to tags/newtag. This is
 in theory correct, but in practice leads to creating a tags/newtag subpage
 of the page I'm editing, while my tagbase is supposed to be relative to the
@@ -38,3 +38,6 @@ tags located in tags/ and tags located in whatever/tags/.
 > from the list when creating a new page..
 > 
 > --[[Joey]]
+
+> And, this is [[done]], creating tags with tagbase will put them under the
+> tagbase, unless the tag name starts with "/". --[[Joey]]
index 8fe411e5fdc072976df62730c83798c105f37093..172b49fd1a6dc1ece49ae7de4183cdcc9af0cba8 100644 (file)
@@ -13,7 +13,7 @@ which is exactly the same regular expression drawn out as a constant.  It appear
 > even in 5.8. See also: [[prune_causing_taint_mode_failures]],
 > [[Insecure_dependency_in_mkdir]],
 > [[Insecure_dependency_in_eval_while_running_with_-T_switch]],
-> and especially [[debbug 411786]]
+> and especially [[!debbug 411786]]
 >
 > The last of those was the last straw for me, and I disabled taint
 > checking in the debian package. You can do the same by building ikiwiki
index 8a2456529e7bb314474c127f13cb2da437578b87..db3917d21b16e1c543fc2394f49c01a681653ce5 100644 (file)
@@ -25,12 +25,12 @@ After some digging I found that HTML::Template is being required after the new s
                     filter => sub {
                             my $text_ref = shift;
     @@ -857,6 +856,7 @@
-     } #}}}
+     }
 
-     sub template ($;@) { #{{{
+     sub template ($;@) {
     +       require HTML::Template;
             HTML::Template->new(template_params(@_));
-     } #}}}
+     }
 
 **That** gave me:
 
@@ -53,7 +53,7 @@ After some step through I figured out that the template directory was invalid, a
 
 Other than ikiwiki.in, am I missing something here?
 
->> I think this is [[debbug 425891]]. I have sent there a patch that incorporates the original
+>> I think this is [[!debbug 425891]]. I have sent there a patch that incorporates the original
 >> author's two diffs but has a more correct solution to the first problem described 
 >> above. -- Thomas, 2007-06-26
 
index 86f47edbaf21a9fde4d9dfdd14d7ce91e574ed70..700492345bcdec497f5ab474e14a3f898c4ec5b3 100644 (file)
@@ -21,4 +21,4 @@ I think this will be a own dir for images for every page.
 
 --[[PatrickWinnertz]]
 
-[[tag done]]
+[[!tag done]]
index 7ec1edc4e6638611fd3d64f5e3ff32511194eeac..bdd07210ee9366ea300a18358e5ca19403a9c4ac 100644 (file)
@@ -9,6 +9,6 @@ The first two complaints happen if textile is not loaded, the third fatal one ha
 
 0x92 is "single quote" in the evil windows default codepage. It would be nice to handle this gracefully and not abort ikiwiki at this point, or alternatively, die fatally but mention which input page caused the error.
 
-Interestingly enough, in my case, the input file has several other bad windows characters (0xFC, u-umlaut) which have not caused ikiwiki to abort. ikiwiki version 2.50. -- [[JonDowland]]
+Interestingly enough, in my case, the input file has several other bad windows characters (0xFC, u-umlaut) which have not caused ikiwiki to abort. ikiwiki version 2.50. -- [[users/Jon]]
 
 > Fixed in git. [[done]] --[[Joey]]
diff --git a/doc/bugs/title__40____41___in_a_PageSpec__44___with_meta_enabled__44___causes_a_crash.mdwn b/doc/bugs/title__40____41___in_a_PageSpec__44___with_meta_enabled__44___causes_a_crash.mdwn
new file mode 100644 (file)
index 0000000..8dc78a4
--- /dev/null
@@ -0,0 +1,3 @@
+When the meta plugin is enabled, use of the title() predicate in a [[PageSpec]] fails with "Undefined subroutine &IkiWiki::Plugin::meta::pagetitle called". The [[patch]] is to replace "pagetitle" with "IkiWiki::pagetitle" in the meta plugin, as in [this git commit](http://git.debian.org/?p=users/smcv/ikiwiki.git;a=commit;h=1f26a1bf1655b1d0223b24ba1db70579a3774eb1) (git://git.debian.org/git/users/smcv/ikiwiki.git, branch=master, commit=1f26a).
+
+[[done]] thanks!
diff --git a/doc/bugs/toggle_fails_on_Safari.mdwn b/doc/bugs/toggle_fails_on_Safari.mdwn
new file mode 100644 (file)
index 0000000..25f62e0
--- /dev/null
@@ -0,0 +1,58 @@
+The [[plugins/toggle]] plugin has no effect when viewed on the Safari web browser.
+
+All toggles appear open all the time.
+
+I don't know if this is true for other webkit browsers (the new Konqueror, the iPhone, etc).
+I'm currently testing in the Safari nightly builds, but I've seen the bug in the current release
+of Safari too.
+
+Looking at the Safari Web Inspector, it believes there is a parse error on line 47 of the
+[[news]] page.  This is the definition of the getElementsByClass(class) function.
+
+    45 }
+    46
+    47 function getElementsByClass(class) {
+       SyntaxError: Parse error
+    48         var ret = new Array();
+
+> Reproduced in epiphany-webkit on debian.
+> 
+> Also noticed something interesting when I opened the page in vim. It
+> highlighted the "class" like a type definition, not a variable. Sure
+> enough, replacing with "c" fixed it.
+> 
+> I wonder if webkit is actually in the right here, and using a reseved
+> word like, presumably, "class" as a variable name is not legal. As I try
+> to ignore javascript as much as possible, I can't say. [[done]] --[[Joey]]
+
+>> I also started having a look at this.  I found the same issue with the
+>> the variable 'class'.  I'm not a javascript guru so I looked on the web
+>> at other implementations of getElementsByClass() and noticed some
+>> things that we might use.  I took a bunch of different ideas and came
+>> up with this:
+
+    function getElementsByClass(cls, node, tag) {
+       if (document.getElementsByClass)
+               return document.getElementsByClass(cls, node, tag);
+       if (! node) node = document;
+       if (! tag) tag = '*';
+       var ret = new Array();
+       var pattern = new RegExp("(^|\\s)"+cls+"(\\s|$)");
+       var els = node.getElementsByTagName(tag);
+       for (i = 0; i < els.length; i++) {
+               if ( pattern.test(els[i].className) ) {
+                       ret.push(els[i]);
+               }
+       }
+       return ret;
+    }
+
+>> Most of the changes are minor, except that this one will use the
+>> built in function if it is available.  That is likely to be significantly
+>> faster.  Adding the extra parameters doesn't cause a problem --
+>> they're filled in with useful defaults.
+
+>> I don't know if it is worth making this change, but it is there if you want it.
+
+>>> Well, it seems to work. Although god only knows about IE. Suppose I
+>>> might as well.. --[[Joey]]
diff --git a/doc/bugs/txt_plugin_having_problems_with_meta_directives.mdwn b/doc/bugs/txt_plugin_having_problems_with_meta_directives.mdwn
new file mode 100644 (file)
index 0000000..2222448
--- /dev/null
@@ -0,0 +1,19 @@
+When applying my usual copyright and licensing header to a [[plugins/txt]]
+page, garbled output is created.
+
+Here is the header:
+
+    \[[meta copyright="Copyright © 2001, 2002, 2003, 2004, 2005, 2008 Free
+    Software Foundation, Inc."]]
+    
+    \[[meta license="""[[toggle id="license" text="GFDL 1.2+"]][[toggleable
+    id="license" text="Permission is granted to copy, distribute and/or modify
+    this document under the terms of the GNU Free Documentation License,
+    Version 1.2 or any later version published by the Free Software Foundation;
+    with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+    A copy of the license is included in the section entitled
+    [[GNU_Free_Documentation_License|/fdl]]."]]"""]]
+
+--[[tschwinge]]
+
+> [[done]], made it less zealous about encoding html entities. --[[Joey]]
diff --git a/doc/bugs/typo_in_skeleton.pm:_sessionncgi.mdwn b/doc/bugs/typo_in_skeleton.pm:_sessionncgi.mdwn
new file mode 100644 (file)
index 0000000..4772ace
--- /dev/null
@@ -0,0 +1,5 @@
+skeleton.pm.example contains the typo "sessionncgi" when defining a sub, which means the skeleton plugin won't work as a session CGI action as-is. [My repository has a patch on the 'trivia' branch](http://git.debian.org/?p=users/smcv/ikiwiki.git;a=commitdiff;h=72ffc85d). --[[smcv]]
+
+[[!tag patch]]
+
+[[done]]
index 13ebe1cabda46e819f47ec2e2625b37722835678..b01fc44f2d11233730f26996033aacb962ce2849 100644 (file)
@@ -43,4 +43,4 @@ The out put is:
 > alone. If you feel the other things you brought up are bugs, please talk
 > to the markdown maintainer. --[[Joey]]
 
-[[tag done]]
+[[!tag done]]
index b8e84969c894a771f582aa7b27cde3e1803c380d..c827c6dd85b8b8d4cf7ffec25849d80df4000393 100644 (file)
@@ -1,9 +1,4 @@
 If a file in the srcdir is removed, exposing a file in the underlaydir,
-ikiwiki will not notice the change and rebuild it until the file in the
-underlaydir gets a mtime newer than the mtime the removed file had.
-
-Relatedly, if there are two files with different extensions that build a
-page with the same name, in a directory, ikiwiki will update the page
-whenever either changes, using the changed one as the source. But if that
-most recently changed one is removed, it won't rebuild the page using the
-older one as the source.
+ikiwiki will notice the removal and delete the page from the destdir. The
+page from the underlay will not be built. (However, it will be if the wiki
+gets rebuilt.)
diff --git a/doc/bugs/unicode_chars_in_wikiname_break_auth.mdwn b/doc/bugs/unicode_chars_in_wikiname_break_auth.mdwn
new file mode 100644 (file)
index 0000000..472597c
--- /dev/null
@@ -0,0 +1,20 @@
+I spent hours trying to understand why my wiki suddenly refused me to log in (using passwordauth).
+The failure message was always: `login failed, perhaps you need to turn on cookies?`
+
+Inspecting the cookie information (thanks to Iceweasel's webdeveloper add-on), I realized there were some weird-looking encoded chars in the cookie name.
+
+Replacing "·" with "-" in `wikiname` fixed this login issue.
+
+> Hmm, Recai sent me a patch a long time ago to handle utf-8 here by encoding
+> the wikiname. But it doesn't seem to work, somehow the encoded utf-8
+> value still doesn't make it through. (CGI::Session seems to have underermined utf-8
+> issues too.) Seems like I will have to possibly break some sessions and
+> entity-encode the wikiname in the cookie.. [[done]]. --[[Joey]]
+
+>> I confirm it fixes the bug for me. --[[intrigeri]]
+
+(BTW, such a char was replaced by -I don't remember what encoding thingie- in my setup file, when running `ikiwiki-transition setupformat`.)
+
+> Thanks for the heads up, fixed that too. --[[Joey]]
+
+>> I confirm it fixes the bug for me. --[[intrigeri]]
diff --git a/doc/bugs/unicode_encoded_urls_and_recentchanges.mdwn b/doc/bugs/unicode_encoded_urls_and_recentchanges.mdwn
new file mode 100644 (file)
index 0000000..88dbfc3
--- /dev/null
@@ -0,0 +1,38 @@
+it appears that unicode characters in the title that are unicode letters are spared the __ filename encoding but instead saved in their utf8 encoding. (correct me if i'm wrong; didn't find the code that does this.) -- see below for examples.
+
+> Filenames can have any alphanumerics in them without the __ escaping.
+> Your locale determines whether various unicode characters are considered
+> alphanumeric. In other words, it just looks at the [[:alpha:]] character
+> class, whatever your locale defines it to be. --[[Joey]]
+
+this is not a problem per se, but (at least with git backend) the recent changes missinterpret the file name character set (it seems to read the filenames as latin1) and both display wrong titles and create broken links.
+
+the problem can be shown with an auto-setup'd ikiwiki without cgi when manually creating utf8 encoded filenames and running ikiwiki with LANG=en_GB.UTF-8 .
+
+> Encoding issue, I figured out a fix. [[done]] --[[Joey]]
+
+>> the link text works now, but the link goes to
+>> `ikiwiki.cgi?page=uml%C3%A4ute&do=recentchanges_link`, which fails with
+>> "missing page". it seems that bestlink can't handle utf8 encoded texts. (the
+>> same happens, by the way, when using meta-redir to a page with high bytes in
+>> the name.)
+>>
+>>> The problem is that all cgi inputs have to be explicitly decoded to
+>>> utf-8, which I've now done for `recentchange_link`.
+>>>> thanks a lot, i think that closed the bug.
+>>> 
+>>> I cannot, however, reproduce a problem with meta redir. Here it
+>>> generated the following html, which redirected the browser ok:
+>>>    <meta http-equiv="refresh" content="0; URL=./../â/" />
+>>>> sorry, my fault -- it was the blank which needed to be replaced by an
+>>>> underscore, not the high byte character
+>>
+>> update: i've had a look at the git options; you could run git with '-z' (NUL
+>> termination) in the `git_commit_info` function; this would require some
+>> changes in `parse_diff_tree`, but otherwise completely eliminate the
+>> problems with git escaping.
+>> 
+>>> If you would like to develop a patch to that effect, I'd be glad to
+>>> drop the current nasty code.
+>>>> i'll have a look, but i'm afraid that's above my current perl skills.
+>>>> --[[chrysn]]
diff --git a/doc/bugs/unwanted_discussion_links_on_discussion_pages.mdwn b/doc/bugs/unwanted_discussion_links_on_discussion_pages.mdwn
new file mode 100644 (file)
index 0000000..c74a094
--- /dev/null
@@ -0,0 +1,36 @@
+Background: some po translations (amongst which `fr.po`) translate "discussion" to an upper-cased word (in French: "Discussion").
+By the way, this is wished e.g. in German, where such a noun has to be written with an upper-cased "D", but I can not see
+the logic behind the added "D" in French.
+
+Anyway, this gettext-translated word is used to name the discussion pages, as `$discussionlink` in `Render.pm` is
+built from `gettext("discussion")`. In the same piece of code, a case-sensitive regexp that tests wether the page
+being rendered is a discussion page is case-sensitive.
+
+On the other hand, new discussion pages are created with a name built from `gettext("Discussion")` (please note the upper-cased
+"D"). Such a new page name seems to be automagically downcased.
+
+This leads to newly created discussion pages not being recognized as discussion pages by the
+`$page !~ /.*\/\Q$discussionlink\E$/` regexp, so that then end with an unwanted discussion link.
+
+A simple fix that seems to work is to make this regexp case-insensitive:
+
+    git diff IkiWiki/Render.pm
+    diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
+    index adae9f0..093c25b 100644
+    --- a/IkiWiki/Render.pm
+    +++ b/IkiWiki/Render.pm
+    @@ -77,7 +77,7 @@ sub genpage ($$) {
+            }
+            if ($config{discussion}) {
+                    my $discussionlink=gettext("discussion");
+    -               if ($page !~ /.*\/\Q$discussionlink\E$/ &&
+    +               if ($page !~ /.*\/\Q$discussionlink\E$/i &&
+                       (length $config{cgiurl} ||
+                        exists $links{$page."/".$discussionlink})) {
+                            $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1));
+
+But the best way would be to avoid assuming implicitely that translators will translate "discussion" and "Discussion" the same way.
+
+> [[done]] --[[Joey]] 
+
+[[!tag patch]]
diff --git a/doc/bugs/user_links_on_recentchanges_pages_problem.mdwn b/doc/bugs/user_links_on_recentchanges_pages_problem.mdwn
new file mode 100644 (file)
index 0000000..d00f681
--- /dev/null
@@ -0,0 +1,12 @@
+When I click on a linked username for commits on the recentchanges page (on
+the live ikiwiki.info) I get a link such as
+<http://ikiwiki.info/ikiwiki.cgi?page=users%2Fjoey&do=recentchanges_link>
+which returns something like
+
+    <a href="http://ikiwiki.info">ikiwiki</a>/ Error
+    <p class="error">Error: unknown do parameter
+
+-- [[Jon]]
+
+> That was fixed in 3.04 but ikiwiki.info had not been upgraded to it yet.
+> [[done]] --[[Joey]] 
diff --git a/doc/bugs/websetup_eats_setupconf_and_allow__95__symlinks__95__before__95__srcdir.mdwn b/doc/bugs/websetup_eats_setupconf_and_allow__95__symlinks__95__before__95__srcdir.mdwn
new file mode 100644 (file)
index 0000000..47063d5
--- /dev/null
@@ -0,0 +1,21 @@
+My web server runs in a chroot jail. This makes things interesting because the paths are slightly different depending on whether you are inside or outside the chroot.
+
+To override an incorrectly guessed path, I set setupconf in the .setup file. I also set allow_symlinks_before_srcdir=>1. However, when I tried websetup, the setup file was correctly changed but these important settings disappeared. This seems like a bug.
+
+> I don't know what "setupconf" is. This is the first mention of it in the
+> ikiwiki source tree. 
+> 
+> I've fixed the `allow_symlinks_before_srcdir` issue. --[[Joey]]
+
+I meant setupfile as in IkiWiki::Setup::dump($config{setupfile}) from IkiWiki/Plugin/websetup.pm
+
+Sorry for the confusion.
+
+> Ok, that's an internal setting that I never envisioned someone digging
+> out and setting in their setup file. It could be made an exported config
+> option, but then every generated setup file will have this setting in it,
+> which will be at best redundant.
+> 
+> Can you find another solution, such as a symlink, for your special case?
+
+I see your point. [[done]]
index 1e5fe71dfbbdacdc177024af4bb3e3330e768ccd..29e03f2d61f12a5ce2212ff1a6247ea1fc62390e 100644 (file)
@@ -1,15 +1,15 @@
-Wiki formatting between `\[[toc ]]` and an inline fails to render.  The
+Wiki formatting between `\[[!toc ]]` and an inline fails to render.  The
 problem does not seem to trigger if the inline uses the titlepage template,
 or if it doesn't match any pages.  See example below; also reproducible
 with a single-file wiki containing the text below, rendered via `ikiwiki
 --plugin toc`.
 
-> This is [[debbug 421843]], and I suspect it affects certian other plugins
+> This is [[!debbug 421843]], and I suspect it affects certian other plugins
 > that also use empty divs as placeholders. It's fixed in markdown 1.0.2 b7
 > (available in debian experimental). So I'll [[close|done]] this as it's
 > not really an ikiwiki bug. --[[Joey]]
 
-[[toc ]]
+[[!toc ]]
 
 **not bold**
 
@@ -19,7 +19,7 @@ with a single-file wiki containing the text below, rendered via `ikiwiki
 
 [not a link](http://ikiwiki.info)
 
-[[inline pages="news/*" description="Sparse News" show=1 feeds=no]]
+[[!inline pages="news/*" description="Sparse News" show=1 feeds=no]]
 
 **bold**
 
index f5cbc8894f088713dd0249eda9a05bb5f4b56e27..b2a8b06323cd7f497918d748eb0b710ef981b10f 100644 (file)
@@ -1,6 +1,6 @@
 In [[ikiwiki/markdown]] syntax, none of the other special characters get processed
 inside a code block.  However, in ikiwiki, [[wiki_links|ikiwiki/wikilink]] and
-[[preprocessor_directives|ikiwiki/preprocessordirective]] still get processed
+[[preprocessor_directives|ikiwiki/directive]] still get processed
 inside a code block, requiring additional escaping.  For example, `[links
 don't work](#here)`, but `a [[ikiwiki/wikilink]] becomes HTML`. --[[JoshTriplett]]
 
@@ -46,4 +46,4 @@ and have it render like:
 > there should give some strong hints how to fix this bug, though I haven't
 > tried to apply the method yet. --[[Joey]]
 
-[[debbug 487397]]
+[[!debbug 487397]]
index f0dc13eaf57db1b108f8be7b1a2c8b0b7f77987a..cca01718c124d494566d8a1364a079377fe63142 100644 (file)
@@ -1,6 +1,6 @@
 I try to create wikilink in table. But it does not work. Here is example:
 
-       \[[table class=table1 data="""
+       \[[!table class=table1 data="""
        \[[wikilink_test|index]]
        \[[wikilink_test\|index]]
        [wikilink test](/servers/webmail1)
@@ -21,7 +21,7 @@ What exactly is a difference between wikilink and URL reference to the same page
 
 Trying to report this I found something weird. I changed in the example [[ with || because wiki renders something wrongly. You can see what I tried originally here:
 
-       \[[table class=table1 data="""
+       \[[!table class=table1 data="""
        \[[wikilink_test|servers/webmail1]]
        \[[wikilink_test|servers/webmail1]]
        [wikilink test](/servers/webmail1)
diff --git a/doc/cgi/discussion.mdwn b/doc/cgi/discussion.mdwn
new file mode 100644 (file)
index 0000000..4cd7c5a
--- /dev/null
@@ -0,0 +1,22 @@
+## Markdown or CGI error prevents web-based editing 
+
+I have a working ikiwiki configuration with an SVN backend, running on Ubuntu 7.10, Apache 2.2.4. I'm using Perl 5.8.8, however, I had to use Text::Markdown 1.0.5 from CPAN instead of the latest because I had the same issue as someone [here](http://ikiwiki.info/index/discussion/) (Namely I was getting this error until I used the old Markdown version: "*** glibc detected *** double free or corruption (!prev): 0x0922e478 ***
+").
+
+> aside: that might have been related to [Text::Markdown bug #37297](http://rt.cpan.org/Public/Bug/Display.html?id=37297).
+> --ChapmanFlack 9Jul2008
+
+CGI seems to be working at least partly - the History and Recent Changes pages both work. However, if I attempt to edit or create a page, I get this error:
+    Error: Failed to load plugin IkiWiki::Plugin::mdwn: Can't locate IkiWiki/Plugin/mdwn.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.8.8 /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl .) at (eval 6) line 2. BEGIN failed--compilation aborted at (eval 6) line 2. 
+
+Since ikiwiki builds, it has to be finding Markdown at build time, right? What am I doing wrong here? I would appreciate a point in the right direction. Thanks. --mrled
+
+> Ikiwiki is failing to find `IkiWiki/Plugin/mdwn.pm` which is a plugin included in ikiwiki itself.
+> So, that file must not have been installed in any of the directories in the @INC search path listed.
+> Either fix the installation so ikiwiki's perl modules are installed in one of the standard locations,
+> or you could use the `libdir` setting in the setup file to point ikiwiki
+> at the directory the perl modules are installed. --[[Joey]]
+
+>> Ah hah! That helped... once I knew that it was ikiwiki's internal thing, I was able to figure out that it was a permissions issue. For the record, I didn't change permissions or the default install prefix of /usr/local (well, at least not on purpose). Thanks for your help. --mrled
+
+>>> Interesting.. so just a permissions problem of some sort that prevented the cgi from seeing the modules that were there in-path? --[[Joey]]
index 37fb59071607e042b7476fcc738419a6ff97cd72..486a4d1864a2e731cb9d7d6cd6bc37c9f2705609 100644 (file)
@@ -7,4 +7,5 @@ developers monitor [[RecentChanges]] closely, via the webpage, email,
 [CIA](http://cia.navi.cx), and IRC, and respond in a timely fashion.
 
 You could also drop by the IRC channel `#ikiwiki` on
-[OFTC](http://www.oftc.net/) (`irc.oftc.net`).
+[OFTC](http://www.oftc.net/) (`irc.oftc.net`), or use the
+[identi.ca ikiwiki group](http://identi.ca/group/ikiwiki).
diff --git a/doc/convert.mdwn b/doc/convert.mdwn
new file mode 100644 (file)
index 0000000..871cd31
--- /dev/null
@@ -0,0 +1,7 @@
+Do you have an existing wiki or blog using other software, and would like
+to convert it to ikiwiki? Various tools and techniques have been developed
+to handle such conversions.
+
+* [[tips/convert_mediawiki_to_ikiwiki]]
+* [[tips/convert_MoinMoin_and_TWiki_to_ikiwiki]]
+* [[tips/convert_blogger_blogs_to_ikiwiki]]
index bb3c15f517ca01c568528ded44144023f57dd2e1..5b6b9e1aface309a0ebdd34a4c798f6cc10e9b00 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="CSS"]]
+[[!meta title="CSS"]]
 
 ## Using CSS with ikiwiki
 
index 00ad9cf134c5af648afc1128ce295540b348db80..c0e349552e8faf41ee4c30013d83908518d2f194 100644 (file)
@@ -1,32 +1,27 @@
-[[meta title="CSS Market"]]
+[[!meta title="CSS Market"]]
 
-User contributed stylesheet files for ikiwiki. Feel free to add your own
-stylesheets here. (Upload as wiki pages; wiki gnomes will convert them to css
-files..)
+User contributed stylesheet files for ikiwiki. Unless otherwise noted,
+these style sheets can be installed by copying them into your wiki's source
+dir with a filename of `local.css`.
+
+Feel free to add your own stylesheets here. (Upload as wiki pages; wiki
+gnomes will convert them to css files..)
 
 * **[[css_market/zack.css]]**, contributed by [[StefanoZacchiroli]],
   customized mostly for *blogging purposes*, can be seen in action on 
-  [zack's blog](http://www.bononia.it/~zack/blog/)
-  [[meta stylesheet="zack"]]
+  [zack's blog](http://upsilon.cc/~zack/blog/)
+  [[!meta stylesheet="zack"]]
 
 * **[[css_market/kirkambar.css]]**, contributed by [[Roktas]].  This far from perfect
   stylesheet follows a [Gitweb](http://www.kernel.org/git/?p=git/git.git;a=tree;f=gitweb)
   like theme, so it may provide a consistent look'n feel along with the [[rcs/git]] backend. ;-)
   You can see it in action on [kirkambar](http://kirkambar.net/) (Turkish content).
-  [[meta stylesheet="kirkambar"]]
+  [[!meta stylesheet="kirkambar"]]
 
 * **[[css_market/embeddedmoose.css]]**, contributed by [[JoshTriplett]].
   Designed for [Embedded Moose](http://embeddedmoose.com).  Some ideas from the
   Debian lighttpd index.html page.
-  [[meta stylesheet="embeddedmoose"]]
-
-* **Refresh**, contributed by [[FredericLespez]]. Adapted from a free template
-  designed by [styleshout](http://www.styleshout.com).
-  You can see it [here](http://fred.ccheznous.org). You can download the local.css file and
-  the modified templates [here](http://fred.ccheznous.org/refresh_20060602.tgz).
-    * You'll find a updated version of these templates [here](http://www.der-winnie.de/~winnie/configs/ikiwiki-templates.tar.gz). 
-      These templates are known to work with ikiwiki 2.31, and since I'll install always the newest one on my server I'll will update them on a regular basis.
-
+  [[!meta stylesheet="embeddedmoose"]]
 
 * **[[02_Template.css]]**, contributed and adapted by [maxx](http://martin.wuertele.net/), [original](http://www.openwebdesign.org/viewdesign.phtml?id=3057)
   designed by [jarico](http://www.openwebdesign.org/userinfo.phtml?user=jcarico) 
@@ -34,20 +29,37 @@ files..)
   **[[css_market/02_Template.tmpl]]**. If you prefer 
   [my header image](http://martin.wuertele.net/images/header.png) you can 
   use it under the terms of the MIT License (see png comment).
-  [[meta stylesheet="02_Template"]]
+  [[!meta stylesheet="02_Template"]]
 
 * **[[css_market/cstamas.css]]**, contributed by [[cstamas]].
   This one is based on embeddedmoose, however it is slightly different now.
   [My webpage's](http://users.itk.ppke.hu/~cstamas/tag/english) is not the same.
   You can grab some pictures used as background patterns from there.
-  [[meta stylesheet="cstamas"]]
+  [[!meta stylesheet="cstamas"]]
 
 * **[[css_market/bma.css]]**, contributed by [bma](http://subvert.org.uk/~bma/).
   Not quite the same as I use on my site, since that has slightly modified
   templates.
-  [[meta stylesheet="bma"]]
+  [[!meta stylesheet="bma"]]
+
+* **[blankoblues.css][1]**, contributed by [[Blanko]]. Can be seen on [Blankoblues Demo][2]. Local.css and templates available [here][3].
+
+* **[contraste.css][4]**, contributed by [[Blanko]]. Can be seen on [Contraste Demo][5]. Local.css and templates available [here][6].
+
+* **[[css_market/actiontabs.css]]**, contributed by [[svend]]. This style sheet displays
+  the action list (Edit, RecentChanges, etc.) as tabs.
+  [[!meta stylesheet="actiontabs"]]
 
 If your web browser allows selecting between multiple stylesheets, this
 page can be viewed using many of the stylesheets above. For example, if
 using Epiphany with the Select Stylesheet extension enabled, use View ->
 Style.  In Firefox or Iceweasel, use View -> Page Style.
+
+<!-- Page links -->
+
+ [1]: http://blankoworld.homelinux.com/demo/ikiwiki/blankoblues/src/local.css (Download Blankoblues CSS)
+ [2]: http://blankoworld.homelinux.com/demo/ikiwiki/blankoblues/htdocs/ (Take a tour on Blankoblues Demo)
+ [3]: http://blankoworld.homelinux.com/demo/ikiwiki/blankoblues/blankoblues.tar.gz (Download local.css and templates for Blankoblues theme)
+ [4]: http://blankoworld.homelinux.com/demo/ikiwiki/contraste/src/local.css (Download Contraste CSS)
+ [5]: http://blankoworld.homelinux.com/demo/ikiwiki/contraste/htdocs/ (Take a tour on Contraste Demo)
+ [6]: http://blankoworld.homelinux.com/demo/ikiwiki/contraste/contraste.tar.gz (Download local.css and templates for Contraste theme)
diff --git a/doc/css_market/actiontabs.css b/doc/css_market/actiontabs.css
new file mode 100644 (file)
index 0000000..a1dc47e
--- /dev/null
@@ -0,0 +1,122 @@
+/* ikiwiki local style sheet */
+
+/* Add local styling here, instead of modifying style.css. */
+
+a {
+       text-decoration: none;
+       color: #005a9c;
+}
+
+a:hover {
+       text-decoration: underline;
+}
+
+
+hr {
+       border-style: none;
+       background-color: #999;
+       height: 1px;
+}
+
+code, pre {
+    background: #eee;
+}
+
+pre {
+    padding: .5em;
+}
+
+body {
+       margin: 0;
+       padding: 0;
+       font-family: sans-serif;
+       color: black;
+       background: white;
+}
+
+.pageheader {
+       margin: 0;
+       padding: 1em 2em 0 2em;
+       background: #eee;
+       border-color: #999;
+       border-style: none none solid none;
+       border-width: 1px;
+}
+
+.header {
+       font-size: 100%;
+       font-weight: normal;
+}
+
+.title {
+       display: block;
+       margin-top: .2em;
+       font: 140% sans-serif;
+       text-transform: capitalize;
+}
+
+.actions {
+       text-align: right;
+       padding: 0;
+}
+
+#content, #comments, #footer {
+       margin: 1em 2em;
+}
+
+#pageinfo {
+       border-color: #999;
+}
+
+.inlinepage {
+       margin: .4em 0;
+       padding: .4em 0;
+       border-style: none;
+       border-top: 1px solid #aaa;
+}
+
+.inlineheader {
+       font-size: 120%;
+       font-weight: normal;
+}
+
+h1 { font: 120% sans-serif }
+h2 { font: bold 100% sans-serif }
+h3 { font: italic 100% sans-serif }
+h4, h5, h6 { font: small-caps 100% sans-serif }
+
+/* Smaller headings for inline pages */
+.inlinepage h1 { font-size: 110% }
+.inlinepage h2 { font-size: 100% }
+.inlinepage h3 { font-size: 100% }
+
+.pageheader .actions ul {
+       border-style: none
+}
+
+.actions ul {
+       font-size: 75%;
+       padding: 0;
+       border-style: none;
+}
+
+.actions ul li a {
+       text-decoration: none;
+}
+
+.actions ul li {
+       margin: 0;
+       padding: .1em .5em 0 .5em;
+       background: white;
+       border-color: #999;
+       border-style: solid solid none solid;
+       border-width: 1px;
+}
+
+div.recentchanges {
+       border-style: none;
+}
+
+.pagecloud {
+       width: auto;
+}
diff --git a/doc/css_market/discussion.mdwn b/doc/css_market/discussion.mdwn
new file mode 100644 (file)
index 0000000..3dc47b5
--- /dev/null
@@ -0,0 +1,37 @@
+What is the correct way to install the .tmpl files? -- [[JosephTurian]]
+
+> For themes that need them, you can set `templatedir` to some directory in
+> your setup file, and put the templates there. Or install directly overtop
+> ikiwiki's standard templates (in, eg `/usr/share/ikiwiki/templates`)
+> --[[Joey]]
+
+----
+
+How can I update a .css file uploaded to the CSS market?
+My CSS has been updated to address comments (for the comments plugin), but I cannot find a way to update zack.css.
+The most recent version is always available at: <http://git.upsilon.cc/cgi-bin/gitweb.cgi?p=zack-homepage.git;a=blob_plain;f=local.css;hb=HEAD>
+
+-- [[StefanoZacchiroli]]
+
+> Just letting me know about the change works -- updated. --[[Joey]] 
+
+----
+
+Added small changes to embeddedmoose.css to work with ikiwiki 3.x.  Figured here is as good as any until Josh can review and update if he so chooses:  <http://bosboot.org/tb-embeddedmoose.css>.  It removes annoying borders around the header and footer.  -- [[TimBosse]]
+
+-----
+
+I removed this from the list since both places to download it are broken.
+--[[Joey]] 
+
+* **Refresh**, contributed by [[FredericLespez]]. Adapted from a free template
+  designed by [styleshout](http://www.styleshout.com).
+  You can see it [here](http://fred.ccheznous.org). You can download the local.css file and
+  the modified templates [here](http://fred.ccheznous.org/refresh_20060602.tgz).
+
+    * This link (above) seems to deliver an empty tarball.
+
+    * You'll find a updated version of these templates [here](http://www.der-winnie.de/~winnie/configs/ikiwiki-templates.tar.gz). 
+       These templates are known to work with ikiwiki 2.31, and since I'll install always the newest one on my server I'll will update them on a regular basis.
+        * (This link appears to be broken?)
+
index dbc2e5c445b3293723ab4bcc9a87bfa14f0d29b2..5a0521d54bce1e700c8531f7f27c4b2dfe7d97d6 100644 (file)
  */
 
 body {
-  font-family: sans;
-  width: 760px;
-  margin-left: 20px;
+  font-family: sans-serif;
+  font-size: medium;
 }
+h1, h2, h3, h4 {
+  font-weight: normal;
+}
+h1 { font-size: 140%; }
+h2 { font-size: 120%; }
+h3 { font-size: 110%; }
+h4 { font-size: 105% }
 
-div#content {
-  font-size: 11pt;
+a { text-decoration: none; }
+a:hover { text-decoration: underline; }
+
+.flow {
+  float: right;
+  margin-left: 10px;
+  margin-bottom: 10px;
+  text-align: center;
 }
 
-.header span {
-  font-size: 14pt;
-  font-weight: normal;
+.attrib-caption {
+  font-size: xx-small;
+  font-style: italic;
 }
 
-div.actions ul {
-  font-size: 10pt;
+input {
+  border: solid 1px;
+  border-color: #aaa;
 }
 
-h1 {
-  font-weight: normal;
-  font-size: 17pt;
+.header { font-weight: normal; }
+
+.selflink { text-decoration: underline; }
+
+.pageheader .actions ul,
+#sitemeta {
+  border-top: solid 1px;
+  border-bottom: solid 1px;
+  font-size: small;
+  border-color: #aaa;
+  background: #eee;
 }
-h2 {
-  font-weight: normal;
-  font-size: 16pt;
+.actions ul {
+  padding: 1px;
+  margin-top: 5px;
 }
-h3 {
-  font-weight: normal;
-  font-size: 15pt;
+#sitemeta {
+  padding: 0;
+  margin-bottom: 5px;
 }
-h4 {
-  font-weight: normal;
-  font-size: 14pt;
+#backlinks,
+.tags {
+  margin-top: 0;
+  margin-bottom: 0;
 }
-h5 {
-  font-weight: normal;
-  font-size: 13pt;
+
+#pageinfo {
+  border: none;
 }
-h6 {
-  font-weight: normal;
-  font-size: 12pt;
+
+#searchform div:before {
+  font-size: small;
+  content: "search:";
+}
+#searchform input {
+  border-top: none;
+  border-bottom: none;
+  vertical-align: bottom;
+  margin-right: 7px;
 }
 
-div.inlinepage > span.header > a {
-  float: right;
-  display: block;
-  font-size: 11pt;
-  font-weight: normal;
-  margin: 0;
+#sidebar {
+  border: solid;
+  border-width: 1px;
   padding: 0;
+  margin-top: 15px;
+  border: 1px solid;
+  border-color: #aaa;
+  background: #eee;
+  width: 16ex;
 }
-div.inlinepage > span.header > a:before {
-  content: "permalink: ";
-  font-size: smaller;
-  text-decoration: none;
-  font-style: italic;
+#sidebar ul {
+  margin: 0;
+  padding-left: 1em;
+  list-style-type: none;
 }
-
-div.inlinepage {
-  margin-bottom: 10px;
+#sidebar ul ul {
+  padding-left: 1.5em;
+  font-size: 90%;
 }
 
-div.inlinepage h1 {
-  font-weight: normal;
-  font-size: 14pt;
+#pageinfo,
+#footer {
   margin: 0;
 }
-div.inlinepage h2 {
-  font-weight: normal;
-  font-size: 13pt;
-  margin: 0;
+#pageinfo {
+  font-size: small;
 }
-div.inlinepage h3 {
-  font-weight: normal;
-  font-size: 12pt;
+.pagecopyright,
+.pagelicense,
+.pagedate {
   margin: 0;
+  display: inline;
 }
-div.inlinepage h4 {
-  font-weight: normal;
-  font-size: 11pt;
-  margin: 0;
+#backlinks {
+  margin-top: 5px;
+  margin-bottom: 10px;
+  font-size: larger;
 }
-div.inlinepage h5 {
-  font-weight: normal;
-  font-size: 11pt;
-  margin: 0;
+.validation {
+  display: inline;
+  float: right;
 }
-div.inlinepage h6 {
-  font-weight: normal;
-  font-size: 11pt;
-  margin: 0;
+
+.pagecloud {
+  margin-left: 5px;
 }
 
-div#blogform {
-  padding: 0px 5px;
-  margin-bottom: 10px;
+table.identikit tr th {
+  text-align: right;
+  vertical-align: top;
+}
+table.identikit tr th:after {
+  content: ":";
+}
+table.identikit tr td {
+  text-align: left;
+  vertical-align: top;
 }
 
-pre {
-  width: 90%;
-  font-size: 10pt;
-  font-family: monospace;
-  background: #e1e1e1;
-  margin-left: 4%;
-  padding-top: 5px;
-  padding-bottom: 5px;
+.doi_logo , .doi_logo a {
+    background: #3965bd;
+    color: white !important;
+    font-size: 80%;
+    text-decoration: none;
+    font-family: times;
+    font-weight: bold;
+    padding: 0px 1px 0px 2px;
 }
 
-.pagecloud {
-  width: 25%;
-  border-top: 1px solid #aaa;
-  border-bottom: 1px solid #aaa;
-  background: #eee;
-  color: black !important;
+#comments {
+    margin-top: 5ex;
+    border-top: solid 1px;
+    border-color: #aaa;
+    font-size: small;
+}
+
+#comments #feedlink {
+    text-align: right;
+}
+#comments #feedlink:before {
+    content: "comment feeds: ";
+}
+
+.addcomment {
+    padding: 5px;
+    font-style: italic;
+}
+
+.comment {
+    border: none;
+    background-color: #eee;
+    margin: 5px;
+    margin-top: 10px;
+}
+
+.comment-subject {
+    font-style: normal;
 }
 
-.pagecloud a {
-  text-decoration: none;
+.comment-header {
+    border-top: solid 1px;
+    border-color: #aaa;
+    text-align: right;
+    font-style: normal;
 }
index f3f0a004b08cd851c157fc8c02728fc929513c03..015c87f1b36e0846e880165bf1dde055fdc46fe2 100644 (file)
@@ -10,12 +10,7 @@ Installation steps and requirements are listed on the [[install]] page.
 
 ## packages
 
-If using Debian (since 4.0), or Ubuntu (since 6.10):
-[[template id=note text="""
-Note that Debian 4.0 and especially Ubuntu 6.10 contain older versions of
-ikiwiki, there have been lots of enhancements and bug fixes since those
-versions.
-"""]]
+To install with apt, if using Debian or Ubuntu:
 
         apt-get install ikiwiki
 
@@ -24,14 +19,25 @@ Or download the deb from <http://packages.debian.org/unstable/web/ikiwiki>.
 There is a backport of a recent version of ikiwiki for Debian 4.0 at
 <http://packages.debian.org/etch-backports/ikiwiki>.
 
-There is also an unofficial backport of ikiwiki for Ubuntu Gutsy
-and Ubuntu Hardy, provided by Paweł Tęcza,
+Fedora versions 8 and newer have RPMs of ikiwiki available.
+
+There is also an unofficial backport of ikiwiki for Ubuntu Jaunty, provided by
+[[Paweł_Tęcza|users/ptecza]],
 at [http://gpa.net.icm.edu.pl/ubuntu/](http://gpa.net.icm.edu.pl/ubuntu/index-en.html).
 
-Also, FreeBSD has ikiwiki in its
+NetBSD and many other platforms: pkgsrc has an [ikiwiki package](ftp://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/www/ikiwiki/README.html).
+
+FreeBSD has ikiwiki in its
 [ports collection](http://www.freshports.org/www/ikiwiki/).
 
-And Gentoo has an [ebuild](http://bugs.gentoo.org/show_bug.cgi?id=144453) in its bug database. 
+Gentoo has an [ebuild](http://bugs.gentoo.org/show_bug.cgi?id=144453) in its bug database. 
+
+The [openSUSE Build Service](http://software.opensuse.org/search?baseproject=ALL&p=1&q=ikiwiki) has packages for openSUSE
+
+IkiWiki can be installed [from macports](http://www.macports.org/ports.php?by=name&substr=ikiwiki)
+by running `sudo port install ikiwiki`.
+
+A [PKGBUILD for Arch Linux](http://aur.archlinux.org/packages.php?ID=12284) is in the AUR.
 
 ## revision control
 
index 14e9b3804cb79185ebcd9fd6fd1936936ccebc88..2155d7feab627bb733b681eb2f494678b0b8f0c5 100644 (file)
@@ -1,18 +1,25 @@
 This is an [[example_blog|index]]. Just copy the blog subdirectory into
-your wiki to quickly get started blogging with ikiwiki.
+your wiki to quickly get started blogging with ikiwiki. 
 
-Some additional configuration you might want to do:
+Or, run this command to set up a blog with ikiwiki.
+
+       % ikiwiki -setup /etc/ikiwiki/auto-blog.setup
 
-* Change the name of the blog, by editing `index.mdwn` and changing
-  the `title`.
+Some additional configuration you might want to do:
 
 * Make sure to configure ikiwiki to generate RSS or Atom feeds.
 
 * Make sure you have the tag plugin enabled, and tag posts using it. An
   example of how to tag a post is:
-       \[[tag tags/life]]
+       \[[!tag tags/life]]
+
+* Enable the [[sidebar|plugins/sidebar]] plugin to get a sidebar listing all
+  the categories you've tagged posts with.
+
+* Enable the [[pagestats|plugins/pagestats]] plugin to get a tag cloud
+  to display on the [[index]].
 
-* Enable the sidebar plugin to get a sidebar listing all the categories
-  you've tagged posts with.
+* Enable the [[comments|plugins/comments]] plugin and configure it to
+  enable comments to posts to the blog:
 
-* Enable the pagestats plugin to get a tag cloud display on the [[index]].
+       comments_pagespec => 'blog/posts/* and !*/Discussion',
index b0514d575e105d2c6739e413742023414a7c639a..84c732dd1ea24a8f63a5068e0c2c15372c25cb5f 100644 (file)
@@ -1,14 +1,13 @@
-[[meta title="example blog"]]
+[[!pagestats pages="./tags/*"]]
 
-[[pagestats pages="./tags/*"]]
+Welcome to my blog.
 
-Welcome to my blog. Have a look at the most recent posts below, or
-browse the tag cloud on the right. An archive of all [[posts]] is also
-available.
+Have a look at the most recent posts below, or browse the tag cloud on the
+right. An archive of all [[posts]] is also available.
 
-[[inline pages="./posts/* and !*/Discussion" show="10"
-actions=yes rootpage="./posts"]]
+[[!inline pages="./posts/* and !*/Discussion" show="10"
+actions=yes rootpage="posts"]]
 
 ----
 
-This wiki is powered by [ikiwiki](http://ikiwiki.info).
+This blog is powered by [ikiwiki](http://ikiwiki.info).
index 71eb9f1b16656b7a9ae52894dbfab5aadfcc130a..4b2939120ef75b2b3a505d6290109d102de9c008 100644 (file)
@@ -1,3 +1,3 @@
 Here is a full list of posts to my [[blog|index]].
 
-[[inline pages="./posts/* and !*/Discussion" archive=yes feedshow=10 quick=yes]]
+[[!inline pages="./posts/* and !*/Discussion" archive=yes feedshow=10 quick=yes]]
index f8a698801a93707fb3900aea95a01a5838b7ef02..d4943234109a3cef652c1303dd118772d54b0434 100644 (file)
@@ -1,4 +1,4 @@
 This is the first post to this example blog. To add new posts, just add
-files to the blog/posts/ subdirectory, or use the web form.
+files to the posts/ subdirectory, or use the web form.
 
-[[tag tags/tech]]
+[[!tag tags/tech]]
index 19475d7c73875b7641d2f69b3ce8d6b9cce61816..a9fac388ea953f6f973dedde8e247e31c441721c 100644 (file)
@@ -4,4 +4,4 @@ Example sidebar
 * [[Archive|posts]]
 
 Categories:
-[[map pages="./tags/* and !*/Discussion"]]
+[[!map pages="./tags/* and !*/Discussion"]]
index daf77549afcd4cf8fedb46702e55942d075f407f..53cc8d368b599795bc1eacea1ab47df73b994fc0 100644 (file)
@@ -1,3 +1,3 @@
-[[pagestats pages="./tags/*"]]
+[[!pagestats pages="./tags/*"]]
 
 On the right you can see the tag cloud for this blog.
index 2f7a573795216a815b8e840cb55fb49584dfd2ea..719f2b19222c812c31807e627bb35458e4425cc4 100644 (file)
@@ -1,4 +1,4 @@
 This feed contains pages in the "life" category.
 
-[[inline pages="link(tags/life) and ./posts/* and !*/Discussion"
+[[!inline pages="link(tags/life) and !*/Discussion"
 show="10" actions=yes]]
index dff92f333666a3fa2ba43672647c822f5322c839..e811cac34ab6f0a2fe482d4cbb868daec30289fa 100644 (file)
@@ -1,3 +1,3 @@
 This feed contains pages in the "tech" category.
 
-[[inline pages="link(tags/tech) and !*/Discussion" show=10 actions=yes]]
+[[!inline pages="link(tags/tech) and !*/Discussion" show=10 actions=yes]]
index ad8d6cdb4a3beac38ddc5ff4b806dfe8b8a6ddc3..46ead2b62ae9f3795eaa34dccb9b68eba491bbee 100644 (file)
@@ -1,4 +1,4 @@
 This is FooBar's bug list. Link bugs to [[bugs/done]] when done.
 
-[[inline pages="./bugs/* and !./bugs/done and !link(done) 
+[[!inline pages="./bugs/* and !./bugs/done and !link(done) 
 and !*/Discussion" actions=yes postform=yes show=0]]
index af88c1c7c307aa0460dc3f0c9adbbbbcc112db6c..ad332e2a2687eb2e4378777d86457ba32b854c8a 100644 (file)
@@ -1,3 +1,3 @@
 recently fixed [[bugs]]
 
-[[inline pages="./* and link(./done) and !*/Discussion" sort=mtime show=10]]
+[[!inline pages="./* and link(./done) and !*/Discussion" sort=mtime show=10]]
index 249c6f77907b1024abdf7543908526824566a9cf..fe0c3eff04132915ea737e5095c7e0f6b3124985 100644 (file)
@@ -1,6 +1,6 @@
 FooBar frequently asked questions.
 
-[[toc ]]
+[[!toc ]]
 
 ## Is this a real program?
 
index e2d180d1fc1b609c28dba237ddda74c29776a9b3..e03a969a03918f178c34f907652cc7821df0a479 100644 (file)
@@ -1,7 +1,7 @@
 FooBar is an amazing example program that does not exist. Use it for all
 your example program needs. This is its wiki.
 
-* [[download]]
+* **[[download]]**
 * [[news]]
 * [[documentation|doc]]
 * [[bugs]]
index 20642c203e3d85667a3fcee2365b3ab5bda41d8f..9b53c7d99c186b288441e7863d4588afd3facf27 100644 (file)
@@ -2,4 +2,4 @@ This is where annoucements of new releases, features, and other news is
 posted. FooBar users are recommended to subscribe to this page's RSS
 feed.
 
-[[inline pages="./news/* and !*/Discussion" rootpage="news" show="30"]]
+[[!inline pages="./news/* and !*/Discussion" rootpage="news" show="30"]]
index 759decb4032523df2ad8b9ea99d560281314d80a..ac7ff93c7f79d7c07b463060ced263e0c2c1fac6 100644 (file)
@@ -3,5 +3,5 @@
 <TMPL_VAR news>
 
 </TMPL_IF>
-FooBar <TMPL_VAR version> released with [[toggle text="these changes" id="changelog"]]
-[[toggleable id="changelog" text="""<TMPL_VAR changelog>"""]]
+FooBar <TMPL_VAR version> released with [[!toggle text="these changes" id="changelog"]]
+[[!toggleable id="changelog" text="""<TMPL_VAR changelog>"""]]
index df963ab4f3ea7908d5cc0d2da2816f43862ee37e..3925d78ef41089dd3cc5dc1c93f957adff6bc340 100644 (file)
@@ -1,12 +1,13 @@
 An overview of some of ikiwiki's features:
-[[toc ]]
+[[!toc ]]
 
 ## Uses a real RCS
 
 Rather than implement its own system for storing page histories etc,
-ikiwiki uses a real Revision Control System. This isn't (just) because we're
-lazy, it's because a real RCS is a good thing to have, and there are
-advantages to using one that are not possible with a standard wiki.
+ikiwiki uses a real [[Revision_Control_System|rcs]]. This isn't (just)
+because we're lazy, it's because a real RCS is a good thing to have, and
+there are advantages to using one that are not possible with a standard
+wiki.
 
 Instead of editing pages in a stupid web form, you can use vim and commit
 changes via [[Subversion|rcs/svn]], [[rcs/git]], or any of a number of other
@@ -15,6 +16,10 @@ changes via [[Subversion|rcs/svn]], [[rcs/git]], or any of a number of other
 ikiwiki can be run from a [[post-commit]] hook to update your wiki
 immediately whenever you commit a change using the RCS.
 
+It's even possible to securely let
+[[anonymous_users_git_push_changes|tips/untrusted_git_push]]
+to the wiki.
+
 Note that ikiwiki does not require a RCS to function. If you want to
 run a simple wiki without page history, it can do that too.
 
@@ -32,7 +37,7 @@ Any page with a filename ending in ".mdwn" is converted from markdown to html
 by ikiwiki. Markdown understands text formatted as it would be in an email,
 and is quite smart about converting it to html. The only additional markup
 provided by ikiwiki on top of regular markdown is the [[ikiwiki/WikiLink]] and 
-[[ikiwiki/PreprocessorDirective]].
+the [[ikiwiki/directive]].
 
 If you prefer to use some other markup language, ikiwiki allows others to
 easily be added by [[plugins]]. For example it also supports traditional
@@ -47,7 +52,7 @@ program, or other special file and link to it from your wiki pages.
 
 ## Blogging
 
-You can turn any page in the wiki into a [[ikiwiki/blog]]. Pages matching a
+You can turn any page in the wiki into a [[blog]]. Pages matching a
 specified [[ikiwiki/PageSpec]] will be displayed as a weblog within the blog
 page. And RSS or Atom feeds can be generated to follow the blog.
 
@@ -72,12 +77,11 @@ can change the look and layout of all pages in any way you would like.
 
 ## [[Plugins]]
 
-Plugins can be used to add additional features to ikiwiki. The interface
-is quite flexible, allowing plugins to implement additional markup
-languages, register [[ikiwiki/PreProcessorDirective]]s, hook into [[CGI]] mode,
-and more. Most of ikiwiki's features are actually provided by plugins.
-Ikiwiki's backend RCS support is also pluggable, so support for new
-revision control systems can be added to ikiwiki.
+Plugins can be used to add additional features to ikiwiki. The interface is
+quite flexible, allowing plugins to implement additional markup languages,
+register [[directives|ikiwiki/directive]], provide a [[RCS]] backend, hook
+into [[CGI]] mode, and much more. Most of ikiwiki's features are actually
+provided by plugins.
 
 The standard language for ikiwiki plugins is perl, but ikiwiki also supports
 [[plugins/write/external]] plugins: Standalone programs that can be written in
@@ -142,14 +146,15 @@ authentication, or other methods implemented via plugins.
 
 Thanks to subpages, every page can easily and automatically have a
 /Discussion subpage. By default, these links are included in the
-[[templates]] for each page.
+[[templates]] for each page. If you prefer blog-syle
+[[plugins/comments]], that is available too.
 
 ### Edit controls
 
-Wiki admins can [[lock_pages|page_locking]] so that only other admins can
-edit them. Or a wiki can be set up to allow anyone to edit Discussion
-pages, but only registered users to edit other pages. These are just two
-possibilities, since page edit controls can be changed via plugins.
+Wiki admins can lock pages so that only other admins can edit them. Or a
+wiki can be set up to allow anyone to edit Discussion pages, but only
+registered users to edit other pages. These are just two possibilities,
+since page edit controls can be changed via plugins.
 
 ### [[PageHistory]]
 
@@ -161,6 +166,11 @@ Well, sorta. Rather than implementing YA history browser, it can link to
 ikiwiki can use the xapian search engine to add powerful
 full text [[plugins/search]] capabilities to your wiki.
 
+### Translation via po files
+
+The [[plugins/po]] plugin allows translating individual wiki pages using
+standard `po` files.
+
 ### [[w3mmode]]
 
 Can be set up so that w3m can be used to browse a wiki and edit pages
index cced9636b68dfbe1b229232f4806e6eea8be9202..729540774e734bea1df5d5140ce0d6783b0a2252 100644 (file)
@@ -4,5 +4,5 @@ _This is a bold experiment by me, since I have exactly such a question. This ove
 
 ## Current topics ##
 
-[[inline pages="forum/*  and !forum/discussion and !forum/*/*" 
-actions=yes rootpage="forum" postformtext="Add a new thread titled:" show=0]]
+[[!inline pages="forum/*  and !forum/discussion and !forum/*/*" 
+archive=yes rootpage="forum" postformtext="Add a new thread titled:" show=0]]
diff --git a/doc/forum/Accessing_meta_values_in_pages__63__.mdwn b/doc/forum/Accessing_meta_values_in_pages__63__.mdwn
new file mode 100644 (file)
index 0000000..78594f9
--- /dev/null
@@ -0,0 +1,8 @@
+If I set a meta value on a page (lets say \[[!meta author="Adam Shand"]] is there some way to retrieve the value of author and put it somewhere visible on the page?  Eg. can I write:
+
+author: $author
+
+I know I can update the raw templates but it'd be nice to be able to do this in the pages them selves.
+
+Cheers,
+Adam.
diff --git a/doc/forum/Adding_new_markup_to_markdown.mdwn b/doc/forum/Adding_new_markup_to_markdown.mdwn
new file mode 100644 (file)
index 0000000..39d233a
--- /dev/null
@@ -0,0 +1,11 @@
+I'm using ikiwiki to manage my personal wiki. One of the things I'm toying with is storing my grocery list in a wiki. The way I typically grocery-shop is to make one huge master list containing all the items I typically buy in a single cycle. Then, on any given trip, I make a subset list containing only the items I need. I'd like to streamline this process by making the master list a series of checkboxes. Before each trip, I load the list page on my phone, check off all the items I already have, then check off individual items as I get them.
+
+I'm not sure if there's a convenient way of adding checkboxes to wiki pages, and after a bit of thought I decided that "( )" would be a good markup for this. Ideally I'd like to still have access to other markdown conventions so I could, say, organize the list with headings and such when it grows large, so I don't want to create an entirely separate format, or a separate copy of the markdown plugin.
+
+Is there an existing means of, say, adding supersets to wiki markup? I suppose I could use an inline directive that inserts a multisellect HTML element, but I really like ( ). :)
+
+Ideal would be some sort of filter infrastructure. Plugins could register with a larger filter plugin that adds an inline directive. I could then invoke the checkbox filter at the top of my grocery list, and all instances of ( ) would be replaced with HTML. Might also make sense for the individual filters to specify whether or not they're invoked before or after the page template, or perhaps just always invoke them after. *shrug*
+
+Does something like this exist? I'd really like to avoid messing around with raw HTML or an inline for each of 40-50 list items. :)
+
+-- [[Nolan]]
diff --git a/doc/forum/Can_OpenID_users_be_adminusers__63__.mdwn b/doc/forum/Can_OpenID_users_be_adminusers__63__.mdwn
new file mode 100644 (file)
index 0000000..7599e71
--- /dev/null
@@ -0,0 +1,69 @@
+I've just finished an upgrade to 3.141 and am trying to give myself admin rights to play with the new webadmin features.  My login is via OpenID but from reading on the wiki I believe that OpenID users should be able to be granted admin rights.  However I'm obviously doing something wrong as when I click on the "Preferences" link at the top of the page I don't see any admin features.
+
+My login is: http://adam.shand.net/
+
+In .ikiwiki/userdb I see:
+
+> adam@shand.net
+> email <br>
+> password <br>
+> locked_pages <br>
+> banned <br>
+> 1229722296 <br>
+> regdate <br>
+> http://adam.shand.net/ <br>
+
+And in my config file I have:
+
+> adminuser => [qw{http://adam.shand.net/}],
+
+Any pointers to what I'm doing wrong would be much appreciated.
+
+Thanks,
+Adam.
+
+> This is certianly supposed to work. For example, the admin
+> user on my ikiwikis is `http://joey.kitenet.net/`
+> 
+> The only caveat I know of to make it work is that the 
+> adminuser openid url has to exactly match the openid url that
+> ikiwiki sees when you log in. Including any trailing slash,
+> and the `http://`. --[[Joey]] 
+>> Hrm, it's not working.  I'm sure I've made a silly mistake somewhere but
+>> I've looked and looked and just can't find it.  Any suggestions on where
+>> to look for debugging information would be much appreciated. -- [[Adam]]
+
+>>> Well, you could use this patch to add debugging info about admin
+>>> username comparisons:
+
+<pre>
+diff --git a/IkiWiki/UserInfo.pm b/IkiWiki/UserInfo.pm
+index 0bf100a..77b467a 100644
+--- a/IkiWiki/UserInfo.pm
++++ b/IkiWiki/UserInfo.pm
+@@ -71,6 +71,8 @@ sub userinfo_setall ($$) {
+ sub is_admin ($) {
+       my $user_name=shift;
++      print STDERR "is_admin test @{$config{adminuser}} vs $user_name: ".(grep { $_ eq $user_name } @{$config{adminuser}})."\n";
++
+       return grep { $_ eq $user_name } @{$config{adminuser}};
+ }
+</pre>
+
+>>>> After applying that change to what is probably
+>>>> `/usr/share/perl5/IkiWiki/UserInfo.pm` on your system, 
+>>>> when you go to the preferences page it should log in your web server's
+>>>> error.log, something like this:
+
+       [Wed Jul 08 12:54:35 2009] [error] [client 127.0.1.1] is_admin test http://joey.kitenet.net/ vs http://joey.kitenet.net/: 1
+
+>>>> So you can see if the two usernames/openids match. If the end is "0",
+>>>> they don't match. If nothing is logged, you have not enabled the websetup plugin.
+>>>> If the end if "1" you should see the "Wiki Setup" button, if not the
+>>>> problem is not in determining if you're an admin, but elsewhere..
+>>>> --[[Joey]]
+
+I was being incredibly stupid and missed that websetup is a **plugin** and thus needed to be enabled.  Many thanks for your patient assistance, by helping me eliminate the unlikely it eventually led me to the obvious.  Cheers.  -- [[Adam]]
diff --git a/doc/forum/Darcs_as_the_RCS___63__.mdwn b/doc/forum/Darcs_as_the_RCS___63__.mdwn
new file mode 100644 (file)
index 0000000..9664240
--- /dev/null
@@ -0,0 +1,13 @@
+Hi,
+
+I have successfully installed and set up my first instance of [[ikiwiki]] on my dedicated server. Following [[joey]]'s screencasts made this easy (thank you).
+
+Currently, I have set up the RCS to be git but I do not like this very much. I'd rather want darcs but if I replace rcs settings, it fails.
+
+What should I put in the configuration file to use darcs ?
+
+> Darcs is not yet supported. It's being [[worked_on|todo/darcs]].
+
+> > That's good news for me then ! Thank you.
+
+>>> Better news: It will be in version 2.10. --[[Joey]] 
diff --git a/doc/forum/How_does_ikiwiki_remember_times__63__.mdwn b/doc/forum/How_does_ikiwiki_remember_times__63__.mdwn
new file mode 100644 (file)
index 0000000..5522cbf
--- /dev/null
@@ -0,0 +1,89 @@
+This is similar to the last post in this forum. I want to know exactly how ikiwiki remembers the times associated with pages, especially when using it for blogging, so I know whether I can trust it or not. From that last thread, I think what ikiwiki does is this:
+
+*   The created time of a file is when that file was first committed into the versioning repository (in my case git)
+
+    > If `--getctime` it used, yes. In normal operation, when new files
+    > are added, ikiwiki sets the creation time to the ctime of the file
+    > on disk, rather than bothering to ask the VCS. --[[Joey]] 
+
+*   The modified time of a file is what that file was last updated in the repository
+
+    > Almost right, the modified time is actually taken from the
+    > modification time of the file in disk. --[[Joey]] 
+
+And with a blog, by default, the posts are ordered by creation time, although an option can order them by modified time.
+
+Okay. So this should mean that the times are safe if, for example, I delete my working copy and then clone another one from the bare git repository, or otherwise mess up the creation times and mtimes stored as file metadata on the filesystem.
+
+Do I have it right?
+
+> Some VCS, like git, set the file mtimes to the current time
+> when making a new checkout, so they will be lost if you do that.
+> The creation times can be retrived using the `--getctime` option.
+> I suppose it might be nice if there were a `--getmtime` that pulled
+> true modification times out of the VCS, but I haven't found it a big
+> deal in practice for the last modification times to be updated to the
+> current time when rebuilding a wiki like this. --[[Joey]] 
+>
+> > Thanks for the clarification. I ran some tests of my own to make sure I understand it right, and I'm satisfied
+> > that the order of posts in my blog can be retrieved from the VCS using the `--getctime` option, at least if I
+> > choose to order my posts by creation time rather than modification time. But I now know that I can't rely on
+> > page modification times in ikiwiki as these can be lost permanently.
+> >
+> > I would suggest that there should at least be a `--getmtime` option like you describe, and perhaps that 
+> > `--getctime` and `--getmtime` be _on by default_. In my opinion the creation times and modification times of 
+> > pages in ikiwiki are part of the user's content and are important to protect, because the user may be relying 
+> > on them, especially if they use blogging or lists of recently modified pages, etc. Right now the modification
+> > times can be lost permanently.
+> >
+> > Is there a typo in the description of `--getctime` in the man page?
+> >
+> > > --getctime
+> > > Pull  **last  changed  time**  for each new page out of the revision
+> > > control system. This rarely used option provides a  way  to  get
+> > > the real creation times of items in weblogs, such as when build‐
+> > > ing a wiki from a new Subversion checkout. It is unoptimised and
+> > > quite  slow. It is best used with --rebuild, to force ikiwiki to
+> > > get the ctime for all pages.
+> >
+> > Surely it is not the _last changed time_ but the _first seen time_ of each page that is pulled out of the VCS?
+> > If the aim is to get the real creation times of items in weblogs, then the last times that the items were
+> > changed in the VCS is not going to help. -- [[seanh]]
+>>> Typo, fixed. --[[Joey]] 
+
+> > > If you want to preserve the date of a page, the best way to do it is to
+> > > use [[ikiwiki/directive/meta]] date="foo". This will survive checkouts,
+> > > VCS migrations, etc. -- [[Jon]]
+> > >
+> > > > That's a good tip Jon. That would also survive renaming a page by renaming its mdwn file, which would 
+> > > > normally lose the times also. (And in that case I think both times are irretrievable, even by 
+> > > > `--getctime`). I might start using a simple script to make blog posts that creates a file for
+> > > > me, puts today's date in the file as a meta, and opens the file in my editor.  -- [[seanh]]
+
+>>>>> I use a script that does that and also sets up templates and tags
+>>>>> for a new item:
+
+    #!/bin/sh
+    set -u
+    set -e
+
+    if [ $# -ne 1 ]; then
+        echo usage: $0 pagename >&2
+        exit 1
+    fi
+
+    pagename="$1"
+
+    if [ -e "$pagename" ]; then
+        echo error: "$pagename" exists >&2
+            exit 1
+    fi
+
+    date=$(date)
+    echo '\[[!template id=draft]]' >> "$pagename"
+    echo "\[[!meta date=\"$date\"]]" >> "$pagename"
+    echo "\[[!tag draft]]" >> "$pagename"
+    git add "$pagename"
+    $EDITOR "$pagename"
+
+>>>>> -- [[Jon]]
diff --git a/doc/forum/How_to_fix___34__does_not_map_to_Unicode__34___errors__63__.mdwn b/doc/forum/How_to_fix___34__does_not_map_to_Unicode__34___errors__63__.mdwn
new file mode 100644 (file)
index 0000000..20a4ad0
--- /dev/null
@@ -0,0 +1,20 @@
+I'm getting a number of errors like this when running ikiwiki:
+
+    utf8 "\xA2" does not map to Unicode at /usr/local/share/perl/5.10.0/IkiWiki.pm line 739, <$in> chunk 1.
+
+I think it's because some of my files contain non-utf8, non-unicode, or somehow bad characters in them, probably fancy quotes and the like that have been copy-and-pasted from my web browser. The problem is that I have hundreds of files, I transferred them all over from pyblosxom to ikiwiki at once, and the error message doesn't tell me which file the error comes from. How can I fix this?
+
+Thanks  
+-- seanh
+
+> Unfortunatly, these messages are logged by perl so there's no way to add
+> a filename to them.
+> 
+> If you run the build in --verbose mode, you should see which page ikiwiki
+> is working on, and unless it inlines some other page, you can be pretty
+> sure that page contains invalid utf-8 if the message is then printed.
+>
+> Another option is to use the `isutf8` program from 
+> [moreutils](http://kitenet.net/~joey/code/moreutils/),
+> and run it on each file, it will tell you the line number
+> and character position that is invalid. --[[Joey]] 
diff --git a/doc/forum/Is_there_a_pagespec_for_creation_dates_relative_to_today__63__.mdwn b/doc/forum/Is_there_a_pagespec_for_creation_dates_relative_to_today__63__.mdwn
new file mode 100644 (file)
index 0000000..53c70e5
--- /dev/null
@@ -0,0 +1,26 @@
+Dear users,
+
+
+using the directive inline, I want to show all pages (for example named 2008.10.2:foo.mdwn or 2009.12.3:bar.mdwn), whose date in the title are in the future. So in this example only the second one.
+
+I did not find a directive doing this in [[/ikiwiki/PageSpec]].
+
+Does somebody have an idea? I just came up with using a tag “recent” or using a separate folder. But this would be a quite some work to maintain this setup.
+
+
+Thanks,
+
+Paul
+
+> There's no such pagespec, and doing one is difficult, because such a
+> pagespec will change what it matches over time. So ikiwiki would have to
+> somehow figure out that pages matched by it yesterday no longer match,
+> and that pages containing the pagespec need to be rebuilt. Which means
+> you'd also need a cron job.
+
+>> Thank you for the explanation.
+
+> I suspect what you're trying to accomplish is
+> [[todo/tagging_with_a_publication_date]]? --[[Joey]]
+
+>> Yeah, something like that. Thanks! --[[PaulePanter]]
diff --git a/doc/forum/LaTeX_Error.mdwn b/doc/forum/LaTeX_Error.mdwn
new file mode 100644 (file)
index 0000000..587baec
--- /dev/null
@@ -0,0 +1,66 @@
+Greetings. 
+
+I am put this code in one page:
+[[!teximg code="\frac{1}{5}" alt="1/5"]]
+
+this is the configuration file ikiwiki.info:
+
+add_plugins => [qw{sidebar goodstuff textile html htmlscrubber table pagetemplate teximg map meta anonok img version textile txt}]
+
+  *Here the log*
+
+This is pdfTeXk, Version 3.141592-1.40.3 (Web2C 7.5.6) (format=latex 2008.8.4)  5 AUG 2008 10:01
+entering extended mode
+ %&-line parsing enabled.
+**/tmp/fb7742f8dd0c66473643ba40592e2be2.SBQfJo94ii/fb7742f8dd0c66473643ba40592e
+2be2.tex
+
+(/tmp/fb7742f8dd0c66473643ba40592e2be2.SBQfJo94ii/fb7742f8dd0c66473643ba40592e2
+be2.tex
+
+[...]
+
+Package scrkbase Info: You've used the obsolete option `12pt'.
+(scrkbase)             \KOMAoptions{fontsize=12pt} will be used instead.
+(scrkbase)             You should do this change too on input line 594.
+
+[...]
+
+! LaTeX Error: File `mhchem.sty' not found.
+
+Type X to quit or <RETURN> to proceed,
+or enter new name. (Default extension: sty)
+
+Enter file name: 
+! Emergency stop.
+<read *> 
+         
+l.1 ...l}\usepackage[version=3]{mhchem}\usepackage
+
+                                                  {amsmath}\usepackage{amsfo...
+
+(cannot \read from terminal in nonstop modes)
+
+Here is how much of TeX's memory you used:
+ 761 strings out of 94074
+ 10268 string characters out of 1167096
+ 66007 words of memory out of 1500000
+ 4120 multiletter control sequences out of 10000+50000
+ 3938 words of font info for 15 fonts, out of 1200000 for 2000
+ 645 hyphenation exceptions out of 8191
+ 30i,1n,28p,410b,45s stack positions out of 5000i,500n,6000p,200000b,10000s
+No pages of output.
+
+
+Some idea ?. 
+
+>> It looks like teximg uses some less standard LaTeX packages.  (see line 100 of Ikiwiki/Plugin/teximg.pm in the Ikiwiki source.)
+>> A quick work-around for an end-user would be to install the 'mhchem' LaTeX package (look in [CTAN](http://www.ctan.org/) ).
+>> A medium-term workaround would be to replace 'scrartcl' on line 100 with 'article', and delete line 101 in the teximg source.
+>> Longer term it would be nice to give teximg a configurable preamble.
+>> Hrm - maybe that configurable preamble should be a [[todo]]? -- [[users/Will]]
+
+>>>Yes it works. Thanks. I am writing some code for examples.
+
+
diff --git a/doc/forum/Let__39__s_just_rely_on_backlinks_for_this__63__.mdwn b/doc/forum/Let__39__s_just_rely_on_backlinks_for_this__63__.mdwn
new file mode 100644 (file)
index 0000000..35940cf
--- /dev/null
@@ -0,0 +1,3 @@
+Re [Let's just rely on backlinks for this?](http://git.ikiwiki.info/?p=ikiwiki;a=blobdiff;f=doc/ikiwiki/pagespec/discussion.mdwn;h=4eed3722ccc744595fc8380e68e69dc9e1ad6450;hp=f4fdd764ed61c34c09af9df046a1a134b7d0ffe6;hb=a4ce0468f6f562ad4ec749f156528aa5b3f2fe39;hpb=23a4ee6d15dbd9b8e8c6588a829dd30a26a8de32) and [2](http://git.ikiwiki.info/?p=ikiwiki;a=blobdiff;f=doc/ikiwiki/wikilink/discussion.mdwn;h=0677ff7ded6a86be7d010dfd97affdb6b266832a;hp=274c8aaf1d075adbf3b76496e1945348aefe836a;hb=4f4666c4ae5cdf5e04ac42cc52a97d90e978adb0;hpb=a4ce0468f6f562ad4ec749f156528aa5b3f2fe39):
+
+I simply didn't notice there is an "add a new bug" form at [[bugs]], so I used the obvious way to create a page through the web-interface: to put first a wikilink pointing at the new page. --Ivan Z.
diff --git a/doc/forum/Migrating_old_repository_to_new_ikiwiki_system__63__.mdwn b/doc/forum/Migrating_old_repository_to_new_ikiwiki_system__63__.mdwn
new file mode 100644 (file)
index 0000000..fe67e6a
--- /dev/null
@@ -0,0 +1,58 @@
+How do I setup an old ikiwiki repository on a new system?
+
+I have a git repository from an old ikiwiki system.
+I reformatted that hard drive, but saved the repository.
+
+I copied it the repository to my new system, which is now the "master" host.
+I installed ikiwiki on the new system.
+
+How do I set up an ikiwiki system using a pre-existing repository (instead of creating a new one)? --[[JosephTurian]]
+
+> Well, if you have:
+> * A git repository of the wiki
+> * A setup file for the wiki
+>
+> Then you should:
+> 
+> 1. Manually set up a bare git repository, and push
+>    your backed up repository to it.
+> 2. `git clone` from the bare git repository to 
+>    recreate the ikiwiki srcdir
+> 3. `git clone` from the bare git repository a second time,
+>    to create a checkout you can manually edit (optional)
+> 4. run `ikiwiki --getctime --setup your.setup`
+>    The getctime will ensure page creation times are accurate
+>    by putting the info out of the git history,
+>    and only needs to be done once.
+>
+> If you preserved your repository, but not the setup file,
+> the easiest way to make one is probably to run
+> `ikiwiki -dumpsetup` and edit the setup file. --[[Joey]] 
+
+> > I get the following errors after running ikiwiki setup:
+
+    shortcut plugin will not work without shortcuts.mdwn
+    shortcut plugin will not work without shortcuts.mdwn
+    successfully generated /home/turian/public_html/iki/ikiwiki.cgi
+    shortcut plugin will not work without shortcuts.mdwn
+    successfully generated /home/turian/repos/iki.git/hooks/post-update
+    Can't stat /usr/share/ikiwiki/basewiki/../javascript: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Plugin/autoindex.pm line 60
+    Can't stat /usr/share/ikiwiki/basewiki/../smiley: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Plugin/autoindex.pm line 60
+    Can't stat /usr/share/ikiwiki/basewiki: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Plugin/autoindex.pm line 60
+    Can't stat /usr/share/ikiwiki/basewiki/../javascript: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Render.pm line 320
+    Can't stat /usr/share/ikiwiki/basewiki/../smiley: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Render.pm line 320
+    Can't stat /usr/share/ikiwiki/basewiki: No such file or directory
+     at /home/turian/utils//lib/perl5/site_perl/5.8.8//IkiWiki/Render.pm line 320
+    internal error: smileys.mdwn cannot be found in /home/turian/iki or underlay
+
+> > How do I resolve these errors? I have my PERL5LIB location set correctly.
+
+>>> Well, that's unrelated to the original question, but
+>>> I guess you should set `underlaydir` in your setup file to
+>>> point to whereever you have installed the basewiki directory.
+>>> --[[Joey]] 
diff --git a/doc/forum/Sidebar_with_links__63__.mdwn b/doc/forum/Sidebar_with_links__63__.mdwn
new file mode 100644 (file)
index 0000000..790ee85
--- /dev/null
@@ -0,0 +1,58 @@
+I'm trying to create a template to use as a sidebar with links. The template will be static
+(no variables are used). I first created a page with this directive: \[[!template id=sidebar]],
+and then created the template with the web interface.
+
+This is the code I put in the template:
+
+    <div class="infobox">
+    <ul>
+    <li>\[[Existing internal link|exists]]</li>
+    <li>\[[Non-existing internal link|doesnotexist]]</li>
+    <li>[External link](http://google.com/)</li>
+    </ul>
+    <http://google.com/>
+    </div>
+
+This is the relevant part of the resulting html file `template/sidebar.html`:
+
+    <div class="infobox">
+    <ul>
+    <li><a href="../exists.html">Existing internal link</a></li>
+    <li><span class="createlink"><a href="http://localhost/cgi-bin/itesohome.cgi?page=doesnotexist&amp;from=templates%2Fsidebar&amp;do=create" rel="nofollow">?</a>Non-existing internal link</span></li>
+    <li>[External link](http://google.com/)</li>
+    </ul>
+    </div>
+
+Note that the `<http://google.com/>` link has disappeared, and that `[External link](http://google.com/)`
+has been copied literally instead of being converted to a link, as I expected.
+
+> Templates aren't Markdown page. [[ikiwiki/WikiLink]] only are expanded. --[[Jogo]]
+
+>> Thanks for the help Jogo. Looking at the [[templates]] page, it says that
+"...you can include WikiLinks and all other forms of wiki markup in the template." I read this
+to mean that a template may indeed include Markdown. Am I wrong in my interpratation? --[[buo]] 
+
+>> I discovered that if I eliminate all html from my sidebar.mdwn template, the links are
+rendered properly. It seems that the mix of Markdown and html is confusing some part of
+Ikiwiki. --[[buo]]
+
+Worse, this is the relevant part of the html file of the page that includes the template:
+
+    <div class="infobox">
+    <ul>
+    <li><span class="selflink">Existing internal link</span></li>
+    <li><span class="createlink"><a href="http://localhost/cgi-bin/itesohome.cgi?page=doesnotexist&amp;from=research&amp;do=create" rel="nofollow">?</a>Non-existing internal link</span></li>
+    <li>[External link](http://google.com/)</li>
+    </ul>
+    </div>
+
+Note that the `Existing internal link` is no longer a link. It is only text.
+
+What am I doing wrong? Any help or pointers will be appreciated. --[[buo]]
+
+-----
+
+I think I have figured this out. I thought the template was filled and then
+processed to convert Markdown to html. Instead, the text in each variable is
+processed and then the template is filled. I somehow misunderstood the 
+[[templates]] page. -- [[buo]]
diff --git a/doc/forum/What_is_wrong_with_my_recentchange_page___63__.mdwn b/doc/forum/What_is_wrong_with_my_recentchange_page___63__.mdwn
new file mode 100644 (file)
index 0000000..4914cba
--- /dev/null
@@ -0,0 +1,13 @@
+Hi again,
+
+I have finally finished my setup *but* I still have a problem with RecentChanges page.
+
+Can somebody check it for me at [http://maillard.mobi/~xma/wiki/recentchanges/] and tell what is wrong ?
+
+Thank you.
+
+--[[xma]]
+
+> Looks to me like you don't have the meta plugin enabled. --[[Joey]]
+
+> > You are right. Now all is ok. --[[xma]]
diff --git a/doc/forum/appear_if_you_are_login_or_not_in_a_page.mdwn b/doc/forum/appear_if_you_are_login_or_not_in_a_page.mdwn
new file mode 100644 (file)
index 0000000..be9854a
--- /dev/null
@@ -0,0 +1,36 @@
+Hi,
+
+Can you give me a hint for showing if one user is logged or not. If user is logged, then I want to display the user name, as wikipedia or dokuwiki for example.
+Regards,
+Xan.
+
+> ikiwiki doesn't serve pages, so this can't be done inside ikiwiki.
+> For certain kinds of authentication it might be possible anyway.
+> For instance, if you're using [[plugins/httpauth]] exclusively and
+> your server has PHP, you could put `<?php print("$REMOTE_USER");
+> ?>` in all the relevant ikiwiki [[templates]] and arrange for the
+> generated HTML pages to get run through the PHP interpreter. The trick
+> would work differently with other [[plugins/type/auth]] plugins,
+> if at all. --[[Schmonz]]
+
+>> Thanks a lot, Xan.
+
+>>> Another possible trick would be to use some Javascript to make a
+>>> "who am I?" AJAX request to the CGI (the CGI would receive the
+>>> session cookie, if any, and be able to answer). Obviously, this
+>>> wouldn't work for users who've disabled Javascript, but since it's
+>>> non-essential, that's not so bad. You'd need to
+>>> [[write_a_plugin|plugins/write]] to add a suitable CGI action,
+>>> perhaps ?do=whoami, and insert the Javascript. --[[smcv]]
+
+>>>> It's an idea, but you're trading off a serious speed hit for a very
+>>>> minor thing. --[[Joey]]
+
+>>>> Cool idea. A similar trick (I first saw it
+>>>> [here](http://www.peej.co.uk/articles/http-auth-with-html-forms.html))
+>>>> could be used to provide a [[plugins/passwordauth]]-like login form
+>>>> for [[plugins/httpauth]]. --[[Schmonz]]
+
+>>>>> I always assumed the entire reason someone might want to use the
+>>>>> httpauth plugin is to avoid nasty site-specific login forms..
+>>>>> --[[Joey]] 
diff --git a/doc/forum/bashman.mdwn b/doc/forum/bashman.mdwn
new file mode 100644 (file)
index 0000000..32c006b
--- /dev/null
@@ -0,0 +1,7 @@
+ [[!teximg code="\{}_pF_q(a_1,...,a_p;c_1,...,c_q;z) = \sum_{n=0}^\infty \frac{(a_1)_n\cdot\cdot\cdot(a_p)_n}{(c_1)_n\cdot\cdot\cdot(c_q)_n} \frac{z^n}{n!}"]]
+
+JAJAJA, the teximg is not loaded... :-(
+
+Bye. 
+
+> This wiki does not have teximg enabled. --[[Joey]]
diff --git a/doc/forum/chinese_character_problem.mdwn b/doc/forum/chinese_character_problem.mdwn
new file mode 100644 (file)
index 0000000..aea5570
--- /dev/null
@@ -0,0 +1,21 @@
+just finished setting up ikiwiki..
+
+I can type chinese, save and display it correctly in ikiwiki for the first time. However, when i try to edit the page again, the chinese character in the form is unrecognizable. you can see it here <http://ikiwiki.perlchina.org/>
+
+I am using the latest ikiwiki(manually installed as non-root user) and CGI::FormBuilder(3.0501) on Debian 4.0
+
+这个没问题 it is not a problem on ikiwiki website though.
+
+Thanks.
+
+
+> Is your system perhaps not configured with a utf-8 default locale? Or ikiwiki not configured to use it?
+> Make sure that some utf-8 locale is enabled (in /etc/locale.gen on Debian for example) and try setting `locale` in your > ikiwiki setup file. --[[Joey]]
+
+I have installed locales-all and locale -a shows that zh_CN.UTF-8 is installed(there is no /etc/local.gen file though). then I enabled this line "locale => 'zh_CN.UTF-8'" in my wiki setup and -setup again. but that generated lots error messages "Missing constant domain at (eval 30) line 3"
+
+sorry being a n00b on this thing  what else can I do?
+
+> See [[bugs/Missing_constant_domain_at_IkiWiki.pm_line_842]].
+> Looks like you need to upgrade to a newer version of 
+> [[!cpan Locale::gettext]] --[[Joey]] 
diff --git a/doc/forum/discussion.mdwn b/doc/forum/discussion.mdwn
new file mode 100644 (file)
index 0000000..93cf465
--- /dev/null
@@ -0,0 +1,7 @@
+I like the idea of this forum heirarchy -- but I think a map would be clearer than inlining the sub-pages. -- [[users/Jon]]
+
+> The easier way to accomplish this is to set archive=yes in the inline.
+> Switching to archive view can be useful when there are a lot of long
+> posts and people tend to want to scan by title to find interesting ones
+> and not necessarily read them all, which probably fits this forum pretty
+> well --[[Joey]]
diff --git a/doc/forum/google_openid_broken__63__.mdwn b/doc/forum/google_openid_broken__63__.mdwn
new file mode 100644 (file)
index 0000000..1be9d04
--- /dev/null
@@ -0,0 +1,30 @@
+when I login via to this wiki (or ours) via Google's OpenID, I get this error:
+
+Error: OpenID failure: no_identity_server: The provided URL doesn't declare its OpenID identity server. 
+
+Any idea how to fix this??
+
+> Google is [doing things with openid that are not in the spec](http://googledataapis.blogspot.com/2008/10/federated-login-for-google-account.html)
+> and it's not clear to me that they intend regular openid to work at all.
+> What is your google openid URL so I can take a look at the data they are
+> providing? --[[Joey]] 
+
+
+http://openid-provider.appspot.com/larrylud
+
+> I've debugged this some and filed
+> <https://rt.cpan.org/Ticket/Display.html?id=48728> on the Openid perl
+> module. It's a pretty easy fix, so I hope upstream will fix it quickly.
+> --[[Joey]] 
+
+>> A little more information here:  I'm using that same openid provider at the moment.  Note that
+>> that provider isn't google - it is someone using the google API to authenticate.  I normally have it
+>> set up as a redirect from my home page (which means I can change providers easily).
+
+    <link rel="openid.server" href="http://openid-provider.appspot.com/will.uther">
+    <link rel="openid.delegate" href="http://openid-provider.appspot.com/will.uther">
+
+>> In that mode it works (I used it to log in to make this edit).  However, when I try the openid
+>> URL directly, it doesn't work.  I think there is something weird with re-direction.  I hope this
+>> isn't a more general security hole.
+>> -- [[Will]]
diff --git a/doc/forum/ikiwiki__39__s_notion_of_time.mdwn b/doc/forum/ikiwiki__39__s_notion_of_time.mdwn
new file mode 100644 (file)
index 0000000..ee564fc
--- /dev/null
@@ -0,0 +1,35 @@
+I'm having some difficulties with ikiwiki's notion of time.
+
+For (regular) pages, the *last edited* date is the one where the file
+was indeed last modified according to the file system information.
+The *created* date (commented out in the HTML) is, at least for
+`--getctime` operation, the date, where the file was last registered
+as changed with the VCS.
+
+Now, at least with git, the thing is that when you're checking out files,
+they'll get the checkout-time's current time stamp.
+
+What I strive for is the following: *created* be the date when the file
+(under its current name) was *first* registered with the VCS (which is
+more logical in my opinion), and *last edited* be the date the file was
+last registered as changed with the VCS, which is the current
+`--getctime` *created* date.
+
+This means that I can build the HTML files from different checkouts of the
+VCS and they won't differ in the time stamps they contain in the HTML.
+
+What is the rationale for ikiwiki's current behavior with respect to these
+time stamps?
+
+--[[tschwinge]]
+
+> Presumably it's the authors of the git and mercurial backends
+> not understanding the documentation for `rcs_getctime`,
+> which states:
+> 
+>>This is used to get the page creation time for a file from the RCS, by
+>>looking it up in the history.
+> 
+> I've fixed both broken implementations to correctly look
+> up the first, not the last, commit. Other VCS do not seem
+> to have the problem. --[[Joey]] 
diff --git a/doc/forum/ikiwiki_over_database__63__.wiki b/doc/forum/ikiwiki_over_database__63__.wiki
new file mode 100644 (file)
index 0000000..a70f9c9
--- /dev/null
@@ -0,0 +1,11 @@
+Is there here any possibility to modifying ikiwiki (via plugin) for store pages in database. I'm thinking about storing pages in sqlite or mysql for serving it much faster. The idea is from sputnik.org [http://sputnik.freewisdom.org/] but with perl ;-). Could we integrate the sputnik code in ikiwiki as a solution?
+
+-----
+
+ikiwiki generates static pages in a filesystem. It's responsible for editing and regenerating them, but they're served by any old web server. If you go to the trouble of stuffing the generated pages into a database, you'll need to go to further trouble to serve them back out somehow: write your own web server, perhaps, or a module for a particular web server. Either way you'll have sacrificed ikiwiki's interoperability, and it's not at all clear (since you're adding, in the best case, one layer of indirection reading the generated files) you'll have gained any improved page-serving performance. If it's source pages you want to store in a database, then you lose the ability to do random Unixy things to source pages, including managing them in a revision control system.
+
+Static HTML pages in a filesystem and the ability to do random Unixy things are two of the uniquely awesome features of ikiwiki.  It's probably possible to do what you want, but it's unlikely that you really want it. I'd suggest you either get to know ikiwiki better, or choose one of the many wiki implementations that already works as you describe. --[[Schmonz]]
+
+---
+
+Thanks, [[Schmonz]]. You clarify me much things,.... Xan.
diff --git a/doc/forum/is_it_possible_to_NOT_add_openid2_meta_tags.mdwn b/doc/forum/is_it_possible_to_NOT_add_openid2_meta_tags.mdwn
new file mode 100644 (file)
index 0000000..e952263
--- /dev/null
@@ -0,0 +1,67 @@
+### "meta openid" problems
+
+I have add the followning to _index.mdwn_ on my site.
+
+    \[[!meta openid="http://certifi.ca/lunix"
+    server="http://certifi.ca/_serve"]]
+
+This resulted in the following being added to my site
+
+    <link href="http://certifi.ca/_serve" rel="openid.server" />
+    <link href="http://certifi.ca/_serve" rel="openid2.provider" />
+    <link href="http://certifi.ca/lunix" rel="openid.delegate" />
+    <link href="http://certifi.ca/lunix" rel="openid2.local_id" /> -->
+
+Perhaps I have done something wrong but this fails to work when I try to log in to several sites using my sites url as my login.  
+If I edit index.html and remove the two openid2 lines all works fine.  
+**Is there a way to only add openid version 1 tags to my index.html ?  
+Or a way to make it work the way it is ?** --[Mick](http://www.lunix.com.au)
+
+> Before I think about adding a way to not add the openid 2 tags,
+> I'd like to know what the problem is. Is there something
+> wrong with the tags? Does your openid provider not support
+> openid 2, and the site you are logging into sees the openid 2 tags
+> and uses it, not falling back to openid 1? 
+> 
+> Since certifi.ca is a public openid provider (run by a
+> guy I know even!), I should be
+> able to reproduce your problem if you can tell me what
+> site(s) you are trying to log into. --[[Joey]]
+
+----------
+
+I was using _phpMyID_ and its not _openid2_ compliant so I switched to certifi.ca to counteract that but I really  
+want to go back to running my own provider.  
+I can't login to identi.ca.unless I comment out the openid2 lines.(this may be there problem, I get sent to certifi.ca's site and redirected back to identi.ca)    
+I will test all the different openid enabled sites I log into today and see what happens.  
+It seems that since I have moved my site to its final location and made it live over night I am able to login to most places now.   
+I do not have a proper understanding of the inner workings of openid so not exactly sure what part is failing but I think the problem  
+lays with the consumers not falling back to the openid1 tags when they are openid1 only consumers.  --[Mick](http://www.lunix.com.au)  
+
+> So, just to clarify, certifi.ca works ok (I verified this, logging into identi.ca using it).
+> You had the problem running your own openid provider which did not support 2.0, in which case,
+> consumers seem justified in not falling back (guess; I don't know the 2.0 spec).
+> The only way this seems fixable is to add an option to meta to allow disabling openid 2. Which
+> should be easy enough to do. --[[Joey]] 
+
+I can't log into identi.ca with openid2 tags. strange. I will look at that again today.  
+Having the option to disable openid2 tags would be perfect. 
+Thanks Joey. --[Mick](http://www.lunix.com.au)
+
+>> Actually, it seems that identi.ca / certifi.ca do
+>> not interoperate when using openid2. It actually
+>> fails half the time, and succeeds half the time;
+>> seems to be picking openid1 and openid2 randomly and failing
+>> on the latter. I have emailed Evan Prodromou about this weird behavior.
+>> Not clear to me if identi.ca or certifi.ca is at fault,
+>> but luckily he runs both..
+>> --[[Joey]] 
+
+Ahh so it's not just me.  
+It's handy having contacts in the _right_ places.  --[Mick](http://www.lunix.com.au)
+
+>> ikiwiki's next release will allow adding 'delegate=1' to the 
+>> meta directive to only delegate to openid1. --[[Joey]] 
+
+## awesome.  
+--[Mick](http://www.lunix.com.au)
diff --git a/doc/forum/managing_todo_lists.mdwn b/doc/forum/managing_todo_lists.mdwn
new file mode 100644 (file)
index 0000000..0a69af8
--- /dev/null
@@ -0,0 +1,44 @@
+I keep some TODO lists on ikiwiki pages. I'm half-tempted to write a plugin
+to make ticking items off and adding items easier via the web interface. I'm
+aware though that this is not really what ikiwiki is designed for. Would
+anyone else find this useful? -- [[users/jon]]
+
+----
+
+My subsequent thoughts about how to approach this are two-fold.
+
+Firstly, a filetype for todo lists, probably OPML, but I haven't looked to see
+if there is something more suitable. A plugin that converts this source into a
+traditional page output, i.e. a DOM tree of ul or ol and li elements.
+
+Secondly, some magic javascript to make editing the list via the web page 
+more interactive: add items, strike items out, reorder items etc., without
+round-tripping to the cgi for each operation.
+
+Finally, a mechanism whereby the changes made to the page live can be
+committed back to the repository:
+
+ * ...perhaps the input → output conversion is reversible, and the HTML DOM
+   representing the list can be transformed back into the source and submitted
+   to the cgi like a regular edit: issues include the result of other
+   postprocessing: templates, wikilinks, etc.
+ * perhaps an embedded copy of the source is included in the output and the
+   javascript operates on that in tandem with the static copy
+   * perhaps the "output" is generated live by the JS at view time (with maybe
+     a plugin-generated rendered output for non JS environments)
+
+I envisage a button called "commit changes" appearing once some changes are
+made that submits the changes to the CGI, perhaps via a back channel. I'm not
+sure how to handle embeds or challenges from the CGI such as a login challenge
+(maybe the back channel would not be necessary in the first cut).
+
+> You might look at the [[plugins/hnb]] plugin. HNB supports checklists.
+> There's not a fancy web interface, but the hnb command-line program can
+> be used to edit them. --[[Joey]] 
+
+>> thanks - I'll give it a look. I spent a few hours writing some javascript to manipulate a ul/li DOM tree in an outliner-fashion the other day. I might be able to join the puzzle pieces together sometime. [[Jon]]
+
+a solution for this could be similar to a solution for [[todo/structured page data]], as todo lists are definitely a form of structured data. (in both cases, the page's current content is rendered into a html form, whose result is then saved as the page's new contents) --[[chrysn]]
+
+> Thanks for the link: yup, there's definitely some common ground there.
+> -- [[Jon]]
diff --git a/doc/forum/multi-user_setup_of_ikiwiki__44___gitosis_and_apache2_in_Debian_Sid.mdwn b/doc/forum/multi-user_setup_of_ikiwiki__44___gitosis_and_apache2_in_Debian_Sid.mdwn
new file mode 100644 (file)
index 0000000..fa8b501
--- /dev/null
@@ -0,0 +1,67 @@
+Dear developers and users,
+
+
+# Problem
+
+I am trying to set up ikiwiki for a website. Users should be able to edit pages using the webbrowser (ikiwiki.cgi) and a few should be able to edit it using versioning control and in this case Git.
+
+I have ikiwiki working for a single user (me), but I do not [[get_the_permissions_right|/rcs/Git]] for multiple users and commiters. The wiki admin does not own the Git repository in this case. And I do not understand everything yet (especially concerning wrappers).
+
+# Programs
+
+I am running Debian Etch with gitosis (0.2+20080626-2) installed from etch-backports, Apache2 (apache2.2-common 2.2.3-4+etch5) and ikiwiki (2.63) from Sid.
+
+# Goal
+
+* The website (run by ikiwiki) should be accessable via http://www.example.org/
+* Users can edit pages using the webbrowser.
+* Git is used as the backend.
+* The Git repository should be publicaly browsable via http://git.example.org/git/project.git (gitweb).
+* The Git repository can be accessed with git clone git://git.example.org/git/project.git (git-daemon).
+* Some manually set up users can push their changes over SSH to the repository and the post-update hook updates the wiki.
+
+# Directory Layout and permissions.
+
+## Website
+
+The website is stored in /srv/www/www.example.org/htdocs/ (destdir in ikiwiki.setup) and is owned by www-data:root with rights 755.
+
+## Git repository
+
+The [package gitosis](http://joey.kitenet.net/blog/entry/locking_down_ssh_authorized_keys/) creates an user gitosis with the home directory /srv/gitosis/ and the repository are stored in /srv/gitosis/repository/project.git owned by gitosis:gitosis and permissions 750. I can setup the permissions who is allowed to access this repository and if it should be published using git-daemon or gitweb in the configuration file gitosis.conf.
+
+# My efforts without results
+
+I could not come up with a working set of users which are put into different groups to create a good result with ikiwiki. The main problem is that under Debian umask is set to 022 which means that the members of a group are not allowed to write. I did not want to change this.
+
+> You can set the umask for ikiwiki itself, without changing the system umask, via the usmask setting in the setup file. --[[Joey]]
+
+In the end, I did the following. I created a directory /srv/ikiwiki/ which is owned by gitosis. The [[setup_file|/usage]] is also located there (/srv/ikiwiki/project.setup). I put the srcdir there too (srcdir => '/srv/ikiwiki/project/'). So now sudo -u gitosis ikiwiki --project.setup is able to create the post-update hook (git_wrapper => '/srv/gitosis/repositories/project.git/hooks/post-update'). Since this hook is called every time something is checked in over SSH, it is run by gitosis, so I did not set it suid. Or do I have to, because ikiwiki.cgi will be run as www-data?
+
+> Generally, ikiwiki.cgi is run as the user who owns the wiki and repository, in this case, gitosis. The ikwiiki.cgi needs to be able to write to source files in the wiki; it needs to be able to commit changes,
+> and it needs to be able to generate and write the html files. If you don't want ikiwiki.cgi to run as gitosis, you will need to put gitosis and www-data in a group and give them both write access, with appropriate umask, etc. --[[Joey]]
+
+## cgi_wrapper
+
+I do not understand those wrappers completely. The cgi is a script, which can be called by a webserver, e. g. [[Apache_2|/tips/dot_cgi]]. But www-data is normally not allowed to write to the source directory (which is owned by gitosis or push to the repository). Therefore it should be run as the user gitosis. And because cgi scripts can not be made suid, I wrapper (in this case a C program) is created (cgi\_wrapper) which can be made suid and therefore be run as the user gitosis. Is this correct?
+
+> It seems to me like you understand the wrapper pretty well. It's main reson to exist is to safely be suid, yes.
+
+So where is good place to save this wrapper? cgi_wrapper => '/srv/ikiwiki/project-wrapper'? Then /srv/ikiwiki/project-wrapper is created from a temporary C file prject-wrapper.c?
+
+
+No sudo -u gitosis ikikwiki --setup project.setup is still not able to put the compilation result into /srv/www/www.project.org/htdocs because this is owned by www-data. I just came up with two things.
+
+1. Set destdir => '/srv/ikiwiki/html-project', do ln -s /srv/ikiwiki/html-project /srv/www/www.example.org/htdocs and adduser www-data gitosis. But I am not sure about the security implications of using symbolic links.
+
+2. Since the webserver (Apache 2) has just to read the html files (is that true for static and dynamic (PHP) pages) sudo chown -R gitosis:www-data /srv/www/www.example.org/ should do it. But it is per default www-data:root under Debian, so I do not know if this should be changed.
+
+
+Could you please enlighten me. It should be possible seeing for example this site.
+
+> www-data is not really intended to own files. So that if the web server is compromised, it cannot rewrite your web site. So make the site's destdir be owned by the same user that ikiwiki runs as.
+> /srv/www is not shipped by debian; it is a bug in debian for any package to make files owned by www-data; so it seems to me that your /srv/www www-data ownership is something you must have configured yourself. --[[Joey]]
+
+Thanks in advance,
+
+--[[PaulePanter]]
diff --git a/doc/forum/perl5lib_and_wrappers.mdwn b/doc/forum/perl5lib_and_wrappers.mdwn
new file mode 100644 (file)
index 0000000..83efc7c
--- /dev/null
@@ -0,0 +1,13 @@
+I don't know if I'm doing this right...  I'm using a server provider that doesn't allow me to install into standard perl locations, so I used PREFIX to install things in my home dir.  The problem is that when the wrapper is run by the CGI server, it can't find the perl modules I installed.  There didn't seem to be a way to set the PERL5LIB from the standard config, so I added one.  Patch attached.  Or did I miss something and this was already possible?
+
+> The standard way to do it is to set `INSTALL_BASE=$HOME` when running
+> `Makefile.PL`. If you do this, ikiwiki will be built with a special `use
+> lib $HOME` line inserted, that will make it look in the specified
+> directory for perl modules.
+> 
+> The [[tips/nearlyfreespeech]] tip has an example of doing this.
+> --[[Joey]]
+
+>> Thanks!  I found that page, but didn't recognise the importance of INSTALL_BASE.
+
+>> It looks like INSTALL_BASE only appeared in version 6.31 of the Perl MakeMaker.  My provider is still running version 6.30.  Looks like I'll be keeping my patches for the moment...  sigh.
diff --git a/doc/forum/speeding_up_ikiwiki.mdwn b/doc/forum/speeding_up_ikiwiki.mdwn
new file mode 100644 (file)
index 0000000..0b21642
--- /dev/null
@@ -0,0 +1,91 @@
+My website takes a fairly long time to render. It takes a long time to do
+things like add pages, too. I'd like to try and understand what takes the
+time and what I might be able to do to speed things up.
+
+I have 1,234 objects on my site (yikes!). 717 are items under "/log" which
+I think might be the main culprit because there are some complex pagespecs
+operating in that area (e.g. log/YYYY/MM/DD, YYYY/MM and YYYY for YYYY >=
+2003, YYYY <= 2008 which include every page under log/ which was modified
+in the corresponding YYYY or YYYY/MM or YYYY/MM/DD). There is very little
+linking between the world outside of /log and that within it.
+
+I was interested in generating a graphical representation of ikiwiki's idea of
+page inter-dependencies. I started by looking at the '%links' hash using the
+following plugin:
+
+    #!/usr/bin/perl
+    package IkiWiki::Plugin::deps;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 3.00;
+    
+    
+    sub import {
+        hook(type => "format", id => "deps", call => \&fooble);
+    }
+    
+    my $hasrun = 0;
+    
+    sub fooble ($$) {
+        if(0 == $hasrun) {
+            $hasrun = 1;
+            open MYFILE, ">/home/jon/deps.dot";
+            foreach my $key (keys %links) {
+                my $arrref = $links{$key};
+                foreach my $page (@$arrref) {
+                    print MYFILE "$key -> $page;\n";
+                }
+            }
+            close MYFILE;
+        }
+    }
+    
+    1
+
+The resulting file was enormous: 2,734! This turns out to be because of the following code in scan() in Render.pm:
+
+    if ($config{discussion}) {$
+        # Discussion links are a special case since they're
+        # not in the text of the page, but on its template.
+        $links{$page}=[ $page."/".gettext("discussion") ];
+
+Worst case (no existing discussion pages) this will double the number of link
+relationships. Filtering out all of those, the output drops to 1,657. This
+number is still too large to really visualize: the graphviz PNG and PDF output
+engines segfault for me, the PS one works but I can't get any PS software to
+render it without exploding.
+
+Now, the relations in the links hash are not the same thing as IkiWiki's notion of dependencies. Can anyone point me at  that data structure / where I might be able to add some debugging foo to generate a graph of it?
+
+Once I've figured out that I might be able to optimize some pagespecs. I
+understand pagespecs are essentially translated into sequential perl code. I
+might gain some speed if I structure my complex pagespecs so that the tests
+which have the best time complexity vs. "pages ruled out" ratio are performed
+first.
+
+I might also be able to find some dependencies which shouldn't be there and
+remove the dependency.
+
+In general any advice people could offer on profiling ikiwiki would be great.
+I did wonder about invoking the magic profiling arguments to perl via the CGI
+wrapper.
+
+
+-- [[Jon]]
+
+> Dependencies go in the `%IkiWiki::depends` hash, which is not exported. It
+> can also be dumped out as part of the wiki state - see [[tips/inside_dot_ikiwiki]].
+>
+> It's a map from page name to increasingly complex pagespec, although
+> the `optimize-depends` branch in my git repository changes that to a
+> map from a page name to a *list* of pagespecs which are automatically
+> or'd together for use (this at least means duplicates can be weeded out).
+>
+> See [[todo/should_optimise_pagespecs]] for more on that.
+>
+> I've been hoping to speed up IkiWiki too - making a lot of photo albums
+> with my [[plugins/contrib/album]] plugin makes it pretty slow.
+>
+> One thing that I found was a big improvement was to use `quick=yes` on all
+> my `archive=yes` [[ikiwiki/directive/inline]]s. --[[smcv]]
diff --git a/doc/forum/understanding_filter_hooks.mdwn b/doc/forum/understanding_filter_hooks.mdwn
new file mode 100644 (file)
index 0000000..061d6d2
--- /dev/null
@@ -0,0 +1,9 @@
+Hi All;
+
+I'm trying to use a filter hook as part of making [[wikilinks|ikiwiki/wikilink]] work in [[plugins/contrib/tex4ht]].
+It seems that filter is called for every page. For my application I just want it to be called for ".tex" files, 
+but right now I have to have a look at the content, which I don't like so much.
+
+Is there a better hook to use for this? I need to transform the input before preprocessing.
+
+[[DavidBremner]] 
diff --git a/doc/forum/usedirs___38___indexpages_using_problem.mdwn b/doc/forum/usedirs___38___indexpages_using_problem.mdwn
new file mode 100644 (file)
index 0000000..05c85e2
--- /dev/null
@@ -0,0 +1,17 @@
+My ikiwiki setup file configed like:
+
+       usedirs => 0,
+       indexpages => 1,
+
+I create a directory and some .mdwn source file  /Whatis/index.mdwn and /Whatis/OSS.mdwn . The html file ikiwiki generated is
+/Whatis/index.html and /Whatis/OSS.html . 
+
+But in the page [OSS.html](http://atoz.org.cn/Whatis/OSS.html) , the auto generated link (on the page top)
+to “Whatis” is /Whatis.html file , not to /Whatis/index.html. So the link to “Whatis” is fail .
+
+Is it a bug , and how can I do for that ?
+
+> I suggest that you name your page `Whatis.mdwn`, and not
+> `Whatis/index.mdwn`. That will make ikiwiki's links work,
+> and allows you to link to the `Whatis` page by that name.
+> --[[Joey]] 
diff --git a/doc/forum/wiki_name_in_page_titles.mdwn b/doc/forum/wiki_name_in_page_titles.mdwn
new file mode 100644 (file)
index 0000000..01ff8d8
--- /dev/null
@@ -0,0 +1,26 @@
+I'd like to have the wiki name appear in page titles as in "WikiName:
+Page Title."  If I use `<TMPL_VAR WIKINAME>: <TMPL_VAR TITLE>` in the
+template this works for all pages except the index page itself which
+will have title "WikiName: WikiName" as its title.  Does anyone know
+of a template-based solution to this or do I need to write a plugin
+that provides a `IS_HOMEPAGE` template variable? --[[JasonBlevins]]
+
+> Hmm, one way to work around this is to put a meta title directive on the
+> index page. Then TITLE will be that, rather than WIKINAME, and your
+> template should work. --[[Joey]]
+
+>> I ended up writing a [path][] plugin since I had some other
+>> path-specific conditional things to include in my templates.
+>>
+>> So now I can do things like this:
+>>
+>>     <title>
+>>     <TMPL_VAR WIKINAME><TMPL_UNLESS IS_HOMEPAGE>: <TMPL_VAR TITLE></TMPL_UNLESS>
+>>     </title>
+>>
+>> But also more complicated path-specific conditionals like
+>> `IN_DIR_SUBDIR` to indicate subpages of `/dir/subdir/`.  I've got a
+>> few other small plugins brewing so I'll try to put up some contrib
+>> pages for them soon. --[[JasonBlevins]]
+
+[path]: http://code.jblevins.org/ikiwiki/plugins.git/plain/path.pm
index 653c2fe822a22bb6f63c208c547d87e31643bb21..7ac1ac6b44e8663cd5d443db9d46a66c7fa7307d 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Free Software"]]
+[[!meta title="Free Software"]]
 
 ikiwiki, and this documentation wiki, are licensed under the terms of the
 GNU [[GPL]], version 2 or later.
diff --git a/doc/freesoftware/discussion.mdwn b/doc/freesoftware/discussion.mdwn
new file mode 100644 (file)
index 0000000..e71fd29
--- /dev/null
@@ -0,0 +1,3 @@
+And where is the code, please ?
+
+> [[download]] --[[Joey]] 
index d268757cc7936c64b423a19f6cced830d77567a6..06bccc7a320c136cbe06ebf86d57d0fbec675eb3 100644 (file)
@@ -1,5 +1,12 @@
-Ikiwiki is developed in a git repository and can be checked out 
-like this:
+Ikiwiki, and this documentation wiki, are developed in a git repository and
+can be checked out like this:
+
+[[!template id=note text="""
+You can push changes back to ikiwiki's git repository over the `git://`
+transport, to update this wiki, if you'd like, instead of editing it on the
+web. Changes that could not be made via the web will be automatically
+rejected.
+"""]]
 
        git clone git://git.ikiwiki.info/
 
@@ -11,12 +18,39 @@ The gitweb is [here](http://git.ikiwiki.info/?p=ikiwiki).
 
 Commits to this git repository are fed into [CIA](http://cia.vc), and can
 be browsed, subscribed to etc on its
-[project page](http://cia.vc/stats/project/ikiwiki).
+[project page](http://cia.vc/stats/project/ikiwiki). They're also fed into
+[twitter](http://twitter.com/ikiwiki).
 
-## branches
+## personal git repositories
 
 You are of course free to set up your own ikiwiki git repository with your
-own [[patches|patch]].
+own [[patches|patch]]. If you list it here, the `gitremotes` script will
+automatically add it to git remotes. Your repo will automatically be pulled
+into [[Joey]]'s working tree. This is recommended. :-)
+
+<!-- Machine-parsed format: * wikilink <git:url> -->
+
+* github `git://github.com/joeyh/ikiwiki.git`
+  ([browse](http://github.com/joeyh/ikiwiki/tree/master))  
+  A mirror of the main repo, automatically updated.
+* l10n `git://l10n.ikiwiki.info/`
+  Open push localization branch used for <http://l10n.ikiwiki.info/>
+* [[smcv]] `git://git.pseudorandom.co.uk/git/smcv/ikiwiki.git`
+* [[intrigeri]] `git://gaffer.ptitcanardnoir.org/ikiwiki.git`
+* [[gmcmanus]] `git://github.com/gmcmanus/ikiwiki.git`
+* [[jelmer]] `git://git.samba.org/jelmer/ikiwiki.git`
+* [[hendry]] `git://webconverger.org/git/ikiwiki`
+* [[jon]] `git://github.com/jmtd/ikiwiki.git`
+* [[ikipostal|DavidBremner]] `git://pivot.cs.unb.ca/git/ikipostal.git`
+* [[ikimailbox|DavidBremner]] `git://pivot.cs.unb.ca/git/ikimailbox.git`
+* [[ikiplugins|DavidBremner]] `git://pivot.cs.unb.ca/git/ikiplugins.git`
+* [[jonas|JonasSmedegaard]] `git://source.jones.dk/ikiwiki-upstream`
+* [[arpitjain]] `git://github.com/arpitjain11/ikiwiki.git`
+* [[chrysn]] `git://github.com/github076986099/ikiwiki.git`
+* [[simonraven]] `git://github.com/kjikaqawej/ikiwiki-simon.git`
+* [[schmonz]] `git://github.com/schmonz/ikiwiki.git`
+
+## branches
 
 Some of the branches included in the main repository include:
 
@@ -27,8 +61,9 @@ Some of the branches included in the main repository include:
   instead of xhtml.
 * `wikiwyg` adds [[todo/wikiwyg]] support. It is unmerged pending some
   changes.
+* `debian-stable` is used for updates to the old version included in
+  Debian's stable release, and `debian-testing` is used for updates to
+  Debian's testing release.
 * `pristine-tar` contains deltas that
   [pristine-tar](http://kitenet.net/~joey/code/pristine-tar)
   can use to recreate released tarballs of ikiwiki
-* `debian-stable` is used for updates to the old version included in
-  Debian's stable release.
index e76b3f3180918ab93142a165f6e29f25d96a91aa..13f88dc27a7ca3bd1c62d3221e63efbf74676246 100644 (file)
@@ -4,18 +4,25 @@ ikiwiki-makerepo - check an ikiwiki srcdir into revision control
 
 # SYNOPSIS
 
-ikiwiki-makerepo svn|git srcdir repository
+ikiwiki-makerepo svn|git|monotone|darcs srcdir repository
 
-ikiwiki-makerepo mercurial srcdir
+ikiwiki-makerepo bzr|mercurial srcdir
 
 # DESCRIPTION
 
 `ikiwiki-makerepo` injects a `srcdir` directory, containing an ikiwiki wiki,
-into a `repository` that it creates. The repository can be a svn, git, or
-mercurial repository.
+into a `repository` that it creates. The repository can be created using
+any of a variety of revision control systems.
 
-Note that for mercurial, the srcdir is converted into a mercurial
-repository. There is no need to have a separate repository with mercurial.
+Note that for mercurial and bzr, the srcdir is converted into a
+repository. There is no need to have a separate repository with mercurial
+or bzr.
+
+For darcs, the master repo's apply hook will be preconfigured to call a
+ikiwiki wrapper.
+
+Note that for monotone, you are assumed to already have run "mtn genkey"
+to generate a key.
 
 # AUTHOR
 
index 693c1db832472f85d3fc6823197b6970082dec2a..3d81d659f1108a43ff4eb9a624739b069f98d3f0 100644 (file)
@@ -8,42 +8,66 @@ ikiwiki-transition type ...
 
 # DESCRIPTION
 
-`ikiwiki-transition` aids in converting wiki pages when
-there's a major change in ikiwiki syntax. It also handles other transitions
-not involving wiki pages.
+`ikiwiki-transition` aids in converting wiki pages when there's a major
+change in ikiwiki syntax. It also handles other transitions not involving
+wiki pages.
 
-# prefix_directives
+# prefix_directives your.setup
 
-The `prefix_directives` mode converts the specified ikiwiki page from
-the old preprocessor directive syntax, requiring a space, to the new
-syntax, prefixed by '!'.
+The `prefix_directives` mode converts all pages from the old preprocessor
+directive syntax, requiring a space, to the new syntax, prefixed by '!'.
 
 Preprocessor directives which already use the new syntax will remain
 unchanged.
 
-Note that if the page contains wiki links with spaces, which some
+Note that if a page contains wiki links with spaces, which some
 older versions of ikiwiki accepted, the prefix_directives transition will
 treat these as preprocessor directives and convert them.
 
-# indexdb
+# setupformat your.setup
+
+The `setupformat` mode converts a setup file from using a single `wrappers` block
+to using `cgi_wrapper`, `git_wrapper`, etc.
+
+Note that all comments and any unusual stuff like perl code in the setup
+file will be lost, as it is entirely rewritten by the transition.
+
+# aggregateinternal your.setup
+
+The `aggregateinternal` mode moves pages aggregated by the aggregate plugin
+so that the `aggregateinternal` option can be enabled.
+
+# moveprefs your.setup
+
+Moves values that used to be admin preferences into the setup file.
+
+Note that all comments and any unusual stuff like perl code in the setup
+file will be lost, as it is entirely rewritten by the move.
+
+# indexdb your.setup|srcdir
 
 The `indexdb` mode handles converting a plain text `.ikiwiki/index` file to
-a binary `.ikiwiki/indexdb`. In this mode, you should specify the srcdir of
-the wiki as the second parameter. You do not normally need to run
+a binary `.ikiwiki/indexdb`. You do not normally need to run
 `ikiwiki-transition indexdb`; ikiwiki will automatically run it as
 necessary.
 
-# hashpassword
+# hashpassword your.setup|srcdir
 
 The `hashpassword` mode forces any plaintext passwords stored in the
 `.ikiwiki/userdb` file to be replaced with password hashes. (The
-Authen::Passphrase perl module is needed to do this.) In this mode, you
-should specify the srcdir of the wiki as the second parameter. 
+Authen::Passphrase perl module is needed to do this.)
 
 If this is not done explicitly, a user's plaintext password will be
 automatically converted to a hash when a user logs in for the first time
 after upgrade to ikiwiki 2.48.
 
+# deduplinks your.setup
+
+In the past, bugs in ikiwiki have allowed duplicate link information
+to be stored in its indexdb. This mode removes such duplicate information,
+which may speed up wikis afflicted by it. Note that rebuilding the wiki
+will have the same effect.
+
 # AUTHOR
 
 Josh Triplett <josh@freedesktop.org>, Joey Hess <joey@ikiwiki.info>
index 4e87f92e67b31b81ae8dcd6864f2a2bd471628ff..e5ea72e36cf519816489c17d34b45c9eb895031e 100644 (file)
@@ -4,14 +4,16 @@ ikiwiki-update-wikilist - add or remove user from /etc/ikiwiki/wikilist
 
 # SYNOPSIS
 
-ikiwiki-update-wikilist
+ikiwiki-update-wikilist [-r]
 
 # DESCRIPTION
 
-`ikiwiki-update-wikilist` is designed to be made suid root, but not installed
+`ikiwiki-update-wikilist` is designed to be made suid root, but is not installed
 suid by default. If made suid, it allows users to add or remove their names
-from the `/etc/ikiwiki/wikilist` file. If a user's name is not in the file,
-it will be added; if the name is already present, it will be removed.
+from the `/etc/ikiwiki/wikilist` file. 
+
+By default, the user's name will be added.
+The `-r` switch causes the user's name to be removed.
 
 If your name is in `/etc/ikiwiki/wikilist`, the [[ikiwiki-mass-rebuild]](8)
 command will look for a ~/.ikiwiki/wikilist file, and rebuild the wikis listed
index c98a97e5940f0d4bec153b095d7fa1e85fcfb44f..e0a971d96b631cc48a39b39f6dc9d27fee52bc6e 100644 (file)
@@ -7,11 +7,10 @@ This wiki is powered by [ikiwiki](http://ikiwiki.info/).
 Some documentation on using ikiwiki:
 
 * [[ikiwiki/formatting]]
-* [[ikiwiki/blog]]
-* [[ikiwiki/pagespec]]
-* [[ikiwiki/PreprocessorDirective]]
 * [[ikiwiki/wikilink]]
-* [[ikiwiki/markdown]]
 * [[ikiwiki/subpage]]
+* [[ikiwiki/pagespec]]
+* [[ikiwiki/directive]]
+* [[ikiwiki/markdown]]
 * [[ikiwiki/openid]]
 * [[ikiwiki/searching]]
diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup
deleted file mode 100644 (file)
index 6d327fd..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#!/usr/bin/perl
-# Configuration file for ikiwiki.
-# Passing this to ikiwiki --setup will make ikiwiki generate wrappers and
-# build the wiki.
-#
-# Remember to re-run ikiwiki --setup any time you edit this file.
-
-use IkiWiki::Setup::Standard {
-       wikiname => "MyWiki",
-       #adminuser => ["yourname", ],
-       adminemail => 'me@example.org',
-
-       # Be sure to customise these..
-       srcdir => "/path/to/source",
-       destdir => "/var/www/wiki",
-
-       url => "http://example.org/wiki",
-       cgiurl => "http://example.org/wiki/ikiwiki.cgi",
-       #templatedir => "/usr/share/ikiwiki/templates",
-       #underlaydir => "/usr/share/ikiwiki/basewiki",
-
-       # Subversion stuff.
-       #rcs => "svn",
-       #historyurl => "http://svn.example.org/trunk/[[file]]",
-       #diffurl => "http://svn.example.org/trunk/[[file]]?root=wiki&amp;r1=[[r1]]&amp;r2=[[r2]]",
-       #svnrepo => "/svn/wiki",
-       #svnpath => "trunk",
-
-       # Git stuff.
-       #rcs => "git",
-       #historyurl => "http://git.example.org/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
-       #diffurl => "http://git.example.org/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
-       #gitorigin_branch => "origin",
-       #gitmaster_branch => "master",
-
-       # Tla stuff.
-       #rcs => "tla"
-       #historyurl => ??,
-       #diffurl => ??,
-
-       # Mercurial stuff.
-       #rcs => "mercurial",
-       #historyurl => "http://localhost:8000/log/tip/[[file]]", # hg serve'd local repository
-       #diffurl => "http://localhost:8000/?fd=[[r2]];file=[[file]]",
-
-       # Bazaar stuff.
-       #rcs => "bzr",
-       #historyurl => "", 
-       #diffurl => "http://example.com/revision?start_revid=[[r2]]#[[file]]-s", # using loggerhead
-
-       # Monotone stuff
-       #rcs => "monotone",
-       #mtnkey => "web\@machine.company.com",
-       #historyurl => "http://viewmtn.example.com/branch/head/filechanges/com.example.branch/[[file]]",
-       #diffurl => "http://viewmtn.example.com/revision/diff/[[r1]]/with/[[r2]]/[[file]]",
-       # Set if you want the wiki to sync on update and commit.
-       #mtnsync => 0,
-       # The path to your workspace (defaults to the srcdir itself)
-       # e.g. use if your srcdir is a subdirectory of the workspace.
-       #mtnrootdir => "path/to/root/of/workspace",
-
-       wrappers => [
-               #{
-               #       # The cgi wrapper.
-               #       cgi => 1,
-               #       wrapper => "/var/www/wiki/ikiwiki.cgi",
-               #       wrappermode => "06755",
-               #},
-               #{
-               #       # The svn post-commit wrapper.
-               #       # Note that this will overwrite any existing
-               #       # post-commit hook script, which may not be
-               #       # what you want.
-               #       wrapper => "/svn/wikirepo/hooks/post-commit",
-               #       wrappermode => "04755",
-               #       # Log to syslog since svn post-commit hooks
-               #       # hide output and errors.
-               #       syslog => 1,
-               #},
-               #{
-               #       # The git post-update wrapper.
-               #       # Note that this will overwrite any existing
-               #       # post-update hook script, which may not be
-               #       # what you want.
-               #       wrapper => "/git/wiki.git/hooks/post-update",
-               #       wrappermode => "06755",
-               #},
-               #{
-               #       # The monotone netsync hook.
-               #       wrapper => "path/to/root/of/workspace/_MTN/ikiwiki-netsync-hook",
-               #       wrappermode => "06755",
-               #},
-       ],
-
-       # Default to generating rss feeds for pages with feeds?
-       #rss => 1,
-       # Default to generating atom feeds for pages with feeds?
-       #atom => 1,
-       # Allow generating feeds even if not generated by default?
-       #allowrss => 1,
-       #allowatom => 1,
-       # Urls to ping with XML-RPC when feeds are updated
-       #pingurl => [qw{http://rpc.technorati.com/rpc/ping}],
-       # Include discussion links on all pages?
-       discussion => 1,
-       # To exclude files matching a regexp from processing. This adds to
-       # the default exclude list.
-       #exclude => qr/\.wav$/,
-       # To change the extension used for generated html files.
-       #htmlext => 'htm',
-       # Time format (for strftime)
-       #timeformat => '%c',
-       # Locale to use. Must be a UTF-8 locale.
-       #locale => 'en_US.UTF-8',
-       # Only send cookies over SSL connections.
-       #sslcookie => 1,
-       # Logging settings:
-       #verbose => 1,
-       syslog => 0,
-       # To link to user pages in a subdirectory of the wiki.
-       #userdir => "users",
-       # To create output files named page.html rather than page/index.html.
-       #usedirs => 0,
-       # Simple spam prevention: require an account-creation password.
-       #account_creation_password => "example",
-       # Cost of generating a password using Authen::Passphrase::BlowfishCrypt
-       #password_cost => 8,
-       # Uncomment to force ikiwiki to run with a particular umask.
-       #umask => 022,
-       # Default settings for the recentchanges page.
-       #recentchangespage => "recentchanges",
-       #recentchangesnum => 100,
-       # Use new '!'-prefixed preprocessor directive syntax
-       #prefix_directives => 0,
-       # Attempt to make hardlinks to source files instead of copying them.
-       # Useful if the wiki contains large media files.
-       #hardlink => 1,
-       # Enable use of multimarkdown features in .mdwn files.
-       #multimarkdown => 1,
-
-       # To add plugins, list them here.
-       #add_plugins => [qw{goodstuff search wikitext camelcase
-       #                   htmltidy fortune sidebar map rst anonok}],
-       # If you want to disable any of the default plugins, list them here.
-       #disable_plugins => [qw{inline htmlscrubber passwordauth openid}],
-       # To add a directory to the perl search path, use this.
-       #libdir => "/home/me/.ikiwiki/",
-       
-       # To override environment variable settings, you can list values here.
-       #ENV => {
-       #       TZ => "America/New_York",
-       #       PATH => "/home/me/bin:/usr/local/bin:/usr/bin:/bin",
-       #},
-
-       # For use with the tag plugin, make all tags be located under a
-       # base page.
-       #tagbase => "tag",
-
-       # For use with the search plugin if the omega cgi is located
-       # somewhere else.
-       #omega_cgi => "/usr/lib/cgi-bin/omega/omega",
-
-       # For use with the openid plugin, to give an url to a page users
-       # can use to signup for an OpenID.
-       #openidsignup => "http://myopenid.com/",
-
-       # For use with the mirrorlist plugin, a list of mirrors.
-       #mirrorlist => {
-       #       mirror1 => "http://hostname1",
-       #       mirror2 => "http://hostname2/mirror",
-       #},
-       
-       # For use with the anonok plugin, a PageSpec specifying what
-       # pages anonymous users can edit
-       #anonok_pagespec => "*",
-       
-       # For use with the aggregate plugin, to allow aggregation to be
-       # triggered via the web.
-       #aggregate_webtrigger => 1,
-       
-       # For use with the pinger plugin, how many seconds to wait before
-       # timing out.
-       #pinger_timeout => 15.
-       
-       # For use with the amazon S3 plugin, your public access key id.
-       #amazon_s3_key_id => 'XXXXXXXXXXXXXXXXXXXX',
-       # And a file holding your secret key. This file *must* not be
-       # readable by others!
-       #amazon_s3_key_file => "/home/me/.hide/.s3_key
-       # The globally unique name of the bucket to use to store the wiki.
-       #amazon_s3_bucket => "mywiki",
-       # A prefix to prepend to each page name.
-       #amazon_s3_prefix => "wiki/",
-       # Uncomment to use the S3 European datacenter.
-       #amazon_s3_location => "EU",
-       # Uncomment if you need to store each index file twice.
-       #amazon_s3_dupindex => 1,
-       
-       # For use with the attachment plugin, a program that returns
-       # nonzero if its standard input contains an virus.
-       #virus_checker => "clamdscan -",
-}
diff --git a/doc/ikiwiki/blog.mdwn b/doc/ikiwiki/blog.mdwn
deleted file mode 100644 (file)
index f1293ec..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-[[!meta robots="noindex, follow"]]
-[[!if test="enabled(inline)"
-     then="This wiki has the inline plugin **enabled**."
-     else="This wiki has the inline plugin **disabled**."]]
-
-[[!if test="enabled(inline)"
-     then="You can"
-     else="If this wiki had the inline plugin enabled, you could"]]
-turn any page on this wiki into a weblog by using the `inline`
-[[PreProcessorDirective]]. For example:
-
-       \[[!inline pages="blog/* and !*/Discussion" show="10" rootpage="blog"]]
-
-Any pages that match the specified [[PageSpec]] (in the example, any
-[[SubPage]] of "blog") will be part of the blog, and the newest 10
-of them will appear in the page. Note that if files that are not pages
-match the [[PageSpec]], they will be included in the feed using RSS
-enclosures, which is useful for podcasting.
-
-The optional `rootpage` parameter tells the wiki that new posts to this blog
-should default to being [[SubPage]]s of "blog", and enables a form at the
-top of the blog that can be used to add new items.
-
-If you want your blog to have an archive page listing every post ever made
-to it, you can accomplish that like this:
-
-       \[[!inline pages="blog/* and !*/Discussion" archive="yes"]]
-
-You can even create an automatically generated list of all the pages on the
-wiki, with the most recently added at the top, like this:
-
-       \[[!inline pages="* and !*/Discussion" archive="yes"]]
-
-If you want to be able to add pages to a given blog feed by tagging them,
-you can do that too. To tag a page, just make it link to a page or pages 
-that represent its tags. Then use the special `link()` [[PageSpec]] to match
-all pages that have a given tag:
-
-       \[[!inline pages="link(life)"]]
-
-Or include some tags and exclude others:
-
-       \[[!inline pages="link(debian) and !link(social)"]]
-
-## usage
-
-Here are descriptions of all the supported parameters to the `inline`
-directive:
-
-* `pages` - A [[PageSpec]] of the pages to inline.
-* `show` - Specify the maximum number of matching pages to inline.
-  Default is 10, unless archiving, when the default is to show all.
-  Set to 0 to show all matching pages.
-* `skip` - Specify a number of pages to skip displaying. Can be useful
-  to produce a feed that only shows archived pages.
-* `rss` - controls generation of an rss feed. If the wiki is configured to
-  generate rss feeds by default, set to "no" to disable. If the wiki is
-  configured to `allowrss`, set to "yes" to enable.
-* `atom` - controls generation of an atom feed. If the wiki is configured to
-  generate atom feeds by default, set to "no" to disable. If the wiki is
-  configured to `allowatom`, set to "yes" to enable.
-* `feeds` - controls generation of all types of feeds. Set to "no" to
-  disable generating any feeds.
-* `postform` - Set to "yes" to enables a form to post new pages to a [[blog]].
-* `postformtext` - Set to specify text that is displayed in a postform.
-* `rootpage` - Also enables a form to post new pages to a [[blog]], and
-  allows specifying of a page that is used as the parent page for new pages.
-* `archive` - If set to "yes", only list page titles and some metadata, not
-  full controls.
-* `quick` - Build archives in quick mode, without reading page contents for
-  metadata. By default, this also turns off generation of any feeds.
-* `template` - Specifies the template to fill out to display each inlined
-  page. By default the `inlinepage` template is used, while
-  the `archivepage` template is used for archives. Set this parameter to
-  use some other, custom template, such as the `titlepage` template that
-  only shows post titles. Note that you should still set `archive=yes` if
-  your custom template does not include the page content.
-* `raw` - Rather than the default behavior of creating a [[blog]],
-  if raw is set to "yes", the page will be included raw, without additional
-  markup around it, as if it were a literal part of the source of the 
-  inlining page.
-* `description` - Sets the description of the rss feed if one is generated.
-  Defaults to the name of the wiki.
-* `actions` - If set to "yes" add links to the bottom of the inlined pages 
-  for editing and discussion (if they would be shown at the top of the page
-  itself).
-* `sort` - Controls how inlined pages are sorted. The default, "age" is to
-  sort newest created pages first. Setting it to "title" will sort pages by
-  title, and "mtime" sorts most recently modified pages first.
-* `reverse` - If set to "yes", causes the sort order to be reversed.
-* `feedpages` - A [[PageSpec]] of inlined pages to include in the rss/atom
-  feeds. The default is the same as the `pages` value above, and only pages
-  matches by that value are included, but some of those can be excluded by
-  specifying a tighter [[PageSpec]] here.
-* `feedshow` - Specify the maximum number of matching pages to include in
-  the rss/atom feeds. The default is the same as the `show` value above.
-* `feedonly` - Only generate the feed, do not display the pages inline on
-  the page.
-* `timeformat` - Use this to specify how to display the time or date for pages
-  in the blog. The format string is passed to the strftime(3) function.
diff --git a/doc/ikiwiki/blog/discussion.mdwn b/doc/ikiwiki/blog/discussion.mdwn
deleted file mode 100644 (file)
index 91b2ff4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-## How do you provide the per post discussion links in your own blog?
-
-> That's configured by the "actions" parameter to the inline directive. See
-> docs in [[plugins/inline]]. --[[Joey]]
-
-And do you have any ideas/hints about implementing a "comments" feature.
-What I'm after is something for users who don't quite understand the Wiki
-style for discussions.  I would like to have a form for them to post a
-comment and have the comment appended to the discussion Wiki-style.  Maybe
-take it as far as implementing "replies" to other comments.
-
--- Marcelo
-
-> See [[todo/discussion_page_as_blog]] for some of my own thoughts on this
-> --[[Joey]]
-
----
-
-## More dynamic `rootpage` parameter of inline plugin?
-
-(Moved to [[todo/dynamic_rootpage]])
diff --git a/doc/ikiwiki/directive.mdwn b/doc/ikiwiki/directive.mdwn
new file mode 100644 (file)
index 0000000..fb88aa7
--- /dev/null
@@ -0,0 +1,43 @@
+[[!meta robots="noindex, follow"]]
+Directives are similar to a [[ikiwiki/WikiLink]] in form, except they
+begin with `!` and may contain parameters. The general form is:
+
+       \[[!directive param="value" param="value"]]
+
+This gets expanded before the rest of the page is processed, and can be used
+to transform the page in various ways.
+
+The quotes around values can be omitted if the value is a simple word.
+Also, some directives may use parameters without values, for example:
+
+       \[[!tag foo]]
+
+A directive does not need to all be on one line, it can be
+wrapped to multiple lines if you like:
+       
+       \[[!directive foo="baldersnatch"
+       bar="supercalifragilisticexpialidocious" baz=11]]
+
+Also, multiple lines of *quoted* text can be used for a value.
+To allow quote marks inside the quoted text, delimit the block
+of text with triple-quotes:
+
+       \[[!directive text="""
+       1. "foo"
+       2. "bar"
+       3. "baz"
+       """]]
+
+ikiwiki also has an older syntax for directives, which requires a space in
+directives to distinguish them from [[wikilinks|ikiwiki/wikilink]]. This
+syntax has several disadvantages: it requires a space after directives with
+no parameters (such as `\[[pagecount ]]`), and it prohibits spaces in
+[[wikilinks|ikiwiki/wikilink]].  ikiwiki now provides the `!`-prefixed
+syntax shown above as default.  However, ikiwiki still supports wikis using
+the older syntax, if the `prefix_directives` option is disabled.
+
+[[!if test="enabled(listdirectives)" then="""
+Here is a list of currently available directives in this wiki:
+
+[[!listdirectives ]]
+"""]]
diff --git a/doc/ikiwiki/directive/aggregate.mdwn b/doc/ikiwiki/directive/aggregate.mdwn
new file mode 100644 (file)
index 0000000..ddfcd40
--- /dev/null
@@ -0,0 +1,57 @@
+The `aggregate` directive is supplied by the [[!iki plugins/aggregate desc=aggregate]] plugin.
+This plugin requires extra setup, specifically, a cron job. See the
+plugin's documentation for details.
+
+This directive allows content from other feeds to be aggregated into the wiki.
+Aggregate a feed as follows:
+
+       \[[!aggregate name="example blog" dir="example"
+       feedurl="http://example.com/index.rss"
+       url="http://example.com/" updateinterval="15"]]
+
+That example aggregates posts from the specified RSS feed, updating no
+more frequently than once every 15 minutes (though possibly less
+frequently, if the cron job runs less frequently than that), and puts a
+page per post under the example/ directory in the wiki.
+
+You can then use ikiwiki's [[inline]] directive to create a blog of one or
+more aggregated feeds. For example:
+
+       \[[!inline pages="internal(example/*)"]]
+
+Note the use of `internal()` in the [[ikiwiki/PageSpec]] to match
+aggregated pages. By default, aggregated pages are internal pages,
+which prevents them from showing up directly in the wiki, and so this
+special [[PageSpec]] is needed to match them.
+
+## usage
+
+Here are descriptions of all the supported parameters to the `aggregate`
+directive:
+
+* `name` - A name for the feed. Each feed must have a unique name.
+  Required.
+* `url` - The url to the web page for the feed that's being aggregated.
+  Required.
+* `dir` - The directory in the wiki where pages should be saved. Optional,
+  if not specified, the directory is based on the name of the feed.
+* `feedurl` - The url to the feed. Optional, if it's not specified ikiwiki
+  will look for feeds on the `url`. RSS and atom feeds are supported.
+* `updateinterval` - How often to check for new posts, in minutes. Default
+  is 15 minutes.
+* `expireage` - Expire old items from this feed if they are older than
+  a specified number of days. Default is to never expire on age.
+* `expirecount` - Expire old items from this feed if there are more than
+  the specified number total. Oldest items will be expired first. Default
+  is to never expire on count.
+* `tag` - A tag to tag each post from the feed with. A good tag to use is
+  the name of the feed. Can be repeated multiple times. The [[tag]] plugin
+  must be enabled for this to work.
+* `template` - Template to use for creating the aggregated pages. Defaults to
+  aggregatepost.
+
+Note that even if you are using subversion or another revision control
+system, pages created by aggregation will *not* be checked into revision
+control.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/brokenlinks.mdwn b/doc/ikiwiki/directive/brokenlinks.mdwn
new file mode 100644 (file)
index 0000000..91bafe5
--- /dev/null
@@ -0,0 +1,14 @@
+The `brokenlinks` directive is supplied by the [[!iki plugins/brokenlinks desc=brokenlinks]] plugin.
+
+This directive generates a list of broken links on pages in the wiki. This is
+a useful way to find pages that still need to be written, or links that
+are written wrong.
+
+The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
+pages to search for broken links, default is search them all.
+
+Example:
+
+       \[[!brokenlinks pages="* and !recentchanges"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/brokenlinks/discussion.mdwn b/doc/ikiwiki/directive/brokenlinks/discussion.mdwn
new file mode 100644 (file)
index 0000000..65e97cf
--- /dev/null
@@ -0,0 +1 @@
+Would it be possible to have such a thing also checking for external links? -- [[user/emptty]]
diff --git a/doc/ikiwiki/directive/calendar.mdwn b/doc/ikiwiki/directive/calendar.mdwn
new file mode 100644 (file)
index 0000000..8a257d6
--- /dev/null
@@ -0,0 +1,46 @@
+The `calendar` directive is supplied by the [[!iki plugins/calendar desc=calendar]] plugin.
+This plugin requires extra setup.  See the plugin documentation for details.
+
+This directive displays a calendar, similar to the typical calendars shown on
+some blogs.
+
+# examples
+
+       \[[!calendar ]]
+
+       \[[!calendar type="month" pages="blog/* and !*/Discussion"]]
+
+       \[[!calendar type="year" year="2005" pages="blog/* and !*/Discussion"]]
+
+The calendar is essentially a fancy front end to archives of previous
+pages, usually used for blogs. It can produce a calendar for a given month,
+or a list of months for a given year.
+
+The month format calendar simply links to any page posted on each
+day of the month. The year format calendar links to archive pages, with
+names like `archives/2007` (for all of 2007)  and `archives/2007/01`
+(for January, 2007). For this to work, you'll need to create these archive
+pages. They typically use [[inline]] to display or list pages created in
+the given time frame.
+
+## usage
+
+* `type` - Used to specify the type of calendar wanted. Can be one of
+  "month" or "year". The default is a month view calendar.
+* `pages` - Specifies the [[ikiwiki/PageSpec]] of pages to link to from the
+  month calendar. Defaults to "*".
+* `archivebase` - Configures the base of the archives hierarchy. The
+  default is "archives". Note that this default can also be overridden
+  for the whole wiki by setting `archivebase` in ikiwiki's setup file.
+* `year` - The year for which the calendar is requested. Defaults to the
+  current year.
+* `month` - The numeric month for which the calendar is requested, in the
+  range 1..12. Used only for the month view calendar, and defaults to the
+  current month.
+* `week_start_day` - A number, in the range 0..6, which represents the day
+  of the week that the month calendar starts with. 0 is Sunday, 1 is Monday,
+  and so on. Defaults to 0, which is Sunday.
+* `months_per_row` - In the annual calendar, number of months to place in
+  each row. Defaults to 3.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/color.mdwn b/doc/ikiwiki/directive/color.mdwn
new file mode 100644 (file)
index 0000000..553767f
--- /dev/null
@@ -0,0 +1,25 @@
+The `color` directive is supplied by the [[!iki plugins/color desc=color]] plugin.
+
+This directive can be used to color a piece of text on a page.
+It can be used to set the foreground and/or background color of the text.
+
+You can use a color name (e.g. `white`) or HTML code (e.g. `#ffffff`)
+to define colors. 
+
+## examples
+
+Here the foreground color is defined as a word, while the background color
+is defined as a HTML color code:
+
+       \[[!color foreground=white background=#ff0000 text="White text on red background"]]
+
+The background color is missing, so the text is displayed on default
+background:
+
+       \[[!color foreground=white text="White text on default color background"]]
+
+The foreground is missing, so the text has the default foreground color:
+
+       \[[!color background=#ff0000 text="Default color text on red background"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/comment.mdwn b/doc/ikiwiki/directive/comment.mdwn
new file mode 100644 (file)
index 0000000..21386df
--- /dev/null
@@ -0,0 +1,38 @@
+The `comment` directive is supplied by the
+[[!iki plugins/comments desc=comments]] plugin, and is used to add a comment
+to a page. Typically, the directive is the only thing on a comment page,
+and is filled out by the comment plugin when a user posts a comment.
+
+Example:
+
+       \[[!comment format=mdwn
+       username="foo"
+       subject="Bar"
+       date="2009-06-02T19:05:01Z"
+       content="""
+       Blah blah.
+       """
+       ]]
+
+## usage
+
+The only required parameter is `content`, the others just add or override
+metadata of the comment.
+
+* `content` - Text to display for the comment.
+  Note that [[directives|ikiwiki/directive]]
+  may not be allowed, depending on the configuration
+  of the comment plugin.
+* `format` - Specifies the markup used for the content.
+* `subject` - Subject for the comment.
+* `date` - Date the comment was posted. Can be entered in
+  nearly any format, since it's parsed by [[!cpan TimeDate]]
+* `username` - Used to record the username (or OpenID)
+  of a logged in commenter.
+* `ip` - Can be used to record the IP address of a commenter,
+  if they posted anonymously.
+* `claimedauthor` - Records the name that the user entered,
+  if anonmous commenters are allowed to enter their (unverified)
+  name.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/copy.mdwn b/doc/ikiwiki/directive/copy.mdwn
new file mode 100644 (file)
index 0000000..a0aa0ef
--- /dev/null
@@ -0,0 +1,3 @@
+[[!meta redir=/ikiwiki/directive/cutpaste]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/cut.mdwn b/doc/ikiwiki/directive/cut.mdwn
new file mode 100644 (file)
index 0000000..a0aa0ef
--- /dev/null
@@ -0,0 +1,3 @@
+[[!meta redir=/ikiwiki/directive/cutpaste]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/cutpaste.mdwn b/doc/ikiwiki/directive/cutpaste.mdwn
new file mode 100644 (file)
index 0000000..ca580e5
--- /dev/null
@@ -0,0 +1,50 @@
+The `copy`, `cut` and `paste` directives are supplied by the
+[[!iki plugins/cutpaste desc=cutpaste]] plugin.
+
+With these directives you can store and recall pieces of text in a page:
+
+ * `\[[!cut id=name text="text"]]` memorizes the text allowing to recall it
+   using the given ID.  The text being cut is not included in the output.
+ * `\[[!copy id=name text="text"]]` memorizes the text allowing to recall it
+   using the given ID.  The text being cut *is* included in the output.
+ * `\[[!paste id=name]]` is replaced by the previously memorized text.
+
+The text being cut, copied and pasted can freely include wiki markup, including
+more calls to cut, copy and paste.
+
+You do not need to memorize the text before using it: a cut directive can
+follow the paste directive that uses its text.  In fact, this is quite useful
+to postpone big blocks of text like long annotations and have a more natural
+flow.  For example:
+
+       \[[!toggleable id="cut" text="[[!paste id=cutlongdesc]]"]]
+       \[[!toggleable id="copy" text="[[!paste id=copylongdesc]]"]]
+       \[[!toggleable id="paste" text="[[!paste id=pastelongdesc]]"]]
+
+       [...some time later...]
+
+       \[[!cut id=cutlongdesc text="""
+          blah blah blah
+       """]]
+       \[[!cut id=copylongdesc text="""
+          blah blah blah
+       """]]
+       \[[!cut id=pastelongdesc text="""
+          blah blah blah
+       """]]
+
+This can potentially be used to create loops, but ikiwiki is clever and breaks
+them.
+
+Since you can paste without using double quotes, copy and paste can be used to
+nest directives that require multiline parameters inside each other:
+
+       \[[!toggleable id=foo text="""
+         [[!toggleable id=bar text="[[!paste id=baz]]"]]
+       """]]
+
+       \[[!cut id=baz text="""
+       multiline parameter!
+       """]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/edittemplate.mdwn b/doc/ikiwiki/directive/edittemplate.mdwn
new file mode 100644 (file)
index 0000000..d731bdb
--- /dev/null
@@ -0,0 +1,36 @@
+The `edittemplate` directive is supplied by the [[!iki plugins/edittemplate desc=edittemplate]] plugin.
+
+This directive allows registering template pages, that provide default
+content for new pages created using the web frontend. To register a
+template, insert a [[ikiwiki/directive/template]] directive on some other page.
+
+       \[[!edittemplate template="bugtemplate" match="bugs/*"]]
+
+In the above example, the page named "bugtemplate" is registered as a
+template to be used when any page named "bugs/*" is created. To avoid
+the directive displaying a note about the template being registered, add
+"silent=yes".
+
+Often the template page contains a simple skeleton for a particular type of
+page. For the bug report pages in the above example, it might look
+something like:
+
+       Package: 
+       Version: 
+       Reproducible: y/n
+       Details:
+
+The template page can also contain [[!cpan HTML::Template]] directives,
+similar to other ikiwiki [[templates]]. Currently only one variable is
+set: `<TMPL_VAR name>` is replaced with the name of the page being
+created.
+
+----
+
+It's generally not a good idea to put the `edittemplate` directive in
+the template page itself, since the directive would then be included as
+part of the template on new pages, which would then in turn be registered
+as templates. If multiple pages are registered as templates for a new page,
+an arbitrary one is chosen, so that could get confusing.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/format.mdwn b/doc/ikiwiki/directive/format.mdwn
new file mode 100644 (file)
index 0000000..23830e9
--- /dev/null
@@ -0,0 +1,29 @@
+The `format` directive is supplied by the [[!iki plugins/format desc=format]]
+plugin.
+
+The directive allows formatting a chunk of text using any available page
+format. It takes two parameters. First is the type of format to use,
+ie the extension that would be used for a standalone file of this type.
+Second is the text to format.
+
+For example, this will embed an otl outline inside a page using mdwn or
+some other format:
+
+       \[[!format otl """
+       foo
+               1
+               2
+       bar
+               3
+               4
+       """]]
+
+Note that if the highlight plugin is enabled, this directive can also be
+used to display syntax highlighted code. Many languages and formats are
+supported. For example:
+
+       \[[format perl """
+       print "hello, world\n";
+       """]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/fortune.mdwn b/doc/ikiwiki/directive/fortune.mdwn
new file mode 100644 (file)
index 0000000..45f533e
--- /dev/null
@@ -0,0 +1,8 @@
+The `fortune` directive is supplied by the [[!iki plugins/fortune desc=fortune]] plugin.
+
+This just uses the `fortune` program to insert a fortune cookie into the page.
+Usage:
+
+       \[[!fortune ]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/graph.mdwn b/doc/ikiwiki/directive/graph.mdwn
new file mode 100644 (file)
index 0000000..4331872
--- /dev/null
@@ -0,0 +1,23 @@
+The `graph` directive is supplied by the [[!iki plugins/graphviz desc=graphviz]] plugin.
+
+This directive allows embedding [graphviz](http://www.graphviz.org/) graphs in a
+page.  Example usage:
+
+       \[[!graph src="a -> b -> c; a -> c;"]]
+
+Note that graphs will only show up in previews if your browser has
+[[!wikipedia data: URI]] support, or if the same graph already exists on that
+page.
+
+The `graph` directive supports the following parameters:
+
+- `src` - The graphviz source to render.
+- `type` - The type of graph to render: `graph` or `digraph`.  Defaults to
+  `digraph`.
+- `prog` - The graphviz program to render with: `dot`, `neato`, `fdp`, `twopi`,
+  or `circo`.  Defaults to `dot`.
+- `height`, `width` - Limit the size of the graph to a given height and width,
+  in inches. You must specify both to limit the size; otherwise, graphviz will
+  choose a size, without any limit.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/haiku.mdwn b/doc/ikiwiki/directive/haiku.mdwn
new file mode 100644 (file)
index 0000000..979f089
--- /dev/null
@@ -0,0 +1,15 @@
+The `haiku` directive is supplied by the [[!iki plugins/haiku desc=haiku]] plugin.
+
+This directive allows inserting a randomly generated haiku into a wiki page.
+Just type:
+
+       \[[!haiku hint="argument"]]
+
+[[!haiku hint="argument test"]]
+
+The hint parameter can be omitted, it only provides the generator a hint of
+what to write the haiku about. If no hint is given, it might base it on the
+page name. Since the vocabulary it knows is very small, many hints won't
+affect the result at all.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/if.mdwn b/doc/ikiwiki/directive/if.mdwn
new file mode 100644 (file)
index 0000000..2cbf70c
--- /dev/null
@@ -0,0 +1,48 @@
+The `if` directive is supplied by the [[!iki plugins/conditional desc=conditional]] plugin.
+
+With this directive, you can make text be conditionally displayed on a page.
+For example:
+
+       \[[!if test="enabled(smiley)"
+             then="The smiley plugin is enabled :-)"
+             else="No smiley plugin here.."]]
+
+If the specified `test` succeeds, the `then` text will be displayed,
+otherwise the `else` text will be displayed. The `else` part is optional.
+
+The `then` and `else` values can include any markup that would be allowed
+in the wiki page outside the template. Triple-quoting the values even allows
+quotes to be included.
+
+The `test` is a [[ikiwiki/PageSpec]]; if it matches any page in the wiki
+then it succeeds. So you can do things like testing for the existence of a
+page or pages, testing to see if any pages were created in a given month,
+and so on.
+
+If you want the [[ikiwiki/PageSpec]] to only match against the page that
+contains the conditional, rather than matching against all pages in the
+wiki, set the "all" parameter to "no".
+
+In an `if` directive, the regular [[ikiwiki/PageSpec]] syntax is expanded
+with the following additional tests:
+
+* enabled(plugin)
+
+  Tests whether the specified plugin is enabled.
+
+* sourcepage(glob)
+
+  Tests whether the glob matches the name of the page that contains the
+  conditional.
+
+* destpage(glob)
+
+  Tests whether the glob matches the name of the page that is being built.
+  That might be different than the name of the page that contains the
+  conditional, if it's being inlined into another page.
+
+* included()
+
+  Tests whether the page is being included onto another page.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/img.mdwn b/doc/ikiwiki/directive/img.mdwn
new file mode 100644 (file)
index 0000000..66efd00
--- /dev/null
@@ -0,0 +1,38 @@
+The `img` directive is supplied by the [[!iki plugins/img desc=img]] plugin.
+
+This is an image handling directive.  While ikiwiki supports inlining full-size
+images by making a [[ikiwiki/WikiLink]] that points to the image, using
+this directive you can easily scale down an image for inclusion onto a page,
+providing a link to a full-size version.
+
+## usage
+
+       \[[!img image1.jpg size="200x200" alt="clouds"]]
+
+The image file will be searched for using the same rules as used to find
+the file pointed to by a [[ikiwiki/WikiLink]].
+
+The `size` parameter is optional, defaulting to full size. Note that the
+original image's aspect ratio is always preserved, even if this means
+making the image smaller than the specified size. You can also specify only
+the width or the height, and the other value will be calculated based on
+it: "200x", "x200"
+
+You can also pass `alt`, `title`, `class`, `align` and `id` parameters.
+These are passed through unchanged to the html img tag. If you include a
+`caption` parameter, the caption will be displayed centered beneath the image.
+
+The `link` parameter is used to control whether the scaled down image links
+to the full size version. By default it does; set "link=somepage" to link
+to another page instead, or "link=no" to disable the link, or
+"link=http://url" to link to a given url.
+
+You can also set default values that will be applied to all later images on
+the page, unless overridden. Useful when including many images on a page.
+
+       \[[!img defaults size=200x200 alt="wedding photo"]]
+       \[[!img photo1.jpg]]
+       \[[!img photo2.jpg]]
+       \[[!img photo3.jpg size=200x600]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/inline.mdwn b/doc/ikiwiki/directive/inline.mdwn
new file mode 100644 (file)
index 0000000..99f7959
--- /dev/null
@@ -0,0 +1,125 @@
+The `inline` directive is supplied by the [[!iki plugins/inline desc=inline]] plugin.
+
+This is a directive that allows including one wiki page inside another.
+The most common use of inlining is generating blogs and RSS or Atom feeds.
+
+Example:
+
+       \[[!inline pages="blog/* and !*/Discussion" show="10" rootpage="blog"]]
+
+Any pages that match the specified [[PageSpec]] (in the example, any
+[[SubPage]] of "blog") will be part of the blog, and the newest 10
+of them will appear in the page. Note that if files that are not pages
+match the [[PageSpec]], they will be included in the feed using RSS
+enclosures, which is useful for podcasting.
+
+The optional `rootpage` parameter tells the wiki that new posts to this
+blog should default to being [[SubPages|SubPage]] of "blog", and enables a
+form at the top of the blog that can be used to add new items.
+
+If you want your blog to have an archive page listing every post ever made
+to it, you can accomplish that like this:
+
+       \[[!inline pages="blog/* and !*/Discussion" archive="yes"]]
+
+You can even create an automatically generated list of all the pages on the
+wiki, with the most recently added at the top, like this:
+
+       \[[!inline pages="* and !*/Discussion" archive="yes"]]
+
+If you want to be able to add pages to a given blog feed by tagging them,
+you can do that too. To tag a page, just make it link to a page or pages 
+that represent its tags. Then use the special `link()` [[PageSpec]] to match
+all pages that have a given tag:
+
+       \[[!inline pages="link(life)"]]
+
+Or include some tags and exclude others:
+
+       \[[!inline pages="link(debian) and !link(social)"]]
+
+## usage
+
+There are many parameters you can use with the `inline`
+directive. These are the commonly used ones:
+
+* `pages` - A [[PageSpec]] of the pages to inline.
+* `show` - Specify the maximum number of matching pages to inline.
+  Default is 10, unless archiving, when the default is to show all.
+  Set to 0 to show all matching pages.
+* `archive` - If set to "yes", only list page titles and some metadata, not
+  full contents.
+* `description` - Sets the description of the rss feed if one is generated.
+  Defaults to the name of the wiki.
+* `skip` - Specify a number of pages to skip displaying. Can be useful
+  to produce a feed that only shows archived pages.
+* `postform` - Set to "yes" to enable a form to post new pages to a
+  blog.
+* `postformtext` - Set to specify text that is displayed in a postform.
+* `rootpage` - Enables the postform, and allows controling where
+  newly posted pages should go, by specifiying the page that
+  they should be a [[SubPage]] of.
+
+Here are some less often needed parameters:
+
+* `actions` - If set to "yes" add links to the bottom of the inlined pages 
+  for editing and discussion (if they would be shown at the top of the page
+  itself).
+* `rss` - controls generation of an rss feed. If the wiki is configured to
+  generate rss feeds by default, set to "no" to disable. If the wiki is
+  configured to `allowrss`, set to "yes" to enable.
+* `atom` - controls generation of an atom feed. If the wiki is configured to
+  generate atom feeds by default, set to "no" to disable. If the wiki is
+  configured to `allowatom`, set to "yes" to enable.
+* `feeds` - controls generation of all types of feeds. Set to "no" to
+  disable generating any feeds.
+* `emptyfeeds` - Set to "no" to disable generation of empty feeds.
+  Has no effect if `rootpage` or `postform` is set.
+* `template` - Specifies the template to fill out to display each inlined
+  page. By default the `inlinepage` template is used, while
+  the `archivepage` template is used for archives. Set this parameter to
+  use some other, custom template, such as the `titlepage` template that
+  only shows post titles or the `microblog` template, optimised for
+  microblogging. Note that you should still set `archive=yes` if
+  your custom template does not include the page content.
+* `raw` - Rather than the default behavior of creating a blog,
+  if raw is set to "yes", the page will be included raw, without additional
+  markup around it, as if it were a literal part of the source of the 
+  inlining page.
+* `sort` - Controls how inlined pages are sorted. The default, "age" is to
+  sort newest created pages first. Setting it to "title" will sort pages by
+  title, and "mtime" sorts most recently modified pages first. If
+  [[!cpan Sort::Naturally]] is installed, `sort` can be set to "title_natural"
+  to sort by title with numbers treated as such ("1 2 9 10 20" instead of
+  "1 10 2 20 9").
+* `reverse` - If set to "yes", causes the sort order to be reversed.
+* `feedshow` - Specify the maximum number of matching pages to include in
+  the rss/atom feeds. The default is the same as the `show` value above.
+* `feedonly` - Only generate the feed, do not display the pages inline on
+  the page.
+* `quick` - Build archives in quick mode, without reading page contents for
+  metadata. By default, this also turns off generation of any feeds.
+* `timeformat` - Use this to specify how to display the time or date for pages
+  in the blog. The format string is passed to the strftime(3) function.
+* `feedpages` - A [[PageSpec]] of inlined pages to include in the rss/atom
+  feeds. The default is the same as the `pages` value above, and only pages
+  matched by that value are included, but some of those can be excluded by
+  specifying a tighter [[PageSpec]] here.
+* `guid` - If a URI is given here (perhaps a UUID prefixed with `urn:uuid:`),
+  the Atom feed will have this as its `<id>`. The default is to use the URL
+  of the page containing the `inline` directive.
+* `feedfile` - Can be used to change the name of the file generated for the
+  feed. This is particularly useful if a page contains multiple feeds.
+  For example, set "feedfile=feed" to cause it to generate `page/feed.atom`
+  and/or `page/feed.rss`. This option is not supported if the wiki is
+  configured not to use `usedirs`.
+* `pagenames` - If given instead of `pages`, this is interpreted as a
+  space-separated list of links to pages (with the same
+  [[SubPage/LinkingRules]] as in a [[ikiwiki/WikiLink]]), and they are inlined
+  in exactly the order given: the `sort` and `pages` parameters cannot be used
+  in conjunction with this one.
+
+[[!meta robots="noindex, follow"]]
+
+A related directive is the [[ikiwiki/directive/edittemplate]] directive, which allows
+default text for a new page to be specified.
diff --git a/doc/ikiwiki/directive/inline/discussion.mdwn b/doc/ikiwiki/directive/inline/discussion.mdwn
new file mode 100644 (file)
index 0000000..be0665d
--- /dev/null
@@ -0,0 +1,126 @@
+## How do you provide the per post discussion links in your own blog?
+
+> That's configured by the "actions" parameter to the inline directive. See
+> docs in [[plugins/inline]]. --[[Joey]]
+
+And do you have any ideas/hints about implementing a "comments" feature.
+What I'm after is something for users who don't quite understand the Wiki
+style for discussions.  I would like to have a form for them to post a
+comment and have the comment appended to the discussion Wiki-style.  Maybe
+take it as far as implementing "replies" to other comments.
+
+-- Marcelo
+
+> See [[plugins/comments]]
+> --[[Joey]]
+
+---
+
+## More dynamic `rootpage` parameter of inline plugin?
+
+(Moved to [[todo/dynamic_rootpage]])
+
+---
+
+## Excluding Images
+
+Is there a simple way to exclude images, stylesheets, and other
+"non-page" files other than a blacklist approach like
+`pages="* and !*.png and !*.css"`?  --[[JasonBlevins]]
+
+> The [[plugins/filecheck]] plugin adds a 'ispage()' pagespec test that can do that.
+> --[[Joey]]
+
+---
+
+## Documentation for parameter `template`?
+
+I would be especially interested in a list of variables which can be used in such a template.
+
+> I try to keep ikiwiki's templates self-documenting, so if you take
+> a look at a template used by inline, such as the default `/usr/share/ikiwiki/template/inlinepage.tmpl`,
+> you can see all or nearly all the template variables in use in it.
+
+I have a page template with some structured information as parameters. For
+example `location="nowhere"` and `price="20"`. Is there a possibility to
+extract those information, i. e. access the parameters, to compose the item
+for the inline directive from these information? For example the line »Go
+to nowhere for 20 bugs.« is shown inlined.
+
+--[[PaulePanter]]
+
+> Let's not confuse the template directive with the templates used by inline.
+> When a page is inlined, any template directives in it are first expanded,
+> using the user-defined templates for that. Then, the inline directive's
+> template is used to insert it into the inlining page.
+> 
+> So no, you can't reference template directive parameters inside inline's
+> template, because it's already expanded at that point. --[[Joey]] 
+
+>> Thank you for the explanation. Can you think of another way to accomplish
+>> my goals?
+>>
+>> Right now, I only see the option to edit the title with the
+>> `[[/ikiwiki/directive/meta]]` directive and the field `title`.
+>>
+>> How could a solution look like?
+>>
+>> 1. The possibility to add custom fields to the `meta` directive.
+>> 1. The possibility to specify in a page, how the page should be displayed
+>>    when used by inlined. That could be done by a new directive `cinlined`
+>>    (for »custom inlined«) which is chosen by the `inline` directive to
+>>    display if told to do so.
+>>
+>>    [[!cinlined text="""Text which can also use Parameter, bla blubb …"""]]
+>> --[[PaulePanter]]
+>>> You can make the body of a page change depending on whether it's being
+>>> inlined, with the [[ikiwiki/directive/if]] directive from the
+>>> [[plugins/conditional]] plugin:
+>>>
+>>>     \[[!if test="inlined()"
+>>>       then="""[[!template id=productsummary
+>>>         location="Warehouse 23" price=20
+>>>         ]]"""
+>>>       else="""[[!template id=productdetail
+>>>         location="Warehouse 23" price=20
+>>>         description="Every home should have one"
+>>>         ]]"""
+>>>     ]]
+>>>
+>>> Perhaps that does some of what you want?
+>>>
+>>> If you want to go beyond that, my inclination would be to write
+>>> a simple plugin to deal with whatever it is you want to do (bug
+>>> metadata or product metadata or whatever) rather than prematurely
+>>> generalizing. --[[smcv]]
+
+## meta parameters are not enough
+
+I think I have the same problem as Paule, as I want extra arbitary parameters in my template.
+
+This is what I am doing currently, which makes my skin crawl. In `wgts/foo.mdwn`
+I have resorted to using AUTHORURL as the location of this widgets icon:
+
+       [[!meta authorurl="/ico/aHR0cDovL2JvbmRpLm9tdHAub3JnL3dpZGdldHMvYmF0dGVyeQ==.png" ]]
+
+In templates I have a file called `wgtlist.tmpl`:
+
+       <div class="widget">
+       <TMPL_IF NAME="AUTHORURL">
+       <img src="<TMPL_VAR AUTHORURL>" />
+       </TMPL_IF>
+       <TMPL_IF NAME="PERMALINK">
+       <a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a><br />
+       <TMPL_ELSE>
+       <a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a><br />
+       </TMPL_IF>
+       Posted <TMPL_VAR CTIME>
+       </div>
+
+My index page has:
+
+       [[!inline pages="./wgts/*" show=5 feeds=no actions=no rootpage="wgts" archive="yes" template=wgtlist]]
+
+Else can you please suggest a smarter way of getting certain data out from pages for a inline index?
+
+--[[hendry]]
diff --git a/doc/ikiwiki/directive/linkmap.mdwn b/doc/ikiwiki/directive/linkmap.mdwn
new file mode 100644 (file)
index 0000000..db79a14
--- /dev/null
@@ -0,0 +1,24 @@
+The `linkmap` directive is supplied by the [[!iki plugins/linkmap desc=linkmap]] plugin.
+
+This directive uses [graphviz](http://www.graphviz.org/) to generate a
+graph showing the links between a set of pages in the wiki. Example usage:
+
+       \[[!linkmap pages="* and !blog/* and !*/Discussion"]]
+
+Only links between mapped pages will be shown; links pointing to or from
+unmapped pages will be omitted. If the pages to include are not specified,
+the links between all pages (and other files) in the wiki are mapped. For
+best results, only a small set of pages should be mapped, since otherwise
+the map can become very large, unwieldy, and complicated. Also, the map is
+rebuilt whenever one of the mapped pages is changed, which can make the
+wiki a bit slow.
+
+Here are descriptions of all the supported parameters to the `linkmap`
+directive:
+
+* `pages` - A [[ikiwiki/PageSpec]] of the pages to map.
+* `height`, `width` - Limit the size of the map to a given height and width,
+  in inches. Both must be specified for the limiting to take effect, otherwise
+  the map's size is not limited.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/listdirectives.mdwn b/doc/ikiwiki/directive/listdirectives.mdwn
new file mode 100644 (file)
index 0000000..b41d27a
--- /dev/null
@@ -0,0 +1,20 @@
+The `listdirectives` directive is supplied by the [[!iki plugins/listdirectives desc=listdirectives]] plugin.
+
+This directive generates a list of available
+[[directives|ikiwiki/directive]].
+
+       \[[!listdirectives]]
+
+There is one optional keyword argument, `generated`.  Normally the
+`listdirectives` directive will list all built in directives and directives
+directly registered by plugins.  With this keyword, `listdirectives` will
+also list directives generated later.  For example, all [[shortcuts]] are
+directives generated in turn by the `shortcut` directive.  They will only
+be listed if the `generated` argument is supplied.
+
+    \[[!listdirectives generated]]
+
+This extended list is often quite long, and often contains many
+undocumented directives.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/map.mdwn b/doc/ikiwiki/directive/map.mdwn
new file mode 100644 (file)
index 0000000..09c95a0
--- /dev/null
@@ -0,0 +1,19 @@
+The `map` directive is supplied by the [[!iki plugins/map desc=map]] plugin.
+
+This directive generates a hierarchical page map for the wiki. Example usage:
+
+       \[[!map pages="* and !blog/* and !*/Discussion"]]
+
+If the pages to include are not specified, all pages (and other files) in
+the wiki are mapped.
+
+By default, the names of pages are shown in the map. The `show` parameter
+can be used to show the titles or descriptions of pages instead (as set by
+the [[meta]] directive). For example:
+
+       \[[!map pages="* and !blog/* and !*/Discussion" show=title]]
+
+Hint: To limit the map to displaying pages less than a certain level deep,
+use a [[ikiwiki/PageSpec]] like this: `pages="* and !*/*/*"`
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/map/discussion.mdwn b/doc/ikiwiki/directive/map/discussion.mdwn
new file mode 100644 (file)
index 0000000..062b426
--- /dev/null
@@ -0,0 +1,74 @@
+Question: Is there a way to generate a listing that shows *both* title and description meta information? Currently, a \[\[!map ...]] shows only one of the two, but I'd like to generate a navigation that looks like a description list. For example:
+
+ * This is the title meta information.
+
+   This is the description meta information
+
+ * This is another title.  
+
+   And so on ...
+
+Is that possible?
+
+--Peter
+
+----
+
+The site I'm trying to set up right now (not really a wiki - no public editing) is divided into topics.  Topics are pages that have `\[[!meta link="/topic"]]`.  Topic pages contain an index of their subpages (done with `\[[!inline]]`); the subpages are the real content.  I want a map in the sidebar that lists:
+
+ * all of the topics;
+ * all of the first-level subpages of the *current topic only*.
+
+That is, if the current page is "Topic A" or "Topic A/Page 1", then the map should look like
+
+    Topic A
+        Page 1
+        Page 2
+        Page 3
+    Topic B
+    Topic C
+
+but if the current page is "Topic B" or one of its subpages, then the map should look like
+
+    Topic A
+    Topic B
+        Page 1
+        Page 2
+        Page 3
+    Topic C
+
+On the top-level index page, or on any other page that is neither a topic nor a subpage of a topic, the map should list only the topics.
+
+Is there any way to do that?  I don't mind mucking around with `\[[!meta]]` on every page if that's what it takes.
+
+-- Zack
+
+> I think that you're looking for this:
+> 
+> `pages="((Topic*/* or Topic*) and ./*) or (Topic* and ! Topic*/*)"`
+> 
+> Let's pull that [[PageSpec]] apart. 
+> 
+> * `(Topic*/* or Topic*)` matches all pages that are underneath a Topic
+>    page or are a topic page themselves.
+> * `and ./*` further adds the limitation that the pages have to be
+>   in the same directory as the page that is displaying the map. So,
+>   for `Topic_A/Page_1`, it will match `Topic_A/*`; for `Topic_A`,
+>   it will match `Topic_*` but not subpages.
+> * Finally, `Topic* and ! Topic*/*` matches all the toplevel topic pages,
+>   since we always want those to show up.
+> 
+> I haven't tested that this works or displays, but I hope it gets you
+> on the right track. PS, be aware of
+> [[this_sidebar_issue|todo/Post-compilation_inclusion_of_the_sidebar]]!
+> --[[Joey]]
+
+>> Thanks, but this assumes that topic pages are named `Topic<something>`.
+>> They aren't.  They are tagged with `\[[!meta link="/topic"]]`, and as
+>> far as I can tell there is no [[PageSpec]] notation for "subpages of a
+>> page that satisfies link(foo)"...
+>> -- Zack
+
+>>> I think that the ideas and code in
+>>> [[todo/tracking_bugs_with_dependencies]] might also handle this case.
+>>> --[[Joey]]
diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn
new file mode 100644 (file)
index 0000000..000f461
--- /dev/null
@@ -0,0 +1,161 @@
+The `meta` directive is supplied by the [[!iki plugins/meta desc=meta]] plugin.
+
+This directive allows inserting arbitrary metadata into the source of a page.
+Enter the metadata as follows:
+
+       \[[!meta field="value"]]
+       \[[!meta field="value" param="value" param="value"]]
+
+The first form sets a given field to a given value, while the second form
+also specifies some additional sub-parameters.
+
+The field values are treated as HTML entity-escaped text, so you can include
+a quote in the text by writing `&quot;` and so on.
+
+Supported fields:
+
+* title
+
+  Overrides the title of the page, which is generally the same as the
+  page name.
+
+  Note that if the title is overridden, a "title_overridden" variable will
+  be set to a true value in the template; this can be used to format things
+  differently in this case.
+
+* license
+
+  Specifies a license for the page, for example, "GPL". Can contain
+  WikiLinks and arbitrary markup.
+
+* copyright
+
+  Specifies the copyright of the page, for example, "Copyright 2007 by
+  Joey Hess". Can contain WikiLinks and arbitrary markup.
+
+* author
+
+  Specifies the author of a page.
+
+* authorurl
+
+  Specifies an url for the author of a page.
+
+* description
+
+  Specifies a "description" of the page. You could use this to provide
+  a summary, for example, to be picked up by the [[map]] directive.
+
+* permalink
+
+  Specifies a permanent link to the page, if different than the page
+  generated by ikiwiki.
+
+* date
+
+  Specifies the creation date of the page. The date can be entered in
+  nearly any format, since it's parsed by [[!cpan TimeDate]].
+
+* stylesheet
+
+  Adds a stylesheet to a page. The stylesheet is treated as a wiki link to
+  a `.css` file in the wiki, so it cannot be used to add links to external
+  stylesheets. Example:
+
+       \[[!meta stylesheet=somestyle rel="alternate stylesheet"
+       title="somestyle"]]
+
+* openid
+
+  Adds html &lt;link&gt; tags to perform OpenID delegation to an external
+  OpenID server. This lets you use an ikiwiki page as your OpenID.
+
+  By default this will delegate for both `openid` and `openid2`. To only
+  delegate for one, add a parameter such as `delegate=openid`.
+
+  An optional `xrds-location`
+  parameter lets you specify the location of any [eXtensible Resource
+  DescriptorS](http://www.windley.com/archives/2007/05/using_xrds.shtml).
+
+  Example:
+
+       \\[[!meta openid="http://joeyh.myopenid.com/"
+       server="http://www.myopenid.com/server"
+       xrds-location="http://www.myopenid.com/xrds?username=joeyh.myopenid.com""]]
+
+* link
+
+  Specifies a link to another page. This can be used as a way to make the
+  wiki treat one page as linking to another without displaying a user-visible
+  [[ikiwiki/WikiLink]]:
+
+       \[[!meta link=otherpage]]
+
+  It can also be used to insert a html &lt;link&gt; tag. For example:
+
+       \[[!meta link="http://joeyh.myopenid.com/" rel="openid.delegate"]]
+
+  However, this latter syntax won't be allowed if the 
+  [[!iki plugins/htmlscrubber desc=htmlscrubber]] plugin is enabled, since it can be used to
+  insert unsafe content.
+
+* redir
+
+  Causes the page to redirect to another page in the wiki.
+
+       \[[!meta redir=otherpage]]
+
+  Optionally, a delay (in seconds) can be specified. The default is to
+  redirect without delay.
+
+  It can also be used to redirect to an external url. For example:
+
+       \[[!meta redir="http://example.com/"]]
+
+  However, this latter syntax won't be allowed if the 
+  [[!iki plugins/htmlscrubber desc=htmlscrubber]] plugin is enabled, since it can be used to
+  insert unsafe content.
+
+  For both cases, an anchor to jump to inside the destination page may also be
+  specified using the common `#ANCHOR` syntax.
+
+* robots
+
+  Causes the robots meta tag to be written:
+
+        \[[!meta robots="index, nofollow"]]
+
+  Valid values for the attribute are: "index", "noindex", "follow", and
+  "nofollow". Multiple comma-separated values are allowed, but obviously only
+  some combinations make sense. If there is no robots meta tag, "index,
+  follow" is used as the default.
+
+  The value is escaped, but its contents are not otherwise checked.
+
+* guid
+
+  Specifies a globally unique ID for a page. This guid should be a URI
+  (in particular, it can be `urn:uuid:` followed by a UUID, as per
+  [[!rfc 4122]]), and it will be used to identify the page's entry in RSS
+  and Atom feeds. If not given, the default is to use the page's URL as its
+  guid.
+
+  This is mostly useful when a page has moved, to keep the guids for
+  pages unchanged and avoid_flooding_aggregators
+  (see [[!iki tips/howto_avoid_flooding_aggregators]]).
+
+* updated
+
+  Specifies a fake modification time for a page, to be output into RSS and
+  Atom feeds. This is useful to avoid flooding aggregators that sort by
+  modification time, like Planet: for instance, when editing an old blog post
+  to add tags, you could set `updated` to be one second later than the original
+  value. The date/time can be given in any format that
+  [[!cpan TimeDate]] can understand, just like the `date` field.
+
+If the field is not one of the above predefined fields, the metadata will be
+written to the generated html page as a &lt;meta&gt; header. However, this
+won't be allowed if the [[!iki plugins/htmlscrubber desc=htmlscrubber]] plugin is enabled,
+since it can be used to insert unsafe content.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/more.mdwn b/doc/ikiwiki/directive/more.mdwn
new file mode 100644 (file)
index 0000000..5065519
--- /dev/null
@@ -0,0 +1,16 @@
+The `more` directive is supplied by the [[!iki plugins/more desc=more]] plugin.
+
+This directive provides a way to have a "more" link on a post in a blog, that
+leads to the full version of the page. Use it like this:
+
+       \[[!more linktext="click for more" text="""
+       This is the rest of my post. Not intended for people catching up on
+       their blogs at 30,000 feet. Because I like to make things
+       difficult.
+       """]]
+
+If the `linktext` parameter is omitted it defaults to just "more".
+
+Note that you can accomplish something similar using a [[toggle]] instead.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/orphans.mdwn b/doc/ikiwiki/directive/orphans.mdwn
new file mode 100644 (file)
index 0000000..b03f5ac
--- /dev/null
@@ -0,0 +1,15 @@
+The `orphans` directive is supplied by the [[!iki plugins/orphans desc=orphans]] plugin.
+
+This directive generates a list of possibly orphaned pages -- pages that no
+other page links to. Example:
+
+       \[[!orphans pages="* and !blog/*"]]
+
+The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
+pages to check for orphans, default is search them all.
+
+Note that it takes backlinks into account, but does not count inlining a
+page as linking to it, so will generally count many blog-type pages as
+orphans.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/pagecount.mdwn b/doc/ikiwiki/directive/pagecount.mdwn
new file mode 100644 (file)
index 0000000..0e6ca3c
--- /dev/null
@@ -0,0 +1,10 @@
+The `pagecount` directive is supplied by the [[!iki plugins/pagecount desc=pagecount]] plugin.
+
+This directive counts pages currently in the wiki. Example:
+
+       \[[!pagecount pages="*"]]
+
+The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
+pages to count, default is to count them all.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/pagestats.mdwn b/doc/ikiwiki/directive/pagestats.mdwn
new file mode 100644 (file)
index 0000000..426f3e4
--- /dev/null
@@ -0,0 +1,25 @@
+The `pagestats` directive is supplied by the [[!iki plugins/pagestats desc=pagestats]] plugin.
+
+This directive can generate stats about how pages link to each other. It can
+produce either a tag cloud, or a table counting the number of links to each
+page.
+
+Here's how to use it to create a [[tag]] cloud:
+
+       \[[!pagestats pages="tags/*"]]
+
+And here's how to create a table of all the pages on the wiki:
+
+       \[[!pagestats style="table"]]
+
+The optional `among` parameter limits counting to pages that match a
+[[ikiwiki/PageSpec]]. For instance, to display a cloud of tags used on blog
+entries, you could use:
+
+       \[[!pagestats pages="tags/*" among="blog/posts/*"]]
+
+or to display a cloud of tags related to Linux, you could use:
+
+       \[[!pagestats pages="tags/* and not tags/linux" among="tagged(linux)"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/pagestats/discussion.mdwn b/doc/ikiwiki/directive/pagestats/discussion.mdwn
new file mode 100644 (file)
index 0000000..3c9dc71
--- /dev/null
@@ -0,0 +1,10 @@
+I am trying to create a tag cloud using:  
+           
+     \[[!pagestats  pages="tags/*"]]
+
+Nothing shows up when I first used this directive. I found that I had to create a page for the tag for it to show up in pagestats.
+I would rather not find and create a page for every tag I have created or will create. Is there an easier way to create a list of tags?
+
+Thanks
+
+----
diff --git a/doc/ikiwiki/directive/pagetemplate.mdwn b/doc/ikiwiki/directive/pagetemplate.mdwn
new file mode 100644 (file)
index 0000000..0e4066f
--- /dev/null
@@ -0,0 +1,15 @@
+The `pagetemplate` directive is supplied by the [[!iki plugins/pagetemplate desc=pagetemplate]] plugin.
+
+This directive allows a page to be created using a different wikitemplates.
+The page text is inserted into the template, so the template controls the
+overall look and feel of the wiki page. This is in contrast to the
+[[ikiwiki/directive/template]] directive, which allows inserting templates
+_into_ the body of a page.
+
+This directive can only reference templates that are already installed
+by the system administrator, typically into the
+`/usr/share/ikiwiki/templates` directory. Example:
+
+       \[[!pagetemplate template="my_fancy.tmpl"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/paste.mdwn b/doc/ikiwiki/directive/paste.mdwn
new file mode 100644 (file)
index 0000000..a0aa0ef
--- /dev/null
@@ -0,0 +1,3 @@
+[[!meta redir=/ikiwiki/directive/cutpaste]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/ping.mdwn b/doc/ikiwiki/directive/ping.mdwn
new file mode 100644 (file)
index 0000000..691c758
--- /dev/null
@@ -0,0 +1,18 @@
+The `ping` directive is supplied by the [[!iki plugins/pinger desc=pinger]] plugin.
+
+This directive allows ikiwiki to be configured to hit a URL each time it
+updates the wiki. One way to use this is in conjunction with the [[!iki plugins/pingee desc=pingee]]
+plugin to set up a loosely coupled mirror network, or a branched version of
+a wiki. By pinging the mirror or branch each time the main wiki changes, it
+can be kept up-to-date.
+
+        \[[!ping from="http://mywiki.com/"
+        to="http://otherwiki.com/ikiwiki.cgi?do=ping"]]
+
+The "from" parameter must be identical to the url of the wiki that is doing
+the pinging. This is used to prevent ping loops.
+
+The "to" parameter is the url to ping. The example shows how to ping
+another ikiwiki instance.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/poll.mdwn b/doc/ikiwiki/directive/poll.mdwn
new file mode 100644 (file)
index 0000000..6aa3d2c
--- /dev/null
@@ -0,0 +1,25 @@
+The `poll` directive is supplied by the [[!iki plugins/poll desc=poll]] plugin.
+
+This directive allows you to create online polls in the wiki. Here's an
+example use:
+
+       \[[!poll 0 "red" 0 "green" 0 "blue"]]
+
+The numbers indicate how many users voted for that choice. When a user
+votes for a choice in the poll, the page is modified and the number
+incremented.
+
+While some basic precautions are taken to prevent users from accidentially
+voting twice, this sort of poll should not be counted on to be very
+accurate; all the usual concerns about web based polling apply. Unless the
+page that the poll is in is locked, users can even edit the page and change
+the numbers!
+
+Parameters: 
+
+* `open` - Whether voting is still open. Set to "no" to close the poll to
+  voting.
+* `total` - Show total number of votes at bottom of poll. Default is "yes".
+* `percent` - Whether to display percents. Default is "yes".
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/polygen.mdwn b/doc/ikiwiki/directive/polygen.mdwn
new file mode 100644 (file)
index 0000000..e872634
--- /dev/null
@@ -0,0 +1,11 @@
+The `polygen` directive is supplied by the [[!iki plugins/polygen desc=polygen]] plugin.
+
+This directive allows inserting text generated by polygen into a wiki page.
+For example:
+
+       \[[!polygen grammar="genius"]]
+
+It's also possible to specify a starting nonterminal for the grammar by
+including `symbol="text"` in the directive.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/postsparkline.mdwn b/doc/ikiwiki/directive/postsparkline.mdwn
new file mode 100644 (file)
index 0000000..c17d329
--- /dev/null
@@ -0,0 +1,45 @@
+The `postsparkline` directive is supplied by the [[!iki plugins/postsparkline desc=postsparkline]] plugin.
+
+This directive uses the [[!iki plugins/sparkline desc=sparkline]] plugin to create a
+[[sparkline]] of statistics about a set of pages, such as posts to a blog.
+
+# examples
+
+       Post interval: 
+       \[[!postsparkline pages="blog/* and !*/Discussion" max=100
+       formula=interval style=bar barwidth=2 barspacing=1 height=13]]
+       
+       Posts per month this year: 
+       \[[!postsparkline pages="blog/* and !*/Discussion" max=12
+       formula=permonth style=bar barwidth=2 barspacing=1 height=13]]
+
+# usage
+
+All options aside fron the `pages`, `max`, `formula`, `time`, and `color`
+options are the same as in [[sparkline]] directive.
+
+You don't need to specify any data points (though you can if you want to).
+Instead, data points are automatically generated based on the creation
+times of pages matched by the specified `pages` [[ikiwiki/PageSpec]]. A
+maximum of `max` data points will be generated.
+
+The `formula` parameter controls the formula used to generate data points.
+Available forumlae:
+
+* `interval` - The height of each point represents how long it has been
+  since the previous post.
+* `perday` - Each point represents a day; the height represents how
+  many posts were made that day.
+* `permonth` - Each point represents a month; the height represents how
+  many posts were made that month.
+* `peryear` - Each point represents a day; the height represents how
+  many posts were made that year.
+
+The `time` parameter has a default value of "ctime", since forumae use
+the creation times of pages by default. If you instead want
+them to use the modification times of pages, set it to "mtime".
+
+To change the color used to draw the sparkline, use the `color` parameter.
+For example, "color=red".
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/progress.mdwn b/doc/ikiwiki/directive/progress.mdwn
new file mode 100644 (file)
index 0000000..529f1c3
--- /dev/null
@@ -0,0 +1,18 @@
+The `progress` directive is supplied by the [[!iki plugins/progress desc=progress]] plugin.
+
+This directive generates a progress bar.
+
+There are two possible parameter sets.  The first is a single parameter
+"percent" which holds a percentage figure of how complete the progress bar is.
+
+The second possible set of parameters is a pair of [[ikiwiki/PageSpec]]s,
+`totalpages` and `donepages`. The directive counts the number of
+pages in each pagespec and shows the percentage of the total pages that are
+done.
+
+For example, to show what percentage of pages have
+discussion pages:
+
+       \[[!progress totalpages="* and !*/Discussion" donepages="*/Discussion"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/shortcut.mdwn b/doc/ikiwiki/directive/shortcut.mdwn
new file mode 100644 (file)
index 0000000..29db86c
--- /dev/null
@@ -0,0 +1,9 @@
+The `shortcut` directive is supplied by the [[!iki plugins/shortcut desc=shortcut]] plugin.
+
+This directive allows external links to commonly linked to sites to be made
+more easily using shortcuts.
+
+The available shortcuts are defined on the [[shortcuts]] page in
+the wiki. The `shortcut` directive can only be used on that page.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/sparkline.mdwn b/doc/ikiwiki/directive/sparkline.mdwn
new file mode 100644 (file)
index 0000000..1f691e1
--- /dev/null
@@ -0,0 +1,52 @@
+The `sparkline` directive is supplied by the [[!iki plugins/sparkline desc=sparkline]] plugin.
+
+This directive allows for embedding sparklines into wiki pages. A
+sparkline is a small word-size graphic chart, that is designed to be
+displayes alongside text.
+
+# examples
+
+       \[[!sparkline 1 3 5 -3 10 0 width=40 height=16
+       featurepoint="4,-3,red,3" featurepoint="5,10,green,3"]]
+
+This creates a simple line graph, graphing several points.
+It will be drawn 40 pixels wide and 16 pixels high. The high point in the
+line has a green marker, and the low point has a red marker.
+
+       \[[!sparkline 1 -1(red) 1 -1(red) 1 1 1 -1(red) -1(red) style=bar barwidth=2
+       barspacing=1 height=13]]
+
+This more complex example generates a bar graph. 
+The bars are 2 pixels wide, and separated by one pixel, and the graph is 13
+pixels tall. Width is determined automatically for bar graphs. The points
+with negative values are colored red, instead of the default black.
+
+# usage
+
+The form for the data points is "x,y", or just "y" if the x values don't
+matter. Bar graphs can also add "(color)" to specify a color for that bar.
+
+The following named parameters are recognised. Most of these are the same
+as those used by the underlying sparkline library, which is documented in
+more detail in [its wiki](http://sparkline.wikispaces.com/usage).
+
+* `style` - Either "line" (the default) or "bar".
+* `width` - Width of the graph in pixels. Only needed for line graphs.
+* `height` - Height of the graph in pixels. Defaults to 16.
+* `barwidth` - Width of bars in a bar graph. Default is 1 pixel.
+* `barspacing` - Spacing between bars in a bar graph, in pixels. Default is
+  1 pixel.
+* `ymin`, `ymax` - Minimum and maximum values for the Y axis. This is
+  normally calculated automatically, but can be explicitly specified to get
+  the same values for multiple related graphs.
+* `featurepoint` - Adds a circular marker to a line graph, with optional
+  text. This can be used to label significant points.
+  
+  The value is a comma-delimited list of parameters specifying the feature
+  point: X value, Y value, color name, circle diameter, text (optional),
+  and text location (optional). Example: `featurepoint="3,5,blue,3"`
+  
+  Available values for the text location are: "top", "right", "bottom", and
+  "left".
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/table.mdwn b/doc/ikiwiki/directive/table.mdwn
new file mode 100644 (file)
index 0000000..e27a94b
--- /dev/null
@@ -0,0 +1,45 @@
+The `table` directive is supplied by the [[!iki plugins/table desc=table]] plugin.
+
+This directive can build HTML tables from data in CSV (comma-separated values)
+or DSV (delimiter-separated values) format.
+
+## examples
+
+       \[[!table data="""
+       Customer|Amount
+       Fulanito|134,34
+       Menganito|234,56
+       Menganito|234,56
+       """]]
+    
+       \[[!table class="book_record" format=csv file="data/books/record1"]]
+
+In this second example the `record1` page should be similar to:
+
+       "Title","Perl Best Practices"
+       "Author","Damian Conway"
+       "Publisher","O’Reilly"
+
+To make a cell span multiple columns, follow it with one or more empty
+cells. For example:
+
+       \[[!table data="""
+       left||right|
+       a|b|c|d
+       this cell spans 4 columns|||
+       """]]
+
+## usage
+
+* `data` - Values for the table.
+* `file` - A file in the wiki containing the data.
+* `format` - The format of the data, either "csv", "dsv", or "auto"
+  (the default).
+* `delimiter` - The character used to separate fields. By default,
+   DSV format uses a pipe (`|`), and CSV uses a comma (`,`).
+* `class` - A CSS class for the table html element.
+* `header` - By default, or if set to "row", the first data line is used
+  as the table header. Set it to "no" to make a table without a header, or
+  "column" to make the first column be the header.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/tag.mdwn b/doc/ikiwiki/directive/tag.mdwn
new file mode 100644 (file)
index 0000000..64736f8
--- /dev/null
@@ -0,0 +1,34 @@
+The `tag` and `taglink` directives are supplied by the [[!iki plugins/tag desc=tag]] plugin.
+
+These directives allow tagging pages. List tags as follows:
+
+       \[[!tag tech life linux]]
+
+The tags work the same as if you had put a (hidden) [[ikiwiki/WikiLink]] on
+the page for each tag, so you can use a [[ikiwiki/PageSpec]] match all
+pages that are tagged with a given tag, for example. The tags will also
+show up on blog entries and at the bottom of the tagged pages, as well as
+in RSS and Atom feeds.
+
+If you want a visible [[ikiwiki/WikiLink]] along with the tag, use taglink
+instead:
+
+       \[[!taglink foo]]
+       \[[!taglink tagged_as_foo|foo]]
+
+Note that if the wiki is configured to use a tagbase, then the tags will be
+located under a base directory, such as "tags/". This is a useful way to
+avoid having to write the full path to tags, if you want to keep them
+grouped together out of the way.
+
+Bear in mind that specifying a tagbase means you will need to incorporate it
+into the `link()` [[ikiwiki/PageSpec]] you use: e.g., if your tagbase is
+`tag`, you would match pages tagged "foo" with `link(tag/foo)`.
+
+If you want to override the tagbase for a particular tag, you can use
+something like this:
+
+       \[[!tag ./foo]]
+       \[[!taglink /foo]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/taglink.mdwn b/doc/ikiwiki/directive/taglink.mdwn
new file mode 100644 (file)
index 0000000..dbfabf8
--- /dev/null
@@ -0,0 +1,3 @@
+[[!meta redir=/ikiwiki/directive/tag]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/template.mdwn b/doc/ikiwiki/directive/template.mdwn
new file mode 100644 (file)
index 0000000..d538b69
--- /dev/null
@@ -0,0 +1,18 @@
+The `template` directive is supplied by the [[!iki plugins/template desc=template]] plugin.
+
+[[Templates]] are files that can be filled out and inserted into pages in the
+wiki, by using the template directive. The directive has an `id` parameter
+that identifies the template to use. The remaining parameters are used to
+fill out the template.
+
+Example:
+
+       \[[!template id=note text="""Here is the text to insert into my note."""]]
+
+This fills out the `note` template, filling in the `text` field with
+the specified value, and inserts the result into the page.
+
+For a list of available templates, and details about how to create more,
+see the [[templates]] page.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/testpagespec.mdwn b/doc/ikiwiki/directive/testpagespec.mdwn
new file mode 100644 (file)
index 0000000..dde7d99
--- /dev/null
@@ -0,0 +1,24 @@
+The `testpagespec` directive is supplied by the [[!iki plugins/testpagespec desc=testpagespec]] plugin.
+
+This directive allows testing a [[ikiwiki/PageSpec]] to see if it matches a
+page, and to see the part that matches, or causes the match to fail.
+
+Example uses:
+
+       \[[!testpagespec pagespec="foopage and barpage" match="foopage"]]
+
+This will print out something like "no match: barpage does not match
+foopage", highlighting which part of the [[ikiwiki/PageSpec]] is causing
+the match to fail.
+       
+       \[[!testpagespec pagespec="foopage or !bar*" match="barpage"]]
+
+This will print out something like "no match: bar* matches barpage", since
+the part of the [[ikiwiki/PageSpec]] that fails is this negated match.
+       
+       \[[!testpagespec pagespec="foopage or barpage" match="barpage"]]
+
+This will print out something like "match: barpage matches barpage",
+indicating the part of the [[ikiwiki/PageSpec]] that caused it to match.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/testpagespec/discussion.mdwn b/doc/ikiwiki/directive/testpagespec/discussion.mdwn
new file mode 100644 (file)
index 0000000..66c9a9c
--- /dev/null
@@ -0,0 +1,6 @@
+How does one test a user identity?  I tried "pagename and user(username) for the match, and had a "no user specified" error.
+
+> You can't test them with this directive, because such pagespecs test to
+> see if logged in user, who is performing some action, matches. When the
+> page with the directive is built, the concept of a user being logged in
+> doesn't really apply. --[[Joey]] 
diff --git a/doc/ikiwiki/directive/teximg.mdwn b/doc/ikiwiki/directive/teximg.mdwn
new file mode 100644 (file)
index 0000000..992a3f6
--- /dev/null
@@ -0,0 +1,23 @@
+The `teximg` directive is supplied by the [[!iki plugins/teximg desc=teximg]] plugin.
+
+This directive renders LaTeX formulas into images.
+
+## examples
+
+       \[[!teximg code="\frac{1}{2}"]]
+       \[[!teximg code="E = - \frac{Z^2 \cdot  \mu \cdot e^4}{32\pi^2 \epsilon_0^2 \hbar^2 n^2}" ]]
+
+To scale the image, use height=x:
+
+       \[[!teximg code="\frac{1}{2}" height="17"]]
+       \[[!teximg code="\frac{1}{2}" height="8"]]
+
+If no height is chosen the default height 12 is used. Valid heights are: 8, 9,
+10, 11, 12, 14, 17, 20. If another height is entered, the closest available
+height is used.
+
+To add an alt text to the image, use alt="text":
+
+       \[[!teximg code="\frac{1}{2}" alt="1/2"]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/toc.mdwn b/doc/ikiwiki/directive/toc.mdwn
new file mode 100644 (file)
index 0000000..bf504da
--- /dev/null
@@ -0,0 +1,21 @@
+The `toc` directive is supplied by the [[!iki plugins/toc desc=toc]] plugin.
+
+Add a table of contents to a page:
+
+       \[[!toc ]]
+
+The table of contents will be automatically generated based on the
+headers of the page. By default only the largest headers present on the
+page will be shown; to control how many levels of headers are shown, use
+the `levels` parameter:
+
+       \[[!toc levels=2]]
+
+The toc directive will take the level of the first header as the topmost
+level, even if there are higher levels seen later in the file.
+
+The table of contents will be created as an ordered list. If you want
+an unordered list instead, you can change the list-style in your local
+style sheet.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/toggle.mdwn b/doc/ikiwiki/directive/toggle.mdwn
new file mode 100644 (file)
index 0000000..db11f03
--- /dev/null
@@ -0,0 +1,34 @@
+The `toggle` and `toggleable` directives are supplied by the [[!iki plugins/toggle desc=toggle]] plugin.
+
+With these directives you can create links on pages that, when clicked, toggle
+display of other parts of the page.
+
+It uses javascript to accomplish this; browsers without javascript will
+always see the full page content.
+
+Example use:
+
+       \[[!toggle id="ipsum" text="show"]]
+
+       \[[!toggleable id="ipsum" text="""
+       Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
+       eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
+       ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+       aliquip ex ea commodo consequat.
+
+       [[!toggle id="ipsum" text="hide"]]
+       """]]
+
+Note that you can include wiki markup in the toggleable text,
+including even additional toggles, as shown in the above example.
+
+Also, the toggle and the togglable definitions do not need to be next to
+each other, but can be located anywhere on the page. There can also be
+mutiple toggles that all toggle a single togglable.
+
+The id has a default value of "default", so can be omitted in simple cases.
+
+If you'd like a toggleable to be displayed by default, and toggle to
+hidden, then pass a parameter "open=yes" when setting up the toggleable.
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/toggleable.mdwn b/doc/ikiwiki/directive/toggleable.mdwn
new file mode 100644 (file)
index 0000000..5536f44
--- /dev/null
@@ -0,0 +1,3 @@
+[[!meta redir=/ikiwiki/directive/toggle]]
+
+[[!meta robots="noindex, follow"]]
diff --git a/doc/ikiwiki/directive/version.mdwn b/doc/ikiwiki/directive/version.mdwn
new file mode 100644 (file)
index 0000000..f1e2085
--- /dev/null
@@ -0,0 +1,12 @@
+The `version` directive is supplied by the [[!iki plugins/version desc=version]] plugin.
+
+This directive allows inserting the version of ikiwiki onto a page.
+
+Whenever ikiwiki is upgraded to a new version, the page will be rebuilt,
+updating the version number.
+
+Use is simple:
+
+       \[[!version ]]
+
+[[!meta robots="noindex, follow"]]
index 29dbce181563ce00af528ffe1cc9918e8da87e49..befbce9aa421b3255bf8bb4012c898e38030e1b9 100644 (file)
@@ -7,7 +7,7 @@ called [[MarkDown]], and it works like this:
 
 Leave blank lines between paragraphs.
 
-You can \**emphasise*\* or \*\***strongly emphasise**\*\* text by placing it
+You can *\*emphasise\** or **\*\*strongly emphasise\*\*** text by placing it
 in single or double asterisks.
 
 To create a list, start each line with an asterisk:
@@ -70,26 +70,37 @@ you use the following additional features:
        \[[!wikipedia War\_of\_1812]]
 """]]
 
+[[!if test="enabled(template) and templates" then="""
+* Create and fill out [[templates]] for repeated chunks of
+  parameterized wiki text.
+"""]]
+
+* Insert various [[directives|directive]] onto a page to perform useful
+  actions.
+[[!if test="enabled(toc) or enabled(meta) or enabled(inline)" then="""
+  For example, you can:
+"""]]
+
 [[!if test="enabled(toc)" then="""
-* Add a table of contents to a page:
+  * Add a table of contents to a page:
 
-       \[[!toc ]]
+       \[[!toc]]
 """]]
 
 
 [[!if test="enabled(meta)" then="""
-* Change the title of a page:
+  * Change the title of a page:
 
        \[[!meta title="full page title"]]
 """]]
 
-[[!if test="enabled(inline) and blog" then="""
-* Create a [[blog]] by inlining a set of pages:
+[[!if test="enabled(inline)" then="""
+  * Create a blog by inlining a set of pages:
 
        \[[!inline pages="blog/*"]]
 """]]
 
-[[!if test="enabled(template) and templates" then="""
-* Create and fill out [[templates]] for repeated chunks of
-  parameterized wiki text.
+[[!if test="enabled(listdirectives)" then="""
+  Full list of [[directives|directive]] enabled for this wiki:
+  [[!listdirectives ]]
 """]]
index bbda9add70a07f5862ef0aba66bd8088e8f807e3..68419192942abb3c25758e5d8b52f319bf8311f1 100644 (file)
@@ -4,10 +4,8 @@ is a minimal markup language that resembles plain text as used in
 email messages. It is the markup language used by this wiki by default.
 
 For documentation about the markdown syntax, see [[formatting]] and
-[Markdown: syntax](http://daringfireball.net/projects/markdown/syntax). A
-[markdown mode](http://jblevins.org/projects/markdown-mode/) for 
-emacs can help in editing.
+[Markdown: syntax](http://daringfireball.net/projects/markdown/syntax).
 
-Note that [[WikiLink]]s and [[PreProcessorDirective]]s are not part of the
-markdown syntax, and are the only bit of markup that this wiki handles
-internally.
+Note that [[WikiLinks|WikiLink]] and [[directives|directive]] are not part
+of the markdown syntax, and are the only bit of markup that this wiki
+handles internally.
index dd851e5492353a3adc0b04de76d40880bd94edb5..a7965528486143de1f2be5cd255062e6786763f3 100644 (file)
@@ -16,7 +16,7 @@ To sign up for an OpenID, visit one of the following identity providers:
 * [Videntity](http://videntity.org/)
 * [LiveJournal](http://www.livejournal.com/openid/)
 * [TrustBearer](https://openid.trustbearer.com/)
-* or any of the [many others out there](http://openiddirectory.com/openid-providers-c-1.html).
+* or any of the [many others out there](http://openiddirectory.com/openid-providers-c-1.html)
 
 Your OpenID is the URL that you are given when you sign up.
 [[!if test="enabled(openid)" then="""
index 156e3f6ca84a40eeb1c0b2009200d48f28675996..5f0f44e2ebe6cf847bfe2b6c8b73d8e62ad4969b 100644 (file)
@@ -22,25 +22,35 @@ match all pages except for Discussion pages and the SandBox:
 
        * and !SandBox and !*/Discussion
 
-Some more elaborate limits can be added to what matches using any of these
-functions:
+Some more elaborate limits can be added to what matches using these functions:
 
-* "`link(page)`" - match only pages that link to a given page (or glob)
-* "`backlink(page)`" - match only pages that a given page links to
-* "`creation_month(month)`" - match only pages created on the given month
+* "`link(page)`" - matches only pages that link to a given page (or glob)
+* "`tagged(tag)`" - matches pages that are tagged or link to the given tag (or
+  tags matched by a glob)
+* "`backlink(page)`" - matches only pages that a given page links to
+* "`creation_month(month)`" - matches only pages created on the given month
 * "`creation_day(mday)`" - or day of the month
 * "`creation_year(year)`" - or year
-* "`created_after(page)`" - match only pages created after the given page
+* "`created_after(page)`" - matches only pages created after the given page
   was created
-* "`created_before(page)`" - match only pages created before the given page
+* "`created_before(page)`" - matches only pages created before the given page
   was created
-* "`glob(someglob)`" - match pages that match the given glob. Just writing
+* "`glob(someglob)`" - matches pages that match the given glob. Just writing
   the glob by itself is actually a shorthand for this function.
 * "`internal(glob)`" - like `glob()`, but matches even internal-use 
   pages that globs do not usually match.
 * "`title(glob)`", "`author(glob)`", "`authorurl(glob)`",
   "`license(glob)`", "`copyright(glob)`" - match pages that have the given
   metadata, matching the specified glob.
+* "`user(username)`" - tests whether a modification is being made by a
+  user with the specified username. If openid is enabled, an openid can also
+  be put here.
+* "`admin()`" - tests whether a modification is being made by one of the
+  wiki admins.
+* "`ip(address)`" - tests whether a modification is being made from the
+  specified IP address.
+* "`postcomment(glob)`" - matches only when comments are being 
+  posted to a page matching the specified glob
 
 For example, to match all pages in a blog that link to the page about music
 and were written in 2005:
@@ -57,29 +67,10 @@ More complex expressions can also be created, by using parentheses for
 grouping. For example, to match pages in a blog that are tagged with either
 of two tags, use:
 
-       blog/* and (link(tag/foo) or link(tag/bar))
+       blog/* and (tagged(foo) or tagged(bar))
 
 Note that page names in PageSpecs are matched against the absolute
 filenames of the pages in the wiki, so a pagespec "foo" used on page
 "a/b" will not match a page named "a/foo" or "a/b/foo". To match
 relative to the directory of the page containing the pagespec, you can
 use "./". For example, "./foo" on page "a/b" matches page "a/foo".
-
-## Old syntax
-
-The old PageSpec syntax was called a "GlobList", and worked differently in
-two ways:
-
-1. "and" and "or" were not used; any page matching any item from the list
-   matched.
-2. If an item was prefixed with "`!`", then no page matching that item
-   matched, even if it matched an earlier list item.
-
-For example, here is the old way to match all pages except for the SandBox
-and Discussion pages:
-
-       * !SandBox !*/Discussion
-
-Using this old syntax is still supported. However, the old syntax is
-deprecated and will be removed at some point, and using the new syntax is
-recommended.
index 2a1f8aaab2642f5b1f4aec10231a974275dcdfcf..419f00ee4284f3a0bae6305e290a1ef8d5cef95a 100644 (file)
@@ -4,53 +4,34 @@
      else="This wiki has attachments **disabled**."]]
 
 If attachments are enabled, the wiki admin can control what types of
-attachments will be accepted, by entering a [[ikiwiki/PageSpec]] in the
-"Allowed Attachments" field of their preferences page.
+attachments will be accepted, via the `allowed_attachments`
+configuration setting.
 
 For example, to limit arbitrary files to 50 kilobytes, but allow
 larger mp3 files to be uploaded by joey into a specific directory, and
-check all attachments for virii, something like this could be used:
+check all attachments for viruses, something like this could be used:
   
        virusfree() and ((user(joey) and podcast/*.mp3 and mimetype(audio/mpeg) and maxsize(15mb)) or (!ispage() and maxsize(50kb)))
 
-The regular [[ikiwiki/PageSpec]] syntax is expanded with thw following
+The regular [[ikiwiki/PageSpec]] syntax is expanded with the following
 additional tests:
 
-* maxsize(size)
-
-  Tests whether the attachment is no larger than the specified size.
-  The size defaults to being in bytes, but "kb", "mb", "gb" etc can be
-  used to specify the units.
+* "`maxsize(size)`" - tests whether the attachment is no larger than the
+  specified size. The size defaults to being in bytes, but "kb", "mb", "gb"
+  etc can be used to specify the units.
   
-* minsize(size)
-
-  Tests whether the attachment is no smaller than the specified size.
-
-* ispage()
+* "`minsize(size)`" - tests whether the attachment is no smaller than the
+  specified size.
 
-  Tests whether the attachment will be treated by ikiwiki as a wiki page.
-  (Ie, if it has an extension of ".mdwn", or of any other enabled page
-  format).
+* "`ispage()`" - tests whether the attachment will be treated by ikiwiki as a
+  wiki page. (Ie, if it has an extension of ".mdwn", or of any other enabled
+  page format).
 
   So, if you don't want to allow wiki pages to be uploaded as attachments,
   use `!ispage()` ; if you only want to allow wiki pages to be uploaded
   as attachments, use `ispage()`.
 
-* user(username)
-
-  Tests whether the attachment is being uploaded by a user with the
-  specified username. If openid is enabled, an openid can also be put here.
-
-* ip(address)
-
-  Tests whether the attacment is being uploaded from the specified IP
-  address.
-
-* mimetype(foo/bar)
-
-  This checks the MIME type of the attachment. You can include a glob
-  in the type, for example `mimetype(image/*)`.
-
-* virusfree()
+* "`mimetype(foo/bar)`" - checks the MIME type of the attachment. You can
+  include a glob in the type, for example `mimetype(image/*)`.
 
-  Checks the attachment with an antiviral program.
+* "`virusfree()`" - checks the attachment with an antiviral program.
diff --git a/doc/ikiwiki/pagespec/attachment/discussion.mdwn b/doc/ikiwiki/pagespec/attachment/discussion.mdwn
new file mode 100644 (file)
index 0000000..373242b
--- /dev/null
@@ -0,0 +1,15 @@
+Would it be possible to factor out this pagespec 
+code so that other plugins can use it without enabling attachments?
+I am interested for [[todo/mbox]] --[[DavidBremner]]
+
+> I can split out all of them except for `ip()` and `user()` easily. I
+> have just changed the code so the rest will test the existing source file
+> is no other filename is specified. Do you have any reason to want to
+> check ip addresses and user names? Not sure what to call the plugin, but
+> breaking it out is easy enough. --[[Joey]]
+
+>> I don't think `ip()` and `user()` necessarily make sense for a mail box 
+>> that is already on the disk, so no, I don't think I'll miss
+>> them. --[[DavidBremner]] 
+
+>>> Done, [[plugins/filecheck]] --[[Joey]]
index 0733c90c8efd7cc8a47b55d91f3cdd10fbcc1432..4eed3722ccc744595fc8380e68e69dc9e1ad6450 100644 (file)
@@ -65,3 +65,30 @@ How can I fix this?  --[[sabr]]
 
 > I don't see why that wouldn't work. Can I download the source to your
 > wiki from somewhere to investigate? --[[Joey]]
+
+----
+
+Should negation work with user(), with locked_pages in setup?  I
+experimented with setting locked_pages => 'user(someuser)' and was able to
+edit as a different user.  However, setting locked_pages =>
+'!user(someuser)' doesn't seem to allow edits for only 'someuser' - it
+locks out all users.
+
+> Negation works with anything in any PageSpec. I tested the case you
+> describe, and a negated pagespec worked for me; all users except the
+> listed user (and except wiki admins of course) were locked out.
+> --[[Joey]] 
+
+>> It must be a local problem, then, cause I've tried it with two separate 
+>> machines.  Both are running the most recent release of ikiwiki in 
+>> pkgsrc - 2.66.  Perhaps an update to a newer version would solve the issue.
+
+----
+
+Is there a way to refer to all subpages of the current page, if  the name of the 
+current page is not known (i.e. the pagespec is used in a template)? The ./ syntax
+does not seem suitable for this, as
+
+> \[[!map pages="./*"]]
+
+also lists the current page and all its siblings.
diff --git a/doc/ikiwiki/pagespec/po.mdwn b/doc/ikiwiki/pagespec/po.mdwn
new file mode 100644 (file)
index 0000000..e0264dd
--- /dev/null
@@ -0,0 +1,16 @@
+[[!if test="enabled(po)"
+     then="This wiki has po support **enabled**."
+     else="This wiki has po support **disabled**."]]
+
+If the [[!iki plugins/po desc=po]] plugin is enabled, the regular
+[[ikiwiki/PageSpec]] syntax is expanded with the following additional
+tests that can be used to improve user navigation in a multi-lingual
+wiki:
+
+* "`lang(LL)`" - tests whether a page is written in the language
+  specified as a ISO639-1 (two-letter) language code.
+* "`currentlang()`" - tests whether a page is written in the same
+  language as the current page.
+
+Note that every non-po page is considered to be written in
+`po_master_language`, as specified in `ikiwiki.setup`.
diff --git a/doc/ikiwiki/preprocessordirective.mdwn b/doc/ikiwiki/preprocessordirective.mdwn
deleted file mode 100644 (file)
index 743c0d9..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-[[!meta robots="noindex, follow"]]
-Preprocessor directives are similar to a [[WikiLink]] in form, except they
-begin with `!` and may contain parameters. The general form is:
-
-       \[[!directive param="value" param="value"]]
-
-This gets expanded before the rest of the page is processed, and can be used
-to transform the page in various ways.
-
-The quotes around values can be omitted if the value is a simple word.
-Also, some directives may use parameters without values, for example:
-
-       \[[!tag foo]]
-
-A preprocessor directive does not need to all be on one line, it can be
-wrapped to multiple lines if you like:
-       
-       \[[!directive foo="baldersnatch"
-       bar="supercalifragalisticexpealadocious" baz=11]]
-
-Also, multiple lines of *quoted* text can be used for a value.
-To allow quote marks inside the quoted text, delimit the block
-of text with triple-quotes:
-
-       \[[!directive text="""
-       1. "foo"
-       2. "bar"
-       3. "baz"
-       """]]
-
-ikiwiki also has an older syntax for preprocessor directives, which requires a
-space in directives to distinguish them from [[wikilinks|wikilink]].  This
-syntax has several disadvantages: it requires a space after directives with no
-parameters (such as `\[[pagecount ]]`), and it prohibits spaces in
-[[wikilinks|wikilink]].  ikiwiki now provides the `!`-prefixed syntax shown
-above as the preferred alternative.  However, ikiwiki still supports wikis
-using the older syntax, if the `prefix_directives` option is not enabled.
-For backward compatibility with existing wikis, this option currently
-defaults to off, so ikiwiki supports the old syntax.
index 539e7193db7ebd65e532034b72c1b6337eaf8831..4c128793313c0764de628e49069e68ef3258488b 100644 (file)
@@ -5,7 +5,7 @@ then="This wiki has searching **enabled**."
 else="This wiki has searching **disabled**."]]
 
 If searching is enabled, you can enter search terms in the search field,
-as you'd expect. There are a few special things you can do to constuct
+as you'd expect. There are a few special things you can do to construct
 more powerful searches.
 
 * To match a phrase, enclose it in double quotes.
index bd5e3d1850a3fef2acf7afb20318f7bd908f33ed..f561d58505ee9262e8c875324d1fad4aa4fd5a93 100644 (file)
@@ -21,13 +21,13 @@ name as the link text. For example `\[[foo_bar|SandBox]]` links to the SandBox
 page, but the link will appear like this: [[foo_bar|SandBox]].
 
 To link to an anchor inside a page, you can use something like
-`\[[WikiLink#foo]]`
+`\[[WikiLink#foo]]` .
 
-## Preprocessor directives and wikilinks
+## Directives and WikiLinks
 
 ikiwiki has two syntaxes for
-[[preprocessor_directives|PreprocessorDirective]].  The older syntax
-used spaces to distinguish between preprocessor directives and
+[[directives|directive]].  The older syntax
+used spaces to distinguish between directives and
 wikilinks; as a result, with that syntax in use, you cannot use spaces
 in WikiLinks, and must replace spaces with underscores.  The newer
 syntax, enabled with the `prefix_directives` option in an ikiwiki
index fa3ac8604db53a9fad41925a1cb1a1b939457985..b146c9447336336ca486f4fd227fb09134f84cba 100644 (file)
@@ -1,6 +1,6 @@
-# Creating an anchor in Markdown
+# Creating an [[anchor]] in Markdown
 
-Is it a native Markdown "tag" for creating an anchor? Unfortunately,
+Is it a native Markdown "tag" for creating an [[anchor]]? Unfortunately,
 I haven't any information about it at
 [Markdown syntax](http://daringfireball.net/projects/markdown/syntax) page.
 
@@ -14,10 +14,10 @@ BTW, ikiwiki doesn't displays the #foo anchor in the example
 --[[Paweł|ptecza]]
 
 > No such syntax exists in markdown.  ikiwiki could certainly have a
-> [[preprocessor_directive|preprocessordirective]] for it, though.
+> [[preprocessor_directive|directive]] for it, though.
 > --[[JoshTriplett]]
 
->> [[tag wishlist]]
+>> [[!tag wishlist]]
 >> I'd like to implement such a thing.  Joey, what is this supposed to look like?
 >> `\[[anchor WHATEVER]]`?  --[[tschwinge]]
 
@@ -51,6 +51,19 @@ simply write [[wikilink]]s like `\[[../bar]]` (or even just `\[[..]]`?), but
 this doesn't work, so I had to resort to using `\[[foo/bar]]` instead.
 --[[tschwinge]]
 
+> I believe, that doesn't entirely solve the problem. Just assume, your hierarchy is `/foo/bar/foo/bar`.
+
+> How do you access from the page `/foo/bar/foo/bar` the `/foo/bar` and not `/foo/bar/foo/bar`?
+
+> Do we have a way to implement `\[[../..]]` or `\[[/foo/bar]]`?
+
+> Even worse, trying to link from `/foo/bar` to `/foo/bar/foo/bar` ... this will probably need `\[[./foo/bar]]` --[[Jan|jwalzer]]
+
+>> There is no ".." syntax in wikilinks, but if the link begins with "/" it
+>> is rooted at the top of the wiki, as documented in
+>> [[subpage/linkingrules]]. Therefore, every example page name you listed
+>> above will work unchanged as a wikilink to that page! --[[Joey]]
+
 ----
 
 How do I make images clickable?  The obvious guess, \[[foo.png|/index]], doesn't work.  --[[sabr]]
@@ -58,3 +71,11 @@ How do I make images clickable?  The obvious guess, \[[foo.png|/index]], doesn't
 > You can do it using the img plugin. The syntax you suggested would be ambiguous,
 > as there's no way to tell if the text is meant to be an image or displayed as-is.
 > --[[Joey]]
+
+----
+
+Is it possible to refer to a page, say \[[foobar]], such that the link text is taken from foobar's title [[directive/meta]] tag? --Peter
+
+> Not yet. :-) Any suggestion for a syntax for it? Maybe something like \[[|foobar]] ? --[[Joey]]
+
+I like your suggestion because it's short and conscise. However, it would be nice to be able to refer to more or less arbitrary meta tags in links, not just "title". To do that, the link needs two parameters: the page name and the tag name, i.e. \[[pagename!metatag]]. Any sufficiently weird separater can be used instead of '!', of course. I like \[[pagename->metatag]], too, because it reminds me of accessing a data member of a structure (which is what referencing a meta tag is, really). --Peter
index 9adda157ccc2f4a656639ceff3cc46797993dcee..e1e25a0458d3a4f423ab034467b8e6c5ec1571e9 100644 (file)
@@ -1,12 +1,15 @@
-Projects
-========
+Projects & Organizations
+========================
 
 * [This wiki](http://ikiwiki.info) (of course!)
-* [UK Software Patents info page](http://www.softwarepatents.co.uk/)
+* The [GNU Hurd](http://www.gnu.org/software/hurd/)
+* [DragonFly BSD](http://www.dragonflybsd.org/)
+* [Monotone](http://monotone.ca/wiki/FrontPage/)
+* The [Free Software Foundation](http://fsf.org) uses it for their internal wiki, with subversion.
+* The [cairo graphics library](http://cairographics.org/) website.
+* The [Portland State Aerospace Society](http://psas.pdx.edu) website.  Converted from a combination of TWiki and MoinMoin to ikiwiki, including full history ([[rcs/Git]] backend).
 * [Planet Debian upstream](http://updo.debian.net/)
-* The [ion window manager homepage](http://modeemi.fi/~tuomov/ion/)
 * [Debian Mentors wiki](http://jameswestby.net/mentors/)
-* [LinuxWorld.com's monkey.linuxworld.com contributor wiki](http://monkey.linuxworld.com/) ([[rcs/Git]] backend)
 * The [Sparse wiki](http://kernel.org/pub/linux/kernel/people/josh/sparse).
 * [The BSD Associate Admin Book Project](http://bsdwiki.reedmedia.net/)
 * The [maildirman wiki](http://svcs.cs.pdx.edu/maildirman)
@@ -16,25 +19,33 @@ Projects
 * [Braawi Ltd](http://braawi.com/) and the community site [Braawi.org](http://braawi.org/)
 * [Webconverger](http://webconverger.org/) (a Web only linux distribution) with a [blog](http://webconverger.org/blog/)
 * [debian-community.org](http://debian-community.org/)
-* The [cairo graphics library](http://cairographics.org/) website.
-* The [Portland State Aerospace Society](http://psas.pdx.edu) website.  Converted from a combination of TWiki and MoinMoin to ikiwiki, including full history ([[rcs/Git]] backend).
 * [DebTorrent](http://debtorrent.alioth.debian.org)
 * The [netconf project](http://netconf.alioth.debian.org)
 * The [Debian Packaging Handbook project](http://packaging-handbook.alioth.debian.org/wiki/)
 * The [libkdtree project](http://libkdtree.alioth.debian.org)
 * The [pcc](http://pcc.ludd.ltu.se/) (Portable C Compiler) project.  (Simple rcs backend)
-* [The TOVA Company](http://www.tovatest.com) public site. We also use it for internal documentation and issue tracking, all with a [[rcs/Git]] backend.
+* [The TOVA Company](http://www.tovatest.com) public site.  We also use it for internal documentation and issue tracking, all with a [[rcs/Git]] backend.
 * Technical support websites for [Homebase](http://support.homebase.dk) and [Kaospilotene](http://support.kaospilot.no) (each with [source](http://source.homebase.dk/) [provided](http://source.kaospilot.no/))
 * [CampusGrün Hamburg](http://www.campusgruen.org/)
 * The [awesome window manager homepage](http://awesome.naquadah.org/)
 * [Enemies of Carlotta](http://www.e-o-c.org/)
 * [vcs-pkg](http://vcs-pkg.org)
 * [vcs-home](http://vcs-home.madduck.net)
-* [GNU Hurd wiki](http://www.bddebian.com/~wiki/)
 * [Query Object Framework](http://qof.alioth.debian.org/)
 * [Estron - Object Relational Mapping interpreter](http://estron.alioth.debian.org/)
 * [Public Domain collection of Debian related tips & tricks](http://dabase.com/tips/) - please add any tips too
 * [Finnish Debian community](http://debian.fi)
+* [INCL intranuclear cascade and ABLA evaporation/fission](http://www.cs.helsinki.fi/u/kaitanie/incl/)
+* [dist-bugs](http://dist-bugs.kitenet.net/)
+* [Chaos Computer Club Düsseldorf](https://www.chaosdorf.de)
+* [monkeysphere](http://web.monkeysphere.info/)
+* [The Walden Effect](http://www.waldeneffect.org/)
+* The support pages for [Trinity Centre for High Performance Computing](http://www.tchpc.tcd.ie/support/)
+* [St Hugh of Lincoln Catholic Primary School in Surrey](http://www.sthugh-of-lincoln.surrey.sch.uk/)
+* [Pigro Network](http://www.pigro.net) is running a hg based ikiwiki. (And provides ikiwiki hosting for $10/m.)
+* [Cosin Homepage](http://cosin.ch) uses an Ikiwiki with a subversion repository.
+* [Bosco Free Orienteering Software](http://bosco.durcheinandertal.ch)
+* [MIT Student Information Processing Board](http://sipb.mit.edu/)
 
 Personal sites and blogs
 ========================
@@ -95,10 +106,31 @@ Personal sites and blogs
 * [madduck's (new) homepage](http://madduck.net)
 * [Olivier Berger's professional homepage](http://www-public.it-sudparis.eu/~berger_o/)
 * [Andrey Tarantsov's homepage](http://www.tarantsov.com/)
+* [Don Marti's blog](http://zgp.org/~dmarti/)
+* [[users/Jon]]'s [homepage](http://jmtd.net/)
+* [[xma]] is using ikiwiki (<http://maillard.mobi/~xma/>)
+* [[JanWalzer|jwalzer]]'s [homepage](http://wa.lzer.net/) -- Work in Progress
+* [[Adam_Trickett|ajt]]'s home intranet/sanbox system ([Internet site & blog](http://www.iredale.net/) -- not ikiwiki yet)
+* [[Simon_McVittie|smcv]]'s [website](http://www.pseudorandom.co.uk/) and
+  [blog](http://smcv.pseudorandom.co.uk/)
+* Svend's [website](http://www.ciffer.net/~svend/) and [blog](http://www.ciffer.net/~svend/blog/)
+* [muammar's site](http://muammar.me)
+* [Per Bothner's blog](http://per.bothner.com/blog/)
+* [Bernd Zeimetz (bzed)](http://bzed.de/)
+* [Gaudenz Steinlin](http://gaudenz.durcheinandertal.ch)
+* [Simon Kjika'qawej C.](http://simonraven.kisikew.org/) - several other sites, too.
+* [NeoCarz Wiki](http://www.neocarz.com/wiki/) Yes - its actually Ikiwiki behind that! I'm using Nginx and XSL to transform the ikiwiki renderings thanks to the valid XHTML output of ikiwiki. Great work Joey!!
+* [Natalian - Kai Hendry's personal blog](http://natalian.org/)
+* [Mick Pollard aka \_lunix_ - Personal sysadmin blog and wiki](http://www.lunix.com.au)
+* [tumashu's page](http://tumashu.github.com) This is my personal site in github  created with ikiwiki and only a page,you can get the [source](http://github.com/tumashu/tumashu/tree/master)  
+* [Skirv's Wiki](http://wiki.killfile.org) - formerly Skirv's Homepage
+* [Jimmy Tang - personal blog and wiki](http://www.sgenomics.org/~jtang)
 
 Please feel free to add your own ikiwiki site!
 
-See also: [Debian ikiwiki popcon graph](http://people.debian.org/~igloo/popcon-graphs/index.php?packages=ikiwiki)
+See also: [Debian ikiwiki popcon graph](http://qa.debian.org/popcon.php?package=ikiwiki)
 and [google search for ikiwiki powered sites](http://www.google.com/search?q=%22powered%20by%20ikiwiki%22).
 
-While nothing makes me happier than knowing that ikiwiki has happy users, dropping some change in the [[TipJar]] is a nice way to show extra appreciation.
+While nothing makes me happier than knowing that ikiwiki has happy users,
+dropping some change in the [[TipJar]] is a nice way to show extra
+appreciation.
index 2da3668d4aa3c700a703023c5177f8b09614dd85..39a9bb9210fc09dd15672144c9c5ab5d76c7bf9e 100644 (file)
@@ -29,3 +29,7 @@ Thanks, --[[Chao]]
 Thanks for the reply Joey! ikiwiki is a fantastic wiki complier, though I do
 not have my own machine momentarily, i will pay close attention to its development.
 Hopefully I will be one of the ikiwiki users one day :) cheers --[[Chao]]
+
+----
+
+Are there automated hosting sites for ikiwiki yet?  If you know one, can you add one in a new section on [[ikiwikiusers]] please?  If you don't know any and you're willing to pay to set one up (shouldn't be much more expensive than a single ikiwiki IMO), [contact me](http://www.ttllp.co.uk/contact.html) and let's talk. -- MJR
index 1a416d79888d00cc9bb15b7bf4f724142cef871b..93526c42ce5ced330645b4096e81185c025ba063 100644 (file)
@@ -2,9 +2,9 @@ Ikiwiki is a **wiki compiler**. It converts wiki pages into HTML pages
 suitable for publishing on a website. Ikiwiki stores pages and history in a
 [[revision_control_system|rcs]] such as [[Subversion|rcs/svn]] or [[rcs/Git]].
 There are many other [[features]], including support for
-[[blogging|ikiwiki/blog]], as well as a large array of [[plugins]].
+[[blogging|blog]], as well as a large array of [[plugins]].
 
-[[template id=links]]
+[[!template id=links]]
 
 ## using ikiwiki
 
@@ -15,7 +15,7 @@ with ikiwiki, and some [[tips]].
 All wikis are supposed to have a [[SandBox]], so this one does too.
 
 This site generally runs the latest release of ikiwiki; currently, it runs
-ikiwiki [[version ]].
+ikiwiki [[!version ]].
 
 ## developer resources
 
index 329673e917b15edbeef4158b241ba30e3594a5a4..d52cb0a2dc41a3a7742f27e1955972d842b3b6d4 100644 (file)
@@ -5,7 +5,7 @@ Do so here..
 Note that for more formal bug reports or todo items, you can also edit the
 [[bugs]] and [[todo]] pages.
 
-[[toc ]]
+[[!toc ]]
 
 # Installation/Setup questions
 
@@ -58,6 +58,8 @@ I'm kind of at a loss how to track this down or work around it.  Any suggestions
 >Ubuntu Hardy Heron has a debian package now, but that does not work either.
 > --Dirk 22Apr2008
 
+> This might be related to [Text::Markdown bug #37297](http://rt.cpan.org/Public/Bug/Display.html?id=37297).--ChapmanFlack 9Jul2008
+
 ----
 
 # Installation of selected docs (html)
@@ -94,7 +96,7 @@ I'd like to install ikiwiki as a non-root user. I can plow through getting all t
 perl dependencies installed because that's well documented in the perl world,
 but I don't know how to tell ikiwiki to install somewhere other than / --BrianWilson
 
-> Checkout the tips section for [[tips/SharedHosting]].  It should do the trick. --MattReynolds
+> Checkout the tips section for [[tips/DreamHost]].  It should do the trick. --MattReynolds
 
 ----
 
@@ -266,7 +268,7 @@ easily, perl is possible (but I'm not strong in perl).
 
 > Jamey Sharp and I have a set of scripts in progress to convert other wikis to ikiwiki, including history, so that we can migrate a few of our wikis.  We already have support for migrating MoinMoin wikis to ikiwiki, including conversion of the entire history to Git.  We used this to convert the [XCB wiki](http://xcb.freedesktop.org/wiki/) to ikiwiki; until we finalize the conversion and put the new wiki in place of the old one, you can browse the converted result at <http://xcb.freedesktop.org/ikiwiki>.  We already plan to add support for TWiki (including history, since you can just run parsecvs on the TWiki RCS files to get Git), so that we can convert the [Portland State Aerospace Society wiki](http://psas.pdx.edu) (currently in Moin, but with much of its history in TWiki, and with many of its pages still in TWiki format using Jamey's TWiki format for MoinMoin).
 >
-> Our scripts convert by way of HTML, using portions of the source wiki's code to render as HTML (with some additional code to do things like translate MoinMoin's `\[[TableOfContents]]` to ikiwiki's `\[[toc ]]`), and then using a modified [[cpan HTML::WikiConverter]] to turn this into markdown and ikiwiki.  This produces quite satisfactory results, apart from things that don't have any markdown equivalent and thus remain HTML, such as tables and definition lists.  Conversion of the history occurs by first using another script we wrote to translate MoinMoin history to Git, then using our git-map script to map a transformation over the Git history.
+> Our scripts convert by way of HTML, using portions of the source wiki's code to render as HTML (with some additional code to do things like translate MoinMoin's `\[[TableOfContents]]` to ikiwiki's `\[[!toc ]]`), and then using a modified [[!cpan HTML::WikiConverter]] to turn this into markdown and ikiwiki.  This produces quite satisfactory results, apart from things that don't have any markdown equivalent and thus remain HTML, such as tables and definition lists.  Conversion of the history occurs by first using another script we wrote to translate MoinMoin history to Git, then using our git-map script to map a transformation over the Git history.
 >
 > We will post the scripts as soon as we have them complete enough to convert our wikis.
 >
@@ -286,6 +288,10 @@ easily, perl is possible (but I'm not strong in perl).
 
 >>> It appears the scripts were never posted?  I recently imported my Mediawiki site into Iki.  If it helps, my notes are here: <http://iki.u32.net/Mediawiki_Conversion> --[[sabr]]
 
+>>>>> The scripts have been posted now, see [[joshtriplett]]'s user page, 
+>>>>> and I've pulled together all ways I can find to [[convert]] other
+>>>>> systems into ikiwiki. --[[Joey]]
+
 ----
 
 # LaTeX support?
@@ -409,7 +415,7 @@ I'm sure that this is documented somewhere but I've ransacked the wiki and I can
 > The default `wiki_file_regexp` matches filenames containing only
 > `[-[:alnum:]_.:/+]`
 > 
-> The IkiWiki::titlepage() function will convert freeform text to a valid
+> The titlepage() function will convert freeform text to a valid
 > page name. See [[todo/should_use_a_standard_encoding_for_utf_chars_in_filenames]]
 > for an example. --[[Joey]]
 
diff --git a/doc/index/openid/discussion.mdwn b/doc/index/openid/discussion.mdwn
new file mode 100644 (file)
index 0000000..4a50fd9
--- /dev/null
@@ -0,0 +1,62 @@
+# OpenID discussion
+
+## No return_to in OpenID server
+
+Hi, there's no return_to from a designated OpenID server page, specs requires (I think a "should" or "must", can't recall exact wording) that it redirects back to the RP, in order to complete the registration and authentication. Unless I'm missing something, and the doc is incomplete, I'd consider this a bug. I don't expect to be of much use WRT coming up with a patch, but I'm willing to test ;-) .
+
+> If this is a bug, could you please explain:
+> 
+> * What happens when the bug occurs?
+> * How can one reproduce the bug?
+>
+> PS, please file bugs under [[bugs]] in future. --[[Joey]]
+
+>> Oops, my bad, didn't know that existed at the time I wrote this.
+>>
+>> What happened is that the process wouldn't complete, therefore I couldn't login with my OpenID.
+>>
+>> reproducibility: every time
+>>
+>> Should probably move this page, eh? ;)
+>> I'd do that, but I dunno know other than using the SCM backend in question....
+
+Here's some actual output (with my OpenID URL stripped out):
+
+do=postsignin&oic.time=1238224497-1450566d93097caa707f&openid.assoc_handle=%7BHMAC-SHA1%7D%7B49cdce76%7D%7BBhuXXw%3D%3D%7D&openid.identity=|<==== MY OPENID URL GOES HERE ====>|&openid.mode=id_res&openid.op_endpoint=http%3A%2F%2Fwww.myopenid.com%2Fserver&openid.response_nonce=2009-03-28T07%3A15%3A02ZDUFmG3&openid.return_to=http%3A%2F%2Fsimonraven.kisikew.org%2Fbin%2Fikiwiki.cgi%3Fdo%3Dpostsignin%26oic.time%3D1238224497-1450566d93097caa707f&openid.sig=E51Xh6Gnjku%2B0se57qCyhHbT5QY%3D&openid.signed=assoc_handle%2Cidentity%2Cmode%2Cop_endpoint%2Cresponse_nonce%2Creturn_to%2Csigned
+
+The `return_to` arg should NOT be `signed`, it should be the originating URL where you initially logged in.
+
+>> Yes, exactly. That's also my understanding of the spec.
+
+> I think you're confusing 'openid.return_to' with 'return_to'. The
+> former is present above, and is, indeed, the originating url, the latter
+> is part of the *value* of the 'openid.signed' parameter generated by myopenid.com. --[[Joey]] 
+
+Also, I dunno what the assoc_handle is doing spitting out an arg like `{HMAC-SHA1}{49cdce76}{BhuXXw%3D%3D}` it should be processed further. I have the needed perl packages installed (latest for Lenny). Hrm, would endianness matter?
+
+> Again, this value is created by the openid server, not by ikiwiki.
+> I see the same HMAC-SHA1 when using myopenid, and completly different
+> things for other openid servers. (Ie, when using livejournal as an openid server,
+> `openid.assoc_handle=1239305290:STLS.QiU6zTZ6w2bM3ttRkdaa:e68f91b751`)
+
+>> OK, I wasn't too sure about that, seemed bogus or somehow wrong or in error, like it wasn't actually being `completed`.
+
+> I'm fairly sure that is all a red herring.
+> 
+> So, when I was talking about reproducing the bug, I was thinking perhaps you could tell me what openid server you're using,
+> etc, so I can actually see the bug with my own eyes.
+
+>> myopenid.com, with the CNAME option turned on.
+
+> The sanitised url parameters you've provided are not generated by ikiwiki at all.
+> They don't even seem to be generated by the underlying [[!cpan Net::OpenID]] library.
+
+>> That was a server log entry with date/host/time stripped, and my URL also stripped. Everything else is as was in the log. I installed the Debian packages in Lenny, both server and consumer OpenID Perl packages.
+
+> I'm pretty sure that what you're showing me is the url myopenid redirects
+> the browser to after successfully signing in. At that point, ikiwiki
+> should complete the signin. What fails at this point? How can I reproduce this failure? --[[Joey]] 
+
+I'll try it again myself. I had tried it oh probably 6 times before I finally gave up on it. Maybe I'm getting rusty and I'm just PEBKACing all over the place. :P
+
+Also, to address the point about this discussion being in the wrong area (not under bugs), should I move it, or will you? I don't mind doing it, if you can't.
index 40b7b4c5b88059c16ca1422bdcb2e58dd24b0609..cc3a4c29f186ca1d0c952c28b14733dda70d0659 100644 (file)
@@ -1,6 +1,7 @@
-The easiest way to install ikiwiki is using the Debian package, but you can
-also [[download]] the source and install it by hand. Ikiwiki should work on
-most unix-like systems.
+This page documents how to install ikiwiki if a prepackaged version is not
+available for your distribution, and you are faced with [[downloading|download]]
+the source and installing by hand. Ikiwiki should work on most unix-like
+systems.
 
 ## Dependencies
 
@@ -10,29 +11,15 @@ Ikiwiki is a perl program, and needs a recent version of perl such as
 It's recommended you have a C compiler, as ikiwiki uses one to build
 wrappers.
 
-Ikiwiki requires the [[cpan Text::Markdown]], [[cpan URI]],
-[[cpan HTML::Parser]], [[cpan HTML::Template]], and [[cpan HTML::Scrubber]]
+Ikiwiki requires the [[!cpan Text::Markdown]], [[!cpan URI]],
+[[!cpan HTML::Parser]], [[!cpan HTML::Template]], and [[!cpan HTML::Scrubber]]
 perl modules be installed. It can also use a lot of other perl modules, if
 they are available.
 
 Various [[plugins]] use other perl modules and utilities; see their individual
 documentation for details.
 
-## Debian
-
-The Debian packages depend on and recommend an appropriate set of packages,
-so just install ikiwiki using apt.
-
-## Fedora 7
-
-While Fedora 7 doesn't have an ikiwiki package, you can install needed
-perl modules using this command:
-
-       yum install perl-Text-Markdown perl-Mail-Sendmail perl-HTML-Scrubber \
-         perl-XML-Simple perl-TimeDate perl-HTML-Template perl-CGI-FormBuilder \
-         perl-CGI-Session perl-File-MimeInfo perl-gettext perl-Authen-Passphrase
-
-## Installing by hand
+### Installing dependencies by hand
 
 If you want to install by hand from the tarball, you should make sure that
 all the perl modules are installed. This is one way to install them, using
@@ -41,6 +28,8 @@ CPAN:
        PERL5LIB=`pwd` PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'CPAN::Shell->install("Bundle::IkiWiki")'
        PERL5LIB=`pwd` PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'CPAN::Shell->install("Bundle::IkiWiki::Extras")'
 
+## Installing ikiwiki by hand
+
 Then to build and install ikiwiki:
 
        perl Makefile.PL # PREFIX=/dir to install elsewhere
index d60d511a579957429847e673dec092014734053b..02cdb29c915092bdeb3ac55b0eb32464d73f5f8d 100644 (file)
@@ -1,3 +1,19 @@
+No matter what I do, ikiwiki gives me a `Can't locate loadable object for module Locale::gettext in @INC` although I've installed (and reinstalled) the Locale module, and no luck. If I look at the directories in the INC path, I can see the file. The wiki won't compile in spite of this, and I've tried everything I can think of.. -- [[tychoish]]
+
+> Sounds like the `Locale::gettext` perl module is there, but your perl
+> installation is broken so that the accompnying so file is not there, or
+> doesn't work. On my system I have 
+> `/usr/lib/perl5/Locale/gettext.pm` and
+> `/usr/lib/perl5/auto/Locale/gettext.so` -- suspect your problem is with
+> the second one.
+> 
+> If you can't fix it, this problem could probably be worked around by
+> unsetting all environment variables when running ikiwiki (`LANG`,
+> `LC_ALL`, `LC_MESSAGES`). Then it won't try to load `Locale::gettext` at
+> all. --[[Joey]]
+
+---
+
 I am trying to install Ikiwiki version 2.1 from the source tarball.
 
 It has all gone fairly smoothly until I try and run 'make'.
@@ -94,7 +110,7 @@ This is perl, v5.8.8 built for i486-linux
 
 ## Installation in a non-root enviroment
 I had a pretty hellacious time installing Ikiwiki (largely due to problems
-in Perl) and documented them in [[tips/SharedHosting]].  I'd like to get feedback on the doc and also know if I should file a few bugs to make the installation process a little friendlier to non-root folks.  Thanks for the great app!
+in Perl) and documented them in [[tips/Dreamhost]].  I'd like to get feedback on the doc and also know if I should file a few bugs to make the installation process a little friendlier to non-root folks.  Thanks for the great app!
 
 
 ## Typing error?
@@ -153,3 +169,103 @@ good. Date::Parse was already installed. --[[vibrog]]
     usemymalloc=n, bincompat5005=undef
 
 Not sure how to provide proper version information for you.--[[vibrog]]
+
+---
+
+I've tried a couple of times and my cpan has never recognised Bundle::IkiWiki. Is that section of the page still accurate? -- [[users/Jon]]
+
+> Are you running perl with the environemnt settings specified on the page?
+> Can you show how it fails to find the bundle? --[[Joey]]
+
+>> I was not. Next time I build I will have to try that (I'll need to tweak it as I already override PERL5LIB; also I need to specify http proxies). Thanks for your help! -- [[users/Jon]]
+
+---
+
+##Further problems with Bundle::IkiWiki
+I'm also having trouble with finding Bundle::IkiWiki.  I've tried it with the environment settings and without them, and also using the interactive 
+form of the cpan command.  I've also gone to cpan.org and searched -- eg
+
+    http://search.cpan.org/search?query=ikiwiki&mode=all
+
+and no Bundle for IkiWiki comes up at all.
+
+The error I get from the various cpan attempts is basically always the same:
+
+    Warning: Cannot install Bundle::IkiWiki, don't know what it is.
+    Try the command
+
+        i /Bundle::IkiWiki/
+
+    to find objects with matching identifiers.
+
+When I try that command, BTW, it basically seems to find the same stuff I get when searching on the cpan web site.
+
+This happens both on Ubuntu 8.04 and CentOS 5.1
+
+Any help would be greatly appreciated... --kent
+
+> Bundle::IkiWiki is included in ikiwiki itself, so of course cpan.org
+> does not know about it.
+> 
+> If you can show me exactly what command you ran (the tested, working
+> commands on the parent page?) and how it failed, I can try to debug
+> your problem.
+
+Just today I noticed the "Bundle" subdirectory.  What a moron I am! :-)  Also, I misunderstood the PERL5LIB=`pwd` part -- 
+I glibly thought it indicated the sink for the installation of the modules, rather than the source, and I was running 
+the cpan command from another window in a different directory, and just spiraled down into error...
+
+> The real question in my mind is why you'd want to do this at all when
+> using Ubuntu, which incldues packages of ikiwiki and all its
+> dependencies. --[[Joey]]
+
+For ubuntu 8.04: 
+
+    $ ikiwiki --version
+    ikiwiki version 2.32.3ubuntu2.1
+    $
+
+I was just trying to get the latest version.
+
+In any case, thanks for the help, and thanks for the superb software.  I really like it a lot.
+
+---
+
+## Prerequisite modules not found for non-root user
+Hi, I'm a non-root user trying to use IkiWiki on an academic webserver with Perl 5.8.8 but several missing modules, so I grab them from CPAN (edited):
+
+    cd ~; PERL5LIB=`pwd`/ikiwiki:`pwd`/ikiwiki/cpan:`pwd`/lib/perl5 PERL_MM_USE_DEFAULT=1 perl -MCPAN -e 'CPAN::Shell->install("Bundle::IkiWiki")'
+
+That puts a lot of files in ~/.cpan. Then when I go into the directory where I untarred IkiWiki and try to run the Perl makefile:
+
+    cd ~/ikiwiki; perl Makefile.PL PREFIX=$HOME/ikiwiki
+
+I get warnings that all the modules needed were not found:
+
+Warning: prerequisite CGI::FormBuilder  not found.
+Warning: prerequisite CGI::Session 0 not found.
+Warning: prerequisite Date::Parse 0 not found.
+Warning: prerequisite HTML::Scrubber 0 not found.
+Warning: prerequisite HTML::Template 0 not found.
+Warning: prerequisite Mail::Sendmail 0 not found.
+Warning: prerequisite Text::Markdown 0 not found.
+
+CORRECTION 1: I played around with CPAN and got the installation to the point of succeeding with >99% of tests in "make test".
+
+> What was the magic CPAN rune that worked for you? --[[Joey]] 
+
+An attempt of "make install" failed while trying to put files in /etc/IkiWiki but per the output's instructions, I reran "make install" and that seemed to work, until this error, which doesn't seem to be satisfiable:
+
+    Warning: You do not have permissions to install into /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi at /usr/lib/perl5/5.8.8/ExtUtils/Install.pm line 114.
+    Installing /usr/lib/perl5/site_perl/5.8.8/IkiWiki.pm
+    mkdir /usr/lib/perl5/site_perl/5.8.8/IkiWiki: Permission denied at /usr/lib/perl5/5.8.8/ExtUtils/Install.pm line 176
+
+Any suggestions? Whew!
+
+> When you build ikiwiki, try doing it like this to make it
+> install to your home directory. Then you can run `~/bin/ikiwiki`
+> --[[Joey]] 
+
+       perl Makefile.PL INSTALL_BASE=$HOME PREFIX=
+       make
+       make install
index b9cb0c14fd68ce7721b6c16fd48ffd0251e7d63f..58413f94c377b2fc8cd4abee77de0c687b5240dc 100644 (file)
@@ -2,7 +2,7 @@ This is where announcements of new releases, features, and other news are
 posted. [[IkiWikiUsers]] are recommended to subscribe to this page's RSS
 feed.
 
-[[inline pages="news/* and !*/Discussion"
+[[!inline pages="news/* and !news/*/* and !news/discussion"
 feedpages="created_after(news/Article_on_Ikiwiki_as_a_BTS)" rootpage="news" show="30"]]
 
 By the way, some other pages with RSS feeds about ikiwiki include
diff --git a/doc/news/code_swarm.mdwn b/doc/news/code_swarm.mdwn
new file mode 100644 (file)
index 0000000..09b6852
--- /dev/null
@@ -0,0 +1,34 @@
+I've produced a [code_swarm](http://vis.cs.ucdavis.edu/~ogawa/codeswarm/)
+visualization of the first 2+ years of ikiwiki's commit history. 
+
+[[!img screenshot.png size="480x360" alt="screenshot"]]
+
+* [15 mb avi](http://kitenet.net/~joey/screencasts/ikiwiki_swarm.avi)
+* [stream on vimeo](http://vimeo.com/1324348)
+
+PS, while I'm posting links to videos, here's a 
+[video of a lightning talk about ikiwiki](http://log.hugoschotman.com/hugo/2008/07/webtuesday-2008-07-08-lightning-talk-by-axel-beckert-about-ikiwiki.html).
+
+--[[Joey]]
+
+### notes
+
+Interesting things to watch for:
+
+* Initial development of ikiwiki to the point it was getting web edits. 
+  (First 2 seconds of video!)
+* Introduction to plugin support, and later, plugin changes dominating code
+  changes.
+* Introduction of openid support and the resulting *swarm* of openid
+  commenters.
+* Switch to git, my name in the logs changes from "joey" to "Joey Hess",
+  and there are more code commits directly from others.
+
+Getting the commit log was tricky because every web commit is in there too,
+so it has to deal with things like IPs and openids. The [[code_swarm_log.pl]]
+script will munge the log to handle these, and it was configured with
+[[code_swarm.config]].
+
+Video editing by kino, ffmpeg, ffmpeg2theora, and too many hours of pain.
+
+Audio by the Punch Brothers.
diff --git a/doc/news/code_swarm/code_swarm.config b/doc/news/code_swarm/code_swarm.config
new file mode 100644 (file)
index 0000000..eea55de
--- /dev/null
@@ -0,0 +1,51 @@
+# This is a sample configuration file for code_swarm for ikiwiki
+
+# Frame width
+Width=640
+
+# Frame height
+Height=480
+
+# Input file
+InputFile=data/sample-repevents.xml
+
+# Particle sprite file
+ParticleSpriteFile=particle.png
+
+# Project time per frame
+MillisecondsPerFrame=21600000
+#MillisecondsPerFrame=43200000
+
+# Background in R,G,B
+Background=0,0,0
+
+# Color assignment rules
+# Keep in order, do not skip numbers. Numbers start
+# at 1.
+# 
+# Pattern:  "Label", "regex", R,G,B R,G,B
+# Label is optional.  If it is omitted, the regex
+# will be used.
+#
+
+ColorAssign1="Discussion (blue)",".*discussion.*", 0,0,255, 0,0,255
+ColorAssign2="Docs (green)",".*\.mdwn", 255,0,0, 255,0,0
+ColorAssign3="Plugins (orange)",".*Plugin/.*", 255,116,0, 255,116,0
+ColorAssign4="Code (red)",".*\.p[ml]", 0,255,0, 0,255,0
+
+# Save each frame to an image?
+TakeSnapshots=true
+
+# Where to save each frame
+SnapshotLocation=frames/code_swarm-#####.png
+
+# Create a glow around names? (Runs slower)
+NameHalos=false
+
+# Natural distance of files to people
+EdgeLength=40
+
+debug=false
+
+# OpenGL is experimental. Use at your own risk.
+UseOpenGL=false
diff --git a/doc/news/code_swarm/code_swarm_log.pl b/doc/news/code_swarm/code_swarm_log.pl
new file mode 100755 (executable)
index 0000000..25e0a67
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+# Munge a git log into log for code_swarm.
+# Deals with oddities of ikiwiki commits, like web commits, and openids.
+use IkiWiki;
+use IkiWiki::Plugin::openid;
+
+my $sep='-' x 72;
+$/=$sep."\n";
+
+my %config=IkiWiki::defaultconfig();
+
+foreach (`git-log --name-status --pretty=format:'%n$sep%nr%h | %an | %ai (%aD) | x lines%n%nsubject: %s%n'`) {
+       my ($subject)=m/subject: (.*)\n/m;
+       if ($subject=~m/$config{web_commit_regexp}/) {
+               my $user = defined $2 ? "$2" : "$3";
+               my $oiduser = IkiWiki::openiduser($user);
+               if (defined $oiduser) {
+                       $oiduser=~s/ \[.*\]//; # too much clutter for code_swarm
+                       $user=$oiduser;
+               }
+               s/ \| [^|]+ \| / | $user | /;
+       }
+       s/subject: (.*)\n\n//m;
+       print;
+}
diff --git a/doc/news/code_swarm/screenshot.png b/doc/news/code_swarm/screenshot.png
new file mode 100644 (file)
index 0000000..1178e3f
Binary files /dev/null and b/doc/news/code_swarm/screenshot.png differ
index c3674a92df792430ff23d8625ac04e4c403a92d2..351e39c624fb2ca184c05cf286bd54c9318dcf4d 100644 (file)
@@ -1,3 +1,12 @@
+## Ikiwiki 3.12
+
+Joey, what about news for Ikiwiki 3.12? The changelog says is has been released
+6 days ago... :) --[[Paweł|ptecza]]
+
+---
+
+## Ikiwiki 2.14
+
 Hi Joey! Where can I find the source package for ikiwiki 2.14? I rather prefer
 `wget` than `git` to download it :) I've just checked
 [Debian page of ikiwiki source package](http://packages.debian.org/unstable/source/ikiwiki)
diff --git a/doc/news/git_push_to_this_wiki.mdwn b/doc/news/git_push_to_this_wiki.mdwn
new file mode 100644 (file)
index 0000000..4b3fcbe
--- /dev/null
@@ -0,0 +1,3 @@
+Now you can use [[git]] to clone this wiki, and push your changes back,
+thanks to ikiwiki's new support for [[tips/untrusted_git_push]]. Enjoy
+working on the wiki while offline! --[[Joey]]
diff --git a/doc/news/git_push_to_this_wiki/discussion.mdwn b/doc/news/git_push_to_this_wiki/discussion.mdwn
new file mode 100644 (file)
index 0000000..33230c7
--- /dev/null
@@ -0,0 +1,37 @@
+Thanks, Joey!  This is awesome...I had to try it out :)
+--[[JasonBlevins]]
+
+I am really happy to hear of this new feature, that I was (more or less)
+secretly dreaming of. But - and that's why I'm still insanely editing
+this wiki inside a web browser - I wonder how I'll use it for real: my
+own master branch contains a few dozens merge commits, and one is created
+every time I `git pull` ikiwiki repository (or another clone of it, living
+on one of my other boxes that by chance had Internet access more recently).
+I do not want to clutter Joey's repository with these commits, so I guess
+I have to learn some more of Git everything-is-possible world (a nice thing
+is: I am not limited anymore to "Emacs can do it", and I'm now in a position
+to say "Git can do it" or "ikiwiki already does it", depending on the
+situation). Well, let's focus. Git wizards amongst us (let's use this wiki
+as if it were users@ikiwiki.info, ok?), what would you suggest? I was thinking
+of having a new branch in my cloned repository, dedicated to editing this wiki;
+I could use `rebase` instead of `fetch+merge` to get the new upstream commits
+into this special-purpose branch. I guess it would work nicely if I had only
+one offline box with not-yet-pushed changes at the same time, but would break
+in awful and various ways when it is not the case. Any alternative idea?
+--[[intrigeri]]
+
+> Not that I'm very careful to avoid pushing merge commits (see git log ;-), 
+> but I sometimes use `git pull --rebase` to pull changes from a repo. That
+> will rebase your local changes on top of the changes pulled, avoiding the
+> merge commits. I'm sure more involved solutions are possible. --[[Joey]]
+
+> I decided to use my local `master` branch as a copy of `origin/master`
+> (kitenet) and move my local modifications to a separate branch.  I'm using
+> `master` to edit the wiki but there is still the problem of new upstream
+> commits since the last pull.  I already had this problem as Joey had pushed
+> some changes while I was editing locally.  Not knowing about
+> `pull --rebase`, I took the long way out: branch, roll back HEAD, rebase,
+> and merge.  That was too much work...It looks like `pull --rebase` is the
+> way to go. --[[JasonBlevins]]
+
+Awesome ! --[[xma]]
index 248b217837c489a5ed8894e44bab8425d3eb0087..e6723c8730c5b0fd608d3a037ab8284aacc2de36 100644 (file)
@@ -9,7 +9,7 @@ default configuration:
   the procedure described at [[tips/switching_to_usedirs]]
   or edit your setup file to turn `usedirs` off: `usedirs => 0,`
 * [[plugins/OpenID]] logins are now enabled by default, if the
-  [[cpan Net::OpenID::Consumer]] perl module is available. Password logins
+  [[!cpan Net::OpenID::Consumer]] perl module is available. Password logins
   are also still enabled by default. If you like, you can turn either OpenID
   or password logins off via the `disable_plugins` setting.
 
@@ -29,4 +29,4 @@ An overview of changes in the year since the 1.0 release:
 * Some support for other markup languages than markdown: rst, textile.
 * Unit test suite, with more than 300 tests.
 
-[[meta date="2007-04-30 00:51:57 -0400"]]
+[[!meta date="2007-04-30 00:51:57 -0400"]]
diff --git a/doc/news/ikiwiki_version_3.0.mdwn b/doc/news/ikiwiki_version_3.0.mdwn
new file mode 100644 (file)
index 0000000..7ca636c
--- /dev/null
@@ -0,0 +1,42 @@
+Ikiwiki has reached version 3.0 and entered a new phase in its
+[[development_cycle|roadmap]].
+
+The 3.0 release of ikiwiki changes several defaults and finishes
+some transitions. You will need to modify your wikis to work with
+ikiwiki 3.0. A document explaining the process is available
+in [[tips/upgrade_to_3.0]].
+
+The highlights of the changes in version 3.0 include:
+
+* Support for uploading [[attachments|plugins/attachment]].
+* Can [[plugins/rename]] and [[plugins/remove]] pages and files via the web.
+* [[Web_based_setup|plugins/websetup]].
+* Blog-style [[plugins/comments]] as an alternative to Discussion pages.
+* Many other new plugins including [[plugins/htmlbalance]], [[plugins/format]],
+  [[plugins/progress]], [[plugins/color]], [[plugins/autoindex]],
+  [[plugins/cutpaste]], [[plugins/hnb]], [[plugins/creole]], [[plugins/txt]],
+  [[plugins/amazon_s3]], [[plugins/pinger]], [[plugins/pingee]],
+  [[plugins/edittemplate]]
+* The RecentChanges page is compiled statically, not generated from the CGI.
+* Support for additional revision control systems: [[rcs/bzr]],
+  [[rcs/monotone]]
+* Support for [[tips/untrusted_git_push]].
+* A new version (3.00) of the plugin API, exporting additional
+  commonly used functions from `IkiWiki.pm`.
+* Nearly everything in ikiwiki is now a plugin, from WikiLinks to
+  page editing, to RecentChanges.
+* Far too many bug fixes, features, and enhancements to list here.
+
+Thanks to the many contributors to ikiwiki 3.0, including:
+
+  Jelmer Vernooij, Recai Oktaş, William Uther, Simon McVittie, Axel Beckert,
+  Bernd Zeimetz, Gabriel McManus, Paweł Tęcza, Peter Simons, Manoj
+  Srivastava, Patrick Winnertz, Jeremie Koenig, Josh Triplett, thm, Michael
+  Gold, Jason Blevins, Alexandre Dupas, Henrik Brix Andersen, Thomas Keller,
+  Enrico Zini, intrigeri, Scott Bronson, Brian May, Adeodato Simó, Brian
+  Downing, Nis Martensen. (And anyone I missed.)
+
+Also, thanks to the users, bug submitters, and documentation wiki editors.
+Without you, ikiwiki would just be a little thing I use for my home page.
+
+--[[Joey]]
index c81145fcfc6fe69c461e160bd006305b0f54a9ca..79eeaec01ff7f8fb87154cec1088a81a2e6382f0 100644 (file)
@@ -10,4 +10,4 @@ log back in, try out the OpenID signup process if you don't already have an
 OpenID, and see how OpenID works for you. And let me know your feelings about
 making such a switch. --[[Joey]]
 
-[[poll 59 "Accept only OpenID for logins" 18 "Accept only password logins" 35 "Accept both"]]
+[[!poll 63 "Accept only OpenID for logins" 20 "Accept only password logins" 36 "Accept both"]]
index 64a29d345c08cef021596bb6ad6c89b160ca7325..e611fa77b819c36b3fc6da04e0c33bc0aa5baa1f 100644 (file)
@@ -15,6 +15,8 @@ as well. Also have I just created an account on this wiki as well?
 > can configure it to eg, subscribe your email address to changes to pages.
 > --[[Joey]]
 
+OK, my openid login works too. One question though, is there a setup parameter which controls whether new registrations are permitted at all? For instance, I'm thinking that I'd like to use the wiki format for content, but I don't want it editable by anyone who isn't already set up. Does this work? --[[Tim Lavoie]]
+
 ----
 
 # How to ban an IP address?
@@ -42,13 +44,14 @@ only Apache/iptables rules for this? Maybe it's related to
 
 > Error: /srv/web/ikiwiki.info/todo/Configurable_minimum_length_of_log_message_for_web_edits/index.html independently created, not overwriting with version from todo/Configurable_minimum_length_of_log_message_for_web_edits
 
-[[jondowland]]
+[[users/jon]]
 
 ----
 
 ### Logging Out
 
-If I've logged in by OpenID, how do I log out?  I don't see any logout button anywhere on IkiWIki.  (is it because I hit "forever" for my OpenID authorization duration?)
+If I've logged in by OpenID, how do I log out?  I don't see any logout
+button anywhere on IkiWiki.  (is it because I hit "forever" for my OpenID authorization duration?)
 > No, it's because it's on the preferences page!  That's somewhat non-obvious...
 
 >> This is a problem with having a static wiki. If I just put "Logout" as
@@ -62,3 +65,18 @@ Even if IkiWiki does let me log out, how do I *stay* logged out?  Let's say I'm
 > don't check the box that makes your provider set a cookie when you log in.)
 > 
 > AFAIK openid doesn't have single signoff capabilities yet. --[[Joey]]
+
+I'm having a problem using my preferred openid. I have
+http://thewordnerd.info configured as a delegate to
+thewordnerd.myopenid.com. It works fine on Lighthouse, Slicehost and
+everywhere else I've used it. Here, though, if I use the delegate I'm sent
+to my openid identity URL on myopenid.com. If I use the identity URL
+directly, I get the verification page.
+
+Is my delegation broken in some way that works for all these other apps but
+which fails here? Or is something broken in Ikiwiki's implementation?
+
+> I guess this is the same issue filed by you at
+> [[bugs/OpenID_delegation_fails_on_my_server]] --[[Joey]]
+
+Yes. I'd only recently set up my server as a delegate under wordpress, so still thought that perhaps the issue was on my end. But I'd since used my delegate successfully elsewhere, so I filed it as a bug against ikiwiki.
index 181edd0c7f752f7aa231e6b58f47b0826b110835..67651f2cff754f2ab3cf30fe2460efb2a9b06caa 100644 (file)
@@ -1,7 +1,7 @@
 Quick poll: Do you feel that ikiwiki is fast enough on this server, or
 should I move it to my much beefier auxiliary server?
 
-[[poll open=no 40 "It's fast enough" 6 "It's too slow!" 4 "No opinion"]]
+[[!poll open=no 40 "It's fast enough" 6 "It's too slow!" 4 "No opinion"]]
 
 If you have specifics on performance issues, you might mention them on the
 [[discussion]] page.
diff --git a/doc/news/version_2.48.mdwn b/doc/news/version_2.48.mdwn
deleted file mode 100644 (file)
index 76dbd7d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-**This release fixes an important security hole, upgrade immediately.**
-
-News for ikiwiki 2.48:
-
-   If you allowed password based logins to your wiki, those passwords were
-   stored in cleartext in the userdb. To guard against exposing users'
-   passwords, I recommend you install the [[cpan Authen::Passphrase]] perl module, and
-   then run `ikiwiki-transition hashpassword /path/to/srcdir` to replace all
-   existing cleartext passwords with strong (blowfish) hashes.
-
-ikiwiki 2.48 released with [[toggle text="these changes"]]
-[[toggleable text="""
-   * Fix security hole that occurred if openid and passwordauth were both
-     enabled. passwordauth would allow logging in as a known openid, with an
-     empty password. Closes: #[483770](http://bugs.debian.org/483770)
-     (CVE-2008-0169)
-   * Add rel=nofollow to edit links. This may prevent some spiders from
-     pounding on the cgi following edit links.
-   * passwordauth: If Authen::Passphrase is installed, use it to store
-     password hashes, crypted with Eksblowfish.
-   * `ikiwiki-transiition hashpassword /path/to/srcdir` can be used to
-     hash existing plaintext passwords.
-   * Passwords will no longer be mailed, but instead a password reset link.
-   * The password\_cost config setting is provided as a "more security" knob.
-   * teximg: Fix logurl.
-   * teximg: If the log isn't written, avoid ugly error messages.
-   * Updated French translation. Closes: #[478530](http://bugs.debian.org/478530)"""]]
diff --git a/doc/news/version_2.49.mdwn b/doc/news/version_2.49.mdwn
deleted file mode 100644 (file)
index 4c95b50..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-News for ikiwiki 2.49:
-
-   The search plugin no longer uses hyperestraier. Instead, to use it you
-   will now need to install xapian-omega, and the [[cpan Search::Xapian]],
-   [[cpan HTML::Scrubber]], and [[cpan Digest::SHA1]] perl modules. Ie,
-   `apt-get install xapian-omega libsearch-xapian-perl libhtml-scrubber-perl libdigest-sha1-perl`
-
-   Also, wikis that use the search plugin will need to be rebuilt, 
-   since the search form has changed. This will not be done automatically,
-   but can be done by running `ikiwiki-mass-upgrade` as root, or
-   running `ikiwiki -setup` on individual setup files.
-
-ikiwiki 2.49 released with [[toggle text="these changes"]]
-[[toggleable text="""
-   * haiku: Generate valid xhtml.
-   * ikiwiki-mass-rebuild: Don't trust $! when setting $)
-   * inline: The optimisation in 2.41 broke nested inlines. Detect those
-     and avoid overoptimising.
-   * search: Converted to use xapian-omega.
-   * Filter hooks are no longer called during the scan phase. This will
-     prevent wikilinks added by filters from being scanned properly. But
-     no known filter hook does that, so let's not waste time on it.
-   * Pass a destpage parameter to the sanitize hook.
-   * The search interface now allows searching for a page by title
-     ("title:foo"), as well as for pages that contain a given link
-     ("link:bar")."""]]
diff --git a/doc/news/version_2.50.mdwn b/doc/news/version_2.50.mdwn
deleted file mode 100644 (file)
index 4863ee2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-ikiwiki 2.50 released with [[toggle text="these changes"]]
-[[toggleable text="""
-   * img: Support captions.
-   * img: Don't generate empty title attributes, etc.
-   * img: Allow setting defaults for class and id too.
-   * ikiwiki-mass-rebuild: Make group list comparison more robust.
-   * search: Work around xapian bug #486138 by only stemming locales
-     in a whitelist."""]]
\ No newline at end of file
diff --git a/doc/news/version_2.51.mdwn b/doc/news/version_2.51.mdwn
deleted file mode 100644 (file)
index a139d6e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-ikiwiki 2.51 released with [[toggle text="these changes"]]
-[[toggleable text="""
-   * Improve toplevel parentlink to link directly to index.html when usedirs is
-     disabled.
-   * map: Add a "show" parameter. "show=title" can be used to display page
-     titles, rather than the default page name. Based on a patch from
-     Jaldhar H. Vyas, Closes: #[484510](http://bugs.debian.org/484510)
-   * hnb: New plugin, contributed by Axel Beckert.
-   * meta: Store "description" in pagestate for use by other plugins.
-   * map: Support show=description.
-   * textile: The Text::Textile perl module has some regexps that fail if
-     input is flagged as utf-8, but contains invalid characters such as 0x92.
-     To prevent it from crashing, re-encode the content before calling it,
-     which will ensure that it's really utf-8.
-   * Version the suggests of xapian-omega to a version known to be new enough
-     to work with ikiwiki. Reportedly, version 0.9.9 is too old to work.
-     Closes: #[486592](http://bugs.debian.org/486592)
-   * creole: New plugin from Bernd Zeimetz. Closes: #[486930](http://bugs.debian.org/486930)
-   * aggregate: Add template parameter.
-   * Add support for the universal edit button &lt;http://universaleditbutton.org/&gt;
-     (To get this on all pages of an exiting wiki, rebuild the wiki.)
-   * txt: New plugin, contributed by Gabriel McManus.
-   * smiley: Generate links relative to the destpage. (Fixes a reversion from
-     2.41.)
-   * toc: Revert change in 2.45 that made it run at sanitize time. That broke
-     use of toc in a sidebar.
-   * Call format hooks when generating page previews, thus fixing toc display
-     there, as well as fixing inlins to again display in page previews, since
-     it's started using format hooks. This also allows several other things,
-     like embed, that use format hooks, to work during page preview time.
-   * Format hooks should not rely on getting an entire html document, as they
-     will only get the body during page preview.
-   * toggle: Deal with preview mode when adding javascript."""]]
\ No newline at end of file
diff --git a/doc/news/version_2.52.mdwn b/doc/news/version_2.52.mdwn
deleted file mode 100644 (file)
index 3bdd12f..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-News for ikiwiki 2.52:
-
-   All wikis need to be rebuilt on upgrade to this version. If you listed your
-   wiki in /etc/ikiwiki/wikilist this will be done automatically when the
-   Debian package is upgraded. Or use ikiwiki-mass-rebuild to force a rebuild.
-
-ikiwiki 2.52 released with [[toggle text="these changes"]]
-[[toggleable text="""
-   * attachment: New plugin for uploading and managing attachments.
-     This includes a fairly powerful PageSpec based admin pref for deciding
-     whether to accept a given upload, and an attachment management interface
-     on the edit page.
-     (Sponsored by The TOVA Company.)
-   * If attachments are not enabled, configure CGI.pm to disable file
-     uploads by default. (An anti-DOS measure.)
-   * toggle: Add support for toggles that are open by default.
-   * toggle: Fix to work in preview mode.
-   * toggle: Add javascript to top of page, not to end. This avoids flicker
-     since closed toggles will not be displayed as the page is loading.
-   * The editpage form now uses the raw page name, not the page title, in its
-     'page' cgi parameter. Using the title was ambiguous and made it
-     impossible to tell between some pages, like "foo/bar" and "foo\_\_47\_\_bar",
-     sometimes causing the wrong page to be edited.
-   * This change means that some edit links need to be updated.
-     Force a rebuild on upgrade to this version.
-   * Above change also allowed really fixing escaped slashes from the blogpost
-     form."""]]
\ No newline at end of file
diff --git a/doc/news/version_3.141.mdwn b/doc/news/version_3.141.mdwn
new file mode 100644 (file)
index 0000000..ac76ce0
--- /dev/null
@@ -0,0 +1,28 @@
+ikiwiki 3.141 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * comment: Make comment directives no longer use the internal "\_comment"
+     form, and document the comment directive syntax.
+   * Avoid relying on translators preserving the case when translating
+     "discussion", which caused Discussion pages to get unwanted Discussion
+     links.
+   * Tighten up matching of bare words inside directives; do not
+     allow an unterminated triple string to be treated as a series
+     of bare words. Fixes runaway regexp recursion/backtracking
+     in strange situations.
+   * Setup automator: Check that each plugin added to the generated
+     setup file can be loaded and that its config is ok. If a plugin
+     fails for any reason, disable it in the generated file.
+     Closes: [532001](http://bugs.debian.org/532001)
+   * pagecount: Fix broken optimisation for * pagespec.
+   * goto: Support being passed a page title that is not a valid page
+     name, to support several cases including mercurial's long user
+     names on the RecentChanges page, and urls with spaces being handled
+     by the 404 plugin.
+   * Optimise use of gettext, and avoid ugly warnings if Locale::gettext
+     is not available. Closes: #[532285](http://bugs.debian.org/532285)
+   * meta: Add openid delegate parameter to allow delegating only
+     openid or openid2.
+   * Disable the Preferences link if no plugin with an auth hook is enabled.
+   * Updated French translation. Closes: #[532654](http://bugs.debian.org/532654)
+   * aggregate: Fix storing of changed md5.
+   * aggregate: Avoid resetting ctime when an item md5 changes."""]]
diff --git a/doc/news/version_3.141/discussion.mdwn b/doc/news/version_3.141/discussion.mdwn
new file mode 100644 (file)
index 0000000..1f5f392
--- /dev/null
@@ -0,0 +1,16 @@
+Version 3.141!? Is it not a mistake? Maybe you meant 3.14.1 or 3.15?
+--[[Paweł|users/ptecza]]
+
+> I suspect the next version will be 3.1415 ;) -- [[Jon]]
+
+>> And next 3.14159, 3.141592, etc. :) I think that version schema
+>> should be patented by Joey ;) --[[Paweł|users/ptecza]]
+
+>>> That's not exactly new; quoting from <http://www-cs-faculty.stanford.edu/~knuth/abcde.html>:
+>>>
+>>>> The latest and best TeX is currently version 3.1415926 (and plain.tex is version 3.141592653); METAFONT is currently version 2.718281 (and plain.mf is version 2.71). My last will and testament for TeX and METAFONT is that their version numbers ultimately become $\pi$ and $e$, respectively. At that point they will be completely error-free by definition.
+>>>
+>>> --[[tschwinge]]
+
+>>>> Thanks for the info, Thomas! I didn't know about it. Sorry Joey,
+>>>> but Don Knuth was faster. What a pity... ;) --[[Paweł|users/ptecza]]
diff --git a/doc/news/version_3.1415.mdwn b/doc/news/version_3.1415.mdwn
new file mode 100644 (file)
index 0000000..93310bc
--- /dev/null
@@ -0,0 +1,7 @@
+ikiwiki 3.1415 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * img: Fix extra double quote with alt text. (smcv)
+   * Updated French debconf templates translation. Closes: #[535103](http://bugs.debian.org/535103)
+   * openid: Support Net::OpenID 2.x when pretty-printing
+     openids. (smcv)
+   * highlight: Fix utf-8 encoding bug. Closes: #[535028](http://bugs.debian.org/535028)"""]]
\ No newline at end of file
diff --git a/doc/news/version_3.14159.mdwn b/doc/news/version_3.14159.mdwn
new file mode 100644 (file)
index 0000000..21f91fd
--- /dev/null
@@ -0,0 +1,5 @@
+ikiwiki 3.14159 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * svn: Fix rcs\_rename to properly scope call to dirname.
+   * img: Pass the align parameter through to the generated img tag.
+   * Move OpenID pretty-printing from openid plugin to core (smcv)"""]]
\ No newline at end of file
diff --git a/doc/news/version_3.141592.mdwn b/doc/news/version_3.141592.mdwn
new file mode 100644 (file)
index 0000000..5911e07
--- /dev/null
@@ -0,0 +1,19 @@
+ikiwiki 3.141592 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Add new hooks: canremove, canrename, rename. (intrigeri)
+   * rename: Refactor subpage rename handling code into rename hook. (intrigeri)
+   * po: New plugin, suporting translation of wiki pages using po files.
+     (intrigeri)
+   * Add build machinery to build po files to translate the underlay wikis,
+   * Add further build machinery to generate translated underlays from
+     the po file, for use by wikis whose primary language is not English.
+   * Add Danish basewiki translation by Jonas Smedegaard.
+   * img: Fix adding of dependency from page to the image.
+   * pagestats: add `among` parameter, which only counts links from specified
+     pages (smcv)
+   * pagestats: when making a tag cloud, don't emit links where the tag is
+     unused (smcv)
+   * map: Avoid emitting an unclosed ul element if the map is empty. (harishcm)
+   * inline: Add pagenames parameter that can be used to list a set of
+     pages to inline, in a specific order, without using a PageSpec. (smcv)
+   * Add getsource plugin (Will, smcv)"""]]
\ No newline at end of file
diff --git a/doc/page_locking.mdwn b/doc/page_locking.mdwn
deleted file mode 100644 (file)
index 21f4fb0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-The administrator of a wiki can choose to lock some pages, which allows
-only the admin to edit them using the online interface. This doesn't
-prevent anyone who can commit to the underlying revision control system
-from editing the pages, however.
-
-To lock a page, log into the wiki as whatever user is configured as the
-admin, and in your Preferences page, you'll find a field listing locked
-pages. This is a [[ikiwiki/PageSpec]], so you have a fair bit of control
-over what kinds of pages to lock. For example, you could choose to lock all
-pages created before 2006, or all pages that are linked to from the page
-named "locked". More usually though, you'll just list some names of pages
-to lock.
-
-One handy thing to do if you're using ikiwiki for your blog is to lock 
-"* and !*/Discussion". This prevents others from adding to or modifying
-posts in your blog, while still letting them comment via the Discussion
-pages.
index fc2a3f54386a1f4ab863f705bc350aecf61232a0..5c3b4a8d06b5224aebf6bea2b499069310f60f5f 100644 (file)
@@ -1,5 +1,8 @@
 ikiwiki supports adding "History" links to the top of pages to browse the
-revison history of a page. This is enabled by the `historyurl` setting,
+revision history of a page. This is enabled by the `historyurl` setting,
 which is used to specify the URL to a web interface such as [[ViewVC]]
 (for Subversion) or [[Gitweb]]. In that url, "\[[file]]" is replaced with
 the name of the file to view.
+
+The [[plugins/repolist]] plugin can supplement this information with
+urls to the underlying repository of the wiki.
index ca16202259824a4513e276806ee1b91d1d989a86..b570d995c843a047189014d2ef7a24ea4ac1facb 100644 (file)
@@ -7,5 +7,5 @@ once it's ready to be applied, add a 'patch' tag so it will show up here.
 If your patch is non-trivial and might need several iterations to get
 right, please consider publishing a [[git]] branch.
 
-[[inline pages="(todo/* or bugs/*) and link(patch) and !link(bugs/done) and
+[[!inline pages="(todo/* or bugs/*) and link(patch) and !link(bugs/done) and
 !link(todo/done) and !*/Discussion" rootpage="todo" archive="yes"]]
diff --git a/doc/patch/core.mdwn b/doc/patch/core.mdwn
new file mode 100644 (file)
index 0000000..fcf0bdb
--- /dev/null
@@ -0,0 +1,7 @@
+Some [[patches|patch]] affect the ikiwiki core, rather than just a plugin.
+This tag collects those patches. Please tag such patches with 'patch/core'
+as well as 'patch'.
+
+[[!inline pages="(todo/* or bugs/*) and link(patch/core)
+    and !link(bugs/done) and !link(todo/done) and !*/Discussion"
+  rootpage="todo" archive="yes"]]
index 439cecc8aff3d1efdb0fe6dfefc9fffae2882fea..527568208913e1c379c1ae31b79e2202173dab58 100644 (file)
@@ -1,19 +1,19 @@
 Most of ikiwiki's [[features]] are implemented as plugins. Many of these 
 plugins are included with ikiwiki.
 
-[[pagestats pages="plugins/type/* and !plugins/type/slow"]]
+[[!pagestats pages="plugins/type/* and !plugins/type/slow"]]
 
 There's documentation if you want to [[write]] your own plugins, or you can
 [[install]] plugins [[contributed|contrib]] by others.
 
 To enable a plugin, use the `--plugin` switch described in
-[[usage]], or the equivalent `add_plugins` line in [[ikiwiki.setup]].
+[[usage]], or the equivalent `add_plugins` line in ikiwiki.setup.
 Enable the [[goodstuff]] plugin to get a nice selection of plugins that
 will fit most uses of ikiwiki.
 
 ## Plugin directory
 
-[[inline pages="plugins/* and !plugins/type/* and !plugins/write and 
+[[!inline pages="plugins/* and !plugins/type/* and !plugins/write and 
 !plugins/write/* and !plugins/contrib and !plugins/install and !*/Discussion"
-feedpages="created_after(plugins/graphviz)" archive="yes"
+feedpages="created_after(plugins/graphviz)" archive="yes" sort=title
 rootpage="plugins/contrib" postformtext="Add a new plugin named:" show=0]]
diff --git a/doc/plugins/404.mdwn b/doc/plugins/404.mdwn
new file mode 100644 (file)
index 0000000..ad332ee
--- /dev/null
@@ -0,0 +1,20 @@
+[[!template id=plugin name=404 author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/useful]]
+
+This plugin lets you use the IkiWiki CGI script as an Apache 404 handler,
+to give the behaviour of various other wiki engines where visiting a
+nonexistent page provides you with a link to create it.
+
+To achieve this, put something like this in the wiki's Apache configuration
+file:
+
+    ErrorDocument 404 /ikiwiki.cgi
+
+(The path here needs to be whatever the path is to the ikiwiki.cgi from
+the root of your web server.)
+
+Or put something like this in the wiki's Lighttpd (>=1.4.17) configuration file:
+
+    server.error-handler-404 = "/ikiwiki.cgi"
+
+
index 574c8b125e9486e3433a89711eddd4ebbab03fb0..e2efcd83f1d67dc17481f5cd2b2534329290a445 100644 (file)
@@ -1,26 +1,13 @@
-[[template id=plugin name=aggregate author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=aggregate author="[[Joey]]"]]
+[[!tag type/useful]]
 
-This plugin allows content from other feeds to be aggregated into the wiki.
-Aggregate a feed as follows
+This plugin allows content from other feeds to be aggregated into the
+wiki. To specify feeds to aggregate, use the
+[[ikiwiki/directive/aggregate]] [[ikiwiki/directive]].
 
-       \[[aggregate name="example blog"
-       feedurl="http://example.com/index.rss"
-       url="http://example.com/" updateinterval="15"]]
-
-That example aggregates posts from the specified RSS feed, updating no
-more frequently than once every 15 minutes, and puts a page per post under
-the example/ directory in the wiki.
-
-You can then use ikiwiki's [[ikiwiki/blog]] support to create a blog of one or
-more aggregated feeds.
-
-## setup
-
-Make sure that you have the [[html]] plugin enabled, as the created pages are
-in html format. The [[meta]] and [[tag]] plugins are also recommended. The
-[[htmltidy]] plugin is suggested, since feeds can easily contain html
-problems, some of which tidy can fix.
+The [[meta]] and [[tag]] plugins are also recommended. Either the
+[[htmltidy]] or [[htmlbalance]] plugin is suggested, since feeds can easily
+contain html problems, some of which these plugins can fix.
 
 You will need to run ikiwiki periodically from a cron job, passing it the
 --aggregate parameter, to make it check for new posts. Here's an example
@@ -31,37 +18,24 @@ crontab entry:
 Alternatively, you can allow `ikiwiki.cgi` to trigger the aggregation. You
 should only need this if for some reason you cannot use cron, and instead
 want to use a service such as [WebCron](http://webcron.org). To enable
-this, enable on `aggregate_webtrigger` in your setup file. The url to
+this, turn on `aggregate_webtrigger` in your setup file. The url to
 visit is `http://whatever/ikiwiki.cgi?do=aggregate_webtrigger`. Anyone
 can visit the url to trigger an aggregation run, but it will only check
 each feed if its `updateinterval` has passed.
 
-## usage
+## aggregated pages
 
-Here are descriptions of all the supported parameters to the `aggregate`
-directive:
+This plugin creates a page for each aggregated item. 
 
-* `name` - A name for the feed. Each feed must have a unique name.
-  Required.
-* `url` - The url to the web page for the feed that's being aggregated.
-  Required.
-* `dir` - The directory in the wiki where pages should be saved. Optional,
-  if not specified, the directory is based on the name of the feed.
-* `feedurl` - The url to the feed. Optional, if it's not specified ikiwiki
-  will look for feeds on the `url`. RSS and atom feeds are supported.
-* `updateinterval` - How often to check for new posts, in minutes. Default
-  is 15 minutes.
-* `expireage` - Expire old items from this feed if they are older than
-  a specified number of days. Default is to never expire on age.
-* `expirecount` - Expire old items from this feed if there are more than
-  the specified number total. Oldest items will be expired first. Default
-  is to never expire on count.
-* `tag` - A tag to tag each post from the feed with. A good tag to use is
-  the name of the feed. Can be repeated multiple times. The [[tag]] plugin
-  must be enabled for this to work.
-* `template` - Template to use for creating the html pages. Defaults to
-  aggregatepost.
+If the `aggregateinternal` option is enabled in the setup file (which is
+the default), aggregated pages are stored in the source directory with a
+"._aggregated" extension. These pages cannot be edited by web users, and
+do not generate first-class wiki pages. They can still be inlined into a
+blog, but you have to use `internal` in [[PageSpecs|IkiWiki/PageSpec]],
+like `internal(blog/*)`.
 
-Note that even if you are using subversion or another revision control
-system, pages created by aggregation will *not* be checked into revision
-control.
+If `aggregateinternal` is disabled, you will need to enable the [[html]]
+plugin as well as aggregate itself, since feed entries will be stored as
+HTML, and as first-class wiki pages -- each one generates
+a separate HTML page in the output, and they can even be edited. This
+option is provided only for backwards compatability.
diff --git a/doc/plugins/aggregate/discussion.mdwn b/doc/plugins/aggregate/discussion.mdwn
new file mode 100644 (file)
index 0000000..1a98445
--- /dev/null
@@ -0,0 +1,91 @@
+I'm trying to set up a [planet of my users' blogs](http://help.schmonz.com/planet/). I've enabled the aggregate, meta, and tag plugins (but not htmltidy, that thing has a gajillion dependencies). `aggregateinternal` is 1. The cron job is running and I've also enabled the webtrigger. My usage is like so:
+
+    \[[!inline pages="internal(planet/*) show=0"]]
+    
+    \[[!aggregate
+    name="Amitai's blog"
+    url="http://www.schmonz.com/"
+    dir="planet/schmonz-blog"
+    feedurl="http://www.schmonz.com/atom/"
+    expirecount="2"
+    tag="schmonz"
+    ]]
+    
+    \[[!aggregate
+    name="Amitai's photos"
+    url="http://photos.schmonz.com/"
+    dir="planet/schmonz-photos"
+    feedurl="http://photos.schmonz.com/main.php?g2_view=rss.SimpleRender&g2_itemId=7"
+    expirecount="2"
+    tag="schmonz"
+    ]]
+
+
+(and a few more `aggregate` directives like these)
+
+Two things aren't working as I'd expect:
+
+1. `expirecount` doesn't take effect on the first run, but on the second. (This is minor, just a bit confusing at first.)
+2. Where are the article bodies for e.g. David's and Nathan's blogs? The bodies aren't showing up in the `._aggregated` files for those feeds, but the bodies for my own blog do, which explains the planet problem, but I don't understand the underlying aggregation problem. (Those feeds include article bodies, and show up normally in my usual feed reader rss2email.) How can I debug this further? --[[schmonz]]
+
+> I only looked at David's, but its rss feed is not escaping the html
+> inside the rss `description` tags, which is illegal for rss 2.0. These
+> unknown tags then get ignored, including their content, and all that's
+> left is whitespace. Escaping the html to `&lt;` and `&gt;` fixes the
+> problem. You can see the feed validator complain about it here:
+> <http://feedvalidator.org/check.cgi?url=http%3A%2F%2Fwww.davidj.org%2Frss.xml>
+> 
+> It's sorta unfortunate that [[!cpan XML::Feed]] doesn't just assume the
+> un-esxaped html is part of the description field. Probably other feed
+> parsers are more lenient. --[[Joey]]
+
+>> Thanks for the quick response (and the `expirecount` fix); I've forwarded it to David so he can fix his feed. Nathan's Atom feed validates -- it's generated by the same CMS as mine -- so I'm still at a loss on that one. --[[schmonz]]
+
+>>> Nathan's feed contains only summary elements, with no content elements.
+>>> This is legal according to the Atom spec, so I've fixed ikiwiki to use
+>>> the summary if no content is available. --[[Joey]]
+
+>>>> After applying your diffs, blowing away my cached aggregated stuff, and running the aggregate cron job by hand, the resulting planet still doesn't have Nathan's summaries... and the two posts from each feed that aren't being expired aren't the two newest ones (not sure what the pattern is there). Have I done something wrong? --[[schmonz]]
+
+>>>>> I think that both issues are now fixed. Thanks for testing.
+>>>>> --[[Joey]]
+
+>>>>>> I can confirm, they're fixed on my end. --[[schmonz]]
+
+New bug: new posts aren't getting displayed (or cached for aggregation). After fixing his feed, David posted a new item today, and the aggregator is convinced there's nothing to do, whether by cronjob or webtrigger. I verified that it wasn't another problem with his feed by adding another of my ikiwiki's feed to the planet, running the aggregator, posting a new item, and running the aggregator again: no new item. --[[schmonz]]
+
+> Even if you start it more frequently, aggregation will only occur every
+> `updateinterval` minutes (default 15), maximum. Does this explain what
+> you're seeing? --[[Joey]]
+
+>> Crap, right, and my test update has since made it into the planet. His post still hasn't. So it must be something with David's feed again? A quick test with XML::Feed looks like it's parsing just fine: --[[schmonz]]
+
+    $ perl 
+    use XML::Feed;
+    my $feed = XML::Feed->parse(URI->new('http://www.davidj.org/rss.xml')) or die XML::Feed->errstr;
+    print $feed->title, "\n";
+    for my $entry ($feed->entries) {
+    print $entry->title, ": ", $entry->issued, "\n";
+    }
+    ^D
+    davidj.org
+    Amway Stories - Refrigerator Pictures: 2008-09-19T00:12:27
+    Amway Stories - Coffee: 2008-09-13T10:08:17
+    Google Alphabet Update: 2008-09-11T22:55:37
+    Writing for writing's sake: 2008-09-09T23:39:05
+    Google Chrome: 2008-09-02T23:12:26
+    Mister Casual: 2008-07-25T09:01:17
+    Parental Conversations: 2008-07-24T10:44:44
+    Place Of George Orwell: 2008-06-03T22:11:07
+    The Raw Beauty Of A National Duolian: 2008-05-31T12:41:06
+
+> I had no problem getting the "Refrigerator Pictures" post to aggregate
+> here, though without a copy of the old feed I can't be 100% sure I've
+> reproduced your ikiwiki's state. --[[Joey]]
+
+>> Okay, I blew away the cached entries and aggregator state files and reran the aggregator and all appears well again. If the problem recurs I'll be sure to post here. :-) --[[schmonz]]
+
+>>> On the off chance that you retained a copy of the old state, I'd not
+>>> mind having a copy to investigate. --[[Joey]]
+
+>>>> Didn't think of that, will keep a copy if there's a next time. -- [[schmonz]]
index caa0c01530be6251683de0fe8b7bda6b790e0354..331dc4acf1a78c3ec980e5441a4a5830cffa8d20 100644 (file)
@@ -1,12 +1,12 @@
-[[template id=plugin name=amazon_s3 author="[[Joey]]"]]
-[[tag type/special-purpose]]
+[[!template id=plugin name=amazon_s3 author="[[Joey]]"]]
+[[!tag type/special-purpose]]
 
 This plugin allows ikiwiki to publish a wiki in the [Amazon Simple Storage
 Service](http://aws.amazon.com/s3) (S3). As pages are rendered, ikiwiki
 will upload them to Amazon S3. The entire wiki contents, aside from the
 ikiwiki CGI, can then be served directly out of Amazon S3.
 
-You'll need the [[cpan Net::Amazon::S3]] and [[cpan File::MimeInfo]] perl
+You'll need the [[!cpan Net::Amazon::S3]] and [[!cpan File::MimeInfo]] perl
 modules and an Amazon S3 account to use this plugin.
 
 ## configuration
index 2afde29b3b43c3286f89cb42269d92d4fe058bd3..506657a1c1a16806921b216d842f8bc815adf22c 100644 (file)
@@ -1,9 +1,19 @@
-[[template id=plugin name=anonok author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=anonok author="[[Joey]]"]]
+[[!tag type/auth]]
 
 By default, anonymous users cannot edit the wiki. This plugin allows
 anonymous web users, who have not signed in, to edit any page in the wiki
 by default.
 
-The plugin also has a configuration setting, `anonok_pagespec`. This
-[[PageSpec]] can be used to allow anonymous editing of matching pages.
+Please think twice before enabling this plugin. If your wiki is accessible
+to the internet, it *will* be subject to spamming if this plugin is
+enabled. Such spam is not only a pain to deal with, but it bloats the
+revision control history of your wiki.
+
+The plugin has a configuration setting, `anonok_pagespec`. This
+[[ikiwiki/PageSpec]] can be used to allow anonymous editing of matching pages.
+
+If you're using the [[comments]] plugin, you can allow anonymous comments
+to be posted by setting:
+
+       anonok_pagespec => "postcomment(*)"
index ce04bcd2fce5d8a3983ffa85b7972d87ce06ab95..4fcd714f8b806bee88365ff129a9e28f8ca85e9d 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=attachment core=0 author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=attachment core=0 author="[[Joey]]"]]
+[[!tag type/web]]
 
 This plugin allows files to be uploaded to the wiki over the web.
 
@@ -20,15 +20,8 @@ Bear in mind that if you let anyone upload a particular kind of file
    contains html as a web page; including running any malicious javascript
    embedded in that page.
 
-If you enable this plugin, be sure to lock that down, by entering an
-[[enhanced_PageSpec|ikiwiki/pagespec/attachment]] in the "Allowed
-Attachments" field of the wiki admin's preferences page.
-
-This plugin will use the [[cpan File::MimeInfo::Magic]] perl module, if
-available, for mimetype checking.
-
-The `virusfree` [[PageSpec|ikiwiki/pagespec/attachment]] requires that
-ikiwiki be configured with a virus scanner program via the `virus_checker`
-option in the setup file. If using `clamav`, with `clamd`, set it to
-"clamdscan -". Or to use clamav without the `clamd` daemon, you
-could set it to "clamscan -".
+If you enable this plugin, be sure to lock it down, via the
+`allowed_attachments` setup file option. This is a special 
+[[enhanced_PageSpec|ikiwiki/pagespec/attachment]] using tests provided by
+the [[filecheck]] plugin. That plugin will be automatically enabled when
+this plugin is enabled.
diff --git a/doc/plugins/autoindex.mdwn b/doc/plugins/autoindex.mdwn
new file mode 100644 (file)
index 0000000..03e2d12
--- /dev/null
@@ -0,0 +1,7 @@
+[[!template id=plugin name=autoindex core=0 author="[[Joey]]"]]
+[[!tag type/useful]]
+
+This plugin searches for [[SubPages|ikiwiki/subpage]] with a missing parent
+page, and generates the parent pages. The generated page content is
+controlled by the `autoindex.tmpl` [[template|wikitemplates]], which by
+default, uses a [[map]] to list the SubPages.
diff --git a/doc/plugins/autoindex/discussion.mdwn b/doc/plugins/autoindex/discussion.mdwn
new file mode 100644 (file)
index 0000000..82e30aa
--- /dev/null
@@ -0,0 +1,7 @@
+Would it be possible to add an option to only generate the index files
+for the html output and not place the markdown files in the wiki source?
+
+The reason being that I have a lot of directories which need to be autoindexed,
+but I would prefer if the index files didn't clutter up my git repository.
+
+even without that feature the plugin is a great help, thanks
diff --git a/doc/plugins/blogspam.mdwn b/doc/plugins/blogspam.mdwn
new file mode 100644 (file)
index 0000000..a13b6e8
--- /dev/null
@@ -0,0 +1,32 @@
+[[!template id=plugin name=blogspam author="[[Joey]]"]]
+[[!tag type/auth]]
+
+This plugin adds antispam support to ikiwiki, using the
+[blogspam.net](http://blogspam.net/) API. Both page edits and
+[[comment|comments]] postings can be checked for spam. Page edits that
+appear to contain spam will be rejected; comments that look spammy will be
+stored in a queue for moderation by an admin.
+
+To check for and moderate comments, log in to the wiki as an admin,
+go to your Preferences page, and click the "Comment Moderation" button.
+
+The plugin requires the [[!cpan RPC::XML]] perl module.
+
+You can control how content is tested via the `blogspam_options` setting.
+The list of options is [here](http://blogspam.net/api/testComment.html#options).
+By default, the options are configured in a way that is appropriate for
+wiki content. This includes turning off some of the more problematic tests.
+An interesting option for testing is `fail`, by setting it (e.g.,
+`blogspam_options => 'fail'`), *all* comments will be marked as SPAM, so that
+you can check whether the interaction with blogspam.net works.
+
+The `blogspam_pagespec` setting is a [[ikiwiki/PageSpec]] that can be
+used to configure which pages are checked for spam. The default is to check
+all edits. If you only want to check [[comments]] (not wiki page edits),
+set it to "postcomment(*)".
+
+By default, the blogspam.net server is used to do the spam checking. To
+change this, the `blogspam_server` option can be set to the url for a
+different server implementing the same API. Note that content is sent
+unencrypted over the internet to the server, and the server sees
+the full text of the content.
index 208d7120b280ca7593f4635e769bbc0074935f85..c039a9d1715f5e5d00850cad0bd5c7cef85aaa19 100644 (file)
@@ -1,13 +1,9 @@
-[[template id=plugin name=brokenlinks author="[[Joey]]"]]
-[[tag type/link type/meta]]
+[[!template id=plugin name=brokenlinks author="[[Joey]]"]]
+[[!tag type/link type/meta]]
 
-This plugin generates a list of broken links on pages in the wiki. This is
-a useful way to find pages that still need to be written, or links that
-are written wrong.
-
-The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
-pages to search for broken links, default is search them all.
+This plugin provides a [[ikiwiki/directive/brokenlinks]] [[ikiwiki/directive]]
+that generates a list of broken links on pages in the wiki.
 
 If this plugin is turned on, here's a list of broken links on this wiki:
 
-[[brokenlinks pages="* and !recentchanges"]]
+[[!brokenlinks pages="* and !recentchanges"]]
index d429bde88b62fd913c68609d200964881598c78e..d695762b7d9a7494ea1e83f2fc9c41989aacb77f 100644 (file)
@@ -1,55 +1,16 @@
-[[template id=plugin name=calendar author="[[ManojSrivastava]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=calendar author="[[ManojSrivastava]]"]]
+[[!tag type/chrome]]
 
-This plugin displays a calendar, similar to the typical calendars shown on
+This plugin provides a [[ikiwiki/directive/calendar]] [[ikiwiki/directive]].
+The directive displays a calendar, similar to the typical calendars shown on
 some blogs.
 
-# examples
-
-       \[[calendar ]]
-
-       \[[calendar type="month" pages="blog/* and !*/Discussion"]]
-
-       \[[calendar type="year" year="2005" pages="blog/* and !*/Discussion"]]
-
-This plugin is inspired by the calendar plugin for Blosxom, but
-derives no code from it. This plugin is essentially a fancy front end
-to archives of previous pages, usually used for blogs. It can produce
-a calendar for a given month, or a list of months for a given year.
-
 Since ikiwiki is a wiki compiler, to keep the calendar up-to-date,
-wikis that include it need to be preiodically refreshes, typically by cron
+wikis that include it need to be periodically refreshes, typically by cron
 at midnight. Example crontab:
 
        0 0 * * * ikiwiki -setup ~/ikiwiki.setup -refresh
 
-The month format calendar simply links to any page posted on each
-day of the month. The year format calendar links to archive pages, with
-names like `archives/2007` (for all of 2007)  and `archives/2007/01`
-(for January, 2007). For this to work, you'll need to create these archive
-pages. They typically use [[inline]] to display or list pages created in
-the given time frame.
-
-## usage
-
-* `type` - Used to specify the type of calendar wanted. Can be one of
-  "month" or "year". The default is a month view calendar.
-* `pages` - Specifies the [[ikiwiki/PageSpec]] of pages to link to from the
-  month calendar. Defaults to "*".
-* `archivebase` - Configures the base of the archives hierarchy. The
-  default is "archives". Note that this default can also be overridden
-  for the whole wiki by setting `archivebase` in ikiwiki's setup file.
-* `year` - The year for which the calendar is requested. Defaults to the
-  current year.
-* `month` - The numeric month for which the calendar is requested, in the
-  range 1..12. Used only for the month view calendar, and defaults to the
-  current month.
-* `week_start_day` - A number, in the range 0..6, which represents the day
-  of the week that the month calendar starts with. 0 is Sunday, 1 is Monday,
-  and so on. Defaults to 0, which is Sunday.
-* `months_per_row` - In the annual calendar, number of months to place in
-  each row. Defaults to 3.
-
 ## CSS
 
 The output is liberally sprinkled with classes, for fine grained CSS
@@ -59,7 +20,7 @@ customization.
 * `month-calendar-head` - The head of the month calendar (ie,"March").
 * `month-calendar-day-head` - A column head in the month calendar (ie, a
   day-of-week abbreviation).
-* `month-calendar-day-noday`, `month-calendar-day-link`, 
+* `month-calendar-day-noday`, `month-calendar-day-link`,
   `month-calendar-day-nolink`, `month-calendar-day-future`,
   `month-calendar-day-this-day` - The day squares on the month calendar,
   for days that are not in the month (before or after the month itself), that
diff --git a/doc/plugins/calendar/discussion.mdwn b/doc/plugins/calendar/discussion.mdwn
new file mode 100644 (file)
index 0000000..9d57b7a
--- /dev/null
@@ -0,0 +1,6 @@
+It would be nice if the "month" type calendar could collect all of the 
+matching pages on a given date in some inline type way. --[[DavidBremner]]
+
+Is it possible to get the calendar to link to pages based not on their timestamp (as I understand that it does now, or have I misunderstood this?) and instead on for example their location in a directory hierarchy. That way the calendar could be used as a planning / timeline device which I think would be great. --[[Alexander]]
+
+I would like the ability to specify relative previous months. This way I could have a sidebar with the last three months by specifying no month, then 'month="-1"' and 'month="-2"'. Negative numbers for the month would otherwise be invalid, so this shouldn't produce any conflicts with expected behavior. (Right?) -- [[StevenBlack]]
index 81270f41a9ecde48a291bed262ab481e495c4e6e..1764b31b2a009afae8fe0fca846f4032dfcef912 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=camelcase author="[[Joey]]"]]
+[[!template id=plugin name=camelcase author="[[Joey]]"]]
 
 This plugin makes words in CamelCase be treated as a [[ikiwiki/WikiLink]].
 That is to say, any two or more words capitalised and mashed together are
@@ -7,4 +7,4 @@ link.
 
 If this plugin is enabled, this will be a link: SandBox
 
-[[tag type/link]]
+[[!tag type/link]]
diff --git a/doc/plugins/color.mdwn b/doc/plugins/color.mdwn
new file mode 100644 (file)
index 0000000..dbb8b87
--- /dev/null
@@ -0,0 +1,5 @@
+[[!template id=plugin name=color core=0 author="[[ptecza]]"]]
+[[!tag type/chrome]]
+
+This plugin provides a [[ikiwiki/directive/color]] [[ikiwiki/directive]].
+The directive can be used to color a piece of text on a page.
diff --git a/doc/plugins/comments.mdwn b/doc/plugins/comments.mdwn
new file mode 100644 (file)
index 0000000..7e22324
--- /dev/null
@@ -0,0 +1,52 @@
+[[!template id=plugin name=comments author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/useful]]
+
+This plugin adds "blog-style" comments. Unlike the wiki-style freeform 
+Discussion pages, these comments are posted by a simple form, cannot later
+be edited, and rss/atom feeds are provided of each page's comments.
+
+When using this plugin, you should also enable [[htmlscrubber]] and either
+[[htmltidy]] or [[htmlbalance]]. Directives are filtered out by default, to
+avoid commenters slowing down the wiki by causing time-consuming
+processing. As long as the recommended plugins are enabled, comment
+authorship should hopefully be unforgeable by CGI users.
+
+The intention is that on a non-wiki site (like a blog) you can lock all
+pages for admin-only access, then allow otherwise unprivileged (or perhaps
+even anonymous) users to comment on posts. See the documentation of the
+[[lockedit]] and [[anonok]] pages for details on locking down a wiki so
+users can only post comments.
+
+Individual comments are stored as internal-use pages named something like
+`page/comment_1`, `page/comment_2`, etc. These pages internally use a
+[[comment_directive|ikiwiki/directive/comment]].
+
+There are some global options for the setup file:
+
+* `comments_pagespec`: [[ikiwiki/PageSpec]] of pages where comments are
+  allowed. The default is not to allow comments on any pages. To allow
+  comments to all posts to a blog, you could use
+  `blog/posts/* and !*/Discussion`.
+* `comments_closed_pagespec`: [[ikiwiki/PageSpec]] of pages where
+  posting of new comments is closed, but any existing comments will still
+  be displayed. Often you will list a set of individual pages here.
+  For example: `blog/controversial or blog/flamewar`
+* `comments_pagename`: if this is e.g. `comment_` (the default), then
+  comment pages will be named something like `page/comment_12`
+* `comments_allowdirectives`: if true (default false), comments may
+  contain IkiWiki [[directives|ikiwiki/directive]]
+* `comments_commit`: if true (default true), comments will be committed to
+  the version control system
+* `comments_allowauthor`: if true (default false), anonymous commenters may
+  specify a name for themselves, and the \[[!meta author]] and
+  \[[!meta authorurl]] directives will not be overridden by the comments
+  plugin
+
+## comment moderation
+
+If you enable the [[blogspam]] plugin, comments that appear spammy will be
+held for moderation. Wiki admins can access the comment moderation queue
+via a button on their Preferences page.
+
+The comments are stored in `.ikiwiki/comments_pending/`, and can be
+deleted, or moved into the wiki's srcdir to be posted.
diff --git a/doc/plugins/comments/discussion.mdwn b/doc/plugins/comments/discussion.mdwn
new file mode 100644 (file)
index 0000000..396d1f6
--- /dev/null
@@ -0,0 +1,190 @@
+## Why internal pages? (unresolved)
+
+Comments are saved as internal pages, so they can never be edited through the CGI,
+only by direct committers.
+
+> So, why do it this way, instead of using regular wiki pages in a
+> namespace, such as `$page/comments/*`? Then you could use [[plugins/lockedit]] to
+> limit editing of comments in more powerful ways. --[[Joey]]
+
+>> Er... I suppose so. I'd assumed that these pages ought to only exist as inlines
+>> rather than as individual pages (same reasoning as aggregated posts), though.
+>>
+>> lockedit is actually somewhat insufficient, since `check_canedit()`
+>> doesn't distinguish between creation and editing; I'd have to continue to use
+>> some sort of odd hack to allow creation but not editing.
+>>
+>> I also can't think of any circumstance where you'd want a user other than
+>> admins (~= git committers) and possibly the commenter (who we can't check for
+>> at the moment anyway, I don't think?) to be able to edit comments - I think
+>> user expectations for something that looks like ordinary blog comments are
+>> likely to include "others can't put words into my mouth".
+>>
+>> My other objection to using a namespace is that I'm not particularly happy about
+>> plugins consuming arbitrary pieces of the wiki namespace - /discussion is bad
+>> enough already. Indeed, this very page would accidentally get matched by rules
+>> aiming to control comment-posting... :-) --[[smcv]]
+
+>>> Thinking about it, perhaps one way to address this would be to have the suffix
+>>> (e.g. whether commenting on Sandbox creates sandbox/comment1 or sandbox/c1 or
+>>> what) be configurable by the wiki admin, in the same way that recentchanges has
+>>> recentchangespage => 'recentchanges'? I'd like to see fewer hard-coded page
+>>> names in general, really - it seems odd to me that shortcuts and smileys
+>>> hard-code the name of the page to look at. Perhaps I could add
+>>> discussionpage => 'discussion' too? --[[smcv]]
+
+>>> (I've now implemented this in my branch. --[[smcv]])
+
+>> The best reason to keep the pages internal seems to me to be that you
+>> don't want the overhead of every comment spawning its own wiki page. --[[Joey]]
+
+## Formats (resolved)
+
+The plugin now allows multiple comment formats while still using internal
+pages; each comment is saved as a page containing one `\[[!comment]]` directive,
+which has a superset of the functionality of [[ikiwiki/directives/format]].
+
+## Access control (unresolved?)
+
+By the way, I think that who can post comments should be controllable by
+the existing plugins opendiscussion, anonok, signinedit, and lockedit. Allowing
+posting comments w/o any login, while a nice capability, can lead to
+spam problems. So, use `check_canedit` as at least a first-level check?
+--[[Joey]]
+
+> This plugin already uses `check_canedit`, but that function doesn't have a concept
+> of different actions. The hack I use is that when a user comments on, say, sandbox,
+> I call `check_canedit` for the pseudo-page "sandbox[postcomment]". The
+> special `postcomment(glob)` [[ikiwiki/pagespec]] returns true if the page ends with
+> "[postcomment]" and the part before (e.g. sandbox) matches the glob. So, you can
+> have postcomment(blog/*) or something. (Perhaps instead of taking a glob, postcomment
+> should take a pagespec, so you can have postcomment(link(tags/commentable))?)
+>
+> This is why `anonok_pagespec => 'postcomment(*)'` and `locked_pages => '!postcomment(*)'`
+> are necessary to allow anonymous and logged-in editing (respectively).
+>
+>> I changed that to move the flag out of the page name, and into a variable that the `match_postcomment`
+>> function checks for. Other ugliness still applies. :-) --[[Joey]] 
+>
+> This is ugly - one alternative would be to add `check_permission()` that takes a
+> page and a verb (create, edit, rename, remove and maybe comment are the ones I
+> can think of so far), use that, and port the plugins you mentioned to use that
+> API too. This plugin could either call `check_can("$page/comment1", 'create')` or
+> call `check_can($page, 'comment')`.
+> 
+> One odd effect of the code structure I've used is that we check for the ability to
+> create the page before we actually know what page name we're going to use - when
+> posting the comment I just increment a number until I reach an unused one - so
+> either the code needs restructuring, or the permission check for 'create' would
+> always be for 'comment1' and never 'comment123'. --[[smcv]]
+
+>> Now resolved, in fact --[[smcv]]
+
+> Another possibility is to just check for permission to edit (e.g.) `sandbox/comment1`.
+> However, this makes the "comments can only be created, not edited" feature completely
+> reliant on the fact that internal pages can't be edited. Perhaps there should be a
+> `editable_pages` pagespec, defaulting to `'*'`? --[[smcv]]
+
+## comments directive vs global setting (resolved?)
+
+When comments have been enabled generally, you still need to mark which pages
+can have comments, by including the `\[[!comments]]` directive in them. By default,
+this directive expands to a "post a comment" link plus an `\[[!inline]]` with
+the comments. [This requirement has now been removed --[[smcv]]]
+
+> I don't like this, because it's hard to explain to someone why they have
+> to insert this into every post to their blog. Seems that the model used
+> for discussion pages could work -- if comments are enabled, automatically
+> add the comment posting form and comments to the end of each page.
+> --[[Joey]]
+
+>> I don't think I'd want comments on *every* page (particularly, not the
+>> front page). Perhaps a pagespec in the setup file, where the default is "*"?
+>> Then control freaks like me could use "link(tags/comments)" and tag pages
+>> as allowing comments.
+>>
+>>> Yes, I think a pagespec is the way to go. --[[Joey]]
+
+>>>> Implemented --[[smcv]]
+
+>> 
+>> The model used for discussion pages does require patching the existing
+>> page template, which I was trying to avoid - I'm not convinced that having
+>> every possible feature hard-coded there really scales (and obviously it's
+>> rather annoying while this plugin is on a branch). --[[smcv]]
+
+>>> Using the template would allow customising the html around the comments
+>>> which seems like a good thing? --[[Joey]]
+
+>>>> The \[[!comments]] directive is already template-friendly - it expands to
+>>>> the contents of the template `comments_embed.tmpl`, possibly with the
+>>>> result of an \[[!inline]] appended. I should change `comments_embed.tmpl`
+>>>> so it uses a template variable `INLINE` for the inline result rather than
+>>>> having the perl code concatenate it, which would allow a bit more
+>>>> customization (whether the "post" link was before or after the inline).
+>>>> Even if you want comments in page.tmpl, keeping the separate comments_embed.tmpl
+>>>> and having a `COMMENTS` variable in page.tmpl might be the way forward,
+>>>> since the smaller each templates is, the easier it will be for users
+>>>> to maintain a patched set of templates. (I think so, anyway, based on what happens
+>>>> with dpkg prompts in Debian packages with monolithic vs split
+>>>> conffiles.) --[[smcv]]
+
+>>>>> I've switched my branch to use page.tmpl instead; see what you think? --[[smcv]]
+
+## Raw HTML (resolved?)
+
+Raw HTML was not initially allowed by default (this was configurable).
+
+> I'm not sure that raw html should be a problem, as long as the
+> htmlsanitizer and htmlbalanced plugins are enabled. I can see filtering
+> out directives, as a special case. --[[Joey]]
+
+>> Right, if I sanitize each post individually, with htmlscrubber and either htmltidy
+>> or htmlbalance turned on, then there should be no way the user can forge a comment;
+>> I was initially wary of allowing meta directives, but I think those are OK, as long
+>> as the comment template puts the \[[!meta author]] at the *end*. Disallowing
+>> directives is more a way to avoid commenters causing expensive processing than
+>> anything else, at this point.
+>>
+>> I've rebased the plugin on master, made it sanitize individual posts' content
+>> and removed the option to disallow raw HTML. Sanitizing individual posts before
+>> they've been htmlized required me to preserve whitespace in the htmlbalance
+>> plugin, so I did that. Alternatively, we could htmlize immediately and always
+>> save out raw HTML? --[[smcv]]
+
+>>> There might be some use cases for other directives, such as img, in
+>>> comments.
+>>> 
+>>> I don't know if meta is "safe" (ie, guaranteed to be inexpensive and not
+>>> allow users to do annoying things) or if it will continue to be in the
+>>> future. Hard to predict really, all that can be said with certainty is
+>>> all directives will contine to be inexpensive and safe enough that it's
+>>> sensible to allow users to (ab)use them on open wikis.
+>>> --[[Joey]]
+
+----
+
+I have a test ikiwiki setup somewhere to investigate adopting the comments
+plugin. It is setup with no auth enabled and I got hammered with a spam attack
+over the last weekend (predictably).  What surprised me was the scale of the
+attack: ikiwiki eventually triggered OOM and brought the box down. When I got
+it back up, I checked out a copy of the underlying git repository, and it
+measured 280M in size after being packed. Of that, about 300K was data prior
+to the spam attack, so the rest was entirely spam text, compressed via git's
+efficient delta compression.
+
+I had two thoughts about possible improvements to the comments plugin in the
+wake of this:
+
+ * comment pagination - there is a hard-to-define upper limit on the number
+   of comments that can be appended to a wiki page whilst the page remains
+   legible.  It would be useful if comments could be paginated into sub-pages.
+
+ * crude flood control - asides from spam attacks (and I am aware of
+   [[plugins/blogspam]]), people can crap flood or just aggressively flame
+   repeatedly. An interesting prevention measure might be to not let an IP
+   post more than 3 sequential comments to a page, or to the site, without
+   at least one other comment being interleaved. I say 3 rather than 2 since
+   correction follow-ups are common.
+
+-- [[Jon]]
index 7a230fbae3e7a0aa187977814567a027cfc2260c..95ffb2764ebc7f2fcba3ec0cd6ad28d079f7c361 100644 (file)
@@ -1,47 +1,5 @@
-[[template id=plugin name=conditional core=1 author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=conditional core=1 author="[[Joey]]"]]
+[[!tag type/format]]
 
-With this plugin, you can make text be conditionally displayed on a page.
-For example:
-
-       \[[if test="enabled(smiley)"
-             then="The smiley plugin is enabled :-)"
-             else="No smiley plugin here.."]]
-
-If the specified `test` succeeds, the `then` text will be displayed,
-otherwise the `else` text will be displayed. The `else` part is optional.
-
-The `then` and `else` values can include any markup that would be allowed
-in the wiki page outside the template. Triple-quoting the values even allows
-quotes to be included.
-
-The `test` is a [[ikiwiki/PageSpec]]; if it matches any page in the wiki
-then it succeeds. So you can do things like testing for the existence of a
-page or pages, testing to see if any pages were created in a given month,
-and so on.
-
-If you want the [[ikiwiki/PageSpec]] to only match against the page that
-contains the conditional, rather than matching against all pages in the
-wiki, set the "all" parameter to "no".
-
-The regular [[ikiwiki/PageSpec]] syntax is expanded with the following
-additional tests:
-
-* enabled(plugin)
-
-  Tests whether the specified plugin is enabled.
-
-* sourcepage(glob)
-
-  Tests whether the glob matches the name of the page that contains the
-  conditional.
-
-* destpage(glob)
-
-  Tests whether the glob matches the name of the page that is being built.
-  That might be different than the name of the page that contains the
-  conditional, if it's being inlined into another page.
-
-* included()
-
-  Tests whether the page is being included onto another page.
+This plugin provides the [[ikiwiki/directive/if]] [[ikiwiki/directive]].
+With this directive, you can make text be conditionally displayed on a page.
index 79b8390fa4d7a671865b1b71759e8233237f5369..629d05940e438c1d4ced78fc3b6cc39d7a35caa2 100644 (file)
@@ -14,9 +14,9 @@ is supposed to have *no* blank lines between...
 > The blank lines in this example are coming from the newline after `then="`, and also from the newline before the close quote. If you remove those newlines, I think it should work. --[[Joey]]
 
 >> No, that's unfortunately not it, see here:
->> [[if test="enabled(trallala)" then="foot"]]
+>> [[!if test="enabled(trallala)" then="foot"]]
 >> Continued.  But on the other
->> [[if test="enabled(trallala)" then="foot" else="hand:"]]
+>> [[!if test="enabled(trallala)" then="foot" else="hand:"]]
 >> Continued.  --[[tschwinge]]
 
 >>> Seems ok, no? The only linebreaks I see in the source are the ones you
@@ -25,9 +25,9 @@ is supposed to have *no* blank lines between...
 >>>> Okay, that would explain the linebreak between 1 and 3.  But then, why are all linebreaks removed between 3 and 5?
 
 >>>> 1 No, that's unfortunately not it, see here:
->>>> [[if test="enabled(trallala)" then="foot"]]
+>>>> [[!if test="enabled(trallala)" then="foot"]]
 >>>> 3 Continued.  But on the other
->>>> [[if test="enabled(trallala)" then="foot" else="hand:"]]
+>>>> [[!if test="enabled(trallala)" then="foot" else="hand:"]]
 >>>> 5 Continued.  --[[tschwinge]]
 
 >>>>> The conditional after 1 evaluates to "", so there's a blank line
@@ -38,10 +38,10 @@ I have a sidebar that contains
 <pre>
   #### Archives
 
-  \[[calendar type="year" months_per_row="6"  pages="blog/* and !*/Discussion"]]
-  \[[calendar type="month" pages="blog/* and !*/Discussion"]]
+  \[[!calendar type="year" months_per_row="6"  pages="blog/* and !*/Discussion"]]
+  \[[!calendar type="month" pages="blog/* and !*/Discussion"]]
   &lt;h4&gt;Indices&lt;/h4&gt
-  \[[map pages="archives/* and !*/Discussion"]]
+  \[[!map pages="archives/* and !*/Discussion"]]
 </pre>
 I am trying to make it so that the archives and index only show up if the destpage is either blog/* or / -- the top of the wiki. Unfortunately, I don't think I am getting the
 conditional right -- I have a "]] left over at the end (looking at the rendered html). Ideally, I would like to be able to do todays calendar on the top level pagel and 
index d0b3fa7506ea8b0b79615065248c6b654e25f742..a03e6a95d72993abf28aeb5b68a40ed0cbbf4dc2 100644 (file)
@@ -1,7 +1,6 @@
-Contributed [[plugins]]:
+These plugins are provided by third parties and are not currently
+included in ikiwiki. See [[install]] for installation help.
 
-(See [[install]] for installation help.)
-
-[[inline pages="plugins/contrib/* !*/Discussion" 
+[[!inline pages="plugins/contrib/* and !*/Discussion" 
 feedpages="created_after(plugins/contrib/navbar)" archive="yes"
 rootpage="plugins/contrib" postformtext="Add a new plugin named:" show=0]]
diff --git a/doc/plugins/contrib/album.mdwn b/doc/plugins/contrib/album.mdwn
new file mode 100644 (file)
index 0000000..395c99b
--- /dev/null
@@ -0,0 +1,108 @@
+[[!template id=plugin name=album author="[[Simon_McVittie|smcv]]"]]
+[[!template id=gitbranch branch=smcv/album author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/chrome]]
+
+Available from [[smcv]]'s git repository, in the `album` branch
+([[users/smcv/gallery|users/smcv/gallery]] contains some older
+thoughts about this plugin).
+
+This plugin formats a collection of images into a photo album,
+in the same way as many websites: good examples include the
+PHP application [Gallery](http://gallery.menalto.com/), Flickr,
+and Facebook's Photos "application". I've called it `album`
+to distinguish it from [[contrib/gallery|plugins/contrib/gallery]],
+although `gallery` might well be a better name for this functionality.
+
+The web UI I'm trying to achieve consists of one
+[HTML page of thumbnails](http://www.pseudorandom.co.uk/2008/2008-03-08-panic-cell-gig/)
+as an entry point to the album, where each thumbnail links to
+[a "viewer" HTML page](http://www.pseudorandom.co.uk/2008/2008-03-08-panic-cell-gig/img_0068/)
+with a full size image, next/previous thumbnail links, and
+[[plugins/comments]].
+
+(The Summer of Code [[plugins/contrib/gallery]] plugin does the
+next/previous UI in Javascript using Lightbox, which means that
+individual photos can't be bookmarked in a meaningful way, and
+the best it can do as a fallback for non-Javascript browsers
+is to provide a direct link to the image.)
+
+## Writing the viewers
+
+    \[[!albumimage image=foo.jpg album=myalbum
+        title=...
+        caption=...
+        copyright=...
+        size=...
+        viewertemplate=...
+    ]]
+
+Each viewer contains one `\[[!albumimage]]` directive. This
+sets the `image` filename, the `album` in which this image appears,
+and an optional `caption`, and can override the `size` at which to
+display the image and the `viewertemplate` to use to display the
+image.
+
+It can also have `title`, `copyright` and `date` parameters, which
+are short-cuts for [[ikiwiki/directive/meta]] directives.
+
+The viewer can also have any other content, but typically the
+directive will be the only thing there.
+
+Eventually, there will be a specialized CGI user interface to
+edit all the photos of an album at once, upload a new photo
+(which will attach the photo but also write out a viewer page
+for it), or mark an already-uploaded photo as a member of an
+album (which is done by writing out a viewer page for it).
+
+The `\[[!albumimage]]` directive is replaced by an
+[[ikiwiki/directive/img]], wrapped in some formatting using a
+template (by default `albumviewer.tmpl`). The template can (and
+should) also include "next photo", "previous photo" and
+"up to gallery" links.
+
+The next/previous links are themselves implemented by
+[[inlining|ikiwiki/directive/inline]] the next or previous
+photo, using a special template (by default `albumnext.tmpl`
+or `albumprev.tmpl`), in `archive`/`quick` mode.
+
+> With hindsight, using an inline here is wrong - I should just
+> run hooks and fill in the template within the album plugin.
+> inline has some specialized functionality that's overkill
+> here, and its delayed HTML substitution breaks the ability
+> to have previous/up/next links both above and below the
+> photo, for instance. --[[smcv]]
+
+## Writing the album
+
+The album contains one `\[[!album]]` directive. It may also
+contain any number of `\[[!albumsection]]` directives, for
+example the demo album linked above could look like:
+
+    \[[!album]]
+    <!-- replaced with one uncategorized photo -->
+
+    ## Gamarra
+
+    \[[!albumsection filter="link(gamarra)"]]
+    <!-- all the Gamarra photos -->
+
+    ## Smokescreen
+
+    \[[!albumsection filter="link(smokescreen)"]]
+    <!-- all the Smokescreen photos -->
+
+    ...
+
+The `\[[!album]]` directive is replaced by an
+[[ikiwiki/directive/inline]] which automatically includes every
+page that has an `\[[!albumimage]]` directive linking it to this
+album, except those that will appear in an `\[[!albumsection]]`.
+
+The `inline` is in `archive`/`quick` mode, but includes some
+extra information about the images, including file size and a
+thumbnail (again, made using [[ikiwiki/directive/img]]). The
+default template is `albumitem.tmpl`, which takes advantage
+of these things.
+
+Each `\[[!albumsection]]` is replaced by a similar inline, which
+selects a subset of the photos in the album.
index ab50715c71c1f6b11d705fd44c5c6adb52727172..f44125b101b6e4684451bab6ad9de24a1018e861 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=attach author="[[Ben]]"]]
+[[!template id=plugin name=attach author="[[Ben]]"]]
 
 **Note: This plugin is currently pending upload. It is also most assuredly beta.**
 
diff --git a/doc/plugins/contrib/cvs.mdwn b/doc/plugins/contrib/cvs.mdwn
new file mode 100644 (file)
index 0000000..6b600ee
--- /dev/null
@@ -0,0 +1,33 @@
+[[!template id=plugin name=cvs core=0 author="[[schmonz]]"]]
+
+[[!template id=gitbranch branch=schmonz author="[[schmonz]]"]]
+
+This plugin allows ikiwiki to use [[!wikipedia desc="CVS" Concurrent Versions System]] as an [[rcs]].
+
+### Usage
+7. Install [cvsps](http://www.cobite.com/cvsps/), [[!cpan IPC::Cmd]], [[!cpan String::ShellQuote]], and [cvsweb](http://www.freebsd.org/projects/cvsweb.html) or the like.
+7. Adjust CVS-related parameters in your setup file.
+
+Consider creating `$HOME/.cvsrc` if you don't have one already; the plugin doesn't need it, but you yourself might. Here's a good general-purpose one:
+
+    cvs -q
+    checkout -P
+    update -dP
+    diff -u
+    rdiff -u
+
+### Implementation details
+* `cvs.pm` started life as a copy of [[3.14159|news/version_3.14159]]'s `svn.pm`.
+* `IkiWiki.pm:wiki_file_prune_regexps` avoids copying CVS metadata into `$DESTDIR`.
+* [[ikiwiki-makerepo]]:
+ * creates a repository,
+ * imports `$SRCDIR` into top-level module `ikiwiki` (vendor tag IKIWIKI, release tag PRE_CVS),
+ * configures the post-commit hook in `CVSROOT/loginfo`.
+* CVS multi-directory commits happen separately; the post-commit hook sees only the first directory's changes in time for [[recentchanges|plugins/recentchanges]]. The next run of `ikiwiki --setup` will correctly re-render such a recentchanges entry. It should be possible to solve this problem with NetBSD's `commit_prep` and `log_accum` scripts (see below).
+
+### To do
+* Add automated tests. (Blindly adding svn-like tests to `t/file_pruned.t` doesn't do the trick.)
+* If the argument to `cvs add` smells like a binary file, `cvs add -kb` it (for [[plugins/attachment]] support).
+* Don't slurp the entire `cvsps` output into memory (!).
+* Instead of resource-intensively scraping changesets with `cvsps`, have `ikiwiki-makerepo` set up NetBSD-like `log_accum` and `commit_prep` scripts that coalesce and keep records of commits. `cvsps` can be used as a fallback for repositories without such records.
+* Perhaps prevent web edits from attempting to create `.../CVS/foo.mdwn` (and `.../cvs/foo.mdwn` on case-insensitive filesystems); thanks to the CVS metadata directory, the attempt will fail anyway (and much more confusingly) if we don't.
diff --git a/doc/plugins/contrib/cvs/discussion.mdwn b/doc/plugins/contrib/cvs/discussion.mdwn
new file mode 100644 (file)
index 0000000..e1fa6e4
--- /dev/null
@@ -0,0 +1,91 @@
+I've started reviewing this, and the main thing I don't like is the
+post-commit wrapper wrapper that ikiwiki-makerepo is patched to set up.
+That just seems unnecessarily complicated. Why can't ikiwiki itself detect
+the "cvs add <directory>" call and avoid doing anything in that case?
+--[[Joey]] 
+
+> The wrapper wrapper does three things:
+>
+> 7. It ignores `cvs add <directory>`, since this is a weird CVS
+> behavior that ikiwiki gets confused by and doesn't need to act on.
+> 7. It prevents `cvs` locking against itself: `cvs commit` takes a
+> write lock and runs the post-commit hook, which runs `cvs update`,
+> which wants a read lock and sleeps forever -- unless the post-commit
+> hook runs in the background so the commit can "finish".
+> 7. It fails silently if the ikiwiki post-commit hook is missing.
+> CVS doesn't have any magic post-commit filenames, so hooks have to
+> be configured explicitly. I don't think a commit will actually fail
+> if a configured post-commit hook is missing (though I can't test
+> this at the moment).
+>
+> Thing 1 can probably be handled within ikiwiki, if that seems less
+> gross to you.
+
+>> It seems like it might be. You can use a `getopt` hook to check
+>> `@ARGV` to see how it was called. --[[Joey]] 
+
+>>> This does the trick iff the post-commit wrapper passes its args
+>>> along. Committed on my branch. This seems potentially dangerous,
+>>> since the args passed to ikiwiki are influenced by web commits.
+>>> I don't see an exploit, but for paranoia's sake, maybe the wrapper
+>>> should only be built with execv() if the cvs plugin is loaded?
+>>> --[[schmonz]]
+
+>>>> Hadn't considered that. While in wrapper mode the normal getopt is not
+>>>> done, plugin getopt still runs, and so any unsafe options that 
+>>>> other plugins support could be a problem if another user runs
+>>>> the setuid wrapper and passes those options through. --[[Joey]]
+
+>>>>> I've tried compiling the argument check into the wrapper as
+>>>>> the first thing main() does, and was surprised to find that
+>>>>> this doesn't prevent the `cvs add <dir>` deadlock in a web
+>>>>> commit. I was convinced this'd be a reasonable solution,
+>>>>> especially if conditionalized on the cvs plugin being loaded,
+>>>>> but it doesn't work. And I stuck debug printfs at the beginning
+>>>>> of all the rcs_foo() subs, and whatever `cvs add <dir>` is
+>>>>> doing to ikiwiki isn't visible to my plugin, because none of
+>>>>> those subs are getting called. Nuts. Can you think of anything
+>>>>> else that might solve the problem, or should I go back to
+>>>>> generating a minimal wrapper wrapper that checks for just
+>>>>> this one thing? --[[schmonz]]
+
+>>>>>> I don't see how there could possibly be a difference between
+>>>>>> ikiwiki's C wrapper and your shell wrapper wrapper here. --[[Joey]]
+
+> Thing 2 I'm less sure of. (I'd like to see the web UI return
+> immediately on save anyway, to a temporary "rebuilding, please wait
+> if you feel like knowing when it's done" page, but this problem
+> with CVS happens with any kind of commit, and could conceivably
+> happen with some other VCS.)
+
+>> None of the other VCSes let a write lock block a read lock, apparently.
+>> 
+>> Anyway, re the backgrounding, when committing via the web, the
+>> post-commit hook doesn't run anyway; the rendering is done via the
+>> ikiwiki CGI. It would certianly be nice if it popped up a quick "working"
+>> page and replaced it with the updated page when done, but that's
+>> unrelated;  the post-commit
+>> hook only does rendering when committing using the VCS directly. The
+>> backgrounding you do actually seems safe enough -- but tacking
+>> on a " &" to the ikiwiki wrapper call doesn't need a wrapper script,
+>> does it? --[[Joey]]
+
+>>> Nope, it works fine to append it to the `CVSROOT/loginfo` line.
+>>> Fixed on my branch. --[[schmonz]]
+
+> Thing 3 I think I did in order to squelch the error messages that
+> were bollixing up the CGI. It was easy to do this in the wrapper
+> wrapper, but if that's going away, it can be done just as easily
+> with output redirection in `CVSROOT/loginfo`.
+>
+> --[[schmonz]]
+
+>> If the error messages screw up the CGI they must go to stdout.
+>> I thought we had stderr even in the the CVS dark ages. ;-) --[[Joey]] 
+
+>>> Some messages go to stderr, but definitely not all. That's why
+>>> I wound up reaching for IPC::Cmd, to execute the command line
+>>> safely while shutting CVS up. Anyway, I've tested what happens
+>>> if a configured post-commit hook is missing, and it seems fine,
+>>> probably also thanks to IPC::Cmd.
+>>> --[[schmonz]]
index 27e0ffefd75ead15575de26a1dcf32c54274469c..b9ad3cc8eb3375a5e3f94b7a69e0045afa6e8b6b 100644 (file)
@@ -1,21 +1,16 @@
-[[template id=plugin name=copyright author="[[tschwinge]]"]]
-[[template id=plugin name=license author="[[tschwinge]]"]]
+[[!template id=plugin name=copyright author="[[tschwinge]]"]]
+[[!template id=plugin name=license author="[[tschwinge]]"]]
 
-[[meta title="default content for *copyright* and *license*"]]
+[[!meta title="default content for *copyright* and *license*"]]
 
 Someone was just asking for it and I had written these two plugins already some months ago,
 so I'm now publishing them here.
 
-<http://www.schwinge.homeip.net/~thomas/tmp/copyright.pm>
-<http://www.schwinge.homeip.net/~thomas/tmp/license.pm>
+[`copyright.pm`](http://www.schwinge.homeip.net/~thomas/tmp/copyright.pm)
+and
+[`license.pm`](http://www.schwinge.homeip.net/~thomas/tmp/license.pm)
 
-/!\ Note that there is still an issue to be resolved with these plugins: have a look at
-[tmpfs](http://www.bddebian.com/~wiki/hurd/translator/tmpfs/).  There are two inlined pages,
-[tmpfs-notes\_bing](http://www.bddebian.com/~wiki/hurd/translator/tmpfs/notes_bing/) and
-[tmpfs-notes\_various](http://www.bddebian.com/~wiki/hurd/translator/tmpfs/notes_various/).
-Compare the *copyright* and *license* information of the inlined pages on *tmpfs* to those
-on the source pages, *tmpfs-notes_bing* and *tmpfs-notes_various*.
-They are different, but shouldn't be.
+Usage instructions are found inside the two plugin files.
 
 --[[tschwinge]]
 
@@ -28,5 +23,25 @@ template variable somebody wants to use.
 --[[bma]]
 
 Copyright and license values are not "template values", they are values
-tracked by the meta plugin, and that various code compares and uses to fill
+tracked by the [[meta]] plugin, and that various code compares and uses to fill
 out the templates. Something like varioki cannot do that. --[[Joey]]
+
+Somewhat more detailed usage documentation would be appreciated. I tried to setup
+those plugins with a current ikiwiki release, i.e. 2.61, but they appeared to do
+nothing, really. Also, those example pages don't seem to use those plugins, even;
+they set "copyright" and "license" properties using ordinary [[meta]] tags. Maybe
+I'm missing something terribly obvious? --Peter
+
+> Only obvious if you read the source :-). You need to put a file named "copyright.html"
+>(respectively "license.html") in your wiki. Everything underneath that (in the wikilink sense) will use that
+>content for the license or copyright. Saves putting \[[meta license="foo"]] in every page [[DavidBremner]]
+
+By the way: these need not be *HTML* files; `copyright.mdwn`,
+respectively `license.mdwn`, or every other format supported
+by ikiwiki are likewise fine.  --[[tschwinge]]
+
+> Jon has done something similar in [[todo/allow_site-wide_meta_definitions]];
+> his version has the advantages that it doesn't invent magical page names,
+> and can extend beyond just copyright and license, but has the disadvantage
+> that it doesn't support setting defaults for a given "subdirectory"
+> only. --[[smcv]]
index 06c1844f726dedad4843796dc0d64f91b9deead9..72df13bd0b06a47d05a5b79834d85d9ac32e0a77 100644 (file)
@@ -1,12 +1,12 @@
-[[template id=plugin name=gallery author="[[arpitjain]]"]]
+[[!template id=plugin name=gallery author="[[arpitjain]]"]]
 
 This plugin would create a nice looking gallery of the images. It has been build over the img plugin in Ikiwiki
 
-SVN repository of plugin is located at <http://ned.snow-crash.org:8080/svn/ikiwiki-gallery>
+GIT repo of the plugin is located at <http://github.com/joeyh/ikiwiki/tree/gallery>
 
 
 USAGE : 
-\[[gallery imagedir="images" option="value"]]
+\[[!gallery imagedir="images" option="value"]]
 
 Available options : <br>
     * imagedir(required) => Directory containing images. It will scan all the files with jpg|png|gif extension from the directory and will put it in the gallery.<br>
@@ -32,7 +32,8 @@ It uses templated named [Lightbox](http://www.hudddletogether.com).
 For any feedback or query, feel free to mail me at arpitjain11 [AT] gmail.com 
 
 Additional details are available [here](http://myweb.unomaha.edu/~ajain/ikiwikigallery.html).
+> That link is broken. --[[JosephTurian]]
 
 -- [[arpitjain]]
 
-[[tag plugins]] [[tag patch]] [[tag soc]] [[tag wishlist]]
+[[!tag plugins]] [[!tag patch]] [[!tag soc]] [[!tag wishlist]]
index 37fa6f884a829afaedf9755a89df430c32ab713f..08fc2456f95ab2cf7bdef72b9c166f2b0e2a3f4f 100644 (file)
@@ -6,13 +6,13 @@ rebased it onto the *origin/master*, built a Debian package and installed that o
 However, I can't even get simply things like this to work:
 
     $ cat web/index.mdwn
-    [[gallery imagedir="b" vcs="0"]]
+    [[!gallery imagedir="b" vcs="0"]]
     $ ls web/b/
     1.jpg  2.jpg  3.jpg  4.jpg
     $ ikiwiki [...] --plugin gallery web web.rendered
     [...]
     $ grep gallery web.rendered/index.html 
-    <p>[[gallery Failed to Read Directory b.]]</p>
+    <p>[[!gallery Failed to Read Directory b.]]</p>
 
 When using `vcs="1"` it's no better:
 
@@ -25,7 +25,7 @@ When using `vcs="1"` it's no better:
 Its probably because of the restriction of permissions by plugins in newer version of IkiWiki. 
 For the time being, you can turn resizing off till I look into conditional underlay directory feature. 
 
-USAGE : [[gallery imagedir="directory" resize="0"]]
+USAGE : [[!gallery imagedir="directory" resize="0"]]
 
 New version updated at SVN REPO : http://ned.snow-crash.org:8080/svn/ikiwiki-gallery/
 
index 93f415fb5ed7e40bc67702fbc476d3772dff89cd..953f296abb049de647dccdc5fb45446f6e431c50 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=googlemaps author="Christian Mock"]]
-[[tag type/special-purpose todo/geotagging]]
+[[!template id=plugin name=googlemaps author="Christian Mock"]]
+[[!tag type/special-purpose todo/geotagging]]
 
 `googlemaps` is a plugin that allows using the [Google Maps API][2]
 from ikiwiki.
index 287afa0f541922b63d1458625b592502fc2c3313..becbf89a518daf924e38d102f60a9ce299c85dd8 100644 (file)
@@ -1,6 +1,6 @@
-[[template id=plugin name=headinganchors author="[[PaulWise]]"]]
+[[!template id=plugin name=headinganchors author="[[PaulWise]]"]]
 
-This is a simple plugin to add ids to all headings, based on their text. It
+This is a simple plugin to add ids (which will serve as [[anchor]]s) to all headings, based on their text. It
 works as a postprocessing filter, allowing it to work on mdwn, wiki, html,
 rst and any other format that produces html. The code is available here:
 
@@ -12,9 +12,9 @@ rst and any other format that produces html. The code is available here:
        use strict;
        use IkiWiki 2.00;
 
-       sub import { #{{{
+       sub import {
                hook(type => "sanitize", id => "headinganchors", call => \&headinganchors);
-       } # }}}
+       }
 
        sub text_to_anchor {
                my $str = shift;
@@ -26,11 +26,11 @@ rst and any other format that produces html. The code is available here:
                return $str;
        }
 
-       sub headinganchors (@) { #{{{
+       sub headinganchors (@) {
                my %params=@_;
                my $content=$params{content};
                $content=~s{<h([0-9])>([^>]*)</h([0-9])>}{'<h'.$1.' id="'.text_to_anchor($2).'">'.$2.'</h'.$3.'>'}gie;
                return $content;
-       } # }}}
+       }
 
        1
diff --git a/doc/plugins/contrib/headinganchors/discussion.mdwn b/doc/plugins/contrib/headinganchors/discussion.mdwn
new file mode 100644 (file)
index 0000000..91fe04a
--- /dev/null
@@ -0,0 +1 @@
+Isn't this functionality a part of what [[plugins/toc]] needs and does? Then probably the [[plugins/toc]] plugin's code could be split into the part that implements the [[plugins/contrib/headinganchors]]'s functionality and the TOC generation itself. That will bring more order into the code and the set of available plugins. --Ivan Z.
index 9b43a106cad03bf736375faf2e4a22280ef00e1e..8abb76583b58f156986d7d00d0c3dcb15d603538 100644 (file)
@@ -1,3 +1,6 @@
+[[!template id=plugin name=highlightcode author="[[sabr]]"]]
+[[!tag type/format]]
+
 A small plugin to allow Ikiwiki to display source files complete with syntax highlighting. Files with recognized extensions (i.e. my-file.cpp) are be rendered just like any other Ikiwiki page. You can even edit your source files with Ikiwiki's editor.
 
 It uses the Syntax::Highlight::Engine::Kate Perl module to do the highlighting.
index c55338bf575a098e41a082453f8c8a5fab7a1161..6c25966e0bed620be0e9712b25f3d5ef187aa086 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=img author="Christian Mock"]]
-[[tag type/chrome]]
+[[!template id=plugin name=img author="Christian Mock"]]
+[[!tag type/chrome]]
 
 `img` is an enhanced image handling plugin.
 
index d4b38fb61dc365e287df3bd3b92c9cdc870b86e5..ea4ccb042bdd7e3b2f1faefcede8fb21c6b7fb31 100644 (file)
@@ -10,18 +10,18 @@ differently scaled versions of the image, why not just create three pages
 and use the plugin once per page? Something like this on the first one if
 it's got multiple clickable thumbnails:
 
-       \[[img foo.jpg width=256 link=page2]]
+       \[[!img foo.jpg width=256 link=page2]]
 
 This on the second:
 
-       \[[img foo.jpg width=1024 link=page3]]
+       \[[!img foo.jpg width=1024 link=page3]]
        \[[small|page1]]
        \[[medium|page2]]
        \[[large|page3]]
 
 This on the third:
        
-       \[[img foo.jpg link=page3]]
+       \[[!img foo.jpg link=page3]]
        \[[small|page1]]
        \[[medium|page2]]
        \[[large|parge3]]
index 204910290e6a818f549cae35c42e1752204192c3..84ece042e4e694d6fad0e52d9005a6e0423e426a 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=linguas author="Jordà Polo"]]
+[[!template id=plugin name=linguas author="Jordà Polo"]]
 
 Linguas
 =======
@@ -10,7 +10,8 @@ Download: [linguas.pm](http://ettin.org/pub/ikiwiki/linguas.pm) (2006-08-21).
 
 Note that even though it is still available for download, this plugin is no
 longer actively maintained. If you are interested in multilingual wiki pages, you
-can also take a look at other approaches such as [[todo/l10n]] or Lars Wirzenius's
+can also take a look at other approaches such as [[todo/l10n]], [[plugins/po]],
+or Lars Wirzenius's
 [Static website, with translations, using IkiWiki](http://liw.iki.fi/liw/log/2007-05.html#20070528b).
 
 Usage
@@ -20,14 +21,14 @@ Translatable pages and translations must have the following format:
 `pagename.$LANG`, where `$LANG` is a ISO639-1 (two-letter) language code.
 To enable linguas, add the following line in the source code of the page:
 
-       \[[linguas ]]
+       \[[!linguas ]]
 
 Note that linguas is only required in one of the pages (the original,
 for instance); the rest of translations will be automatically
 updated. Additionally, it is also possible to specify the title of
 the translation:
 
-       \[[linguas title="Translated title"]]
+       \[[!linguas title="Translated title"]]
 
 
 Template
@@ -103,4 +104,4 @@ The following fixes it:
         +               push @links, IkiWiki::htmllink($page, $destpage, $trans, noimageinline => 0, forcesubpage => 0, linktext => $link);
                 }
          
-                my $otherlinguas = 'Translations:';
\ No newline at end of file
+                my $otherlinguas = 'Translations:';
diff --git a/doc/plugins/contrib/mailbox.mdwn b/doc/plugins/contrib/mailbox.mdwn
new file mode 100644 (file)
index 0000000..b7a9f81
--- /dev/null
@@ -0,0 +1,18 @@
+[[!template id=plugin name=mailbox author="[[DavidBremner]]"]]
+[[!tag type/format]]
+
+The `mailbox` plugin adds support to ikiwiki for 
+rendering mailbox file into a page displaying the mails
+in the mailbox. It supports mbox, maildir, and MH folders,
+does threading, and deals with MIME.
+
+One hitch I noticed was that it is not currently possible to treat a
+maildir or an MH directory as a page (i.e. just call it foo.mh and have it
+transformed to page foo). I'm not sure if this is possible and worthwhile
+to fix. It is certainly workable to use a [[!mailbox ]] directive.
+-- [[DavidBremner]]
+
+This plugin is not in ikiwiki yet, but can be downloaded
+from <http://pivot.cs.unb.ca/git/ikimailbox.git>
+
+
diff --git a/doc/plugins/contrib/mailbox/discussion.mdwn b/doc/plugins/contrib/mailbox/discussion.mdwn
new file mode 100644 (file)
index 0000000..00fb0c0
--- /dev/null
@@ -0,0 +1,5 @@
+# The remote repo
+
+For some reason, `git fetch` from http://pivot.cs.unb.ca/git/ikimailbox.git/ didn't work very smoothly for me: it hung, and I had to restart it 3 times before the download was complete.
+
+I'm writing this just to let you know that there might be some problems with such connections to your http-server. --Ivan Z.
diff --git a/doc/plugins/contrib/mediawiki.mdwn b/doc/plugins/contrib/mediawiki.mdwn
new file mode 100644 (file)
index 0000000..7bf1ba0
--- /dev/null
@@ -0,0 +1,7 @@
+[[!template id=plugin name=mediawiki author="[[sabr]]"]]
+[[!tag type/format]]
+
+[The Mediawiki plugin](http://u32.net/Mediawiki_Plugin/) allows ikiwiki to
+process pages written using MediaWiki markup.
+
+Available at <http://alcopop.org/~jon/mediawiki.pm>
diff --git a/doc/plugins/contrib/mediawiki/discussion.mdwn b/doc/plugins/contrib/mediawiki/discussion.mdwn
new file mode 100644 (file)
index 0000000..5066d9d
--- /dev/null
@@ -0,0 +1,5 @@
+Anyone know a safe place where this plugin can be found? -- mjr at phonecoop.coop
+
+> I ended up doing a backassward way of doing it, as described at the [convert discussion page](http://ikiwiki.info/tips/convert_mediawiki_to_ikiwiki/discussion/). -[[simonraven]]
+
+>> I've mirrored it at <http://alcopop.org/~jon/mediawiki.pm>. -- [[Jon]]
index 830179999f13fa37c3333ebd4ae476b026e45649..061e4588c88e023cb43fc71a52483982cca55b85 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=navbar author="[[TobiOetiker]]"]]
+[[!template id=plugin name=navbar author="[[TobiOetiker]]"]]
 
 The Navbar Plugin renders a Navigation Bar into your page. It is based on code
 from the [[sidebar_plugin|plugins/sidebar]].
diff --git a/doc/plugins/contrib/navbar/discussion.mdwn b/doc/plugins/contrib/navbar/discussion.mdwn
new file mode 100644 (file)
index 0000000..0bbec74
--- /dev/null
@@ -0,0 +1,2 @@
+Where can I download this plugin ?
+-- [[jogo]]
diff --git a/doc/plugins/contrib/opml.mdwn b/doc/plugins/contrib/opml.mdwn
new file mode 100644 (file)
index 0000000..3f98e80
--- /dev/null
@@ -0,0 +1,11 @@
+[[!template id=plugin name=opml author="[[JanWalzer|jwalzer]]"]]
+[[!tag type/format]]
+
+The idea of this plugin is to parse in an OPML-File and output a linklist, maybe some customization.
+OPML-Files are xml-files that most RSS-Readers write out, to summarize their subscribes feedlist.
+
+I have a "dumb" perlscript running on my website, that tries to do a opml2mdwn transformation, but its quite bad on that.
+
+This Plugin is **NOT Ready** in any way. I'm just putting this page up as a hook, to discuss it.
+
+I intend to work on this, but I'd appreciate any help on this.
diff --git a/doc/plugins/contrib/opml/discussion.mdwn b/doc/plugins/contrib/opml/discussion.mdwn
new file mode 100644 (file)
index 0000000..3a145c7
--- /dev/null
@@ -0,0 +1,4 @@
+If this is the wrong place for the development of the plugin, please mode it on to a more appropriate one. 
+
+Currently I'm quite stuck with the perl-stuff itself. I'm trying to become comfortable with the language, but it seems, the language doesn't like me. I'm lost in complex datastructures, when trying to iterate through the output of XML::Simple. --[[Jan|jwalzer]]
+
diff --git a/doc/plugins/contrib/postal.mdwn b/doc/plugins/contrib/postal.mdwn
new file mode 100644 (file)
index 0000000..b2f8753
--- /dev/null
@@ -0,0 +1,35 @@
+[[!template id=plugin name=postal author="[[DavidBremner]]"]]
+[[!tag type/useful]]
+
+The `postal` plugin allows users to send mail to
+a special address to comment on a page. It uses the [[mailbox]]
+plugin to display their comments in the wiki.
+
+This plugin is not in ikiwiki yet, but can be downloaded
+from <http://pivot.cs.unb.ca/git/ikipostal.git>
+
+Details:
+
+  * Adds a mailto: url to each page matching some pagespec
+    (currently every page gets a comment footer)
+
+  * This mailto url goes to an address identifying the page  (something like
+    user-iki-blog~I\_hate\_markdown@host.fqdn.tld).
+    [more details](http://www.cs.unb.ca/~bremner/blog/posts/encoding)         
+   
+  * on the mail receiving end, these messages are either deleted, or ran through
+    a filter to be turned into blog posts.   I have
+[written](http://pivot.cs.unb.ca/git/?p=ikipostal.git;a=blob_plain;f=filters/postal-accept.pl;hb=HEAD)
+  a filter that decodes the address and writes the message into an appropriate 
+mailbox. The changes are then checked into version control; typically a hook then updates the html version of the wiki.
+  * work in progress can be 
+
+   - [cloned](http://pivot.cs.unb.ca/git/ikipostal.git), or 
+   - [browsed](http://pivot.cs.unb.ca/git/?p=ikipostal.git;a=summary)
+  
+ * I would be interested in any ideas people have about security.
+
+The current version of this plugin is now running on my home page. See for example
+[a recent post in my blog](http://www.cs.unb.ca/~bremner/blog/posts/can-i-haz-a-distributed-rss/).  
+Unfortunately although the [[mailbox|todo/mbox]] renderer supports threading, I haven't had 
+a chance to implement comments on comments yet. --[[DavidBremner]]
diff --git a/doc/plugins/contrib/postal/discussion.mdwn b/doc/plugins/contrib/postal/discussion.mdwn
new file mode 100644 (file)
index 0000000..4eaacc0
--- /dev/null
@@ -0,0 +1,24 @@
+It seems like the filter 'postal-accept.pl' I wrote doesn't refresh thoroughly enough.  When a comment is added  it calls
+
+         IkiWiki::add_depends($page,$comments_page);
+
+And then after adding the actual comment, it ends with
+
+         IkiWiki::refresh();
+         IkiWiki::saveindex();
+
+Sure enough, the page being commented on is refreshed, but not any inline pages (e.g. tags pages, blog top level) that contain it.
+Is there a way to recursively refresh? Or should it work that way by default. I guess it is some part of the api that I don't understand, 
+since I think not many people grub about in the internals of ikiwiki this way.
+It would be nice to figure this out, doing a full rebuild every time I get a blog comment is not that fun.
+
+[[DavidBremner]]
+
+> Ikiwiki currently doesn't have support for transitive dependencies.
+> This is discussed deep inside [[todo/tracking_bugs_with_dependencies]]
+> and in [[todo/inlines_inheriting_links]]. 
+> 
+> FYI, the [[plugins/comments]] plugin avoids this problem by only showing the
+> comments on the page, and not on pages that inline it. --[[Joey]] 
+>> Ok, thanks for the speedy response. I guess I should do the same thing.
+>> [[DavidBremner]]
diff --git a/doc/plugins/contrib/rsync.mdwn b/doc/plugins/contrib/rsync.mdwn
new file mode 100644 (file)
index 0000000..71cd639
--- /dev/null
@@ -0,0 +1,21 @@
+[[!template id=plugin name=rsync core=0 author="[[schmonz]]"]]
+
+[[!template id=gitbranch branch=schmonz author="[[schmonz]]"]]
+
+This plugin allows ikiwiki to push generated pages to another host
+by running a command such as `rsync`.
+
+### Usage
+7. Enable automated SSH key exchange between ikiwiki and the remote
+   host. [keychain](http://www.gentoo.org/proj/en/keychain/) makes
+   it easy to use a passphrase-protected key for this purpose. It's
+   also a good idea to specify the exact command line to be permitted
+   in the remote host's `$HOME/.ssh/authorized_keys`.
+7. Set `rsync_command` in your setup file. If you're using a
+   passphrase-protected key, then set `rsync_command` to a shell
+   script which reads `keychain`'s current state before calling
+   `rsync`.
+
+### Implementation details
+* The plugin relies on a new "postrefresh" hook called at the very end of
+  `IkiWiki/Render.pm:refresh()`.
diff --git a/doc/plugins/contrib/rsync/discussion.mdwn b/doc/plugins/contrib/rsync/discussion.mdwn
new file mode 100644 (file)
index 0000000..20c04af
--- /dev/null
@@ -0,0 +1,48 @@
+## A use case
+
+Why I needed this plugin: I have two web servers available to me
+for a project. Neither does everything I need, but together they
+do. (This is a bit like the [Amazon S3
+scenario](http://kitenet.net/~joey/blog/entry/running_a_wiki_on_Amazon_S3/).)
+
+Server (1) is a university web server. It provides plentiful space
+and bandwidth, easy authentication for people editing the wiki, and
+a well-known stable URL. The wiki really wants to live here and
+very easily could except that the server doesn't allow arbitrary
+CGIs.
+
+Server (2) is provided by a generous alumnus's paid [[tips/DreamHost]]
+account. Disk and particularly network usage need to be minimized
+because over some threshold it costs him. CGI, etc. are available.
+
+My plan was to host the wiki on server (1) by taking advantage of
+server (2) to store the repository, source checkout, and generated
+pages, to host the repository browser, and to handle ikiwiki's CGI
+operations. In order for this to work, web edits on (2) would need
+to automatically push any changed pages to (1).
+
+As a proof of concept, I added an rsync post-commit hook after
+ikiwiki's usual. It worked, just not for web edits, which is how
+the wiki will be used. So I wrote this plugin to finish the job.
+The wiki now lives on (1), and clicking "edit" just works. --[[schmonz]]
+
+> Just out of interest, why use `rsync` and not `git push`.  i.e. a
+> different setup to solve the same problem would be to run a
+> normal ikiwiki setup on the universities server with its git
+> repository available over ssh (same security setup your using
+> for rsync should work for git over ssh).  On the cgi-capable server,
+> when it would rsync, make it git push.  It would seem that git
+> has enough information that it should be able to be more
+> network efficient.  It also means that corruption at one end
+> wouldn't be propagated to the other end. -- [[Will]]
+
+>> Hey, that's a nice solution. (The site was in svn to begin with,
+>> but it's in git now.) One advantage of my approach in this particular
+>> case: server (1) doesn't have `git` installed, but does have `rsync`,
+>> so (1)'s environment can remain completely untweaked other than the
+>> SSH arrangement. I kind of like that all the sysadmin effort is
+>> contained on one host.
+>>
+>> This plugin is definitely still useful for projects not able to use
+>> a DVCS (of which I've got at least one other), and possibly for
+>> other uses not yet imagined. ;-) --[[schmonz]]
index a28f79e2069a066e2818e07ce9ab7b68a19d0e5f..77c41a95594baa84c9314c2168994f710f3fc0d4 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=sar author="[[VictorMoral]]"]]
-[[tag type/chrome type/slow ]]
+[[!template id=plugin name=sar author="[[VictorMoral]]"]]
+[[!tag type/chrome type/slow ]]
 
 The `sar` plugin is useful to make global or local search and replace operations
 using common or specific terms.
@@ -14,19 +14,19 @@ The global dictionary page is like this:
 
     ## Sites and projects
 
-    - [[sar search="ikiwiki" first="[IkiWiki](http://ikiwiki.info)" next="_IkiWiki_"]]
-    - [[sar search="debian" first="[Debian](http://debian.org)" next="_Debian_"]]
-    - [[sar search="perl" first="[Perl](http://perl.org)" next="_Perl_"]]
-    - [[sar search="linux" replace="GNU/Linux"]]
+    - [[!sar search="ikiwiki" first="[IkiWiki](http://ikiwiki.info)" next="_IkiWiki_"]]
+    - [[!sar search="debian" first="[Debian](http://debian.org)" next="_Debian_"]]
+    - [[!sar search="perl" first="[Perl](http://perl.org)" next="_Perl_"]]
+    - [[!sar search="linux" replace="GNU/Linux"]]
    
     ## Persons
-    - [[sar search="joey" first="[Joey Hess](http://ikiwiki.info/users/joey]]" next="_Joey_" ]]
-    - [[sar search="angel" first="[Angel](http://triptico.com)" next="Angel"]]
+    - [[!sar search="joey" first="[Joey Hess](http://ikiwiki.info/users/joey]]" next="_Joey_" ]]
+    - [[!sar search="angel" first="[Angel](http://triptico.com)" next="Angel"]]
 
     ## Technical terms
 
-    - [[sar search="smtp" first="\[[wp SMTP]]" next="‘SMTP‘"]]
-    - [[sar search="pop3" first="\[[wp POP3]]" next="’POP3’"]]
+    - [[!sar search="smtp" first="\[[!wp SMTP]]" next="‘SMTP‘"]]
+    - [[!sar search="pop3" first="\[[!wp POP3]]" next="’POP3’"]]
 
 The search expressions must be surrounded by double dashes in a source ikiwiki
 page, like this:
@@ -70,11 +70,11 @@ value is `*`, but a recommended value is `link(tag/sar)`.
 
 In a ikiwiki source page we can write this
 
-    \[[sar search=debian replace="__Debian__"]]
+    \[[!sar search=debian replace="__Debian__"]]
 
 for define a global replace for the term `--debian--` or
 
-    \[[sar search=ibm first=’[IBM](http://www.ibm.com)’
+    \[[!sar search=ibm first=’[IBM](http://www.ibm.com)’
             next="_IBM_"]]
 
 to define a replace for the first match of the string `--ibm--` and a different
index 06c9bbc29d8b356762d3c5c32c16196ac37ef7ac..9b09657bf0540aabc5ab4e5c8e3fcd575cde3a4a 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=siterel2pagerel author="[[PaulWise]]"]]
+[[!template id=plugin name=siterel2pagerel author="[[PaulWise]]"]]
 
 This is a simple plugin to convert all site-relative links to page-relative
 links (converts /foo into ../../../foo or similar). It works as a
@@ -13,11 +13,11 @@ other format that produces html. The code is available here:
        use strict;
        use IkiWiki 2.00;
 
-       sub import { #{{{
+       sub import {
                hook(type => "sanitize", id => "siterel2pagerel", call => \&siterel2pagerel);
-       } # }}}
+       }
 
-       sub siterel2pagerel (@) { #{{{
+       sub siterel2pagerel (@) {
                my %params=@_;
                my $baseurl=IkiWiki::baseurl($params{page});
                my $content=$params{content};
@@ -25,6 +25,6 @@ other format that produces html. The code is available here:
                $content=~s/(<img(?:\s+(?:class|id|width|height)\s*="?\w+"?)*)\s+src=\s*"\/([^"]*)"/$1 src="$baseurl$2"/mig;
                # FIXME: do <script and everything else that can have URLs in it
                return $content;
-       } # }}}
+       }
 
        1
index 0066c9b9fa5cbca92c17cf255eb5a8e5eae3ccb7..07ac2086f4cfeca1bf27c810fd19d933ac76d716 100644 (file)
@@ -4,17 +4,27 @@ I noticed several places in the wiki talking about similar ideas, so I decided t
 
 I have implemented a simple wrapper around
  [source-highlight](http://www.gnu.org/software/src-highlite/).  You can find the latest version in 
-[git](http://pivot.cs.unb.ca/git?p=ikiperl.git;a=blob_plain;f=IkiWiki/Plugin/sourcehighlight.pm;hb=HEAD).
+[git](http://pivot.cs.unb.ca/git?p=ikiplugins.git;a=blob_plain;f=IkiWiki/Plugin/sourcehighlight.pm;hb=HEAD).
 You must specify `highlight_lang=>"foo,bar"` in your setup file.
 where foo and bar are the (source-supported) languages you want to
 highlight
 ### Issues
 
-- I would like to have a link to the raw source; using will_render() and then copying the file should work. 
+- I would like to have a link to the raw source; using will_render() and then copying the file should work.
 
-- the common case of foo.c and foo.h breaks
-because they both generate page working/dir/foo. 
-It looks to me like ikiwiki is hardcoded to strip the extension in `pagename()` (IkiWiki.pm).
-This problem with sourcehighlight needs to be fixed before it is very useful.
+> You might also like to look at the [[todo/source_link]] todo. -- [[Will]]
 
-[[DavidBremner]]
+- Is there a way to configure the colors used by source-highlight (other than editing the globally installed "default.style" file)? It would help if I could pass the command arbitrary command-line arguments; then I could configure which config file it's supposed to use. For instance, I'm not a fan of hard-coding the colors into the HTML output. IMHO, css-style formatting should be preferred. All that can be set via the command line ... --Peter
+
+> I don't really have time right now, but it should be easy to add, if you look at how src-lang is handled.  Patches are welcome :-) --[[DavidBremner]]
+
+Note that [[Will]] wrote a plugin that uses source-highlight also. It's
+available
+[[here|todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion]].
+--[[Joey]]
+
+To be honest, [[Will]]'s version of this looks more polished.  I will try his 
+plugin and see if it can just replace mine. --[[DavidBremner]]
+
+
+*Updated* Now uses keepextension so multiple extensions should be OK
index 3ea3b8e3201b24cc42a02f835039efd77b23c7b2..5ca6311f9d63c6151de5f6a17c103a827f608e2e 100644 (file)
@@ -1,7 +1,7 @@
-[[template id=plugin name=syntax author="[[VictorMoral]]"]]
-[[tag type/chrome type/slow]]
+[[!template id=plugin name=syntax author="[[VictorMoral]]"]]
+[[!tag type/chrome type/slow]]
 
-The `syntax` plugin adds support to ikiwiki for syntax highlighting through the *vim* editor and its perl interface [[cpan Text::VimColor]].  It depends on a functional vim installation.
+The `syntax` plugin adds support to ikiwiki for syntax highlighting through the *vim* editor and its perl interface [[!cpan Text::VimColor]].  It depends on a functional vim installation.
 
 The plugin inserts a fragment of HTML with special marks from a file or a string text. It accepts the following parameters:
 
@@ -17,7 +17,7 @@ In the case of file parameter, `syntax` will build a html link for direct downlo
 
 Example:
 
-       \[[syntax type="perl" text="""  
+       \[[!syntax type="perl" text="""  
        #!/usr/bin/perl
 
        my $a = "World";
@@ -26,7 +26,7 @@ Example:
 
 or 
 
-       \[[syntax file="/examples/hello.pl" description="My first perl program"]]
+       \[[!syntax file="/examples/hello.pl" description="My first perl program"]]
 
 This plugin create the following CSS styles:
 
index e5a549c0526acc1c3f4f9ac1366511864e77602e..bee18d96f108d88a5bd34afd080a654ca8547b53 100644 (file)
@@ -4,11 +4,11 @@ I have written a simple wrapper around tex4ht to convert tex files to html. This
 my old tex4ht based home page, it seems to work OK. 
 
 The current version is available from 
-[git](http://pivot.cs.unb.ca/git?p=ikiperl.git;a=blob_plain;f=IkiWiki/Plugin/tex4ht.pm;hb=HEAD)
+[git](http://pivot.cs.unb.ca/git?p=ikiplugins.git;a=blob_plain;f=IkiWiki/Plugin/tex4ht.pm;hb=HEAD)
 
 ### Other related ideas/plugins:
 
-- [[todo/latex]] There is work in progress at converting snippets of latex.  No idea how the hybrid approach of tex4ht (part fonts, part bitmaps) compares to the [[todo/latex]] approach.
+- [[todo/latex]] There is work in progress at converting snippets of latex.  No idea how the hybrid approach of tex4ht (part font, part bitmaps) compares to the [[todo/latex]] approach.
 
 - pandoc can also convert latex to html or markdown. It is much faster than tex4ht; on the other hand, the rendering quality is not quite as good, and pandoc does not understand user defined TeX macros.
 
index c33a370ea390cfdbbede05e6fd06ebda154362b8..595bd27aa7a270732a38142ede24c7e72dfeb566 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=texinfo author="[[tschwinge]]"]]
+[[!template id=plugin name=texinfo author="[[tschwinge]]"]]
 
 [[I|tschwinge]] started writing a plugin to render
 [GNU Texinfo](http://www.gnu.org/software/texinfo/)
diff --git a/doc/plugins/contrib/trail.mdwn b/doc/plugins/contrib/trail.mdwn
new file mode 100644 (file)
index 0000000..337e5d4
--- /dev/null
@@ -0,0 +1,66 @@
+[[!tag type/chrome patch]]
+[[!template id=gitbranch branch=smcv/trail author="[[smcv]]"]]
+
+Available from [[smcv]]'s git repository, in the `trail` branch. This
+plugin aims to solve [[todo/wikitrails]] in a simpler way.
+
+Joey: what do you think of this plugin? If you like the general approach
+and are likely to include it in ikiwiki, I'll try to modify
+[[plugins/contrib/album]] to be based on it, rather than partially
+reinventing it.
+
+Bugs:
+
+* \[[!inline pages="..." trail=yes]] currently tries to work out
+  what pages are in the trail, and their order, at scan time. That
+  won't work, because matching a pagespec at scan time is
+  unreliable - pages we want might not have been scanned yet! I
+  haven't worked out a solution for this. I think
+  \[[!inline pagenames="..." trail=yes]] would be safe, though.
+
+----
+
+[[!template id=plugin name=trail author="[[Simon_McVittie|smcv]]"]]
+
+It's sometimes useful to have "trails" of pages in a wiki, as a guided
+tour, sequence of chapters etc. In this plugin, a trail is represented
+by a page, and the pages in the trail are indicated by specially marked
+links within that page.
+
+If using the default `page.tmpl`, each page automatically displays the
+trails that it's a member of (if any), with links to the trail and to
+the next and previous members.
+
+The `traillink` [[ikiwiki/directive]] is used to record which pages
+are in a trail, and simultaneously link to them. Alternatively, the
+[[ikiwiki/directive/inline]] directive can be used with `trail=yes`
+to record the inlined pages as part of the trail, in the order in
+which they are inlined.
+
+## Directives
+
+(These will go to the appropriate pages in [[ikiwiki/directive]] if this
+plugin is included in ikiwiki.)
+
+### traillink
+
+The `traillink` directive is supplied by the [[!iki plugins/contrib/trail desc=trail]]
+plugin. This directive appears on the page representing a trail. It acts
+as a visible [[ikiwiki/WikiLink]], but also records the linked page as
+a member of the trail.
+
+Various syntaxes can be used:
+
+    \[[!traillink Badgers]]
+    \[[!traillink How_to_find_mushrooms_using_badgers|badgers]]
+    \[[!traillink badgers text="How to find mushrooms using badgers"]]
+
+### trailoptions
+
+The `trailoptions` directive is supplied by the [[!iki plugins/contrib/trail desc=trail]]
+plugin. This directive appears on the page representing a trail, and
+produces no output.
+
+Currently, the only option supported is `[[!trailoptions circular=yes]]`,
+which adds links between the first and last pages, turning the trail into
+a circle.
diff --git a/doc/plugins/contrib/unixauth.mdwn b/doc/plugins/contrib/unixauth.mdwn
new file mode 100644 (file)
index 0000000..6108ebf
--- /dev/null
@@ -0,0 +1,221 @@
+[[!template id=plugin name=unixauth core=0 author="[[schmonz]]"]]
+[[!tag type/auth]]
+
+This plugin authenticates users against the Unix user database. It presents a similar UI to [[plugins/passwordauth]], but simpler, as there's no need to be able to register or change one's password.
+
+To authenticate, either [checkpassword](http://cr.yp.to/checkpwd.html) or [pwauth](http://www.unixpapa.com/pwauth/) must be installed and configured. `checkpassword` is strongly preferred. If your web server runs as an unprivileged user -- as it darn well should! -- then `checkpassword` needs to be setuid root. (Or your ikiwiki CGI wrapper, I guess, but don't do that.) Other checkpassword implementations are available, notably [checkpassword-pam](http://checkpasswd-pam.sourceforge.net/).
+
+Config variables that affect the behavior of `unixauth`:
+
+* `unixauth_type`: defaults to unset, can be "checkpassword" or "pwauth"
+* `unixauth_command`: defaults to unset, should contain the full path and any arguments
+* `unixauth_requiressl`: defaults to 1, can be 0
+* `sslcookie`: needs to be 1 if `unixauth_requiressl` is 1 (perhaps this should be done automatically?)
+
+__Security__: [As with passwordauth](/security/#index14h2), be wary of sending usernames and passwords in cleartext. Unlike passwordauth, sniffing `unixauth` credentials can get an attacker much further than mere wiki access. Therefore, this plugin defaults to not even _displaying_ the login form fields unless we're running under SSL. Nobody should be able to do anything remotely dumb until the admin has done at least a little thinking. After that, dumb things are always possible. ;-)
+
+`unixauth` needs the `HTTPS` environment variable, available in ikiwiki 2.67 or later (fixed in #[502047](http://bugs.debian.org/502047)), without which it fails closed.
+
+The plugin has not been tested with newer versions of ikiwiki. [[schmonz]] hopes to have time to polish this plugin soon.
+
+[[!toggle id="code" text="unixauth.pm"]]
+
+[[!toggleable id="code" text="""
+
+    #!/usr/bin/perl
+    # Ikiwiki unixauth authentication.
+    package IkiWiki::Plugin::unixauth;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 2.00;
+    
+    sub import {
+        hook(type => "getsetup", id => "unixauth", call => \&getsetup);
+            hook(type => "formbuilder_setup", id => "unixauth",
+                call => \&formbuilder_setup);
+            hook(type => "formbuilder", id => "unixauth",
+                call => \&formbuilder);
+        hook(type => "sessioncgi", id => "unixauth", call => \&sessioncgi);
+    }
+    
+    sub getsetup () {
+        return
+        unixauth_type => {
+                type => "string",
+                example => "checkpassword",
+                description => "type of authenticator; can be 'checkpassword' or 'pwauth'",
+                safe => 0,
+                rebuild => 1,
+        },
+        unixauth_command => {
+                type => "string",
+                example => "/path/to/checkpassword",
+                description => "full path and any arguments",
+                safe => 0,
+                rebuild => 1,
+        },
+        unixauth_requiressl => {
+                type => "boolean",
+                example => "1",
+                description => "require SSL? strongly recommended",
+                safe => 0,
+                rebuild => 1,
+        },
+        plugin => {
+                description => "Unix user authentication",
+                safe => 0,
+                rebuild => 1,
+        },
+    }
+    
+    # Checks if a string matches a user's password, and returns true or false.
+    sub checkpassword ($$;$) {
+        my $user=shift;
+        my $password=shift;
+        my $field=shift || "password";
+    
+        # It's very important that the user not be allowed to log in with
+        # an empty password!
+        if (! length $password) {
+                return 0;
+        }
+    
+        my $ret=0;
+        if (! exists $config{unixauth_type}) {
+                # admin needs to carefully think over his configuration
+                return 0;
+        }
+        elsif ($config{unixauth_type} eq "checkpassword") {
+                open UNIXAUTH, "|$config{unixauth_command} true 3<&0" or die("Could not run $config{unixauth_type}");
+                print UNIXAUTH "$user\0$password\0Y123456\0";
+                close UNIXAUTH;
+                $ret=!($?>>8);
+        }
+        elsif ($config{unixauth_type} eq "pwauth") {
+                open UNIXAUTH, "|$config{unixauth_command}" or die("Could not run $config{unixauth_type}");
+                print UNIXAUTH "$user\n$password\n";
+                close UNIXAUTH;
+                $ret=!($?>>8);
+        }
+        else {
+                # no such authentication type
+                return 0;
+        }
+    
+        if ($ret) {
+            my $userinfo=IkiWiki::userinfo_retrieve();
+            if (! length $user || ! defined $userinfo ||
+                ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) {
+                    IkiWiki::userinfo_setall($user, {
+                        'email' => '',
+                        'regdate' => time,
+                    });
+            }
+        }
+    
+        return $ret;
+    }
+    
+    sub formbuilder_setup (@) {
+        my %params=@_;
+    
+        my $form=$params{form};
+        my $session=$params{session};
+        my $cgi=$params{cgi};
+    
+        # if not under SSL, die before even showing a login form,
+        # unless the admin explicitly says it's fine
+        if (! exists $config{unixauth_requiressl}) {
+                $config{unixauth_requiressl} = 1;
+        }
+        if ($config{unixauth_requiressl}) {
+            if ((! $config{sslcookie}) || (! exists $ENV{'HTTPS'})) {
+                die("SSL required to login. Contact your administrator.<br>");
+            }
+        }
+    
+        if ($form->title eq "signin") {
+                $form->field(name => "name", required => 0);
+                $form->field(name => "password", type => "password", required => 0);
+                
+                if ($form->submitted) {
+                        my $submittype=$form->submitted;
+                        # Set required fields based on how form was submitted.
+                        my %required=(
+                                "Login" => [qw(name password)],
+                        );
+                        foreach my $opt (@{$required{$submittype}}) {
+                                $form->field(name => $opt, required => 1);
+                        }
+        
+                        # Validate password against name for Login.
+                        if ($submittype eq "Login") {
+                                $form->field(
+                                        name => "password",
+                                        validate => sub {
+                                                checkpassword($form->field("name"), shift);
+                                        },
+                                );
+                        }
+                        
+                        # XXX is this reachable? looks like no
+                        elsif ($submittype eq "Login") {
+                                $form->field( 
+                                        name => "name",
+                                        validate => sub {
+                                                my $name=shift;
+                                                length $name &&
+                                                IkiWiki::userinfo_get($name, "regdate");
+                                        },
+                                );
+                        }
+                }
+                else {
+                        # First time settings.
+                        $form->field(name => "name");
+                        if ($session->param("name")) {
+                                $form->field(name => "name", value => $session->param("name"));
+                        }
+                }
+        }
+        elsif ($form->title eq "preferences") {
+                $form->field(name => "name", disabled => 1, 
+                        value => $session->param("name"), force => 1,
+                        fieldset => "login");
+                $form->field(name => "password", disabled => 1, type => "password",
+                        fieldset => "login"),
+        }
+    }
+    
+    sub formbuilder (@) {
+        my %params=@_;
+    
+        my $form=$params{form};
+        my $session=$params{session};
+        my $cgi=$params{cgi};
+        my $buttons=$params{buttons};
+    
+        if ($form->title eq "signin") {
+                if ($form->submitted && $form->validate) {
+                        if ($form->submitted eq 'Login') {
+                                $session->param("name", $form->field("name"));
+                                IkiWiki::cgi_postsignin($cgi, $session);
+                        }
+                }
+        }
+        elsif ($form->title eq "preferences") {
+                if ($form->submitted eq "Save Preferences" && $form->validate) {
+                        my $user_name=$form->field('name');
+                }
+        }
+    }
+    
+    sub sessioncgi ($$) {
+        my $q=shift;
+        my $session=shift;
+    }
+    
+    1
+
+"""]]
diff --git a/doc/plugins/contrib/unixauth/discussion.mdwn b/doc/plugins/contrib/unixauth/discussion.mdwn
new file mode 100644 (file)
index 0000000..2326498
--- /dev/null
@@ -0,0 +1,38 @@
+The security of this plugin scares me. As noted in the plugin
+documentation, you basically have to use it with SSL, since snooping on the
+login password doesn't give you an essentially useless account -- it gives
+you an actual account on the machine!
+
+Also, apparently pwauth defers *all* auth attempts if one fails, and it
+does this by using a lock file, and sleeping after a failed auth attempt.
+Which is needed to avoid brute-forcing, since this is a significant
+password.. but how will that interact with ikiwiki? Well, ikiwiki _also_
+uses a lock file. So, at a minimum, someone can not only try to brute-force
+the pwauth password, but the ikiwiki processes that stack up due to that
+will also keep ikiwiki's lock held. Which basically DOSes the wiki for
+everyone else; noone else can try to log in, or log out, or edit a page,
+all of which require taking the lock.
+
+So I don't think I'll be accepting this plugin into ikiwiki itself..
+--[[Joey]]
+
+Thanks for the comments. That's definitely an undesirable interaction between pwauth and ikiwiki; in my current application it wouldn't be a serious problem, but I'd like this plugin to be general-purpose and safe enough for inclusion in ikiwiki. It's the system-users-are-wiki-users idea I'm married to here, not pwauth itself; can you suggest another approach I might take?
+-- [[schmonz]]
+
+> Have you considered using [[plugins/httpauth]] and then the appropriate apache module?  There are apache modules like [mod_authnz_external](http://unixpapa.com/mod_auth_external.html) that might help.  The advantage of these solutions is that they usually make the security implications explicit.  -- Will
+
+Actually, yes. That's how I made sure I had pwauth working to begin with. I'm partial to the form-based approach because I'm not aware of any way to reliably "log out" browsers from HTTP authentication. If that *is* reliably possible, then I worked way too hard for no reason. ;-)
+-- [[schmonz]]
+
+I've added support for [checkpassword](http://cr.yp.to/checkpwd/interface.html), since those generally don't have any rate-limiting cleverness to interfere with ikiwiki's, and made a few other changes. Please check out the plugin docs again and let me know if this is closer to being acceptable.
+-- [[schmonz]]
+
+> I actually think that the rate limiting is a good thing. After all,
+> ikiwiki doesn't do its own login rate limiting. Just need to find a way
+> to disentangle the two locks. --[[Joey]]
+
+>> Ah, ok, I misunderstood your comment. I'll see what I can figure out. --[[schmonz]]
+
+>>> My time's been limited for this, but I just saw [[todo/avoid_thrashing]]. How does that interact with pwauth or checkpassword? --[[schmonz]]
+
+>>>> The DOS still happens, it just uses less memory. --[[Joey]]
diff --git a/doc/plugins/contrib/unixrelpagespec.mdwn b/doc/plugins/contrib/unixrelpagespec.mdwn
new file mode 100644 (file)
index 0000000..a35f76c
--- /dev/null
@@ -0,0 +1,42 @@
+[[!template id=plugin name=unixrelpagespec core=0 author="[[Jogo]]"]]
+
+I don't understand why `./*` correspond to siblings and not subpages.
+This is probably only meaningfull with [[plugins/autoindex]] turned on.
+
+Here is a small plugin wich follow usual Unix convention :
+
+- `./*` expand to subpages
+- `../*` expand to siblings
+
+---
+    #!/usr/bin/perl
+    # UnixRelPageSpec plugin.
+    # by Joseph Boudou <jogo at matabio dot net>
+    
+    package IkiWiki::Plugin::unixrelpagespec;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 3.00;
+    
+    sub import {
+        inject(
+            name => 'IkiWiki::PageSpec::derel',
+            call => \&unix_derel
+        );
+    }
+    
+    sub unix_derel ($$) {
+        my $path = shift;
+        my $from = shift;
+    
+        if ($path =~ m!^\.{1,2}/!) {
+            $from =~ s#/?[^/]+$## if (defined $from and $path =~ m/^\.{2}/);
+            $path =~ s#^\.{1,2}/##;
+            $path = "$from/$path" if length $from;
+        }
+    
+        return $path;
+    }
+    
+    1;
index b2496adad6b6d57cb7cd7ab73da16601699d9483..6961e8d1d2e7755898c893b0d7032d17fa697f94 100644 (file)
@@ -1,9 +1,9 @@
-[[template id=plugin name=creole author="BerndZeimetz"]]
-[[tag type/format]]
+[[!template id=plugin name=creole author="BerndZeimetz"]]
+[[!tag type/format]]
 
 This plugin allows ikiwiki to process pages written in
 [WikiCreole](http://www.wikicreole.org/) format.
-To use it, you need to have the [[cpan Text::WikiCreole]] perl
+To use it, you need to have the [[!cpan Text::WikiCreole]] perl
 module installed, enable the plugin, then files with the extention `.creole`
 will be processed as creole.
 
@@ -12,5 +12,11 @@ wiki markup formats, so should be fairly easy to guess at. There is also a
 [CheatSheet](http://www.wikicreole.org/wiki/CheatSheet).
 
 Links are standard [[WikiLinks|ikiwiki/WikiLink]]. Links and
-[[PreProcessorDirectives]] inside `{{{ }}}` blocks are still expanded,
-since this happens before the creole format is processed.
+[[directives|ikiwiki/directive]] inside `{{{ }}}` blocks are still expanded,
+since this happens before the creole format is processed. (You need to escape
+them manually, via \\\[[directives]], the ~ escaping of creole doesn't work on
+this.)
+
+The standard ikiwiki [[WikiLinks|ikiwiki/WikiLink]] is almost the same as Creole link, except that creole uses \[[pagename|description]] while ikiwiki uses \[[description|pagename]].
+
+
diff --git a/doc/plugins/creole/discussion.mdwn b/doc/plugins/creole/discussion.mdwn
new file mode 100644 (file)
index 0000000..38ee2bd
--- /dev/null
@@ -0,0 +1,15 @@
+I've installed Text::WikiCreole 0.05 and enabled the plugin, but I get an error when rebuilding the wiki: `Undefined subroutine &IkiWiki::Plugin::creole::creole_custombarelinks called at /usr/pkg-20080723/lib/perl5/vendor_perl/5.8.0/IkiWiki/Plugin/creole.pm line 23`. Is there a newer Text::WikiCreole I'm not finding online?
+-- [[schmonz]]
+
+> There's a patch in the debian package of libtext-wikicreole-perl that
+> adds that option. I'm not sure what the status of it being released
+> upstream is, though IIRC I was assured it would not be a problem.
+> --[[Joey]]
+
+>> I've added the patch to pkgsrc as well. Thanks. --[[schmonz]]
+
+>> Currently the creole plugin is included in ikiwiki but the ikiwiki deb (3.0.3) doesn't suggests libtext-wikicreole-perl.  Why? --[[weakish]]
+
+>>> forgot, done now --[[Joey]] 
+
+I'm moving over a really stinkingly old UseMod and creole seems the nearest match. I've worked out that Bare /Subpage links need to become \[\[Subpage\]\], and Top/Sub links need to be \[\[Top/Sub\]\] (or \[\[Top/Sub|Top/Sub\]\], to display in exactly the same way), but I'm stuck on generic hyperlinks. The creole cheat sheet says I should be able to do \[\[http://url.path/foo|LinkText\]\], but that comes out as a link to create the "linktext" page, and Markdown-style \[Link Text\](http://url.path/foo) just gets rendered as is. Any suggestions? --[[schmonz]]
diff --git a/doc/plugins/cutpaste.mdwn b/doc/plugins/cutpaste.mdwn
new file mode 100644 (file)
index 0000000..f74f8a2
--- /dev/null
@@ -0,0 +1,7 @@
+[[!template id=plugin name=cutpaste author="[[Enrico]]"]]
+[[!tag type/chrome]]
+
+This plugin provides the [[ikiwiki/directive/cut]],
+[[ikiwiki/directive/copy]] and [[ikiwiki/directive/paste]]
+[[directives|ikiwiki/directive]].
+With these directives you can store and recall pieces of text in a page.
index b2c6df05d9f18e127ed449cff34bdaf0136e9856..741606a6e71d184df8e2b5f1b8e70a56f7900848 100644 (file)
@@ -1,8 +1,9 @@
-[[template id=plugin name=ddate author="[[Joey]]"]]
-[[tag type/fun]]
+[[!template id=plugin name=ddate author="[[Joey]]"]]
+[[!tag type/fun]]
+[[!tag type/date]]
 
 Enables use of Discordian dates. `--timeformat` can be used to change
 the date format; see `ddate(1)`.
 
-This plugin requires the [[cpan DateTime]] and 
-[[cpan DateTime::Calendar::Discordian]] perl modules.
+This plugin requires the [[!cpan DateTime]] and 
+[[!cpan DateTime::Calendar::Discordian]] perl modules.
index 34aaa22cd982f75c098f74c5a03a03866f7a68d1..854307a98ad971b7659adb271871a0dcb192e0ca 100644 (file)
@@ -20,4 +20,17 @@ It would be nice if the page gave a brief synopsis for each plugin.  For example
 >Allows embedding of graphviz graphs.  
 >Posted Mon, 09 Apr 2007 05:09:04 -0400   
 
---MichaelRasmussen
\ No newline at end of file
+--MichaelRasmussen
+
+Any objections to listing plugins alphabetically rather than by creation date?  (i.e. change the inline to have sort="title".)
+
+-- Will
+
+> Well, it's been done by Josh, but I do wonder if there wasn't value to
+> being able to look at the top of the page for new plugins? --[[Joey]]
+
+>> I agree, which is why I brought it up here rather than just changing it.
+>> On balance I think the alphabetical list is better.  You could have a 
+>> "recently changed" list with the 10 most recently changed plugins
+>> at the top.  That would allow what you suggested, but still allow
+>> the main list to be alphabetical. -- [[Will]]
index 61c36a9d67f80b067d2bb71a7f8cba145d41a634..8d9daa0ff41e6c92078958bd51595159c224e076 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=editdiff author="[[JeremieKoenig]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=editdiff author="[[JeremieKoenig]]"]]
+[[!tag type/web]]
 
 This plugin adds a "Diff" button when a page is being edited.
 When clicked, a diff between the stored page and provided content
diff --git a/doc/plugins/editdiff/discussion.mdwn b/doc/plugins/editdiff/discussion.mdwn
new file mode 100644 (file)
index 0000000..dbb02ae
--- /dev/null
@@ -0,0 +1,5 @@
+I've enabled the plugin on an SVN-backed wiki, but am not seeing the Diff button when editing. (I do see the Rename and Remove buttons from having enabled those plugins.) Any ideas why it wouldn't be showing up? --[[schmonz]]
+
+> It was broken, I've fixed it. --[[Joey]]
+
+>> Awesome, thanks! --[[schmonz]]
diff --git a/doc/plugins/editpage.mdwn b/doc/plugins/editpage.mdwn
new file mode 100644 (file)
index 0000000..b830e51
--- /dev/null
@@ -0,0 +1,5 @@
+[[!template id=plugin name=editpage core=1 author="[[Joey]]"]]
+
+This plugin allows editing wiki pages in the web interface. It's enabled by
+default if [[cgi]] is enabled; disable it if you want cgi for other things
+while not allowing page edits.
index 8140b4f4195fc6d118b89b1c33c6280a29e1eaac..85dfdfc2d23aa5ecb6ea57014a57cdbca8e99d9a 100644 (file)
@@ -1,33 +1,6 @@
-[[template id=plugin name=edittemplate author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=edittemplate author="[[Joey]]"]]
+[[!tag type/web]]
 
-This plugin allows registering template pages, that provide default
-content for new pages created using the web frontend. To register a
-template, insert a [[Preprocessor_Directive|/ikiwiki/preprocessordirective]] on some other page.
-
-       \[[!edittemplate template="bugtemplate" match="bugs/*"]]
-
-In the above example, the page named "bugtemplate" is registered as a
-template to be used when any page named "bugs/*" is created.
-
-Often the template page contains a simple skeleton for a particular type of
-page. For the bug report pages in the above example, it might look
-something like:
-
-       Package: 
-       Version: 
-       Reproducible: y/n
-       Details:
-
-The template page can also contain [[cpan HTML::Template]] directives,
-similar to other ikiwiki [[templates]]. Currently only one variable is
-set: `<TMPL_VAR name>` is replaced with the name of the page being
-created.
-
-----
-
-It's generally not a good idea to put the `edittemplate` directive in
-the template page itself, since the directive would then be included as
-part of the template on new pages, which would then in turn be registered
-as templates. If multiple pages are registered as templates for a new page,
-an arbitrary one is chosen, so that could get confusing.
+This plugin provides the [[ikiwiki/directive/edittemplate]] [[ikiwiki/directive]].
+This directive allows registering template pages, that provide default
+content for new pages created using the web frontend.
index ba327da8d6d9e0f217bb51b6ff122c8790209758..85592cb722ca1bf2f185e4b64989736ae920811f 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=embed author="[[Joey]]"]]
-[[tag type/html]]
+[[!template id=plugin name=embed author="[[Joey]]"]]
+[[!tag type/html]]
 
 This plugin allows embedding content from external sites on 
 wiki pages.
@@ -13,6 +13,14 @@ In the examples below, the parts of the html that you can change are denoted
 with "XXX"; everything else must appear exactly as shown to be accepted by the
 plugin.
 
+**This plugin is deprecated.** Rather than relying on these complex lists
+of safe content, which constantly fall out of date, you're recommended to
+configure the [[htmlscrubber]] to not scrub some pages, which only trusted
+users can edit. Then you can embed anything from anywhere on those pages.
+See [[tips/embedding_content]] for details and examples.
+This plugin's lists of safe embedded content will not be maintained, and 
+the plugin will be removed in a future  release.
+
 ## google maps
 
 Use html like this to embed a map:
index 52dbf6a2f9ebfc08598e44a33c92074f994ec40a..7941f8a6c1d1772d29ae1e10cd6f8df41578346e 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=favicon author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=favicon author="[[Joey]]"]]
+[[!tag type/chrome]]
 
 If this plugin is enabled, then an icon link is added to pages, for web
 browsers to display. The icon is currently hardcoded to be a favicon.ico,
diff --git a/doc/plugins/filecheck.mdwn b/doc/plugins/filecheck.mdwn
new file mode 100644 (file)
index 0000000..f4563d5
--- /dev/null
@@ -0,0 +1,16 @@
+[[!template id=plugin name=filecheck core=0 author="[[Joey]]"]]
+[[!tag type/useful]]
+
+This plugin enhances the regular [[ikiwiki/PageSpec]] syntax with
+some additional tests, for things like file size, mime type, and virus
+status. These tests are mostly useful for the [[attachment]] plugin, and
+are documented [[here|ikiwiki/pagespec/attachment]].
+
+This plugin will use the [[!cpan File::MimeInfo::Magic]] perl module, if
+available, for mimetype checking.
+
+The `virusfree` [[PageSpec|ikiwiki/pagespec/attachment]] requires that
+ikiwiki be configured with a virus scanner program via the `virus_checker`
+option in the setup file. If using `clamav`, with `clamd`, set it to
+"clamdscan -". Or to use clamav without the `clamd` daemon, you
+could set it to "clamscan -".
diff --git a/doc/plugins/filecheck/discussion.mdwn b/doc/plugins/filecheck/discussion.mdwn
new file mode 100644 (file)
index 0000000..f91950b
--- /dev/null
@@ -0,0 +1,17 @@
+First, thanks again for making this plugin.
+
+I don't know if this is a problem for [[plugins/attachment]], but there seems to
+be no way to detect text/plain using File::MimeInfo::Magic::magic().
+There is a heuristic ::default that decides between text/plain and application/octet-stream.  
+
+Would you be receptive to a patch that e.g. called File::MimeInfo::Magic::default()
+if ::magic() returns undef?  --[[DavidBremner]]
+
+> Yes, that looks to be ok. --[[Joey]]
+
+>> OK, here is such a patch. One modification of previous behaviour is that 
+>> that if default returns undef, this is returned. As far as I understand
+>> the code/doc for File::MimeInfo, under is used only as an error return
+>> for ::default
+
+>>> Applied
diff --git a/doc/plugins/format.mdwn b/doc/plugins/format.mdwn
new file mode 100644 (file)
index 0000000..91e707f
--- /dev/null
@@ -0,0 +1,9 @@
+[[!template id=plugin name=format core=0 author="[[Joey]]"]]
+[[!tag type/format]]
+
+This plugin allows mixing different page formats together, by embedding
+text formatted one way inside a page formatted another way. This is done
+using the [[ikiwiki/directive/format]] [[ikiwiki/directive]].
+
+For example, it could be used to embed an [[otl]] outline inside a page
+that is formatted as [[mdwn]].
diff --git a/doc/plugins/format/discussion.mdwn b/doc/plugins/format/discussion.mdwn
new file mode 100644 (file)
index 0000000..df8448e
--- /dev/null
@@ -0,0 +1,15 @@
+Is there any way to tell if an htmlize hook have been called from a format directive?
+
+I am currently modifying the [[contrib/highlightcode]] plugin by [[sabr]] and I wanted to have a different behavior depending on the fact that the htmlize hook is called from a format directive or not. For instance, this could disable the raw copy of the highlighted code. Since I have enabled the keepextension option, I tried to rely on the page extension to decide whenever I have to create the raw file or not but this does not seems a reliable approach.
+
+One possible solution is to add an optional parameter to the htmlize hook (and thus to htmlize function in IkiWiki.pm) which could tell if this is the format directive that called the function but I am not sure that is a good way to do this.
+
+> It's (probably) not just the format directive that has a potential problem here.
+> Imagine a syntax highlighted source code file that contains some other
+> directive, such as table or meta. Such a directive calls `htmlize` on the
+> parameters passed to it.
+> 
+> There is one way to detect this ATM. If `%IkiWiki::preprocessing` has
+> anything in it, then ikiwiki is in the middle of handling a preprocessing
+> directive. So you could check that. It's getting into internals, so not
+> ideal.. --[[Joey]]
index b855c18f3a5f0414f3c5b07b089f2f25fc5fd74c..9966f456da05b35a00fba722b338d8eb8edfffdb 100644 (file)
@@ -1,15 +1,13 @@
-[[template id=plugin name=fortune author="[[Joey]]"]]
-[[tag type/fun]]
+[[!template id=plugin name=fortune author="[[Joey]]"]]
+[[!tag type/fun]]
 
-This just uses the `fortune` program to insert a fortune into the page.
-Usage:
+This plugin implements the [[ikiwiki/directive/fortune]] [[ikiwiki/directive]].
+This directive  uses the `fortune` program to insert a fortune into the page.
 
-       \[[fortune ]]
-
-[[if test="enabled(fortune)" then="""
+[[!if test="enabled(fortune)" then="""
 Here's a fortune for you:
 
 ----
 
-[[fortune ]]
+[[!fortune ]]
 """]]
diff --git a/doc/plugins/getsource.mdwn b/doc/plugins/getsource.mdwn
new file mode 100644 (file)
index 0000000..20040cc
--- /dev/null
@@ -0,0 +1,13 @@
+[[!template id=plugin name=getsource author="[[Will_Uther|Will]]"]]
+
+This plugin adds a "Source" link to the top of each page that uses
+the CGI to display the page's source.
+
+Configuration for this plugin in the setup file:
+
+* `getsource_mimetype => "text/plain; charset=utf-8"`
+
+  Sets the MIME type used when page source is requested. The default is
+  usually appropriate, but you could set this to `application/octet-stream`
+  to encourage browsers to download the source to a file rather than showing
+  it in the browser.
index ca888910d34840815b0cc41dd41566c228a29367..ee1bffcfa8f8e07f0336eff76a0ebc6fd5a0a8ca 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=goodstuff author="[[Joey]]"]]
-[[tag type/bundle]]
+[[!template id=plugin name=goodstuff author="[[Joey]]"]]
+[[!tag type/bundle]]
 
 This plugin enables a bunch of other plugins -- basically all the ones that
 are not too intrusive, work well with little configuration, and are nice to
@@ -12,16 +12,18 @@ Currently included:
 * [[brokenlinks]]
 * [[img]]
 * [[map]]
-* [[meta]]
+* [[more]]
 * [[orphans]]
 * [[pagecount]]
 * [[pagestats]]
+* [[progress]]
 * [[shortcut]]
 * [[smiley]]
 * [[tag]]
+* [[table]]
 * [[template]]
 * [[toc]]
 * [[toggle]]
-* [[otl]]
+* [[repolist]]
 
 New plugins will be added to this bundle from time to time.
diff --git a/doc/plugins/google.mdwn b/doc/plugins/google.mdwn
new file mode 100644 (file)
index 0000000..7c61e63
--- /dev/null
@@ -0,0 +1,12 @@
+[[!template id=plugin name=google author="Peter Simons"]]
+[[!tag type/web]]
+
+This plugin adds a search form to the wiki, using google's site search.
+
+Google is asked to search for pages in the domain specified in the wiki's
+`url` configuration parameter. Results will depend on whether google has
+indexed the site, and how recently. Also, if the same domain has other
+content, outside the wiki's content, it will be searched as well.
+
+The [[search]] plugin offers full text search of only the wiki, but
+requires that a search engine be installed on your site.
diff --git a/doc/plugins/google/discussion.mdwn b/doc/plugins/google/discussion.mdwn
new file mode 100644 (file)
index 0000000..babc919
--- /dev/null
@@ -0,0 +1,6 @@
+This plugin uses the googleform.tmpl
+which produces valid HTML but invalid XHTML.
+This is not very good since the default ikiwiki
+templates produce XHTML instead of HTML.
+
+> Fixed, thanks for the patch! --[[Joey]] 
diff --git a/doc/plugins/googlecalendar.mdwn b/doc/plugins/googlecalendar.mdwn
deleted file mode 100644 (file)
index 6d7429d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[[template id=plugin name=googlecalendar author="[[Joey]]"]]
-[[tag type/special-purpose]]
-
-*Note*: This plugin is deprecated. Please switch to the [[embed]] plugin.
-
-This plugin allows embedding a google calendar iframe in the wiki.
-Normally, if the [[htmlscrubber]] is enabled, such iframes are scrubbed out
-of the wiki content since they're not very safe if created by malicious
-users. But some iframes are legitimate, and safe, if you trust the embedded
-content. This plugin is an example of how to deal with this in ikiwiki.
-
-Example use:
-
-       \[[googlecalendar html="""
-       <iframe src="http://www.google.com/calendar/embed?src=adkrdken8mupngh13jshlbenoc%40group.calendar.google.com&title=OSEL%20Calendar&chrome=NAVIGATION&bgcolor=%2371d873&height=588" style=" border-width:0 " width="480" frameborder="0" height="588"></iframe>
-       """]]
-
-The iframe should be the one provided by google. Note that it's used in a
-way that avoids cross-site scripting attacks, assuming you trust google's
-content.
diff --git a/doc/plugins/goto.mdwn b/doc/plugins/goto.mdwn
new file mode 100644 (file)
index 0000000..9c401c5
--- /dev/null
@@ -0,0 +1,10 @@
+[[!template id=plugin name=goto author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/useful]]
+
+This plugin adds a `do=goto` mode for the IkiWiki CGI script. It's mainly
+for internal use by the [[404]], [[comments]] and [[recentchanges]]
+plugins, which enable it automatically.
+
+With this plugin enabled you can link to `ikiwiki.cgi?do=goto&page=some/where`
+to make a link that will redirect to the page `/some/where` if it exists, or
+offer a link to create it if it doesn't.
index fb669ae219ceed219c5db318b9ce0efc0b24fc23..b89f16b59512092fb9512462bd5bd2e1c09d1a6e 100644 (file)
@@ -1,13 +1,8 @@
-[[template id=plugin name=graphviz author="[[JoshTriplett]]"]]
-[[tag type/chrome type/format]]
+[[!template id=plugin name=graphviz author="[[JoshTriplett]]"]]
+[[!tag type/chrome type/format]]
 
-This plugin allows embedding [graphviz](http://www.graphviz.org/) graphs in a
-page.  Example usage:
-
-       \[[graph src="a -> b -> c; a -> c;"]]
-
-Note that graphs will only show up in previews if your browser has
-[[wikipedia data: URI]] support, or if the same graph already exists on that
+This plugin provides the [[ikiwiki/directive/graph]] [[ikiwiki/directive]].
+This directive allows embedding [graphviz](http://www.graphviz.org/) graphs in a
 page.
 
 Security implications: graphviz does not seem to have any syntax exploitable to
@@ -20,22 +15,11 @@ already do these things with just the core of ikiwiki, but the graphviz plugin
 allows for an amplification attack, since users can send less data to use large
 amounts of processing time and disk usage.
 
-The `graph` directive supports the following parameters:
-
-- `src` - The graphviz source to render.
-- `type` - The type of graph to render: `graph` or `digraph`.  Defaults to
-  `digraph`.
-- `prog` - The graphviz program to render with: `dot`, `neato`, `fdp`, `twopi`,
-  or `circo`.  Defaults to `dot`.
-- `height`, `width` - Limit the size of the graph to a given height and width,
-  in inches. You must specify both to limit the size; otherwise, graphviz will
-  choose a size, without any limit.
-
-[[if test="enabled(graphviz)" then="""
+[[!if test="enabled(graphviz)" then="""
 Some example graphs:
 
-[[graph src="a -> b -> c; a -> b;"]]
-[[graph src="a -- b -- c -- a;" prog="circo" type="graph"]]
+[[!graph src="a -> b -> c; a -> b;"]]
+[[!graph src="a -- b -- c -- a;" prog="circo" type="graph"]]
 """]]
 
-This plugin uses the [[cpan Digest::SHA1]] perl module.
+This plugin uses the [[!cpan Digest::SHA1]] perl module.
index 259669d670bf436bb08a97a3d6b73a9b9514a836..74eac1c29679961c96ec2c9329cd8be81296b7a3 100644 (file)
@@ -1,20 +1,11 @@
-[[template id=plugin name=haiku author="[[Joey]]"]]
-[[tag type/fun]]
+[[!template id=plugin name=haiku author="[[Joey]]"]]
+[[!tag type/fun]]
 
-This plugin allows inserting a randomly generated haiku into a wiki page.
-Just type:
-
-       \[[haiku hint="argument"]]
-
-[[haiku hint="argument test"]]
-
-The hint parameter can be omitted, it only provides the generator a hint of
-what to write the haiku about. If no hint is given, it might base it on the
-page name. Since the vocabulary it knows is very small, many hints won't
-affect the result at all.
+This plugin provides a [[ikiwiki/directive/haiku]] [[ikiwiki/directive]].
+The directive allows inserting a randomly generated haiku into a wiki page.
 
 As a special bonus, enabling this plugin makes any error messages ikiwiki
 should display be written in haiku.
 
-You need to have the Coy module installed for this plugin to do anything
-interesting. That does all the heavy lifting.
+You need to have the [[!cpan Coy]] module installed for this plugin to do
+anything interesting. That does all the heavy lifting.
diff --git a/doc/plugins/highlight.mdwn b/doc/plugins/highlight.mdwn
new file mode 100644 (file)
index 0000000..5f04fda
--- /dev/null
@@ -0,0 +1,77 @@
+[[!template id=plugin name=highlight author="[[Joey]]"]]
+[[!tag type/format]]
+
+This plugin allows ikiwiki to syntax highlight source code, using
+a fast syntax highlighter that supports over a hundred programming
+languages and file formats.
+
+## prerequisites
+
+You will need to install the perl bindings to the
+[highlight library](http://www.andre-simon.de/). In Debian
+they are in the [[!debpkg libhighlight-perl]] package. If
+your distribution does not have them, look in `examples/swig`
+in highlight's source.
+
+## embedding highlighted code
+
+To embed highlighted code on a page, you can use the
+[[format]] plugin.
+
+For example:
+
+       \[[!format c """
+       void main () {
+               printf("hello, world!");
+       }
+       """]]
+
+       \[[!format diff """
+       -bar
+       +foo
+       """]]
+
+You can do this for any extension or language name supported by
+the [highlight library](http://www.andre-simon.de/) -- basically anything
+you can think of should work.
+
+## highlighting entire source files
+
+To enable syntax highlighting of entire standalone source files, use the
+`tohighlight` setting in your setup file to control which files should be
+syntax highlighted. Here is a typical setting for it, enabling highlighting
+for files with the extensions .c, etc, and also for any files named
+"Makefile".
+
+       tohighlight => ".c .h .cpp .pl .py Makefile:make",
+
+It knows what language to use for most filename extensions (see
+`/etc/highlight/filetypes.conf` for a partial list), but if you want to
+bind an unusual filename extension, or any file without an extension
+(such as a Makefile), to a language, you can do so by appending a colon
+and the name of the language, as illustrated for Makefiles above.
+
+With the plugin configured this way, source files become full-fledged
+wiki pages, which means they can include [[WikiLinks|ikiwiki/wikilink]]
+and [[directives|ikiwiki/directive]] like any other page can, and are also
+affected by the [[smiley]] plugin, if it is enabled. This can be annoying
+if your code accidentially contains things that look like those.
+
+On the other hand, this also allows your syntax highlighed
+source code to contain markdown formatted comments and hyperlinks
+to other code files, like this:
+
+       /* \[[!format mdwn """
+               This comment will be formatted as *markdown*!
+
+               See \[[bar.h]].
+       ""]] */
+
+Finally, bear in mind that this lets anyone who can edit a page in your
+wiki also edit source code files that are in your wiki. Use appropriate
+caution.
+
+## colors
+
+The colors etc used for the syntax highlighting are entirely configurable
+by CSS. See ikiwiki's [[style.css]] for the defaults.
diff --git a/doc/plugins/highlight/discussion.mdwn b/doc/plugins/highlight/discussion.mdwn
new file mode 100644 (file)
index 0000000..556b041
--- /dev/null
@@ -0,0 +1,21 @@
+It would be nice to be able to set a few options for the highlighter
+object. In particular, today I noticed my tabs were not being expanded
+correctly, which could be fixed the command line with --replace-tabs but
+programmatically needs a call to setPreformatting.  I could probably play
+with this, but what is your preferred way to support options? something
+like 'highlight_options=>{replace_tabs=>8,line_numbers=>0}' ?  Of course,
+if you want to implement it I won't complain :-). [[DavidBremner]]
+
+> I don't know about tab replacement, which I can't really see the point
+> of, but if there are multiple options, giving each its own nane would
+> word better for websetup than would putting all the options in a
+> sub-hash. --[[Joey]] 
+
+
+Has anyone got this running with CentOS/RHEL ?   
+Having trouble working out where to get the perl bindings for highlight. --[Mick](http://www.lunix.com.au)  
+
+> The perl bindings are hidden in `examples/swig` in highlight's source.
+> --[[Joey]] 
+
+Thanks for prompt reply.All working. I will post on my site tonight and link here what I did on CentOS to make this work. --[Mick](http://www.lunix.com.au) 
index 647fe19c1d499e5837370eae589b18f3b5547879..afe04c9437229f9c86caaae0a72813b1f1f0d177 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=hnb author="[[XTaran]]"]]
-[[tag type/format type/slow]]
+[[!template id=plugin name=hnb author="[[XTaran]]"]]
+[[!tag type/format type/slow]]
 
 This plugin allows ikiwiki to process `.hnb` XML files, as created by 
 the Hierachical Notebook [hnb](http://hnb.sourceforge.net/). To use it, you need to have 
index 8efefcbcb93e5ad9c11e49b9dc8d8175a98004b6..55e11bff09cd4d0f7180a09e1989c2f5eb80409f 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=html author="[[Joey]]"]]
-[[tag type/html type/format]]
+[[!template id=plugin name=html author="[[Joey]]"]]
+[[!tag type/html type/format]]
 
 This plugin lets html pages be used as source pages for the wiki. The
 html pages will still be wrapped in the same html template as any other
diff --git a/doc/plugins/htmlbalance.mdwn b/doc/plugins/htmlbalance.mdwn
new file mode 100644 (file)
index 0000000..f4e2298
--- /dev/null
@@ -0,0 +1,9 @@
+[[!template id=plugin name=htmlbalance author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/html]]
+
+This plugin ensures that the HTML emitted by ikiwiki contains well-balanced
+HTML tags, by parsing it with [[!cpan HTML::TreeBuilder]] and re-serializing it. This
+acts as a lighter-weight alternative to [[plugins/htmltidy]]; it doesn't
+ensure validity, but it does at least ensure that formatting from a
+blog post pulled in by the [[ikiwiki/directive/inline]] directive doesn't
+leak into the rest of the page.
diff --git a/doc/plugins/htmlbalance/discussion.mdwn b/doc/plugins/htmlbalance/discussion.mdwn
new file mode 100644 (file)
index 0000000..c66528a
--- /dev/null
@@ -0,0 +1,10 @@
+Would it be possible to use [[!cpan HTML::Entities]] rather than
+`XML::Atom::Util` for encoding entities? The former is already an ikiwiki
+dependency (via [[!cpan HTML::Parser]]).
+
+> Now switched to HTML::Entities --[[Joey]]
+
+I also wonder if there's any benefit to using this plugin aside from with
+aggregate. Perhaps a small one but aggregate seems like the main case..
+wondering if it would be better to just have aggregate balanace the html
+automatically and do away with the separate plugin. --[[Joey]]
index b32c264df3f245688375093b88142ba2318683a7..c59b46e14e12624463881101fff3190de36061c1 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=htmlscrubber core=1 author="[[Joey]]"]]
-[[tag type/html]]
+[[!template id=plugin name=htmlscrubber core=1 author="[[Joey]]"]]
+[[!tag type/html]]
 
 This plugin is enabled by default. It sanitizes the html on pages it renders
 to avoid XSS attacks and the like.
@@ -13,7 +13,7 @@ All attributes that can be used to specify an url are checked to make sure
 that the url is in a known, safe scheme, and to block embedded javascript
 in such urls.
 
-It uses the [[cpan HTML::Scrubber]] perl module to perform its html
+It uses the [[!cpan HTML::Scrubber]] perl module to perform its html
 sanitisation, and this perl module also deals with various entity encoding
 tricks.
 
@@ -31,6 +31,12 @@ Note that enabling or disabling the htmlscrubber plugin also affects some
 other HTML-related functionality, such as whether [[meta]] allows
 potentially unsafe HTML tags.
 
+The `htmlscrubber_skip` configuration setting can be used to skip scrubbing
+of some pages. Set it to a [[ikiwiki/PageSpec]], such as "!*/Discussion",
+and pages matching that can have all the evil CSS, JavsScript, and unsafe
+html elements you like. One safe way to use this is to use [[lockedit]] to
+lock those pages, so only admins can edit them.
+
 ----
 
 Some examples of embedded javascript that won't be let through when this
diff --git a/doc/plugins/htmlscrubber/discussion.mdwn b/doc/plugins/htmlscrubber/discussion.mdwn
new file mode 100644 (file)
index 0000000..5e8b637
--- /dev/null
@@ -0,0 +1,18 @@
+**Ok, I have yet to post a big dummy wiki-noobie question around here, so here goes:**
+
+Yes, I want to play around with *gulp* Google Ads on an ikiwiki blog, namely, in the *sidebar*. 
+
+No, I do not want to turn htmlscrubber off, but apart from that I have not been able to allow &lt;script&gt; elements as required by Google.
+
+Thoughts?
+
+---
+
+***Fixed!***
+
+Did some more reading, did some searching on the wiki, and found, under *embed*, these
+
+    htmlscrubber_skip => '!*/Discussion',
+    locked_pages => '!*/Discussion',
+
+Thanks!
index dae812df256885c976fd2a1a0969964eceac1d9e..580e56f596d690e42ce10467329f05e1b07354d5 100644 (file)
@@ -1,10 +1,11 @@
-[[template id=plugin name=htmltidy author="Faidon Liambotis"]]
-[[tag type/html]]
-[[tag type/slow]]
+[[!template id=plugin name=htmltidy author="Faidon Liambotis"]]
+[[!tag type/html]]
+[[!tag type/slow]]
 
 This plugin uses [tidy](http://tidy.sourceforge.net/) to tidy up the html
 emitted by ikiwiki. Besides being nicely formatted, this helps ensure that
 even if users enter suboptimal html, your wiki generates valid html.
 
 Note that since tidy is an external program, that is run each time a page
-is built, this plugin will slow ikiwiki down somewhat.
+is built, this plugin will slow ikiwiki down somewhat. [[plugins/htmlbalance]]
+might provide a faster alternative.
index 26f258bd38a832e2595f1c876b646e44b2096009..11ed223e7f7f083c537042fbbc1fe4ebaeb4ce67 100644 (file)
@@ -1,9 +1,9 @@
-[[template id=plugin name=httpauth author="Alec Berryman"]]
-[[tag type/auth]]
+[[!template id=plugin name=httpauth author="Alec Berryman"]]
+[[!tag type/auth]]
 
 This plugin allows HTTP basic authentication to be used to log into the
 wiki. To use the plugin, your web server should be set up to perform HTTP
-basic authentiation. The authenticated user will be automatically signed
-into the wiki.
+basic authentiation for at least the directory containing `ikiwiki.cgi`. 
+The authenticated user will be automatically signed into the wiki.
 
 This plugin is included in ikiwiki, but is not enabled by default.
index a4661f1a84eafe76233efc5e3a543639fd25d1fd..114438765d058a50b0e9a4efaebb19d3926ddc8a 100644 (file)
@@ -1,41 +1,14 @@
-[[template id=plugin name=img author="Christian Mock"]]
-[[tag type/chrome]]
+[[!template id=plugin name=img author="Christian Mock"]]
+[[!tag type/chrome]]
 
-This is an image handling plugin. While ikiwiki supports inlining full-size
-images by making a [[ikiwiki/WikiLink]] that points to the image, using
-this plugin you can easily scale down an image for inclusion onto a page,
-providing a link to a full-size version.
+This plugin provides the [[ikiwiki/directive/img]] [[ikiwiki/directive]].
+While ikiwiki supports inlining full-size images by making a
+[[ikiwiki/WikiLink]] that points to the image, using this directive you can
+easily scale down an image for inclusion onto a page, providing a link to a
+full-size version.
 
 This plugin uses the [ImageMagick](http://www.imagemagick.org/) tools via
 [PerlMagick](http://www.imagemagick.org/www/perl-magick.html).
 
 Note that this is a stripped down version of Christian Mock's
 [[original_img_plugin|contrib/img]].
-
-## usage
-
-       \[[img image1.jpg size="200x200" alt="clouds"]]
-
-The image file will be searched for using the same rules as used to find
-the file pointed to by a [[ikiwiki/WikiLink]].
-
-The `size` parameter is optional, defaulting to full size. Note that the
-original image's aspect ratio is always preserved, even if this means
-making the image smaller than the specified size.
-
-You can also pass `alt`, `title`, `class` and `id` parameters. These are
-passed through unchanged to the html img tag. If you include a `caption`
-parameter, the caption will be displayed centered beneath the image.
-
-The `link` parameter is used to control whether the scaled down image links
-to the full size version. By default it does; set "link=somepage" to link
-to another page instead, or "link=no" to disable the link, or
-"link=http://url" to link to a given url.
-
-You can also set default values that will be applied to all later images on
-the page, unless overridden. Useful when including many images on a page.
-
-       \[[img defaults size=200x200 alt="wedding photo"]]
-       \[[img photo1.jpg]]
-       \[[img photo2.jpg]]
-       \[[img photo3.jpg size=200x600]]
index 02d46e38081a1d60fb019dc445072dabb96e90e0..e1bb2d15b0b2fb1d313cd328813b54538be16500 100644 (file)
@@ -5,3 +5,8 @@ logo link to \[[hurd/logo]] / <http://www.bddebian.com/~wiki/hurd/logo/>
 instead of linking to the PNG image file.  --[[tschwinge]]
 
 > Done, use link=somepage --[[Joey]]
+
+It would be handy if the `class` and `id` tags were passed through to the surrounding `table` in the case of `caption` being present.  Would this break anything?  --[[neale]]
+
+> Seems unlikely to break *too* much. I can imagine css that styles the img
+> unexpectedly applying the table. --[[Joey]]
index fc6f9e8af1595d07672342e45a41622d13949fac..6c3282576538e62eff77601cbae106da9c04e7f7 100644 (file)
@@ -1,10 +1,5 @@
-[[template id=plugin name=inline core=1 author="[[Joey]]"]]
-
-This is a [[ikiwiki/PreProcessorDirective]] that allows including one wiki page
-inside another. For example:
-
-       \[[inline pages="blog/*"]]
-
-The most common use of inlining is generating blogs and RSS or Atom feeds.
-See [[ikiwiki/blog]] for details.
+[[!template id=plugin name=inline core=1 author="[[Joey]]"]]
 
+This plugin provides the [[ikiwiki/directive/inline]]
+[[ikiwiki/directive]], which allows including one wiki page
+inside another.
index 3efcb4c4b7a24222f7cf605472c69e0e92ea9d7c..900662eecc425ba60a9b84990ab0a726c7a017c9 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Installing third party plugins"]]
+[[!meta title="Installing third party plugins"]]
 
 Most ikiwiki plugins are perl modules and should be installed somewhere in
 the perl module search path. See the @INC list at the end of the output of
index 03f299282baf133549bb2f33facc98ee422d9772..6adbf3eae06e724e0ee768da3ab80c09bc2b0831 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=link core=1 author="[[Joey]]"]]
-[[tag type/link]]
+[[!template id=plugin name=link core=1 author="[[Joey]]"]]
+[[!tag type/link]]
 
-This plugin implements standard [[WikiLinks|WikiLink]].
+This plugin implements standard [[WikiLinks|ikiwiki/wikilink]].
index 6cd23b5cb6be0ff690bf9489a42333abd0a6c185..89cb9d8aeb5ff8735ca1dd551bc6787c483f3673 100644 (file)
@@ -1,29 +1,13 @@
-[[template id=plugin name=linkmap author="[[Joey]]"]]
-[[tag type/meta]]
-[[tag type/slow]]
-This plugin uses [graphviz](http://www.graphviz.org/) to generate a graph showing the links between a
-set of pages in the wiki. Example usage:
+[[!template id=plugin name=linkmap author="[[Joey]]"]]
+[[!tag type/meta]]
+[[!tag type/slow]]
 
-       \[[linkmap pages="* and !blog/* and !*/Discussion"]]
+This plugin provides the [[ikiwiki/directive/linkmap]] [[ikiwiki/directive]].
+It uses [graphviz](http://www.graphviz.org/) to generate a graph showing the
+links between a set of pages in the wiki.
 
-Only links between mapped pages will be shown; links pointing to or from
-unmapped pages will be omitted. If the pages to include are not specified,
-the links between all pages (and other files) in the wiki are mapped. For
-best results, only a small set of pages should be mapped, since otherwise
-the map can become very large, unweildy, and complicated. Also, the map is
-rebuilt whenever one of the mapped pages is changed, which can make the
-wiki a bit slow.
-
-Here are descriptions of all the supported parameters to the `linkmap`
-directive:
-
-* `pages` - A [[ikiwiki/PageSpec]] of the pages to map.
-* `height`, `width` - Limit the size of the map to a given height and width,
-  in inches. Both must be specified for the limiting to take effect, otherwise
-  the map's size is not limited.
-
-[[if test="enabled(linkmap)" then="""
+[[!if test="enabled(linkmap)" then="""
 Here is an example link map, of the index page and all pages it links to:
 
-[[linkmap pages="index or (backlink(index) and !*.png)"]]
+[[!linkmap pages="index or (backlink(index) and !*.png)"]]
 """]]
diff --git a/doc/plugins/listdirectives.mdwn b/doc/plugins/listdirectives.mdwn
new file mode 100644 (file)
index 0000000..2d9bce0
--- /dev/null
@@ -0,0 +1,15 @@
+[[!template id=plugin name=listdirectives author="Will"]]
+[[!tag type/meta]]
+
+This plugin provides the [[ikiwiki/directive/listdirectives]]
+[[ikiwiki/directive]], which inserts a list of currently available
+directives into the page.
+
+Each directive links to a wiki page with the same name, that should
+document that directive. The location of these pages can be controlled via
+the `directive_description_dir` setting in the setup file, the default is
+"ikiwiki/directive/foo".
+
+When this plugin is enabled, it enables the directives underlay, which
+contains documentation about all the directives included in plugins shipped
+with ikiwiki. This adds about 200 kb to the size of your wiki.
index 8dd4485580e79b08cc4c3b654f371f91509720c6..c8f64ea47a6b35579bed329da4da902952920eb3 100644 (file)
@@ -1,4 +1,28 @@
-[[template id=plugin name=lockedit core=1 author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=lockedit core=1 author="[[Joey]]"]]
+[[!tag type/auth]]
 
-This plugin enables [[page_locking]]. It is enabled by default.
+This plugin allows the administrator of a wiki to lock some pages, limiting
+who can edit them using the online interface. This doesn't prevent anyone
+who can commit to the underlying revision control system from editing the
+pages, however. (Unless you set up [[tips/untrusted_git_push]].)
+
+The `locked_pages` setting configures what pages are locked. It is a
+[[ikiwiki/PageSpec]], so you have lots of control over what kind of pages
+to lock. For example, you could choose to lock all pages created before
+2006, or all pages that are linked to from the page named "locked". More
+usually though, you'll just list some names of pages to lock.
+
+One handy thing to do if you're using ikiwiki for your blog is to lock
+"* and !*/Discussion". This prevents others from adding to or modifying
+posts in your blog, while still letting them comment via the Discussion
+pages.
+
+Alternatively, if you're using the [[comments]] plugin, you can lock
+"!postcomment(*)" to allow users to comment on pages, but not edit anything
+else.
+
+Wiki administrators can always edit locked pages. The [[ikiwiki/PageSpec]]
+can specify that some pages are not locked for some users. For example,
+"important_page and !user(joey)" locks `important_page` while still
+allowing joey to edit it, while "!*/Discussion and user(bob)" prevents bob
+from editing pages except for Discussion pages.
index df34d77cd8007cd72e344da43c6f8e871a2b7b35..8f5a9f15e23cb2477fcaffe26d36c0cb99b6d1ac 100644 (file)
@@ -1,26 +1,11 @@
-[[template id=plugin name=map author="Alessandro Dotti Contra"]]
-[[tag type/meta]]
+[[!template id=plugin name=map author="Alessandro Dotti Contra"]]
+[[!tag type/meta]]
 
-[[meta description="some page description"]]
+This plugin provides the [[ikiwiki/directive/map]] [[ikiwiki/directive]],
+which generates a hierarchical page map for the wiki.
 
-This plugin generates a hierarchical page map for the wiki. Example usage:
-
-       \[[map pages="* and !blog/* and !*/Discussion"]]
-
-If the pages to include are not specified, all pages (and other files) in
-the wiki are mapped.
-
-By default, the names of pages are shown in the map. The `show` parameter
-can be used to show the titles or descriptions of pages instead (as set by
-the [[meta]] plugin). For example:
-
-       \[[map pages="* and !blog/* and !*/Discussion" show=title]]
-
-Hint: To limit the map to displaying pages less than a certain level deep,
-use a [[ikiwiki/PageSpec]] like this: `pages="* and !*/*/*"`
-
-[[if test="enabled(map)" then="""
+[[!if test="enabled(map)" then="""
 Here's an example map, for the plugins section of this wiki:
 
-[[map pages="(plugins or plugins/*) and !*/*/*"]]
+[[!map pages="(plugins or plugins/*) and !*/*/*"]]
 """]]
index 814e4f9343bfbca2dd974f57558f38e882a3e9a0..2f7b140d6e6859369dd89d3fcf6a59ac63de7bc7 100644 (file)
@@ -16,5 +16,34 @@ Thoughts, anyone?  --[[KarlMW]]
 
 We'd also very much like to have an option to display the title of the page instead of the filename in the map plugin. --Andrew
 
-There's a patch implementing this in [[debbug 484510]]. It needs a few fixes
+There's a patch implementing this in [[!debbug 484510]]. It needs a few fixes
 before I merge it. Now applied. --[[Joey]]
+
+----
+
+I noticed that when the pagespec returns no map items, the map plugin does not close off the ul and div tags. Below is a simple patch 
+that seems to work on the examples I tried. I am a beginner so please help me out here. Thanks. --[[harishcm]]
+
+    --- a/map.pm
+    +++ b/map.pm
+    @@ -81,6 +81,13 @@
+            my $openli=0;
+            my $addparent="";
+            my $map = "<div class='map'>\n<ul>\n";
+    +
+    +       # Return properly closed $map if %mapitems is empty
+    +       if (!scalar(keys %mapitems)) {
+    +               $map .= "</ul>\n</div>\n";
+    +               return $map; 
+    +       }
+    +
+            foreach my $item (sort keys %mapitems) {
+                    my @linktext = (length $mapitems{$item} ? (linktext => $mapitems{$item}) : ());
+                    $item=~s/^\Q$common_prefix\E\///
+    
+> This was also reported as [[bugs/map_fails_to_close_ul_element_for_empty_list]];
+> this patch is simpler than the one there, but has the same problem (it emits
+> `<ul></ul>`, which technically isn't valid HTML either). --[[smcv]]
+
+>> Thanks for the tip, I added another patch addressing the issue at
+>> [[bugs/map_fails_to_close_ul_element_for_empty_list]]. --[[harishcm]]
index b5ce9c79cb419bfd49ebbad1b3122543105079e8..6ad1fb229a99aa83cc7b9d68a2d87867cd2b7cef 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=mdwn core=1 author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=mdwn core=1 author="[[Joey]]"]]
+[[!tag type/format]]
 
 This plugin lets ikwiki convert files with names ending in ".mdwn" to html.
 It uses the [[ikiwiki/markdown]] minimal markup language.
@@ -10,9 +10,9 @@ are also available in other plugins.
 There are several implementations of markdown support that can be used by
 this plugin. The [original version of
 markdown](http://daringfireball.net/projects/markdown/) can be used, or the
-[[cpan Text::Markdown]] perl module.
+[[!cpan Text::Markdown]] perl module.
 
-[[cpan Text::Markdown]] also includes a markdown variant called
+[[!cpan Text::Markdown]] also includes a markdown variant called
 [multimarkdown](http://fletcherpenney.net/MultiMarkdown/), which supports
 tables, footnotes, and other new features. Multimarkdown is not enabled by
 default, but can be turned on via the `multimarkdown` option in the setup
diff --git a/doc/plugins/mdwn/discussion.mdwn b/doc/plugins/mdwn/discussion.mdwn
new file mode 100644 (file)
index 0000000..4b05e7f
--- /dev/null
@@ -0,0 +1,7 @@
+Unlike other format, ikiwiki is somehow depends
+on mdwn, since the underlay dir
+is written in mdwn.  If you want to disable mdwn,
+you need to overwrite the underlay
+dir (set underlaydir in ikiwiki.setup
+to your own underlay dir or replace underlay pages
+in your $SRC).
index c3f971d06bd6a24144e16a27cfe1768d87b354a4..e49bdcc501bb0f3bfa91f6d18b79b0a0a2fb925b 100644 (file)
@@ -1,129 +1,5 @@
-[[template id=plugin name=meta author="[[Joey]]"]]
-[[tag type/meta]]
+[[!template id=plugin name=meta core=1 author="[[Joey]]"]]
+[[!tag type/meta]]
 
-This plugin allows inserting arbitrary metadata into the source of a page.
-Enter the metadata as follows:
-
-       \[[!meta field="value"]]
-       \[[!meta field="value" param="value" param="value"]]
-
-The first form sets a given field to a given value, while the second form
-also specifies some additional sub-parameters.
-
-The field values are treated as HTML entity-escaped text, so you can include
-a quote in the text by writing `&quot;` and so on.
-
-Supported fields:
-
-* title
-
-  Overrides the title of the page, which is generally the same as the
-  page name.
-
-  Note that if the title is overridden, a "title_overridden" variable will
-  be set to a true value in the template; this can be used to format things
-  differently in this case.
-
-* license
-
-  Specifies a license for the page, for example, "GPL". Can contain
-  WikiLinks and arbitrary markup.
-
-* copyright
-
-  Specifies the copyright of the page, for example, "Copyright 2007 by
-  Joey Hess". Can contain WikiLinks and arbitrary markup.
-
-* author
-
-  Specifies the author of a page.
-
-* authorurl
-
-  Specifies an url for the author of a page.
-
-* permalink
-
-  Specifies a permanent link to the page, if different than the page
-  generated by ikiwiki.
-
-* date
-
-  Specifies the creation date of the page. The date can be entered in
-  nearly any format, since it's parsed by [[cpan TimeDate]].
-
-* stylesheet
-
-  Adds a stylesheet to a page. The stylesheet is treated as a wiki link to
-  a `.css` file in the wiki, so it cannot be used to add links to external
-  stylesheets. Example:
-
-       \[[!meta stylesheet=somestyle rel="alternate stylesheet"
-       title="somestyle"]]
-
-* openid
-
-  Adds html &lt;link&gt; tags to perform OpenID delegation to an external
-  OpenID server (for `openid` and `openid2`). An optional `xrds-location`
-  parameter lets you specify the location of any [eXtensible Resource
-  DescriptorS](http://www.windley.com/archives/2007/05/using_xrds.shtml).
-
-  This lets you use an ikiwiki page as your OpenID. Example:
-
-       \\[[!meta openid="http://joeyh.myopenid.com/"
-       server="http://www.myopenid.com/server"
-       xrds-location="http://www.myopenid.com/xrds?username=joeyh.myopenid.com""]]
-
-* link
-
-  Specifies a link to another page. This can be used as a way to make the
-  wiki treat one page as linking to another without displaying a user-visible
-  [[ikiwiki/WikiLink]]:
-
-       \[[!meta link=otherpage]]
-
-  It can also be used to insert a html &lt;link&gt; tag. For example:
-
-       \[[!meta link="http://joeyh.myopenid.com/" rel="openid.delegate"]]
-
-  However, this latter syntax won't be allowed if the [[htmlscrubber]] is
-  enabled, since it can be used to insert unsafe content.
-
-* redir
-
-  Causes the page to redirect to another page in the wiki.
-
-       \[[!meta redir=otherpage]]
-
-  Optionally, a delay (in seconds) can be specified. The default is to
-  redirect without delay.
-
-  It can also be used to redirect to an external url. For example:
-
-       \[[!meta redir="http://example.com/"]]
-
-  However, this latter syntax won't be allowed if the [[htmlscrubber]] is
-  enabled, since it can be used to insert unsafe content.
-
-  For both cases, an anchor to jump to inside the destination page may also be
-  specified using the common `PAGE#ANCHOR` syntax.
-
-* robots
-
-  Causes the robots meta tag to be written:
-
-        \[[!meta robots="index, nofollow"]]
-
-  Valid values for the attribute are: "index", "noindex", "follow", and
-  "nofollow". Multiple comma-separated values are allowed, but obviously only
-  some combinations make sense. If there is no robots meta tag, "index,
-  follow" is used as the default.
-
-  The plugin escapes the value, but otherwise does not care about its
-  contents. In particular, it does not check the values against the set of
-  valid values but serves whatever you pass it.
-
-If the field is not one of the above predefined fields, the metadata will be
-written to the generated html page as a &lt;meta&gt; header. However, this
-won't be allowed if the [[htmlscrubber]] is enabled, since it can be used to
-insert unsafe content.
+This plugin provides the [[ikiwiki/directive/meta]] [[ikiwiki/directive]],
+which allows inserting various metadata into the source of a page.
index 8388a1172ca70e75c065b4573ab734c204fca933..814b93a41bbc95b6030d0e178ef2e8a0eeab9311 100644 (file)
@@ -11,7 +11,7 @@ Now I've work-arounded it using apostrophes in another way
 
 --[[Paweł|ptecza]]
 
-> As with any other parameter in a [[ikiwiki/preprocessordirective]], you can
+> As with any other parameter in a [[ikiwiki/directive]], you can
 > triple-quote, and then include quotation marks inside. --[[Joey]]
 
 >> Thanks for the hint! Toggle plugin is probably my favourite ikiwiki
index 25bad05856627c7ce096157be319301321fbfa4a..b371e8eb7f9a36f4462f49077a41e5d0ae7a2754 100644 (file)
@@ -1,8 +1,7 @@
-[[template id=plugin name=mirror author="[[Joey]]"]]
-[[tag type/special-purpose]]
+[[!template id=plugin name=mirror author="[[Joey]]"]]
+[[!tag type/special-purpose]]
 
 This plugin allows adding links a list of mirrors to each page in the
 wiki. For each mirror, a name and an url should be specified. Pages are
 assumed to exist in the same location under the specified url on each
-mirror. The [[ikiwiki.setup]] file has an example of configuring a list of
-mirrors.
+mirror.
index 44a7778134b1254863454867327842ae6fa07ef0..e9a971289b0a0bdf39a0f885f59cd6e3c5e8d3c6 100644 (file)
@@ -1,15 +1,6 @@
-[[template id=plugin name=more author="Ben"]]
-[[tag type/format]]
+[[!template id=plugin name=more author="Ben"]]
+[[!tag type/format]]
 
-This plugin provides a way to have a "more" link on a page in a blog, that
-leads to the full version of the page. Use it like this:
-
-       \[[more linktext="click for more" text="""
-       This is the rest of my post. Not intended for people catching up on
-       their blogs at 30,000 feet. Because I like to make things
-       difficult.
-       """]]
-
-If the `linktext` parameter is omitted it defaults to just "more".
-
-Note that you can accomplish something similar using a [[toggle]] instead.
+This plugin provides the [[ikiwiki/directive/more]] [[ikiwiki/directive]],
+which is a way to have a "more" link on a post in a blog, that leads to the
+full version of the page.
diff --git a/doc/plugins/more/discussion.mdwn b/doc/plugins/more/discussion.mdwn
new file mode 100644 (file)
index 0000000..f369d1e
--- /dev/null
@@ -0,0 +1,7 @@
+# Test:
+
+[[!more  linktext="click for more" text="""
+This is the rest of my post. Not intended for people catching up on
+their blogs at 30,000 feet. Because I like to make things
+difficult.
+"""]]
index cf0036c4c659dc148fa86989a09a70c930499794..b2ba68bf7796a23d85d7cba5c7f403448e349f09 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=opendiscussion author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=opendiscussion author="[[Joey]]"]]
+[[!tag type/auth]]
 
 This plugin allows editing of Discussion pages by anonymous users who have
 not logged into the wiki.
index a85727eca8d3b98a86ef64cc331f5cd79abc3836..91fc7cddc0a26da6707d5e7ccc47c7adfa1e6a72 100644 (file)
@@ -1,13 +1,15 @@
-[[template id=plugin name=openid core=1 author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=openid core=1 author="[[Joey]]"]]
+[[!tag type/auth]]
 
 This plugin allows users to use their [OpenID](http://openid.net/) to log
 into the wiki.
 
-The plugin needs the [[cpan Net::OpenID::Consumer]] perl module. The
-[[cpan LWPx::ParanoidAgent]] perl module is used if available, for added
-security. Finally, the [[cpan Crypt::SSLeay]] perl module is needed to support
-users entering "https" OpenID urls.
+The plugin needs the [[!cpan Net::OpenID::Consumer]] perl module.
+Version 1.x is needed in order for OpenID v2 to work.
+
+The [[!cpan LWPx::ParanoidAgent]] perl module is used if available, for
+added security. Finally, the [[!cpan Crypt::SSLeay]] perl module is needed
+to support users entering "https" OpenID urls.
 
 This plugin has a configuration option. You can set `--openidsignup`
 to the url of a third-party site where users can sign up for an OpenID. If
index 66c431868de2955bbf6a1eb7c8e6e1f35fef37e8..39e947b8293769ced36e3f01e312d86b3b307876 100644 (file)
@@ -6,4 +6,16 @@ It is scheduled for 2007-12-20 18:00 UTC.
 See <http://umeet.uninet.edu/umeet2007/english/prog.html> for the complete program
 and for information about how to join.
 
---[[tschwinge]]
\ No newline at end of file
+--[[tschwinge]]
+
+----
+<a id="Yahoo_unsupported" />
+[[!tag bugs]]
+
+It looks like OpenID 2.0 (the only supported by Yahoo) is not supported in ikiwiki. :( I signed up at http://openid.yahoo.com/ , and tried to login to my ikiwiki with the new ID (of the form: https://me.yahoo.com/a-username), but Yahoo told me:
+
+> Sorry! You will not be able to login to this website as it is using an older version of the the OpenID technology. Yahoo! only supports OpenID 2.0 because it is more secure. For more information, check out the OpenID documentation at [Yahoo! Developer Network](http://developer.yahoo.com/openid/).
+
+-- Ivan Z.
+
+They have more on OpenID 2.0 in [their FAQ](http://developer.yahoo.com/openid/faq.html). --Ivan Z.
index f7a856ef11e932bc0b654dfa243322c878fcff4d..ea7c4df13f42aba0a83a3b957cd3fcc621d89e69 100644 (file)
@@ -1,20 +1,14 @@
-[[template id=plugin name=orphans author="[[Joey]]"]]
-[[tag type/meta]]
+[[!template id=plugin name=orphans author="[[Joey]]"]]
+[[!tag type/meta]]
 
-This plugin generates a list of possibly orphaned pages -- pages that no
-other page links to.
+This plugin provides the [[ikiwiki/directive/orphans]]
+[[ikiwiki/directive]], which generates a list of possibly orphaned pages --
+pages that no other page links to.
 
-The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
-pages to check for orphans, default is search them all.
-
-Note that it takes [[BackLinks]] into account, but does not count inlining a
-page as linking to it, so will generally count many blog-type pages as
-orphans.
-
-[[if test="enabled(orphans)" then="""
+[[!if test="enabled(orphans)" then="""
 Here's a list of orphaned pages on this wiki:
 
-[[orphans pages="* and !news/* and !todo/* and !bugs/* and !users/* and
+[[!orphans pages="* and !news/* and !todo/* and !bugs/* and !users/* and
 !recentchanges and !examples/* and !tips/* and !sandbox/* and !templates/* and
 !wikiicons/* and !plugins/*"]]
 """]]
diff --git a/doc/plugins/orphans/discussion.mdwn b/doc/plugins/orphans/discussion.mdwn
new file mode 100644 (file)
index 0000000..3165e59
--- /dev/null
@@ -0,0 +1,22 @@
+It seems that the orphans plugin doesn't recognize markdown-style links of the kind:
+
+    [Pretty link name](realname)
+
+In my wiki, the page "realname" shows up as an orphan although it's being linked to.
+
+> Like anything in ikiwiki that deals with links, this only takes
+> [[WikiLinks|ikiwiki/wikilink]] into account. There should be no real
+> reason to use other link mechanisms provided by eg, markdown for internal
+> links in the wiki (indeed, using them is likely to cause broken links
+> when doing things like inlining or renaming pages). --[[Joey]]
+
+
+The orphans plugin fails with an error when it has to deal with a page that contains '+' characters as part of the filename. Apparently the code uses regular expressions and forgets to quote that string at some cruicial point. The error message I see is:
+
+     \[[!orphans Error: Nested quantifiers in regex; 
+     marked by <-- HERE in m/^(c++ <-- HERE |)$/ at
+     /usr/lib/perl5/vendor_perl/5.8.8/IkiWiki/Plugin/orphans.pm line 43.]]
+
+--Peter
+
+> Fixed. BTW, for an important bug like this, use [[bugs]]. --[[Joey]]
index 013a5072abb99f1673abefd4605c0689e16582c6..d890b01268681a6d1d1230d7c28e917e7aa06569 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=otl author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=otl author="[[Joey]]"]]
+[[!tag type/format]]
 
 This plugin allows ikiwiki to process `.otl` outline files, as created by 
 [vimoutliner](http://www.vimoutliner.org/). To use it, you need to have 
index 8f7029df8a4994fa76127d620a746d751bd3e2fe..a56027e607958364045fbc613b5bda53352fb082 100644 (file)
@@ -1,14 +1,10 @@
-[[template id=plugin name=pagecount author="[[Joey]]"]]
-[[tag type/meta]]
+[[!template id=plugin name=pagecount author="[[Joey]]"]]
+[[!tag type/meta]]
 
-Provides a \\[[pagecount ]] [[ikiwiki/PreProcessorDirective]] that is
-replaced with the total number of pages currently in the wiki.
-
-The optional parameter "pages" can be a [[ikiwiki/PageSpec]] specifying the
-pages to count, default is to count them all.
-
-This plugin is included in ikiwiki, but is not enabled by default.
+This plugin provides the [[ikiwiki/directive/pagecount]]
+[[ikiwiki/directive]], which displays the number of pages
+currently in the wiki.
 
 If it is turned on it can tell us that this wiki includes
-[[pagecount pages="* and !recentchanges"]]
-pages, of which [[pagecount pages="*/Discussion"]] are discussion pages.
+[[!pagecount ]] pages, of which
+[[!pagecount pages="*/Discussion"]] are discussion pages.
index f766a1ac806b5830319e3a066af11612fb9d23f1..c3eba63637b81b1257f3c17f2591ea4a99700865 100644 (file)
@@ -1,14 +1,6 @@
-[[template id=plugin name=pagestats author="Enrico Zini"]]
-[[tag type/meta type/tags]]
+[[!template id=plugin name=pagestats author="Enrico Zini"]]
+[[!tag type/meta type/tags]]
 
-This plugin can generate stats about how pages link to each other. It can
-produce either a del.icio.us style cloud, or a table counting the number of
-links to each page.
-
-Here's how to use it to create a [[tag]] cloud:
-
-       \[[pagestats pages="tags/*"]]
-
-And here's how to create a table of all the pages on the wiki:
-
-       \[[pagestats style="table"]]
+This plugin provides the [[ikiwiki/directive/pagestats]]
+[[ikiwiki/directive]], which can generate stats about how pages link to
+each other, or display a tag cloud.
index bea1543400704f3cbdaef82d6fe3a91da98070b1..afd5eb5000f42ecc9d63fef243dec3baafc8fb35 100644 (file)
@@ -1,14 +1,10 @@
-[[template id=plugin name=pagetemplate author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=pagetemplate author="[[Joey]]"]]
+[[!tag type/chrome]]
 
-This plugin allows a page to be created using a different
-[[template|wikitemplates]]. The page text is inserted into the template, so
-the template controls the overall look and feel of the wiki page. This is
-in contrast to the [[template]] plugin, which allows inserting templates
-_into_ the body of a page.
+This plugin provides the [[ikiwiki/directive/pagetemplate]]
+[[ikiwiki/directive]], which allows a page to be created using a different
+[[template|wikitemplates]].
 
 This plugin can only use templates that are already installed in
-/usr/share/ikiwiki/templates (or wherever ikiwiki is configured to look for
-them). You can choose to use any .tmpl files in that directory. Example:
-
-       \[[pagetemplate template=my_fancy.tmpl]]
+`/usr/share/ikiwiki/templates` (or wherever ikiwiki is configured to look for
+them). You can choose to use any .tmpl files in that directory.
diff --git a/doc/plugins/parentlinks.mdwn b/doc/plugins/parentlinks.mdwn
new file mode 100644 (file)
index 0000000..ef262a3
--- /dev/null
@@ -0,0 +1,5 @@
+[[!template id=plugin name=parentlinks core=1 author="[[intrigeri]]"]]
+[[!tag type/link]]
+
+This plugin generates the links to a page's parents that typically appear
+at the top of a wiki page.
index 473424764f9b26c5b98b52a4a46af2457e9199ce..fe680a0f8543bb5867fb246dbc74c48740757b4f 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=passwordauth core=1 author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=passwordauth core=1 author="[[Joey]]"]]
+[[!tag type/auth]]
 
 This plugin lets ikiwiki prompt for a user name and password when logging
 into the wiki. It also handles registering users, resetting passwords, and
@@ -18,7 +18,7 @@ as an "ask an existing member to get an account" system.)
 
 Users' passwords are stored in the `.ikiwiki/userdb` file, which needs to
 be kept safe to prevent exposure of passwords. If the
-[[cpan Authen::Passphrase]] perl module is installed, only hashes of the
+[[!cpan Authen::Passphrase]] perl module is installed, only hashes of the
 passwords will be stored. This is strongly recommended.
 
 The `password_cost` configuration option can be used to make the stored
index f4e7ae7a1225df56d0efeacd4f2c5ef8c5df087e..50e21062ec319364b48632dda9e83ed074347142 100644 (file)
@@ -9,3 +9,143 @@ the *Preferences -- Subscriptions*.  --[[tschwinge]]
 >> Aha, then the problem is Firefox, which is automatically filling the
 >> *Password* field with its previous value, but not filling the
 >> *Confirm Password* one.  --[[tschwinge]]
+
+## easy access to the userdb for apache auth?
+
+My use case is:
+
+* restricted ikiwiki
+* read/edit only allowed from the local network (done with apache restrictions)
+* edit only for people authenticated (done with vanilla ikiwiki passwordauth)
+
+I would like to allow people to read/edit the wiki from outside of the
+local network, if and only if they already have an ikiwiki account.
+
+[[httpauth]] doesn't fit since it doesn't allow anonymous local users
+to create their own account. I want a single, local, simple auth
+database.
+
+My (naïve?) idea would be:
+
+* keep the [[passwordauth]] system
+* provide a way for Apache to use the userdb for authentication if
+people want to connect from outside
+
+I looked at the various auth modules for apache2. It seems that none
+can use a "perl Storable data" file. So, I think some solutions could
+be:
+
+* use a sqlite database instead of a perl Storable file
+  * can be used with
+    [mod_auth_dbd](http://httpd.apache.org/docs/2.2/mod/mod_authn_dbd.html) 
+  * requires a change in ikiwiki module [[passwordauth]]
+* use an external program to read the userdb and talk with
+  [mod_auth_external](http://unixpapa.com/mod_auth_external.html)
+  * requires the maintainance of this external auth proxy over ikiwiki
+    userdb format changes
+  * (I don't know perl)
+* include this wrapper in ikiwiki
+  * something like `ikiwiki --auth user:pass:userdb` check the
+    `user:pass` pair in `userdb` and returns an Accept/Reject flag to
+    Apache 
+  * requires a change in ikiwiki core
+  * still requires
+    [mod_auth_external](http://unixpapa.com/mod_auth_external.html)
+* do it with Apache perl sections
+  * (I don't know perl)
+
+Any opinion/suggestion/solution to this is welcome and appreciated.
+
+--
+[[NicolasLimare]]
+
+For a similar use case, I've been intending to implement
+[[todo/httpauth_feature_parity_with_passwordauth]], but your idea may
+actually be the way to go. IMHO, the Perl sections idea is the
+easiest to setup, but on the long run, I'd prefer ikiwiki to optionnally
+use a userdb storage backend supported at least by Apache and lighttpd.
+--[[intrigeri]]
+
+Tons of CPAN modules may help, but most of them are specific to `mod_perl`,
+and AFAIK, ikiwiki is generally not run with `mod_perl`. It's not clear to me
+wether these modules depend on the webapp to be run with `mod_perl` set 
+as the script handler, or only on `mod_perl` to be installed and loaded.
+
+* CPAN's `Apache::AuthenHook` allows to plug arbitrary Perl handlers as
+  Apache authentication providers.
+* CPAN's `Apache::Authen::Program` (`mod_perl`)
+* [http://www.openfusion.com.au/labs/mod_auth_tkt/](mod_auth_tkt) along with CPAN's
+  `Apache::AuthTkt`
+--[[intrigeri]]
+
+I've more or less managed to implement something based on `mod_perl` and
+`Apache::AuthenHook`, respectively in Debian packages `libapache2-mod-perl2`
+and `libapache-authenhook-perl`.
+
+In the Apache VirtualHost configuration, I have added the following:
+
+       PerlLoadModule Apache::AuthenHook
+       PerlModule My::IkiWikiBasicProvider
+
+       <Location /test/>
+               AuthType Basic
+               AuthName "wiki"
+               AuthBasicProvider My::IkiWikiBasicProvider
+               Require valid-user
+               ErrorDocument 401 /test/ikiwiki.cgi?do=signin
+       </Location>
+       <LocationMatch "^/test/(ikiwiki\.cgi$|.*\.css$|wikiicons/)">
+               Satisfy any
+       </LocationMatch>
+
+The perl module lies in `/etc/apache2/My/IkiWikiBasicProvider.pm`:
+
+       package My::IkiWikiBasicProvider;
+
+       use warnings;
+       use strict;
+       use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED);
+       use Storable;
+       use Authen::Passphrase;
+
+       sub userinfo_retrieve () {
+               my $userinfo=eval{ Storable::lock_retrieve("/var/lib/ikiwiki/test/.ikiwiki/userdb") };
+               return $userinfo;
+       }
+
+       sub handler {
+               my ($r, $user, $password) = @_;
+               my $field = "password";
+
+               if (! defined $password || ! length $password) {
+                       return Apache2::Const::DECLINED;
+               }
+               my $userinfo = userinfo_retrieve();
+               if (! length $user || ! defined $userinfo ||
+                   ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) {
+                       return Apache2::Const::DECLINED;
+               }
+               my $ret=0;
+               if (exists $userinfo->{$user}->{"crypt".$field}) {
+                       error $@ if $@;
+                       my $p = Authen::Passphrase->from_crypt($userinfo->{$user}->{"crypt".$field});
+                       $ret=$p->match($password);
+               }
+               elsif (exists $userinfo->{$user}->{$field}) {
+                       $ret=$password eq $userinfo->{$user}->{$field};
+               }
+               if ($ret) {
+                       return Apache2::Const::OK;
+               }
+               return Apache2::Const::DECLINED;
+       }
+
+       1;
+
+This setup also allows people with the master password to create their own
+account.
+
+I'm not really fluent in Perl, and all this can probably be improved (*or
+might destroy your computer as it is* and YMMV).
+
+-- [[Lunar]]
index 03eeb581cefd8b1c9bf784ed238425fb567877fd..6156c235fd76e1524b30b8265a856439dd0061da 100644 (file)
@@ -1,9 +1,9 @@
-[[template id=plugin name=pingee author="[[Joey]]"]]
-[[tag type/special-purpose]]
+[[!template id=plugin name=pingee author="[[Joey]]"]]
+[[!tag type/special-purpose]]
 
 This plugin causes ikiwiki to listen for pings, typically delivered from
 another ikiwiki instance using the [[pinger]] plugin. When a ping is
-recieved, ikiwiki will update the wiki, the same as if `ikiwiki --refresh`
+received, ikiwiki will update the wiki, the same as if `ikiwiki --refresh`
 were ran at the command line.
 
 An url such as the following is used to trigger a ping:
index f747a9f0b5931e5d983d7ec4104b45dcb4950e37..00d83e1bb1ca68ccf6d74a3f0c12814437508743 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=pinger author="[[Joey]]"]]
-[[tag type/special-purpose]]
+[[!template id=plugin name=pinger author="[[Joey]]"]]
+[[!tag type/special-purpose]]
 
 This plugin allows ikiwiki to be configured to hit a URL each time it
 updates the wiki. One way to use this is in conjunction with the [[pingee]]
@@ -7,18 +7,12 @@ plugin to set up a loosely coupled mirror network, or a branched version of
 a wiki. By pinging the mirror or branch each time the main wiki changes, it
 can be kept up-to-date.
 
-        \[[!ping from="http://mywiki.com/"
-        to="http://otherwiki.com/ikiwiki.cgi?do=ping"]]
+To configure what URLs to ping, use the [[ikiwiki/directive/ping]]
+[[ikiwiki/directive]].
 
-The "from" parameter must be identical to the url of the wiki that is doing
-the pinging. This is used to prevent ping loops.
-
-The "to" parameter is the url to ping. The example shows how to ping
-another ikiwiki instance.
-
-The [[cpan LWP]] perl module is used for pinging. Or the [[cpan
+The [[!cpan LWP]] perl module is used for pinging. Or the [[!cpan
 LWPx::ParanoidAgent]] perl module is used if available, for added security.
-Finally, the [[cpan Crypt::SSLeay]] perl module is needed to support pinging
+Finally, the [[!cpan Crypt::SSLeay]] perl module is needed to support pinging
 "https" urls.
 
 By default the pinger will try to ping a site for 15 seconds before timing
diff --git a/doc/plugins/plaintext/discussion.mdwn b/doc/plugins/plaintext/discussion.mdwn
deleted file mode 100644 (file)
index 6b907e6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-I guess the reason I never thought to write this is when I put a .txt file
-in ikiwiki, I'm happy enough to see it copied through unchanged.
-
-I guess the advantage of using this plugin is that you get the page wrapper
-around the preformatted text, and could even inline such a page.
-
-There is not currently a good way to turn off some processing steps for
-some page types. It's either all or nothing. The patch in
-[[todo/format_escape]] might allow a formatter to register its own special
-version of htmllink that didn't do anything, but would that be enough?
-
---[[Joey]]
-
-[Here](http://www.gmcmanus.org/plaintext.pm) is an alternate approach.
-It encodes entities using a filter hook, before wikilinks are linkified.
-So wikilinks turn up as links.
-It also uses URI::Find to turn URIs into links.
-
-I'm not very familiar with Perl, so this code could be improved.
-
---Gabriel
-
-I like this approach! It sidesteps the annoying problem, and it actually
-makes the .txt format genuinely wiki-like, by allowing wikilinks and
-preprocessor directices.
-
-The only thing I am not sure about is the conversion of external urls to
-hyperlinks. 
-
-Can you please add a copyright/license statemnt to the top of the plugin?
-If you do, I'll add it to ikiwiki. Thanks! --[[Joey]]
-
-> I've added copyright and license (GPLv2 or later). --Gabriel
diff --git a/doc/plugins/po.mdwn b/doc/plugins/po.mdwn
new file mode 100644 (file)
index 0000000..57459c1
--- /dev/null
@@ -0,0 +1,325 @@
+[[!template id=plugin name=po core=0 author="[[intrigeri]]"]]
+[[!tag type/format]]
+
+This plugin adds support for multi-lingual wikis, translated with
+gettext, using [po4a](http://po4a.alioth.debian.org/).
+
+It depends on the Perl `Locale::Po4a::Po` library (`apt-get install po4a`).
+As detailed bellow in the security section, `po4a` is subject to
+denial-of-service attacks before version 0.35.
+
+[[!toc levels=2]]
+
+Introduction
+============
+
+A language is chosen as the "master" one, and any other supported
+language is a "slave" one.
+
+A page written in the "master" language is a "master" page. It can be
+of any page type supported by ikiwiki, except `po`. It does not have to be
+named a special way: migration to this plugin does not imply any page
+renaming work.
+
+Example: `bla/page.mdwn` is a "master" Markdown page written in
+English; if `usedirs` is enabled, it is rendered as
+`bla/page/index.en.html`, else as `bla/page.en.html`.
+
+Any translation of a "master" page into a "slave" language is called
+a "slave" page; it is written in the gettext PO format. `po` is now
+a page type supported by ikiwiki.
+
+Example: `bla/page.fr.po` is the PO "message catalog" used to
+translate `bla/page.mdwn` into French; if `usedirs` is enabled, it is
+rendered as `bla/page/index.fr.html`, else as `bla/page.fr.html`
+
+(In)Compatibility
+=================
+
+This plugin does not support the `indexpages` mode. If you don't know
+what it is, you probably don't care.
+
+
+Configuration
+=============
+
+Supported languages
+-------------------
+
+`po_master_language` is used to set the "master" language in
+`ikiwiki.setup`, such as:
+
+        po_master_language => { 'code' => 'en', 'name' => 'English' }
+
+`po_slave_languages` is used to set the list of supported "slave"
+languages, such as:
+
+        po_slave_languages => { 'fr' => 'Français',
+                                'es' => 'Español',
+                                'de' => 'Deutsch',
+        }
+
+Decide which pages are translatable
+-----------------------------------
+
+The `po_translatable_pages` setting configures what pages are
+translatable. It is a [[ikiwiki/PageSpec]], so you have lots of
+control over what kind of pages are translatable.
+
+The `.po` files are not considered as being translatable, so you don't need to
+worry about excluding them explicitly from this [[ikiwiki/PageSpec]].
+
+Internal links
+--------------
+
+### Links targets
+
+The `po_link_to` option in `ikiwiki.setup` is used to decide how
+internal links should be generated, depending on web server features
+and site-specific preferences.
+
+#### Default linking behavior
+
+If `po_link_to` is unset, or set to `default`, ikiwiki's default
+linking behavior is preserved: `\[[destpage]]` links to the master
+language's page.
+
+#### Link to current language
+
+If `po_link_to` is set to `current`, `\[[destpage]]` links to the
+`destpage`'s version written in the current page's language, if
+available, *i.e.*:
+
+* `foo/destpage/index.LL.html` if `usedirs` is enabled
+* `foo/destpage.LL.html` if `usedirs` is disabled
+
+#### Link to negotiated language
+
+If `po_link_to` is set to `negotiated`, `\[[page]]` links to the
+negotiated preferred language, *i.e.* `foo/page/`.
+
+(In)compatibility notes:
+
+* if `usedirs` is disabled, it does not make sense to set `po_link_to`
+  to `negotiated`; this option combination is neither implemented
+  nor allowed.
+* if the web server does not support Content Negotiation, setting
+  `po_link_to` to `negotiated` will produce a unusable website.
+
+Server support
+==============
+
+Apache
+------
+
+Using Apache `mod_negotiation` makes it really easy to have Apache
+serve any page in the client's preferred language, if available.
+
+Add 'Options MultiViews' to the wiki directory's configuration in Apache.
+
+When `usedirs` is enabled, one has to set `DirectoryIndex index` for
+the wiki context.
+
+Setting `DefaultLanguage LL` (replace `LL` with your default MIME
+language code) for the wiki context can help to ensure
+`bla/page/index.en.html` is served as `Content-Language: LL`.
+
+For details, see [Apache's documentation](http://httpd.apache.org/docs/2.2/content-negotiation.html).
+
+lighttpd
+--------
+
+lighttpd unfortunately does not support content negotiation.
+
+**FIXME**: does `mod_magnet` provide the functionality needed to
+ emulate this?
+
+
+Usage
+=====
+
+Templates
+---------
+
+When `po_link_to` is not set to `negotiated`, one should replace some
+occurrences of `BASEURL` with `HOMEPAGEURL` to get correct links to
+the wiki homepage.
+
+The `ISTRANSLATION` and `ISTRANSLATABLE` variables can be used to
+display things only on translatable or translation pages.
+
+### Display page's versions in other languages
+
+The `OTHERLANGUAGES` loop provides ways to display other languages'
+versions of the same page, and the translations' status.
+
+An example of its use can be found in the default
+`templates/page.tmpl`. In case you want to customize it, the following
+variables are available inside the loop (for every page in):
+
+* `URL` - url to the page
+* `CODE` - two-letters language code
+* `LANGUAGE` - language name (as defined in `po_slave_languages`)
+* `MASTER` - is true (1) if, and only if the page is a "master" page
+* `PERCENT` - for "slave" pages, is set to the translation completeness, in percents
+
+### Display the current translation status
+
+The `PERCENTTRANSLATED` variable is set to the translation
+completeness, expressed in percent, on "slave" pages. It is used by
+the default `templates/page.tmpl`.
+
+Additional PageSpec tests
+-------------------------
+
+This plugin enhances the regular [[ikiwiki/PageSpec]] syntax with some
+additional tests that are documented [[here|ikiwiki/pagespec/po]].
+
+Automatic PO file update
+------------------------
+
+Committing changes to a "master" page:
+
+1. updates the POT file and the PO files for the "slave" languages;
+   the updated PO files are then put under version control;
+2. triggers a refresh of the corresponding HTML slave pages.
+
+Also, when the plugin has just been enabled, or when a page has just
+been declared as being translatable, the needed POT and PO files are
+created, and the PO files are checked into version control.
+
+Discussion pages and other sub-pages
+------------------------------------
+
+Discussion should happen in the language in which the pages are
+written for real, *i.e.* the "master" one. If discussion pages are
+enabled, "slave" pages therefore link to the "master" page's
+discussion page.
+
+Likewise, "slave" pages are not supposed to have sub-pages;
+[[WikiLinks|wikilink]] that appear on a "slave" page therefore link to
+the master page's sub-pages.
+
+Translating
+-----------
+
+One can edit the PO files using ikiwiki's CGI (a message-by-message
+interface could also be implemented at some point).
+
+If [[tips/untrusted_git_push]] is setup, one can edit the PO files in one's
+preferred `$EDITOR`, without needing to be online.
+
+Markup languages support
+------------------------
+
+[[Markdown|mdwn]] is well supported. Some other markup languages supported
+by ikiwiki mostly work, but some pieces of syntax are not rendered
+correctly on the slave pages:
+
+* [[reStructuredText|rst]]: anonymous hyperlinks and internal
+  cross-references
+* [[wikitext]]: conversion of newlines to paragraphs
+* [[creole]]: verbatim text is wrapped, tables are broken
+* [[html]] and LaTeX: not supported yet; the dedicated po4a modules
+  could be used to support them, but they would need a security audit
+* other markup languages have not been tested.
+
+Security
+========
+
+[[po/discussion]] contains a detailed security analysis of this plugin
+and its dependencies.
+
+When using po4a older than 0.35, it is recommended to uninstall
+`Text::WrapI18N` (Debian package `libtext-wrapi18n-perl`), in order to
+avoid a potential denial of service.
+
+TODO
+====
+
+Better links
+------------
+
+Once the fix to
+[[bugs/pagetitle_function_does_not_respect_meta_titles]] from
+[[intrigeri]]'s `meta` branch is merged into ikiwiki upstream, the
+generated links' text will be optionally based on the page titles set
+with the [[meta|plugins/meta]] plugin, and will thus be translatable.
+It will also allow displaying the translation status in links to slave
+pages. Both were implemented, and reverted in commit
+ea753782b222bf4ba2fb4683b6363afdd9055b64, which should be reverted
+once [[intrigeri]]'s `meta` branch is merged.
+
+An integration branch, called `meta-po`, merges [[intrigeri]]'s `po`
+and `meta` branches, and thus has this additional features.
+
+Language display order
+----------------------
+
+Jonas pointed out that one might want to control the order that links to
+other languages are listed, for various reasons. Currently, there is no
+order, as `po_slave_languages` is a hash. It would need to be converted
+to an array to support this. (If twere done, twere best done quickly.)
+--[[Joey]] 
+
+Pagespecs
+---------
+
+I was suprised that, when using the map directive, a pagespec of "*"
+listed all the translated pages as well as regular pages. That can 
+make a big difference to an existing wiki when po is turned on,
+and seems generally not wanted.
+(OTOH, you do want to match translated pages by
+default when locking pages.) --[[Joey]]
+
+Edit links on untranslated pages
+--------------------------------
+
+If a page is not translated yet, the "translated" version of it
+displays wikilinks to other, existing (but not yet translated?)
+pages as edit links, as if those pages do not exist. 
+
+That's really confusing, especially as clicking such a link
+brings up an edit form to create a new, english page.
+
+This is with po_link_to=current or negotiated. With default, it doesn't
+happen.. 
+
+Also, this may only happen if the page being linked to is coming from an
+underlay, and the underlays lack translation to a given language.
+--[[Joey]] 
+
+Double commits of po files
+--------------------------
+
+When adding a new english page, the po files are created, committed,
+and then committed again. The second commit makes this change:
+
+       -"Content-Type: text/plain; charset=utf-8\n"
+       -"Content-Transfer-Encoding: ENCODING"
+       +"Content-Type: text/plain; charset=UTF-8\n"
+       +"Content-Transfer-Encoding: ENCODING\n"
+
+Same thing happens when a change to an existing page triggers a po file
+update. --[[Joey]] 
+
+Ugly messages with empty files
+------------------------------
+
+If there are empty .mdwn files, the po plugin displays some ugly messages.
+
+Translation of directives
+-------------------------
+
+If a translated page contains a directive, it may expand to some english
+text, or text in whatever single language ikiwiki is configured to "speak".
+
+Maybe there could be a way to switch ikiwiki to speaking another language
+when building a non-english page? Then the directives would get translated.
+
+Documentation
+-------------
+
+Maybe write separate documentation depending on the people it targets:
+translators, wiki administrators, hackers. This plugin may be complex
+enough to deserve this.
diff --git a/doc/plugins/po/discussion.mdwn b/doc/plugins/po/discussion.mdwn
new file mode 100644 (file)
index 0000000..ab822e7
--- /dev/null
@@ -0,0 +1,726 @@
+[[!toc ]]
+
+----
+
+# Security review
+
+## Probable holes
+
+_(The list of things to fix.)_
+
+### po4a-gettextize
+
+* po4a CVS 2009-01-16
+* Perl 5.10.0
+
+`po4a-gettextize` uses more or less the same po4a features as our
+`refreshpot` function.
+
+Without specifying an input charset, zzuf'ed `po4a-gettextize` quickly
+errors out, complaining it was not able to detect the input charset;
+it leaves no incomplete file on disk. I therefore had to pretend the
+input was in UTF-8, as does the po plugin.
+
+        zzuf -c -s 13 -r 0.1 \
+            po4a-gettextize -f text -o markdown -M utf-8 -L utf-8 \
+             -m GPL-3 -p GPL-3.pot
+
+Crashes with:
+
+        Malformed UTF-8 character (UTF-16 surrogate 0xdfa4) in substitution
+        iterator at /usr/share/perl5/Locale/Po4a/Po.pm line 1449.
+        Malformed UTF-8 character (fatal) at /usr/share/perl5/Locale/Po4a/Po.pm
+        line 1449.
+
+An incomplete pot file is left on disk. Unfortunately Po.pm tells us
+nothing about the place where the crash happens.
+
+> It's fairly standard perl behavior when fed malformed utf-8. As long
+> as it doesn't crash ikiwiki, it's probably acceptable. Ikiwiki can
+> do some similar things itself when fed malformed utf-8 (doesn't
+> crash tho) --[[Joey]]
+
+----
+
+## Potential gotchas
+
+_(Things not to do.)_
+
+
+### Blindly activating more po4a format modules
+
+The format modules we want to use have to be checked, as not all are
+safe (e.g. the LaTeX module's behaviour is changed by commands
+included in the content); they may use regexps generated from
+the content.
+
+----
+
+## Hopefully non-holes
+
+_(AKA, the assumptions that will be the root of most security holes...)_
+
+### PO file features
+
+No [documented](http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files)
+directive that can be put in po files is supposed to cause mischief
+(ie, include other files, run commands, crash gettext, whatever).
+
+### gettext
+
+#### Security history
+
+The only past security issue I could find in GNU gettext is
+[CVE-2004-0966](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-0966),
+*i.e.* [Debian bug #278283](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=278283):
+the autopoint and gettextize scripts in the GNU gettext package (1.14
+and later versions) may allow local users to overwrite files via
+a symlink attack on temporary files.
+
+This plugin would not have allowed to exploit this bug, as it does not
+use, either directly or indirectly, the faulty scripts.
+
+Note: the lack of found security issues can either indicate that there
+are none, or reveal that no-one ever bothered to find or publish them.
+
+#### msgmerge
+
+`refreshpofiles()` runs this external program.
+
+* I was not able to crash it with `zzuf`.
+* I could not find any past security hole.
+
+#### msgfmt
+
+`isvalidpo()` runs this external program.
+
+* I was not able to make it behave badly using zzuf: it exits cleanly
+  when too many errors are detected.
+* I could not find any past security hole.
+
+### po4a
+
+#### Security history
+
+The only past security issue I could find in po4a is
+[CVE-2007-4462](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-4462):
+`lib/Locale/Po4a/Po.pm` in po4a before 0.32 allowed local users to
+overwrite arbitrary files via a symlink attack on the
+gettextization.failed.po temporary file.
+
+This plugin would not have allowed to exploit this bug, as it does not
+use, either directly or indirectly, the faulty `gettextize` function.
+
+Note: the lack of found security issues can either indicate that there
+are none, or reveal that no-one ever bothered to find or publish them.
+
+#### General feeling
+
+Are there any security issues on running po4a on untrusted content?
+
+To say the least, this issue is not well covered, at least publicly:
+
+* the documentation does not talk about it;
+* grep'ing the source code for `security` or `trust` gives no answer.
+
+On the other hand, a po4a developer answered my questions in
+a convincing manner, stating that processing untrusted content was not
+an initial goal, and analysing in detail the possible issues.
+The following analysis was done with his help.
+
+#### Details
+
+* the core (`Po.pm`, `Transtractor.pm`) should be safe
+* po4a source code was fully checked for other potential symlink
+  attacks, after discovery of one such issue
+* the only external program run by the core is `diff`, in `Po.pm` (in
+  parts of its code we don't use)
+* `Locale::gettext` is only used to display translated error messages
+* Nicolas François "hopes" `DynaLoader` is safe, and has "no reason to
+  think that `Encode` is not safe"
+* Nicolas François has "no reason to think that `Encode::Guess` is not
+  safe". The po plugin nevertheless avoids using it by defining the
+  input charset (`file_in_charset`) before asking `TransTractor` to
+  read any file. NB: this hack depends on po4a internals.
+
+##### Locale::Po4a::Text
+
+* does not run any external program
+* only `do_paragraph()` builds regexp's that expand untrusted
+  variables; according to [[Joey]], this is "Freaky code, but seems ok
+  due to use of `quotementa`".
+
+##### Text::WrapI18N
+
+`Text::WrapI18N` can cause DoS
+([Debian bug #470250](http://bugs.debian.org/470250)).
+It is optional, and we do not need the features it provides.
+
+If a recent enough po4a (>=0.35) is installed, this module's use is
+fully disabled. Else, the wiki administrator is warned about this
+at runtime.
+
+##### Term::ReadKey
+
+`Term::ReadKey` is not a hard dependency in our case, *i.e.* po4a
+works nicely without it. But the po4a Debian package recommends
+`libterm-readkey-perl`, so it will probably be installed on most
+systems using the po plugin.
+
+`Term::ReadKey` has too far reaching implications for us to
+be able to guarantee anything wrt. security.
+
+If a recent enough po4a (>=2009-01-15 CVS, which will probably be
+released as 0.35) is installed, this module's use is fully disabled.
+
+##### Fuzzing input
+
+###### po4a-translate
+
+* po4a CVS 2009-01-16
+* Perl 5.10.0
+
+`po4a-translate` uses more or less the same po4a features as our
+`filter` function.
+
+Without specifying an input charset, same behaviour as
+`po4a-gettextize`, so let's specify UTF-8 as input charset as of now.
+
+`LICENSES` is a 21M file containing 100 concatenated copies of all the
+files in `/usr/share/common-licenses/`; I had no existing PO file or
+translated versions at hand, which renders these tests
+quite incomplete.
+
+        zzuf -cv -s 0:10 -r 0.001:0.3 \
+          po4a-translate -d -f text -o markdown -M utf-8 -L utf-8 \
+            -k 0 -m LICENSES -p LICENSES.fr.po -l test.fr
+
+... seems to lose the fight, at the `readpo(LICENSES.fr.po)` step,
+against some kind of infinite loop, deadlock, or any similar beast.
+
+The root of this bug lies in `Text::WrapI18N`, see the corresponding
+section.
+
+
+----
+
+## Fixed holes
+
+
+----
+
+# original contrib/po page, with old commentary
+
+I've been working on a plugin called "po", that adds support for multi-lingual wikis,
+translated with gettext, using [po4a](http://po4a.alioth.debian.org/).
+
+More information:
+
+* It can be found in my "po" branch:
+  `git clone git://gaffer.ptitcanardnoir.org/ikiwiki.git`
+* It is self-contained, *i.e.* it does not modify ikiwiki core at all.
+* It is documented (including TODO and plans for next work steps) in
+  `doc/plugins/po.mdwn`, which can be found in the same branch.
+* No public demo site is available so far, I'm working on this.
+
+My plan is to get this plugin clean enough to be included in ikiwiki.
+
+The current version is a proof-of-concept, mature enough for me to dare submitting it here,
+but I'm prepared to hear various helpful remarks, and to rewrite parts of it as needed.
+
+Any thoughts on this?
+
+> Well, I think it's pretty stunning what you've done here. Seems very
+> complete and well thought out. I have not read the code in great detail
+> yet.
+> 
+> Just using po files is an approach I've never seen tried with a wiki. I
+> suspect it will work better for some wikis than others. For wikis that
+> just want translations that match the master language as closely as
+> possible and don't wander off and diverge, it seems perfect. (But what happens
+> if someone edits the Discussion page of a translated page?)
+> 
+> Please keep me posted, when you get closer to having all issues solved
+> and ready for merging I can do a review and hopefully help with the
+> security items you listed. --[[Joey]]
+
+>> Thanks a lot for your quick review, it's reassuring to hear such nice words
+>> from you. I did not want to design and write a full translation system, when
+>> tools such as gettext/po4a already have all the needed functionality, for cases
+>> where the master/slave languages paradigm fits.
+>> Integrating these tools into ikiwiki plugin system was a pleasure.
+>>
+>> I'll tell you when I'm ready for merging, but in the meantime,
+>> I'd like you to review the changes I did to the core (3 added hooks).
+>> Can you please do this? If not, I'll go on and hope I'm not going to far in
+>> the wrong direction.
+>>
+>>> Sure.. I'm not completly happy with any of the hooks since they're very
+>>> special purpose, and also since `run_hooks` is not the best interface
+>>> for a hook that modifies a variable, where only the last hook run will
+>>> actually do anything. It might be better to just wrap
+>>> `targetpage`, `bestlink`, and `beautify_urlpath`. But, I noticed
+>>> the other day that such wrappers around exported functions are only visible by
+>>> plugins loaded after the plugin that defines them.
+>>> 
+>>> Update: Take a look at the new "Function overriding" section of
+>>> [[plugins/write]]. I think you can just inject wrappers about a few ikiwiki
+>>> functions, rather than adding hooks. The `inject` function is pretty
+>>> insane^Wlow level, but seems to work great. --[[Joey]]
+>>>
+>>>> Thanks a lot, it seems to be a nice interface for what I was trying to achieve.
+>>>> I may be forced to wait two long weeks before I have a chance to confirm
+>>>> this. Stay tuned. --[[intrigeri]]
+>>>>
+>>>>> I've updated the plugin to use `inject`. It is now fully self-contained,
+>>>>> and does not modify the core anymore. --[[intrigeri]]
+>>
+>> The Discussion pages issue is something I am not sure about yet. But I will
+>> probably decide that "slave" pages, being only translations, don't deserve
+>> a discussion page: the discussion should happen in the language in which the
+>> pages are written for real, which is the "master" one. --[[intrigeri]]
+>> 
+>> I think that's a good decision, you don't want to translate discussion,
+>> and if the discussion page turns out multilingual, well, se la vi. ;-)
+>> 
+>> Relatedly, what happens if a translated page has a broken link, and you
+>> click on it to edit it? Seems you'd first have to create a master page
+>> and could only then translate it, right? I wonder if this will be clear
+>> though to the user.
+>>
+>>> Right: a broken link points to the URL that allows to create
+>>> a page that can either be a new master page or a non-translatable
+>>> page, depending on `po_translatable_pages` value. The best
+>>> solution I can thing of is to use [[plugins/edittemplate]] to
+>>> insert something like "Warning: this is a master page, that must
+>>> be written in $MASTER_LANGUAGE" into newly created master pages,
+>>> and maybe another warning message on newly created
+>>> non-translatable pages. It seems quite doable to me, but in order
+>>> to avoid breaking existing functionality, it implies to hack a bit
+>>> [[plugins/edittemplate]] so that multiple templates can be
+>>> inserted at page creation time. [[--intrigeri]]
+>>>
+>>>> I implemented such a warning using the formbuilder_setup hook.
+>>>> --[[intrigeri]]
+>>
+>> And also, is there any way to start a translation of a page into a new
+>> lanauge using the web interface?
+>>
+>>> When a new language is added to `po_slave_languages`, a rebuild is
+>>> triggered, and all missing PO files are created and checked into
+>>> VCS. An unpriviledged wiki user can not add a new language to
+>>> `po_slave_languages`, though. One could think of adding the needed
+>>> interface to translate a page into a yet-unsupported slave
+>>> language, and this would automagically add this new language to
+>>> `po_slave_languages`. It would probably be useful in some
+>>> usecases, but I'm not comfortable with letting unpriviledged wiki
+>>> users change the wiki configuration as a side effect of their
+>>> actions; if this were to be implemented, special care would be
+>>> needed. [[--intrigeri]]
+>>>
+>>>> Actually I meant into any of the currently supported languages.
+>>>> I guess that if the template modification is made, it will list those
+>>>> languages on the page, and if a translation to a language is missing,
+>>>> the link will allow creating it?
+>>>>
+>>>>> Any translation page always exist for every supported slave
+>>>>> language, even if no string at all have been translated yet.
+>>>>> This implies the po plugin is especially friendly to people who
+>>>>> prefer reading in their native language if available, but don't
+>>>>> mind reading in English else.
+>>>>>
+>>>>> While I'm at it, there is a remaining issue that needs to be
+>>>>> sorted out: how painful it could be for non-English speakers
+>>>>> (assuming the master language is English) to be perfectly able
+>>>>> to navigate between translation pages supposed to be written in
+>>>>> their own language, when their translation level is most
+>>>>> often low.
+>>>>>
+>>>>> (It is currently easy to display this status on the translation
+>>>>> page itself, but then it's too late, and how frustrating to load
+>>>>> a page just to realize it's actually not translated enough for
+>>>>> you. The "other languages" loop also allows displaying this
+>>>>> information, but it is generally not the primary
+>>>>> navigation tool.)
+>>>>>
+>>>>> IMHO, this is actually a social problem (i.e. it's no use adding
+>>>>> a language to the supported slave ones if you don't have the
+>>>>> manpower to actually do the translations), that can't be fully
+>>>>> solved by technical solutions, but I can think of some hacks
+>>>>> that would limit the negative impact: a given translation's
+>>>>> status (currently = percent translated) could be displayed next
+>>>>> to the link that leads to it; a color code could as well be used
+>>>>> ("just" a matter of adding a CSS id or class to the links,
+>>>>> depending on this variable). As there is already work to be done
+>>>>> to have the links text generation more customizable through
+>>>>> plugins, I could do both at the same time if we consider this
+>>>>> matter to be important enough. --[[intrigeri]]
+>>>>>
+>>>>>> The translation status in links is now implemented in my
+>>>>>> `po`branch. It requires my `meta` branch changes to
+>>>>>> work, though. I consider the latter to be mature enough to
+>>>>>> be merged. --[[intrigeri]]
+
+>> FWIW, I'm tracking your po branch in ikiwiki master git in the po
+>> branch. One thing I'd like to try in there is setting up a translated
+>> basewiki, which seems like it should be pretty easy to do, and would be
+>> a great demo! --[[Joey]]
+>>
+>>> I have a complete translation of basewiki into danish, available merged into
+>>> ikiwiki at git://source.jones.dk/ikiwiki-upstream (branch underlay-da), and am working with
+>>> others on preparing one in german.  For a complete translated user
+>>> experience, however, you will also need templates translated (there are a few
+>>> translatable strings there too).  My most recent po4a Markdown improvements
+>>> adopted upstream but not yet in Debian (see
+>>> [bug#530574](http://bugs.debian.org/530574)) correctly handles multiple
+>>> files in a single PO which might be relevant for template translation handling.
+>>> --[[JonasSmedegaard]]
+>>
+>>> I've merged your changes into my own branch, and made great
+>>> progress on the various todo items. Please note my repository
+>>> location has changed a few days ago, my user page was updated
+>>> accordingly, but I forgot to update this page at the same time.
+>>> Hoping it's not too complicated to relocated an existing remote...
+>>> (never done that, I'm a Git beginner as well as a Perl
+>>> newbie) --[[intrigeri]]
+>>>>
+>>>> Just a matter of editing .git/config, thanks for the heads up.
+>>>>>
+>>>>> Joey, please have a look at my branch, your help would be really
+>>>>> welcome for the security research, as I'm almost done with what
+>>>>> I am able to do myself in this area. --[[intrigeri]]
+>>>>>>
+>>>>>> I came up with a patch for the WrapI18N issue --[[Joey]]
+
+I've set this plugin development aside for a while. I will be back and
+finish it at some point in the first quarter of 2009. --[[intrigeri]]
+
+> Abstract: Joey, please have a look at my po and meta branches.
+> 
+> Detailed progress report:
+> 
+> * it seems the po branch in your repository has not been tracking my
+>   own po branch for two months. any config issue?
+> * all the plugin's todo items have been completed, robustness tests
+>   done
+> * I've finished the detailed security audit, and the fix for po4a
+>   bugs has entered upstream CVS last week
+> * I've merged your new `checkcontent` hook with the `cansave` hook
+>   I previously introduced in my own branch; blogspam plugin updated
+>   accordingly
+> * the rename hook changes we discussed elsewhere are also part of my
+>   branch
+> * I've introduced two new hooks (`canremove` and `canrename`), not
+>   a big deal; IMHO, they extend quite logically the plugin interface
+> * as highlighted on [[bugs/pagetitle_function_does_not_respect_meta_titles]],
+>   my `meta` branch contains a new feature that is really useful in a
+>   translatable wiki
+> 
+> As a conclusion, I'm feeling that my branches are ready to be
+> merged; only thing missing, I guess, are a bit of discussion and
+> subsequent adjustments.
+> 
+> --[[intrigeri]]
+
+> I've looked it over and updated my branch with some (untested)
+> changes.
+> 
+>> I've merged your changes into my branch. Only one was buggy.
+> 
+> Sorry, I'd forgotten about your cansave hook.. sorry for the duplicate
+> work there.
+> 
+> Reviewing the changes, mostly outside of `po.pm`, I have
+> the following issues.
+>  
+> * renamepage to renamelink change would break the ikiwiki
+>   3.x API, which I've promised not to do, so needs to be avoided
+>   somehow. (Sorry, I guess I dropped the ball on not getting this
+>   API change in before cutting 3.0..)
+>> 
+>> Fixed, see [[todo/need_global_renamepage_hook]].
+>>
+> * I don't understand the parentlinks code change and need to figure it
+>   out. Can you explain what is going on there?
+>> 
+>> I'm calling `bestlink` there so that po's injected `bestlink` is
+>> run. This way, the parent links of a page link to the parent page
+>> version in the proper language, depending on the
+>> `po_link_to=current` and `po_link_to=negotiated` settings.
+>> Moreover, when using my meta branch enhancements plus meta title to
+>> make pages titles translatable, this small patch is needed to get
+>> the translated titles into parentlinks.
+>> 
+> * canrename's mix of positional and named parameters is way too
+>   ugly to get into an ikiwiki API. Use named parameters
+>   entirely. Also probably should just use named parameters
+>   for canremove.
+> * `skeleton.pm.example`'s canrename needs fixing to use either
+>   the current or my suggested parameters.
+>> 
+>> Done.
+>> 
+> * I don't like the exporting of `%backlinks` and `$backlinks_calculated`
+>   (the latter is exported but not used).
+>> 
+>> The commit message for 85f865b5d98e0122934d11e3f3eb6703e4f4c620
+>> contains the rationale for this change. I guess I don't understand
+>> the subtleties of `our` use, and perldoc does not help me a lot.
+>> IIRC, I actually did not use `our` to "export" these variables, but
+>> rather to have them shared between `Render.pm` uses.
+>>
+>>> My wording was unclear, I meant exposing. --[[Joey]]
+>>>  
+>>>> I guess I still don't know Perl's `our` enough to understand clearly.
+>>>> No matter whether these variables are declared with `my` or `our`,
+>>>> any plugin can `use IkiWiki::Render` and then access
+>>>> `$IkiWiki::backlinks`, as already does e.g. the pagestat plugin.
+>>>> So I guess your problem is not with letting plugins use these
+>>>> variables, but with them being visible for every piece of
+>>>> (possibly external) code called from `Render.pm`. Am I right?
+>>>> If I understand clearly, using a brace block to lexically enclose
+>>>> these two `our` declarations, alongside with the `calculate_backlinks`
+>>>> and `backlinks` subs definitions, would be a proper solution, wouldn't
+>>>> it? --[[intrigeri]]
+>>>>
+>>>>> No, %backlinks and the backlinks() function are not the same thing.
+>>>>> The variable is lexically scoped; only accessible from inside
+>>>>> `Render.pm` --[[Joey]] 
+>>>> 
+> * What is this `IkiWiki::nicepagetitle` and why are you
+>   injecting it into that namespace when only your module uses it?
+>   Actually, I can't even find a caller of it in your module.
+>> 
+>> I guess you should have a look to my `meta` branch and to
+>> [[bugs/pagetitle_function_does_not_respect_meta_titles]] in order
+>> to understand this :)
+>>
+>>> It would probably be good if I could merge this branch without 
+>>> having to worry about also immediatly merging that one. --[[Joey]] 
+>>> 
+>>>> I removed all dependencies on my `meta` branch from the `po` one.
+>>>> This implied removing the `po_translation_status_in_links` and
+>>>> `po_strictly_refresh_backlinks` features, and every link text is now
+>>>> displayed in the master language. I believe the removed features really
+>>>> enhance user experience of a translatable wiki, that's why I was
+>>>> initially supposing the `meta` branch would be merged first.
+>>>> IMHO, we'll need to come back to this quite soon after `po` is merged.
+>>>> --[[intrigeri]]
+>>>>
+>>>> Maybe you should keep those features in a meta-po branch?
+>>>> I did a cursory review of your meta last night, have some issues with it, 
+>>>> but this page isn't the place for a detailed review. --[[Joey]] 
+>>>>
+>>>>> Done. --[[intrigeri]]
+>>> 
+> * I'm very fearful of the `add_depends` in `postscan`. 
+>   Does this make every page depend on every page that links
+>   to it? Won't this absurdly bloat the dependency pagespecs
+>   and slow everything down? And since nicepagetitle is given
+>   as the reason for doing it, and nicepagetitle isn't used,
+>   why do it?
+>> 
+>> As explained in the 85f865b5d98e0122934d11e3f3eb6703e4f4c620 log:
+>> this feature hits performance a bit. Its cost was quite small in my
+>> real-world use-cases (a few percents bigger refresh time), but
+>> could be bigger in worst cases. When using the po plugin with my
+>> meta branch changes (i.e. the `nicepagetitle` thing), and having
+>> enabled the option to display translation status in links, this
+>> maintains the translation status up-to-date in backlinks. Same when
+>> using meta title to make the pages titles translatable. It does
+>> help having a nice and consistent translated wiki, but as it can
+>> also involve problems, I just turned it into an option.
+>> 
+>>> This has been completely removed for now due to the removal of
+>>> the dependency on my `meta` branch. --[[intrigeri]]
+>> 
+> * The po4a Suggests should be versioned to the first version
+>   that can be used safely, and that version documented in 
+>   `plugins/po.mdwn`.
+>>
+>> Done.
+>> 
+>> --[[intrigeri]]
+> 
+> --[[Joey]] 
+
+I reverted the `%backlinks` and `$backlinks_calculated` exposing.
+The issue they were solving probably will arise again when I'll work
+on my meta branch again (i.e. when the simplified po one is merged),
+but the po thing is supposed to work without these ugly `our`.
+Seems like it was the last unaddressed item from Joey's review, so I'm
+daring a timid "please pull"... or rather, please review again :)
+--[[intrigeri]]
+
+> Ok, I've reviewed and merged into my own po branch. It's looking very
+> mergeable.
+> 
+> * Is it worth trying to fix compatability with `indexpages`?
+>> 
+>> Supporting `usedirs` being enabled or disabled was already quite
+>> hard IIRC, so supporting all four combinations of `usedirs` and
+>> `indexpages` settings will probably be painful. I propose we forget
+>> about it until someone reports he/she badly needs it, and then
+>> we'll see what can be done.
+>> 
+> * Would it make sense to go ahead and modify `page.tmpl` to use
+>   OTHERLANGUAGES and PERCENTTRANSLATED, instead of documenting how to modify it?
+>> 
+>> Done in my branch.
+>> 
+> * Would it be better to disable po support for pages that use unsupported
+>   or poorly-supported markup languages?
+> 
+>> I prefer keeping it enabled, as:
+>> 
+>> * most wiki markups "almost work"
+>> * when someone needs one of these to be fully supported, it's not
+>>   that hard to add dedicated support for it to po4a; if it were
+>>   disabled, I fear the ones who could do this would maybe think
+>>   it's blandly impossible and give up.
+>> 
+> * What's the reasoning behind checking that the link plugin
+>   is enabled? AFAICS, the same code in the scan hook should
+>   also work when other link plugins like camelcase are used.
+>> 
+>> That's right, fixed.
+>> 
+> * In `pagetemplate` there is a comment that claims the code
+>   relies on `genpage`, but I don't see how it does; it seems
+>   to always add a discussion link?
+>> 
+>> It relies on IkiWiki::Render's `genpage` as this function sets the
+>> `discussionlink` template param iff it considers a discussion link
+>> should appear on the current page. That's why I'm testing
+>> `$template->param('discussionlink')`.
+>> 
+>>> Maybe I was really wondering why it says it could lead to a broken
+>>> link if the cgiurl is disabled. I think I see why now: Discussionlink
+>>> will be set to a link to an existing disucssion page, even if cgi is
+>>> disabled -- but there's no guarantee of a translated discussion page
+>>> existing in that case. *However*, htmllink actually checks
+>>> for this case, and will avoid generating a broken link so AFAICS, the
+>>> comment is actually innacurate.. what will really happen in this case
+>>> is discussionlink will be set to a non-link translation of
+>>> "discussion". Also, I consider `$config{cgi}` and `%links` (etc)
+>>> documented parts of the plugin interface, which won't change; po could
+>>> rely on them to avoid this minor problem. --[[Joey]] 
+>>>> 
+>>>> Done in my branch. --[[intrigeri]]
+>>>> 
+>
+> * Is there any real reason not to allow removing a translation?
+>   I'm imagining a spammy translation, which an admin might not
+>   be able to fix, but could remove.
+>> 
+>> On the other hand, allowing one to "remove" a translation would
+>> probably lead to misunderstandings, as such a "removed" translation
+>> page would appear back as soon as it is "removed" (with no strings
+>> translated, though). I think an admin would be in a position to
+>> delete the spammy `.po` file by hand using whatever VCS is in use.
+>> Not that I'd really care, but I am slightly in favour of the way
+>> it currently works.
+>>
+>>> That would definitly be confusing. It sounds to me like if we end up
+>>> needing to allow web-based deletion of spammy translations, it will
+>>> need improvements to the deletion UI to de-confuse that. It's fine to
+>>> put that off until needed --[[Joey]] 
+>> 
+> * Re the meta title escaping issue worked around by `change`. 
+>   I suppose this does not only affect meta, but other things
+>   at scan time too. Also, handling it only on rebuild feels
+>   suspicious -- a refresh could involve changes to multiple
+>   pages and trigger the same problem, I think. Also, exposing
+>   this rebuild to the user seems really ugly, not confidence inducing.
+>   
+>   So I wonder if there's a better way. Such as making po, at scan time,
+>   re-run the scan hooks, passing them modified content (either converted
+>   from po to mdwn or with the escaped stuff cheaply de-escaped). (Of
+>   course the scan hook would need to avoid calling itself!)
+> 
+>   (This doesn't need to block the merge, but I hope it can be addressed
+>   eventually..)
+>  
+> --[[Joey]] 
+>> 
+>> I'll think about it soon.
+>> 
+>> --[[intrigeri]]
+>>
+>>> Did you get a chance to? --[[Joey]] 
+
+ * As discussed at [[todo/l10n]] the templates needs to be translatable too.  They
+   should be treated properly by po4a using the markdown option - at least with my
+   later patches in [bug#530574](http://bugs.debian.org/530574)) applied.
+
+ * It seems to me that the po plugin (and possibly other parts of ikiwiki) wrongly
+   uses gettext.  As I understand it, gettext (as used currently in ikiwiki) always
+   lookup a single language, That might make sense for a single-language site, but
+   multilingual sites should emit all strings targeted at the web output in each own
+   language.
+
+   So generally the system language (used for e.g. compile warnings) should be separated
+   from both master language and slave languages.
+
+   Preferrably the gettext subroutine could be extended to pass locale as optional
+   secondary parameter overriding the default locale (for messages like "N/A" as
+   percentage in po plugin).  Alternatively (with above mentioned template support)
+   all such strings could be externalized as templates that can then be localized.
+
+# Robustness tests
+
+### Enabling/disabling the plugin
+
+* enabling the plugin with `po_translatable_pages` set to blacklist: **OK**
+* enabling the plugin with `po_translatable_pages` set to whitelist: **OK**
+* enabling the plugin without `po_translatable_pages` set: **OK**
+* disabling the plugin: **OK**
+
+### Changing the plugin config
+
+* adding existing pages to `po_translatable_pages`: **OK**
+* removing existing pages from `po_translatable_pages`: **OK**
+* adding a language to `po_slave_languages`: **OK**
+* removing a language from `po_slave_languages`: **OK**
+* changing `po_master_language`: **OK**
+* replacing `po_master_language` with a language previously part of
+  `po_slave_languages`: needs two rebuilds, but **OK** (this is quite
+  a perverse test actually)
+
+### Creating/deleting/renaming pages
+
+All cases of master/slave page creation/deletion/rename, both via RCS
+and via CGI, have been tested.
+
+### Misc
+
+* general test with `usedirs` disabled: **OK**
+* general test with `indexpages` enabled: **not OK**
+* general test with `po_link_to=default` with `userdirs` enabled: **OK**
+* general test with `po_link_to=default` with `userdirs` disabled: **OK**
+
+Duplicate %links ?
+------------------
+
+I notice code in the scan hook that seems to assume
+that %links will accumulate duplicate links for a page.
+That used to be so, but the bug was fixed. Does this mean
+that po might be replacing the only link on a page, in error? 
+--[[Joey]] 
+
+> It would replace it. The only problematic case is when another
+> plugin has its own reasons, in its `scan` hook, to add a page
+> that is already there to `$links{$page}`. This other plugin's
+> effect might then be changed by po's `scan` hook... which could
+> be either good (better overall l10n) or bad (break the other
+> plugin's goal). --[[intrigeri]]
+
+>> Right.. well, the cases where links are added is very small.
+>> Grepping for `add_link`, it's just done by link, camelcase, meta, and
+>> tag. All of these are supposed to work just link regular links
+>> so I'd think that is ok. We could probably remove the currently scary
+>> comment about only wanting to change the first link. --[[Joey]] 
+
+>>> Commit 3c2bffe21b91684 in my po branch does this. --[[intrigeri]]
+>>>> Cherry-picked --[[Joey]] 
index 94d5fa339c19664b18d58e1a507bb8a8f4484463..510f67798caf22183fd0dccf489022b9b4eb784f 100644 (file)
@@ -1,24 +1,5 @@
-[[template id=plugin name=poll author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=poll author="[[Joey]]"]]
+[[!tag type/web]]
 
-This plugin allows you to create online polls in the wiki. Here's an
-example use:
-
-       \[[poll 0 "red" 0 "green" 0 "blue"]]
-
-The numbers indicate how many users voted for that choice. When a user
-votes for a choice in the poll, the page is modified and the number
-incremented.
-
-While some basic precautions are taken to prevent users from accidentially
-voting twice, this sort of poll should not be counted on to be very
-accurate; all the usual concerns about web based polling apply. Unless the
-page that the poll is in is locked, users can even edit the page and change
-the numbers!
-
-Parameters: 
-
-* `open` - Whether voting is still open. Set to "no" to close the poll to
-  voting.
-* `total` - Show total number of votes at bottom of poll. Default is "yes".
-* `percent` - Whether to display percents. Default is "yes".
+This plugin provides the [[ikiwiki/directive/poll]] [[ikiwiki/directive]],
+which allows inserting an online poll into a page.
index 8d6794073ae9063d4c2f759466c722e331decf19..6045c1ec91dc23f99c737b622fb2846a672f26bf 100644 (file)
@@ -1,29 +1,24 @@
-[[template id=plugin name=polygen author="Enrico Zini"]]
-[[tag type/fun]]
+[[!template id=plugin name=polygen author="Enrico Zini"]]
+[[!tag type/fun]]
 
-This plugin allows inserting text generated by polygen into a wiki page.
-For example:
+This plugin provides the [[ikiwiki/directive/polygen]] [[ikiwiki/directive]],
+which allows inserting text generated by polygen into a wiki page.
 
-       \[[polygen grammar="genius"]]
-
-It's also possible to specify a starting nonterminal for the grammar by
-including `symbol="text"` in the directive.
-
-[[if test="enabled(polygen)" then="""
+[[!if test="enabled(polygen)" then="""
 ----
 
 Here are a few notes about ikiwiki, courtesy of polygen:
 
-Ikiwiki is internally based on a [[polygen grammar="designpatterns"]]
-coupled to a [[polygen grammar="designpatterns"]], as described in
-"[[polygen grammar="paper"]]" by [[polygen grammar="nipponame"]] of
-[[polygen grammar="boyband"]].
+Ikiwiki is internally based on a [[!polygen grammar="designpatterns"]]
+coupled to a [[!polygen grammar="designpatterns"]], as described in
+"[[!polygen grammar="paper"]]" by [[!polygen grammar="nipponame"]] of
+[[!polygen grammar="boyband"]].
 
 Ikiwiki reviews:
 <ul>
-<li>[[polygen grammar="reviews"]]</li>
-<li>[[polygen grammar="reviews"]]</li>
-<li>[[polygen grammar="reviews"]]</li>
+<li>[[!polygen grammar="reviews"]]</li>
+<li>[[!polygen grammar="reviews"]]</li>
+<li>[[!polygen grammar="reviews"]]</li>
 </ul>
 
 """]]
index d716022e1e6c85cc37953d938a6b1bd446450bd8..c81f91bdc51d46dfecffb8550a53edd3af88322a 100644 (file)
@@ -1,48 +1,10 @@
-[[template id=plugin name=postsparkline author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=postsparkline author="[[Joey]]"]]
+[[!tag type/chrome]]
 
-This plugin uses the [[sparkline]] plugin to create a sparkline of
+This plugin provides the [[ikiwiki/directive/postsparkline]] [[ikiwiki/directive]].
+It uses the [[sparkline]] plugin to create a sparkline of
 statistics about a set of pages, such as posts to a blog.
 
-# examples
-
-       Post interval: 
-       \[[postsparkline pages="blog/* and !*/Discussion" max=100
-       formula=interval style=bar barwidth=2 barspacing=1 height=13]]
-       
-       Posts per month this year: 
-       \[[postsparkline pages="blog/* and !*/Discussion" max=12
-       formula=permonth style=bar barwidth=2 barspacing=1 height=13]]
-
-# usage
-
-All options aside fron the `pages`, `max`, `formula`, `time`, and `color`
-options are passed on to the sparkline plugin.
-
-You don't need to specify any data points (though you can if you want to).
-Instead, data points are automatically generated based on the creation
-times of pages matched by the specified `pages` [[ikiwiki/PageSpec]]. A
-maximum of `max` data points will be generated.
-
-The `formula` parameter controls the formula used to generate data points.
-Available forumlae:
-
-* `interval` - The height of each point represents how long it has been
-  since the previous post.
-* `perday` - Each point represents a day; the height represents how
-  many posts were made that day.
-* `permonth` - Each point represents a month; the height represents how
-  many posts were made that month.
-* `peryear` - Each point represents a day; the height represents how
-  many posts were made that year.
-
-The `time` parameter has a default value of "ctime", since forumae use
-the creation times of pages by default. If you instead want
-them to use the modification times of pages, set it to "mtime".
-
-To change the color used to draw the sparkline, use the `color` parameter.
-For example, "color=red".
-
 # adding formulae
 
 Additional formulae can be added without modifying this plugin by writing
index 49feaa8e63ec764a87d8fc3a39ee0cf604aafb68..11ad4252fb16b1862b1a0bb0474de957eb5ec350 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=prettydate author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=prettydate author="[[Joey]]"]]
+[[!tag type/date]]
 
 Enabling this plugin changes the dates displayed on pages in the wiki to
 a format that is nice and easy to read. Examples: "late Wednesday evening, 
@@ -16,4 +16,4 @@ The format used for the date can be customised using the `prettydateformat`
 configuration variable in the setup file. `%X` will be expanded to the
 prettified time value. The default prettydateformat is `"%X, %B %o, %Y"`.
 
-This plugin uses the [[cpan TimeDate]] perl module.
+This plugin uses the [[!cpan TimeDate]] perl module.
diff --git a/doc/plugins/progress.mdwn b/doc/plugins/progress.mdwn
new file mode 100644 (file)
index 0000000..e1b560c
--- /dev/null
@@ -0,0 +1,5 @@
+[[!template id=plugin name=progress author="[[Will]]"]]
+[[!tag type/meta]]
+
+This plugin provides the [[ikiwiki/directive/progress]]
+[[ikiwiki/directive]], which generates a progress bar.
index 237fb1db68798a9fbd2c91ca08ed3dff228b2e2d..3b2d3d06cc3aa5f7fb33223dcf941e375906adb3 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=rawhtml author="[[Joey]]"]]
-[[tag type/html type/format]]
+[[!template id=plugin name=rawhtml author="[[Joey]]"]]
+[[!tag type/html type/format]]
 
 This plugin changes how ikiwiki handles html files, making it treat html
 or xhtml files not as source files but as data files that are copied
index b48dcbacfb55353d4dacc23ea3cabab1f42ea5a5..9375296a4d81158f737a59f408b66ab124372885 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=recentchanges core=1 author="[[Joey]]"]]
+[[!template id=plugin name=recentchanges core=1 author="[[Joey]]"]]
 
 This plugin examines the [[revision_control_system|rcs]] history and
 generates a page describing each recent change made to the wiki. These
@@ -8,19 +8,22 @@ pages can be joined together with [[inline]] to generate the
 Typically only the RecentChanges page will use the pages generated by this
 plugin, but you can use it elsewhere too if you like. It's used like this:
 
-       \[[inline pages="internal(recentchanges/change_*)"
+       \[[!inline pages="internal(recentchanges/change_*)"
        template=recentchanges show=0]]
 
 Here's an example of how to show only changes to "bugs/*".
 This matches against the title of the change, which includes a list of
 modified pages.
 
-       \[[inline pages="internal(recentchanges/change_*) and title(*bugs/*)"
+       \[[!inline pages="internal(recentchanges/change_*) and title(*bugs/*)"
        template=recentchanges show=0]]
 
 Here's an example of how to show only changes that Joey didn't make.
 (Joey commits sometimes as user `joey`, and sometimes via openid.)
        
-       \[[inline pages="internal(recentchanges/change_*) and
+       \[[!inline pages="internal(recentchanges/change_*) and
        !author(joey) and !author(http://joey.kitenet.net*)"
        template=recentchanges show=0]]
+
+If you want to generate feeds for the RecentChanges page, you have to use
+[[`rss`_or_`atom`_in_the_setup_file|/todo/minor adjustment to setup documentation for recentchanges feeds]].
index f805eabe106e9d122be432acf3c03a7ffa4d124e..a7b113ade60fc2ab6176c4028baf9c4c4383f4c7 100644 (file)
@@ -1,4 +1,4 @@
-[[template id=plugin name=recentchangesdiff core=0 author="[[Joey]]"]]
+[[!template id=plugin name=recentchangesdiff core=0 author="[[Joey]]"]]
 
 This plugin extends the [[recentchanges]] plugin, adding a diff for each
 change. The diffs are by default hidden from display on the recentchanges
diff --git a/doc/plugins/relativedate.mdwn b/doc/plugins/relativedate.mdwn
new file mode 100644 (file)
index 0000000..3ada086
--- /dev/null
@@ -0,0 +1,16 @@
+[[!template id=plugin name=relativedate author="[[Joey]]"]]
+[[!tag type/date]]
+
+This plugin lets dates be displayed in relative form. Examples: "2 days ago", 
+"1 month and 3 days ago", "30 minutes ago". Hovering over the date will
+cause a tooltip to pop up with the absolute date.
+
+This only works in browsers with javascript enabled; other browsers will
+show the absolute date instead. Also, this plugin can be used with other
+plugins like [[prettydate]] that change how the absolute date is displayed.
+
+If this plugin is enabled, you may also add relative dates to pages in the
+wiki, by using html elements in the "relativedate" class. For example, this
+will display as a relative date:
+
+       <span class="relativedate">Tue Jan 20 12:00:00 EDT 2009</span>
diff --git a/doc/plugins/remove.mdwn b/doc/plugins/remove.mdwn
new file mode 100644 (file)
index 0000000..47993f4
--- /dev/null
@@ -0,0 +1,7 @@
+[[!template id=plugin name=remove core=0 author="[[Joey]]"]]
+[[!tag type/web]]
+
+This plugin allows pages or other files to be removed using the web
+interface.
+
+Users can only remove things that they are allowed to edit or upload.
diff --git a/doc/plugins/rename.mdwn b/doc/plugins/rename.mdwn
new file mode 100644 (file)
index 0000000..ddaede8
--- /dev/null
@@ -0,0 +1,11 @@
+[[!template id=plugin name=rename core=0 author="[[Joey]]"]]
+[[!tag type/web]]
+
+This plugin allows pages or other files to be renamed using the web
+interface.
+
+Users can only rename things that they are allowed to edit or upload.
+
+It attempts to fix up links to renamed pages, and if some links cannot be
+fixed up, the pages that contain the broken links will be displayed after
+the rename.
diff --git a/doc/plugins/repolist.mdwn b/doc/plugins/repolist.mdwn
new file mode 100644 (file)
index 0000000..9b3a757
--- /dev/null
@@ -0,0 +1,17 @@
+[[!template id=plugin name=repolist author="[[Joey]]"]]
+[[!tag type/useful]]
+
+This plugin allows you to configure ikiwiki with the location of
+[[rcs]] repositories for your wiki's source. This is done via the
+"repositories" setting in the setup file. Once you tell it where the source
+to your wiki can be downloaded from, this information can be published on
+your wiki in various ways.
+
+This plugin supports the [rel-vcs-*](http://kitenet.net/~joey/rfc/rel-vcs/)
+microformat, and uses it to embed the repository location information in
+every wiki page.
+
+By using this plugin, you will make [[Joey]] very happy, as he will be able
+to easily check out the source of your wiki, for purposes of debugging and
+general curiosity. More generally, making it easy for others to find the
+repository for your wiki is just a Plain Good Idea(TM).
index 49dd81e70718224a605f3cc7380dc945416485ea..5e97e2d8058391ec39cb7a493c3a4a6e1a219732 100644 (file)
@@ -1,9 +1,9 @@
-[[template id=plugin name=rst author="martin f. krafft"]]
-[[tag type/format]]
+[[!template id=plugin name=rst author="martin f. krafft"]]
+[[!tag type/format]]
 
 This plugin lets ikwiki convert files with names ending in ".rst" to html.
 It uses the [reStructuredText](http://docutils.sourceforge.net/rst.html)
-markup syntax. You need to have [[cpan RPC::XML]], python and the
+markup syntax. You need to have [[!cpan RPC::XML]], python and the
 python-docutils module installed to use it.
 
 Note that this plugin does not interoperate very well with the rest of
@@ -11,7 +11,7 @@ ikiwiki. Limitations include:
 
 * There are issues with inserting raw html into documents, as ikiwiki 
   does with [[WikiLinks|ikiwiki/WikiLink]] and many 
-  [[PreprocessorDirectives|ikiwiki/PreprocessorDirective]].
+  [[directives|ikiwiki/directive]].
 
 So while you may find this useful for importing old files into your wiki,
 using this as your main markup language in ikiwiki isn't recommended at
index a792b670f7cf0fd63008804e40aef95c6a4df460..9909784d54ca2ce092841fe9ea0413fec75de911 100644 (file)
@@ -29,4 +29,15 @@ An exhaustive list of differences between prest and "standard" reST follows:
 * csv directive doesn't require csv.py
 * references directive doesn't allow options
 
-There may be a few others; my eyes glazed over. --Ethan
\ No newline at end of file
+There may be a few others; my eyes glazed over. --Ethan
+
+rst support for ikiwiki seems to be on hold. rst is much more elegant
+than markdown in my opinion, so I tried it out in ikiwiki. I found out
+in other places that some directives work just fine, like [[meta]] and
+[[tag]], others work fine if you wrap them in `.. raw::`, like [[inline]].
+
+But to make a wiki we need [[WikiLinks]]; they can't be escape-inserted or
+such since they are inline elements in the text.. But images work fine in
+rst's syntax.. what about using rst syntax for wikilinks as well?
+Is it possible to inject something into the parser to turn unmached links
+``WikiLink`_` into ikiwiki links? --ulrik
index 9336b240353ab3c0061fdffb2977e19fbd9bdcfa..92cc5945a27489c9118e272582bd15651456c3dd 100644 (file)
@@ -1,10 +1,10 @@
-[[template id=plugin name=search author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=search author="[[Joey]]"]]
+[[!tag type/web]]
 
 This plugin adds full text search to ikiwiki, using the
 [xapian](http://xapian.org/) engine, its
 [omega](http://xapian.org/docs/omega/overview.html) frontend, and the
-[[cpan Search::Xapian]], [[cpan Digest::SHA1]], and [[cpan HTML::Scrubber]]
+[[!cpan Search::Xapian]], [[!cpan Digest::SHA1]], and [[!cpan HTML::Scrubber]]
 perl modules.
 
 The [[ikiwiki/searching]] page describes how to write search queries.
index 8a31a9bd164c552cbe42e76c2f289c72408890e8..cca1f4bdd18d4875074a058b061945971c549020 100644 (file)
@@ -1,7 +1,8 @@
-[[template id=plugin name=shortcut author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=shortcut author="[[Joey]]"]]
+[[!tag type/format]]
 
-This plugin allows external links to commonly linked to sites to be made
+This plugin provides the [[ikiwiki/directive/shortcut]] [[ikiwiki/directive]].
+It allows external links to commonly linked to sites to be made
 more easily using shortcuts.
 
 The available shortcuts are defined on the [[shortcuts]] page in
index 8b137891791fe96927ad78e64b0aad7bded08bdc..4e11ce08c04230b8d3abdcec2980f7b2f0901c92 100644 (file)
@@ -1 +1,12 @@
+The plugin depends on [[mdwn]].  If you have
+disabled [[mdwn]], to get [[shortcut]] work, you need
+commit in a shortcuts.ext (ext is `rcs|creole|html|txt|etc`),
+and edit/patch [[shortcut]].
+
+Maybe use the `default_pageext` is better than hardcode .mdwn?
+
+--[[weakish]]
+
+> done, it will use `default_pageext` now --[[Joey]] 
+
 
index 9ddfa19fb42b1d0c009ef2b671714c961688d027..36982eff386a31e91eaa3fade012795bb9fd61c1 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=sidebar author="Tuomo Valkonen"]]
-[[tag type/chrome]]
+[[!template id=plugin name=sidebar author="Tuomo Valkonen"]]
+[[!tag type/chrome]]
 
 If this plugin is enabled, then a sidebar is added to pages in the wiki.
 The content of the sidebar is simply the content of a page named
index 525a90fe8fe44575cded9ae800e39d8ab3226b0f..814ab55086ba216909455d3f5948f5fe24f16233 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=signinedit core=1 author="[[Joey]]"]]
-[[tag type/auth]]
+[[!template id=plugin name=signinedit core=1 author="[[Joey]]"]]
+[[!tag type/auth]]
 
 This plugin, which is enabled by default, requires users be logged in
 before editing pages in the wiki.
index 4e03f09e4e61a74b9d7005fca0b6d6823e63d88c..e4153c612b6dc6bbd8a77948ed068fe943a5413b 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=smiley author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=smiley author="[[Joey]]"]]
+[[!tag type/chrome]]
 
 This plugin makes it easy to insert smileys and other special symbols into
 pages in the wiki. The symbols are all listed on the [[smileys]] page,
index 9a5d0eb74b99d33ee8e6f5fd72c0e8a6942995de..bcc5daec60668443444f6f55a48bb9d2f11a6614 100644 (file)
@@ -1,9 +1,10 @@
-[[template id=plugin name=sparkline author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=sparkline author="[[Joey]]"]]
+[[!tag type/chrome]]
 
-This plugin allows for easily embedding sparklines into wiki pages. A
-sparkline is a small word-size graphic chart, that is designed to be
-inlined alongside text.
+This plugin provides the [[ikiwiki/directive/sparkline]]
+[[ikiwiki/directive]], which allows for easily embedding sparklines into
+wiki pages. A sparkline is a small word-size graphic chart, that is designed
+to be displayed alongside text.
 
 # requirements
 
@@ -15,62 +16,7 @@ to use the plugin, you will need:
   php can find it when `sparkline/Sparkline.php` is required.
 * The GD PHP module used by the Sparkline library.
 * A "php" program in the path, that can run standalone php programs.
-* [[cpan Digest::SHA1]]
+* [[!cpan Digest::SHA1]]
 
 On a Debian system, this can be accomplished by installing these packages:
 `libsparkline-php` `php5-gd` `php5-cli` `libdigest-sha1-perl`
-
-This plugin also uses the [[cpan Digest::SHA1]] perl module.
-
-# examples
-
-       \[[sparkline 1 3 5 -3 10 0 width=40 height=16
-       featurepoint="4,-3,red,3" featurepoint="5,10,green,3"]]
-
-This creates a simple line graph, graphing several points.
-[[if test="enabled(sparkline)" then="""
-[[sparkline 1 3 5 -3 10 0 width=40 height=16
-featurepoint="4,-3,red,3" featurepoint="5,10,green,3"]]
-"""]]
-It will be drawn 40 pixels wide and 16 pixels high. The high point in the
-line has a green marker, and the low point has a red marker.
-
-       \[[sparkline 1 -1(red) 1 -1(red) 1 1 1 -1(red) -1(red) style=bar barwidth=2
-       barspacing=1 height=13]]
-
-This more complex example generates a bar graph. 
-[[if test="enabled(sparkline)" then="""
-[[sparkline 1 -1(red) 1 -1(red) 1 1 1 -1(red) -1(red)
-style=bar barwidth=2 barspacing=1 height=13]]
-"""]]
-The bars are 2 pixels wide, and separated by one pixel, and the graph is 13
-pixels tall. Width is determined automatically for bar graphs. The points
-with negative values are colored red, instead of the default black.
-
-# usage
-
-The form for the data points is "x,y", or just "y" if the x values don't
-matter. Bar graphs can also add "(color)" to specify a color for that bar.
-
-The following named parameters are recognised. Most of these are the same
-as those used by the underlying sparkline library, which is documented in
-more detail in [its wiki](http://sparkline.wikispaces.com/usage).
-
-* `style` - Either "line" (the default) or "bar".
-* `width` - Width of the graph in pixels. Only needed for line graphs.
-* `height` - Height of the graph in pixels. Defaults to 16.
-* `barwidth` - Width of bars in a bar graph. Default is 1 pixel.
-* `barspacing` - Spacing between bars in a bar graph, in pixels. Default is
-  1 pixel.
-* `ymin`, `ymax` - Minimum and maximum values for the Y axis. This is
-  normally calculated automatically, but can be explicitly specified to get
-  the same values for multiple related graphs.
-* `featurepoint` - Adds a circular marker to a line graph, with optional
-  text. This can be used to label significant points.
-  
-  The value is a comma-delimited list of parameters specifying the feature
-  point: X value, Y value, color name, circle diameter, text (optional),
-  and text location (optional). Example: `featurepoint="3,5,blue,3"`
-  
-  Available values for the text location are: "top", "right", "bottom", and
-  "left".
index 6920c8f8080e53175afc9ccb5ab3c70519564a72..7b080acdaffceca13c8e31420ddb0c1fa10cdfc2 100644 (file)
@@ -1,45 +1,8 @@
-[[template id=plugin name=table author="[[VictorMoral]]"]]
-[[tag type/format]]
+[[!template id=plugin name=table author="[[VictorMoral]]"]]
+[[!tag type/format]]
 
-This plugin can build HTML tables from data in CSV (comma-separated values)
+This plugin provides the [[ikiwiki/directive/table]] [[ikiwiki/directive]].
+It can build HTML tables from data in CSV (comma-separated values)
 or DSV (delimiter-separated values) format.
 
-It needs the perl module [[cpan Text::CSV]] for the CSV data.
-
-## examples
-
-       \[[table data="""
-       Customer|Amount
-       Fulanito|134,34
-       Menganito|234,56
-       Menganito|234,56
-       """]]
-    
-       \[[table class="book_record" format=csv file="data/books/record1"]]
-
-In this second example the `record1` page should be similar to:
-
-       "Title","Perl Best Practices"
-       "Author","Damian Conway"
-       "Publisher","O’Reilly"
-
-To make a cell span multiple columns, follow it with one or more empty
-cells. For example:
-
-       \[[table data="""
-       left||right|
-       a|b|c|d
-       this cell spans 4 columns|||
-       """]]
-
-## usage
-
-* `data` - Values for the table.
-* `file` - A file in the wiki containing the data.
-* `format` - The format of the data, either "csv", "dsv", or "auto"
-  (the default).
-* `delimiter` - The character used to separate fields. By default,
-   DSV format uses a pipe (`|`), and CSV uses a comma (`,`).
-* `class` - A CSS class for the table html element.
-* `header` - Set to "no" to make a table without a header. By default,
-  the first data line is used as the table header.
+It needs the perl module [[!cpan Text::CSV]] for the CSV data.
index 79a89d8a7cf99272652072c3605c97e742a53c2c..16e5a5a56e058e8d3415349c586e2649f1475856 100644 (file)
@@ -18,9 +18,49 @@ In my version, there is three options for the header field :
 
 Here is the links to the patch and to a patched version of the plugin :
 
-+ [table.pm.patch](http://lohrun.free.fr/ikiwiki/table.pm.patch)
-+ [table.pm](http://lohrun.free.fr/ikiwiki/table.pm)
++ [table.pm.patch](http://alexandre.dupas.free.fr/code/ikiwiki/table.pm.patch)
++ [table.pm](http://alexandre.dupas.free.fr/code/ikiwiki/table.pm)
 
 I hope this might be intresting for some ikiwiki user's.
 
 --[[AlexandreDupas]]
+
+> Thanks for the patch, I've merged it in.
+> (Just FYI, in future, I recommend using a unified diff. Also, not
+> renaming variables that don't really need to be renamed makes your patch
+> easier to apply.) --[[Joey]]
+
+---
+
+# Horizontal cell alignment
+
+Do you know any easy method of horizontal cell alignment? I know I can set `class`
+attribute for the table, but how to set different `class` for different cells?
+
+[DokuWiki](http://www.dokuwiki.org/) has a nice horizontal alignment solution.
+Suppose that we have `|foo|` cell. If I want to align the cell to left,
+then I should type `|foo |`. If I want to do right alignment, then I type `| foo|`.
+For centering cell content I need to type `| foo |`. Please note that I used
+only one space for all examples, but in DokuWiki I can use many spaces.
+
+Do you like it? Can you implement the same in Ikiwiki? :) --[[Paweł|ptecza]]
+
+> Multimarkdown has [table support](http://fletcherpenney.net/multimarkdown/users_guide/multimarkdown_syntax_guide/#tables)
+> that includes alignment. (Using colons to control it.) So you can turn on
+> `multimarkdown` in setup to use that.
+> 
+> I'd not mind if someone adds alignment to this plugin. Although the
+> universe of possible table formatting stuff is nearly endless, and at
+> some point it becomes clearer and simpler to just write the table in
+> html.. --[[Joey]]
+
+>> Thanks a lot for the info about Multimarkdown! It seems very interesting.
+
+>> I'll look at that plugin and try to add that feature, if it's not
+>> too hard.
+
+>> I know that people have many ideas how to format their tables
+>> and it's not easy to create universal tool. Of course `table` plugin
+>> was written rather for simple usage. However cell alignment is very
+>> helpful feature, so I think the plugin should be able to do it.
+>> --[[Paweł|ptecza]]
index edae03887727737bff0812faf2a7739b52e89675..8ff70a069ce666cc9fc909878b2a7e93518d8296 100644 (file)
@@ -1,30 +1,14 @@
-[[template id=plugin name=tag author="[[Joey]]"]]
-[[tag type/tags type/link]]
+[[!template id=plugin name=tag author="[[Joey]]"]]
+[[!tag type/tags type/link]]
 
-This plugin allows tagging pages. List tags as follows:
+This plugin provides the [[ikiwiki/directive/tag]] and 
+[[ikiwiki/directive/taglink]] [[directives|ikiwiki/directive]].
+These directives allow tagging pages.
 
-       \[[tag tech life linux]]
+It also provides the `tagged()` [[ikiwiki/PageSpec]], which can be used to
+match pages that are tagged with a specific tag.
 
-The tags work the same as if you had put a (hidden) [[ikiwiki/WikiLink]] on
-the page for each tag, so you can use a [[ikiwiki/PageSpec]] match all
-pages that are tagged with a given tag, for example. The tags will also
-show up on blog entries and at the bottom of the tagged pages, as well as
-in RSS and Atom feeds.
-
-If you want a visible [[ikiwiki/WikiLink]] along with the tag, use taglink
-instead:
-
-       \[[taglink foo]]
-       \[[taglink tagged_as_foo|foo]]
-
-This plugin has a configuration option. Set --tagbase=tags and links to tags
-will be located under the specified base page. If ikiwiki is configured
-this way, then the example above actually tags the page with the tags
-tags/tech, tags/life, and tags/linux. This is a useful way to avoid
-having to write the full path to tags, if you want to keep them grouped
-together out of the way.
-
-[[if test="enabled(tag)" then="""
+[[!if test="enabled(tag)" then="""
 This wiki has the tag plugin enabled, so you'll see a note below that this
 page is tagged with the "tags" tag.
 """]]
index 7e830fc131025d8d57174b91ad489a79f8fd5b48..b6dab5358a90d14d79038e8c13bbe9a5cfe1fa1b 100644 (file)
@@ -1,4 +1,4 @@
-I'd like to modify this plugin such that the tag pages are automatically created and populated with a list of relevant posts. The content of the tag page is simply `"\[[inline pages="link(tag/$tag)"]]`. The tag plugin will have to determine whether a page for the given tag already exists, and if not use that Markdown fragment to  generate it.
+I'd like to modify this plugin such that the tag pages are automatically created and populated with a list of relevant posts. The content of the tag page is simply `"\[[!inline pages="link(tag/$tag)"]]`. The tag plugin will have to determine whether a page for the given tag already exists, and if not use that Markdown fragment to  generate it.
 
 There are clearly many ways to do this, but any opinions on which is the cleanest?
 
@@ -22,3 +22,9 @@ AOLMODE=true echo "I too would really like this feature, which would make cgi fr
 better" --[[DavidBremner]]
 
 Please make the actual text used a template some way or another. I may want `map` instead of `inline`. --[[madduck]]
+
+
+See [[todo/auto-create tag pages according to a template]]
+
+-- Jeremy Schultz <jeremy.schultz@uleth.ca>
+
index daa2403ccd0d6099cae941702ffd20ab66561dce..3485fe64ce51953438ec661ec3276ee56572d267 100644 (file)
@@ -1,6 +1,7 @@
-[[template id=plugin name=template author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=template author="[[Joey]]"]]
+[[!tag type/format]]
 
+This plugin provides the [[ikiwiki/directive/template]] [[ikiwiki/directive]].
 With this plugin, you can set up templates, and cause them to be filled out
 and inserted into pages in the wiki. It's documented and existing templates
 are listed in the [[templates]] page.
index 9a13ab5909f462f53f1c221efaa22ba48dc7aff0..dabcb0becd9c68410d9a285cbcf0a17dba936728 100644 (file)
@@ -1,23 +1,6 @@
-[[template id=plugin name=testpagespec author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=testpagespec author="[[Joey]]"]]
+[[!tag type/useful]]
 
-This plugin allows testing a [[ikiwiki/PageSpec]] to see if it matches a
+This plugin provides a [[ikiwiki/directive/testpagespec]] [[ikiwiki/directive]].
+The directive allows testing a [[ikiwiki/PageSpec]] to see if it matches a
 page, and to see the part that matches, or causes the match to fail.
-
-Example uses:
-
-       \[[testpagespec pagespec="foopage and barpage" match="foopage"]]
-
-This will print out something like "no match: barpage does not match
-foopage", highlighting which part of the [[ikiwiki/PageSpec]] is causing
-the match to fail.
-       
-       \[[testpagespec pagespec="foopage or !bar*" match="barpage"]]
-
-This will print out something like "no match: bar* matches barpage", since
-the part of the [[ikiwiki/PageSpec]] that fails is this negated match.
-       
-       \[[testpagespec pagespec="foopage or barpage" match="barpage"]]
-
-This will print out something like "match: barpage matches barpage",
-indicating the part of the [[ikiwiki/PageSpec]] that caused it to match.
index 588bf540777907d506aa7ff5cd90c27a1e06adab..ae052837fa6fecf88303730ba28bb7519ea458f4 100644 (file)
@@ -1,29 +1,18 @@
-[[template id=plugin name=teximg author="[[PatrickWinnertz]]"]]
-[[tag type/chrome type/slow]]
+[[!template id=plugin name=teximg author="[[PatrickWinnertz]]"]]
+[[!tag type/chrome type/slow]]
 
-This plugin renders LaTeX formulas into images.
+This plugin provides a [[ikiwiki/directive/teximg]] [[ikiwiki/directive]],
+that renders LaTeX formulas into images.
 
-Of course you will need LaTeX installed for this to work. The plugin
-also uses mhchem.sty, which in Debian is in the texlive-science package and
-may not be part of a regular texlive installation.
+Of course you will need LaTeX installed for this to work.
 
-## examples
+See [this site](http://www.der-winnie.de/opensource/gsoc2007) for rendered
+images.
 
-       \[[teximg code="\ce{[Cu(NH3)3]^{2+}}"]]
-       \[[teximg code="\frac{1}{2}"]]
-       \[[teximg code="E = - \frac{Z^2 \cdot  \mu \cdot e^4}{32\pi^2 \epsilon_0^2 \hbar^2 n^2}" ]]
+## configuration
 
-To scale the image, use height=x:
-
-       \[[teximg code="\ce{[Cu(NH3)3]^{2+}}" height="17"]]
-       \[[teximg code="\ce{[Cu(NH3)3]^{2+}}" height="8"]]
-
-If no height is choosen the default height 12 is used. Valid heights are: 8, 9,
-10, 11, 12, 14, 17, 20. If another height is entered, the closest available
-height is used.
-
-To add an alt text to the image, use alt="text":
-
-       \[[teximg code="\frac{1}{2}" alt="1/2"]]
-
-See [this site](http://www.der-winnie.de/opensource/gsoc2007) for rendered images.
+There are several configuration directives that can be used in the setup
+file. `teximg_prefix` can be set to change the LaTeX preamble, and
+`teximg_postfix` to change the LaTeX postfix. The `teximg_dvipng` setting
+can be set to 0 to disable use of `dvipng`, and instead force use of `dvips`
+and `convert`.
index c32b55e4b4c45cd8f5a4caeb36227019d364dc51..4ed7d4e814d6e7fa418f8e051eb073676aa2fd0e 100644 (file)
@@ -1,6 +1,6 @@
-[[template id=plugin name=syntax author="mazirian"]]
-[[tag type/format]]
+[[!template id=plugin name=syntax author="mazirian"]]
+[[!tag type/format]]
 
 Textile is a versatile markup language. So here's a plugin that will use the
 Textile  markup language to render .txtl files in your data directory. 
-You must have [[cpan Text::Textile]] installed for it to work.
+You must have [[!cpan Text::Textile]] installed for it to work.
diff --git a/doc/plugins/textile/discussion.mdwn b/doc/plugins/textile/discussion.mdwn
deleted file mode 100644 (file)
index 945c9b4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.
\ No newline at end of file
index c1f8f25f0c3d81a1065d4aa05a7ba4f4f9c2c68d..2b7686681ee110072fd8576da0a98e30b1fff91d 100644 (file)
@@ -1,20 +1,5 @@
-[[template id=plugin name=toc author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=toc author="[[Joey]]"]]
+[[!tag type/chrome]]
 
-Add a table of contents to a page:
-
-       \[[toc ]]
-
-The table of contents will be automatically generated based on the
-headers of the page. By default only the largest headers present on the
-page will be shown; to control how many levels of headers are shown, use
-the `levels` parameter:
-
-       \[[toc levels=2]]
-
-The toc plugin will take the level of the first header as the topmost
-level, even if there are higher levels seen later in the file.
-
-The table of contents will be created as an ordered list. If you want
-an unordered list instead, you can change the list-style in your local
-style sheet.
\ No newline at end of file
+This plugin provides the [[ikiwiki/directive/toc]] [[ikiwiki/directive]],
+which adds a table of contents to a page.
index b33575824e88f083bbec295b6b939f780c63cd14..69ac613e01e63eada17f05ef4f9da4adbcf06a0c 100644 (file)
@@ -1,33 +1,7 @@
-[[template id=plugin name=toggle author="[[Joey]]"]]
-[[tag type/chrome]]
+[[!template id=plugin name=toggle author="[[Joey]]"]]
+[[!tag type/chrome]]
 
-With this plugin you can create links on pages that, when clicked, toggle
+This plugin provides the [[ikiwiki/directive/toggle]] and
+[[ikiwiki/directive/toggleable]] [[directives|ikiwiki/directive]].
+With these directives you can create links on pages that, when clicked, toggle
 display of other parts of the page.
-
-It uses javascript to accomplish this; browsers without javascript will
-always see the full page content.
-
-Example use:
-
-       \[[toggle id="ipsum" text="show"]]
-
-       \[[toggleable id="ipsum" text="""
-       Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
-       eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
-       ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
-       aliquip ex ea commodo consequat.
-
-       [[toggle id="ipsum" text="hide"]]
-       """]]
-
-Note that you can include wiki markup in the toggleable text,
-including even additional toggles, as shown in the above example.
-
-Also, the toggle and the togglable definitions do not need to be next to
-each other, but can be located anywhere on the page. There can also be
-mutiple toggles that all toggle a single togglable.
-
-The id has a default value of "default", so can be omitted in simple cases.
-
-If you'd like a toggleable to be displayed by default, and toggle to
-hidden, then pass a parameter "open=true" when setting up the toggleable.
index 5426a62fc820ae32fbae63f64b402eb832c0658a..e48eef5ba9876d4f4097bae930cac982942ee364 100644 (file)
@@ -1,7 +1,7 @@
 ## Nested plugins
 
 Is it possible to use another plugin into your toggle plugin? For example,
-I want to have toggleable table and try to use Victor Moral's table plugin,
+I want to have toggleable table and try to use [[Victor Moral|users/victormoral]]'s [[table plugin|plugins/table]],
 but no success. How can I do it?
 --PTecza
 
@@ -15,3 +15,29 @@ but no success. How can I do it?
 
 
 ## [[bugs/Bug_when_toggling_in_a_preview_page]]
+
+----
+
+## Using toggle directives in a list item##
+Take this code snippet.
+
+    * [[!toggle id="test" text="test"]]
+      [[!toggleable id="test text="""toggle"""]]
+
+In the HTML-output the `ul` and `div` overlap.
+
+    <div id="content">
+    <ul>
+    <li><a class="toggle" href="#test.test">test</a>
+    <div class="toggleable" id="test.-test"></li>
+    </ul>
+    
+    <p>toggle</p>
+    
+    </div>
+    
+    </div>
+
+Fixing this manually the Javascript seems not to be working and `toggle` is shown unconditionally.
+
+I do not know if this is due to [[shortcomming with nested preprocessor directives|todo/nested_preprocessor_directives]] you mentioned in the beginning of this page. Maybe a note could be added to the main page of the plugin. --Paul
index 8d8cb55c21b482a6264774ae79eb782f13609b70..420898d095b2a7e8b8aed8f303da66515eb3d541 100644 (file)
@@ -1,5 +1,5 @@
-[[template id=plugin name=txt author="[[Gabriel]]"]]
-[[tag type/format]]
+[[!template id=plugin name=txt author="[[Gabriel]]"]]
+[[!tag type/format]]
 
 This plugin makes ikiwiki treat files with names ending in ".txt"
 as wiki pages.
@@ -8,7 +8,7 @@ Unlike other [[type/format]] plugins, no formatting of markup in
 txt files is done; the file contents is displayed to the user as-is,
 with html markup characters such as ">" escaped.
 
-The only exceptions are that [[WikiLinks|WikiLink]] and
-[[PreprocessorDirectives|PreprocessorDirective]] are still expanded by
-ikiwiki, and that, if the [[cpan URI::Find]] perl module is installed, URLs
+The only exceptions are that [[WikiLinks|ikiwiki/WikiLink]] and
+[[directives|ikiwiki/directive]] are still expanded by
+ikiwiki, and that, if the [[!cpan URI::Find]] perl module is installed, URLs
 in the txt file are converted to hyperlinks.
diff --git a/doc/plugins/txt/discussion.mdwn b/doc/plugins/txt/discussion.mdwn
new file mode 100644 (file)
index 0000000..6b907e6
--- /dev/null
@@ -0,0 +1,33 @@
+I guess the reason I never thought to write this is when I put a .txt file
+in ikiwiki, I'm happy enough to see it copied through unchanged.
+
+I guess the advantage of using this plugin is that you get the page wrapper
+around the preformatted text, and could even inline such a page.
+
+There is not currently a good way to turn off some processing steps for
+some page types. It's either all or nothing. The patch in
+[[todo/format_escape]] might allow a formatter to register its own special
+version of htmllink that didn't do anything, but would that be enough?
+
+--[[Joey]]
+
+[Here](http://www.gmcmanus.org/plaintext.pm) is an alternate approach.
+It encodes entities using a filter hook, before wikilinks are linkified.
+So wikilinks turn up as links.
+It also uses URI::Find to turn URIs into links.
+
+I'm not very familiar with Perl, so this code could be improved.
+
+--Gabriel
+
+I like this approach! It sidesteps the annoying problem, and it actually
+makes the .txt format genuinely wiki-like, by allowing wikilinks and
+preprocessor directices.
+
+The only thing I am not sure about is the conversion of external urls to
+hyperlinks. 
+
+Can you please add a copyright/license statemnt to the top of the plugin?
+If you do, I'll add it to ikiwiki. Thanks! --[[Joey]]
+
+> I've added copyright and license (GPLv2 or later). --Gabriel
diff --git a/doc/plugins/type/date.mdwn b/doc/plugins/type/date.mdwn
new file mode 100644 (file)
index 0000000..eae1226
--- /dev/null
@@ -0,0 +1 @@
+These plugins control how ikiwiki displays dates.
diff --git a/doc/plugins/type/web.mdwn b/doc/plugins/type/web.mdwn
new file mode 100644 (file)
index 0000000..b60e26a
--- /dev/null
@@ -0,0 +1 @@
+These plugins enhance the web interface.
index b03c2a0866cab393cdf37386f45ecdfdea303bb7..030ef80526d2110e14a067fb7930457a89e5a6d5 100644 (file)
@@ -1,12 +1,12 @@
-[[template id=plugin name=typography author="[[Roktas]]"]]
-[[tag type/format]]
+[[!template id=plugin name=typography author="[[Roktas]]"]]
+[[!tag type/format]]
 
 This plugin, also known as
 [SmartyPants](http://daringfireball.net/projects/smartypants/), translates
 plain ASCII punctuation characters into ``smart'' typographic punctuation HTML
-entities. To use it, you need to have the [[cpan Text::Typography]] module
+entities. To use it, you need to have the [[!cpan Text::Typography]] module
 installed.
 
 This plugin has a configuration option. To change the attributes,
 set `--typographyattributes=whatever`. See the documentation for
-[[cpan Text::Typography]] for available attributes.
+[[!cpan Text::Typography]] for available attributes.
diff --git a/doc/plugins/underlay.mdwn b/doc/plugins/underlay.mdwn
new file mode 100644 (file)
index 0000000..09d096a
--- /dev/null
@@ -0,0 +1,14 @@
+[[!template id=plugin name=underlay author="[[Simon_McVittie|smcv]]"]]
+[[!tag type/useful]]
+
+This plugin adds an `add_underlays` option to the `.setup` file.
+Its value is a list of underlay directories whose content is added to the wiki.
+
+Multiple underlays are normally set up automatically by other plugins (for
+instance, the images used by the [[plugins/smiley]] plugin), but they can also be
+used as a way to pull in external files that you don't want in revision control,
+like photos or software releases.
+
+Directories in `add_underlays` should usually be absolute. If relative, they're
+interpreted as relative to the parent directory of the basewiki underlay, which
+is probably not particularly useful in this context.
index ec90629477518d010997a16b2c3f5ee7bf16f27f..43027bdd72797223f52a2cfda995c00b24d6f139 100644 (file)
@@ -1,11 +1,6 @@
-[[template id=plugin name=version author="[[Joey]]"]]
-[[tag type/useful]]
+[[!template id=plugin name=version author="[[Joey]]"]]
+[[!tag type/meta]]
 
-This plugin allows inserting the version of ikiwiki onto a page.
-
-Whenever ikiwiki is upgraded to a new version, the page will be rebuilt,
-updating the version number.
-
-Use is simple:
-
-       \[[version ]]
+This plugin provides the [[ikiwiki/directive/version]]
+[[ikiwiki/directive]], which inserts the current version
+of ikiwiki into a page.
diff --git a/doc/plugins/websetup.mdwn b/doc/plugins/websetup.mdwn
new file mode 100644 (file)
index 0000000..f1756ba
--- /dev/null
@@ -0,0 +1,26 @@
+[[!template id=plugin name=websetup core=0 author="[[Joey]]"]]
+[[!tag type/web]]
+
+This plugin allows wiki admins to configure the wiki using a web interface,
+rather than editing the setup file directly. A "Wiki Setup" button is added
+to the admins' preferences page.
+
+Warning: This plugin rewrites your setup file. Any comments or unusual
+things (such as perl code) in the setup file will not be preserved. Also,
+it will only work correctly with new format setup files, as introduced in
+ikiwiki 2.60. Older setup files have a "wrappers" section, which will not
+be properly preserved if this plugin is used.
+
+Most settings can be modified using the web interface. Plugins can be
+enabled and disabled using it too. Some settings are not considered safe
+enough to be manipulated over the web; these are still shown, by default,
+but cannot be modified. To hide them, set `websetup_show_unsafe` to false
+in the setup file. A few settings have too complex a data type to be
+configured via the web.
+
+Plugins that should not be enabled/disabled via the web interface can be
+listed in `websetup_force_plugins` in the setup file.
+
+When the setup is saved, the setup file will be rewritten with the new
+settings, and the wiki will be refreshed, or rebuilt, to make the setip
+changes take effect.
index a87ab06fdd1e4012c52b4badba0916071076cd1b..4837121308716938e9160672caa30c799e2a4132 100644 (file)
@@ -1,8 +1,8 @@
-[[template id=plugin name=wikitext author="[[Joey]]"]]
-[[tag type/format]]
+[[!template id=plugin name=wikitext author="[[Joey]]"]]
+[[!tag type/format]]
 
 This plugin allows ikiwiki to process pages written in the original wiki
-text format. To use it, you need to have the [[cpan Text::WikiFormat]] perl
+text format. To use it, you need to have the [[!cpan Text::WikiFormat]] perl
 module installed, enable the plugin, then files with the extention `.wiki`
 will be processed as wiki text.
 
diff --git a/doc/plugins/wmd.mdwn b/doc/plugins/wmd.mdwn
new file mode 100644 (file)
index 0000000..dc9a307
--- /dev/null
@@ -0,0 +1,16 @@
+[[!template id=plugin name=wmd author="[[Will]]"]]
+[[!tag type/chrome]]
+
+[WMD](http://wmd-editor.com/) is a What You See Is What You Mean editor for
+[[mdwn]]. This plugin makes WMD be used for editing pages in the wiki.
+
+To use the plugin, you will need to install WMD. Download the [WMD
+source](http://wmd-editor.com/downloads/wmd-1.0.1.zip).  In that zip file
+you'll find a few example html files, a readme and `wmd` directory.  Create
+a 'wmd' subdirectory in the ikiwiki `underlaydir` directory (ie `sudo mkdir
+/usr/share/ikiwiki/wmd`). Move the `wmd` directory into the directory you
+made. You should now have a `wmd/wmd/wmd.js` file as well as some other
+javascript files and an images directory in the same place.
+
+Note that the WMD plugin does **not** handle ikiwiki directives.  For this
+reason the normal `preview` button remains.
index 5def4c67967165f927ae696954c254e72f49221d..3976f9adf5a74b504b66efa8478e4d0acc2ebd6e 100644 (file)
@@ -3,7 +3,7 @@ written to extend ikiwiki in many ways. Despite the length of this page,
 it's not really hard. This page is a complete reference to everything a
 plugin might want to do. There is also a quick [[tutorial]].
 
-[[toc levels=2]]
+[[!toc levels=2]]
 
 ## Types of plugins
 
@@ -19,7 +19,7 @@ that can be fleshed out to make a useful plugin.
 `IkiWiki::Plugin::pagecount` is another simple example. All perl plugins
 should `use IkiWiki` to import the ikiwiki plugin interface. It's a good
 idea to include the version number of the plugin interface that your plugin
-expects: `use IkiWiki 2.00`.
+expects: `use IkiWiki 3.00`.
 
 An external plugin is an executable program. It can be written in any
 language. Its interface to ikiwiki is via XML RPC, which it reads from
@@ -46,15 +46,17 @@ being edited.
 
 Plugins should, when imported, call `hook()` to hook into ikiwiki's
 processing. The function uses named parameters, and use varies depending on
-the type of hook being registered -- see below. Note that a plugin can call
-the function more than once to register multiple hooks. All calls to
-`hook()` should be passed a "type" parameter, which gives the type of
-hook, a "id" paramter, which should be a unique string for this plugin, and
-a "call" parameter, which tells what function to call for the hook.
+the type of hook being registered -- see below. A plugin can call
+the function more than once to register multiple hooks.
+
+All calls to `hook()` should be passed a "type" parameter, which gives the
+type of hook, a "id" parameter, which should be a unique string for this
+plugin, and a "call" parameter, which tells what function to call for the
+hook.
 
 An optional "last" parameter, if set to a true value, makes the hook run
-after all other hooks of its type. Useful if the hook depends on some other
-hook being run first.
+after all other hooks of its type, and an optional "first" parameter makes
+it run first. Useful if the hook depends on some other hook being run first.
 
 ## Types of hooks
 
@@ -96,9 +98,21 @@ function is passed no values.
 
 This allows a plugin to manipulate the list of files that need to be
 built when the wiki is refreshed. The function is passed a reference to an
-array of pages that will be rebuilt, and can modify the array, either
+array of files that will be rebuilt, and can modify the array, either
 adding or removing files from it.
 
+### scan
+
+       hook(type => "scan", id => "foo", call => \&scan);
+
+This hook is called early in the process of building the wiki, and is used
+as a first pass scan of the page, to collect metadata about the page. It's
+mostly used to scan the page for [[WikiLinks|ikiwiki/WikiLink]], and add
+them to `%links`. Present in IkiWiki 2.40 and later.
+
+The function is passed named parameters "page" and "content". Its return
+value is ignored.
+
 ### filter
 
        hook(type => "filter", id => "foo", call => \&filter);
@@ -109,34 +123,42 @@ make arbitrary changes. The function is passed named parameters "page",
 
 ### preprocess
 
-Adding a [[ikiwiki/PreProcessorDirective]] is probably the most common use
+Adding a preprocessor [[ikiwiki/directive]] is probably the most common use
 of a plugin.
 
         hook(type => "preprocess", id => "foo", call => \&preprocess);
 
-Replace "foo" with the command name that will be used inside brackets for
-the preprocessor directive.
-
-Each time the directive is processed, the referenced function (`preprocess`
-in the example above) is called, and is passed named parameters. A "page"
-parameter gives the name of the page that embedded the preprocessor
-directive, while a "destpage" parameter gives the name of the page the
-content is going to (different for inlined pages), and a "preview"
-parameter is set to a true value if the page is being previewed. All
-parameters included in the directive are included as named parameters as
-well. Whatever the function returns goes onto the page in place of the
+Replace "foo" with the command name that will be used for the preprocessor
 directive.
 
-An optional "scan" parameter, if set to a true value, makes the hook be
-called during the preliminary scan that ikiwiki makes of updated pages,
-before begining to render pages. This parameter should be set to true if
-the hook modifies data in `%links`. Note that doing so will make the hook
-be run twice per page build, so avoid doing it for expensive hooks. (As an
-optimisation, if your preprocessor hook is called in a void contets, you
-can assume it's being run in scan mode.)
+Each time the directive is processed, the referenced function (`preprocess`
+in the example above) is called. Whatever the function returns goes onto
+the page in place of the directive. Or, if the function aborts using
+`error()`, the directive will be replaced with the error message.
+
+The function is passed named parameters. First come the parameters set
+in the preprocessor directive. These are passed in the same order as
+they're in the directive, and if the preprocessor directive contains a bare
+parameter (example: `\[[!foo param]]`), that parameter will be passed with
+an empty value.
+
+After the parameters from the preprocessor directive some additional ones
+are passed: A "page" parameter gives the name of the page that embedded the
+preprocessor directive, while a "destpage" parameter gives the name of the
+page the content is going to (different for inlined pages), and a "preview"
+parameter is set to a true value if the page is being previewed.
+
+If `hook` is passed an optional "scan" parameter, set to a true value, this
+makes the hook be called during the preliminary scan that ikiwiki makes of
+updated pages, before begining to render pages. This should be done if the
+hook modifies data in `%links` (typically by calling `add_link`). Note that
+doing so will make the hook be run twice per page build, so avoid doing it
+for expensive hooks. (As an optimisation, if your preprocessor hook is
+called in a void context, you can assume it's being run in scan mode, and
+avoid doing expensive things at that point.)
 
 Note that if the [[htmlscrubber]] is enabled, html in
-[[ikiwiki/PreProcessorDirective]] output is sanitised, which may limit what
+preprocessor [[ikiwiki/directive]] output is sanitised, which may limit what
 your plugin can do. Also, the rest of the page content is not in html
 format at preprocessor time. Text output by a preprocessor directive will
 be linkified and passed through markdown (or whatever engine is used to
@@ -146,31 +168,20 @@ htmlize the page) along with the rest of the page.
 
        hook(type => "linkify", id => "foo", call => \&linkify);
 
-This hook is called to convert [[WikiLinks|WikiLink]] on the page into html
+This hook is called to convert [[WikiLinks|ikiwiki/WikiLink]] on the page into html
 links. The function is passed named parameters "page", "destpage", and
 "content". It should return the linkified content.  Present in IkiWiki 2.40
 and later.
 
 Plugins that implement linkify must also implement a scan hook, that scans
-for the links on the page and adds them to `%links`.
-
-### scan
-
-       hook(type => "scan", id => "foo", call => \&scan);
-
-This hook is called early in the process of building the wiki, and is used
-as a first pass scan of the page, to collect metadata about the page. It's
-mostly used to scan the page for WikiLinks, and add them to `%links`.
-Present in IkiWiki 2.40 and later.
-
-The function is passed named parameters "page" and "content". Its return
-value is ignored.
+for the links on the page and adds them to `%links` (typically by calling
+`add_link`).
 
 ### htmlize
 
        hook(type => "htmlize", id => "ext", call => \&htmlize);
 
-Runs on the raw source of a page and turns it into html. The id parameter
+Runs on the source of a page and turns it into html. The id parameter
 specifies the filename extension that a file must have to be htmlized using
 this plugin. This is how you can add support for new and exciting markup
 languages to ikiwiki.
@@ -178,6 +189,18 @@ languages to ikiwiki.
 The function is passed named parameters: "page" and "content" and should
 return the htmlized content.
 
+If `hook` is passed an optional "keepextension" parameter, set to a true
+value, then the extension will not be stripped from the source filename when
+generating the page.
+
+If `hook` is passed an optional "noextension" parameter, set to a true
+value, then the id parameter specifies not a filename extension, but
+a whole filename that can be htmlized. This is useful for files
+like `Makefile` that have no extension.
+
+If `hook` is passed an optional "longname" parameter, this value is used
+when prompting a user to choose a page type on the edit page form.
+
 ### pagetemplate
 
        hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
@@ -187,7 +210,7 @@ ikiwiki, like generating a page, or part of a blog page, or an rss feed, or
 a cgi. This hook allows modifying the variables available on those
 templates. The function is passed named parameters. The "page" and
 "destpage" parameters are the same as for a preprocess hook. The "template"
-parameter is a [[cpan HTML::Template]] object that is the template that
+parameter is a [[!cpan HTML::Template]] object that is the template that
 will be used to generate the page. The function can manipulate that
 template object.
 
@@ -214,6 +237,17 @@ modify the body of a page after it has been fully converted to html.
 The function is passed named parameters: "page", "destpage", and "content",
 and should return the sanitized content.
 
+### postscan
+
+       hook(type => "postscan", id => "foo", call => \&postscan);
+
+This hook is called once the full page body is available (but before the
+format hook). The most common use is to update search indexes. Added in
+ikiwiki 2.54.
+
+The function is passed named parameters "page" and "content". Its return
+value is ignored.
+
 ### format
 
        hook(type => "format", id => "foo", call => \&format);
@@ -258,9 +292,9 @@ state is loaded, and with no session information.
 
        hook(type => "auth", id => "foo", call => \&auth);
 
-This hook can be used to implement a different authentication method than
-the standard web form. When a user needs to be authenticated, each registered
-auth hook is called in turn, and passed a CGI object and a session object. 
+This hook can be used to implement an authentication method. When a user
+needs to be authenticated, each registered auth hook is called in turn, and
+passed a CGI object and a session object. 
 
 If the hook is able to authenticate the user, it should set the session
 object's "name" parameter to the authenticated user's name. Note that
@@ -278,7 +312,7 @@ can check if the session object has a "name" parameter set.
 
 ### canedit
 
-       hook(type => "canedit", id => "foo", call => \&pagelocked);
+       hook(type => "canedit", id => "foo", call => \&canedit);
 
 This hook can be used to implement arbitrary access methods to control when
 a page can be edited using the web interface (commits from revision control
@@ -296,6 +330,47 @@ This hook should avoid directly redirecting the user to a signin page,
 since it's sometimes used to test to see which pages in a set of pages a
 user can edit.
 
+### canremove
+
+       hook(type => "canremove", id => "foo", call => \&canremove);
+
+This hook can be used to implement arbitrary access methods to control
+when a page can be removed using the web interface (commits from
+revision control bypass it). It works exactly like the `canedit` hook,
+but is passed the named parameters `cgi` (a CGI object), `session`
+(a session object) and `page` (the page subject to deletion).
+
+### canrename
+
+       hook(type => "canrename", id => "foo", call => \&canrename);
+
+This hook can be used to implement arbitrary access methods to control when
+a page can be renamed using the web interface (commits from revision control
+bypass it). It works exactly like the `canedit` hook,
+but is passed the named parameters `cgi` (a CGI object), `session` (a
+session object), `src`, `srcfile`, `dest` and `destfile`.
+
+### checkcontent
+       
+       hook(type => "checkcontent", id => "foo", call => \&checkcontent);
+
+This hook is called to check the content a user has entered on a page,
+before it is saved, and decide if it should be allowed.
+
+It is passed named parameters: `content`, `page`, `cgi`, and `session`. If
+the content the user has entered is a comment, it may also be passed some
+additional parameters: `author`, `url`, and `subject`. The `subject`
+parameter may also be filled with the user's comment about the change.
+
+Note: When the user edits an existing wiki page, this hook is also
+passed a `diff` named parameter, which will include only the lines
+that they added to the page, or modified.
+
+The hook should return `undef` on success. If the content is disallowed, it
+should return a message stating what the problem is, or a function
+that can be run to perform whatever action is necessary to allow the user
+to post the content.
+
 ### editcontent
 
        hook(type => "editcontent", id => "foo", call => \&editcontent);
@@ -312,7 +387,7 @@ It can modify the content as desired, and should return the content.
        hook(type => "formbuilder_setup", id => "foo", call => \&formbuilder_setup);
        hook(type => "formbuilder", id => "foo", call => \&formbuilder);
 
-These hooks allow tapping into the parts of ikiwiki that use [[cpan
+These hooks allow tapping into the parts of ikiwiki that use [[!cpan
 CGI::FormBuilder]] to generate web forms. These hooks are passed named
 parameters: `cgi`, `session`, `form`, and `buttons`. These are, respectively,
 the `CGI` object, the user's `CGI::Session`, a `CGI::FormBuilder`, and a
@@ -331,15 +406,101 @@ called. It can be used to validate the form, but should not display it.
 
        hook(type => "savestate", id => "foo", call => \&savestate);
 
-This hook is called wheneven ikiwiki normally saves its state, just before
+This hook is called whenever ikiwiki normally saves its state, just before
 the state is saved. The function can save other state, modify values before
 they're saved, etc.
 
+### renamepage
+
+       hook(type => "renamepage", id => "foo", call => \&renamepage);
+
+This hook is called by the [[plugins/rename]] plugin when it renames
+something, once per page linking to the renamed page's old location.
+The hook is passed named parameters: `page`, `oldpage`, `newpage`, and
+`content`, and should try to modify the content of `page` to reflect
+the name change. For example, by converting links to point to the
+new page.
+
+### rename
+
+       hook(type => "rename", id => "foo", call => \&rename);
+
+When a page or set of pages is renamed, the referenced function is
+called for every page, and is passed named parameters:
+
+* `torename`: a reference to a hash with keys: `src`, `srcfile`,
+  `dest`, `destfile`, `required`.
+* `cgi`: a CGI object
+* `session`: a session object.
+
+Such a hook function returns any additional rename hashes it wants to
+add. This hook is applied recursively to returned additional rename
+hashes, so that it handles the case where two plugins use the hook:
+plugin A would see when plugin B adds a new file to be renamed.
+
+### getsetup
+
+       hook(type => "getsetup", id => "foo", call => \&getsetup);
+
+This hooks is not called during normal operation, but only when setting up 
+the wiki, or generating a setup file. Plugins can use this hook to add
+configuration options.
+
+The hook is passed no parameters. It returns data about the configuration
+options added by the plugin. It can also check if the plugin is usable, and
+die if not, which will cause the plugin to not be offered in the configuration
+interface.
+
+The data returned is a list of `%config` options, followed by a hash
+describing the option. There can also be an item named "plugin", which
+describes the plugin as a whole. For example:
+
+                return
+                       option_foo => {
+                               type => "boolean",
+                               description => "enable foo?",
+                               advanced => 1,
+                               safe => 1,
+                               rebuild => 1,
+                       },
+                       option_bar => {
+                               type => "string",
+                               example => "hello",
+                               description => "option bar",
+                               safe => 1,
+                               rebuild => 0,
+                       },
+                       plugin => {
+                               description => "description of this plugin",
+                               safe => 1,
+                               rebuild => 1,
+                       },
+
+* `type` can be "boolean", "string", "integer", "pagespec",
+  or "internal" (used for values that are not user-visible). The type is
+  the type of the leaf values;  the `%config` option may be an array or
+  hash of these.
+* `example` can be set to an example value.
+* `description` is a short description of the option.
+* `link` is a link to further information about the option. This can either
+  be a [[ikiwiki/WikiLink]], or an url.
+* `advanced` can be set to true if the option is more suitable for advanced
+  users.
+* `safe` should be false if the option should not be displayed in unsafe
+  configuration methods, such as the web interface. Anything that specifies
+  a command to run, a path on disk, or a regexp should be marked as unsafe.
+  If a plugin is marked as unsafe, that prevents it from being
+  enabled/disabled.
+* `rebuild` should be true if changing the option (or enabling/disabling
+  the plugin) will require a wiki rebuild, false if no rebuild is needed,
+  and undef if a rebuild could be needed in some circumstances, but is not
+  strictly required.
+
 ## Plugin interface
 
 To import the ikiwiki plugin interface:
 
-       use IkiWiki '1.00';
+       use IkiWiki '3.00';
 
 This will import several variables and functions into your plugin's
 namespace. These variables and functions are the ones most plugins need,
@@ -354,14 +515,14 @@ it's not exported, the wise choice is to not use it.
 
 A plugin can access the wiki's configuration via the `%config`
 hash. The best way to understand the contents of the hash is to look at
-[[ikiwiki.setup]], which sets the hash content to configure the wiki.
+your ikiwiki setup file, which sets the hash content to configure the wiki.
 
 ### %pagestate
 
 The `%pagestate` hash can be used by plugins to save state that they will need
 next time ikiwiki is run. The hash holds per-page state, so to set a value,
-use `%pagestate{$page}{$id}{$key}=$value`, and to retrieve the value,
-use `%pagestate{$page}{$id}{$key}`.
+use `$pagestate{$page}{$id}{$key}=$value`, and to retrieve the value,
+use `$pagestate{$page}{$id}{$key}`.
 
 The `$value` can be anything that perl's Storable module is capable of
 serializing. `$key` can be any string you like, but `$id` must be the same
@@ -374,6 +535,15 @@ When pages are deleted, ikiwiki automatically deletes their pagestate too.
 Note that page state does not persist across wiki rebuilds, only across
 wiki updates.
 
+### %wikistate
+
+The `%wikistate` hash can be used by a plugin to store persistant state
+that is not bound to any one page. To set a value, use
+`$wikistate{$id}{$key}=$value, where `$value` is anything Storable can
+serialize, `$key` is any string you like, and `$id` must be the same as the
+"id" parameter passed to `hook()` when registering the plugin, so that the
+state can be dropped if the plugin is no longer used.
+
 ### Other variables
 
 If your plugin needs to access data about other pages in the wiki. It can
@@ -385,7 +555,7 @@ use the following hashes, using a page name as the key:
   destination file.
 * `%pagesources` contains the name of the source file for each page.
 
-Also, the %IkiWiki::version variable contains the version number for the
+Also, the `%IkiWiki::version` variable contains the version number for the
 ikiwiki program.
 
 ### Library functions
@@ -410,16 +580,17 @@ Aborts with an error message. If the second parameter is passed, it is a
 function that is called after the error message is printed, to do any final
 cleanup.
 
-Note that while any plugin can use this for a fatal error, plugins should
-try to avoid dying on bad input, as that will halt the entire wiki build
-and make the wiki unusable. So for example, if a
-[[ikiwiki/PreProcessorDirective]] is passed bad parameters, it's better to
-return an error message, which can appear on the wiki page, rather than
-calling error().
+If called inside a preprocess hook, error() does not abort the entire
+wiki build, but instead replaces the preprocessor [[ikiwiki/directive]] with
+a version containing the error message.
+
+In other hooks, error() is a fatal error, so use with care. Try to avoid
+dying on bad input when building a page, as that will halt
+the entire wiki build and make the wiki unusable.
 
 #### `template($;@)`
 
-Creates and returns a [[cpan HTML::Template]] object. The first parameter
+Creates and returns a [[!cpan HTML::Template]] object. The first parameter
 is the name of the file in the template directory. The optional remaining
 parameters are passed to `HTML::Template->new`.
 
@@ -428,6 +599,9 @@ parameters are passed to `HTML::Template->new`.
 Passed a page name, returns the base name that will be used for a the html
 page created from it. (Ie, it appends ".html".)
 
+Use this when constructing the filename of a html file. Use `urlto` when
+generating a link to a page.
+
 #### `add_depends($$)`
 
 Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
@@ -442,6 +616,19 @@ The most often used is "location", which specifies the location the
 PageSpec should match against. If not passed, relative PageSpecs will match
 relative to the top of the wiki.
 
+#### `pagespec_match_list($$;@)`
+
+Passed a reference to a list of page names, and [[ikiwiki/PageSpec]],
+returns the set of pages that match the [[ikiwiki/PageSpec]].
+
+Additional named parameters can be passed, to further limit the match.
+The most often used is "location", which specifies the location the
+PageSpec should match against. If not passed, relative PageSpecs will match
+relative to the top of the wiki.
+
+Unlike pagespec_match, this may throw an error if there is an error in
+the pagespec.
+
 #### `bestlink($$)`
 
 Given a page and the text of a link on the page, determine which
@@ -454,7 +641,7 @@ pages, as described in [[ikiwiki/SubPage/LinkingRules]].
 
 Many plugins need to generate html links and add them to a page. This is
 done by using the `htmllink` function. The usual way to call
-`htmlllink` is:
+`htmllink` is:
 
        htmllink($page, $page, $link)
 
@@ -504,6 +691,16 @@ A failure to write the file will result in it dying with an error.
 
 If the destination directory doesn't exist, it will first be created.
 
+The filename and directory are separate parameters because of
+some security checks done to avoid symlink attacks. Before writing a file,
+it checks to make sure there's not a symlink with its name, to avoid
+following the symlink. If the filename parameter includes a subdirectory
+to put the file in, it also checks if that subdirectory is a symlink, etc.
+The directory parameter, however, is not checked for symlinks. So,
+generally the directory parameter is a trusted toplevel directory like
+the srcdir or destdir, and any subdirectories of this are included in the
+filename parameter.
+
 #### `will_render($$)`
 
 Given a page name and a destination file name (not including the base
@@ -530,6 +727,23 @@ a type that ikiwiki knowns how to htmlize. Otherwise, returns undef.
 Given the name of a source file, returns the name of the wiki page
 that corresponds to that file.
 
+#### `pagetitle($)`
+
+Give the name of a wiki page, returns a version suitable to be displayed as
+the page's title. This is accomplished by de-escaping escaped characters in
+the page name. "_" is replaced with a space, and '__NN__' is replaced by 
+the UTF character with code NN.
+
+#### `titlepage($)`
+
+This performs the inverse of `pagetitle`, ie, it converts a page title into
+a wiki page name.
+
+#### `linkpage($)`
+
+This converts text that could have been entered by the user as a
+[[ikiwiki/WikiLink]] into a wiki page name.
+
 #### `srcfile($;$)`
 
 Given the name of a source file in the wiki, searches for the file in
@@ -559,18 +773,38 @@ time.
 
 This is the standard gettext function, although slightly optimised.
 
-#### `urlto($$)`
+#### `urlto($$;$)`
 
 Construct a relative url to the first parameter from the page named by the
 second. The first parameter can be either a page name, or some other
 destination file, as registered by `will_render`.
 
-#### `targetpage($$)`
+If the third parameter is passed and is true, an absolute url will be
+constructed instead of the default relative url.
+
+#### `newpagefile($$)`
+
+This can be called when creating a new page, to determine what filename
+to save the page to. It's passed a page name, and its type, and returns
+the name of the file to create, relative to the srcdir.
+
+#### `targetpage($$;$)`
 
 Passed a page and an extension, returns the filename that page will be
 rendered to.
 
-## Internal use pages
+Optionally, a third parameter can be passed, to specify the preferred
+filename of the page. For example, `targetpage("foo", "rss", "feed")`
+will yield something like `foo/feed.rss`.
+
+#### `add_link($$)`
+
+This adds a link to `%links`, ensuring that duplicate links are not
+added. Pass it the page that contains the link, and the link text.
+
+## Miscellaneous
+
+### Internal use pages
 
 Sometimes it's useful to put pages in the wiki without the overhead of
 having them be rendered to individual html files. Such internal use pages
@@ -578,30 +812,244 @@ are collected together to form the RecentChanges page, for example.
 
 To make an internal use page, register a filename extension that starts
 with "_". Internal use pages cannot be edited with the web interface,
-generally shouldn't contain wikilinks or preprocessor directives (use
+generally shouldn't contain [[WikiLinks|ikiwiki/WikiLink]] or preprocessor directives (use
 either on them with extreme caution), and are not matched by regular
 PageSpecs glob patterns, but instead only by a special `internal()`
 [[ikiwiki/PageSpec]].
 
-## RCS plugins
+### RCS plugins
+
+ikiwiki's support for [[revision_control_systems|rcs]] is also done via
+plugins. See [[RCS_details|rcs/details]] for some more info.
+
+RCS plugins must register a number of hooks. Each hook has type 'rcs', 
+and the 'id' field is set to the name of the hook. For example:
+       
+       hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+       hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+
+#### `rcs_update()`
+
+Updates the working directory with any remote changes.
+
+#### `rcs_prepedit($)`
+
+Is passed a file to prepare to edit. It can generate and return an arbitrary
+token, that will be passed into `rcs_commit` when committing. For example,
+it might return the current revision ID of the file, and use that
+information later when merging changes.
+
+#### `rcs_commit($$$;$$)`
+
+Passed a file, message, token (from `rcs_prepedit`), user, and ip address.
+Should try to commit the file. Returns `undef` on *success* and a version
+of the page with the rcs's conflict markers on failure.
+
+#### `rcs_commit_staged($$$)`
+
+Passed a message, user, and ip address. Should commit all staged changes.
+Returns undef on success, and an error message on failure.
+
+Changes can be staged by calls to `rcs_add`, `rcs_remove`, and
+`rcs_rename`.
+
+#### `rcs_add($)`
+
+Adds the passed file to the archive. The filename is relative to the root
+of the srcdir.
+
+Note that this should not commit the new file, it should only
+prepare for it to be committed when rcs_commit (or `rcs_commit_staged`) is
+called. Note that the file may be in a new subdir that is not yet in
+to version control; the subdir can be added if so.
+
+#### `rcs_remove($)`
+
+Remove a file. The filename is relative to the root of the srcdir.
+
+Note that this should not commit the removal, it should only prepare for it
+to be committed when `rcs_commit` (or `rcs_commit_staged`) is called. Note
+that the new file may be in a new subdir that is not yet in version
+control; the subdir can be added if so.
+
+#### `rcs_rename($$)`
+
+Rename a file. The filenames are relative to the root of the srcdir.
+
+Note that this should not commit the rename, it should only
+prepare it for when `rcs_commit` (or `rcs_commit_staged`) is called.
+The new filename may be in a new subdir, that is not yet added to
+version control. If so, the subdir will exist already, and should
+be added to revision control.
+
+#### `rcs_recentchanges($)`
+
+Examine the RCS history and generate a list of recent changes.
+The parameter is how many changes to return.
+
+The data structure returned for each change is:
+
+       {
+               rev => # the RCSs id for this commit
+               user => # name of user who made the change,
+               committype => # either "web" or the name of the rcs,
+               when => # time when the change was made,
+               message => [
+                       { line => "commit message line 1" },
+                       { line => "commit message line 2" },
+                       # etc,
+               ],
+               pages => [
+                       {
+                               page => # name of page changed,
+                               diffurl => # optional url to a diff of changes
+                       },
+                       # repeat for each page changed in this commit,
+               ],
+       }
+
+#### `rcs_diff($)`
+
+The parameter is the rev from `rcs_recentchanges`.
+Should return a list of lines of the diff (including \n) in list
+context, and the whole diff in scalar context.
+
+#### `rcs_getctime($)`
 
-ikiwiki's support for [[revision_control_systems|rcs]] also uses pluggable
-perl modules. These are in the `IkiWiki::RCS` namespace, for example
-`IkiWiki::RCS::svn`. 
+This is used to get the page creation time for a file from the RCS, by looking
+it up in the history.
 
-Each RCS plugin must support all the `IkiWiki::rcs_*` functions.
-See IkiWiki::RCS::Stub for the full list of functions. It's ok if
-`rcs_getctime` does nothing except for throwing an error.
+It's ok if this is not implemented, and throws an error.
 
-See [[RCS_details|rcs/details]] for some more info.
+#### `rcs_receive()`
 
-## PageSpec plugins
+This is called when ikiwiki is running as a pre-receive hook (or
+equivalent), and is testing if changes pushed into the RCS from an
+untrusted user should be accepted. This is optional, and doesn't make
+sense to implement for all RCSs.
+
+It should examine the incoming changes, and do any sanity 
+checks that are appropriate for the RCS to limit changes to safe file adds,
+removes, and changes. If something bad is found, it should exit
+nonzero, to abort the push. Otherwise, it should return a list of
+files that were changed, in the form:
+
+       {
+               file => # name of file that was changed
+               action => # either "add", "change", or "remove"
+               path => # temp file containing the new file content, only
+                       # needed for "add"/"change", and only if the file
+                       # is an attachment, not a page
+       }
+
+The list will then be checked to make sure that each change is one that
+is allowed to be made via the web interface.
+
+### PageSpec plugins
 
 It's also possible to write plugins that add new functions to
 [[PageSpecs|ikiwiki/PageSpec]]. Such a plugin should add a function to the
 IkiWiki::PageSpec package, that is named `match_foo`, where "foo()" is
 how it will be accessed in a [[ikiwiki/PageSpec]]. The function will be passed
 two parameters: The name of the page being matched, and the thing to match
-against. It may also be passed additional, named parameters. It should return
-a IkiWiki::SuccessReason object if the match succeeds, or an
-IkiWiki::FailReason object if the match fails.
+against. It may also be passed additional, named parameters.
+
+It should return a IkiWiki::SuccessReason object if the match succeeds, or
+an IkiWiki::FailReason object if the match fails. If the match cannot be
+attempted at all, for any page, it can instead return an
+IkiWiki::ErrorReason object explaining why.
+
+### Setup plugins
+
+The ikiwiki setup file is loaded using a pluggable mechanism. If you look
+at the top of a setup file, it starts with 'use IkiWiki::Setup::Standard',
+and the rest of the file is passed to that module's import method.
+
+It's possible to write other modules in the `IkiWiki::Setup::` namespace that
+can be used to configure ikiwiki in different ways. These modules should,
+when imported, populate `$IkiWiki::Setup::raw_setup` with a reference
+to a hash containing all the config items. They should also implement a
+`gendump` function.
+
+By the way, to parse a ikiwiki setup file and populate `%config`, a
+program just needs to do something like:
+`use IkiWiki::Setup; IkiWiki::Setup::load($filename)`
+
+### Function overriding
+
+Sometimes using ikiwiki's pre-defined hooks is not enough. Your plugin
+may need to replace one of ikiwiki's own functions with a modified version,
+or wrap one of the functions.
+
+For example, your plugin might want to override `displaytime`, to change
+the html markup used when displaying a date. Or it might want to override
+`IkiWiki::formattime`, to change how a date is formatted. Or perhaps you
+want to override `bestlink` and change how ikiwiki deals with [[WikiLinks|ikiwiki/WikiLink]].
+
+By venturing into this territory, your plugin is becoming tightly tied to
+ikiwiki's internals. And it might break if those internals change. But
+don't let that stop you, if you're brave.
+
+Ikiwiki provides an `inject()` function, that is a powerful way to replace
+any function with one of your own. This even allows you to inject a
+replacement for an exported function, like `bestlink`. Everything that
+imports that function will get your version instead. Pass it the name of
+the function to replace, and a new function to call. 
+
+For example, here's how to replace `displaytime` with a version using HTML 5
+markup:
+
+       inject(name => 'IkiWiki::displaytime', call => sub {
+               return "<time>".formattime(@_)."</time>";
+       });
+
+Here's how to wrap `bestlink` with a version that tries to handle
+plural words:
+
+       my $origbestlink=\&bestlink;
+       inject(name => 'IkiWiki::bestlink', call => \&mybestlink);
+
+       sub deplural ($) {
+               my $word=shift;
+               $word =~ s/e?s$//; # just an example :-)
+               return $word;
+       }
+
+       sub mybestlink ($$) {
+               my $page=shift;
+               my $link=shift;
+               my $ret=$origbestlink->($page, $link);
+               if (! length $ret) {
+                       $ret=$origbestlink->($page, deplural($link));
+               }
+               return $ret;
+       }
+
+### Javascript
+
+Some plugins use javascript to make ikiwiki look a bit more web-2.0-ish.
+
+All javascript code should be put in `.js` files in the `javascript`
+underlay, and plugins using those files can enable use of the underlay by
+calling `add_underlay("javascript");` in their `import` function.
+
+You'll have to arrange for `<script>` tags to be added to the pages that
+use your javascript. This can be done using a `format` hook.
+
+Ikiwiki provides some utility functions in `ikiwiki.js`, for use by other
+javascript code. These include:
+
+#### `getElementsByClass(cls, node, tag)` 
+
+Returns an array of elements with the given class. The node and tag are
+optional and define what document node and element names to search.
+
+#### `hook(name, call)`
+
+The function `call` will be run as part of the hook named `name`.
+
+Note that to hook into `window.onload`, you can use the `onload' hook.
+
+#### `run_hooks(name)`
+
+Runs the hooks with the specified name.
diff --git a/doc/plugins/write/discussion.mdwn b/doc/plugins/write/discussion.mdwn
new file mode 100644 (file)
index 0000000..24a556f
--- /dev/null
@@ -0,0 +1,46 @@
+Maybe this is obvious, but the config variable lives in the IkiWiki module, and one probably 
+wants to call defaultconfig for most applications. 
+<pre>
+%IkiWiki::config=IkiWiki::defaultconfig();
+IkiWiki::Setup::load($config_file);
+print  join(",",keys %IkiWiki::config);
+</pre>
+
+[[DavidBremner]]
+
+I'm a little concerned about one aspect of the `%wikistate` variable that was just introduced.
+I think global state for each plugin is a fine idea, but I worry about making it persist across
+rebuilds.  (And by rebuild, I assume we're talking about the `--rebuild` option.)
+
+My reasoning is that a 'rebuild' should be similar to checking out a new copy of the wiki
+and building.  Another way of saying this is that all permanent state should be in the RCS.
+It is great that there is temporary state stored in other places - I think of it as indexing
+and caching.  I'm worried that with the persistence, plugin writers will start putting data
+there that isn't backed by the RCS and that will break IkiWiki's great abilities as a
+distributed wiki.
+
+[[Will]]
+
+> Well, if you look at state that already persists across rebuilds, we have
+> pagectime, which can be extracted from RCS only very slowly in many
+> cases. There's also the separate state stored by the aggregate plugin,
+> which is indeed independant of the RCS, and can in some cases not be
+> replecated by rebuilding a different checkout (if the data is gone from
+> the feeds). Then there's the session cookie database, and the user
+> database, which started out with a lot of local state, has been
+> whittled down by removing admin prefs and subscriptions, but still has
+> important state including password hashes.
+> 
+> So while I take your point about the potential for abuse,
+> there's certianly legitimate reasons to need to store data across
+> rebuilds. And plugins have always been able to drop their own files in
+> wikistatedir as aggregate does and have it persist, so the abuse
+> potential has always been there, the barrier has been lowered only
+> slightly.
+>
+> OTOH, if something can be added to the documentation that encourages
+> good behavior, that'd be a good thing ... --[[Joey]]
+
+---
+
+I would find this page clearer split up into sub-pages. Does anyone agree/disagree? -- [[users/Jon]]
index bda34b77188301c67cdf30c7dc85ac5ab492c008..e30bf2ff3d8d4f3e0cf1054fba7a136dbf9910a3 100644 (file)
@@ -1,8 +1,10 @@
 External plugins are standalone, executable programs, that can be written
 in any language. When ikiwiki starts up, it runs the program, and
-communicates with it using XML RPC. If you want to [[write]] an external
+communicates with it using [XML RPC][xmlrpc]. If you want to [[write]] an external
 plugin, read on..
 
+[xmlrpc]: http://www.xmlrpc.com/
+
 ikiwiki contains one sample external plugin, named `externaldemo`. This is
 written in perl, but is intended to be an example of how to write an
 external plugin in your favorite programming language. Wow us at how much
@@ -11,7 +13,7 @@ easier you can do the same thing in your favorite language. ;-)
 There's now a second external plugin, the [[rst]] plugin, written in
 python. It uses a `proxy.py`, a helper library for ikiwiki python plugins.
 
-[[toc ]]
+[[!toc ]]
 
 ## How external plugins use XML RPC
 
@@ -27,7 +29,7 @@ stdin, using XML RPC. Dispatch the command, and return its result to
 stdout, also using XML RPC. After reading a command, and before returning
 the result, the plugin can output XML RPC requests of its own, calling
 functions in ikiwiki. Note: *Never* make an XML RPC request at any other
-time. Ikiwiki won't be listening for it, and you will deadlock.
+time. IkiWiki won't be listening for it, and you will deadlock.
 
 When ikiwiki starts up an external plugin, the first RPC it will make
 is to call the plugin's `import()` function. That function typically makes
@@ -42,7 +44,7 @@ supported in ikiwiki version 2.6.
 
 ## Accessing data structures
 
-Ikiwiki has a few global data structures such as `%config`, which holds
+IkiWiki has a few global data structures such as `%config`, which holds
 its configuration. External plugins can use the `getvar` and `setvar` RPCs
 to access any such global hash. To get the "url" configuration value,
 call `getvar("config", "url")`. To set it, call 
@@ -83,7 +85,7 @@ language as part of their XML RPC interface.
 
 XML RPC has a limitation that it does not have a way to pass
 undef/NULL/None. There is an extension to the protocol that supports this,
-but it is not yet available in the [[cpan XML::RPC]] library used by
+but it is not yet available in the [[!cpan XML::RPC]] library used by
 ikiwiki.
 
 Until the extension is available, ikiwiki allows undef to be communicated
@@ -94,14 +96,13 @@ the sentinal.
 
 ## Function injection
 
-Some parts of ikiwiki are extensible by adding functions. For example, the
-RCS interface relies on plugins providing several IkiWiki::rcs_* functions.
+Some parts of ikiwiki are extensible by adding or overriding functions.
 It's actually possible to do this from an external plugin too. 
 
-To make your external plugin provide an `IkiWiki::rcs_update` function, for
+To make your external plugin override the `IkiWiki::formattime` function, for
 example, make an RPC call to `inject`. Pass it named parameters "name" and
 "call", where "name" is the name of the function to inject into perl (here
-"Ikiwiki::rcs_update" and "call" is the RPC call ikiwiki will make whenever
+"Ikiwiki::formattime" and "call" is the RPC call ikiwiki will make whenever
 that function is run.
 
 If the RPC call is memoizable, you can also pass a "memoize" parameter, set
@@ -132,12 +133,12 @@ large quantity of data conversion going on. In contrast, `preprocess` hooks
 are called generally rarely, and pass around minimal data.
 
 External plugins should avoid making RPC calls unnecessarily (ie, in a loop).
-Memoizing the results of appropriate RPC calls is one good way to minimise the
+Memoizing the results of appropriate RPC calls is one good way to minimize the
 number of calls.
 
 Injecting a replacement for a commonly called ikiwiki function
 could result in a lot more RPC calls than expected and slow
-eveything down. `pagetitle`, for instance, is called about 100 times
+everything down. `pagetitle`, for instance, is called about 100 times
 per page build. Whenever possible, you should tell ikiwiki to memoize
 injected functions.
 
index 8b12fd183c01f1bec27b37bb549bf06f34a1d1be..5345f71f257c2979065189942ac77ce1074fa1e6 100644 (file)
@@ -5,9 +5,9 @@ What should the plugin do? Let's make it calculate and output the Fibonacci
 sequence. To output the next number in the sequence, all a user has to do
 is write this on a wiki page:
 
-       [[fib ]]
+       \[[!fib]]
 
-When the page is built, the [[ikiwiki/PreProcessorDirective]] will be
+When the page is built, the [[ikiwiki/directive]] will be
 replaced by the next number in the sequence.
 
 Most of ikiwiki's plugins are written in Perl, and it's currently easiest
@@ -27,7 +27,7 @@ important one is the IkiWiki module.
 
        use warnings;
        use strict;
-       use IkiWiki 2.00;
+       use IkiWiki 3.00;
 
 Ok, boilerplate is out of the way. Now to add the one function that ikiwiki
 expects to find in any module: `import`. The import function is called when
@@ -39,16 +39,16 @@ register hooks that ikiwiki will call later.
        }
 
 This has hooked our plugin into the preprocess hook, which ikiwiki uses to
-expand [[PreprocessorDirectives|ikiwiki/preprocessordirective]]. Notice
+expand preprocessor [[directives|ikiwiki/directive]]. Notice
 that "fib" has shown up again. It doesn't actually have to match the module
 name this time, but it generally will. This "fib" is telling ikiwiki what
-kind of PreprocessorDirective to handle, namely one that looks like this:
+kind of preprocessor directive to handle, namely one that looks like this:
 
-       [[fib ]]
+       [[!fib ]]
 
 Notice the `\&preprocess`? This is how you pass a reference to a function,
 and the `preprocess` function is the one that ikiwiki will call to expand
-the PreprocessorDirective. So, time to write that function:
+the preprocessor directive. So, time to write that function:
 
        sub preprocess {
                my %params=@_;
@@ -98,7 +98,7 @@ And let's change the `preprocess` sub to use it:
 
 Feel free to try it out with a simple page like this:
 
-       [[fib ]], [[fib ]], [[fib ]], [[fib ]], [[fib ]]
+       [[!fib ]], [[!fib ]], [[!fib ]], [[!fib ]], [[!fib ]]
 
 Looks like it works ok, doesn't it? That creates a page that lists:
 
@@ -116,7 +116,7 @@ a page that uses fib. Now the inlined page will have one set of numbers,
 and the standalone page another. The numbers might even skip over part of
 the sequence in some cases.
 
-Obviously, using a global `$last` veriable was a bad idea. It would
+Obviously, using a global `$last` variable was a bad idea. It would
 work ok in a more regular cgi-based wiki, which only outputs one page per
 run. But since ikiwiki is a wiki *compiler*, things are a bit more
 complicated. It's not very hard to fix, though, if we do want the sequence
@@ -139,7 +139,7 @@ Ok, one more enhancement. Just incrementing the numbers is pretty boring.
 It would be nice to be able to jump directly to a given point in the
 sequence:
 
-       \[[fib seed=20]], [[fib ]], [[fib ]]
+       \[[!fib seed=20]], [[!fib ]], [[!fib ]]
 
 Just insert these lines of code inside `preprocess`, in the appropriate
 spot:
@@ -169,7 +169,7 @@ be a guard on how high it will go.
                }
                my $num=$last{$page}++;
                if ($num > 25) {
-                       return "[[fib will only calculate the first 25 numbers in the sequence]]";
+                       error "can only calculate the first 25 numbers in the sequence";
                }
                return fib($num);
        }
@@ -182,7 +182,7 @@ does for numbers less than 1. Or for any number that's not an integer. In
 either case, it will run forever. Here's one way to fix that:
 
                if (int($num) != $num || $num < 1) {
-                       return "[[fib positive integers only, please]]";
+                       error "positive integers only, please";
                }
 
 As these security problems have demonstrated, even a simple input from the
index 3c2b264fb3a7a5f65617473d1be898d7b35d009f..c78709e94e4e24c1019b515ebba391e7274e2582 100644 (file)
@@ -34,3 +34,90 @@ Regards.
 >              notify => 1,
 >      }
 >      ],
+
+
+Hello, I've setup ikiwiki with subversion. I can edit pages from web browser using CGI and, when I go to recentchanges, it shows that modification with "web" word. But, if I modify any .mdwn file, it gets updated in website but it doesn't show in recentchanges entry with "svn" word. If I run "svn ci -m changes", it shows in recentchanges correctly.
+
+So, I think I miss something, because I don't think I must run "svn add" or "svn commit" anytime I modify or create a wiki file.
+
+Thanks
+
+> Yes, ikiwiki does expect you to use your revision control system to check
+> in changes. Otherwise, recentchanges cannot work right, since it uses the
+> commit history from your revision control system. --[[Joey]]
+
+-----
+
+I'm working on an [[rcs]] plugin for CVS, adapted from `svn.pm`, in order
+to integrate ikiwiki at sites where that's all they've got. What's working
+so far: web commit (post-commit hook and all), diff, add (under certain
+conditions), and remove. What's not working: with rcs_add(), iff any of the
+new page's parent dirs aren't already under CVS control and the post-commit
+hook is enabled, the browser and ikiwiki stall for several seconds trying
+to add it, then time out. (If I kill ikiwiki when this is happening, it cvs
+adds the topmost parent that needed adding; if I wait for timeout, it
+doesn't. I think.) If I disable the post-commit hook and do the same kind
+of thing, the page is created and saved.
+
+In case you're lucky enough not to know, cvs adds on directories are weird
+-- they operate immediately against the repository, unlike file adds:
+
+    $ cvs add randomdir
+    Directory /Users/schmonz/Documents/cvswiki/repository/ikiwiki/randomdir added to the repository
+
+I was able to work out that when I'm seeing this page save misbehavior, my
+plugin is somewhere inside `system("cvs", "-Q", "add", "$file")`, which was
+never returning. If I changed it to anything other than cvs it iterated
+correctly over all the parent dirs which needed to be added to CVS, in the
+proper order. (cvs add isn't recursive, sadly.)
+
+Can you offer an educated guess what's going wrong here? --[[Schmonz]]
+
+> Got `rcs_recentchanges` working, believe it or not, thanks to [cvsps](http://www.cobite.com/cvsps/). If I can figure out this interaction between the post-commit hook and `cvs add` on directories, the CVS plugin is mostly done. Could it be a locking issue? Where should I be looking? Any suggestions appreciated. --[[Schmonz]]
+
+>> Okay, it is definitely a locking issue. First, on the conjecture that
+>> `cvs add <directory>` was triggering the post-commit hook and confusing
+>> ikiwiki, I wrapped the ikiwiki post-commit binary with a shell script
+>> that exited 0 if the triggering file was a directory. The first half of
+>> the conjecture was correct -- my wrapper got triggered -- but the web
+>> add of `one/two/three.mdwn` (where `one` and `two` weren't existing
+>> CVS-controlled dirs) remained hung as before. There were two ikiwiki
+>> processes running. On a whim, I killed the one with the higher PID; `cvs
+>> add one` immediately completed successfully, then back to a hang and two
+>> ikiwiki processes. I killed the newer one again and then `cvs add
+>> one/two` and `cvs add one/two/three.mdwn` completed and the web add was
+>> successful. --[[Schmonz]]
+
+>>> Aaaaaand I was wrong about the second half of the conjecture being
+>>> wrong. The wrapper script wasn't correctly identifying directories;
+>>> with that fixed, everything works. I've created a
+>>> [[plugins/contrib/cvs]] plugin page. Thanks for listening. :-)
+>>> --[[Schmonz]]
+
+>> Here is a comment I committed to my laptop from Madrid Airport before
+>> your most recent updates, in case it's still useful:
+>>
+>> Locking certianly seems likely to be a problem. ikiwiki calls `rcs_add`
+>> *before* disabling the post-commit plugin, since all over VCS allow
+>> adding something in a staged manner. You can see this in, for example,
+>> `editpage.pm` lines 391+.
+>> 
+>> So I guess what happens is that ikiwiki has taken the wiki lock, calls
+>> `rcs_add`, which does a `cvs add`, which runs the post commit hook,
+>> since it is not disabled -- which blocks waiting for the wiki lock.
+>>
+>> I guess you can fix this in either of three ways: Modify lots of places
+>> in ikiwiki to disable the post commit hook before calling `rcs_add`,
+>> or make cvs's `rcs_add` temporarily disable the commit hook and
+>> re-enable it (but only if it was not already disabled, somehow),
+>> or make cvs's `rcs_add` only make note that it needs to call `cvs add`
+>> later, and do so at `rcs_commit`. The last of these seems easist,
+>> especially since ikiwiki always commits after an add, in the same
+>> process, so you could just use a temporary list of things to add.
+>> --[[Joey]] 
+
+>>> Thanks for the comments. Attempting to set up a wiki on a different system with a different version of `cvs`, I've encountered a new locking problem within CVS: `cvs commit` takes a write lock, post-commit ikiwiki calls `rcs_update()`, `cvs update` wants a read lock and blocks. The easiest fix I can think of is to make `cvs commit` return and relinquish its lock -- so instead of my wrapper script `exec`ing ikiwiki's post-commit hook, I amp it off and exit 0. Seems to do the trick and, if I grok ikiwiki's behavior here, is not dangerous. (Beats me why my development `cvs` doesn't behave the same WRT locking.)
+
+>>> I was all set to take your third suggestion, but now that there's more than one CVS oddity fixed trivially in a wrapper script, I think I prefer doing it that way.
+
+>>> I'd be glad for the CVS plugin to be included in ikiwiki, if and when you deem it ready. Please let me know what needs to be done for that to happen. --[[Schmonz]]
index a6f3849f492fb3aa53acb19478ab7369154fbfc9..f66b854954e57f85b221fc1d9df5504e2701e663 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Revision Control Systems"]]
+[[!meta title="Revision Control Systems"]]
 
 Ikiwiki supports using several revision control systems for storing page
 histories. 
@@ -10,7 +10,7 @@ generic that it can be adapted to work with many systems by writing a
 [[git]] is another well-tested option.
 
 These are all the supported revision control systems:
-[[inline pages="rcs/* and !*/Discussion and !rcs/details" archive=yes]]
+[[!inline pages="rcs/* and !*/Discussion and !rcs/details" archive=yes]]
 
 There is a page with [[details]] about how the different systems work with
 ikiwiki, for the curious.
diff --git a/doc/rcs/darcs.mdwn b/doc/rcs/darcs.mdwn
new file mode 100644 (file)
index 0000000..fbb9bce
--- /dev/null
@@ -0,0 +1,15 @@
+[Darcs](http://darcs.new) is a distributed revison control
+system. Ikiwiki supports storing a wiki in a
+Darcs repository.
+
+An Ikiwiki wrapper is run by the `posthook` to update a wiki whenever commits
+or remote pushes come in. When running as a [[cgi]] with Darcs, ikiwiki
+automatically commits edited pages, and uses the Darcs history to generate the
+[[RecentChanges]] page.
+
+Example for a `_darcs/prefs/defaults` file in `$SRCDIR`:
+
+       apply posthook /path/to/repository/_darcs/ikiwiki-wrapper
+       apply run-posthook
+
+See also [[todo/darcs|todo/darcs]]
index a6174f439974df05398fa88597dbf027c3eb3063..6492cf38c6abe764c0b5c4eeb4f9ab1f42c67edd 100644 (file)
@@ -1,6 +1,6 @@
 A few bits about the RCS backends
 
-[[toc ]]
+[[!toc ]]
 
 ## Terminology
 
@@ -32,98 +32,20 @@ You browse and web-edit the wiki on W.
 W "belongs" to ikiwiki and should not be edited directly.
 
 
-## [darcs](http://darcs.net/) (not yet included)
+## [[darcs]]
 
-Support for using darcs as a backend is being worked on by [Thomas
-Schwinge](mailto:tschwinge@gnu.org), although development is on hold curretly.
-There is a patch in [[todo/darcs]].
+Regarding the repository layout: There are two darcs repositories. One is the `srcdir`, the other we'll call `master`.
 
-### How will it work internally?
+*  HTML is generated from `srcdir`.
+*  CGI edits happen in `srcdir`.
+*  The backend pulls updates from `master` into `srcdir`, i.e. darcs commits should happen to `master`.
+*  `master` calls ikiwiki (through a wrapper) in its apply posthook, i.e. `master/_darcs/prefs/defaults` should look like this:
 
-``Master'' repository R1.
-
-RCS commits from the outside are installed into R1.
-
-HTML is generated from R1.  HTML is automatically generated (by using a
-``post-hook'') each time a new change is installed into R1.  It follows
-that rcs_update() is not needed.
-
-There is a working copy of R1: R2.
-
-CGI operates on R2.  rcs_commit() will push from R2 to R1.
-
-You browse the wiki on R1 and web-edit it on R2.  This means for example
-that R2 needs to be updated from R1 if you are going to web-edit a page,
-as the user otherwise might be irritated otherwise...
-
-How do changes get from R1 to R2?  Currently only internally in
-rcs\_commit().  Is rcs\_prepedit() suitable?
-
-It follows that the HTML rendering and the CGI handling can be completely
-separated parts in ikiwiki.
-
-What repository should [[RecentChanges]] and History work on?  R1?
-
-#### Rationale for doing it differently than in the Subversion case
-
-darcs is a distributed RCS, which means that every checkout of a
-repository is equal to the repository it was checked-out from.  There is
-no forced hierarchy.
-
-R1 is nevertheless called the master repository.  It's used for
-collecting all the changes and publishing them: on the one hand via the
-rendered HTML and on the other via the standard darcs RCS interface.
-
-R2, the repository the CGI operates on, is just a checkout of R1 and
-doesn't really differ from the other checkouts that people will branch
-off from R1.
-
-(To be continued.)
-
-#### Another possible approach
-
-Here's what I (tuomov) think, would be a “cleaner” approach:
-
- 1. Upon starting to edit, Ikiwiki gets a copy of the page, and `darcs changes --context`.
-     This context _and_ the present version of the page are stored in as the “version” of the
-     page in a hidden control of the HTML.
-     Thus the HTML includes all that is needed to generate a patch wrt. to the state of the
-     repository at the time the edit was started. This is of course all that darcs needs.
- 2. Once the user is done with editing, _Ikiwiki generates a patch bundle_ for darcs.
-     This should be easy with existing `Text::Diff` or somesuch modules, as the Web edits
-     only concern single files. The reason why the old version of the page is stored in
-     the HTML (possibly compressed) is that the diff can be generated.
- 3. Now this patch bundle is applied with `darcs apply`, or sent by email for moderation…
-     there are many possibilities.
-
-This approach avoids some of the problems of concurrent edits that the previous one may have,
-although there may be conflicts, which may or may not propagate to the displayed web page.
-(Unfortunately there is not an option to `darcs apply` to generate some sort of ‘confliction resolution
-bundle’.) Also, only one repository is needed, as it is never directly modified
-by Ikiwiki. 
-
-This approach might be applicable to other distributed VCSs as well, although they're not as oriented
-towards transmitting changes with standalone patch bundles (often by email) as darcs is.
-
-> The mercurial plugin seems to just use one repo and edit it directly - is
-> there some reason that's okay there but not for darcs? I agree with tuomov
-> that having just the one repo would be preferable; the point of a dvcs is
-> that there's no difference between one repo and another. I've got a
-> darcs.pm based on mercurial.pm, that's almost usable... --bma
-
->> IMHO it comes down to whatever works well for a given RCS. Seems like
->> the darcs approach _could_ be done with most any distributed system, but
->> it might be overkill for some (or all?) While there is the incomplete darcs
->> plugin in [[todo/darcs]], if you submit one that's complete, I will
->> probably accept it into ikiwiki.. --[[Joey]]
-
->>> I'd like to help make a robust darcs (2) backend. I also think ikiwiki should use 
->>> exactly one darcs repo. I think we can simplify and say conflicting web
->>> edits are not allowed, like most current wiki engines. I don't see that 
->>> saving (so much) context in the html is necessary, then. 
->>> bma, I would like to see your code. --[[Simon_Michael]]
->>> PS ah, there it is. Let's continue on the [[todo/darcs]] page.
+       apply posthook ikiwrap
+       apply run-posthook
 
+*  The backend pushes CGI edits from `srcdir` back into `master` (triggering the apply hook).
+*  The working copies in `srcdir` and `master` should *not* be touched by the user, only by the CGI or darcs, respectively.
 
 ## [[Git]]
 
@@ -266,8 +188,7 @@ on the same local machine, I suggest to create the latter with the "`git clone -
 command to save disk space.
 
 Note that, as a rule of thumb, you should always put the rcs wrapper (`post-update`)
-into the master repository (`.git/hooks/`) as can be noticed in the Git wrappers of
-the sample [[ikiwiki.setup]].
+into the master repository (`.git/hooks/`).
 
 Here is how a web edit works with ikiwiki and git:
 
@@ -281,6 +202,9 @@ Here is a how a commit from a remote repository works:
 
 * git-commit in the remote repository
 * git-push, pushes the commit to the master repo on the server
+* (Optionally, the master repo's pre-receive hook runs, and checks that the
+  update only modifies files that the pushing user is allowed to update. 
+  If not, it aborts the receive.)
 * the master repo's post-update hook notices this update, and runs ikiwiki
 * ikiwiki notices the modifies page source, and compiles it
 
@@ -317,6 +241,8 @@ please refer to [Emanuele](http://nerd.ocracy.org/em/)
 
 ## [[tla]]
 
+Nobody really understands how tla works. ;-)
+
 ## rcs
 
 There is a patch that needs a bit of work linked to from [[todo/rcs]].
index 74402e1558e91638384d8a011511d20eb2f7ee32..000eb0b3cd6282b78c56cbec462782b74c116679 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Git"]]
+[[!meta title="Git"]]
 
 [Git][git] is a distributed revison control system originally developed for
 the Linux kernel. Ikiwiki supports storing a wiki in git.
@@ -17,16 +17,12 @@ shallow, single level tree, with a bare repository (meaning that it
 does not have a working tree checked out) at the root, and various
 working clones (with working directories) as leaf nodes.  The root
 (bare) repository is meant to be pushed to and pulled from the various
-working clones. The image below displays the relationship between the
-root repository and the clone repositories (this is not a directory
-layout):
-
-![Git repository relationships](http://people.debian.org/~srivasta/ikiwiki_git.png)
+working clones.
 
 One of the leaf node clone repositories is special; it has working
-directory which is used to compile the wiki from, and is also used by the
+directory which is used to compile the wiki, and is also used by the
 [[cgi]] to commit changes made via the web interface. It is special
-since the `post-commit` hook for the bare root repository is used to
+since the `post-update` hook for the bare root repository is used to
 trigger an update of this repository, and then an ikiwiki refresh
 updates the published  wiki itself.
 
@@ -47,9 +43,9 @@ repositories:
   repositories will push to/pull from.  It is a bare repository, since
   there are problems pushing to a repository that has a working
   directory. This is called _repository_ in [[ikiwiki-makerepo]]'s
-  manual page. Nominally, this bare repository has a `post-commit` hook
+  manual page. Nominally, this bare repository has a `post-update` hook
   that either is or calls ikiwiki's git wrapper, which changes to the
-  working directory for ikiwiki, does a _git pull_, and refreshes ikiwiki
+  working directory for ikiwiki, does a `git pull`, and refreshes ikiwiki
   to regenerate the wiki with any new content. The [[setup]] page describes
   how to do this.
 
@@ -68,7 +64,7 @@ repositories:
   hack on your wiki. you can commit local changes to the version on
   the laptop, perhaps while offline. Any new content should be pushed to the
   bare master repository when you are ready to publish it, and then
-  the post-commit hook of the bare repository will ensure that the
+  the post-update hook of the bare repository will ensure that the
   ikiwiki's source directory is updated, and the ikiwiki refreshed
   with the new content.
 
@@ -83,7 +79,7 @@ It is **paramount** that you **never** push to the non-bare repository
 Instead, clone the bare repository as mentioned above, and push
 **only** to the bare repository.
 
-The ikiwiki `post-commit` hook should be put in the bare repository.
+The ikiwiki `post-update` hook should be put in the bare repository.
 
 ## git repository with multiple committers
 
@@ -104,6 +100,33 @@ repository, should only be writable by the wiki's admin, and *not* by the
 group. Take care that ikiwiki uses a umask that does not cause files in
 the srcdir to become group writable. (umask 022 will work.)
 
+## git repository with untrusted committers
+
+By default, anyone who can commit to the git repository can modify any file
+on the wiki however they like. A `pre-receive` hook can be set up to limit
+incoming commits from untrusted users. Then the same limits that are placed
+on edits via the web will be in effect for commits to git for the users.
+They will not be allowed to edit locked pages, they will only be able to
+delete pages that the [[plugins/remove]] configuration allows them to
+remove, and they will only be allowed to add non-page attachments that the
+[[plugins/attachment]] configuration allows.
+
+To enable this, you need to set up the git repository to have multiple
+committers. Trusted committers, including the user that ikiwiki runs as, 
+will not have their commits checked by the `pre-receive` hook. Untrusted
+committers will have their commits checked. The configuration settings to
+enable are `git_test_receive_wrapper`, which enables generation of a
+`pre-receive` hook, and `untrusted_committers`, which is a list of
+usernames of the untrusted committers.
+
+Note that when the `pre-receive` hook is checking incoming changes, it
+ignores the git authorship information, and uses the username of the unix
+user who made the commit. Then tests including the `locked_pages` [[PageSpec]]
+are checked to see if that user can edit the pages in the commit.
+
+You can even set up an [[anonymous_user|tips/untrusted_git_push]], to allow
+anyone to push changes in via git rather than using the web interface.
+
 ## Optionally using a local wiki to preview changes
 
 When working on the "working clones" to add content to your wiki,
@@ -124,7 +147,7 @@ is the normal behaviour of ikiwiki, set the configuration of the local wiki:
 
       gitorigin_branch => "",
       ## git post-commit wrapper
-      wrapper => "/working/dir/.git/hooks/post-commit",
+      git_wrapper => "/working/dir/.git/hooks/post-commit",
 
 Then just committing should refresh the private ikiwiki on the local
 host.  Now just run `ikiwiki -setup localwiki.setup -getctime` and
@@ -138,3 +161,28 @@ have a hook that is run locally after pulling changes. Newer
 versions of git will have a `post-merge` hook that should work for
 this purpose.
 
+## Fix for error on git pull origin
+
+Error message when running git pull origin:
+
+    You asked me to pull without telling me which branch you
+    want to merge with, and 'branch.master.merge' in
+    your configuration file does not tell me either.  Please
+    name which branch you want to merge on the command line and
+    try again (e.g. 'git pull <repository> <refspec>').
+    See git-pull(1) for details on the refspec.
+    
+    If you often merge with the same branch, you may want to
+    configure the following variables in your configuration
+    file:
+    
+        branch.master.remote = <nickname>
+        branch.master.merge = <remote-ref>
+        remote.<nickname>.url = <url>
+        remote.<nickname>.fetch = <refspec>
+    
+    See git-config(1) for details.
+
+The solution is to run this command in your srcdir:
+
+    git config branch.master.remote origin
index 4c7df375a07c05dfa91fdb6e3e816f3e727c6518..92f630fc7170c915d3c83b071c5b0a5e9f524032 100644 (file)
@@ -83,3 +83,21 @@ Thanks to gitte on #git on Freenode and of course joeyh. Have a look at [[rcs/de
 I think it would be a good thing if the various git pages where somehow unified. It seems to me that [[tips/laptop_wiki_with_git]] is currently not so different from [[git]]. Let us see what joeyh thinks about the new git pages, but if this level of detail is to go there, I think it could pretty much include (maybe as sub pages) the info in [[tips/laptop_wiki_with_git]] and [[tips/laptop_wiki_with_git_extended]] --[[DavidBremner]]
 
 # Does 'push' from the shallow clones work for you? git-clone and git-fetch explicitly state it doesn't... 
+
+-------
+
+## Permissions for web users and local users editing and creating pages
+What is the right permissions setup for a situation where both web and local users will be editing and creatingt pages? 
+My usage is this: I have a repository /srv/git/wiki.git chowned to me:apache with 775/664 permissions recursively (where 'me' is my account and the ikiwiki administrator), a /srv/www/ikisrc chowned to apache:apache, and a /srv/www/html/wiki chowned to apache:apache. As is, I can commit to the wiki.git repo (because it is owned by me) and web users can commit to it as well (because the group also has write access) what happens when I create a new page from either of those sources? For example, the apache user running ikiwiki.cgi would create /srv/www/ikisrc/something.mdwn, commit and push it to /srv/git/wiki.git, but that new object is owned by apache:apache. If I then try to commit a change to something.mdwn from a cloned repo sitting on my laptop, for example, will the commit not fail because apache created the files? 
+
+Does that mean that apache:apache should just own everything, and I should only commit through that user (via git:// protocol only, maybe, or ssh as apache instead of myself)? For some reason, my head can't quite wrap itself around the whole permissions issue. Thanks. --mrled
+
+> Ikiwiki is designed so that you don't have to worry about this kind of permissions issue.
+> Instead you can just configure the ikiwiki.cgi, in the setup file, to be suid to your
+> user. Then there's no need to let the web server's user modify files at all. --[[Joey]]
+
+
+## using a local wiki to preview changes: an srcdir needed?
+I have read the hints about using a local wiki to preview changes, but I haven't understood: is it assumed that I should also have a separate "srcdir" for this local preview-wiki (as it is done for the main wiki site), or I could point the local ikiwiki's "srcdir" to the working dir? Can something bad happen if I do this? I guess no, because--as I see it--the reason to have 2 repos for the main site was only enabling pushing to it, so it's a peculiarity of git, and not a requirement for a clean functioning of ikiwiki.
+
+Ok, probably, I have answered my question myself, but I'll let this comment stay here, if someone else will be tinking about the same issue. --Ivan Z.
index 5eaae199742fe6c6079ea72b1712f01cc10a3bb2..ebfc352025d6e4c46e1dc4020faf512be6b4ce27 100644 (file)
@@ -2,7 +2,17 @@
 system developed by Matt Mackall. Ikiwiki supports storing a wiki in a
 mercurial repository.
 
-Ikiwiki can run as a post-update hook to update a wiki whenever commits
+Ikiwiki can run as a `post-commit` and/or `incoming` hook to update a wiki whenever commits or remote pushes
 come in. When running as a [[cgi]] with Mercurial, ikiwiki automatically
 commits edited pages, and uses the Mercurial history to generate the
 [[RecentChanges]] page.
+
+Example for a `.hg/hgrc` file in `$SRCDIR`:
+
+    [hooks]
+    post-commit = ikiwiki --setup /path/to/ikiwiki.setup --post-commit
+    incoming = ikiwiki --setup /path/to/ikiwiki.setup --post-commit
+
+Do not use `commit` or `precommit` hooks or ikiwiki will run into a dead lock when committing in `$SRCDIR`. Also note that `--post-commit` and not `--refresh` must be used to avoid dead locking when editing the pages via CGI interface.
+
+See also [[todo/mercurial|todo/mercurial]]
index babd5cf01726afbb29033763f69c1e3fc7e8cac9..2cfcdfbf54a113d4c06971aaf63233f39780872e 100644 (file)
@@ -17,3 +17,8 @@ There is also a mismatch between the way Ikiwiki handles conflicts and the
 way Monotone handles conflicts.  At present, if there is a conflict, then
 Ikiwiki will commit a revision with conflict markers before presenting it
 to the user.  This is ugly, but there is no clean way to fix it at present.
+
+Also note that not all recent ikiwiki features have been implemented in the
+monotone plugin.  At the moment we're missing:
+
+  * [[todo/Untrusted_push_in_Monotone]]
index cafd9b49b5cfb8a9d0ddfa7aa8c2fb39de8e0603..cad5d51f4e96edee1bed08611a38bad007180db0 100644 (file)
@@ -7,4 +7,4 @@ come in. When running as a [[cgi]] with tla, ikiwiki automatically
 commits edited pages to the Arch repostory, and uses the Arch
 log to generate the [[RecentChanges]] page.
 
-Note that the tla support needs the [[cpan MailTools]] perl module.
+Note that the tla support needs the [[!cpan MailTools]] perl module.
index d22a8f30e4541e73ee2b10b4a39a55d1b051edc4..3383fc703fb23bcbf6fbc8bd00367642539f7d67 100644 (file)
@@ -1,4 +1,6 @@
+[[!if test="enabled(meta)" then="""
 [[!meta title="RecentChanges"]]
+"""]]
 Recent changes to this wiki:
 
 [[!inline pages="internal(recentchanges/change_*) and !*/Discussion" 
index af46e162be7f89ab3efb33dc5dc96f1c0b3343ce..2f79f79784ef0efc73c5db8a52a9ff3250dad7f0 100644 (file)
@@ -7,9 +7,7 @@ This is the roadmap for ikiwiki development.
 
 Released 29 April 2006.
 
-The 1.x series changed a great deal over the more than 50 releases in its
-lifetime. It is now in maintenance mode, only security issues or really bad
-bugs will be fixed in 1.x going forward.
+The 1.x series is no longer supported.
 
 ----
 
@@ -31,28 +29,50 @@ bugs will be fixed in 1.x going forward.
 
 Released 30 April 2007.
 
-The 2.x series is expected to undergo continuing development for some time,
-adding improvements and new features, but avoiding changes that break
-backwards compatability.
+The 2.x series is now in maintenance mode. Only security fixes and fixes for
+really bad bugs will be applied going forward.
 
 ----
 
 # 3.0
 
-Still in the early planning stages, version 3.0 will be an opportunity to
-make significant transitions.
-
-* Default to using prefix_directives.
+Version 3.0 is an opportunity to make significant transitions.
+Read [[tips/upgrade_to_3.0]] for the steps you will need to
+follow when upgrading your wiki to this version.
+
+The highlights of the changes in version 3.0 include:
+
+* Support for uploading [[attachments|plugins/attachment]].
+* Can [[plugins/rename]] and [[plugins/remove]] pages and files via the web.
+* [[Web_based_setup|plugins/websetup]].
+* Blog-style [[plugins/comments]] as an alternative to Discussion pages.
+* Many other new plugins including [[plugins/htmlbalance]], [[plugins/format]],
+  [[plugins/progress]], [[plugins/color]], [[plugins/autoindex]],
+  [[plugins/cutpaste]], [[plugins/hnb]], [[plugins/creole]], [[plugins/txt]],
+  [[plugins/amazon_s3]], [[plugins/pinger]], [[plugins/pingee]],
+  [[plugins/edittemplate]]
+* The RecentChanges page is compiled statically, not generated from the CGI.
+* Support for additional revision control systems: [[rcs/bzr]],
+  [[rcs/monotone]]
+* Support for [[tips/untrusted_git_push]].
+* A new version (3.00) of the plugin API, exporting additional
+  commonly used functions from `IkiWiki.pm`.
+* Nearly everything in ikiwiki is now a plugin, from WikiLinks to page
+  editing, to RecentChanges.
+* Far too many bug fixes, features, and enhancements to list here.
+
+Released 31 December, 2008.
+
+The 3.x series is expected to undergo continuing development for some time,
+adding improvements and new features, but avoiding changes that break
+backwards compatability.
 
 ----
 
 # future goals
 
-* Improved [[todo/html]] stylesheets and templates.
-  _(status: [[css_market]] exists; it could always provide more stylesheets.  No alternate templates yet, though.)_
-* More documentation in the basewiki, including documentation for all enabled plugins.  Probably need some solution for [[todo/conditional_underlay_files]], too.
 * Conversion support for existing other wikis.
   (Being worked on for MoinMoin and TWiki by [[Josh_Triplett|JoshTriplett]]
   and Jamey Sharp; support for other wikis should fit into the same
   framework.)
-* [[TODO]], [[bugs]], [[soc]], ...
+* [[TODO]], [[bugs]], ...
diff --git a/doc/robots.txt b/doc/robots.txt
new file mode 100644 (file)
index 0000000..7be87f9
--- /dev/null
@@ -0,0 +1,2 @@
+User-Agent: *
+Disallow: /ikiwiki.cgi
index 33deafaa7c6b19c59e29519fa5f8870280b61c6e..6ea8cc60794e9fdc713e53ae79cd8b286906f84b 100644 (file)
@@ -1,11 +1,39 @@
-This is the SandBox, a page anyone can edit to try out ikiwiki.
+This is the [[SandBox]], a page anyone can edit to try out ikiwiki (version [[!version  ]]).
 
-blather
+----
+2009/7/13 Monday Blue...\\
+While working on [[http://eoffice.im.fju.edu.tw/phpbb/viewtopic.php?p=27199|[97] Phpbb 與 Dokuwiki 之間的往來]] (External Link to //http://eoffice.im.fju.edu.tw/phpbb/viewtopic.php?p=27199// not working?), surf Internet for Wikis supporting //Creole V1.0//, found this site.
+
+* I thought that creole markup is used by ikiwiki...
+* Thought about using //SVN/CVS// server, however with different idea
+* Kinda curious why **Tcl** does not show her face in this Wiki arena
+* It looks like that I was wrong, from Wikipedia Creole page it mention that ikiwiki is also adopting Creole markup.
+
+---
+
+Guten Morgen aus Deutschland. Wir mögen Umläuter (ich weiß, der Plural ist falsch, aber dafür hat er einen). Die sind heutzutage kein Ärgernis mehr.
+
+&amp;#x263a; becomes &#x263a; 
+
+<script>alert("If this pops, ikiwiki is not cross site scripting safe."); /* Fortunately, this does not work. */</script>
 
+--- 
+I try to have a discussion page !!!
 ----
 
+Testing OpenID some more..
+
+test more test
+[[中文显示]]
+
 Here's a paragraph.
 
+The following code block is pre-formatted:
+
+    Testing what
+    pre-formatted code blocks
+    look like.
+
 Here's another one with *emphasised* text.
 
 # Header
@@ -47,14 +75,10 @@ Bulleted list
        * four
         * five
 
-* a new list
- * with sub heads
- * like this
-
 ----
 
-[[template id=note text="this is generated by the [[plugins/haiku]] plugin"]]
-[[haiku hint="sandbox play"]]
+[[!template id=note text="this is generated by the [[plugins/haiku]] plugin"]]
+[[!haiku hint="sandbox play"]]
 
 ----
 
@@ -70,10 +94,80 @@ The haiku will change after every save, mind you.
 * [![ikiwiki logo](http://ikiwiki.info/logo/ikiwiki.png)](http://ikiwiki.info)
 * <a href="http://www.google.com/">plain old html link</a>
 * [[foo]]
-* WikiLink
 
 -----
 
-This sandbox is also a [[ikiwiki/blog]]!
+This SandBox is also a [[blog]]!
+
+[[!inline pages="sandbox/* and !*/Discussion" rootpage="sandbox" show="4" archive="yes"]]
+
+--------
+
+This gives an example of inline code: `tar | netcat` is a nice way to transfer bulk files over the net
+
+But, of course, rsync is better.
+
+----
+
+Let's see what happens... ~~
+
+#中文标题一
+##中文标题二
+###中文标题三
+...
+######中文标题六
+
+###正文:
+
+君不见,黄河之水天上来,奔流到海不复回。
+
+君不见,高堂明镜悲白发,朝如青丝暮成雪。
+
+人生得意须尽欢,莫使金樽空对月。
+
+天生我材必有用,千金散尽还复来。
+
+###列表:
+
+* 天空
+
+   1. 蓝色的
+   2. 好高啊
+
+* 海洋
+
+   1. 有鱼
+       
+       * 鲸鱼
+       * 鲨鱼
+           
+
+* 大地
+
+###链接:
+
+[谷歌](http://www.google.com)
+
+###引用:
+
+> 一级引用
+>
+> 一级引用
+>
+> > 二级引用
+>
+>> 没有空格也可以
+>>> 三级引用
+>
+> 回到一级引用
+
+
+----
+
+
+testing
+
+--
+[[!toc  levels=2]]
 
-[[inline pages="sandbox/* and !*/Discussion" rootpage="sandbox" show="4" archive="yes"]]
+[[Mamma Mia]]
diff --git a/doc/sandbox/Blagging_is_cool.mdwn b/doc/sandbox/Blagging_is_cool.mdwn
new file mode 100644 (file)
index 0000000..16aafa3
--- /dev/null
@@ -0,0 +1,6 @@
+This is a testing Blag-Entry.
+/me loves blagging.
+
+ * Entry one
+ * entry two
+
diff --git a/doc/sandbox/Bleep.mdwn b/doc/sandbox/Bleep.mdwn
new file mode 100644 (file)
index 0000000..316f729
--- /dev/null
@@ -0,0 +1,3 @@
+Just a test page ...
+
+... to see what happens.
diff --git a/doc/sandbox/I_hate_making_new_blog_entries_-_sometimes.wiki b/doc/sandbox/I_hate_making_new_blog_entries_-_sometimes.wiki
new file mode 100644 (file)
index 0000000..54914bb
--- /dev/null
@@ -0,0 +1,25 @@
+!!!Heading Three
+
+Itemized
+* list 
+* of
+* things
+
+or not
+1. mom
+1. hi
+1. there
+
+
+
+!!!Heading Three
+
+Itemized
+* list 
+* of
+* things
+
+or not
+1. mom
+1. hi
+1. there
diff --git a/doc/sandbox/Omgwtf_a_blof_post__33____33____33____33____33__1__33__1__33__11111__33____33____33__1__33__1__33____33__1five.html b/doc/sandbox/Omgwtf_a_blof_post__33____33____33____33____33__1__33__1__33__11111__33____33____33__1__33__1__33____33__1five.html
new file mode 100644 (file)
index 0000000..fc1757d
--- /dev/null
@@ -0,0 +1,31 @@
+<math xmlns="http://www.w3.org/1998/Math/MathML">
+  <mrow>
+    <msup>
+      <mfenced open="(" close=")">
+        <mrow>
+          <mi>a</mi>
+          <mo>+</mo>
+
+          <mi>b</mi>
+        </mrow>
+      </mfenced>
+      <mn>2</mn>
+    </msup>
+    <mo>-</mo>
+    <msub>
+
+      <mfenced open="{" close="}">
+        <mrow>
+          <mi>x</mi>
+          <mo>+</mo>
+          <mi>y</mi>
+        </mrow>
+      </mfenced>
+
+      <mi>i</mi>
+    </msub>
+  </mrow>
+</math>
+<br>
+test <b>test</b><abbr title="test">T.</abbr> <h1>test</h1>
+<a href="https://bugzilla.mozilla.org">øđ</a>
diff --git a/doc/sandbox/Test:_with_a_colon_in_its_name.mdwn b/doc/sandbox/Test:_with_a_colon_in_its_name.mdwn
new file mode 100644 (file)
index 0000000..b91d7cb
--- /dev/null
@@ -0,0 +1 @@
+what happens?
diff --git a/doc/sandbox/Teximg.mdwn b/doc/sandbox/Teximg.mdwn
new file mode 100644 (file)
index 0000000..8483c14
--- /dev/null
@@ -0,0 +1,2 @@
+[[!teximg code="E = - \frac{Z^2 \cdot  \mu \cdot e^4}{32\pi^2 \epsilon_0^2 \hbar^2 n^2}" ]]
+
diff --git a/doc/sandbox/Try_some_math_formulas.mdwn b/doc/sandbox/Try_some_math_formulas.mdwn
new file mode 100644 (file)
index 0000000..6c0fe6d
--- /dev/null
@@ -0,0 +1,6 @@
+# Title with $\TeX$
+
+* How about some math?
+* $\frac{1}{2} = \frac{3}{6}$
+
+and teximg? [[!teximg  code="\frac{1}{2}"]]
index 864f38c0d4e864425e571689ba6cf2fab67bac01..bc051b008e5be69ff07091ef2dc3abe6f712cb45 100644 (file)
@@ -1,3 +1,3 @@
-I recall testing this too, but I'm not sure where the test went. Let's try again. -- [[JonDowland]]
+I recall testing this too, but I'm not sure where the test went. Let's try again. -- [[users/Jon]]
 
 Context: [[todo/discussion_page_as_blog/discussion/castle]]
diff --git a/doc/sandbox/discussion.mdwn b/doc/sandbox/discussion.mdwn
new file mode 100644 (file)
index 0000000..d8c5656
--- /dev/null
@@ -0,0 +1,6 @@
+normally a sandbow doesn't have a discussion page 
+but it's a sandbox 
+
+- 
+little light 
+ikiwiki looks great 
diff --git a/doc/sandbox/foobak.mdwn b/doc/sandbox/foobak.mdwn
new file mode 100644 (file)
index 0000000..c0b526f
--- /dev/null
@@ -0,0 +1 @@
+Foobaka bakfoo.
diff --git a/doc/sandbox/test.mdwn b/doc/sandbox/test.mdwn
new file mode 100644 (file)
index 0000000..db20a2f
--- /dev/null
@@ -0,0 +1 @@
+testing my openid provider @ www.steve.org.uk
index e8ef805c905602868a210e19be350472e7f7d897..0e6074fbddede019531e82b77add6b307463a3dd 100644 (file)
@@ -1,3 +1,3 @@
 Testing nested inlines:
 
-[[inline pages="sandbox/test_nested_inlines/* and !sandbox/test_nested_inlines/*/*" feeds="no"]]
+[[!inline pages="sandbox/test_nested_inlines/* and !sandbox/test_nested_inlines/*/*" feeds="no"]]
diff --git a/doc/sandbox/한글.mdwn b/doc/sandbox/한글.mdwn
new file mode 100644 (file)
index 0000000..e0ba326
--- /dev/null
@@ -0,0 +1 @@
+~를 어떻게 할까~
diff --git a/doc/sandbox/한글페이지.mdwn b/doc/sandbox/한글페이지.mdwn
new file mode 100644 (file)
index 0000000..4fac797
--- /dev/null
@@ -0,0 +1,2 @@
+
+Wow test
index 52ef486e69f425751296a510f4350e8c33ab9051..939d65d01e23830a597ec18c27290295be6735f7 100644 (file)
@@ -6,7 +6,7 @@ security issues with this program than with cat(1). If, however, you let
 others edit pages in your wiki, then some possible security issues do need
 to be kept in mind.
 
-[[toc levels=2]]
+[[!toc levels=2]]
 
 ----
 
@@ -66,8 +66,7 @@ So it's best if only one person can ever directly write to those directories.
 ## setup files
 
 Setup files are not safe to keep in the same revision control repository
-with the rest of the wiki. Just don't do it. [[ikiwiki.setup]] is *not*
-used as the setup file for this wiki, BTW.
+with the rest of the wiki. Just don't do it.
 
 ## page locking can be bypassed via direct commits
 
@@ -362,9 +361,9 @@ allow the security hole to be exploited.
 
 The htmlscrubber did not block javascript in uris. This was fixed by adding
 a whitelist of valid uri types, which does not include javascript. 
-([[cve CVE-2008-0809]]) Some urls specifyable by the meta plugin could also
+([[!cve CVE-2008-0809]]) Some urls specifyable by the meta plugin could also
 theoretically have been used to inject javascript; this was also blocked
-([[cve CVE-2008-0808]]).
+([[!cve CVE-2008-0808]]).
 
 This hole was discovered on 10 February 2008 and fixed the same day
 with the release of ikiwiki 2.31.1. (And a few subsequent versions..)
@@ -377,7 +376,7 @@ parties.
 Cross Site Request Forging could be used to constuct a link that would
 change a logged-in user's password or other preferences if they clicked on
 the link. It could also be used to construct a link that would cause a wiki
-page to be modified by a logged-in user. ([[cve CVE-2008-0165]])
+page to be modified by a logged-in user. ([[!cve CVE-2008-0165]])
 
 These holes were discovered on 10 April 2008 and fixed the same day with
 the release of ikiwiki 2.42. A fix was also backported to Debian etch, as
@@ -391,7 +390,7 @@ pre-emtively guard against that, current versions of ikiwiki store password
 hashes (using Eksblowfish).
 
 If you use the [[plugins/passwordauth]] plugin, I recommend upgrading to
-ikiwiki 2.48, installing the [[cpan Authen::Passphrase]] perl module, and running
+ikiwiki 2.48, installing the [[!cpan Authen::Passphrase]] perl module, and running
 `ikiwiki-transition hashpassword` to replace all existing cleartext passwords
 with strong blowfish hashes. 
 
@@ -404,7 +403,17 @@ passwords in cleartext over the net to log in, either.
 This hole allowed ikiwiki to accept logins using empty passwords, to openid
 accounts that didn't use a password. It was introduced in version 1.34, and
 fixed in version 2.48. The [bug](http://bugs.debian.org/483770) was
-discovered on 30 May 2008 and fixed the same day. ([[cve CVE-2008-0169]])
+discovered on 30 May 2008 and fixed the same day. ([[!cve CVE-2008-0169]])
 
 I recommend upgrading to 2.48 immediatly if your wiki allows both password
 and openid logins.
+
+## Malformed UTF-8 DOS
+
+Feeding ikiwiki page sources containing certian forms of malformed UTF-8
+can cause it to crash. This can potentially be used for a denial of service
+attack.
+
+intrigeri discovered this problem on 12 Nov 2008 and a patch put in place
+later that day, in version 2.70. The fix was backported to testing as version
+2.53.3, and to stable as version 1.33.7.
index ed15da274f8c75137ba2170effabb4a722e78a09..89444c9a861e35f5067994bd5b760670db6acce6 100644 (file)
 This tutorial will walk you through setting up a wiki with ikiwiki.
 
-[[toc ]]
+[[!toc ]]
 
-## [[Download]] and [[install]] ikiwiki.
+## Install ikiwiki
 
 If you're using Debian or Ubuntu, ikiwiki is an `apt-get install ikiwiki` away.
 If you're not, see the [[download]] and [[install]] pages.
 
-## Decide where your wiki's files will go.
+## Create your wiki
 
-As a wiki compiler, ikiwiki builds a wiki from files in a source directory,
-and outputs the files to a destination directory.  If you keep your wiki in
-a version control system, the source directory will contain a working copy
-checked out from the version control system.
+All it takes to create a fully functional wiki using ikiwiki is running
+one command.
+[[!template id=note text="""
+For more control, advanced users may prefer to set up a wiki
+[[by_hand|byhand]].
+"""]]
 
-For the purposes of this tutorial, we'll set shell variables
-for these locations, and use those variables in the commands that follow.
+       % ikiwiki -setup /etc/ikiwiki/auto.setup
 
-       SRCDIR=~/wikiwc
-       DESTDIR=~/public_html/wiki/
+Or, set up a blog with ikiwiki, run this command instead.
 
-Note that ikiwiki owns the working copy directory; do not perform your own
-edits in ikiwiki's working copy.
+       % ikiwiki -setup /etc/ikiwiki/auto-blog.setup
 
-## Create the beginnings of your wiki.
+Either way, it will ask you a couple of questions.
 
-This will create a simple main page for the wiki.
+       What will the wiki be named? foo
+       What revision control system to use? git
+       What wiki user (or openid) will be admin? joey
+       Choose a password:
 
-       mkdir $SRCDIR
-       cd $SRCDIR
-       $EDITOR index.mdwn
+Then, wait for it to tell you an url for your new site..
 
-In the editor, you could start by entering a simple page like
-[[toggle id=page text="this one"]].
-[[toggleable id=page text="""
-       Welcome to your new wiki.
+       Successfully set up foo:
+               url:         http://example.com/~joey/foo
+               srcdir:      ~/foo
+               destdir:     ~/public_html/foo
+               repository:  ~/foo.git
+       To modify settings, edit ~/foo.setup and then run:
+               ikiwiki -setup ~/foo.setup
 
-       All wikis are supposed to have a \[[SandBox]],
-       so this one does too.
+Done! 
 
-       ----
+## Using the web interface
 
-       This wiki is powered by [ikiwiki](http://ikiwiki.info).
-"""]]
-   
-See [[ikiwiki/formatting]] for details about the markup language.
+Now you can go to the url it told you, and edit pages in your new wiki
+using the web interface.
 
-Note that several [[standard_wiki_pages|basewiki]] will be added to your
-wiki, from files in `/usr/share/ikiwiki/basewiki/`, so your wiki will
-automatically get a [[SandBox]], and some other useful pages.
+(If the web interface doesn't seem to allow editing or login, you may
+need to configure [[configure_the_web_server|tips/dot_cgi]].)
 
-## Build your wiki for the first time.
+## Checkout and edit wiki source
 
-       ikiwiki --verbose $SRCDIR $DESTDIR --url=http://example.org/~you/wiki/
+Part of the fun of using ikiwiki is not being limited to using the
+web for editing pages, and instead using your favorite text editor and
+[[Revision_Control_System|rcs]]. 
 
-Replace the url with the real url to your wiki. You should now
-be able to visit the url and see your wiki.
+To do this, you need to check out a copy of the source to your wiki.
+(You should avoid making changes directly to the `srcdir`, as that
+checkout is reserved for use by ikiwiki itself.)
 
-## Add content to your wiki.
+Depending on which [[Revision_Control_System|rcs]] you chose to use,
+you can run one of these commands to check out your own copy of your wiki's
+source. (Remember to replace "foo" with the real directory name.)
 
-Continue editing or adding pages and rebuilding the wiki.
-   
-To quickly get started on a common task like blogging with ikiwiki, you
-can copy in files from the [[examples]]. The examples are located in
-`doc/examples/` in the ikiwiki source package.
+       git clone foo.git foo.src
+       svn checkout file://`pwd`/foo.svn/trunk foo.src
+       bzr clone foo foo.src
+       hg clone foo foo.src
+       # TODO monotone, tla
 
-You can experiment with other ikiwiki parameters such as `--wikiname`
-and `--rebuild` too. Get comfortable with its command line (see
-[[usage]]).
+Now to edit pages by hand, go into the directory you checked out (ie,
+"foo.src"), and fire up your text editor to edit `index.mdwn` or whatever
+other page you want to edit. If you chose to set up a blog, there is even a
+sample first post in `posts/first_post.mdwn` that you can edit.
 
-## Add a setup file.
+Once you've edited a page, use your revision control system to commit
+the changes. For distributed revision control systems, don't forget to push
+your commit.
 
-By now you should be getting tired of typing in all the command line
-options each time you change something in your wiki's setup. Time to
-introduce setup files.
-   
-A sample setup file is [[ikiwiki.setup]]. Download it (or copy it from
-`doc/ikiwiki.setup` in the ikiwiki sources), and edit it. Note that this
-file should *not* be put in your wiki's directory with the rest of the
-files. A good place to put it is in a ~/.ikiwiki/ subdirectory.
-   
-Most of the options, like `wikiname` in the setup file are the same as
-ikiwiki's command line options (documented in [[usage]]. `srcdir` and
-`destdir` are the two directories you specify when running ikiwiki by
-hand. Make sure that these are pointing to the right directories, and
-read through and configure the rest of the file to your liking.
-
-When you're satisfied, run `ikiwiki --setup ikiwiki.setup`, and it
-will set everything up.
+Once the commit reaches the repository, ikiwiki will notice it, and
+automatically update the wiki with your changes.
 
-## Turn on additional features.
+## Customizing the wiki
 
-Now you have a basic wiki with a configuration file. Time to experiment
-with ikiwiki's many features. 
-   
-Let's first enable a key wiki feature and set up [[CGI]] to allow
-editing the wiki from the web. Just edit ikiwiki.setup, uncomment the
-block for the cgi wrapper, make sure the filename for the cgi wrapper
-is ok, run `ikiwiki --setup ikiwiki.setup`, and you're done!
+There are lots of things you can configure to customize your wiki.
+These range from changing the wiki's name, to enabling [[plugins]],
+to banning users and locking pages.
 
-There are lots of other configuration options in ikiwiki.setup that you
-can uncomment, configure, and enable by re-running
-`ikiwiki --setup ikiwiki.setup`. Be sure to browse through all the
-[[plugins]]..
+If you log in as the admin user you configured earlier, and go to
+your Preferences page, you can click on "Wiki Setup" to customize many
+wiki settings and plugins.
 
-## Put your wiki in revision control.
+Some settings cannot be configured on the web, for security reasons or
+because misconfiguring them could break the wiki. To change these settings,
+you can manually edit the setup file, which is named something like
+"foo.setup". The file lists all available configuration settings
+and gives a brief description of each.
 
-At this point you might want to check your wiki in to a revision control
-system so you can keep track of changes and revert edits. Depending
-on the revision control system you choose, the way this is done varies.
+After making changes to this file, you need to tell ikiwiki to use it:
 
-Note that the .ikiwiki subdirectory is where ikiwiki keeps its state, and
-should be preserved, but not checked into revision control.
+       % ikiwiki -setup foo.setup
 
-The new [[ikiwiki-makerepo]] command automates setting up a wiki in
-revision control.
-
-[[toggle id=subversion text="Subversion"]]
-[[toggleable id=subversion text="""
-       REPOSITORY=~/wikirepo
-       ikiwiki-makerepo svn $SRCDIR $REPOSITORY
-"""]]
+## Customizing file locations
 
-[[toggle id=git text="Git"]]
-[[toggleable id=git text="""
-       REPOSITORY=~/wiki.git
-       ikiwiki-makerepo git $SRCDIR $REPOSITORY
-
-Please see [[rcs/git]] for detailed documentation about how
-ikiwiki uses git repositories, and some important caveats
-about using the git repositories.
-"""]]
-
-[[toggle id=mercurial text="Mercurial"]]
-[[toggleable id=mercurial text="""
-       REPOSITORY=$SRCDIR
-       ikiwiki-makerepo mercurial $SRCDIR
-"""]]
+As a wiki compiler, ikiwiki builds a wiki from files in a source directory,
+and outputs the files to a destination directory. The source directory is
+a working copy checked out from the version control system repository.
 
-[[toggle id=bazaar text="Bazaar"]]
-[[toggleable id=bazaar text="""
-       REPOSITORY=$SRCDIR
-       ikiwiki-makerepo bzr $SRCDIR
-"""]]
+When you used `auto.setup`, ikiwiki put the source directory, destination
+directory, and repository in your home directory, and told you the location
+of each. Those locations were chosen to work without customization, but you
+might want to move them to different directories.
 
-[[toggle id=tla text="TLA"]]
-[[toggleable id=tla text="""
-       REPOSITORY=~/wikirepo
-       tla make-archive me@localhost--wiki $REPOSITORY
-       tla my-id "<me@localhost>"
-       cd $SRCDIR
-       tla archive-setup me@localhost--wiki/wiki--0
-       tla init-tree me@localhost--wiki/wiki--0
-       # Edit {arch}/=tagging-method and change the precious
-       # line to add the .ikiwiki directory to the regexp.
-       tla add *
-       tla import
-"""]]
+First, move the destination directory and repository around.
+   
+       % mv public_html/foo /srv/web/foo.com
+       % mv foo.git /srv/git/foo.git
 
-[[toggle id=monotone text="Monotone"]]
-[[toggleable id=monotone text="""
-       # These instructions are standard instructions to import a directory into monotone
-       # and set it up so that you don't need any passwords to use it
-       REPOSITORY=~/.ikiwiki/mtn.db
-       BRANCH=com.company.wikiname
-       # remember the password you use in the next step and
-       # substitute it for 'wikiKeyPass' in the get_passphrase() hook below
-       # note the you should never generate two monotone keys with the same name
-       mtn genkey web@machine.company.com
-       mtn db init --db=$REPOSITORY
-       mv $SRCDIR $SRCDIR-old
-       cd $SRCDIR-old
-       echo ".ikiwiki" > $SRCDIR-old/.mtn-ignore
-       mtn --db=$REPOSITORY --branch=$BRANCH import . -m "initial import"
-       cd ..
-       mtn --db=$REPOSITORY --branch=$BRANCH checkout $SRCDIR
-       mv $SRCDIR-old/.ikiwiki $SRCDIR
-       cat << EOF > $SRCDIR/_MTN/monotonerc
-       function get_passphrase (branchname)
-           return "wikiKeyPass"
-       end
-       EOF
-       rm -r $SRCDIR-old
-"""]]
+If you moved the repository to a new location, checkouts pointing at the
+old location won't work, and the easiest way to deal with this is to delete
+them and re-checkout from the new repository location.
+   
+       % rm -rf foo
+       % git clone /src/git/foo.git
 
-## Configure ikiwiki to use revision control.
-
-Once your wiki is checked in to the revision control system,
-you should configure ikiwiki to use revision control. Edit your
-ikiwiki.setup, and uncomment the lines for the revision control system
-you chose to use. Be sure to set `svnrepo` to $REPOSITORY, if using
-subversion. Uncomment the block for the wrapper for your revision
-control system, and configure the wrapper path in that block
-appropriately (for Git, it should be `$REPOSITORY/hooks/post-update`).
-
-Once it's all set up, run `ikiwiki --setup ikiwiki.setup` once more.
-Now you should be able to edit files in $SRCDIR, and use your revision
-control system to commit them, and the wiki will automatically update.
-And in the web interface, RecentChanges should work, and files changed
-by web users will also be committed using revision control.
+Finally, edit the setup file. Modify the settings for `srcdir`, `destdir`,
+`url`, `cgiurl`, `cgi_wrapper`, `git_wrapper`, etc to reflect where
+you moved things. Remember to run `ikiwiki -setup` after editing the
+setup file.
 
 ## Enjoy your new wiki!
 
diff --git a/doc/setup/byhand.mdwn b/doc/setup/byhand.mdwn
new file mode 100644 (file)
index 0000000..53f8d18
--- /dev/null
@@ -0,0 +1,190 @@
+This tutorial will walk you through setting up a wiki with ikiwiki,
+doing everything by hand. [[Setup]] has an easier method, but with less
+control.
+
+[[!toc ]]
+
+## Decide where your wiki's files will go.
+
+As a wiki compiler, ikiwiki builds a wiki from files in a source directory,
+and outputs the files to a destination directory.  If you keep your wiki in
+a version control system, the source directory will contain a working copy
+checked out from the version control system.
+
+For the purposes of this tutorial, we'll set shell variables
+for these locations, and use those variables in the commands that follow.
+
+       SRCDIR=~/wikiwc
+       DESTDIR=~/public_html/wiki/
+
+Note that ikiwiki owns the working copy directory; do not perform your own
+edits in ikiwiki's working copy.
+
+## Create the beginnings of your wiki.
+
+This will create a simple main page for the wiki.
+
+       mkdir $SRCDIR
+       cd $SRCDIR
+       $EDITOR index.mdwn
+
+In the editor, you could start by entering a simple page like
+[[!toggle id=page text="this one"]].
+[[!toggleable id=page text="""
+       Welcome to your new wiki.
+
+       All wikis are supposed to have a \[[SandBox]],
+       so this one does too.
+
+       ----
+
+       This wiki is powered by [ikiwiki](http://ikiwiki.info).
+"""]]
+   
+See [[ikiwiki/formatting]] for details about the markup language.
+
+Note that several [[standard_wiki_pages|basewiki]] will be added to your
+wiki, from files in `/usr/share/ikiwiki/basewiki/`, so your wiki will
+automatically get a [[SandBox]], and some other useful pages.
+
+## Build your wiki for the first time.
+
+       ikiwiki --verbose $SRCDIR $DESTDIR --url=http://example.org/~you/wiki/
+
+Replace the url with the real url to your wiki. You should now
+be able to visit the url and see your wiki.
+
+## Add content to your wiki.
+
+Continue editing or adding pages and rebuilding the wiki.
+   
+To quickly get started on a common task like blogging with ikiwiki, you
+can copy in files from the [[examples]]. The examples are located in
+`doc/examples/` in the ikiwiki source package.
+
+You can experiment with other ikiwiki parameters such as `--wikiname`
+and `--rebuild` too. Get comfortable with its command line (see
+[[usage]]).
+
+## Add a setup file.
+
+By now you should be getting tired of typing in all the command line
+options each time you change something in your wiki's setup. Time to
+introduce setup files.
+
+To generate a setup file, use `ikiwiki --dumpsetup`. You can pass
+all the options have you been including at the command line, and they
+will be stored in the setup file.
+
+       ikiwiki $SRCDIR $DESTDIR --url=http://example.org/~you/wiki/ --dumpsetup ikiwiki.setup
+
+Note that this file should *not* be put in your wiki's directory with
+the rest of the files. A good place to put it is in a ~/.ikiwiki/
+subdirectory.
+   
+Most of the options, like `wikiname` in the setup file are the same as
+ikiwiki's command line options (documented in [[usage]]). `srcdir` and
+`destdir` are the two directories you specify when running ikiwiki by
+hand. Make sure that these are pointing to the right directories, and
+read through and configure the rest of the file to your liking.
+
+When you're satisfied, run `ikiwiki --setup ikiwiki.setup`, and it
+will set everything up.
+
+## Turn on additional features.
+
+Now you have a basic wiki with a setup file. Time to experiment
+with ikiwiki's many features. 
+   
+Let's first enable a key wiki feature and set up [[CGI]] to allow
+editing the wiki from the web. Just edit ikiwiki.setup, uncomment the
+settings for the `cgi_wrapper`, make sure the filename for the cgi wrapper
+is ok, run `ikiwiki --setup ikiwiki.setup`, and you're done!
+
+There are lots of other configuration options in ikiwiki.setup that you
+can uncomment, configure, and enable by re-running
+`ikiwiki --setup ikiwiki.setup`. Be sure to browse through all the
+[[plugins]]..
+
+## Put your wiki in revision control.
+
+At this point you might want to check your wiki in to a revision control
+system so you can keep track of changes and revert edits. Depending
+on the revision control system you choose, the way this is done varies.
+
+Note that the .ikiwiki subdirectory is where ikiwiki keeps its state, and
+should be preserved, but not checked into revision control.
+
+The [[ikiwiki-makerepo]] command automates setting up a wiki in
+revision control.
+
+[[!toggle id=subversion text="Subversion"]]
+[[!toggleable id=subversion text="""
+       REPOSITORY=~/wikirepo
+       ikiwiki-makerepo svn $SRCDIR $REPOSITORY
+"""]]
+
+[[!toggle id=git text="Git"]]
+[[!toggleable id=git text="""
+       REPOSITORY=~/wiki.git
+       ikiwiki-makerepo git $SRCDIR $REPOSITORY
+
+Please see [[rcs/git]] for detailed documentation about how
+ikiwiki uses git repositories, and some important caveats
+about using the git repositories.
+"""]]
+
+[[!toggle id=mercurial text="Mercurial"]]
+[[!toggleable id=mercurial text="""
+       REPOSITORY=$SRCDIR
+       ikiwiki-makerepo mercurial $SRCDIR
+"""]]
+
+[[!toggle id=bazaar text="Bazaar"]]
+[[!toggleable id=bazaar text="""
+       REPOSITORY=$SRCDIR
+       ikiwiki-makerepo bzr $SRCDIR
+"""]]
+
+[[!toggle id=tla text="TLA"]]
+[[!toggleable id=tla text="""
+       REPOSITORY=~/wikirepo
+       tla make-archive me@localhost--wiki $REPOSITORY
+       tla my-id "<me@localhost>"
+       cd $SRCDIR
+       tla archive-setup me@localhost--wiki/wiki--0
+       tla init-tree me@localhost--wiki/wiki--0
+       # Edit {arch}/=tagging-method and change the precious
+       # line to add the .ikiwiki directory to the regexp.
+       tla add *
+       tla import
+"""]]
+
+[[!toggle id=monotone text="Monotone"]]
+[[!toggleable id=monotone text="""
+       # This assumes that you have already used "mtn genkey you@hostname".
+       REPOSITORY=~/wiki.monotone
+       ikiwiki-makerepo monotone $SRCDIR $REPOSITORY
+"""]]
+
+## Configure ikiwiki to use revision control.
+
+Once your wiki is checked in to the revision control system, you should
+configure ikiwiki to use revision control. Edit your ikiwiki.setup, set
+`rcs` to the the revision control system you chose to use.  Be careful, 
+you may need to use the 'fullname'.  For example, 'hg' doesn't work, you
+should use mercurial.  Be sure to set `svnrepo` to the directory for your
+repository, if using subversion. Uncomment the configuration for the wrapper
+for your revision control system, and configure the wrapper path appropriately 
+(for Git, it should be the path to `hooks/post-update` inside the bare git repository).
+
+Once it's all set up, run `ikiwiki --setup ikiwiki.setup` once more.
+Now you should be able to edit files in $SRCDIR, and use your revision
+control system to commit them, and the wiki will automatically update.
+And in the web interface, RecentChanges should work, and files changed
+by web users will also be committed using revision control.
+
+## Enjoy your new wiki!
+
+Add yourself to [[IkiWikiUsers]]. And check out
+the [[tips]] to find out how to get more out of ikiwiki.
index 807b64131be6a2b0bde8ec56b7ebced94a9e835e..0501f443a732a75d866a0613b70bdfbaec7d8e35 100644 (file)
@@ -96,25 +96,145 @@ What is the syntax for specifying the adminuser as an openid user?  I've tried a
 
 ----
 
-I apologize if this is the incorrect forum for this question, but I am trying to get ikiwiki set up and running with git.  I followed all the directions and all seems to work until I go back and try to make changes.  The steps I am performing:
+I apologize if this is the incorrect forum for this question, but I am
+trying to get ikiwiki set up and running with git.  I followed all the
+directions and all seems to work until I go back and try to make changes.
+The steps I am performing:
 
     cd $SRCDIR  (e.g. ~/ikisrc)
     vim index.mdwn (add a couple lines)
     git commit -a -m 'test'
     git push
 
-I then get a long error message which reads in part "You asked me to pull without telling me which branch you
-want to merge with, and 'branch.master.merge' in your configuration file does not tell me either." From that point on, I get:
+I then get a long error message which reads in part "You asked me to pull
+without telling me which branch you want to merge with, and
+'branch.master.merge' in your configuration file does not tell me either."
+From that point on, I get:
 
     sws@odin:~/dev/ikisrc$ git push
     To /home/git/repos/myikiwiki.git
      ! [rejected]        master -> master (non-fast forward)
     error: failed to push to '/home/git/repos/myikiwiki.git'
 
-If I do a git clone ssh://odin/path/to/$REPOSITORY from another machine and try to edit I get the same error sequence.  What am I doing wrong?
+If I do a git clone ssh://odin/path/to/$REPOSITORY from another machine and
+try to edit I get the same error sequence.  What am I doing wrong?
+
+> I don't know. The only time I have seen this message is when
+> the master git repository was not bare. All current instructions and
+> `ikiwiki-makerepo` have a proper bare repo used for the master
+> repository, but perhaps you followed some old, broken instructions, or 
+> forgot to make it bare? --[[Joey]] 
 
 -----
 
-I follow every steps of the setup procedure, change some templates and tried to modify some page through the web but was not able to do so. Every page seems to be locked by the adminuser user. When I remove the adminuser in the setup file, every ran fine. Did I miss something ? What is exactly the adminuser supposed to be allowed to ? Is he the only user allowed to modify pages ?
+I follow every steps of the setup procedure, change some templates and
+tried to modify some page through the web but was not able to do so. Every
+page seems to be locked by the adminuser user. When I remove the adminuser
+in the setup file, every ran fine. Did I miss something ? What is exactly
+the adminuser supposed to be allowed to ? Is he the only user allowed to
+modify pages ?
 
 > This was a bug in ikwiki that was fixed in version 2.44. --[[Joey]]
+
+-----
+
+pI hope you guys can put up with an absolute newbie. I am fairly new to linux and completely new to Perl. I have just installed MoinMoin locally in my PC, running ubuntu 8.4 and was about to use it until I ran into your ikiwiki. I thought ikiwiki is a better fit for what I want to do, so am seriously considering installing it as well in ubuntu. Except that the install seems way beyond my understanding.
+
+Do i need to install git first? Which git -- the git-core? Ubuntu's instructions on installing the git-core is: "sudo apt-get install git-core". Is that it? Do I need to do a git-init as well, or will the ikiwiki-makerepo handle that? If I have to do a git-init as well, what --share values should I specify?
+
+It seems I will have to install the ikiwiki from the tar.gz file. I have downloaded it, but do I need to install CPAN or CPAN++ first? That doesn't sound right. I am totally confused already. Does anyone have some install documents pitched to someone as ignorant as I am? -- [[WillDioneda]]
+
+> Ubuntu includes ikiwiki (in universe, I assume), so you should just be
+> able to use apt or synaptic to install the package, as documented on the
+> [[download]] page. Install git-core also to get git.
+> 
+> You do not need to use git-init if you use ikiwiki-makrepo. --[[Joey]]
+
+
+Thanks for your response. You're right. Ubuntu does have ikiwiki, except that it is an older version. I tried installing it; saw some error messages from the install, and decided against it. Plus the documentation here in ikiwiki.info seems slightly different. I made an executive/beginner decision: to go for the latest tarball. And found myself in deep water, ...
+
+Anyway, I think I might be able to install it from the tarball I downloaded. I've been reading the discussions, had a look at your screencasts, etc. I will give it another bash. -- [[WillDioneda]]
+
+----
+
+How do I set up cgi editing?  In setup I have:
+
+ * cgiurl => 'http://wiki.had.co.nz/edit.cgi'
+ * cgi_wrapper => 'edit.cgi'
+
+But I don't get an edit link on my pages?  What am I doing wrong?
+
+> Assuming you don't have the editpage plugin disabled, all you should need
+> to so is re-run `ikiwiki -setup` with the above config and it should
+> rebuild your wiki and add the edit links to pages. --[[Joey]]
+
+----
+
+I setup ikiwiki on a fedora 10 machine and I am using apache as my http server. Faced a few difficulties while setting it up as the default setup program left some suid files and group writeable directories on the system. It took some time to get it working and documented what I did at http://flyingtux.blogspot.com/2009/03/installing-ikiwiki.html. Thought it might be useful to someone here. (The version installed is 2.72)
+
+> ikiwiki makes wrappers suid by default, because this ensures that when
+> the ikiwiki.cgi is run by your web server, it runs as the user who owns
+> your wiki, and can thus write to it. ikiwiki is designed to run securely
+> suid. If your webserver uses some
+> mechanism to run the ikiwiki.cgi as the user who owns it, without the
+> suid bit being set, you *could* modify `cgi_wrappermode` in your setup
+> file to drop the suid bit. 
+> 
+> ikiwiki respects the umask, so if your umask is one that causes things to
+> be group writable, they will by. If you want to override that, there is
+> also a `umask        ` setting in your setup file. --[[Joey]] 
+
+----
+
+/etc/ikiwiki/auto.setup tries to get abs_path of a non-existent
+"repository" path (in ikiwiki-makerepo), and that doesn't work in my perl:
+
+<pre>
+[mort@localhost ~]$ perl -e 'use Cwd q{abs_path}; print abs_path("/var")'
+/var[mort@localhost ~]$ perl -e 'use Cwd q{abs_path}; print abs_path("/abcde")'
+[mort@localhost ~]$ 
+</pre>
+
+Because of this, /etc/ikiwiki/auto.setup fails: 
+
+<pre>
+$ ikiwiki -setup /etc/ikiwiki/auto.setup
+What will the wiki be named? wiki
+What revision control system to use? git
+What wiki user (or openid) will be admin? mort
+
+
+Setting up wiki ...
+internal error finding repository abs_path
+/etc/ikiwiki/auto.setup: failed to set up the repository with ikiwiki-makerepo
+
+usage: ikiwiki [options] source dest
+       ikiwiki --setup configfile
+$ perl -v
+
+This is perl, v5.8.8 built for i386-linux-thread-multi
+(with 2 registered patches, see perl -V for more detail)
+
+Copyright 1987-2007, Larry Wall
+
+Perl may be copied only under the terms of either the Artistic License or the
+GNU General Public License, which may be found in the Perl 5 source kit.
+
+Complete documentation for Perl, including FAQ lists, should be found on
+this system using "man perl" or "perldoc perl".  If you have access to the
+Internet, point your browser at http://www.perl.org/, the Perl Home Page.
+
+$ 
+</pre>
+
+Can't ikiwiki's "make test" perhaps test for this, so that one knows something will go wrong?
+-- Ivan Z.
+
+> FWIW, I tried the same thing with perl 5.8.8 from Debian etch, and its
+> Cwd does not have the problem. But I've modified `ikiwiki-makerepo` to
+> avoid using `abs_path` this way anyhow. --[[Joey]] 
+
+Thank you! I'm not a Perl programmer, so what's your opinion: is this behavior a violation of the specification of abs_path and I should report it to [ALTLinux](http://bugs.altlinux.org) (the distro)? --Ivan Z.
+
+> That is not entirely clear to me from the documentation. It doesn't
+> say the path has to exist, but doesn't say it cannot either. --[[Joey]]
index 037c31ee6ede9afb9719c60ae441358e3a658123..500146a319e07d90644048c358a7da3ae379fbda 100644 (file)
@@ -27,7 +27,7 @@ This page controls what shortcut links the wiki supports.
 * [[!shortcut name=debrt url="https://rt.debian.org/Ticket/Display.html?id=%s"]]
 * [[!shortcut name=debss url="http://snapshot.debian.net/package/%s"]]
   * Usage: `\[[!debss package]]`, `\[[!debss package#version]]`, or `\[[!debss package/version]]`.  See http://snapshot.debian.net for details.
-  [[!shortcut name=debwiki url="http://wiki.debian.org/%s"]]
+* [[!shortcut name=debwiki url="http://wiki.debian.org/%s"]]
 * [[!shortcut name=fdobug url="https://bugs.freedesktop.org/show_bug.cgi?id=%s" desc="freedesktop.org bug #%s"]]
 * [[!shortcut name=fdolist url="http://lists.freedesktop.org/mailman/listinfo/%s" desc="%s@lists.freedesktop.org"]]
 * [[!shortcut name=gnomebug url="http://bugzilla.gnome.org/show_bug.cgi?id=%s" desc="GNOME bug #%s"]]
@@ -61,17 +61,17 @@ This page controls what shortcut links the wiki supports.
 * [[!shortcut name=ohloh url="http://www.ohloh.net/projects/%s"]]
 
 To add a new shortcut, use the `shortcut`
-[[ikiwiki/PreprocessorDirective]]. In the url, "%s" is replaced with the
-text passed to the named shortcut, after url-encoding it, and '%S' is
-replaced with the raw, non-encoded text. The optional `desc` parameter
-controls the description of the link.
+[[ikiwiki/directive]]. In the url, "%s" is replaced with the
+text passed to the named shortcut, after [[!wikipedia url_encoding]]
+it, and '%S' is replaced with the raw, non-encoded text. The optional
+`desc` parameter controls the description of the link.
 
 Remember that the `name` you give the shortcut will become a new
-[[ikiwiki/PreprocessorDirective]].  Avoid using a `name` that conflicts
+[[ikiwiki/directive]].  Avoid using a `name` that conflicts
 with an existing directive.  These directives also accept a `desc`
 parameter that will override the one provided at definition time.
 
 If you come up with a shortcut that you think others might find useful,
 consider contributing it to the [shortcuts page on the ikiwiki
-ikiwiki](http://ikiwiki.info/shortcuts/), so that future versions of
+wiki](http://ikiwiki.info/shortcuts/), so that future versions of
 ikiwiki will include your shortcut in the standard underlay.
index 836ccdb9a6968f100e9e248fc8534c5ec93ea455..3c11ed423bcdffe552758ecca865b2da2e2f8b76 100644 (file)
@@ -1,6 +1,6 @@
 This map excludes discussion pages, as well as subpages that are in feeds.
 
-[[map pages="* and !*/discussion and !recentchanges
+[[!map pages="* and !*/discussion and !recentchanges
 and !bugs/* and !examples/*/* and !news/* and !tips/* and !plugins/*
 and !sandbox/* and !todo/* and !users/*
 and !*.css and !*.ico and !*.png and !*.svgz and !*.gif"]]
index 54ac53979b27324180f04d62ece427faf690f916..4c19b05852ff7ded993110151aafc8d8763b4f45 100644 (file)
@@ -1,47 +1,48 @@
 This page is used to control what smileys are supported by the wiki.
 Just write the text of a smiley to display it.
 
-* \:)  [[smileys/smile.png]]
-* \:-) [[smileys/smile.png]]
-* \:D  [[smileys/biggrin.png]]
-* \:-D [[smileys/biggrin.png]]
-* \B)  [[smileys/smile2.png]]
-* \B-) [[smileys/smile2.png]]
-* \:)) [[smileys/smile3.png]]
-* \:-))        [[smileys/smile3.png]]
-* \;)  [[smileys/smile4.png]]
-* \;-) [[smileys/smile4.png]]
-* \:\  [[smileys/ohwell.png]]
-* \:-\ [[smileys/ohwell.png]]
-* \:/  [[smileys/ohwell.png]]
-* \:-/ [[smileys/ohwell.png]]
-* \:|  [[smileys/neutral.png]]
-* \:-| [[smileys/neutral.png]]
-* \>:> [[smileys/devil.png]]
-* \X-( [[smileys/angry.png]]
-* \<:( [[smileys/frown.png]]
-* \:(  [[smileys/sad.png]]
-* \:-( [[smileys/sad.png]]
-* \:-? [[smileys/tongue.png]]
-* \:-P [[smileys/tongue.png]]
-* \:o  [[smileys/redface.png]]
-* \|)  [[smileys/tired.png]]
-* \|-) [[smileys/tired.png]]
-* \{OK}        [[smileys/thumbs-up.png]]
-* \{X} [[smileys/icon-error.png]]
-* \{i} [[smileys/icon-info.png]]
-* \(./)        [[smileys/checkmark.png]]
-* \(!) [[smileys/idea.png]]
-* \[!] [[smileys/attention.png]]
-* \/!\ [[smileys/alert.png]]
-* \(?) [[smileys/question.png]]
-* \{*} [[smileys/star_on.png]]
-* \{o} [[smileys/star_off.png]]
-* \{1}  [[smileys/prio1.png]]
-* \{2}  [[smileys/prio2.png]]
-* \{3}  [[smileys/prio3.png]]
+* \\:) [[smileys/smile.png]]
+* \\:-)        [[smileys/smile.png]]
+* \\:D [[smileys/biggrin.png]]
+* \\:-D        [[smileys/biggrin.png]]
+* \\B) [[smileys/smile2.png]]
+* \\B-)        [[smileys/smile2.png]]
+* \\:))        [[smileys/smile3.png]]
+* \\:-))       [[smileys/smile3.png]]
+* \\;) [[smileys/smile4.png]]
+* \\;-)        [[smileys/smile4.png]]
+* \\:\ [[smileys/ohwell.png]]
+* \\:-\        [[smileys/ohwell.png]]
+* \\:/ [[smileys/ohwell.png]]
+* \\:-/        [[smileys/ohwell.png]]
+* \\:| [[smileys/neutral.png]]
+* \\:-|        [[smileys/neutral.png]]
+* \\>:>        [[smileys/devil.png]]
+* \\X-(        [[smileys/angry.png]]
+* \\<:(        [[smileys/frown.png]]
+* \\:( [[smileys/sad.png]]
+* \\:-(        [[smileys/sad.png]]
+* \\:-?        [[smileys/tongue.png]]
+* \\:-P        [[smileys/tongue.png]]
+* \\:o [[smileys/redface.png]]
+* \\|) [[smileys/tired.png]]
+* \\|-)        [[smileys/tired.png]]
+* \\{OK}       [[smileys/thumbs-up.png]]
+* \\{X}        [[smileys/icon-error.png]]
+* \\{i}        [[smileys/icon-info.png]]
+* \\(./)       [[smileys/checkmark.png]]
+* \\(!)        [[smileys/idea.png]]
+* \\[!]        [[smileys/attention.png]]
+* \\/!\        [[smileys/alert.png]]
+* \\(?)        [[smileys/question.png]]
+* \\{x}        [[smileys/star_on.png]]
+* \\{*}        [[smileys/star_on.png]]
+* \\{o}        [[smileys/star_off.png]]
+* \\{1}        [[smileys/prio1.png]]
+* \\{2}        [[smileys/prio2.png]]
+* \\{3}        [[smileys/prio3.png]]
 
-For example: {*} B) {*}
+For example: {x} B) {x}
 
 ----
 
index fffb5bed4749f7420ddfae2d11d4fe5399b8bc4b..e05543bd5ebef99b6d1e93f1e9f8d637fecd1b85 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Summer of Code"]]
+[[!meta title="Summer of Code"]]
 
 This page includes information about ikiwiki's involvement in
 [Google Summer of Code](http://code.google.com/soc/).
index 870f2ca9b9758820be1336ba24ab0d175ce79ac0..88f06b0f1aa9808aaefb61650c3d011d07f58fd9 100644 (file)
@@ -3,6 +3,6 @@ have a great idea for an ikiwiki project not on this list, please file it
 as a todo item, and ask us if it might work as a Summer of Code project,
 but please don't add the `soc` tag yourself.
 
-[[inline pages="(todo/* or bugs/*) and link(soc) and !todo/done and
+[[!inline pages="(todo/* or bugs/*) and link(soc) and !todo/done and
 !link(todo/done) and !bugs/done and !link(bugs/done) and 
 !*/Discussion" actions=yes show=0]]
index b985079914f9230163a67283465fc9b71ed2b14f..4770fc942d43250221acabc2906c7ad938c9ca6c 100644 (file)
@@ -12,7 +12,7 @@
        display: block;
 }
 
-.author {
+.inlineheader .author {
        margin: 0;
        font-size: 18px;
        font-weight: bold;
        margin: 0;
        padding: 6px;
        list-style-type: none;
+}
+.actions li {
+       display: inline;
+       padding: .2em .4em;
+}
+.pageheader .actions ul {
        border-bottom: 1px solid #000;
 }
 
        border-bottom: 0;
 }
 
-.actions li {
+#otherlanguages ul {
+       margin: 0;
+       padding: 6px;
+       list-style-type: none;
+}
+#otherlanguages li {
        display: inline;
        padding: .2em .4em;
 }
+.pageheader #otherlanguages {
+       border-bottom: 1px solid #000;
+}
 
-.tags {
+div.inlinecontent {
+       margin-top: .4em;
+}
+
+.pagefooter {
+       clear: both;
+}
+.inlinefooter {
        clear: both;
 }
 
+.tags {
+}
+
 #pageinfo {
-       clear: both;
        margin: 1em 0;
        border-top: 1px solid #000;
 }
@@ -80,6 +103,7 @@ div.recentchanges {
        border-style: solid;
        border-width: 1px;
        overflow: auto;
+       clear: both;
        width: 100%;
        background: #eee;
        color: black !important;
@@ -140,12 +164,15 @@ div.recentchanges {
 .pagedate,
 .pagelicense,
 .pagecopyright {
-       clear: both;
        font-style: italic;
        display: block;
        margin-top: 1em;
 }
 
+.error {
+       color: #C00;
+}
+
 /* Used for invalid form fields. */
 .fb_invalid {
        color: red;
@@ -200,6 +227,8 @@ div.recentchanges {
        margin-left: 40px;
        margin-bottom: 40px;
        padding: 2ex 2ex;
+       background: white;
+       color: black !important;
 }
 
 /* outlines */
@@ -241,6 +270,22 @@ div.poll {
        border: 1px solid #aaa;
 }
 
+div.progress {
+       margin-top: 1ex;
+       margin-bottom: 1ex;
+       border: 1px solid #888;
+       width: 400px;
+       background: #eee;
+       color: black !important;
+       padding: 1px;
+}
+div.progress-done {
+       background: #ea6 !important;
+       color: black !important;
+       text-align: center;
+       padding: 1px;
+}
+
 input#openid_url {
        background: url(wikiicons/openidlogin-bg.gif) no-repeat;
        background-color: #fff;
@@ -249,6 +294,14 @@ input#openid_url {
        padding-left: 18px;
 }
 
+input#searchbox {
+       background: url(wikiicons/search-bg.gif) no-repeat;
+       background-color: #fff;
+       background-position: 100% 50%;
+       color: #000;
+       padding-right: 16px;
+}
+
 /* Things to hide in printouts. */
 @media print {
        .actions { display: none; }
@@ -267,6 +320,8 @@ input#openid_url {
        margin-bottom: 1ex;
        padding: 1ex 1ex;
        border: 1px solid #aaa;
+       background: white;
+       color: black !important;
 }
 
 /* Provided for use by template plugin for floating note boxes. */
@@ -277,7 +332,9 @@ input#openid_url {
        margin-bottom: 1ex;
        padding: 1ex 1ex;
        border: 1px solid #aaa;
-       width: 25%
+       width: 25%;
+       background: white;
+       color: black !important;
 }
 
 /* Used by the popup template and for backlinks hiding. */
@@ -299,11 +356,6 @@ input#openid_url {
        border: 2px solid;
        background-color: #dee;
        color: black;
-       
-       /* Nonstandard, but very nice. */
-       opacity: 0.95;
-       -moz-opacity: 0.95;
-       filter: alpha(opacity=95);
 }
 
 /* Formbuilder styling */
@@ -328,3 +380,42 @@ legend {
        background: #eee; 
        color: black !important;
 }
+
+span.color {
+       padding: 2px;
+}
+
+.comment-header,
+.microblog-header {
+       font-style: italic;
+       margin-top: .3em;
+}
+.comment .author,
+.microblog .author {
+       font-weight: bold;
+}
+.comment-subject {
+       font-weight: bold;
+}
+.comment {
+       border: 1px solid #aaa;
+       padding: 3px;
+}
+
+/* Used by the highlight plugin. */
+
+pre.hl { color:#000000; background-color:#ffffff; }
+.hl.num { color:#2928ff; }
+.hl.esc { color:#ff00ff; }
+.hl.str { color:#ff0000; }
+.hl.dstr { color:#818100; }
+.hl.slc { color:#838183; font-style:italic; }
+.hl.com { color:#838183; font-style:italic; }
+.hl.dir { color:#008200; }
+.hl.sym { color:#000000; }
+.hl.line { color:#555555; }
+.hl.mark { background-color:#ffffbb; }
+.hl.kwa { color:#000000; font-weight:bold; }
+.hl.kwb { color:#830000; }
+.hl.kwc { color:#000000; font-weight:bold; }
+.hl.kwd { color:#010181; }
index a210df09c563cecd94322e33dc6a513d8e5d3433..71d925b2458155a13a75ef7ce77497467ef2f13c 100644 (file)
@@ -9,15 +9,15 @@ special link that ikiwiki knows is intended to be used as a tag.
 Generally you will tag a page without putting a visible link on it.
 The [[tag_plugin|plugins/tag]] allows you to do so, like this:
 
-       \[[tag mytag othertag thirdtag]]
+       \[[!tag mytag othertag thirdtag]]
 
 You can also tag a page with a visible link:
 
-       \[[taglink mytag]]
+       \[[!taglink mytag]]
 
 This tag will be displayed just like a regular [[ikiwiki/WikiLink]].
 
-One way to use these tags is to create a [[ikiwiki/blog]] of pages that have a
+One way to use these tags is to create a [[blog]] of pages that have a
 particular set of tags. Or just look at the [[BackLinks]] to a tag page to
 see all the pages that are tagged with it. [[Plugins]] can be written to do
 anything else with tags that you might desire.
index a45ecf6e262fff7eb2f938304dd7a201943b5d77..d7a6297c0cb9735041f4d4670dc9bd85bbfab15a 100644 (file)
@@ -1,6 +1,6 @@
 In another blog, I could tag a post with arbitrary words and not have to do
 anything else for the software to recognize it as a tag.  In Ikiwiki if you
-want to tag something \[[tag foo]] you also have to go to tags/ and create
+want to tag something \[[!tag foo]] you also have to go to tags/ and create
 foo.mkdn (even if it's zero-length), because "tags are links", and links
 don't actually *link* if they have no destination.  This allows for
 customization of how you present different tag feeds, but this (to me) is
index 58d5d11461f77194036c30b919f61d42a53e2dc3..eff0e15e93d5930821677833ce4de8619658fb44 100644 (file)
@@ -9,8 +9,6 @@ wiki.
 
 [[!if test="enabled(template) and enabled(inline)" then="""
 
-## Available templates
-
 These templates are available for inclusion onto other pages in this
 wiki:
 
@@ -50,6 +48,9 @@ module, which allows for some fairly complex things to be done. Consult its
 documentation for the full syntax, but all you really need to know are a
 few things:
 
+* Each parameter you pass to the template directive will generate a 
+  template variable. There are also some pre-defined variables like PAGE
+  and BASENAME.
 * To insert the value of a variable, use `<TMPL_VAR variable>`. Wiki markup
   in the value will first be converted to html.
 * To insert the raw value of a variable, with wiki markup not yet converted
@@ -62,7 +63,7 @@ few things:
 Here's a sample template:
 
         <span class="infobox">
-        Name: [[<TMPL_VAR raw_name>]]<br />
+        Name: \[[<TMPL_VAR raw_name>]]<br />
         Age: <TMPL_VAR age><br />
         <TMPL_IF NAME="color">
         Favorite color: <TMPL_VAR color><br />
@@ -80,6 +81,7 @@ that contains it, so you can include WikiLinks and all other forms of wiki
 markup in the template. Note though that such WikiLinks will not show up as
 backlinks to the page that uses the template.
 
-Note the use of "raw_name" inside the [[WikiLink]] generator. This ensures
-that if the name contains something that might be mistaken for wiki markup,
-it's not converted to html before being processed as a [[WikiLink]].
+Note the use of "raw_name" inside the [[ikiwiki/WikiLink]] generator. This
+ensures that if the name contains something that might be mistaken for wiki
+markup, it's not converted to html before being processed as a
+[[ikiwiki/WikiLink]].
diff --git a/doc/templates/discussion.mdwn b/doc/templates/discussion.mdwn
new file mode 100644 (file)
index 0000000..220d364
--- /dev/null
@@ -0,0 +1,8 @@
+This confuses me enormously. Perhaps because I am new to ikiwiki, to perl, to Linux, etc.
+
+note and popups are templates? But they're not in the templates directory, and in my readings here, templates are supposed to be in the ../templates directory. 
+
+> Ikiwiki has an basewiki underlay that provides wiki files not included in
+> your personal wiki sources. The note and popup template pages are
+> installed there, typically in `/usr/share/ikiwiki/basewiki/templates/`
+> --[[Joey]]
diff --git a/doc/templates/gitbranch.mdwn b/doc/templates/gitbranch.mdwn
new file mode 100644 (file)
index 0000000..fcce925
--- /dev/null
@@ -0,0 +1,18 @@
+<span class="infobox">
+Available in a [[!taglink /git]] repository.<br />
+Branch: <TMPL_VAR branch><br />
+Author: <TMPL_VAR author><br />
+</span>
+<TMPL_UNLESS NAME="branch">
+This template is used to create an infobox for a git branch. It uses
+these parameters:
+
+<ul>
+<li>branch - the name of the branch, prefixed with the name of one of the
+  remotes listed on the [[/git]] page and provided by the gitremotes script
+  (e.g. github/master)</li>
+<li>author - the author of the branch</li>
+</ul>
+
+It also automatically tags the branch with `/git`.
+</TMPL_UNLESS>
index d29e721a97771b5b156b199e4f8bc7fcb0b2fed7..c1d1974d6420b38b185e10587be65932661b751b 100644 (file)
@@ -1,13 +1,13 @@
 <span class="infobox">
 Plugin: <TMPL_VAR name><br />
 Author: <TMPL_VAR author><br />
-Included in ikiwiki: [[if test="sourcepage(plugins/contrib/*)" then="""no""" else="""yes"""]]<br />
+Included in ikiwiki: [[!if test="sourcepage(plugins/contrib/*)" then="""no""" else="""yes"""]]<br />
 Enabled by default: <TMPL_IF core>yes<TMPL_ELSE>no</TMPL_IF><br />
-Included in [[/plugins/goodstuff]]: [[if test="backlink(plugins/goodstuff)" all=no then="""yes""" else="""no"""]]<br />
-Currently enabled: [[if test="enabled(<TMPL_VAR name>)" then="yes" else="no"]]<br />
+Included in [[/plugins/goodstuff]]: [[!if test="backlink(plugins/goodstuff)" all=no then="""yes""" else="""no"""]]<br />
+Currently enabled: [[!if test="enabled(<TMPL_VAR name>)" then="yes" else="no"]]<br />
 </span>
-[[if test="sourcepage(plugins/contrib/*)" then="""[[meta title="<TMPL_VAR name> (third party plugin)"]]"""]]
-<TMPL_IF core>[[tag plugins/type/core]]</TMPL_IF>
+[[!if test="sourcepage(plugins/contrib/*)" then="""[[!meta title="<TMPL_VAR name> (third party plugin)"]]"""]]
+<TMPL_IF core>[[!tag plugins/type/core]]</TMPL_IF>
 <TMPL_UNLESS NAME="name">
 This template is used to create an infobox for an ikiwiki plugin. It uses
 these parameters:
index 74d03d7bf1b0545535cdbba9c22d7cdef1655eca..787df9bf7d973cb03d50180a5270da164bac55c9 100644 (file)
@@ -5,12 +5,14 @@ choose. If you'd like to fund development of a specific feature, see the
 
 <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=joey%40kitenet%2enet&item_name=ikiwiki&no_shipping=1&cn=Comments%3f&tax=0&currency_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8"><img src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" alt="donate with PayPal" /></a>
 
-If you would like your donation listed here, let [[Joey]] know. Thanks to
-the following people for their kind contributions:
+Thanks to the following people for their kind contributions:
 
 * James Westby
 * Kyle S MacLea
 * Adam Shand
 * Martin Krafft
+* Paweł Tęcza
+* Mick Pollard
 
-(Note that this page is locked to prevent anyone from tampering with the PayPal button.)
+(Note that this page is locked to prevent anyone from tampering with the PayPal button.
+If you prefer your donation *not* be listed here, let [[Joey]] know.)
index f0eb43f0cb8f6825a9fcf3c41e63b165e4c36485..53f966001e1a2f9a18648a4da2ccad8ba4f007c9 100644 (file)
@@ -1,5 +1,5 @@
 This page is a place to document tips and techniques for using ikiwiki.
 
-[[inline pages="tips/* and !tips/*/*" 
+[[!inline pages="tips/* and !tips/*/*" 
 feedpages="created_after(tips/howto_avoid_flooding_aggregators)" archive="yes"
 rootpage="tips" postformtext="Add a new tip about:" show=0]]
diff --git a/doc/tips/Adding_Disqus_to_your_wiki.mdwn b/doc/tips/Adding_Disqus_to_your_wiki.mdwn
new file mode 100644 (file)
index 0000000..01447b0
--- /dev/null
@@ -0,0 +1,26 @@
+<a href="http://disqus.com">Disqus</a> is a comment system that you can add to your blog to manage comments.
+
+To add it to ikiwiki first create an account at disqus and add you blog. Then click on the Admin link at that top of the main page.
+
+In the admin section there should be a tab called "Tools" for you site. Select the "Generic Code" option to install your site and then tweak the settings so the comments box looks like you want. This will then create a bit of javascript. Copy that code.
+
+In ikiwiki templates edit the page.tmpl and somewhere down the bottom, I put mine just before the footer, paste in the code that you had from before. This will add a disqus comment box to every page on your site.
+
+If you want to change your blog to also use the comments then you need to edit the inlinepage.tmpl template as well. This time remove the lines 
+
+    <TMPL_IF NAME="DISCUSSIONLINK">
+    <li><TMPL_VAR DISCUSSIONLINK></li>
+
+and replace with
+
+    <li>
+    <TMPL_IF NAME="PERMALINK">
+    <a href="<TMPL_VAR PERMALINK>">Comment</a>
+    <TMPL_ELSE>
+    <a href="<TMPL_VAR PAGEURL>">Comment</a>
+    </TMPL_IF>
+    </li>
+
+This changes the discussion link to a Comment link that takes you to the full page for that blog entry which should contain the disqus comments form that you added before.
+
+Note: This does then mean that to add a comment people need to have javascript enabled.
index 5af894d160359285acbd2a538b2ecc527b3cc196..070638e3e41a947f5717f92f26365459cd673bb9 100644 (file)
@@ -10,7 +10,11 @@ We're going to assume that you're installing CPAN and other Perl modules into ~/
 
 In your .bashrc/.bash_profile/.profile, add:
 
-    export PERL5LIB=~/site/perl/share/perl/5.8:~/site/perl/share/perl/5.8.4:~/site/perl/lib/perl5:~/site/perl/lib/perl/5.8.4
+    export PERL5LIB="$HOME/site/perl/share/perl/5.8:$HOME/site/perl/share/perl/5.8.4:$HOME/site/perl/lib/perl5:$HOME/site/perl/lib/perl/5.8.4"
+
+These locations may be different on your computer. For example, I use:
+
+    export PERL5LIB="$HOME/site/perl/lib/perl5:$HOME/site/perl/lib/perl5/site_perl/5.8.8:$PERL5LIB"
 
 You probably want to add *~/site/perl/bin/* to your path, as well, since Ikiwiki's scripts are put in there.
 
@@ -138,7 +142,7 @@ In ikiwiki.setup, you have to make your source and destination folders have your
     [good]$ ls -la ~
     lrwxrwxrwx  1 root staff 25 2007-08-03 16:44 /home/user -> /home/.server/user
 
-So far, it looks like only the source and destination parameters require this unsymlinked path, but for paranoia reasons, you may want to put them everywhere.  [[news/version_2.14]] explains why this happens.
+So far, it looks like only the source and destination parameters require this unsymlinked path, but for paranoia reasons, you may want to put them everywhere. The changelog for version 2.14 explains why this happens.
 
 Next, add your installed Perl module directory to the *libdir* parameter.  It should look something like :
 
@@ -146,6 +150,8 @@ Next, add your installed Perl module directory to the *libdir* parameter.  It sh
         libdir => "/home/.server/user/site/perl/lib/perl5/",
 
 # CGI Wrapper
+The CGI wrapper file will be created automatically by "ikiwiki --setup path/to/setup", as long as you have inserted a valid filename to be created into the setup file.  On DreamHost, be careful not to put the ikiwiki.cgi file in a directory that has different owner/group than the file itself (such as the main site.domain.tld/ directory): this will cause suexec to fail.
+
 The wrapper mode of "06755" doesn't seem to work.  "755" appears to.  However, this may be completely insecure and/or buggy, so if you know better than I, edit this doc and add it here.
 
 # Pre-created SVN repository
index 03ed78700f9b795baae1dcd9c306189a22ebf0d9..258d385ae17b438aeb09075b76debcadeb9485cd 100644 (file)
@@ -1,3 +1,18 @@
 I managed to install ikiwiki on eggplant farms, with most basic features except markdown.
 
 I think ikiwiki is more suitable for VPS/dedicated server. Shared hosting doesn't fit.
+
+I just (2009/04/27) installed ikiwiki on DreamHost and the CPAN instructions here are unnecessarily complicated. I used "cpan" instead of "perl -MCPAN -e shell" and had no trouble with  that portion of the install. --[[schmonz]]
+
+After tiring of managing things by hand, I've switched to using
+pkgsrc as an unprivileged user. This uses a bit more disk for my
+own copies of perl, python, etc., but in exchange I can `cd
+.../pkgsrc/www/ikiwiki && make install` and everything just works.
+Plus I get all the benefits of a package system, like easy uninstalling
+and being notified of outdated or insecure software.
+
+The only catch: sometimes the package dependency tree gets too deep
+for DreamHost's user process limit, resulting in build death. I
+work around this by resuming the build partway down the tree, then
+trying again from whatever I was actually trying to install.
+--[[schmonz]]
diff --git a/doc/tips/Git_repository_and_web_server_on_different_hosts.mdwn b/doc/tips/Git_repository_and_web_server_on_different_hosts.mdwn
new file mode 100644 (file)
index 0000000..58940b8
--- /dev/null
@@ -0,0 +1,61 @@
+One may want to provide ikiwiki hosting with [[rcs/git]]+ssh access and web
+server located at different hosts. Here's a description for such
+a setup, using password-less SSH as a way of communication between
+these two hosts.
+
+Git server
+==========
+
+Let's create a user called `ikiwiki_example`. This user gets SSH
+access restricted to GIT pull/push, using `git-shell` as a shell.
+
+The root (bare) repository:
+
+- is stored in `~ikiwki_example/ikiwiki_example.git`
+- is owned by `ikiwiki_example:ikiwiki_example`
+- has permissions 0700
+
+The master repository's post-update hook connects via SSH to
+`webserver` as user `ikiwiki_example`, in order to run
+`~/bin/ikiwiki.update` on `webserver`; this post-update hook, located
+in `~ikiwki_example/ikiwiki_example.git/hooks/post-update`, is
+executable and contains:
+
+       #!/bin/sh
+       /usr/bin/ssh ikiwiki_example@webserver bin/ikiwiki.update
+
+Password-less SSH must be setup to make this possible; one can
+restrict `gitserver:ikiwiki_example` to be able to run only the needed
+command on the web server, using such a line in
+`webserver:~ikiwiki_example/.ssh/authorized_keys`:
+
+       command="bin/ikiwiki.update",from="gitserver.example.com",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa ...
+
+Web server
+==========
+
+Let's create a user called `ikiwiki_example` on `webserver`. She needs
+to have write permission to the destination directory.
+
+The working tree repository (`srcdir`):
+
+- is stored in `~ikiwki_example/src`
+- is owned by `ikiwiki_example:ikiwiki_example`
+- has permissions 0700
+- has the following origin: `ikiwiki_example@gitserver:ikiwiki_example.git`
+
+The CGI wrapper is generated with ownership set to
+`ikiwiki_example:ikiwiki_example` and permissions `06755`.
+
+Password-less SSH must be setup so that `ikiwiki_example@webserver` is
+allowed to push to the master repository. As told earlier, SSH access
+to `ikiwiki_example@gitserver` is restricted to GIT pull/push, which
+is just what we need.
+
+The Git wrapper is generated in `~ikiwiki_example/bin/ikiwiki.update`:
+
+       git_wrapper => '/home/ikiwiki_example/bin/ikiwiki.update'
+
+As previously explained, this wrapper is run over SSH by the master
+repository's post-update hook; it pulls updates from the master
+repository and triggers a wiki refresh.
index 7e8ac951c9055262d97270ed1f8ebfc8c6732f34..1093029f55659cb47f5b1c31699b79092410bb75 100644 (file)
@@ -5,3 +5,8 @@ Instead of the [[plugins/search]] plugin you could embed [Google Custom Search](
 Once you've created your "custom search engine", just drop in the search box html like I've done in my [Debian tips and tricks](http://dabase.com/tips/) [source](http://git.webconverger.org/?p=faq.git;a=blob;f=tips.mdwn).
 
 If you have odd "save failed" error messages in Google's CSE's control panel, try `/usr/lib/WebKit/GtkLauncher` from [webkit](http://packages.qa.debian.org/w/webkit.html).
+
+
+# Alternatively
+
+You could use the [[Google_plugin|plugins/google]] from version 2.67.
index 87ef12079284acb2fe215b549030ecfe2c59cdfc..59330caa49ab626954af203b52b816b57b036416 100644 (file)
@@ -2,4 +2,12 @@ Use case: You want to move away from Wordpress to Ikiwiki as your blogging/websi
 
 [This](http://git.chris-lamb.co.uk/?p=ikiwiki-wordpress-import.git) is a simple tool that generates [git-fast-import](http://www.kernel.org/pub/software/scm/git/docs/git-fast-import.html)-compatible data from a WordPress export XML file. It retains creation time of each post, so you can use Ikiwiki's <tt>--getctime</tt> to get the preserve creation times on checkout. 
 
-WordPress categories are mapped onto Ikiwiki tags. The ability to import comments is planned.
\ No newline at end of file
+WordPress categories are mapped onto Ikiwiki tags. The ability to import comments is planned.
+
+-----
+
+I include a modified version of this script. This version includes the ability to write \[[!tag foo]] directives, which the original intended, but didn't actually do.
+
+-- [[users/simonraven]]
+
+[[ikiwiki-wordpress-import]]
diff --git a/doc/tips/Importing_posts_from_Wordpress/discussion.mdwn b/doc/tips/Importing_posts_from_Wordpress/discussion.mdwn
new file mode 100644 (file)
index 0000000..09e6f67
--- /dev/null
@@ -0,0 +1,29 @@
+When I attempt to use this script, I get the following error:
+warning: Not updating refs/heads/master (new tip 26b1787fca04f2f9772b6854843fe99fe06e6088 does not contain fc0ad65d14d88fd27a6cee74c7cef3176f6900ec).  I have git 1.5.6.5, any ideas?
+
+Thanks!!
+
+-----
+
+### KeyError: 146
+
+I also get this error, here's the output (it seems to stem from an error in the python script):
+
+<pre>
+Traceback (most recent call last):
+  File "../ikiwiki-wordpress-import.py", line 74, in <module>
+    main(*sys.argv[1:])
+  File "../ikiwiki-wordpress-import.py", line 54, in main
+    data = content.encode('ascii', 'html_replace')
+  File "../ikiwiki-wordpress-import.py", line 30, in <lambda>
+    % htmlentitydefs.codepoint2name[ord(c)] for c in x.object[x.start:x.end]]), x.end))
+KeyError: 146
+warning: Not updating refs/heads/master (new tip 6dca6ac939e12966bd64ce8a822ef14fe60622b2 does not contain 60b798dbf92ec5ae92f18acac3075c4304aca120)
+git-fast-import statistics:
+</pre>
+
+etc.
+
+(Removed now dead info and blah blah.)
+
+> It works fine.... The script is picky about having everything in proper UTF-8, **and** proper XML and HTML escaping. You need that to have a successful import. I let Emacs remove DOS line endings, and it works OK (if on *nix of some sort, of course). Thing is with this `git fast-import`, is that you have to `git reset` afterwards, (let's say you put them in posts/) `git checkout posts`, `git add posts`, then commit. I don't know if this a characteristic with `git fast-import`, but this is the way I get my posts to exist on the filesystem. If I don't do this, then I lose the data. If you get that "Not updating..." error, then just --force the import in. --[[users/simonraven]]
diff --git a/doc/tips/add_chatterbox_to_blog.mdwn b/doc/tips/add_chatterbox_to_blog.mdwn
new file mode 100644 (file)
index 0000000..aa35b93
--- /dev/null
@@ -0,0 +1,21 @@
+If you use twitter or identi.ca, here's how to make a box
+on the side of your blog that holds your recent status updates
+from there, like I have on [my blog](http://kitenet.net/~joey/blog/)
+--[[Joey]] 
+
+* Enable the [[plugins/aggregate]] plugin, and set up a cron
+  job for it.
+* At the top of your blog's page, add something like the following.
+  You'll want to change the urls of course. Be sure to also change
+  the inline directive's [[PageSpec]] to link to the location the
+  feed is aggregated to, which will be a subpage of the page
+  you put this on (blog in this example):
+
+       \[[!template id=note text="""  
+       \[[!aggregate expirecount=5 name="dents" url="http://identi.ca/joeyh"  
+       feedurl="http://identi.ca/api/statuses/user_timeline/joeyh.atom"]]  
+       \[[!inline pages="internal(./blog/dents/*)" template=microblog
+       show=5 feeds=no]]
+       """]]
+
+Note: Works best with ikiwiki 3.10 or better.
diff --git a/doc/tips/add_chatterbox_to_blog/discussion.mdwn b/doc/tips/add_chatterbox_to_blog/discussion.mdwn
new file mode 100644 (file)
index 0000000..a3d6864
--- /dev/null
@@ -0,0 +1,43 @@
+The example you gave looks a bit odd.
+
+This is what I did from your example (still trying to learn the more complex things ;).
+
+<pre>
+\[[!template id=note text="""
+\[[!aggregate expirecount=5 name=kijkaqawej url=http://identi.ca/kjikaqawej
+feedurl=http://identi.ca/api/statuses/user_timeline/kjikaqawej.atom]]
+\[[!inline pages="internal(kijkaqawej/*)" template=microblog show=5 feeds=no]] """]]
+</pre>
+
+mine, live, here: <http://simonraven.kisikew.org/blog/meta/microblog-feed/>
+
+I expected something like: sidebar, with a number, and displaying them in the sidebar, but they don't display (similar to what you have on your blog).
+
+On the [[/ikiwiki/pagespec]] page, it says "internal" pages aren't "first-class" wiki pages, so it's best not to directly display them, so how do you manage to display them? I'd like to display their name, and what they link to in the sidebar, or otherwise in the main body.
+
+> That's what the inline does, displays the internal pages.
+> 
+> You need to fix your pagespec to refer to where the pages are aggregated
+> to, under the page that contains the aggregate directive. In your example,
+> it should be `internal(./blog/meta/microblog-feed/kijkaqawej/*)` --[[Joey]]
+
+>> Oooh, I see, it's referring to an absolute path (relative to the site), right?
+>> Thanks :).
+
+>>> Right, PageSpecs are always absolute paths unless prefixed with `./`
+>>> (somewhat confusingly since WikiLinks are always realtive unless
+>>> previxed with `/` ...) --[[Joey]] 
+
+>> This is not working for me at all, all I get is some SHA1 hash all the time. I've tried variants of the `internal()` arg, and nothing gets spit out. --[[simonraven]]
+
+>>> Sounds like [[!debbug 380212]]?
+>>> If so, the fix is to use Text::Markdown, or markdown 1.0.2 instead of buggy
+>>> old markdown 1.0.1. --[[Joey]]
+
+>> `ii  libtext-markdown-perl            1.0.21-1                         Markdown and MultiMarkdown markup languages library`
+>>
+>> I'm using `Text::Markdown` due to its "multi-markdown" support. Yes, it does seem exactly like [[!debbug 380212]] .
+>> Maybe update it from CPAN + dh-make-perl (if there's a new one, that is) --[[simonraven]]
+>> I've just built and installed `libtext-markdown-perl 1.0.21-1` from dh-make-perl & CPAN, and regenerated that page.. let's see what happens... no hashes, but nothing else either:
+>>
+>> "kijkaqawej: last checked 10 minutes ago (25 posts)" -- inside of a box, no display of posts.
diff --git a/doc/tips/apache_cgi.mdwn b/doc/tips/apache_cgi.mdwn
deleted file mode 100644 (file)
index f10baed..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-Many ikiwiki examples name the [[cgi]] "ikiwiki.cgi", and put it somewhere
-like `~/public_html/ikiwiki.cgi`, or `/var/www/wiki/ikiwiki.cgi`.
-
-If you follow those examples, you may find that when trying to edit a page
-in your wiki, you see the raw contents of the ikiwiki.cgi program. Or get a
-permission denied problem.
-
-This is because apache is generally not configured to run cgi scripts
-unless they're in `/usr/lib/cgi-bin/`. While you can put ikiwiki.cgi in
-there if you like, here's how to configure apache (version 2) to run `.cgi`
-programs from anywhere.
-
-These instructions are for Debian systems, but the basic apache
-configuration should work anywhere.
-
-* Edit /etc/apache2/apache2.conf and add a line like this:
-
-       AddHandler cgi-script .cgi
-
-* Find the "Options" line for the directory where you've put the
-  ikiwiki.cgi, and add "ExecCGI" to the list of options. For example, if
-  ikiwiki.cgi is in /var/www/, edit `/etc/apache2/sites-enabled/000-default`
-  and add it to the "Options" line in the "Directory /var/www/" stanza.
-  Or, if you've put it in a `~/public_html`, edit
-  `/etc/apache2/mods-available/userdir.conf`.
index b0f5f14c160451367a4f133091948ad9e55689b9..1dfd715383526269b2d3ea867ae6abcc80bb8f2a 100644 (file)
@@ -1,4 +1,4 @@
-I have a [blog](http://git.kitenet.net/?p=joey/home;a=blob_plain;f=bin/blog)
+I have a [blog](http://git.kitenet.net/?p=joey/home.git;a=blob_plain;f=bin/blog)
 program that I use to write blog posts in a text editor. The first line I
 enter is used as the title, and it automatically comes up with a unique page
 name based on the title and handles all the details of posting to my blog.
diff --git a/doc/tips/comments_feed.mdwn b/doc/tips/comments_feed.mdwn
new file mode 100644 (file)
index 0000000..6f81372
--- /dev/null
@@ -0,0 +1,10 @@
+You've enabled the [[plugins/comments]] plugin, so a set of pages on your
+blog can have comments added to them. Pages with comments even have special
+feeds that can be used to subscribe to those comments. But you'd like to
+add a feed that contains all the comments posted to any page. Here's how:
+
+       \[[!inline pages="internal(*/comment_*)" template=comment]]
+
+The special [[ikiwiki/PageSpec]] matches all comments. The
+[[template|wikitemplates]] causes the comments to be displayed formatted
+nicely.
diff --git a/doc/tips/convert_MoinMoin_and_TWiki_to_ikiwiki.mdwn b/doc/tips/convert_MoinMoin_and_TWiki_to_ikiwiki.mdwn
new file mode 100644 (file)
index 0000000..5565dbd
--- /dev/null
@@ -0,0 +1,3 @@
+[[JoshTriplett]] has developed scripts to convert MoinMoin and TWiki wikis
+to ikiwikis backed by a git repository, including full history. For
+details, see [[his_user_page|JoshTriplett]].
diff --git a/doc/tips/convert_mediawiki_to_ikiwiki.mdwn b/doc/tips/convert_mediawiki_to_ikiwiki.mdwn
new file mode 100644 (file)
index 0000000..f03703b
--- /dev/null
@@ -0,0 +1,4 @@
+[[sabr]] explains how to [import MediaWiki content into
+git](http://u32.net/Mediawiki_Conversion/index.html?updated), including
+full edit hostory. The [[plugins/contrib/mediawiki]] plugin can then be
+used by ikiwiki to build the wiki.
diff --git a/doc/tips/convert_mediawiki_to_ikiwiki/discussion.mdwn b/doc/tips/convert_mediawiki_to_ikiwiki/discussion.mdwn
new file mode 100644 (file)
index 0000000..b3fe9f8
--- /dev/null
@@ -0,0 +1,614 @@
+The u32 page is excellent, but I wonder if documenting the procedure here
+would be worthwhile. Who knows, the remote site might disappear. But also
+there are some variations on the approach that might be useful:
+
+ * using a python script and the dom library to extract the page names from
+   Special:Allpages (such as
+   <http://www.staff.ncl.ac.uk/jon.dowland/unix/docs/get_pagenames.py>)
+ * Or, querying the mysql back-end to get the names
+ * using WWW::MediaWiki for importing/exporting pages from the wiki, instead
+   of Special::Export
+
+Also, some detail on converting mediawiki transclusion to ikiwiki inlines...
+
+-- [[users/Jon]]
+
+> "Who knows, the remote site might disappear.". Right now, it appears to
+> have done just that. -- [[users/Jon]]
+
+
+The iki-fast-load ruby script from the u32 page is given below:
+
+        #!/usr/bin/env ruby
+
+        # This script is called on the final sorted, de-spammed revision
+        # XML file.
+        #
+        # It doesn't currently check for no-op revisions...  I believe
+        # that git-fast-load will dutifully load them even though nothing
+        # happened.  I don't care to solve this by adding a file cache
+        # to this script.  You can run iki-diff-next.rb to highlight any
+        # empty revisions that need to be removed.
+        #
+        # This turns each node into an equivalent file.
+        #    It does not convert spaces to underscores in file names.
+        #       This would break wikilinks.
+        #       I suppose you could fix this with mod_speling or mod_rewrite.
+        #
+        # It replaces nodes in the Image: namespace with the files themselves.
+
+
+        require 'rubygems'
+        require 'node-callback'
+        require 'time'
+        require 'ostruct'
+
+
+        # pipe is the stream to receive the git-fast-import commands
+        # putfrom is true if this branch has existing commits on it, false if not.
+        def format_git_commit(pipe, f)
+           # Need to escape backslashes and double-quotes for git?
+           # No, git breaks when I do this. 
+           # For the filename "path with \\", git sez: bad default revision 'HEAD'
+           # filename = '"' + filename.gsub('\\', '\\\\\\\\').gsub('"', '\\"') + '"'
+
+           # In the calls below, length must be the size in bytes!!
+           # TODO: I haven't figured out how this works in the land of UTF8 and Ruby 1.9.
+           pipe.puts "commit #{f.branch}"
+           pipe.puts "committer #{f.username} <#{f.email}> #{f.timestamp.rfc2822}"
+           pipe.puts "data #{f.message.length}\n#{f.message}\n"
+           pipe.puts "from #{f.branch}^0" if f.putfrom
+           pipe.puts "M 644 inline #{f.filename}"
+           pipe.puts "data #{f.content.length}\n#{f.content}\n"
+           pipe.puts
+        end
+
+> Would be nice to know where you could get "node-callbacks"... this thing is useless without it. --[[users/simonraven]]
+
+
+Mediawiki.pm - A plugin which supports mediawiki format.
+
+       #!/usr/bin/perl
+       # By Scott Bronson.  Licensed under the GPLv2+ License.
+       # Extends Ikiwiki to be able to handle Mediawiki markup.
+       #
+       # To use the Mediawiki Plugin:
+       # - Install Text::MediawikiFormat
+       # - Turn of prefix_directives in your setup file.
+       #     (TODO: we probably don't need to do this anymore?)
+       #        prefix_directives => 1,
+       # - Add this plugin on Ikiwiki's path (perl -V, look for @INC)
+       #       cp mediawiki.pm something/IkiWiki/Plugin
+       # - And enable it in your setup file
+       #        add_plugins => [qw{mediawiki}],
+       # - Finally, turn off the link plugin in setup (this is important)
+       #        disable_plugins => [qw{link}],
+       # - Rebuild everything (actually, this should be automatic right?)
+       # - Now all files with a .mediawiki extension should be rendered properly.
+       
+       
+       package IkiWiki::Plugin::mediawiki;
+       
+       use warnings;
+       use strict;
+       use IkiWiki 2.00;
+       use URI;
+       
+       
+       # This is a gross hack...  We disable the link plugin so that our
+       # linkify routine is always called.  Then we call the link plugin
+       # directly for all non-mediawiki pages.  Ouch...  Hopefully Ikiwiki
+       # will be updated soon to support multiple link plugins.
+       require IkiWiki::Plugin::link;
+       
+       # Even if T:MwF is not installed, we can still handle all the linking.
+       # The user will just see Mediawiki markup rather than formatted markup.
+       eval q{use Text::MediawikiFormat ()};
+       my $markup_disabled = $@;
+       
+       # Work around a UTF8 bug in Text::MediawikiFormat
+       # http://rt.cpan.org/Public/Bug/Display.html?id=26880
+       unless($markup_disabled) {
+          no strict 'refs';
+          no warnings;
+          *{'Text::MediawikiFormat::uri_escape'} = \&URI::Escape::uri_escape_utf8;
+       }
+       
+       my %metaheaders;    # keeps track of redirects for pagetemplate.
+       my %tags;      # keeps track of tags for pagetemplate.
+       
+       
+       sub import { #{{{
+          hook(type => "checkconfig", id => "mediawiki", call => \&checkconfig);
+          hook(type => "scan", id => "mediawiki", call => \&scan);
+          hook(type => "linkify", id => "mediawiki", call => \&linkify);
+          hook(type => "htmlize", id => "mediawiki", call => \&htmlize);
+          hook(type => "pagetemplate", id => "mediawiki", call => \&pagetemplate);
+       } # }}}
+       
+       
+       sub checkconfig
+       {
+          return IkiWiki::Plugin::link::checkconfig(@_);
+       }
+       
+       
+       my $link_regexp = qr{
+           \[\[(?=[^!])        # beginning of link
+           ([^\n\r\]#|<>]+)      # 1: page to link to
+           (?:
+               \#              # '#', beginning of anchor
+               ([^|\]]+)       # 2: anchor text
+           )?                  # optional
+       
+           (?:
+               \|              # followed by '|'
+               ([^\]\|]*)      # 3: link text
+           )?                  # optional
+           \]\]                # end of link
+               ([a-zA-Z]*)   # optional trailing alphas
+       }x;
+       
+       
+       # Convert spaces in the passed-in string into underscores.
+       # If passed in undef, returns undef without throwing errors.
+       sub underscorize
+       {
+          my $var = shift;
+          $var =~ tr{ }{_} if $var;
+          return $var;
+       }
+       
+       
+       # Underscorize, strip leading and trailing space, and scrunch
+       # multiple runs of spaces into one underscore.
+       sub scrunch
+       {
+          my $var = shift;
+          if($var) {
+             $var =~ s/^\s+|\s+$//g;      # strip leading and trailing space
+             $var =~ s/\s+/ /g;      # squash multiple spaces to one
+          }
+          return $var;
+       }
+       
+       
+       # Translates Mediawiki paths into Ikiwiki paths.
+       # It needs to be pretty careful because Mediawiki and Ikiwiki handle
+       # relative vs. absolute exactly opposite from each other.
+       sub translate_path
+       {
+          my $page = shift;
+          my $path = scrunch(shift);
+       
+          # always start from root unless we're doing relative shenanigans.
+          $page = "/" unless $path =~ /^(?:\/|\.\.)/;
+       
+          my @result = ();
+          for(split(/\//, "$page/$path")) {
+             if($_ eq '..') {
+                pop @result;
+             } else {
+                push @result, $_ if $_ ne "";
+             }
+          }
+       
+          # temporary hack working around http://ikiwiki.info/bugs/Can__39__t_create_root_page/index.html?updated
+          # put this back the way it was once this bug is fixed upstream.
+          # This is actually a major problem because now Mediawiki pages can't link from /Git/git-svn to /git-svn.  And upstream appears to be uninterested in fixing this bug.  :(
+          # return "/" . join("/", @result);
+          return join("/", @result);
+       }
+       
+       
+       # Figures out the human-readable text for a wikilink
+       sub linktext
+       {
+          my($page, $inlink, $anchor, $title, $trailing) = @_;
+          my $link = translate_path($page,$inlink);
+       
+          # translate_path always produces an absolute link.
+          # get rid of the leading slash before we display this link.
+          $link =~ s#^/##;
+       
+          my $out = "";
+          if($title) {
+              $out = IkiWiki::pagetitle($title);
+          } else {
+             $link = $inlink if $inlink =~ /^\s*\//;
+              $out = $anchor ? "$link#$anchor" : $link;
+             if(defined $title && $title eq "") {
+                # a bare pipe appeared in the link...
+                # user wants to strip namespace and trailing parens.
+                $out =~ s/^[A-Za-z0-9_-]*://;
+                $out =~ s/\s*\(.*\)\s*$//;
+             }
+             # A trailing slash suppresses the leading slash
+             $out =~ s#^/(.*)/$#$1#;
+          }
+          $out .= $trailing if defined $trailing;
+          return $out;
+       }
+       
+       
+       sub tagpage ($)
+       {
+          my $tag=shift;
+       
+          if (exists $config{tagbase} && defined $config{tagbase}) {
+             $tag=$config{tagbase}."/".$tag;
+          }
+       
+          return $tag;
+       }
+       
+       
+       # Pass a URL and optional text associated with it.  This call turns
+       # it into fully-formatted HTML the same way Mediawiki would.
+       # Counter is used to number untitled links sequentially on the page.
+       # It should be set to 1 when you start parsing a new page.  This call
+       # increments it automatically.
+       sub generate_external_link
+       {
+          my $url = shift;
+          my $text = shift;
+          my $counter = shift;
+       
+          # Mediawiki trims off trailing commas.
+          # And apparently it does entity substitution first.
+          # Since we can't, we'll fake it.
+       
+          # trim any leading and trailing whitespace
+          $url =~ s/^\s+|\s+$//g;
+       
+          # url properly terminates on > but must special-case &gt;
+          my $trailer = "";
+          $url =~ s{(\&(?:gt|lt)\;.*)$}{ $trailer = $1, ''; }eg;
+       
+          # Trim some potential trailing chars, put them outside the link.
+          my $tmptrail = "";
+          $url =~ s{([,)]+)$}{ $tmptrail .= $1, ''; }eg;
+          $trailer = $tmptrail . $trailer;
+       
+          my $title = $url;
+          if(defined $text) {
+             if($text eq "") {
+                $text = "[$$counter]";
+                $$counter += 1;
+             }
+             $text =~ s/^\s+|\s+$//g;
+             $text =~ s/^\|//;
+          } else {
+             $text = $url;
+          }
+       
+          return "<a href='$url' title='$title'>$text</a>$trailer";
+       }
+       
+       
+       # Called to handle bookmarks like [[#heading]] or <span class="createlink"><a href="http://u32.net/cgi-bin/ikiwiki.cgi?page=%20text%20&amp;from=Mediawiki_Plugin%2Fmediawiki&amp;do=create" rel="nofollow">?</a>#a</span>
+       sub generate_fragment_link
+       {
+          my $url = shift;
+          my $text = shift;
+       
+          my $inurl = $url;
+          my $intext = $text;
+          $url = scrunch($url);
+       
+          if(defined($text) && $text ne "") {
+             $text = scrunch($text);
+          } else {
+             $text = $url;
+          }
+       
+          $url = underscorize($url);
+       
+          # For some reason Mediawiki puts blank titles on all its fragment links.
+          # I don't see why we would duplicate that behavior here.
+          return "<a href='$url'>$text</a>";
+       }
+       
+       
+       sub generate_internal_link
+       {
+          my($page, $inlink, $anchor, $title, $trailing, $proc) = @_;
+       
+          # Ikiwiki's link link plugin wrecks this line when displaying on the site.
+          # Until the code highlighter plugin can turn off link finding,
+          # always escape double brackets in double quotes: [[
+          if($inlink eq '..') {
+             # Mediawiki doesn't touch links like [[..#hi|ho]].
+             return "[[" . $inlink . ($anchor?"#$anchor":"") .
+                ($title?"|$title":"") . "]]" . $trailing;
+          }
+       
+          my($linkpage, $linktext);
+          if($inlink =~ /^ (:?) \s* Category (\s* \: \s*) ([^\]]*) $/x) {
+             # Handle category links
+             my $sep = $2;
+             $inlink = $3;
+             $linkpage = IkiWiki::linkpage(translate_path($page, $inlink));
+             if($1) {
+                # Produce a link but don't add this page to the given category.
+                $linkpage = tagpage($linkpage);
+                $linktext = ($title ? '' : "Category$sep") .
+                   linktext($page, $inlink, $anchor, $title, $trailing);
+                $tags{$page}{$linkpage} = 1;
+             } else {
+                # Add this page to the given category but don't produce a link.
+                $tags{$page}{$linkpage} = 1;
+                &$proc(tagpage($linkpage), $linktext, $anchor);
+                return "";
+             }
+          } else {
+             # It's just a regular link
+             $linkpage = IkiWiki::linkpage(translate_path($page, $inlink));
+             $linktext = linktext($page, $inlink, $anchor, $title, $trailing);
+          }
+       
+          return &$proc($linkpage, $linktext, $anchor);
+       }
+       
+       
+       sub check_redirect
+       {
+          my %params=@_;
+       
+          my $page=$params{page};
+          my $destpage=$params{destpage};
+          my $content=$params{content};
+       
+          return "" if $page ne $destpage;
+       
+          if($content !~ /^ \s* \#REDIRECT \s* \[\[ ( [^\]]+ ) \]\]/x) {
+             # this page isn't a redirect, render it normally.
+             return undef;
+          }
+       
+          # The rest of this function is copied from the redir clause
+          # in meta::preprocess and actually handles the redirect.
+       
+          my $value = $1;
+          $value =~ s/^\s+|\s+$//g;
+       
+          my $safe=0;
+          if ($value !~ /^\w+:\/\//) {
+             # it's a local link
+             my ($redir_page, $redir_anchor) = split /\#/, $value;
+       
+             add_depends($page, $redir_page);
+             my $link=bestlink($page, underscorize(translate_path($page,$redir_page)));
+             if (! length $link) {
+                return "<b>Redirect Error:</b> <nowiki>[[$redir_page]] not found.</nowiki>";
+             }
+       
+             $value=urlto($link, $page);
+             $value.='#'.$redir_anchor if defined $redir_anchor;
+             $safe=1;
+       
+             # redir cycle detection
+             $pagestate{$page}{mediawiki}{redir}=$link;
+             my $at=$page;
+             my %seen;
+             while (exists $pagestate{$at}{mediawiki}{redir}) {
+                if ($seen{$at}) {
+                   return "<b>Redirect Error:</b> cycle found on <nowiki>[[$at]]</nowiki>";
+                }
+                $seen{$at}=1;
+                $at=$pagestate{$at}{mediawiki}{redir};
+             }
+          } else {
+             # it's an external link
+             $value = encode_entities($value);
+          }
+       
+          my $redir="<meta http-equiv=\"refresh\" content=\"0; URL=$value\" />";
+          $redir=scrub($redir) if !$safe;
+          push @{$metaheaders{$page}}, $redir;
+       
+          return "Redirecting to $value ...";
+       }
+       
+       
+       # Feed this routine a string containing <nowiki>...</nowiki> sections,
+       # this routine calls your callback for every section not within nowikis,
+       # collecting its return values and returning the rewritten string.
+       sub skip_nowiki
+       {
+          my $content = shift;
+          my $proc = shift;
+       
+          my $result = "";
+          my $state = 0;
+       
+          for(split(/(<nowiki[^>]*>.*?<\/nowiki\s*>)/s, $content)) {
+             $result .= ($state ? $_ : &$proc($_));
+             $state = !$state;
+          }
+       
+          return $result;
+       }
+       
+       
+       # Converts all links in the page, wiki and otherwise.
+       sub linkify (@)
+       {
+          my %params=@_;
+       
+          my $page=$params{page};
+          my $destpage=$params{destpage};
+          my $content=$params{content};
+       
+          my $file=$pagesources{$page};
+          my $type=pagetype($file);
+          my $counter = 1;
+       
+          if($type ne 'mediawiki') {
+             return IkiWiki::Plugin::link::linkify(@_);
+          }
+       
+          my $redir = check_redirect(%params);
+          return $redir if defined $redir;
+       
+          # this code was copied from MediawikiFormat.pm.
+          # Heavily changed because MF.pm screws up escaping when it does
+          # this awful hack: $uricCheat =~ tr/://d;
+          my $schemas = [qw(http https ftp mailto gopher)];
+          my $re = join "|", map {qr/\Q$_\E/} @$schemas;
+          my $schemes = qr/(?:$re)/;
+          # And this is copied from URI:
+          my $reserved   = q(;/?@&=+$,);   # NOTE: no colon or [] !
+          my $uric       = quotemeta($reserved) . $URI::unreserved . "%#";
+       
+          my $result = skip_nowiki($content, sub {
+             $_ = shift;
+       
+             # Escape any anchors
+             #s/<(a[\s>\/])/&lt;$1/ig;
+             # Disabled because this appears to screw up the aggregate plugin.
+             # I guess we'll rely on Iki to post-sanitize this sort of stuff.
+       
+             # Replace external links, http://blah or [http://blah]
+             s{\b($schemes:[$uric][:$uric]+)|\[($schemes:[$uric][:$uric]+)([^\]]*?)\]}{
+                generate_external_link($1||$2, $3, \$counter)
+             }eg;
+       
+             # Handle links that only contain fragments.
+             s{ \[\[ \s* (\#[^|\]'"<>&;]+) (?:\| ([^\]'"<>&;]*))? \]\] }{
+                generate_fragment_link($1, $2)
+             }xeg;
+       
+             # Match all internal links
+             s{$link_regexp}{
+                generate_internal_link($page, $1, $2, $3, $4, sub {
+                   my($linkpage, $linktext, $anchor) = @_;
+                   return htmllink($page, $destpage, $linkpage,
+                      linktext => $linktext,
+                      anchor => underscorize(scrunch($anchor)));
+                });
+             }eg;
+          
+             return $_;
+          });
+       
+          return $result;
+       }
+       
+       
+       # Find all WikiLinks in the page.
+       sub scan (@)
+       {
+          my %params = @_;
+          my $page=$params{page};
+          my $content=$params{content};
+       
+          my $file=$pagesources{$page};
+          my $type=pagetype($file);
+       
+          if($type ne 'mediawiki') {
+             return IkiWiki::Plugin::link::scan(@_);
+          }
+       
+          skip_nowiki($content, sub {
+             $_ = shift;
+             while(/$link_regexp/g) {
+                generate_internal_link($page, $1, '', '', '', sub {
+                   my($linkpage, $linktext, $anchor) = @_;
+                   push @{$links{$page}}, $linkpage;
+                   return undef;
+                });
+             }
+             return '';
+          });
+       }
+       
+       
+       # Convert the page to HTML.
+       sub htmlize (@)
+       {
+          my %params=@_;
+          my $page = $params{page};
+          my $content = $params{content};
+       
+       
+          return $content if $markup_disabled;
+       
+          # Do a little preprocessing to babysit Text::MediawikiFormat
+          # If a line begins with tabs, T:MwF won't convert it into preformatted blocks.
+          $content =~ s/^\t/    /mg;
+       
+          my $ret = Text::MediawikiFormat::format($content, {
+       
+              allowed_tags    => [#HTML
+                       # MediawikiFormat default
+                       qw(b big blockquote br caption center cite code dd
+                          div dl dt em font h1 h2 h3 h4 h5 h6 hr i li ol p
+                          pre rb rp rt ruby s samp small strike strong sub
+                          sup table td th tr tt u ul var),
+                        # Mediawiki Specific
+                        qw(nowiki),
+                        # Our additions
+                        qw(del ins),   # These should have been added all along.
+                        qw(span),   # Mediawiki allows span but that's rather scary...?
+                        qw(a),      # this is unfortunate; should handle links after rendering the page.
+                      ],
+       
+              allowed_attrs   => [
+                       qw(title align lang dir width height bgcolor),
+                       qw(clear), # BR
+                       qw(noshade), # HR
+                       qw(cite), # BLOCKQUOTE, Q
+                       qw(size face color), # FONT
+                       # For various lists, mostly deprecated but safe
+                       qw(type start value compact),
+                       # Tables
+                       qw(summary width border frame rules cellspacing
+                          cellpadding valign char charoff colgroup col
+                          span abbr axis headers scope rowspan colspan),
+                       qw(id class name style), # For CSS
+                       # Our additions
+                       qw(href),
+                      ],
+       
+             }, {
+             extended => 0,
+             absolute_links => 0,
+             implicit_links => 0
+             });
+       
+          return $ret;
+       }
+       
+       
+       # This is only needed to support the check_redirect call.
+       sub pagetemplate (@)
+       {
+          my %params = @_;
+          my $page = $params{page};
+          my $destpage = $params{destpage};
+          my $template = $params{template};
+       
+          # handle metaheaders for redirects
+          if (exists $metaheaders{$page} && $template->query(name => "meta")) {
+          # avoid duplicate meta lines
+             my %seen;
+             $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}}));
+          }
+       
+          $template->param(tags => [
+             map {
+                link => htmllink($page, $destpage, tagpage($_), rel => "tag")
+             }, sort keys %{$tags{$page}}
+          ]) if exists $tags{$page} && %{$tags{$page}} && $template->query(name => "tags");
+       
+          # It's an rss/atom template. Add any categories.
+          if ($template->query(name => "categories")) {
+             if (exists $tags{$page} && %{$tags{$page}}) {
+                $template->param(categories => [map { category => $_ },
+                   sort keys %{$tags{$page}}]);
+             }
+          }
+       }
+       
+       1
index 3d9f3198666ce787bdffb0935a29e33bdd6c404f..cf9c2e338a1311e83797a37d7b6f7ec96b5dd342 100644 (file)
@@ -26,7 +26,8 @@ And if someone edits a page on your mirror, it will "git push origin",
 committing the changes back to the origin git repository, and updating the
 origin mirror. Assuming you can push to that git repository. If you can't,
 and you want a mirror, and not a branch, you should disable web edits on
-your mirror.
+your mirror. (You could also point the cgiurl for your mirror at the origin
+wiki.)
 
 ## branching a wiki
 
diff --git a/doc/tips/distributed_wikis/discussion.mdwn b/doc/tips/distributed_wikis/discussion.mdwn
new file mode 100644 (file)
index 0000000..994c493
--- /dev/null
@@ -0,0 +1,7 @@
+Would it work if the mirrored wiki was configured with cgiurl set to the cgiurl of the origin wiki - so that users were seamlessly redirected to the origin for edits? --[[Jamie]]
+
+> Yes, if the origin wiki is set up to ping the mirrored wiki when
+> updated, the mirror is free to use its cgi setup. (Note that the cgi will
+> leave the user on a page on the origin wiki when they save the edit.)
+> I've put a mention of this option in the page.
+> --[[Joey]]
diff --git a/doc/tips/dot_cgi.mdwn b/doc/tips/dot_cgi.mdwn
new file mode 100644 (file)
index 0000000..da55c1f
--- /dev/null
@@ -0,0 +1,67 @@
+It's common to name the [[cgi]] "ikiwiki.cgi", and put it somewhere
+like `~/public_html/ikiwiki.cgi`, or `/var/www/wiki/ikiwiki.cgi`.
+
+If you do that, you may find that when trying to edit a page in your wiki,
+you see the raw contents of the ikiwiki.cgi program. Or get a permission
+denied problem.
+
+This is because web servers are generally not configured to run cgi scripts
+unless they're in `/usr/lib/cgi-bin/`. While you can put ikiwiki.cgi in
+there if you like, it's better to configure your web server to 
+run `.cgi`  programs from anywhere.
+
+These instructions are for Debian systems, but the basic
+configuration changes should work anywhere.
+
+## apache 2
+
+* Edit /etc/apache2/apache2.conf and add a line like this:
+
+       AddHandler cgi-script .cgi
+
+* Find the "Options" line for the directory where you've put the
+  ikiwiki.cgi, and add "ExecCGI" to the list of options. For example, if
+  ikiwiki.cgi is in /var/www/, edit `/etc/apache2/sites-enabled/000-default`
+  and add it to the "Options" line in the "Directory /var/www/" stanza.
+  Or, if you've put it in a `~/public_html`, edit
+  `/etc/apache2/mods-available/userdir.conf`.
+
+* You may also want to enable the [[plugins/404]] plugin.
+  To make apache use it, the apache config file will need a further
+  modification to make it use ikiwiki's CGI as the apache 404 handler.
+  Something like this, with the path adjusted to where you've put the CGI:
+
+       ErrorDocument 404 /cgi-bin/ikiwiki.cgi
+
+## lighttpd
+
+Here is how to enable cgi on [lighttpd](http://www.lighttpd.net/) and
+configure it in order to execute ikiwiki.cgi wherever it is located. 
+
+* Activate cgi by linking `/etc/lighttpd/conf-available/10-cgi.conf` into `/etc/lighttpd/conf-enabled` ([doc](http://trac.lighttpd.net/trac/wiki/Docs%3AModCGI)). 
+
+* Create `/etc/lighttpd/conf-available/90-ikiwiki-cgi.conf` and add a line like this:
+
+    cgi.assign = ( "ikiwiki.cgi"  => "", )
+
+* Activate ikiwiki-cgi by linking `/etc/lighttpd/conf-available/90-ikiwiki-cgi.conf` into `/etc/lighttpd/conf-enabled`. 
+
+* Restart lighttpd server with something like `/etc/init.d/lighttpd restart`.
+
+Note that the first part enables cgi server wide but depending on default
+configuration, it may be not enough. The second part creates a specific
+rule that allow `ikiwiki.cgi` to be executed.
+
+**Warning:** I only use this lighttpd configuration on my development
+server (offline). I am not sure of how secure this approach is.
+If you have any thought about it, feel free to let me know.
+
+## nginx
+
+* To run CGI under nginx, just use a FastCGI wrapper like [this one](http://technotes.1000lines.net/?p=23). The wrapper must be started somehow just like any other FastCGI program. I use launchd on OSX.
+
+## boa
+
+Edit /etc/boa/boa.conf and make sure the following line is not commented:
+
+    AddType application/x-httpd-cgi cgi
diff --git a/doc/tips/dot_cgi/discussion.mdwn b/doc/tips/dot_cgi/discussion.mdwn
new file mode 100644 (file)
index 0000000..124b9ed
--- /dev/null
@@ -0,0 +1,36 @@
+## warning: lighttpd only or both?
+
+Is your warning at the bottom (you don't know how secure it is) only about
+lighttpd or it's about apache2 configuration as well?
+
+> The latter. (Although I don't know why using lighttpd would lead
+> to any additional security exposure anyway.) --[[Joey]] 
+
+I'm asking this because right now I want to setup an httpd solely for the
+public use of ikiwiki on a general purpose computer (there are other things
+there), and so I need to choose the more secure solution. --Ivan Z.
+
+> AFAIU, my main simplest security measure should be running the public
+> ikiwiki's cgi under a special user, but then: how do I push to the repo
+> owned by that other user? I see, probably I should setup the public wiki
+> under the special user (so that it was able to create the cgi-script with
+> the desired permission), and then give my personal user the required
+> permissions to make a git-push by, say, creating a special Unix group for
+> this.
+
+> Shouldn't there be a page here which would document a secure public and
+> multi-user installation of ikiwiki (by "multi-user" I mean writable by a
+> group of local Unix users)? If there isn't such yet, I started writing it
+> with this discussion.--Ivan Z.
+
+> I see, perhaps a simpler setup would not make use of a Unix group, but
+> simply allow pushing to the public wiki (kept under a special user) through
+> git+ssh. --Ivan Z.
+
+>> Yes, it's certianly possible to configure git (and svn, etc) repositories so that
+>> two users can both push to them. There should be plenty of docs out there
+>> about doing that.
+>> 
+>> The easiest way though is probably
+>> to add your ssh key to the special user's `.ssh/authorized_keys`
+>> and push that way. --[[Joey]] 
diff --git a/doc/tips/emacs_syntax_highlighting.mdwn b/doc/tips/emacs_syntax_highlighting.mdwn
new file mode 100644 (file)
index 0000000..941cf54
--- /dev/null
@@ -0,0 +1,3 @@
+A [markdown mode](http://jblevins.org/projects/markdown-mode/) for 
+emacs can help in editing of ikiwiki
+[[ikiwiki/markdown]] files.
diff --git a/doc/tips/embedding_content.mdwn b/doc/tips/embedding_content.mdwn
new file mode 100644 (file)
index 0000000..bfe458a
--- /dev/null
@@ -0,0 +1,35 @@
+Content from sites such as YouTube can be embedded into a web page. Maybe
+you want to do this. But you'll find that the [[plugins/htmlscrubber]]
+doesn't let you. It blocks the tags used to embed such content, because
+they can be abused in many evil ways.
+
+Some plugins have been written to try to work around this problem, by
+whitelisting the html needed to embed things from a few sites like Google
+maps, calendar, videos, and YouTube. The problem with these plugins is that
+they have to be kept up to date to add new sites, and follow changes to the
+html such sites use for embedding.
+
+(Digression: The real problem with the plugins is that they hide the
+underlying trust relationship. If you decide to embed html from a site,
+you'd better trust that site. And if ikiwiki lets you enter such html, it
+needs to trust you.)
+
+The [[plugins/htmlscrubber]] offers a different way around this problem.
+You can configure it to skip scrubbing certain pages, so that content from
+elsewhere can be embedded on those pages. Then use [[plugins/lockedit]]
+to limit who can edit those unscrubbed pages.
+
+For example, suppose your blog is all under `blog/*`, and you want
+only yourself to be able to post there, and you'd like to be able to embed
+youtube videos etc in your blog. Other users can edit some pages in the
+wiki (Discussion pages, say), but not your blog posts. Then you could configure
+ikiwiki as follows:
+
+       htmlscrubber_skip => 'blog/* and !*/Discussion',
+       locked_pages => '!*/Discussion',
+
+More simply, you might want to allow yourself to embed content anywhere
+on the wiki, but scrub content written on Discussion pages:
+       
+       htmlscrubber_skip => '!*/Discussion',
+       locked_pages => '!*/Discussion',
diff --git a/doc/tips/github.mdwn b/doc/tips/github.mdwn
new file mode 100644 (file)
index 0000000..c3fdab7
--- /dev/null
@@ -0,0 +1,64 @@
+Here's how to set up a static wiki or blog using ikiwiki with no hosting
+fees. Everything is hosted on github, both the git repository and the web
+site. Your laptop is used to generate and publish changes to it.
+
+This is possible because github now supports
+[github pages](http://github.com/blog/272-github-pages).
+
+Note that github limits free accounts to 100 mb of git storage. It's
+unlikely that a small wiki or blog will outgrow this, but we are keeping
+two copies of the website in git (source and the compiled site), and all
+historical versions too. So it could happen. If it does, you can pay github
+for more space, or you can migrate your site elsewhere.
+
+## Github Setup
+
+* Go to [github](http://github.com/) and sign up for an account, if you haven't already. 
+* Be sure to add your laptop's ssh key to it so you can push to github.
+* Create a repository on github named `$YOU.github.com`, substituting your
+  *username*. This repository will be used to publish your compiled website.
+* Create a repository on github named `$YOU` (or anything else you like).
+  This repository will be used to publish the source of your website.
+  This is actually optional.
+
+## Local Setup
+
+* On your laptop, create two empty git repositories to correspond to the github repositories: <br />
+       `YOU = your github username here` <br />
+       `mkdir ~/$YOU.github.com` <br />
+       `cd ~/$YOU.github.com` <br />
+       `git init` <br />
+       `git remote add origin git@github.com:$YOU/$YOU.github.com.git` <br />
+       `mkdir ~/$YOU` <br />
+       `cd ~/$YOU` <br />
+       `git init` <br />
+       `git remote add origin git@github.com:$YOU/$YOU.git` <br />
+* Add some wiki pages, such as an `index.mdwn`, to `~/$YOU`, and check them
+  in and commit them to git. You need something to push to github. Run
+  `git push origin master` to push the source pages to github.
+
+## Publishing to Github
+
+* Now build your wiki with a command such as: <br />
+       `ikiwiki ~/$YOU ~/$YOU.github.com --refresh`
+* Each time you build the wiki you will need to commit the changes
+  to git, and push the compiled pages to github: <br />
+       `cd ~/YOU.github.com` <br />
+       `git add .` <br />
+       `git commit -a -m update` <br />
+       `git push origin master` <br />
+
+Your wiki will show up at `http://$YOU.github.com/` within ten
+minutes after the first push, and changes you push to it from then on
+should show up immediately.
+
+## Enhancements
+
+You can follow the instructions in [[laptop_wiki_with_git]] to set up an
+editable version of your wiki on your laptop. Then you can use the web
+interface for editing. You'll still need to follow the instructions above
+to publish your changes to github.
+
+It would also be possible to teach ikiwiki to push compiled pages to github
+itself via a plugin, as was done with the [[plugins/amazon_s3]] plugin. Not
+done yet!
index 570baa5cc8118d6b68940ab32a1cc8379c1deeb0..e45b966897cb1b42b9a500ba89a25eb3b95bce5e 100644 (file)
@@ -1,25 +1,28 @@
-If you have a [[ikiwiki/blog]] that is aggregated, either on a site like Planet
+If you have a [[blog]] that is aggregated, either on a site like Planet
 Debian, or just through user subscriptions, one common problem is that
-changes to the guids of items in the blog can "flood" the aggregator,
+changes to the guids of items in the blog can “flood” the aggregator,
 causing all recent blog entries to be posted to the top of it. 
 
 This can happen in a lot of situations:
 
-* Perhaps you've just switched to ikiwiki from some other blog engine and
+* Perhaps youve just switched to ikiwiki from some other blog engine and
   imported your data.
-* Perhaps you've turned on the `usedirs` setting, which changes all the
+* Perhaps youve turned on the `usedirs` setting, which changes all the
   urls in your wiki. Even if you set up
   [[redirections|redirections_for_usedirs]] for the old urls, you still face
   the issue of flooding aggregators.
-* Perhaps you've just moved stuff around in your wiki.
+* Perhaps youve just moved stuff around in your wiki.
 
-To avoid annoying readers in these situations, it's a good idea to remove
-any existing items from your blog's news feed. That way only new items will
+To avoid annoying readers in these situations, its a good idea to remove
+any existing items from your blogs news feed. That way only new items will
 show up in the aggregator. The best way to do this is to add a `feedpages`
 parameter to the `inline` directive for your blog, with a condition such as:
 
        feedpages=created_after(blog/posts/old_post)
 
-Where "old_post" is the name of the last post you made to the blog before
-making the change. This will limit the feed to only newer posts, while stil
+Where “old_post” is the name of the last post you made to the blog before
+making the change. This will limit the feed to only newer posts, while still
 displaying the old posts in the blog page.
+
+Alternatively, you can add the [[plugins/meta]] guid directives to pages,
+to force the old url to be used.
diff --git a/doc/tips/importing_posts_from_typo.mdwn b/doc/tips/importing_posts_from_typo.mdwn
new file mode 100644 (file)
index 0000000..1b87e7d
--- /dev/null
@@ -0,0 +1 @@
+[Here](http://blog.spang.cc/posts/migrating_from_typo_to_ikiwiki/) is a blog post that gives instructions and a script for importing posts from [Typo](http://typosphere.org/), a Ruby-on-Rails based blogging engine.
diff --git a/doc/tips/importing_posts_from_wordpress/ikiwiki-wordpress-import.mdwn b/doc/tips/importing_posts_from_wordpress/ikiwiki-wordpress-import.mdwn
new file mode 100644 (file)
index 0000000..0c0527f
--- /dev/null
@@ -0,0 +1,233 @@
+[[!meta title="ikiwiki-wordpress-import"]]
+
+I modified the script a bit so categories and tags would actually show up in the output file.
+
+-----
+<pre>
+#!/usr/bin/env python
+
+"""
+    Purpose:
+    Wordpress-to-Ikiwiki import tool
+
+    Copyright:
+    Copyright (C) 2007  Chris Lamb <chris@chris-lamb.co.uk>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    Usage: run --help as an argument with this script.
+
+    Notes:
+    I added some extra bits to include the \[[!tag foo]] stuff in the post,
+    as it wasn't before, at all. I'll diff the versions out so you can see
+    the mess I made :).
+
+"""
+
+import os, sys
+import time
+import re
+
+from BeautifulSoup import BeautifulSoup
+
+import codecs, htmlentitydefs
+
+codecs.register_error('html_replace', lambda x: (''.join([u'&%s;' \
+    % htmlentitydefs.codepoint2name[ord(c)] for c in x.object[x.start:x.end]]), x.end))
+
+def main(name, email, subdir, branch='master'):
+    soup = BeautifulSoup(sys.stdin.read())
+
+    # Regular expression to match stub in URL.
+    stub_pattern = re.compile(r'.*\/(.+)\/$')
+
+    for x in soup.findAll('item'):
+        # Ignore draft posts
+        if x.find('wp:status').string != 'publish': continue
+
+        match = stub_pattern.match(x.guid.string)
+        if match:
+            stub = match.groups()[0]
+        else:
+            # Fall back to our own stubs
+            stub = re.sub(r'[^a-zA-Z0-9_]', '-', x.title.string).lower()
+
+        commit_msg = """Importing WordPress post "%s" [%s]""" % (x.title.string, x.guid.string)
+        timestamp = time.mktime(time.strptime(x.find('wp:post_date_gmt').string, "%Y-%m-%d %H:%M:%S"))
+
+        content = '\[[!meta title="%s"]]\n\n' % (x.title.string.replace('"', r'\"'))
+        content += x.find('content:encoded').string.replace('\r\n', '\n')
+
+        # categories = x.findAll('category')
+        # categories = x.findAll({'category':True}, attrs={'domain':re.compile(('category|tag'))})
+        # categories = x.findAll({'category':True}, domain=["category", "tag"])
+        # categories = x.findAll({'category':True}, nicename=True)
+        """
+        We do it differently here because we have duplicates otherwise.
+        Take a look:
+        &lt;category&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
+        &lt;category domain="category" nicename="health"&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
+
+        If we do the what original did, we end up with all tags and cats doubled.
+        Therefore we only pick out nicename="foo". Our 'True' below is our 'foo'.
+        I'd much rather have the value of 'nicename', and tried, but my
+        python skillz are extremely limited....
+        """
+        categories = x.findAll('category', nicename=True)
+        if categories:
+            content += "\n"
+            for cat in categories:
+                # remove 'tags/' because we have a 'tagbase' set.
+                # your choice: 'tag', or 'taglink'
+                # content += "\n\[[!tag %s]]" % (cat.string.replace(' ', '-'))
+                content += "\n\[[!taglink %s]]" % (cat.string.replace(' ', '-'))
+                # print >>sys.stderr, cat.string.replace(' ', '-')
+
+        # moved this thing down
+        data = content.encode('ascii', 'html_replace')
+        print "commit refs/heads/%s" % branch
+        print "committer %s &lt;%s&gt; %d +0000" % (name, email, timestamp)
+        print "data %d" % len(commit_msg)
+        print commit_msg
+        print "M 644 inline %s" % os.path.join(subdir, "%s.mdwn" % stub)
+        print "data %d" % len(data)
+        print data
+
+if __name__ == "__main__":
+    if len(sys.argv) not in (4, 5):
+        print >>sys.stderr, "%s: usage: %s name email subdir [branch] < wordpress-export.xml | git-fast-import " % (sys.argv[0], sys.argv[0])
+    else:
+        main(*sys.argv[1:])
+
+</pre>
+-----
+
+I have another version of the script, which uses the `timestamp` from the script, and inserts that as a \[[!meta date="foodate"]]. I'm posting it here just in case I happen to be doing something to the httpd.
+
+(Hopefully I've escaped everything properly; if I missed something, check the source.)
+
+-----
+<pre>
+#!/usr/bin/env python
+
+"""
+    Purpose:
+    Wordpress-to-Ikiwiki import tool
+
+    Copyright:
+    Copyright (C) 2007  Chris Lamb <chris@chris-lamb.co.uk>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    Usage: run --help as an argument with this script.
+
+    Notes:
+    I added some extra bits to include the \[[!tag foo]] stuff in the post,
+    as it wasn't before, at all. I'll diff the versions out so you can see
+    the mess I made :).
+
+"""
+
+import os, sys
+import time
+import re
+
+from datetime import datetime
+from BeautifulSoup import BeautifulSoup
+
+import codecs, htmlentitydefs
+
+codecs.register_error('html_replace', lambda x: (''.join([u'&%s;' \
+    % htmlentitydefs.codepoint2name[ord(c)] for c in x.object[x.start:x.end]]), x.end))
+
+def main(name, email, subdir, branch='master'):
+    soup = BeautifulSoup(sys.stdin.read())
+
+    # Regular expression to match stub in URL.
+    stub_pattern = re.compile(r'.*\/(.+)\/$')
+
+    for x in soup.findAll('item'):
+        # Ignore draft posts
+        if x.find('wp:status').string != 'publish': continue
+
+        match = stub_pattern.match(x.guid.string)
+        if match:
+            stub = match.groups()[0]
+        else:
+            # Fall back to our own stubs
+            stub = re.sub(r'[^a-zA-Z0-9_]', '-', x.title.string).lower()
+
+        commit_msg = """Importing WordPress post "%s" [%s]""" % (x.title.string, x.guid.string)
+        timestamp = time.mktime(time.strptime(x.find('wp:post_date_gmt').string, "%Y-%m-%d %H:%M:%S"))
+        content = '\[[!meta title="%s"]]\n' % (x.title.string.replace('"', r'\"'))
+        content += "\[[!meta date=\"%s\"]]\n" % datetime.fromtimestamp(timestamp)
+        content += x.find('content:encoded').string.replace('\r\n', '\n')
+
+        """
+        We do it differently here because we have duplicates otherwise.
+        Take a look:
+        &lt;category&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
+        &lt;category domain="category" nicename="health"&gt;&lt;![CDATA[Health]]&gt;&lt;/category&gt;
+
+        If we do the what original did, we end up with all tags and cats doubled.
+        Therefore we only pick out nicename="foo". Our 'True' below is our 'foo'.
+        I'd much rather have the value of 'nicename', and tried, but my
+        python skillz are extremely limited....
+        """
+        categories = x.findAll('category', nicename=True)
+        if categories:
+            content += "\n"
+            for cat in categories:
+                # remove 'tags/' because we have a 'tagbase' set.
+                # your choice: 'tag', or 'taglink'
+                # content += "\n\[[!tag %s]]" % (cat.string.replace(' ', '-'))
+                content += "\n\[[!taglink %s]]" % (cat.string.replace(' ', '-'))
+                # this is just debugging, and for fun
+                # print >>sys.stderr, cat.string.replace(' ', '-')
+
+        # moved this thing down
+        data = content.encode('ascii', 'html_replace')
+        print "commit refs/heads/%s" % branch
+        print "committer %s &lt;%s&gt; %d +0000" % (name, email, timestamp)
+        print "data %d" % len(commit_msg)
+        print commit_msg
+        print "M 644 inline %s" % os.path.join(subdir, "%s.mdwn" % stub)
+        print "data %d" % len(data)
+        print data
+
+if __name__ == "__main__":
+    if len(sys.argv) not in (4, 5):
+        print >>sys.stderr, "%s: usage: %s name email subdir [branch] < wordpress-export.xml | git-fast-import " % (sys.argv[0], sys.argv[0])
+    else:
+        main(*sys.argv[1:])
+
+</pre>
+-----
+
+
+[[!tag wordpress]]
+[[!tag python]]
+[[!tag conversion]]
+[[!tag ikiwiki]]
index 268910ebcdc75883ecf1aaac0732c39b358ef322..b81ffae8d74c8008d3b519047014b73d8932bba4 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="inside .ikiwiki"]]
+[[!meta title="inside .ikiwiki"]]
 
 The `.ikiwiki` directory contains ikiwiki's internal state. Normally,
 you don't need to look in it, but here's some tips for how to do so if
@@ -63,3 +63,28 @@ To remove that user:
 I've not written actual utilities to do this yet because I've only needed
 to do it rarely, and the data I've wanted has been different each time.
 --[[Joey]]
+
+## the session database
+
+`.ikiwiki/sessions.db` is the session database. See the [[!cpan CGI::Session]]
+documentation for more details.
+
+## lockfiles
+
+In case you're curious, here's what the various lock files do.
+
+* `.ikiwiki/lockfile` is the master ikiwiki lock file. Ikiwiki takes this 
+  lock before reading/writing state.
+* `.ikiwiki/commitlock` is locked as a semophore, to disable the commit hook
+  from doing anything.
+* `.ikiwiki/cgilock` is locked by the cgi wrapper, to ensure that only 
+  one ikiwiki process is run at a time to handle cgi requests.
+
+## plugin state files
+
+Some plugins create other files to store their state. 
+
+* `.ikiwiki/aggregate` is a plain text database used by the aggregate plugin
+  to record feeds and known posts.
+* `.ikiwiki/xapian/` is created by the search plugin, and contains xapian-omega
+  configuration and the xapian database.
index c05e7a3e02cf3ff70fd75314ff5be8d6801c8cbd..34d5b92520e0c40bfccf9357769ae8f8e6e848b4 100644 (file)
@@ -16,3 +16,50 @@ No idea how this happened.  I've blown it away and recreated it but, for future
 >>> --getctime does. --[[Joey]]
 
 >> Alas, I seem to have lost the bad index file to periodic /tmp wiping; I'll send it to you if it happens again.  --[[sabr]]
+
+<!-- Add by Blanko -->
+
+## Lost password for an user
+
+This morning, a person has lost its password. I was able to do something to make another password. This is the way I take : 
+
+> You can certianly do that, but do note that ikiwiki will offer to mail a
+> user a password reset link if they lost their password. --[[Joey]]
+
+### Locate the user database
+
+As tips show us, the user database is in the source file, for an example : 
+
+    src/.ikiwiki/userdb
+
+### See which user to modify
+
+Because I don't know the real login of the user, I have to read all the database : 
+
+    perl -le 'use Storable; my $index=Storable::retrieve("userdb"); use Data::Dumper; print Dumper $index'
+
+Then I was able to find this : 
+
+    'Utilisateur' => {
+                 'email' => 'user@pl.fr',
+                 'cryptresettoken' => '$2a$10$cfVeOoVbFw9VzMlgEbPMsu34pwHIFP84mWlkrs2RCKknZYPZkPffm',
+                 'password' => '',
+                 'resettoken' => '',
+                 'cryptpassword' => '$2a$10$H8bYq.dlb68wpnfJgVZQhOdsF9JQ06cteRfhPQPB5eHKnD5Y3u7au',
+                 'regdate' => '1226574052'
+               },
+
+Let's have a look to modify lines.
+
+### Modify the line
+
+When you have found the line to modify, take the user name, and change its password to **sc** (for an example) :
+
+    perl -le 'use Storable; my $userinfo=Storable::retrieve("userdb"); $userinfo->{"Utilisateur"}->{cryptpassword}=q{$2a$10$7viOHCrUkdAVL135Kr6one1mpZQ/FWYC773G1yZ0EtQciI11sSDRS}; Storable::lock_nstore($userinfo, "userdb")'
+    perl -le 'use Storable; my $userinfo=Storable::retrieve("userdb"); $userinfo->{"Utilisateur"}->{cryptresettoken}=q{}; Storable::lock_nstore($userinfo, "userdb")'
+
+Because I don't know how suppress cryptresettoken and resettoken fields, I change their content with *null*.
+
+After all these modifications, the user *Utilisateur* could connect to its account with the password **sc**, and go to Preferences, then change its password.
+
+<!-- End of Blanko's modifications -->
index 8331c9ad9bc66f83f8444b6abee78e4854aefca9..ea7835b33ae9b4ba7b8d720ec921de197a927fea 100644 (file)
@@ -1,14 +1,14 @@
-[[meta title="Integrated issue tracking with Ikiwiki"]]
+[[!meta title="Integrated issue tracking with Ikiwiki"]]
 
-[[meta author="Joey Hess, LinuxWorld.com"]]
+[[!meta author="Joey Hess, LinuxWorld.com"]]
 
-[[meta copyright="""
+[[!meta copyright="""
 Copyright 2007 Joey Hess <joeyh@ikiwiki.info>, LinuxWorld.com  
 [First published](http://www.linuxworld.com/news/2007/040607-integrated-issue-tracking-ikiwiki.html)
 on [LinuxWorld.com](http://www.linuxworld.com/), a publication of Network
 World Inc., 118 Turnpike Rd., Southboro, MA 01772.
 """]]
-[[meta license="[[GPL|freesoftware]]"]]
+[[!meta license="[[GPL|freesoftware]]"]]
 
 Wikis are not just for encyclopedias and websites anymore. You can use
 Ikiwiki in combination with your revision control system to handle issue
@@ -137,7 +137,7 @@ etc, to document different stages of
 their lifecycle. A developer can take ownership of a
 bug by tagging it with something like "owner/Joey".
 
-To tag a wiki page, edit it and add text such as "\[[tag done]]". Note that
+To tag a wiki page, edit it and add text such as "\[[!tag done]]". Note that
 adding a wiki link to "\[[done]]" will have the same categorisation effect
 as a tag, but the link will show up in the body of the page, which is a
 nice effect if used in a sentence such as "This was \[[done]] in version
@@ -155,23 +155,23 @@ be inlined into a given page. A few examples:
 * A typical list of all open bugs, with their full text, and a form to post new
   bugs.
 
-        \[[inline pages="bugs/* and !link(done) and !*/Discussion" actions=yes postform=yes show=0]]
+        \[[!inline pages="bugs/* and !link(done) and !*/Discussion" actions=yes postform=yes show=0]]
 
 * Index of the 30 most recently fixed bugs.
 
-        \[[inline pages="bugs/* and link(done) and !*/Discussion" sort=mtime show=30 archive=yes]]
+        \[[!inline pages="bugs/* and link(done) and !*/Discussion" sort=mtime show=30 archive=yes]]
 
 * Index of the 10 most recently active bugs.
 
-        \[[inline pages="bugs/* and !link(done) and !*/Discussion" sort=mtime show=10]]
+        \[[!inline pages="bugs/* and !link(done) and !*/Discussion" sort=mtime show=10]]
 
 * Open security issues.
 
-        \[[inline pages="bugs/* and link(security) and !link(done) and !*/Discussion"]]
+        \[[!inline pages="bugs/* and link(security) and !link(done) and !*/Discussion"]]
 
 * Full text of bugs assigned to Joey.
 
-        \[[inline pages="bugs/* and link(owner/Joey) and !link(done) and !*/Discussion" show=0]]
+        \[[!inline pages="bugs/* and link(owner/Joey) and !link(done) and !*/Discussion" show=0]]
 
 It may seem strange to consider using a wiki for issue tracking when there
 are several dedicated bug tracking systems, like Bugzilla, that handle all
index bb14f6d38492b3341642250ef57001e38da694ed..9758beb80d4da3cad214a48307ea27bd1a24d827 100644 (file)
@@ -15,13 +15,15 @@ for setting up ikiwiki with git.
 Next, `git clone` the source (`$REPOSITORY`, not `$SRCDIR`)
 from the server to the laptop.
 
-Now, set up a web server on your laptop, if it doesn't already have one.
+Now, set up a [[web_server|dot_cgi]] on your laptop, if it doesn't
+already have one.
 
 Now you need to write a setup file for ikiwiki on the laptop. Mostly this
 is standard, but a few special settings are needed:
 
 * Configure a cgi wrapper as usual, but configure the git wrapper to
-  be written to the `post-commit` hook of the git clone.
+  be written to the `post-commit` hook of the git clone, rather than the
+  usual `post-update` hook.
 
 * By default, ikiwiki pulls and pushes from `origin`. This shouldn't be 
   done on the laptop, because the origin may not be accessible (when the
@@ -42,8 +44,8 @@ run setup.)
 
 Use standard git commands to handle pulling from and pushing to the server.
 
-Note: Currently, after pulling changes, you will need to manually update
-the wiki, with a command such as `ikiwiki -setup wiki.setup -refresh`. This
-is because git 1.5.4 doesn't have a hook that is run locally after pulling
-changes. Newer versions of git will have a `post-merge` hook that should
-work for this purpose.
+Note that if changes are pulled from the server, you will need to manually
+update the wiki, with a command such as `ikiwiki -setup wiki.setup -refresh`.
+If you'd like it to automatically update when changes are merged in, you
+can simply make a symlink `post-merge` hook pointing at the `post-update`
+hook ikiwiki created.
index 234833ca7c12ee537e9a9a63783a8c2cf074a569..6ce72ae7b8cd749a1d2ad2d8fba1977f55bc1635 100644 (file)
@@ -5,3 +5,8 @@ Or, was this last remark about rebuilding after pulling meant to apply to rebuil
 [[DavidBremner]]
 
 * *Updated*  Now that I play with this a bit, this seems not so important.  Having a seperate sync operation that I run from the laptop is no big deal, and lets me update the parts of my site not yet managed by ikiwiki at the same time.
+
+* Ok, I have finally finished to set this up. I have a question for you :) Is it mandatory to have a locally running webserver on the laptop ? I mean, do I need to setup the CGI wrapper on the laptop ? Is it possible to just add/edit/delete/whatever, git commit all the stuff and git push back to the server ? Thank you. --[[xma]]
+
+> Of course you don't need a web server on the laptop. It is useful for
+> previewing pages before publishing them though. --[[Joey]]
index 620370218053d6af22d38eca6032aa1bc5b77e70..0666da4500edb54c6a47e196fa25ead87695f366 100644 (file)
@@ -10,7 +10,7 @@ a bare repo on `gitserver`, and clone that to a workingdir on  gitserver.
   Next create a setup file for the laptop with 
 
         gitorigin_branch=> "",
-        wrapper => "/working/dir/.git/hooks/post-commit",
+        git_wrapper => "/working/dir/.git/hooks/post-commit",
     
   At this point, assuming you followed page above, and not my hasty summary, 
 
@@ -21,7 +21,7 @@ a bare repo on `gitserver`, and clone that to a workingdir on  gitserver.
 2. Now create a setup file for the server (I call it server.setup).
 
         gitorigin_branch=> "origin",
-        wrapper => "/repo/wiki.git/hooks/post-update.ikiwiki"
+        git_wrapper => "/repo/wiki.git/hooks/post-update.ikiwiki"
        
   Note the non-standard and bizzare name of the hook.   
 
diff --git a/doc/tips/markdown_and_eclipse.mdwn b/doc/tips/markdown_and_eclipse.mdwn
new file mode 100644 (file)
index 0000000..9e8e9bf
--- /dev/null
@@ -0,0 +1,4 @@
+For people that were not born with GNU emacs fingers, 
+there is a markdown editor (with preview and outline)
+for [eclipse](http://www.eclipse.org) available 
+[here](http://www.winterwell.com/software/markdown-editor.php).
diff --git a/doc/tips/mathopd_permissions.mdwn b/doc/tips/mathopd_permissions.mdwn
new file mode 100644 (file)
index 0000000..c0425b9
--- /dev/null
@@ -0,0 +1,15 @@
+When using [mathopd](http://www.mathopd.org) to serve ikiwiki, be careful of your Umask settings in the mathopd.conf.
+
+With `Umask 026` in mathopd.conf, editing pages resulted in the following errors and a 404 page when the wiki tried to take me to the updated page.
+
+    append_indexes: cannot open .../[destdir]/[outputfile].html
+    open: Permission denied
+
+With `Umask 022` in mathopd.conf, editing pages works.
+
+Hopefully this prevents someone else from spending ~2 hours figuring out why this wouldn't work. ;)
+
+> More generally, if your web server uses a nonstandard umask
+> or you're getting permissions related problems in the cgi log
+> when using ikiwiki, you can force ikiwiki to use a sane umask
+> via the `umask` setting in ikiwiki's own setup file. --[[Joey]] 
index 435743bf9c1331e0e33c72e2727ed667ba5a733d..4b3b02eac8acbb2e35cfa4c930c9b5c7808f0bac 100644 (file)
@@ -76,16 +76,16 @@ Here is an example of how I set up a wiki:
 
        mkdir ~/wiki
        cd ~/wiki
-       cp ~/ikiwiki/doc/ikiwiki.setup .
        cp -r ~/ikiwiki/doc/examples/blog/* .
+       ikiwiki -dumpsetup ikiwiki.setup
        nano ikiwiki.setup
        # Set destdir to /home/htdocs
        # Set srcdir to /home/private/wiki
-       # Set url to http://yoursite.nfshost.com/ , set cgiurl likewise
-       # Uncomment the `rcs => "git"` line, and the cgi and git
-       # post-update wrapper blocks.
-       # Set the cgi wrapper path to /home/htdocs/ikiwiki.cgi
-       # Set the git wrapper path to /home/private/wiki.git/hooks/post-update
+       # Set url to http://yoursite.nfshost.com/
+       # Set cgiurl to http://yoursite.nfshost.com/ikiwiki.cgi
+       # Uncomment the `rcs => "git"` line.
+       # Set the cgi_wrapper path to /home/htdocs/ikiwiki.cgi
+       # Set the git_wrapper path to /home/private/wiki.git/hooks/post-update
        # Configure the rest to your liking and save the file.
        ikiwiki-makerepo git . ../wiki.git
        ikiwiki -setup ikiwiki.setup
diff --git a/doc/tips/parentlinks_style.mdwn b/doc/tips/parentlinks_style.mdwn
new file mode 100644 (file)
index 0000000..5294e54
--- /dev/null
@@ -0,0 +1,124 @@
+Here are some tips for ways to style the links
+provided by the [[plugins/parentlinks]] plugin.
+
+This plugin offers a `HTML::Template` loop that iterates over all or
+a subset of a page's parents. It also provides a few bonus
+possibilities, such as styling the parent links depending on their
+place in the path.
+
+[[!toc ]]
+
+Content
+=======
+
+The plugin provides one template loop, called `PARENTLINKS`, that
+returns the list of parent pages for the current page. Every returned
+path element has the following variables set:
+
+* `URL` (string): url to the current path element
+* `PAGE` (string): title of the current path element
+* `DEPTH` (positive integer): depth of the path leading to the
+  current path element, counting from the wiki's root, which has
+  `DEPTH=0`
+* `HEIGHT` (positive integer): distance, expressed in path elements,
+  from the current page to the current path element; e.g. this is
+  1 for the current page's mother, 2 for its grand-mother, etc.
+* `DEPTH_n` (boolean): true if, and only if, `DEPTH==n`
+* `HEIGHT_n` (boolean): true if, and only if, `HEIGHT==n`
+
+Usage
+=====
+
+The `DEPTH_n` and `HEIGHT_n` variables allow the template writer to
+skip arbitrary elements in the parents list: they are arbitrary
+page-range selectors.
+
+The `DEPTH` and `HEIGHT` variables allow the template writer to apply
+general treatment, depending on one of these variables, to *every*
+parent: they are counters.
+
+Basic usage
+-----------
+
+As in the default `page.tmpl`, one can simply display the list of
+parent pages:
+
+       <TMPL_LOOP NAME="PARENTLINKS">
+       <a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>/ 
+       </TMPL_LOOP>
+       <TMPL_VAR TITLE>
+
+
+Styling parents depending on their depth
+----------------------------------------
+
+Say you want the parent links to be styled depending on their depth in
+the path going from the wiki root to the current page; just add the
+following lines in `page.tmpl`:
+
+       <TMPL_LOOP NAME="PARENTLINKS">
+       <a href="<TMPL_VAR NAME="URL">" class="depth<TMPL_VAR NAME="DEPTH">">
+         <TMPL_VAR NAME="PAGE">
+       </a> / 
+       </TMPL_LOOP>
+
+Then write the appropriate CSS bits for `a.depth1`, etc.
+
+Skip some parents, style the others depending on their distance to the current page
+-----------------------------------------------------------------------------------
+
+Say you want to display all the parents links but the wiki homepage,
+styled depending on their distance to the current page; just add the
+following lines in `page.tmpl`:
+
+       <TMPL_LOOP NAME="PARENTLINKS">
+       <TMPL_IF NAME="DEPTH_0">
+       <TMPL_ELSE>
+       <a href="<TMPL_VAR NAME="URL">" class="height<TMPL_VAR NAME="HEIGHT">">
+         <TMPL_VAR NAME="PAGE">
+       </a> / 
+       </TMPL_LOOP>
+
+Then write the appropriate CSS bits for `a.height1`, etc.
+
+Full-blown example
+------------------
+
+Let's have a look at a more complicated example; combining the boolean
+loop variables provided by the plugin (`IS_ROOT` and friends) and
+`HTML::Template` flow control structures, you can have custom HTML
+and/or CSS generated for some special path components; e.g.:
+
+       <!-- all parents, skipping mother and grand'ma, inside a common div+ul -->
+       <div id="oldestparents">
+       <ul>
+       <TMPL_LOOP NAME="PARENTLINKS">
+         <TMPL_IF NAME="HEIGHT_2">
+         <TMPL_ELSE>
+           <TMPL_IF NAME="HEIGHT_1">
+           <TMPL_ELSE>
+             <li><a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a></li>
+           </TMPL_IF>
+         </TMPL_IF>
+       </TMPL_LOOP>
+       </ul>
+       </div>
+       
+       <!-- dedicated div's for mother and grand'ma -->
+       <TMPL_LOOP NAME="PARENTLINKS">
+         <TMPL_IF NAME="HEIGHT_2">
+           <div id="grandma">
+             <a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a>
+           </div>
+         <TMPL_ELSE>
+           <TMPL_IF NAME="HEIGHT_1">
+             <div id="mother">
+               <a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="PAGE"></a>
+             </div>
+           </TMPL_IF>
+         </TMPL_IF>
+       </TMPL_LOOP>
+       
+       <!-- eventually, the current page title -->
+       <TMPL_VAR NAME="TITLE">
+       </div>
diff --git a/doc/tips/untrusted_git_push.mdwn b/doc/tips/untrusted_git_push.mdwn
new file mode 100644 (file)
index 0000000..3573a0d
--- /dev/null
@@ -0,0 +1,122 @@
+This tip will describe how to allow anyone on the planet to `git push`
+changes into your wiki, without needing a special account. All a user needs
+to know is:
+
+       git clone git://your.wiki/path
+       # now modify any of the files the wiki would let you modify on the web
+       git push
+
+This is a wonderful thing to set up for users, because then they can work
+on the wiki while offline, and they don't need to mess around with web
+browsers.
+
+## security
+
+But, you might be wondering, how can this possibly be secure. Won't users
+upload all sorts of garbage, change pages you don't want them to edit, and so
+on.
+
+The key to making it secure is configuring ikiwiki to run as your git
+repository's `pre-receive` hook. There it will examine every change that
+untrusted users push into the wiki, and reject pushes that contain changes
+that cannot be made using the web interface.
+
+So, unless you have the [[plugins/attachment]] plugin turned on,
+non-page files cannot be added. And if it's turned on, whatever
+`allowed_attachments` checks you have configured will also check files
+pushed into git.
+
+And, unless you have the [[plugins/remove]] plugin turned on, no
+files can be deleted.
+
+And if you have `locked_pages` configured, then it will also affect what's
+pushed into git.
+
+Untrusted committers will also not be able to upload files with strange
+modes, or push to any branch except for the configured `gitorigin_branch`,
+or manipulate tags.
+
+One thing to keep an eye on is uploading large files. It may be easier to
+do this via git push than using the web, and that could be abused.
+
+Also, no checking is done that the authors of commits are right, so people
+can make a commit that pretends to be done by someone else.
+
+## user setup
+
+Add a dedicated user who will push in untrusted commits. This user should have
+a locked password, and `git-shell` as its shell.
+
+       root@bluebird:/home/joey>adduser --shell=/usr/bin/git-shell --disabled-password anon
+       Adding user `anon' ...
+
+## ikiwiki setup
+
+You should set up ikiwiki before turning on anonymous push in git. 
+
+Edit your wiki's setup file, and uncomment the lines for
+`git_test_receive_wrapper` and `untrusted_committers`.
+
+       # git pre-receive hook to generate
+       git_test_receive_wrapper => '/srv/git/ikiwiki.info/.git/hooks/pre-receive',
+       # unix users whose commits should be checked by the pre-receive hook
+       untrusted_committers => ['anon'],
+
+The `git_test_receive_wrapper` will become the git `pre-receive` hook. The
+`untrusted_committers` list is the list of unix users who will be pushing in
+untrusted changes. It should *not* include the user that ikiwiki normally runs
+as.
+
+Once you're done modifying the setup file, don't forget to run
+`ikiwiki -setup --refresh --wrappers` on it.
+
+## git setup
+
+You'll need to arrange the permissions on your bare git repository so that
+user anon can write to it. One way to do it is to create a group, and put
+both anon and your regular user in that group. Then make the bare git
+repository owned and writable by the group. See [[rcs/git]] for some more
+tips on setting up a git repository with multiple committers.
+
+Note that anon should *not* be able to write to the `srcdir`, *only* to the bare git
+repository for your wiki.
+
+If you want to allow git over `ssh`, generate a ssh key for anon, and
+publish the *private* key for other people to use. This is optional; you
+can use `git-daemon` instead and not worry about keys.
+
+Now set up `git-daemon`. It will need to run as user `anon`, and be
+configured to export your wiki's bare git repository. I set it up as
+follows in `/etc/inetd.conf`, and ran `/etc/init.d/openbsd-inetd restart`.
+
+       git     stream  tcp     nowait  anon          /usr/bin/git-daemon git-daemon --inetd --export-all --interpolated-path=/srv/git/%H%D /srv/git
+
+At this point you should be able to `git clone git://your.wiki/path` from
+anywhere, and check out the source to your wiki. But you won't be able to
+push to it yet, one more change is needed to turn that on. Edit the
+`config` file of your bare git repository, and allow `git-daemon` to
+receive pushes:
+
+       [daemon]
+               receivepack = true
+
+Now pushes should be accepted, and your wiki immediatly be updated. If it
+doesn't, check your git repo's permissions, and make sure that the
+`post-update` and `pre-receive` hooks are suid so they run as the user who
+owns the `srcdir`.
+
+## infelicities
+
+If a user tries to push a changeset that ikiwiki doesn't like, it will
+abort the push before refs are updated. However, the changeset will still
+be present in your repository, wasting space. Since nothing refers to it,
+it will be expired eventually. You can speed up the expiry by running `git
+prune`.
+
+When aborting a push, ikiwiki displays an error message about why it didn't
+accept it. If using git over ssh, the user will see this error message,
+which is probably useful to them. But `git-daemon` is buggy, and hides this
+message from the user. This can make it hard for users to figure out why
+their push was rejected. (If this happens to you, look at "'git log --stat
+origin/master..`" and think about whether your changes would be accepted
+over the web interface.)
diff --git a/doc/tips/untrusted_git_push/discussion.mdwn b/doc/tips/untrusted_git_push/discussion.mdwn
new file mode 100644 (file)
index 0000000..d95c01e
--- /dev/null
@@ -0,0 +1,33 @@
+I've just tried this (commit c1fa07a). Recent changes shows:
+
+<div id="change-c1fa07ad4f165b42c962ba2a310681107f38c4f7" class="metadata">
+<span class="desc"><br />Changed pages:</span>
+<span class="pagelinks">
+
+<a href="http://git.ikiwiki.info/?p=ikiwiki;a=blobdiff;h=8bfa3dd7601a09b11ecbd20026849a777dc4b1b9;hp=c6302616f52ec058de5a8f5956fc512149a2f1a3;hb=1ea66c3d3f0a33bc3f04d073457b525a70380c37;f=doc/users/jondowland.mdwn"><img src="/wikiicons/diff.png" alt="diff" /></a><a href="http://ikiwiki.info/ikiwiki.cgi?page=users%2Fjondowland&amp;do=recentchanges_link">users/jondowland</a>
+
+
+</span>
+<span class="desc"><br />Changed by:</span>
+<span class="committer">
+
+<a href="http://ikiwiki.info/ikiwiki.cgi?page=users%2Fjon&amp;do=recentchanges_link">jon</a>
+
+</span>
+<span class="desc"><br />Commit type:</span>
+<span class="committype">git</span>
+<span class="desc"><br />Date:</span>
+<span class="changedate"><span class="relativedate" title="Mon, 10 Nov 2008 18:24:22 -0500">18:24:22 11/10/08</span>
+</div>
+
+Note that the user for the commit is 'jon', and the link points at cgi to
+create users/jon. I was wondering if that is configurable for users pushing
+via git. It would be nice perhaps to specify it in some way, perhaps via a
+git-config setting (user.name?). I'm not too familiar with exactly what the
+changeset contains. -- [[users/Jon]]
+
+> All ikiwiki can do it look at who git has recorded as the author of
+> the change (and it looks at the username part of the email address).
+> You can set `user.email` in `.git/config`. --[[Joey]]
+
+> > Ah, excellent. In which case this *should* DTRT... -- [[users/Jon]]
diff --git a/doc/tips/upgrade_to_3.0.mdwn b/doc/tips/upgrade_to_3.0.mdwn
new file mode 100644 (file)
index 0000000..d22813b
--- /dev/null
@@ -0,0 +1,95 @@
+Version 3.0 of ikiwiki makes some significant changes, which
+you will need to deal with when upgrading from ikiwiki 2.x.
+
+[[!toc ]]
+
+## setup file format change
+
+The layout of the setup file changed in a significant way in version 2.60
+of ikiwiki. If you have not changed yours to the new format, now would be a
+good time to do so. Some new features, like the [[plugins/websetup]]
+interface, need the new format setup file.
+  
+You can convert old setup files into the new format by running
+`ikiwiki-transition setupformat your.setup`
+
+## moving settings from Preferences page
+
+The admin preferences page used to have settings for allowed attachments,
+locked pages, and banned users. These three settings have moved to the
+setup file, and will no longer appear on the admin preferences page once
+your wiki is upgraded to 3.0.
+
+You can move these preferences into the setup file by running
+`ikiwiki-transition moveprefs your.setup; ikiwiki -setup your.setup -refresh -wrappers`
+
+(Make sure you have converted the setup file to the new format first.)
+
+## prefix directives
+
+In 3.0, the syntax ikiwiki uses for [[directives|ikiwiki/directive]] has
+changed, requiring that the directive start with a bang: 
+
+       \[[!directive ...]]
+
+If you would like to keep the old syntax, it is still supported, add the
+following to your setup file:
+       
+       prefix_directives => 0,
+
+To convert to the new syntax, make sure that your setup file does *not*
+contain the above, then run `ikiwiki-transition prefix_directives your.setup`
+
+(And then commit the changes it makes to pages in your srcdir.)
+
+## GlobLists
+
+In 3.0, the old "GlobList" syntax for [[PageSpecs|ikiwiki/PageSpec]] is no
+longer supported. A GlobList contains multiple term, but does not separate
+them with "and" or "or":
+
+       sandbox !*/Discussion
+
+To convert this to a modern PageSpec, simply add "and" or "or" as
+appropriate between terms:
+       
+       sandbox and !*/Discussion
+
+GlobLists have been deprecated for more than two years. If your wiki dates
+to the ikiwiki 1.0 era, you should check it for any that might have lurked
+unnoticed in it since back then. Ikiwiki version 2.72 will print warnings
+about any GlobLists it sees.
+
+## aggregateinternal
+
+If your wiki uses the [[aggregate|plugins/aggregate]] plugin, it will start
+to aggregate feeds to special "internal" pages.
+
+If you don't want this change, you can add the following to your setup
+file:
+
+       aggregateinternal => 0,
+
+Otherwise, follow this procedure to upgrade a wiki using the aggregate plugin:
+
+1. Update all [[PageSpecs|ikiwiki/PageSpec]] that refer to the aggregated
+   pages -- such as those in inlines. Put "internal()" around globs
+   in those PageSpecs. For example, if the PageSpec was `foo/*`, it should
+   be changed to `internal(foo/*)`. This has to be done because internal
+   pages are not matched by regular globs.
+2. Use [[ikiwiki-transition]] to rename all existing aggregated `.html`
+   files in the srcdir. The command to run is
+   `ikiwiki-transition aggregateinternal your.setup`,
+3. Refresh the wiki. (`ikiwiki -setup your.setup -refresh`)
+
+## embed / googlecalendar
+
+The googlecalendar plugin has been deprecated for a long time, and is
+removed in 3.0.
+
+The embed plugin is also now deprecated, though not yet removed.
+
+If you use either plugin to embed content from google, youtube, etc,
+into your wiki, you should instead configure the [[plugins/htmlscrubber]]
+to skip sanitising some pages, via the `htmlscrubber_skip` setting.
+See [[embedding_content]] for examples.
index d696bacdbd265024f5b4a3f4fdd0603ba5b31f6c..cf9327395bcde7ab38fea3d02df3b9aa65610e5d 100644 (file)
@@ -4,3 +4,10 @@ you to use a real text editor like Emacs or Vim to edit the contents of text
 areas.  This allows you to edit ikiwiki pages with a real text editor through
 the ikiwiki web interface, rather than only with direct commit 
 access. --[[JoshTriplett]] 
+
+For Firefox or Iceweasel users, the vimperator extension is also a good
+idea.  You can press Ctrl-I in the insert mode of vimperator and switch to
+an external editor, e.g. Vim. --[[WeakishJiang]]
+
+Finally, with wikis configured to allow, [[untrusted_git_push]], you can
+ditch the browser altogether. --[[Joey]] 
index 453efa8d1d80568f78ec94c82f0031674bde9422..172b763c34ae96ff879742d34965a1b5a090474d 100644 (file)
@@ -1,2 +1,4 @@
-[[ikiwiki.vim]] is a vim syntax highlighting file for ikiwiki. Installation
-instructions are at the top of the file.
+[[ikiwiki.vim]] is a vim syntax highlighting file for ikiwiki
+[[ikiwiki/markdown]] files. 
+
+Installation instructions are at the top of the file.
index b1637e7584845af0a9c448b03db3b90c335d9052..72cb52aab1c74b49f62bebbf697239ec2e575f84 100644 (file)
@@ -1 +1,8 @@
-I'm going to look at merging this with potwiki.vim (a vim-based personal wiki) so that you can follow wiki-links and auto-create pages etc., direct from vim. (I'm writing this incase I don't get around to it) -- [[JonDowland]]
+I'm going to look at merging this with potwiki.vim (a vim-based personal wiki) so that you can follow wiki-links and auto-create pages etc., direct from vim. (I'm writing this incase I don't get around to it) -- [[users/Jon]]
+
+----
+
+Another attempt at the same thing is here:
+<http://plasticboy.com/markdown-vim-mode/>
+
+In my tests, [[ikiwiki.vim]] works better than that one, YMMV. --[[Joey]]
index fd87f49a21678dd7f9c56ecb1ce6221246c3d977..bbcad4239f81ec4543bec7d58156559580309ca8 100644 (file)
@@ -1,6 +1,6 @@
 " Vim syntax file
 " Language:     Ikiwiki (links)
-" Maintainer:   Recai Oktaþ (roktasATdebian.org)
+" Maintainer:   Recai Oktaş (roktasATdebian.org)
 " Last Change:  2007 May 29
 
 " Instructions:
index 0d1973546c09b1a2c4cf7d48c245caa5485cc3a8..6eb142cdf277abcf89bc8a959f38832a26c585ef 100644 (file)
@@ -2,7 +2,7 @@ One thing I use ikiwiki for is the web pages for software projects I
 maintain. Each of my projects has a news page with an announcements feed,
 and to automatically update this when I release a new version, generating
 an announcement from the debian/changelog and debian/NEWS files, I use a
-[wikiannounce](http://git.kitenet.net/?p=joey/home;a=blob_plain;f=bin/wikiannounce)
+[wikiannounce](http://git.kitenet.net/?p=joey/home.git;a=blob_plain;f=bin/wikiannounce)
 program. It's somewhat specific to dealing with Debian packages, and uses a
 special `announcedir` target in debian/rules, but the general idea could be
 useful. --[[Joey]]
index 851b4d6b300d4bb0b2525a8df79c148da3219bb4..75314c75becf25f3f801a077910c495d485b1694 100644 (file)
@@ -3,19 +3,19 @@ as any [[patches|patch]]. If it seems more like a bug in the existing code,
 post it to [[bugs]] instead. Link items to [[todo/done]] when done.
 
 <!-- currently commented out because I lost all my mtimes :-)
-[[if test="enabled(postsparkline)"
+[[!if test="enabled(postsparkline)"
 then="""
 How long will it take your todo item to be fixed? Well...  
-[[postsparkline pages="todo/* and !todo/done and !link(todo/done) and !todo/*/*"
+[[!postsparkline pages="todo/* and !todo/done and !link(todo/done) and !todo/*/*"
 max=12 ymin=10 formula=permonth style=bar barwidth=2 barspacing=1 height=13]]
 this many are being added per month  
-[[postsparkline pages="todo/* and !todo and link(todo/done)"
+[[!postsparkline pages="todo/* and !todo and link(todo/done)"
 max=12 ymin=10 formula=permonth time=mtime style=bar barwidth=2 barspacing=1 height=13]]
 while this many are being fixed.
 """]]
 -->
 
-[[inline pages="todo/* and !todo/done and !link(todo/done) and
+[[!inline pages="todo/* and !todo/done and !link(todo/done) and
 !link(patch) and !link(wishlist) and !todo/*/*"
 feedpages="created_after(todo/supporting_comments_via_disussion_pages)"
 actions=yes archive=yes rootpage="todo" postformtext="Add a new todo item titled:" show=0]]
index 1e068cb070e7885f49910dbd16e0a0cfe7ffe58d..e9fb2717f10d4f6edd18fd1175d8eac763effcdf 100644 (file)
@@ -21,7 +21,31 @@ something, that I think is very valuable.
 >>>> Which would rule out openid, or other fun forms of auth. And routing all access
 >>>> through the CGI sort of defeats the purpose of ikiwiki. --[[Ethan]]
 
-Also see [[debbug 443346]].
+Also see [[!debbug 443346]].
+
+> Just a few quick thoughts about this:
+>
+>* I'm only thinking about write ACLs.  As Joey noted, read ACLs need to be done in the web server.
+>* ACLs are going to be really hard for people with direct access to the revision control system.
+>  Which means that we really only need to define ACLs for web access.
+>* ACLs for web access can then be defined by the web master.  These might not need to be
+>  defined in the wiki pages (although they could be).
+>* Given the previous two points, can't this be done with the `match_user()`
+> function defined by the [[plugins/attachment]] plugin (see the [[ikiwiki/pagespec/attachment]] pagespec info)
+> and the [[plugins/lockedit]] plugin?
+>
+> For example, add the following to your config file:
+>
+> locked_pages => '!(user(john) and */Discussion) and *',
+>
+> would lock all pages unless you're john and editing a Discussion page.
+> It's a thought anyway :-).  -- [[Will]]
+
+>> Yes, writing per-user commit ACLs has become somewhat easier with recent
+>> features. Breaking `match_user` out of attachment, and making the
+>> lockedit plugin pass`user` and `ip` params when it calls `pagespec_match`
+>> would be sufficient. And [[done]], configurable via
+>> [[plugin/lockedit]]'s `locked_pages`. --[[Joey]]
 
 I am considering giving this a try, implementing it as a module.
 Here is how I see it:
@@ -30,10 +54,10 @@ Here is how I see it:
     for a given (user, page, operation), as in:
 
     <pre>
-    \[[acl user=joe page=*.png allow=upload]]
-    \[[acl user=bob page=/blog/bob/* allow=*]]
-    \[[acl user=* page=/blog/bob/* deny=*]]
-    \[[acl user=http://jeremie.koenig.myopenid.com/ page=/todo/* deny=create
+    \[[!acl user=joe page=*.png allow=upload]]
+    \[[!acl user=bob page=/blog/bob/* allow=*]]
+    \[[!acl user=* page=/blog/bob/* deny=*]]
+    \[[!acl user=http://jeremie.koenig.myopenid.com/ page=/todo/* deny=create
            reason="spends his time writing todo items instead of source code"]]
     </pre>
 
@@ -43,5 +67,5 @@ Here is how I see it:
     Possibly could refer to other ACL pages, as in:
 
     <pre>
-    \[[acl user=* page=/subsite/* acl=/subsite/acl.mdwn]]
+    \[[!acl user=* page=/subsite/* acl=/subsite/acl.mdwn]]
     </pre>
index 8a4a41971e68d976abee7f11ef3985545f73050c..543c346acc06e8cb6cbf0f2991c810b1bab8ecd5 100644 (file)
@@ -3,7 +3,7 @@ getting regenerated even when I edited only a page that did not affect
 any feed.
 
 I found that the problem only occurs in the presence of a file that
-contains \[[inline pages="*"]].
+contains \[[!inline pages="*"]].
 
 > How is this unexpected? By inlining _every_ page in the wiki, you're
 > making that page depend on every other page; any change to any page in
@@ -15,7 +15,7 @@ contains \[[inline pages="*"]].
 > N+1th page that its PageSpec matches is a no-op.
 > --[[Joey]]
 
-[[tag done]]
+[[!tag done]]
 
 Here's a short script for replicating the bug. Just cut and paste this
 to a shell, (it will only muck in a new /tmp/ikiwiki-test directory
@@ -23,7 +23,7 @@ that it will create):
 
        cd /tmp
        mkdir ikiwiki-test; cd ikiwiki-test; mkdir src
-       echo '\[[inline pages="blog/*"]]' > src/myblog.mdwn
+       echo '\[[!inline pages="blog/*"]]' > src/myblog.mdwn
        mkdir src/blog; echo "A blog entry" > src/blog/entry.mdwn
        echo 'use IkiWiki::Setup::Standard {
                srcdir => "src",
@@ -41,7 +41,7 @@ that it will create):
        echo "not a blog entry" > src/not-a-blog.mdwn
        ikiwiki --setup setup
        ls -l --time-style=full-iso output/myblog/index.rss
-       echo '\[[inline pages="*"]]' > src/archives.mdwn
+       echo '\[[!inline pages="*"]]' > src/archives.mdwn
        ikiwiki --setup setup
        ls -l --time-style=full-iso output/myblog/index.rss
        echo "still not blogging" >> src/not-a-blog.mdwn
@@ -58,7 +58,7 @@ Here's the tail of the output that I see for this command:
        done
        $ ls -l --time-style=full-iso output/myblog/index.rss
        -rw-r--r-- 1 cworth cworth 459 2007-06-01 06:34:36.000000000 -0700 output/myblog/index.rss
-       $ echo '\[[inline pages="*"]]' > src/archives.mdwn
+       $ echo '\[[!inline pages="*"]]' > src/archives.mdwn
        $ ikiwiki --setup setup
        refreshing wiki..
        scanning archives.mdwn
index a03abb196951506211f4272f47c7c7e74d0cc225..6ef7a65f103e469340d2e3c85f8ca316a7532314 100644 (file)
@@ -7,6 +7,6 @@ the account gets approved.)
 
 --[[JoshTriplett]]
 
-[[tag soc]]
+[[!tag soc]]
 
 [[wishlist]]
index 859e6af958215da5a0238296c07e9343cc775cdc..e5ac391c3ab1c41ffb9f23347228ab03a56b368b 100644 (file)
@@ -44,7 +44,7 @@ regenerate this one against that).
                          %config %links %renderedfiles %pagesources %destsources);
         our $VERSION = 2.00; # plugin interface version, next is ikiwiki version
         our $version="2.1";my $installdir="/usr";
-       @@ -70,6 +70,7 @@ sub defaultconfig () { #{{{
+       @@ -70,6 +70,7 @@ sub defaultconfig () {
                plugin => [qw{mdwn inline htmlscrubber passwordauth openid signinedit
                              lockedit conditional}],
                timeformat => '%c',
@@ -52,27 +52,27 @@ regenerate this one against that).
                locale => undef,
                sslcookie => 0,
                httpauth => 0,
-       @@ -447,6 +448,15 @@ sub displaytime ($) { #{{{
+       @@ -447,6 +448,15 @@ sub displaytime ($) {
                                $config{timeformat}, localtime($time)));
-        } #}}}
+        }
 
-       +sub displaydate ($) { #{{{
+       +sub displaydate ($) {
        +       my $time=shift;
        +
        +       # strftime doesn't know about encodings, so make sure
        +       # its output is properly treated as utf8
        +       return decode_utf8(POSIX::strftime(
        +                       $config{dateformat}, localtime($time)));
-       +} #}}}
+       +}
        +
-        sub beautify_url ($) { #{{{
+        sub beautify_url ($) {
                my $url=shift;
 
        diff --git a/Plugin/inline.pm b/Plugin/inline.pm
        index 8f6ab51..7bd6147 100644
        --- a/Plugin/inline.pm
        +++ b/Plugin/inline.pm
-       @@ -148,6 +148,7 @@ sub preprocess_inline (@) { #{{{
+       @@ -148,6 +148,7 @@ sub preprocess_inline (@) {
                                $template->param(pageurl => urlto(bestlink($params{page}, $page), $params{destpage}));
                                $template->param(title => pagetitle(basename($page)));
                                $template->param(ctime => displaytime($pagectime{$page}));
@@ -83,4 +83,4 @@ regenerate this one against that).
        -- 
        1.5.2.2
 
-[[tag patch]]
+[[!tag patch patch/core plugins/inline]]
diff --git a/doc/todo/Add_a_plugin_to_list_available_pre-processor_commands.mdwn b/doc/todo/Add_a_plugin_to_list_available_pre-processor_commands.mdwn
new file mode 100644 (file)
index 0000000..9ac400c
--- /dev/null
@@ -0,0 +1,141 @@
+I've found myself wanting to know which [[plugins]] are switched on so I know which pre-processor commands I can use.  The attached [[patch]] adds a new plugin that generates the list of available plugins. -- [[Will]]
+
+> Good idea, I do see a few problems:
+> 
+> - preprocessor directives do not necessarily have the same name as the
+>   plugin that contains them (for example, the graphviz plugin adds a graph
+>   directive). Won't keys `%{IkiWiki::hooks{preprocess}}` work?
+
+>>> Er, yeah - that's a much better solution. :) -- and done
+
+> - "listplugins" is a bit misnamed since it only does preprocessor directives.
+
+>>> Yes.  Initially this was going to list all enabled plugins.  Then when searching
+>>> for enabled plugins I changed my mind and decided that a list of pre-processor
+>>> directives was more useful.  I'll fix that too. -- changed to `listpreprocessors`
+
+> - comment was copied from version plugin and still mentions version :-)
+
+>>> :-) -- fixed
+
+> - Seems like [[ikiwiki/formatting]] could benefit from including the
+>   list.. however, just a list of preprocessor directive names is not
+>   the most user-friendly thing that could be put on that page. It would
+>   be nice if there were also a short description and maybe an example of
+>   use. Seems like the place to include that info would be in the call
+>   to `hook()`.
+>   (Maybe adding that is more involved than you want to go though..)
+> 
+> --[[Joey]]
+
+>> Adding a whole new hook for a usage example is more effort than I
+>> wanted to go to.  I was thinking of either:
+
+>>> Just to clarify, I meant adding new parameters to the same hook call
+>>> that registers the plugin. --[[Joey]]
+
+>>    - Adding a configuration for a wiki directory.  If a matching page is in the
+>>      specified wiki directory then the plugin name gets turned into a link to that
+>>      page
+>>    - Adding configuration for an external URL.  Each plugin name is added as
+>>       a link to the plugin name appended to the URL.
+
+>>The first option is easier to navigate and wouldn't produce broken links,
+>>but requires all the plugin documentation to be local.  The second option
+>>can link back to the main IkiWiki site, but if you have any non-standard
+>>plugins then you'll get broken links.
+>>
+>>Hrm.  After listing all of that, maybe your idea with the hooks is the better
+>>solution.  I'll think about it some more. -- [[Will]]
+
+>>> I've also run into this problem with the websetup plugin, and
+>>> considered those ideas too. I don't like the external url, because
+>>> ikiwiki.info may be out of sync with the version of ikiwiki being used.
+>>> (Or maybe it's gone! :-) The first idea is fine, except for the bloat
+>>> issue. If turning on listpreprocessors and/or websetup means adding
+>>> hundreds of pages (and of kilobytes) to your wiki, that could be an
+>>> incentive to not turn them on..
+>>>
+>>> Hmm.. maybe the thing to do is to use _internal pages for the plugins;
+>>> then the individual pages would not be rendered, and your inlines would
+>>> still work. Although I don't know how websetup would use it then, and
+>>> also they would have to be non-internal for ikiwiki's own docwiki. Hmm.
+>>> Maybe these are two different things; one is a set of pages describing
+>>> preprocessor directives, and the second a set of pages describing
+>>> plugins. They're so closely related though it seems a shame to keep
+>>> them separate..
+>>> --[[Joey]]
+
+>>> I started implementing the hook based solution, and decided I didn't like
+>>> it because there was no nice way to rebuild pages when the preprocessor
+>>> descriptions changed.  So instead I assumed that the the [[plugins]] pages
+>>> would be moved into the underlay directory.  This plugin then uses an
+>>> `inline` directive to include those pages.  You can use the `inline`
+>>> parameter to decide if you want to include all the descriptions or
+>>> just the titles.  There is also an option to auto-create default/blank
+>>> description pages if they are missing (from a template).  As preprocessor
+>>> commands don't list unless they have a description page, auto-creation
+>>> is enabled by default.
+>>>
+>>>  There are three new templates that are needed.  These are for:
+>>>
+>>>  - The auto-created description pages are generated from `preprocessor-description.tmpl`.
+>>>  - When only pre-processor names are listed, the `listpreprocessors-listonly.tmpl` template is used.
+>>>  - When pre-processor descriptions are included inline, the `listpreprocessors-inline.tmpl` template is used.
+>>>
+>>> -- [[Will]]
+
+>>>> Just a quick note: pages are only created for pre-processor commands
+>>>> that exist when the `refresh` hook is called.  This is before the [[shortcuts]] are
+>>>> processed.  However, the list of available pre-processor commands will include
+>>>> shortcuts if they have description pages (the list is generated later, after the
+>>>> shortcuts have been added).  While this was unplanned, it seems a reasonable
+>>>> tradeoff between including all the large number of shortcuts and including none. -- [[Will]]
+
+>>>>>> I think that using an inline is elegant! However, I don't understand
+>>>>>> why it has to create stub description pages? I doubt that, if a
+>>>>>> directive is missing a page, the stub will be filled out in many
+>>>>>> wikis. And it adds a lot of complexity, particularly committing a
+>>>>>> bunch of generated pages to revision control when the user just
+>>>>>> wants a plugin list seems undesirable.
+>>>>>>
+>>>>>> Seems to me it could use the inline for pages that exist, and append
+>>>>>> to the bottom a generated text for anything that is currently missing.
+>>>>>> The generated text could even have a page creation link in it if
+>>>>>> you wanted.
+>>>>>> --[[Joey]]
+
+>>>>>>> I kinda agree about the page generation.  I don't like mixing an
+>>>>>>> inlined and a list though.  Besides which, that ends
+>>>>>>> up keeping much of complexity of the page generation because
+>>>>>>> the code still has to detect which pages are missing.  I've added
+>>>>>>> a patch that uses a list of wikilinks instead.  This way available
+>>>>>>> pages get linked correctly, and missing pages get normal creation
+>>>>>>> links.  The old patch is still here if you decide you prefer that. -- [[Will]]
+
+>>>>>>>> Can you explain the full/early list (why track both?) and generated parameter?
+
+>>>>>>>>> If you add in all the shortcuts you get quite a long list.  My original idea
+>>>>>>>>> was to just track the plugin commands.  This is the early list.  But then
+>>>>>>>>> I thought that it might be nice for someone looking at wiki source and
+>>>>>>>>> seeing a shortcut to know where it came from.  So I decided to make
+>>>>>>>>> displaying the full list an option, with the original concept as the default.
+
+>>>>>>>>> Another option here might be to generate the full list every time, but give
+>>>>>>>>> generated pre-processor commands (e.g. shortcuts) a different css class.
+>>>>>>>>> I'm not sure that is better than what I have though. 
+
+>>>>>>>>> I keep track of both in the page state because if a command moves from
+>>>>>>>>> a shortcut to the early list (or vice versa) it changes what should be
+>>>>>>>>> displayed in the default use of the plugin.  I thought about tracking just what
+>>>>>>>>> was actually used on the page, but I don't know in the needsbuild hook whether the `generated`
+>>>>>>>>> parameter has been supplied (or maybe the plugin is used twice on the page -
+>>>>>>>>> once in each form).  It was just easier to track both.
+
+>>>>>>>> Only code change I'd suggest is using `htmllink` rather than 
+>>>>>>>> generating a wikilink.
+
+>>>>>>>>> Yeah - that would make sense.  done. -- [[Will]]
+
+Patch is applied (along with some changes..). [[done]] (But, see
+[[directive_docs]].
diff --git a/doc/todo/Add_camelcase_exclusions.mdwn b/doc/todo/Add_camelcase_exclusions.mdwn
new file mode 100644 (file)
index 0000000..6b86132
--- /dev/null
@@ -0,0 +1,23 @@
+Camelcase currently looks for any and call camelcase words and turns them into wiki links.  This patch adds a config item called <code>camelcase_ignore</code> which is an array of camelcase words to ignore.
+
+<pre>
+--- /usr/share/perl5/IkiWiki/Plugin/camelcase.pm.orig   2008-12-24 11:49:14.000000000 +1300
++++ /usr/share/perl5/IkiWiki/Plugin/camelcase.pm        2008-12-24 12:02:21.000000000 +1300
+@@ -33,7 +33,11 @@
+        my $destpage=$params{destpage};
+        $params{content}=~s{$link_regexp}{
+-               htmllink($page, $destpage, IkiWiki::linkpage($1))
++                if (grep {/$1/} @{ $config{'camelcase_ignore'} }) {
++                  $1
++                } else {
++                 htmllink($page, $destpage, IkiWiki::linkpage($1)) 
++                }
+        }eg;
+        return $params{content};
+</pre>
+
+--[[puck]]
+
+[[done]]
index 43810460f6707c3d44ca1ddcc20005817584beee..e4e83428c3372754c7e2fe36fb0b295b42363a02 100644 (file)
@@ -47,4 +47,4 @@ The patch below adds a label for the field to improve usability:
 > to get it to appear higher up is to put it first, or to use Evil absolute
 > positioning. (CSS sucks.) --[[Joey]]
 
-[[wishlist]]
+[[!tag done wishlist]]
index a3db94bdd3c8a34d949d07cf5b6c10a81243bcf6..7e7947fbce94d1a73d723df26299f335a0ef2b29 100644 (file)
@@ -18,3 +18,14 @@ A demo is at <http://www.attacklab.net/showdown-gui.html>
 >> be worthwhile to consider this option again? It seems to have a companion
 >> product (wmd) with formatting widgets and a live preview pane, that is
 >> promised to be MIT licensed as of the next release.... --Chapman Flack
+
+>>> What sort of integration would be needed to put in WMD?
+>>> It looks like it would need to be aware of some plugin/wikiword behavior
+>>> ... perhaps taking a Wikiword and making it appear like a link in preview, but
+>>> with a different style (perhaps diff color/font).  For plugin commands,
+>>> applying a 'real' preview would probably be difficult, so it'd probably
+>>> be necessary to insert some sort of placeholder, perhaps by outputting
+>>> the text in monospace form w/ a lighter font to denote that it won't
+>>> directly be shown in the page... -- [[harningt]]
+
+>>>>> We have a wmd plugin now. --[[Joey]] 
index 0dbcef68d90ffc3c7d3dcaf1ec6e6e5a885af680..536980ea8e9cd4e44e5e8ad6b98f50473d91c56b 100644 (file)
@@ -1,4 +1,4 @@
-This patch adds a space before the forward-slash in the the parent links. There is already a space after the slash.
+This [[patch]] adds a space before the forward-slash in the the parent links. There is already a space after the slash.
 
 > I intentionally put the space after the slash and not before, because I
 > like how it looks that way. So I don't plan to apply this patch unless a
@@ -8,6 +8,11 @@ This patch adds a space before the forward-slash in the the parent links. There
 
 >>> Yes, please.  This seems to be something a lot of people want to customize.  (I certainly do -- a forward slash only looks natural to Unix users)  --[[sabr]]
 
+>> Joey, would I be right to summarize your position on this as "people who
+>> want to change the text of the templates should maintain their own version
+>> of the `.tmpl` files"? It's not clear to me how this todo item could be
+>> closed in a way acceptable to you, except perhaps as WONTFIX. --[[smcv]]
+
 Before:
 
     ikiwiki/ todo/ Add space before slash in parent links
@@ -56,3 +61,23 @@ Patch:
     +<TMPL_VAR INDEXLINK> / <TMPL_VAR TITLE>
      </span>
      </div>
+
+----
+
+It's almost implicit in some of the discussion above but this can be achieved locally if you fork your templates directory from ikiwiki's, with an ammendment such as
+
+    <h1><TMPL_LOOP NAME="PARENTLINKS"><a
+        href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>
+        &rarr;
+        </TMPL_LOOP><TMPL_VAR TITLE></h1>
+
+This is what I do on my site for example. -- [[Jon]]
+
+> You don't actually need to fork the whole directory, "only" `page.tmpl` -
+> put `templatedir => "/foo/templates"` in your setup file, copy `page.tmpl`
+> to that directory, and modify it there. IkiWiki will look in `templatedir`
+> first, then fall back to its default templates if any are missing from
+> `templatedir`.
+>
+> (Admittedly, `page.tmpl` is the hardest to maintain a fork of, because it
+> tends to change whenever a new plugin is added...) --[[smcv]]
index 0a509ae2a22d2831a05b21103c99ee3fd18c9876..6b9fa05351aafeb1174705d7f812494c317dc2fe 100644 (file)
@@ -8,11 +8,11 @@ This patch allows IkiWiki to work with either of the two:
 > be a good idea to check out current git master before spending time on
 > patches in the future. Thanks for the work anyway.. --[[Joey]]
 
-[[tag done]]
+[[!tag done]]
 
     --- IkiWiki/Plugin/mdwn.pm.orig    2008-03-08 11:33:50.000000000 +0100
     +++ IkiWiki/Plugin/mdwn.pm 2008-03-08 13:37:21.000000000 +0100
-    @@ -28,14 +28,20 @@ sub htmlize (@) { #{{{
+    @@ -28,14 +28,20 @@ sub htmlize (@) {
                        $markdown_sub=\&Markdown::Markdown;
                }
                else {
@@ -42,4 +42,4 @@ The above patch, which is against ikiwiki-2.40, should fix [[bugs/markdown_modul
 
 -- [[HenrikBrixAndersen]]
 
-[[tag patch]]
+[[!tag patch]]
index 78764c8c6626b08777b13b0eb88145f7dbf487eb..8a9b5c3b121fe762faa9f0252bae8e6a179decee 100644 (file)
@@ -8,3 +8,5 @@ Alternatively, if including items that have minor external dependencies:
 * Possibly add [[plugins/table]].
 
 --[[JoshTriplett]]
+
+[[done]]
diff --git a/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn b/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn
new file mode 100644 (file)
index 0000000..b97c81e
--- /dev/null
@@ -0,0 +1,79 @@
+I need to display part of my pages' path in the `<title>` meta HTML
+header instead of their basename ; e.g. for /abs/path/to/basename, I'd
+like to set it to path/to/basename.
+
+Of course, one might consider it's my own problem, as I could
+workaround this in my templates, and replace, in the `<title>` meta
+HTML header, `<TMPL_VAR TITLE>` with a `TMPL_LOOP` on `PARENTLINKS`,
+but...
+
+- it's ugly (call it a semantic hijacking if you want) ; a side-effect
+  of this ugliness is :
+- it defeats any further plugin's (e.g. [[plugins/meta]])
+  attempt to override the default title with a nicer one ;
+- all parents appear : there is no way to specify how deep to go up in
+  the parents tree.
+
+So I really want to avoid this ugly workaround.
+
+Looking at `Render.pm`, the second solution I thought of was :
+
+- add a `parents_in_page_title` configuration option (default=0, i.e.
+  the current behaviour) ;
+- modify `Render.pm` to insert as much parents as possible (up to
+  `N=parents_in_page_title`), separated by '/', in the `title`
+  template parameter, before the actual page basename ; I personally
+  would use N=2.
+
+The only problems I can see with this approach are :
+
+- it requires modification of the core, which may not be desirable
+- the resulting title would be unconditionally overridden by the meta
+  plugin, and I can think of no clean solution to make this
+  configurable without hacking [[plugins/meta]], which I'd rather not
+  to ; I don't care, but once you add a ad-hoc feature to the core,
+  you can be sure someone will want a more generic version in less than
+  three months ;)
+
+I'm not too convinced writing a plugin for such a small feature isn't
+overdoing it, so I'm tempted to implement this solution in the
+simplest way : the generated title would be the default and could be
+overridden later by plugins.
+
+Joey, what do you think ?
+
+(Before starting to write any single line of code, I need to know how
+much you are on the "if you can do it as a plugin, don't ever modify
+the core" side... :)
+
+> My general philosophy is that the core should be flexible enough to allow
+> plugins to do arbitrary useful stuff. And there are some things in-core
+> that I'd like to get out (such as backlinks processing), but that cannot
+> currently be moved out efficiently. KISS is also part of my pholisophy.
+>
+> So no, I don't like adding new options to the core that few users will
+> want to use.
+
+In case you're on the hardcore side, I would probably write
+a dedicated plugin, called `genealogictitle` or whatever, and :
+
+- use the pagetemplate hook to modify the `title` template parameter,
+  and maybe set `title_overridden`, as does the meta plugin
+- add a `genealogictitle_depth` configuration option to tell how many
+  parents to display
+- maybe add a `genealogictitle_overrides_meta` or whatever to decide
+  whether a title overridden by [[plugins/meta]] should be overridden
+  by genealogictitle ; but anyway, I've not found, in the plugins
+  documentation, any hint about the order in which the plugins are
+  called for a given hook, so the "choose the strongest between meta
+  and genealogictitle" thing might just be more complicated... (no,
+  I did not Read The Nice Source, yet).
+
+-- intrigeri
+
+> Plugin sounds reasonable. --[[Joey]]
+
+>> Well, it seems I once more designed a solution before clearly
+>> defining my problem... What I really need is more generic, can be
+>> done as a plugin, and deserves its own [[todo|pedigree_plugin]], so
+>> I'm tagging this one wontfix^W [[done]]. I'm sorry. -- intrigeri
diff --git a/doc/todo/Allow_change_of_wiki_file_types.mdwn b/doc/todo/Allow_change_of_wiki_file_types.mdwn
new file mode 100644 (file)
index 0000000..19574b1
--- /dev/null
@@ -0,0 +1,85 @@
+The new [[plugins/rename]] plugin allows files to be renamed, but doesn't seem to allow changing the page type.  It would be nice if there was a way to change page type through the web interface.
+
+#### Background
+
+I'm currently moving a couple of projects from [Trac](http://trac.edgewall.org/) to Ikiwiki.  I don't want to have to re-do all the wiki formatting at once.  Initially I simply imported all the old wiki pages without suffixes.  This made them appear on the web as raw un-editable text.  I wanted other project members to be able to do the updating to the new markup language, so I then renamed the files to use '.txt' suffixes, and that allows them to be edited.  Unfortunately, there is still no way to convert them to '.mdwn' files on the web.
+
+I was hoping that the [[plugins/rename]] plugin would allow web uses to change the filename suffix, but it doesn't.  This means that the page type can be set on page creation using the web interface, but cannot be changed thereafter using the web interface.  I was thinking the UI would be something like adding the 'Page type' drop-down menu that appears on the creation page to either the edit or rename pages.
+
+#### [[patch]]
+
+    diff --git a/IkiWiki/Plugin/rename.pm b/IkiWiki/Plugin/rename.pm
+    index 527ee88..123b772 100644
+    --- a/IkiWiki/Plugin/rename.pm
+    +++ b/IkiWiki/Plugin/rename.pm
+    @@ -43,7 +43,7 @@ sub check_canrename ($$$$$$$) {
+       
+       # Dest checks can be omitted by passing undef.
+       if (defined $dest) {
+    -          if ($src eq $dest || $srcfile eq $destfile) {
+    +          if ($srcfile eq $destfile) {
+                       error(gettext("no change to the file name was specified"));
+               }
+     
+    @@ -54,7 +54,7 @@ sub check_canrename ($$$$$$$) {
+               }
+     
+               # Must not be a known source file.
+    -          if (exists $pagesources{$dest}) {
+    +          if ($src ne $dest && exists $pagesources{$dest}) {
+                       error(sprintf(gettext("%s already exists"),
+                               htmllink("", "", $dest, noimageinline => 1)));
+               }
+    @@ -97,6 +97,24 @@ sub rename_form ($$$) {
+       $f->field(name => "do", type => "hidden", value => "rename", force => 1);
+       $f->field(name => "page", type => "hidden", value => $page, force => 1);
+       $f->field(name => "new_name", value => IkiWiki::pagetitle($page), size => 60);
+    +  if (!$q->param("attachment")) {
+    +          # insert the standard extensions
+    +          my @page_types;
+    +          if (exists $IkiWiki::hooks{htmlize}) {
+    +                  @page_types=grep { !/^_/ }
+    +                          keys %{$IkiWiki::hooks{htmlize}};
+    +          }
+    +  
+    +          # make sure the current extension is in the list
+    +          my ($ext) = $pagesources{$page}=~/\.([^.]+)$/;
+    +          if (! $IkiWiki::hooks{htmlize}{$ext}) {
+    +                  unshift(@page_types, $ext);
+    +          }
+    +  
+    +          $f->field(name => "type", type => 'select',
+    +                  options => \@page_types,
+    +                  value => $ext, force => 1);
+    +  }
+       $f->field(name => "attachment", type => "hidden");
+     
+       return $f, ["Rename", "Cancel"];
+    @@ -223,12 +241,19 @@ sub sessioncgi ($$) {
+                       my $dest=IkiWiki::possibly_foolish_untaint(IkiWiki::titlepage($q->param("new_name")));
+     
+                       # The extension of dest is the same as src if it's
+    -                  # a page. If it's an extension, the extension is
+    +                  # a page. If it's an attachment, the extension is
+                       # already included.
+                       my $destfile=$dest;
+                       if (! $q->param("attachment")) {
+    -                          my ($ext)=$srcfile=~/(\.[^.]+)$/;
+    -                          $destfile.=$ext;
+    +                          my $type=$q->param('type');
+    +                          if (defined $type && length $type && $IkiWiki::hooks{htmlize}{$type}) {
+    +                                  $type=IkiWiki::possibly_foolish_untaint($type);
+    +                          } else {
+    +                                  my ($ext)=$srcfile=~/\.([^.]+)$/;
+    +                                  $type=$ext;
+    +                          }
+    +                          
+    +                          $destfile.=".".$type;
+                       }
+     
+                       check_canrename($src, $srcfile, $dest, $destfile,
+
+-- [[users/Will]]
+
+Thanks, fixed a few bugs and applied. --[[Joey]]
+[[done]]
diff --git a/doc/todo/Allow_disabling_edit_and_preferences_links.mdwn b/doc/todo/Allow_disabling_edit_and_preferences_links.mdwn
new file mode 100644 (file)
index 0000000..17f45dd
--- /dev/null
@@ -0,0 +1,81 @@
+This patch allows disabling the edit and preferences link in the config file.  It is backwards compatible (so peoples edit and preferences links won't suddenly vanish).
+
+To disable edit or prefs respectively, add the following to the config file:
+
+<pre>
+  'edit' => 0,
+  'prefs' => 0, 
+</pre>
+
+Patch:
+<pre>
+--- /usr/share/perl5/IkiWiki/Render.pm.orig     2008-12-23 16:49:00.000000000 +1300
++++ /usr/share/perl5/IkiWiki/Render.pm  2008-12-23 16:55:40.000000000 +1300
+@@ -80,8 +80,10 @@
+        my $actions=0;
+        if (length $config{cgiurl}) {
+-               $template->param(editurl => cgiurl(do => "edit", page => $page));
+-               $template->param(prefsurl => cgiurl(do => "prefs"));
++               $template->param(editurl => cgiurl(do => "edit", page => $page))
++                       if ! defined $config{edit} || (defined $config{edit} && $config{edit} == 1);
++               $template->param(prefsurl => cgiurl(do => "prefs"))
++                       if ! defined $config{prefs} || (defined $config{prefs} && $config{prefs} == 1);
+                $actions++;
+        }
+
+</pre>
+
+> On irc, you said, "That was to allow the hack to of using wikistatedir to
+> allow me to generate two websites, one with inline editting, the other a
+> static page for public consumption."
+> 
+> The edit and preferences links can already be disabled by editing
+> `page.tmpl`. (Look for PREFSURL and EDITURL).
+> 
+> More to the point though, disabling those links does not disable anyone
+> consticting the urls by hand and logging in and editing a page. So you'd
+> really want to disable the editpage plugin in the setup file for the
+> public, static wiki. Sounds like you might also want to turn off cgi
+> entirely for that build. --[[Joey]] 
+
+>> I want to retain the same page.tmpl for both sites (different templates
+>> will just increase the maintenance hell), so disabling the links in the
+>> config for one public site works better in my case.
+>>
+>> I do have the editpage plugin disabled for the public static wiki, but
+>> the link still appears on the site.  I want to keep the cgi on, so that
+>> the site is still searchable. --[[puck]]
+
+>>> For me, disabling the editpage plugin does make the "Edit" link
+>>> disappear (this is with 3.03) but as far as I can tell, "Preferences"
+>>> is not controlled by any plugin.  It would be nice if it were; I am
+>>> trying to achieve a configuration where the only action supported
+>>> via CGI is blog-style comments.  --[Zack](http://zwol.livejournal.com/)
+
+>>> Like [[puck]], I'd like to keep search available but I want to disable all
+>>> login facitilities and thus disable the "Preferences" link.
+>>>
+>>> After digging a little bit in the source code, my first attempt was to make
+>>> the "Preferences" link appear only if there is `sessioncgi` hooks
+>>> registered.  But this will not work as the [[plugins/inline]] plugin also
+>>> defines it.
+>>>
+>>> Looking for `auth` hooks currently would not work as at least
+>>> [[plugins/passwordauth]] does not register one.
+>>>
+>>> Adding a new `canlogin` hook looks like overkill to me.  [[Joey]], how
+>>> about making registration of the `auth` hook mandatory for all plugins
+>>> making sense of the "Preferences" link? --[[Lunar]]
+
+>>>> Hmm, using the `auth` hook existance does seem like a nice solution.
+>>>> While splitting the preferences code out into its own plugin is
+>>>> easily enough done, it has the minor problem of being yet another
+>>>> file nearly all ikiwikis will have to load, and also, prefs would
+>>>> have to be disabled manually. So I like that using the hook would
+>>>> cause it to auto-disable if nothing uses it. It's a bit ugly that
+>>>> passwordauth doesn't need an auth hook (it could be reorged to
+>>>> use it instead of formbuilder, maybe) and would probably just have an
+>>>> empty one. Thanks for the idea. --[[Joey]]  [[done]]
+
+>>>>> Thanks for implementing it! --[[Lunar]]
diff --git a/doc/todo/Allow_edittemplate_to_set_file_type.mdwn b/doc/todo/Allow_edittemplate_to_set_file_type.mdwn
new file mode 100644 (file)
index 0000000..1b99a4e
--- /dev/null
@@ -0,0 +1,44 @@
+Below is a [[patch]] to [[plugins/edittemplate]] that does a few things:
+
+ * It defaults the type of the file to be created to the same type as the template.
+ * It adds a 'silent' parameter to the directive that stops it from printing out what what registered.
+ * It makes the description of what was registered link to the template page (which gives feedback for typos or allows template creation)
+ * It adds a colon to the standard string correcting the syntax.
+
+[[done]] except for the colon change; it's referring to the template as an
+edittemplate there. --[[Joey]]
+
+----
+
+    diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm
+    index 98308de..c381940 100644
+    --- a/IkiWiki/Plugin/edittemplate.pm
+    +++ b/IkiWiki/Plugin/edittemplate.pm
+    @@ -56,8 +56,14 @@ sub preprocess (@) {
+     
+       $pagestate{$params{page}}{edittemplate}{$params{match}}=$params{template};
+     
+    -  return sprintf(gettext("edittemplate %s registered for %s"),
+    -          $params{template}, $params{match});
+    +  return "" if ($params{silent} && IkiWiki::yesno($params{silent}));
+    +
+    +  my $link=IkiWiki::linkpage($params{template});
+    +  add_depends($params{page}, $link);
+    +  my $linkHTML = htmllink($params{page}, $params{destpage}, $link);
+    +
+    +  return sprintf(gettext("edittemplate: %s registered for %s"),
+    +          $linkHTML, $params{match});
+     }
+     
+     sub formbuilder (@) {
+    @@ -89,6 +95,9 @@ sub formbuilder (@) {
+                                       if (pagespec_match($p, $pagespec, location => $registering_page)) {
+                                               $form->field(name => "editcontent",
+                                                        value => filltemplate($pagestate{$registering_page}{edittemplate}{$pagespec}, $page));
+    +                                          $form->field(name => "type",
+    +                                                   value => pagetype($pagesources{$pagestate{$registering_page}{edittemplate}{$pagespec}}))
+    +                                                          if $pagesources{$pagestate{$registering_page}{edittemplate}{$pagespec}};
+                                               return;
+                                       }
+                               }
+
diff --git a/doc/todo/Allow_filenames_that_are_all_type.mdwn b/doc/todo/Allow_filenames_that_are_all_type.mdwn
new file mode 100644 (file)
index 0000000..bebbcaf
--- /dev/null
@@ -0,0 +1,41 @@
+This is a [[patch]] to allow filenames that are just the type.  The best example of this is wanting to
+pass a `Makefile` through one of the [[todo/syntax_highlighting/]] plugins.  With this patch,
+if the plugin can process files of type `.Makefile` then it will also process `Makefile`.
+
+I put this patch on the [[todo/syntax_highlighting/]] page a while ago, but it seemed to get
+lost because it didn't have its own bug to track it.  Now it does :).  -- [[Will]]
+
+> This changes `pagename()`, but what about `pagetype()`?
+> Many things in ikiwiki check if `pagetype($file)` returns
+> true to see if it's a page, etc. --[[Joey]] 
+
+>> I think this patch is complete.  It does not change `pagename()`, it
+>> changes `pagetype()` (the diff is fairly old - line numbers may have
+>> changed).
+>>
+>> Before this patch, `pagetype()` required a `.` in the page name.  With
+>> this patch it doesn't, as long as the extension is being kept.  This allows
+>> the filename to be all extension.  `pagename()` relies on `pagetype()`
+>> to detect the type.  `pagename()` also removes the extension on some
+>> pages, but this patch only affects pages where the extension isn't
+>> removed.
+>>
+>> So, yeah, I think this patch is complete. :)  -- [[Will]]
+
+>>> Thanks, [[applied|done]], but I added a noextension parameter,
+>>> since having keepextension allow files with no extension didn't make
+>>> sense. Also, made it work for pages in subdirs.. --[[Joey]] 
+
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index 8d728c9..1bd46a9 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -618,6 +618,8 @@ sub pagetype ($) {
+       
+       if ($page =~ /\.([^.]+)$/) {
+               return $1 if exists $hooks{htmlize}{$1};
+    +  } elsif ($hooks{htmlize}{$page}{keepextension}) {
+    +          return $page;
+       }
+       return;
+     }
index 2439cd65faa1929a2dc27727e826c96be1681259..da68b04c261d9ccb714cac1cea8f402c3d2b9b77 100644 (file)
@@ -1,7 +1,7 @@
-[[tag wishlist]]
-[[tag patch]]
+[[!tag wishlist]]
+[[!tag patch]]
 
-In our team internal wiki, we wish to impose a policy that all edits must have a comment. Patch in [[debbug 450620]].
+In our team internal wiki, we wish to impose a policy that all edits must have a comment. Patch in [[!debbug 450620]].
 
 > Good idea! I also hate empty commit comments, but I know that it's also a matter
 > of human mentality. Of course, you can forbid users to commit empty comments,
index c3cd51e042459c37393a42c32f1a45cf883ab861..b504698c495131cef5f594a4e60ad0ede279ccc2 100644 (file)
@@ -6,6 +6,6 @@ This seems somewhat difficult, as ikiwiki would need to maintain a cache of the
 
 [scmbug](http://www.mkgnu.net/?q=scmbug) might help here. --[[JoshTriplett]]
 
-[[tag soc]]
+[[!tag soc]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 180355875282114e595d63fe2b261f6b4627f186..bf8de16cda05ec12ebae9b2de7a42748f865d920 100644 (file)
@@ -1,5 +1,8 @@
 This patch adds function bestdir() which returns best directory from the directory structure. This is in addition to the bestlink() function which is there in IkiWiki.pm 
 
+> Um, what is this for? :-) It would probably be a lot easier to review if it
+> had documentation, and/or a plugin that used it. --[[smcv]]
+
 -------
 
     Index: IkiWiki.pm
@@ -8,9 +11,9 @@ This patch adds function bestdir() which returns best directory from the directo
     +++ IkiWiki.pm  (working copy)
     @@ -391,6 +391,35 @@
             return "";
-     } #}}}
+     }
     
-    +sub bestdir ($$) { #{{{
+    +sub bestdir ($$) {
     +    my $page=shift;
     +       my $link=shift;
     +       my $cwd=$page;
@@ -37,12 +40,12 @@ This patch adds function bestdir() which returns best directory from the directo
     +       }
     +
     +       return "";
-    +} #}}}
+    +}
     +
-     sub isinlinableimage ($) { #{{{
+     sub isinlinableimage ($) {
             my $file=shift;
     
 ---- 
 -[[users/arpitjain]]
 
-[[tag patch]]
+[[!tag patch patch/core]]
diff --git a/doc/todo/Bestdir_along_with_bestlink_in_IkiWiki.pm/discussion.mdwn b/doc/todo/Bestdir_along_with_bestlink_in_IkiWiki.pm/discussion.mdwn
new file mode 100644 (file)
index 0000000..d473bc3
--- /dev/null
@@ -0,0 +1,6 @@
+- Is there some implicit license for patches posted on the wiki?
+  I would like to maybe use this in [[todo/mbox]]  --[[DavidBremner]]
+
+> If it's not clear to me that a patch is a derivative work of ikiwiki, I
+> always ask for a license clarification before adding it to ikiwiki.
+> --[[Joey]]
index 0559078e0116ba95d2dd394bf752e0ae45196394..1a810ad5583cd64ff149ed39863fdd0ea0b5cb75 100644 (file)
@@ -20,7 +20,17 @@ be embedded to the source code repository commit messages.
 > I sorta take your point about bug numbers. It can be a pain to refer to
 > 'using_a_wiki_for_issue_tracking' as a bug name in a place like a
 > changelog.
-> 
+
+>> Would a modified [[plugins/inline]] plugin that allowed new pages, but without a title field, be ok?
+>> When you hit the edit button it just chooses a new number and makes a page with that
+>> name.
+
+>> The only issue I can see with this is if you're using a distributed wiki for
+>> distributed bug tracking.  In that case you're going to have to make sure that you
+>> don't get conflicting bug ids.
+>> Maybe there should be two options - consecutive numbering, and uuid numbering
+>> which uses a random (128 bit, base64 encoded = 22 chars) name. -- [[Will]]
+
 > OTOH, I don't see a need for specially formatted commit messages to be
 > used to close bugs. Instead, if your BTS is kept in an ikiwiki wiki in
 > an RCS along with your project, you can do like I do here, and just edit a
@@ -34,7 +44,18 @@ be embedded to the source code repository commit messages.
 >> look like a wikipage anymore, but rather something like the Debian 
 >> BTS web-interface, but it would still benefit from wikilinks to the 
 >> documentation in the wiki etc.
->>
+
+>>> I think it is useful to look at these things separately:
+>>>
+>>> * Bug numbers: See above.
+>>> * Automatic timestamps on comments: this already exists with the inline directive.
+>>> * Email interface: You can certainly get an rss feed of what changes in the wiki.
+>>> * You didn't mention [[todo/structured_page_data]] but that is, I think, part
+>>>     of what you seem to be saying.
+>>> * [[todo/tracking_bugs_with_dependencies]] is also important.
+>>>
+>>> -- [[Will]]
+
 >> About the commit message interface: I was thinking about a project
 >> architecture where the code is kept in a separate revision control
 >> system branch than the metadata (blog, wiki, BTS). This would IMHO
index 1ab0b2e81eab46d03eae6b12ed0f1453610b5fc7..1ac9e99b836540a41479aa7def9b7512e08e89d4 100644 (file)
@@ -69,4 +69,4 @@ Any thoughts on the best way to proceed?
 --[[JasonBlevins]], March 23, 2008 21:41 EDT
 
 
-[[tag soc]] [[tag wishlist]]
+[[!tag soc]] [[!tag wishlist]]
index 6b5824bd30483a0710d1f3f839906e02fc1e1c42..f01c2f65a16108e3453006b4589b30fd52a6e953 100644 (file)
@@ -2,6 +2,6 @@
 
 In some situations, it makes sense to have the repository in use by ikiwiki reside on a different machine. In that case, one could juggle SSH keys for the `post-update` hook. A better way may be to provide a different `do` parameter handler for the CGI, which would pull new commits to the working clone and refresh the wiki. Then, the remote `post-update` hook could just `wget` that URL. To prevent simple DoS attacks, one might assign a simple password.
 
-[[tag wishlist]]
+[[!tag wishlist]]
 
 > [[done]] via the pinger and pingee plugins --[[Joey]]
index c14d8af4fd4f638db96bcc3e72da578e26dfbaa5..3c65272904277555b0f7c923d2cafe8f67040e3a 100644 (file)
@@ -8,3 +8,7 @@ Original discussion:
 >
 >> No, although the existing svn backend could fairly esily be modified into
 >> a CVS backend, by someone who doesn't mind working with CVS. --[[Joey]]
+>>
+>>> Wouldn't say I don't mind, but I needed it. See [[plugins/contrib/cvs]]. --[[Schmonz]]
+
+[[!tag wishlist]]
index 0210c38c31494db602b1f9f01c02bd91ff657d81..74a4fb1b1c8f4d7dd834197408934d69011a9d6f 100644 (file)
@@ -1,3 +1,5 @@
 It would be nice to specify a minimum length for the change log for web edits, and if it's only required vs. non-required. I realise this is not going to solve the problem of crap log messages, but it helps guard against accidental submissions which one would have logged. Mediawiki/wikipedia has that option, and I find it a useful reminder. --[[madduck]]
 
-[[tag wishlist]]
+> +1 --[[lnussel]]
+
+[[!tag wishlist]]
diff --git a/doc/todo/Default_text_for_new_pages.mdwn b/doc/todo/Default_text_for_new_pages.mdwn
new file mode 100644 (file)
index 0000000..a904f82
--- /dev/null
@@ -0,0 +1,104 @@
+The [[ikiwiki/directive/inline]] directive allows the creation of new pages.
+It would be nice if it was possible to specify default text for the new post.
+For example:
+
+    \[[!inline pages="blog/* and !*/Discussion" postform="yes" newposttemplate="blogtemplate.mdwn"]]
+
+This would allow you to create a new blog post.  When you hit the `Edit` button, the system presents
+you with an edit form as normal, but rather than being empty, it has the text from `blogtemplate.mdwn`.
+
+Inline below is a [[patch]] that implements this:
+
+----
+
+    diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm
+    index bb21ed2..10c985c 100644
+    --- a/IkiWiki/Plugin/editpage.pm
+    +++ b/IkiWiki/Plugin/editpage.pm
+    @@ -60,7 +60,7 @@ sub cgi_editpage ($$) {
+     
+       decode_cgi_utf8($q);
+     
+    -  my @fields=qw(do rcsinfo subpage from page type editcontent comments);
+    +  my @fields=qw(do rcsinfo subpage from page type editcontent comments templatepage);
+       my @buttons=("Save Page", "Preview", "Cancel");
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+    @@ -117,9 +117,20 @@ sub cgi_editpage ($$) {
+       }
+       else {
+               $type=$form->param('type');
+    +          
+    +          my $defaultContent = "";
+    +          my $templatepage = $form->param('templatepage');
+    +          if ($templatepage && $pagesources{$templatepage}) {
+    +                  $defaultContent = readfile(IkiWiki::srcfile($pagesources{$templatepage}));
+    +          }
+    +          
+               if (defined $type && length $type && $hooks{htmlize}{$type}) {
+                       $type=possibly_foolish_untaint($type);
+               }
+    +          elsif ($templatepage && $pagesources{$templatepage}) {
+    +                  # favor the type of the template page
+    +                  $type=pagetype($pagesources{$templatepage});
+    +          }
+               elsif (defined $from && exists $pagesources{$from}) {
+                       # favor the type of linking page
+                       $type=pagetype($pagesources{$from});
+    @@ -129,7 +140,7 @@ sub cgi_editpage ($$) {
+               if (! $form->submitted) {
+                       $form->field(name => "rcsinfo", value => "", force => 1);
+               }
+    -          $form->field(name => "editcontent", validate => '/.+/');
+    +          $form->field(name => "editcontent", value => $defaultContent, force => 0, validate => '/.+/');
+       }
+     
+       $form->field(name => "do", type => 'hidden');
+    diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
+    index 8efef3f..075d7d8 100644
+    --- a/IkiWiki/Plugin/inline.pm
+    +++ b/IkiWiki/Plugin/inline.pm
+    @@ -271,6 +271,7 @@ sub preprocess_inline (@) {
+                       $rootpage=$params{page};
+               }
+               $formtemplate->param(rootpage => $rootpage);
+    +          $formtemplate->param(templatepage => $params{newposttemplate}) if $params{newposttemplate};
+               $formtemplate->param(rssurl => $rssurl) if $feeds && $rss;
+               $formtemplate->param(atomurl => $atomurl) if $feeds && $atom;
+               if (exists $params{postformtext}) {
+    diff --git a/templates/blogpost.tmpl b/templates/blogpost.tmpl
+    index 7eeede6..5c8b34c 100644
+    --- a/templates/blogpost.tmpl
+    +++ b/templates/blogpost.tmpl
+    @@ -8,6 +8,9 @@
+     </TMPL_IF>
+     <input type="hidden" name="do" value="blog" />
+     <input type="hidden" name="from" value="<TMPL_VAR ROOTPAGE>" />
+    +<TMPL_IF NAME="TEMPLATEPAGE">
+    +<input type="hidden" name="templatepage" value="<TMPL_VAR TEMPLATEPAGE>" />
+    +</TMPL_IF>
+     <input type="hidden" name="subpage" value="1" />
+     <TMPL_VAR POSTFORMTEXT>
+     <input name="title" size="40" />
+
+---
+
+Perhaps I'm misunderstanding something, but can't you use already existing
+in-house means instead of this patch; use a procedure as I do in the Hurd wiki?
+<http://www.bddebian.com/~wiki/config_edittemplate/> with one template:
+<http://www.bddebian.com/~wiki/config_edittemplate/regular_page/>.
+-- [[tschwinge]]
+
+> You are entirely correct.  I thought I'd seen it somewhere, but then couldn't
+> find it when I came to use it.  If the patch isn't applied (and I can see arguments
+> on both sides of that debate), then at least a pointer to
+> [[ikiwiki/directive/edittemplate]] should be added to [[ikiwiki/directive/inline]]
+> (and I'd make that change myself, but the edit needs to happen in the underlay,
+> not in the online docs).  -- [[Will]]
+
+>> Go ahead and make the edit, ikiwiki's source is arranged such that edits
+>> on this wiki to files that form the underlay will affect the underlay.
+>> (Clearly I won't be adding duplicate functionality.)
+>> --[[Joey]]
+
+>>> Edit made.  [[done]] -- [[Will]]
index e9b3690d00b785f01308fe3603cafa2b49a56e4e..7e692dcd8ef7027cf71a6257d425defeb8dbf9ca 100644 (file)
@@ -1,4 +1,4 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 A useful item, I think, would be for an option to disable certain pages from being indexed.
 
diff --git a/doc/todo/Feature_parity_with_Trac.mdwn b/doc/todo/Feature_parity_with_Trac.mdwn
new file mode 100644 (file)
index 0000000..b2d9d43
--- /dev/null
@@ -0,0 +1,22 @@
+It would be nice to have feature parity with [Trac](http://trac.edgewall.org/).  Note that it is expected that the
+implementation will be quite different, but IkiWiki should support the same uses.
+
+Features needed:
+
+ * Wiki, duh.
+ * Source code viewing: This can be handled quite well with a [[shortcut|shortcuts]] to an external source viewer, or by putting
+    the source in the wiki itself (see the [[todo/automatic_use_of_syntax_plugin_on_source_code_files]] wishlist item and [[todo/syntax_highlighting]] todo item).
+    * This could be improved with [[todo/source_link]].
+    * Currently the source highlighting is a little problematic, as there can be two source files with the same wikiname.
+       e.g. a `hello-world.c` and `hello-world.h`.  See [[bugs/multiple_pages_with_same_name]]
+       > That bug was fixed before you linked to the page. :-)
+       >> I was the one that fixed it... :) -- [[Will]]
+ * Trac 'Timeline' feature: view history of the RCS - the `recentchanges` button.
+ * Trac 'Roadmap' feature: Which TODOs/bugs are needed for which milestones.  Use the [[plugins/progress]] directive to show percentage complete for each milestone.
+ * Bug tracking: see [[tips/integrated_issue_tracking_with_ikiwiki]] and [[todo/Updated_bug_tracking_example]].
+   * Queries on bug database: e.g. all open bugs that don't depend on an open bug.  See [[todo/tracking_bugs_with_dependencies]] and [[todo/structured_page_data]].
+ * Build Status: Maybe this is just a link to an external (centralised) status board (e.g. [BuildBot](http://buildbot.net/)).
+
+-- [[Will]]
+
+[[!tag wishlist]]
index ebfd437e67b535058ffe35d0cf69f3dbef09798c..f41980333fc19d9b0b773eaddf8f1551df7ac555 100644 (file)
@@ -1,6 +1,8 @@
+[[!template id=gitbranch branch=origin/gallery author="[[arpitjain]]"]]
+
 New Version of gallery is available now. Few more features have been added like support for multiple pages, sorting and resizing of images etc.
 
-SVN repository of plugin is located at http://ned.snow-crash.org:8080/svn/ikiwiki-gallery
+Gallery repo is now available at  <http://github.com/joeyh/ikiwiki/tree/gallery>
 
 --[[arpitjain]]
 
@@ -28,9 +30,9 @@ That's one way to do it, and it has some nice benefits, like being able to edit
 
 --[[Joey]]
 
-[[tag soc]]
+[[!tag soc]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
 
 ----
 
@@ -39,7 +41,7 @@ I have implemented the first version of the Gallery Plugin for Ikiwiki as part o
 Plugin can be downloaded from [here](http://myweb.unomaha.edu/~ajain/gallery.tar). 
 
 It can be used as : <br>
-\[[gallery imagedir="images" thumbnailsize="200x200" cols="3" alt="Can not be displayed" title="My Pictures"]]
+\[[!gallery imagedir="images" thumbnailsize="200x200" cols="3" alt="Can not be displayed" title="My Pictures"]]
 
 where-<br>
 * imagedir  => Directory containing images. It will scan all the files with jpg|png|gif extension from the directory and will put it in the gallery.<br>
@@ -59,7 +61,7 @@ For any feedback or query, feel free to mail me at arpitjain11 [AT] gmail.com
 
 Additional details are available [here](http://myweb.unomaha.edu/~ajain/ikiwikigallery.html).
 
-[[tag patch]]
+[[!tag patch]]
 
 > I'd love to merge this into ikiwiki.
 > 
@@ -73,3 +75,9 @@ Additional details are available [here](http://myweb.unomaha.edu/~ajain/ikiwikig
 > the gallery and put it in a "gallery" branch of my git repository.
 > 
 > --[[Joey]]
+
+----
+
+See also [[/users/smcv/gallery]] for another implementation of the same sort of
+thing. Unfortunately, none of the implementation ideas
+I have there seem quite right either... --[[smcv]]
diff --git a/doc/todo/Give_access_to_more_TMPL__95__VAR_variables_in_templates_inserted_by_the_template_plugin.mdwn b/doc/todo/Give_access_to_more_TMPL__95__VAR_variables_in_templates_inserted_by_the_template_plugin.mdwn
new file mode 100644 (file)
index 0000000..c71250b
--- /dev/null
@@ -0,0 +1,111 @@
+[[!tag wishlist patch]]
+
+# Context
+
+I may have missed a simple way to achieve what I need without
+modifying ikiwiki, so here is the context.
+
+I have a first-level directory (called `bricks`) containing a bunch of
+wiki pages :
+
+    /bricks
+     |
+     |- bla.mdwn
+     |
+     |- bli.mdwn
+     |
+     `- ...
+
+I have two groups of tags called `direction` and `usage`, stored in
+two sub-directories of `$tagbase` :
+
+    /tag
+     |
+     |- direction
+     |    |- d1.mdwn
+     |    |- d2.mdwn
+     |    |- ...
+     |
+     |- usage
+     |    |- u1.mdwn
+     |    |- u2.mdwn
+     |    |- ...
+
+Any page in `/brick` can be tagged with one or more tags from any of
+these tags-groups.
+
+I need to present different views for these wiki pages, so a `/view`
+tree is dedicated to this mission :
+
+    /view
+     |
+     |- dev
+     |   |- d1.mdwn
+     |   |- d2.mdwn
+     |   |-...
+     |
+     |- howto
+         |- u1.mdwn
+         |- u2.mdwn
+         |- ...
+
+... where e.g. `/view/dev/d1` lists a subset (depending on other tags)
+of the pages tagged d1.
+
+My current plan is :
+
+- thanks to the edittemplate plugin, `/view/dev/*` and `/view/howto/*` would contain respectively `\[[!template id=dev_direction]]` and `\[[!template id=howto_usage]]`
+- `/templates/dev_direction.mdwn` and `/templates/howto_usage.mdwn` would use `\[[!map ...]]` directives to build their views
+
+# My issue
+
+Such map directives would look something like the following (more
+complicated, actually, but let's focus on my current issue) :
+
+       \[[!map pages="bricks/* and link(tag/usage/<TMPL_VAR BASENAME>)"]]
+
+Where `BASENAME` value would be, e.g., `u1` or `d2`, depending on the
+page inserting the template. But `BASENAME` does not exist. I found
+that `<TMPL_VAR PAGE>` is replaced with the full path to the page, but
+I did not found how to get the page's basename in a template included
+with a `\[[!template id=...]]` directive.
+
+Any idea ?
+
+I guess it would be possible to provide the templates inserted by the
+template plugin with more `TMPL_VAR` variables, but I don't know ikiwiki
+codebase well, so I don't know how hard it would be.
+
+I sure could write a ad-hoc plugin that would use the pagetemplate
+hook to add a custom `<TMPL_LOOP>` selector I could use in my
+templates, or another one that would use the filter hook to add the
+needed `\[[!map ...]]` where it belongs to, but since ikiwiki's
+preprocessor directives already *almost* do what I need, I'd like to
+avoid the ad-hoc plugin solution.
+
+(Adding a parameter such as `name=d1` in every `/view/dev/d*.mdwn` and
+`/view/howto/u*.mdwn` page is not an option : I want to factorize the
+most possible of these pages.
+
+> The following patch adds a `basename` `TMPL_VAR` variable that can be
+> used in the templates inserted by \[[!template plugin]] :
+
+>        diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm
+>        index a6e34fc..bb9dd8d 100644
+>        --- a/IkiWiki/Plugin/template.pm
+>        +++ b/IkiWiki/Plugin/template.pm
+>        @@ -57,6 +57,8 @@ sub preprocess (@) {
+>                       }
+>               }
+>        
+>        +       $template->param("basename" => (split("/", $params{page}))[-1]);
+>        +       
+>               return IkiWiki::preprocess($params{page}, $params{destpage},
+>                        IkiWiki::filter($params{page}, $params{destpage},
+>                        $template->output));
+>
+> -- intrigeri
+
+> Thanks for taking the trouble to develop a patch. [[done]] --[[Joey]]
+
+>> Thanks :) -- intrigeri
index 39a3522d29751d4c7e06fd89c9923a5fd99543b6..057a88b72e9d016d28bc9298610a9dca845c188f 100644 (file)
@@ -34,9 +34,14 @@ for an example.  You will probably need to strip out the metadata variables I
 >>>[xtermin.us rather than localhost](http://xtermin.us/git/?p=website.git;a=blob;f=plugins/googlesitemap.pm) is 404 now.
 >>> -- weakish
 
+There is a [sitemap XML standard](http://www.sitemaps.org/protocol.php) that ikiwiki needs to generate for. 
 
-According to [Google Webmaster tools](https://www.google.com/webmasters/tools/), my site isn't indexed for weeks at a time. Since I [blog](http://webconverger.org/blog/) every couple of days, that doesn't work. Yes I do have pingurl configured which [Google reader](http://reader.google.com/) does pick up quickly, but **not** the general search results from Google.
+# Google Webmaster tools and RSS
 
-There is a [sitemap XML standard](http://www.sitemaps.org/protocol.php) that ikiwiki needs to generate for. 
+On [Google Webmaster tools](https://www.google.com/webmasters/tools) you can substitute an RSS feed as a sitemap. Do not use Atom as if you have malformed XHTML it will fail to parse and you will get a ERROR message like so:
+
+       We were unable to read your Sitemap. It may contain an entry we are unable to recognize. Please validate your Sitemap before resubmitting.
+
+[Google should grok feeds as sitemaps.](http://www.google.com/support/webmasters/bin/answer.py?answer=34654) Or rather [[plugins/inline]] should be improved to support the [sitemap protocol](http://sitemaps.org/protocol.php) natively.
 
-Update: I've since discovered under [Google Webmaster tools 'Subscriber stats'](https://www.google.com/webmasters/tools/subscriberstats), you can tell Google to treat a feed as a sitemap. Therefore in many cases just submitting your [[ikiwiki/blog/]]'s feed will be enough for Google to start better indexing your ikiwiki site.
+-- [[Hendry]]
diff --git a/doc/todo/Have_xapian_index_pdf__44___openoffice__44___documents.mdwn b/doc/todo/Have_xapian_index_pdf__44___openoffice__44___documents.mdwn
new file mode 100644 (file)
index 0000000..7fbe728
--- /dev/null
@@ -0,0 +1,5 @@
+Xapian supports indexing pdfs, openoffice docs, etc. It would be nice if
+the search plugin would index these documents and optionally allow their
+exclusion.
+
+[[!tag wishlist]]
diff --git a/doc/todo/Improve_display_of_OpenIDs.mdwn b/doc/todo/Improve_display_of_OpenIDs.mdwn
new file mode 100644 (file)
index 0000000..e2ba1d9
--- /dev/null
@@ -0,0 +1,5 @@
+Some OpenIDs seen in the IkiWiki git history are displayed poorly in [[RecentChanges]], including mine :-) (`http://smcv.pseudorandom.co.uk/`, shown as `smcv.pseudorandom [co.uk]`)
+
+My `openid` branch on <http://git.pseudorandom.co.uk/> improves on a couple of cases and adds a regression test. --[[smcv]]
+
+[[!tag patch done]]
index 9f52a724a2954cfab44a49478144563020b87639..69169400968b8b6f4f45847c4ac5871f38fe9146 100644 (file)
@@ -19,7 +19,7 @@ Cheers,
        index 59eabb6..82913ba 100644
        --- a/IkiWiki/Plugin/inline.pm
        +++ b/IkiWiki/Plugin/inline.pm
-       @@ -229,6 +229,7 @@ sub preprocess_inline (@) { #{{{
+       @@ -229,6 +229,7 @@ sub preprocess_inline (@) {
                                                $template->param(content => $content);
                                        }
                                        $template->param(pageurl => urlto(bestlink($params{page}, $page), $params{destpage}));
index 3e596656deb442be89b57aea10f043e8b2a6b51e..98a92dddc345a2de8f35058983f0c5e79b872c0d 100644 (file)
@@ -10,4 +10,6 @@ subpage: `<current>/$tagbase/<tagname>`.
 
 See also: [[bugs/tags_base_dir_not_used_when_creating_new_tags]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
+
+[[done]]
diff --git a/doc/todo/Mailing_list.mdwn b/doc/todo/Mailing_list.mdwn
new file mode 100644 (file)
index 0000000..b6a2074
--- /dev/null
@@ -0,0 +1,20 @@
+Please don't shoot me for asking:
+
+Could we have an ikiwiki mailing list?
+
+Here's an example use case:
+I want to discuss building a feature. Such discussion could happen on the wiki, but I would prefer to---at the least---be able to email ikiwiki developers and ask them to participate in this particular discussion.
+
+Does this sound okay?
+
+---[[JosephTurian]]
+
+[[!tag wishlist]]
+
+> People ask for this from time to time, but I personally prefer not to be
+> on an ikiwiki mailing list, because limiting public ikiwiki discussion to
+> this wiki helps make ikiwiki a better platform for discussion. So some
+> (most?) active ikiwiki people subscribe to recentchanges, or to the
+> todo/bugs/forum feeds, or to some other feed they create on their user page.
+> And there's work on making the discussion pages more structured, on
+> accepting comments sent via mail, etc. --[[Joey]]
diff --git a/doc/todo/Make_example_setup_file_consistent.mdwn b/doc/todo/Make_example_setup_file_consistent.mdwn
new file mode 100644 (file)
index 0000000..54cc34a
--- /dev/null
@@ -0,0 +1,33 @@
+The current example ikiwiki.setup file has a number of options included, but commented out.  This is standard.  Unfortunately there are two standards for the settings of those commented out options:
+
+  - Have the commented out options showing the default setting, or
+  - Have the commented out options showing the most common alternate setting.
+
+Each of these has its advantages.  The first makes it clear what the default setting is.  The second makes it easy to switch the option on -- you just uncomment the option.
+
+My issue with ikiwiki's example setup file is that it doesn't appear to be consistent.  Looking at the 'svn' entries (the first set of rcs entries), we see that
+
+    svnpath => "trunk",
+
+is an example of the first type, but 
+
+    rcs => "svn",
+
+is an example of the second type.
+
+I think things could be improved if a clear decision was made here.  Most of the settings seem to be of the second type.  Perhaps all that is needed is for settings of the first type to grow a comment:
+
+    svnpath => "trunk",        #default
+
+What do others think?
+
+> I agree, and I'll take a patch.
+> 
+> I may not work on it myself, since I have some
+> [[interesting_ideas|online_configuration]] that would let ikiwiki
+> generate a setup file for you, rather than having to keep maintain the
+> current example. 
+> 
+> And.. [[done]].. setup files are now generated with `--dumpsetup`, based on
+> the built-in defaults, and commented options show an example
+> setting, not a default. --[[Joey]]
diff --git a/doc/todo/Move_teximg_latex_preamble_to_config_file.mdwn b/doc/todo/Move_teximg_latex_preamble_to_config_file.mdwn
new file mode 100644 (file)
index 0000000..3cedd5a
--- /dev/null
@@ -0,0 +1,156 @@
+The [[plugins/teximg]] plugin currently has a TODO in the source code to make the preamble configurable.  The included [[patch]] makes this change.
+
+The patch also makes some other changes:
+
+  - The default latex preamble is changed to the international standard `article` class from the European `scrartcl` class.
+  - Removed the non-standard `mhchem` package from the default preamble.
+  - Allow the use of `dvipng` rather than `dvips` and `convert` (`convert` is not a standard part of a latex install).  This is configurable.
+
+-- [[Will]]
+
+> I like making this configurable. I do fear that changing what's included
+> by default could break some existing uses of teximg? That needs to be
+> considered, and either the breakage documented in NEWS, or avoided. Also,
+> if mchem is dropped, I think the suggests on texlive-science in
+> debian/control should probably go? --[[Joey]]
+
+>> Yes, changing the defaults could break some existing uses.  I think in
+>> this case, documenting in NEWS and dropping texlive-science is the
+>> best option.  In fact, NEWS should probably document the config
+>> setting to return things to how they were.
+>>
+>> The reason I prefer dropping `mchem` rather than keeping it is that `mchem`
+>> is non-standard.  Now that things are configurable and it is easy to
+>> add in if you want it, having only standard packages by default is a
+>> good thing.  Here is a proposed NEWS entry:
+
+File: TexImg standard preamble changed
+
+The [[plugins/teximg]] [[plugin]] now has a configurable LaTeX preamble.
+As part of this change the `mchem` LaTeX package has been removed from
+the default LaTeX preamble as it wasn't included in many TeX installations.
+
+The previous behaviour can be restored by adding the following to your ikiwiki setup:
+
+       teximg_prefix => '\documentclass{scrartcl}
+               \usepackage[version=3]{mhchem}
+               \usepackage{amsmath}
+               \usepackage{amsfonts}
+               \usepackage{amssymb}
+               \pagestyle{empty}
+               \begin{document}',
+
+In addition, the rendering mechanism has been changed to use `dvipng` by default.
+If you would like to return to the old rendering mechanism using `dvips` and `convert`
+then you should add the following line to your ikiwiki setup:
+
+       teximg_dvipng => 0,
+
+The LaTeX postfix is unchanged, but is also now configurable using `teximg_postfix`.
+Happy TeXing.
+
+>> I think that about covers it.  -- [[Will]]
+
+    diff --git a/IkiWiki/Plugin/teximg.pm b/IkiWiki/Plugin/teximg.pm
+    index 369c108..8c3379f 100644
+    --- a/IkiWiki/Plugin/teximg.pm
+    +++ b/IkiWiki/Plugin/teximg.pm
+    @@ -10,6 +10,18 @@ use File::Temp qw(tempdir);
+     use HTML::Entities;
+     use IkiWiki 2.00;
+     
+    +my $default_prefix = <<EOPREFIX
+    +\\documentclass{article}
+    +\\usepackage{amsmath}
+    +\\usepackage{amsfonts}
+    +\\usepackage{amssymb}
+    +\\pagestyle{empty}
+    +\\begin{document}
+    +EOPREFIX
+    +;
+    +
+    +my $default_postfix = '\\end{document}';
+    +
+     sub import {
+       hook(type => "getsetup", id => "teximg", call => \&getsetup);
+       hook(type => "preprocess", id => "teximg", call => \&preprocess);
+    @@ -21,6 +33,26 @@ sub getsetup () {
+                       safe => 1,
+                       rebuild => undef,
+               },
+    +          teximg_dvipng => {
+    +                  type => "boolean",
+    +                  description => "Should teximg use dvipng to render, or dvips and convert?",
+    +                  safe => 0,
+    +                  rebuild => 0,
+    +          },
+    +          teximg_prefix => {
+    +                  type => "string",
+    +                  example => $default_prefix,
+    +                  description => "LaTeX prefix for teximg plugin",
+    +                  safe => 0, # Not sure how secure LaTeX is...
+    +                  rebuild => 1,
+    +          },
+    +          teximg_postfix => {
+    +                  type => "string",
+    +                  example => $default_postfix,
+    +                  description => "LaTeX postfix for teximg plugin",
+    +                  safe => 0, # Not sure how secure LaTeX is...
+    +                  rebuild => 1,
+    +          },
+     }
+     
+     sub preprocess (@) {
+    @@ -105,25 +137,35 @@ sub gen_image ($$$$) {
+       my $digest = shift;
+       my $imagedir = shift;
+     
+    -  #TODO This should move into the setup file.
+    -  my $tex = '\documentclass['.$height.'pt]{scrartcl}';
+    -  $tex .= '\usepackage[version=3]{mhchem}';
+    -  $tex .= '\usepackage{amsmath}';
+    -  $tex .= '\usepackage{amsfonts}';
+    -  $tex .= '\usepackage{amssymb}';
+    -  $tex .= '\pagestyle{empty}';
+    -  $tex .= '\begin{document}';
+    +  if (!defined $config{teximg_prefix}) {
+    +          $config{teximg_prefix} = $default_prefix;
+    +  }
+    +  if (!defined $config{teximg_postfix}) {
+    +          $config{teximg_postfix} = $default_postfix;
+    +  }
+    +  if (!defined $config{teximg_dvipng}) {
+    +          # TODO: Can we detect whether dvipng or convert is in the path?
+    +          $config{teximg_dvipng} = 1;
+    +  }
+    +  
+    +  my $tex = $config{teximg_prefix};
+       $tex .= '$$'.$code.'$$';
+    -  $tex .= '\end{document}';
+    +  $tex .= $config{teximg_postfix};
+    +  $tex =~ s!\\documentclass{article}!\\documentclass[${height}pt]{article}!g;
+    +  $tex =~ s!\\documentclass{scrartcl}!\\documentclass[${height}pt]{scrartcl}!g;
+     
+       my $tmp = eval { create_tmp_dir($digest) };
+       if (! $@ &&
+    -      writefile("$digest.tex", $tmp, $tex) &&
+    -      system("cd $tmp; latex --interaction=nonstopmode $tmp/$digest.tex > /dev/null") == 0 &&
+    -      system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
+    -      # ensure destination directory exists
+    -      writefile("$imagedir/$digest.png", $config{destdir}, "") &&
+    -      system("convert -density 120  -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0) {
+    +          writefile("$digest.tex", $tmp, $tex) &&
+    +          system("cd $tmp; latex --interaction=nonstopmode $tmp/$digest.tex > /dev/null") == 0 &&
+    +          # ensure destination directory exists
+    +          writefile("$imagedir/$digest.png", $config{destdir}, "") &&
+    +          (($config{teximg_dvipng} &&
+    +                  system("dvipng -D 120 -bg Transparent -T tight -o $config{destdir}/$imagedir/$digest.png $tmp/$digest.dvi > $tmp/$digest.log") == 0
+    +                  ) || 
+    +          (!$config{teximg_dvipng} &&
+    +                  system("dvips -E $tmp/$digest.dvi -o $tmp/$digest.ps 2> $tmp/$digest.log") == 0 &&
+    +                  system("convert -density 120  -trim -transparent \"#FFFFFF\" $tmp/$digest.ps $config{destdir}/$imagedir/$digest.png > $tmp/$digest.log") == 0))) {
+               return 1;
+       }
+       else {
+
+[[done]]
index 2e0603ca77bf4551f18785f3b9ccddaa21a89149..387e4fb82be1b7388cedaf630ee3047c87d6be2c 100644 (file)
@@ -10,6 +10,8 @@ Thanks again to [Joey](http://kitenet.net/~joey) for putting ikiwiki together.
 
 *[Kyle](http://kitenet.net/~kyle/)=*
 
+> Took a bit too long, but [[done]] now. --[[Joey]]
+
 ----
 
 The MediaWiki moving/renaming mechanism is pretty nice.  It's easy to get a list of pages that point to the current page.  When renaming a page it sticks a forwarding page in the original place.  The larger the size of the wiki the more important organization tools become.
@@ -30,286 +32,191 @@ Brad
 >
 > This could also be implemented using a combination of raw inline and meta
 > to change the title (add a "redirected from etc." page. This could be done
-> with a plugin. A redirect page would be [[redirect page="newpage"]].
+> with a plugin. A redirect page would be [[!redirect page="newpage"]].
 > But then if you click "edit" on this redirect page, you won't be able
 > to edit the new page, only the call to redirect.
 > --Ethan
 
 -----
 
-[[tag patch]]
-
-This is my second cut at a feature like that requested here.
-It can also be found [here](http://ikidev.betacantrips.com/patches/move.patch).
-
-A few shortcomings exist: 
-
-* No precautions whatsoever are made to protect against race conditions or failures
-  in the rcs\_move function. I didn't even do the `cgi_editpage` thing where I hold
-  the lock and render afterwards (mostly because the copy I was editing was not
-  up-to-date enough to have that code). Although FAILED_SAVE is in movepage.tmpl,
-  no code activates it yet.
-* Some code is duplicated between cgi\_movepage and cgi\_editpage, as well
-  as rcs\_commit and rcs\_move.
-* The user interface is pretty lame. I couldn't figure out a good way to let
-  the user specify which directory to move things to without implementing a
-  FileChooser thing.
-* No redirect pages like those mentioned on [[todo/Moving_Pages]] exist yet, 
-  so none are created.
-* I added a Move link to page.tmpl but it may belong better someplace else --
-  maybe editpage.tmpl? Not sure.
-* from is redundant with page so far -- but since the Move links could someday
-  come from someplace other than the page itself I kept it around.
-* If I move foo.mdwn to bar.mdwn, foo/* should move too, probably.
-
-> Looks like a good start, although I agree about many of the points above,
-> and also feel that something needs to be done about rcses that don't
-> implement a move operation -- falling back to an add and delete.
-> --[[Joey]]
-
-Hmm. Shouldn't that be done on a by-RCS basis, though? (i.e. implemented
-by backends in the `rcs_move` function)
-
-> Probably, yes, but maybe there's a way to avoid duplicating code for that
-> in several of them.
-
-Also, how should ikiwiki react if a page is edited (say, by another user)
-before it is moved? Bail, or shrug and proceed?
-
-> The important thing is to keep in mind that the page could be edited,
-> moved, deleted, etc in between the user starting the move and the move
-> happening. So, the code really needs to deal with all of these cases in
-> some way. It seems fine to me to go ahead with the move even if the page
-> was edited. If the page was deleted or moved, it seems reasonable to exit
-> with an error.
-
-    diff -urNX ignorepats ikiwiki/IkiWiki/CGI.pm ikidev/IkiWiki/CGI.pm
-    --- ikiwiki/IkiWiki/CGI.pm  2007-02-14 18:17:12.000000000 -0800
-    +++ ikidev/IkiWiki/CGI.pm   2007-02-22 18:54:23.194982000 -0800
-    @@ -561,6 +561,106 @@
-        }
-     } #}}}
-
-    +sub cgi_movepage($$) {
-    +   my $q = shift;
-    +   my $session = shift;
-    +   eval q{use CGI::FormBuilder};
-    +   error($@) if $@;
-    +   my @fields=qw(do from rcsinfo page newdir newname comments);
-    +   my @buttons=("Rename Page", "Cancel");
-    +
-    +   my $form = CGI::FormBuilder->new(
-    +           fields => \@fields,
-    +                header => 1,
-    +                charset => "utf-8",
-    +                method => 'POST',
-    +           action => $config{cgiurl},
-    +                template => (-e "$config{templatedir}/movepage.tmpl" ?
-    +                        {template_params("movepage.tmpl")} : ""),
-    +   );
-    +   run_hooks(formbuilder_setup => sub {
-    +           shift->(form => $form, cgi => $q, session => $session);
-    +   });
-    +
-    +   decode_form_utf8($form);
-    +
-    +   # This untaint is safe because if the page doesn't exist, bail.
-    +   my $page = $form->field('page');
-    +   $page = possibly_foolish_untaint($page);
-    +   if (! exists $pagesources{$page}) {
-    +           error("page does not exist");
-    +   }
-    +   my $file=$pagesources{$page};
-    +   my $type=pagetype($file);
-    +
-    +   my $from;
-    +   if (defined $form->field('from')) {
-    +           ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
-    +   }
-    +
-    +   $form->field(name => "do", type => 'hidden');
-    +   $form->field(name => "from", type => 'hidden');
-    +   $form->field(name => "rcsinfo", type => 'hidden');
-    +   $form->field(name => "newdir", type => 'text', size => 80);
-    +   $form->field(name => "page", value => $page, force => 1);
-    +   $form->field(name => "newname", type => "text", size => 80);
-    +   $form->field(name => "comments", type => "text", size => 80);
-    +   $form->tmpl_param("can_commit", $config{rcs});
-    +   $form->tmpl_param("indexlink", indexlink());
-    +   $form->tmpl_param("baseurl", baseurl());
-    +
-    +   if (! $form->submitted) {
-    +           $form->field(name => "rcsinfo", value => rcs_prepedit($file),
-    +                        force => 1);
-    +   }
-    +
-    +   if ($form->submitted eq "Cancel") {
-    +           redirect($q, "$config{url}/".htmlpage($page));
-    +           return;
-    +   }
-    +
-    +   if (! $form->submitted || ! $form->validate) {
-    +           check_canedit($page, $q, $session);
-    +           $form->tmpl_param("page_select", 0);
-    +           $form->field(name => "page", type => 'hidden');
-    +           $form->field(name => "type", type => 'hidden');
-    +           $form->title(sprintf(gettext("moving %s"), pagetitle($page)));
-    +           my $pname = basename($page);
-    +           my $dname = dirname($page);
-    +           if (! defined $form->field('newname') ||
-    +               ! length $form->field('newname')) {
-    +                   $form->field(name => "newname",
-    +                                value => pagetitle($pname, 1), force => 1);
-    +           }
-    +           if (! defined $form->field('newdir') ||
-    +               ! length $form->field('newdir')) {
-    +                   $form->field(name => "newdir",
-    +                                value => pagetitle($dname, 1), force => 1);
-    +           }
-    +           print $form->render(submit => \@buttons);
-    +   }
-    +   else{
-    +           # This untaint is safe because titlepage removes any problematic
-    +           # characters.
-    +           my ($newname)=$form->field('newname');
-    +           $newname=titlepage(possibly_foolish_untaint($newname));
-    +           my ($newdir)=$form->field('newdir');
-    +           $newdir=titlepage(possibly_foolish_untaint($newdir));
-    +           if (! defined $newname || ! length $newname || file_pruned($newname, $config{srcdir}) || $newname=~/^\//) {
-    +                   error("bad page name");
-    +           }
-    +           check_canedit($page, $q, $session);
-    +
-    +           my $newpage = ($newdir?"$newdir/":"") . $newname;
-    +           my $newfile = $newpage . ".$type";
-    +           my $message = $form->field('comments');
-    +           unlockwiki();
-    +           rcs_move($file, $newfile, $message, $form->field("rcsinfo"),
-    +                    $session->param("name"), $ENV{REMOTE_ADDR});
-    +           redirect($q, "$config{url}/".htmlpage($newpage));
-    +   }
-    +}
-    +
-     sub cgi_getsession ($) { #{{{
-        my $q=shift;
-
-    @@ -656,6 +756,9 @@
-        elsif (defined $session->param("postsignin")) {
-                cgi_postsignin($q, $session);
-        }
-    +   elsif ($do eq 'move') {
-    +           cgi_movepage($q, $session);
-    +   }
-        elsif ($do eq 'prefs') {
-                cgi_prefs($q, $session);
-        }
-    diff -urNX ignorepats ikiwiki/IkiWiki/Rcs/svn.pm ikidev/IkiWiki/Rcs/svn.pm
-    --- ikiwiki/IkiWiki/Rcs/svn.pm      2007-01-27 16:04:48.000000000 -0800
-    +++ ikidev/IkiWiki/Rcs/svn.pm       2007-02-22 01:51:29.923626000 -0800
-    @@ -60,6 +60,34 @@
-        }
-     } #}}}
-
-    +sub rcs_move ($$$$;$$) {
-    +   my $file=shift;
-    +   my $newname=shift;
-    +   my $message=shift;
-    +   my $rcstoken=shift;
-    +   my $user=shift;
-    +   my $ipaddr=shift;
-    +   if (defined $user) {
-    +           $message="web commit by $user".(length $message ? ": $message" : "");
-    +   }
-    +   elsif (defined $ipaddr) {
-    +           $message="web commit from $ipaddr".(length $message ? ": $message" : "");
-    +   }
-    +
-    +   chdir($config{srcdir}); # svn merge wants to be here
-    +
-    +   if (system("svn", "move", "--quiet",
-    +              "$file", "$newname") != 0) {
-    +           return 1;
-    +   }
-    +   if (system("svn", "commit", "--quiet",
-    +              "--encoding", "UTF-8", "-m",
-    +              possibly_foolish_untaint($message)) != 0) {
-    +           return 1;
-    +   }
-    +   return undef # success
-    +}
-    +
-     sub rcs_commit ($$$;$$) { #{{{
-        # Tries to commit the page; returns undef on _success_ and
-        # a version of the page with the rcs's conflict markers on failure.
-    diff -urNX ignorepats ikiwiki/IkiWiki/Render.pm ikidev/IkiWiki/Render.pm
-    --- ikiwiki/IkiWiki/Render.pm       2007-02-14 17:00:05.000000000 -0800
-    +++ ikidev/IkiWiki/Render.pm        2007-02-22 18:30:00.451755000 -0800
-    @@ -80,6 +80,7 @@
-
-        if (length $config{cgiurl}) {
-                $template->param(editurl => cgiurl(do => "edit", page => $page));
-    +           $template->param(moveurl => cgiurl(do => "move", page => $page));
-                $template->param(prefsurl => cgiurl(do => "prefs"));
-                if ($config{rcs}) {
-                        $template->param(recentchangesurl => cgiurl(do => "recentchanges"));
-    diff -urNX ignorepats ikiwiki/templates/movepage.tmpl ikidev/templates/movepage.tmpl
-    --- ikiwiki/templates/movepage.tmpl 1969-12-31 16:00:00.000000000 -0800
-    +++ ikidev/templates/movepage.tmpl  2007-02-22 18:40:39.751763000 -0800
-    @@ -0,0 +1,44 @@
-    +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-    + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-    +<html>
-    +<head>
-    +<base href="<TMPL_VAR BASEURL>" />
-    +<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    +<title><TMPL_VAR FORM-TITLE></title>
-    +<link rel="stylesheet" href="<TMPL_VAR BASEURL>style.css" type="text/css" />
-    +<link rel="stylesheet" href="<TMPL_VAR BASEURL>local.css" type="text/css" />
-    +<TMPL_IF NAME="FAVICON">
-    +<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
-    +</TMPL_IF>
-    +</head>
-    +<body>
-    +<TMPL_IF NAME="FAILED_SAVE">
-    +<p>
-    +<b>Failed to save your changes.</b>
-    +</p>
-    +<p>
-    +Your changes were not able to be saved to disk. The system gave the error:
-    +<blockquote>
-    +<TMPL_VAR ERROR_MESSAGE>
-    +</blockquote>
-    +Your changes are preserved below, and you can try again to save them.
-    +</p>
-    +</TMPL_IF>
-    +<TMPL_VAR FORM-START>
-    +<div class="header">
-    +<span><TMPL_VAR INDEXLINK>/ <TMPL_VAR FORM-TITLE></span>
-    +</div>
-    +<TMPL_VAR FIELD-DO>
-    +<TMPL_VAR FIELD-FROM>
-    +<TMPL_VAR FIELD-RCSINFO>
-    +<TMPL_VAR FIELD-PAGE>
-    +New location: <TMPL_VAR FIELD-NEWDIR>/ <TMPL_VAR FIELD-NEWNAME>
-    +<br />
-    +<TMPL_IF NAME="CAN_COMMIT">
-    +Optional comment about this change:<br />
-    +<TMPL_VAR FIELD-COMMENTS><br />
-    +</TMPL_IF>
-    +<input id="_submit" name="_submit" type="submit" value="Rename Page" /><input id="_submit_2" name="_submit" type="submit" value="Cancel" />
-    +<TMPL_VAR FORM-END>
-    +</body>
-    +</html>
-    diff -urNX ignorepats ikiwiki/templates/page.tmpl ikidev/templates/page.tmpl
-    --- ikiwiki/templates/page.tmpl     2006-12-28 12:27:01.000000000 -0800
-    +++ ikidev/templates/page.tmpl      2007-02-22 01:52:33.078464000 -0800
-    @@ -32,6 +32,9 @@
-     <TMPL_IF NAME="EDITURL">
-     <li><a href="<TMPL_VAR EDITURL>">Edit</a></li>
-     </TMPL_IF>
-    +<TMPL_IF NAME="MOVEURL">
-    +<li><a href="<TMPL_VAR MOVEURL>">Move</a></li>
-    +</TMPL_IF>
-     <TMPL_IF NAME="RECENTCHANGESURL">
-     <li><a href="<TMPL_VAR RECENTCHANGESURL>">RecentChanges</a></li>
-     </TMPL_IF>
+I'm going to try to run through a full analysis and design for moving and
+deleting pages here. I want to make sure all cases are covered. --[[Joey]]
+
+## UI
+
+The UI I envision is to add "Rename" and "Delete" buttons to the file edit
+page. Both next to the Save button, and also at the bottom of the attachment
+management interface.
+
+The attachment(s) to rename or delete would be selected using the check boxes
+and then the button applies to all of them. Deleting multiple attachments
+in one go is fine; renaming multiple attachments in one go is ambiguous,
+and it can just error out if more than one is selected for rename.
+(Alternatively, it could allow moving them all to a different subdirectory.)
+
+The Delete buttons lead to a page to confirm the deletion(s).
+
+The Rename buttons lead to a page with a text edit box for editing the
+page name. The title of the page is edited, not the actual filename.
+
+There will also be a optional comment field, so a commit message can be
+written for the rename/delete.
+
+Note that there's an edge case concerning pages that have a "/" encoded
+as part of their title. There's no way for a title edit box to
+differentiate between that, and a "/" that is instended to refer to a
+subdirectory to move the page to. Consequence is that "/" will always be
+treated literally, as a subdir separator; it will not be possible to use
+this interface to put an encoded "/" in a page's name.
+
+Once a page is renamed, ikiwiki will return to the page edit interface,
+now for the renamed page. Any modifications that the user had made to the
+textarea will be preserved.
+
+Similarly, when an attachment is renamed, or deleted, return to the page
+edit interface (with the attachments displayed).
+
+When a page is deleted, redirect the user to the toplevel index.
+
+Note that this design, particularly the return to the edit interface after
+rename, means that the rename button can *only* be put on the page edit ui.
+It won't be possible to put it on the action bar or somewhere else. (It
+would be possible to code up a different rename button that doesn't do
+that, and use it elsewhere.)
+
+Hmm, unless it saves the edit state and reloads it later, while using a separate
+form. Which seems to solve other problems, so I think is the way to go.
+
+## SubPages
+
+When renaming `foo`, it probably makes sense to also rename
+`foo/Discussion`. Should other SubPages in `foo/` also be renamed? I think
+it's probably simplest to rename all of its SubPages too.
+
+(For values of "simplest" that don't include the pain of dealing with all
+the changed links on subpages.. as well as issues like pagespecs that
+continue to match the old subpages, and cannot reasonably be auto-converted
+to use the new, etc, etc... So still undecided about this.)
+
+When deleting `foo`, I don't think SubPages should be deleted. The
+potential for mistakes and abuse is too large. Deleting Discussion page
+might be a useful exception.
+
+TODO: Currently, subpages are not addressed.
+
+## link fixups
+
+When renaming a page, it's desirable to keep links that point to it
+working. Rather than use redirection pages, I think that all pages that
+link to it should be modified to fix their links.
+
+The rename plugin can add a "rename" hook, which other plugins can use to
+update links &etc. The hook would be passed page content, the old and new
+link names, and would modify the content and return it. At least the link
+plugin should have such a hook.
+
+After calling the "rename" hook, and rendering the wiki, the rename plugin
+can check to see what links remain pointing to the old page. There could
+still be some, for example, CamelCase links probably won't be changed; img
+plugins and others contain logical links to the file, etc. The user can be
+presented with a list of all the pages that still have links to the old
+page, and can manually deal with them.
+
+In some cases, a redirection page will be wanted, to keep long-lived urls
+working. Since the meta plugin supports creating such pages, and since they
+won't always be needed, I think it will be simplest to just leave it up to
+the user to create such a redirection page after renaming a page.
+
+## who can delete/rename what?
+
+The source page must be editable by the user to be deleted/renamed.
+When renaming, the dest page must not already exist, and must be creatable
+by the user, too.
+
+lWhen deleting/renaming attachments, the `allowed_attachments` PageSpec
+is checked too.
+
+## RCS
+
+Three new functions are added to the RCS interface:
+
+* `rcs_remove(file)`
+* `rcs_rename(old, new)`
+* `rcs_commit_staged(message, user, ip)`
+
+See [[rcs_updates_needed_for_rename_and_remove]].
+
+## conflicts
+
+Cases to consider:
+
+* Alice clicks "delete" button for a page; Bob makes a modification;
+  Alice confirms deletion. Ideally in this case, Alice should get an error
+  message that there's a conflict.
+  Update: In my current code, alice's deletion will fail if the file was
+  moved or deleted in the meantime; if the file was modified since alice
+  clicked on the delete button, the modifications will be deleted too. I
+  think this is acceptable.
+* Alice opens edit UI for a page; Bob makes a modification; Alice
+  clicks delete button and confirms deletion. Again here, Alice should get
+  a conflict error. Note that this means that the rcstoken should be
+  recorded when the edit UI is first opened, not when the delete button is
+  hit.
+  Update: Again here, there's no conflict, but the delete succeeds. Again,
+  basically acceptible.
+* Alice and Bob both try to delete a page at the same time. It's fine for
+  the second one to get a message that it no longer exists. Or just to
+  silently fail to delete the deleted page..
+  Update: It will display an error to the second one that the page doesn't
+  exist.
+* Alice deletes a page; Bob had edit window open for it, and saves
+  it afterwards. I think that Bob should win in this case; Alice can always
+  notice the page has been added back, and delete it again.
+  Update: Bob wins.
+* Alice clicks "rename" button for a page; Bob makes a modification;
+  Alice confirms rename. This case seems easy, it should just rename the
+  modified page.
+  Update: it does
+* Alice opens edit UI for a page; Bob makes a modification; Alice
+  clicks rename button and confirms rename. Seems same as previous case.
+  Update: check
+* Alice and Bob both try to rename a page at the same time (to probably
+  different names). Or one tries to delete, and the other to rename. 
+  I think it's acceptible for the second one to get an error message that
+  the page no longer exists.
+  Update: check, that happens
+* Alice renames a page; Bob had edit window open for it, and saves
+  it afterwards, under old name. I think it's acceptible for Bob to succeed
+  in saving it under the old name in this case, though not ideal.
+  Update: Behavior is the same as if Alice renamed the page and Bob created
+  a new page with the old name. Seems acceptable, though could be mildly
+  confusing to Bob (or Alice).
+* Alice starts creating a new page. In the meantime, Bob renames a
+  different page to that name. Alice should get an error message when
+  committing; and it should have conflict markers. Ie, this should work the
+  same as if Bob had edited the new page at the same time as Alice did.
+  Update: That should happen. Haven't tested this case yet to make sure.
+* Bob starts renaming a page. In the meantime, Alice creates a new page
+  with the name he's renaming it to. Here Bob should get a error message
+  that he can't rename the page to an existing name. (A conflict resolution
+  edit would also be ok.)
+  Update: Bob gets an error message.
+* Alice renames (or deletes) a page. In the meantime, Bob is uploading an
+  attachment to it, and finishes after the rename finishes. Is it
+  acceptible for the attachment to be saved under the old name?
+  Update: Meh. It's certianly not ideal; if Bob tries to save the page he
+  uploaded the attachment to, he'll get a message about it having been
+  deleted/renamed, and he can try to figure out what to do... :-/
+* I don't know if this is a conflict, but it is an important case to consider;
+  you need to make sure that there are no security holes.  You dont want
+  someone to be able to rename something to <code>/etc/passwd</code>.
+  I think it would be enough that you cannot rename to a location outside
+  of srcdir, you cannot rename to a location that you wouldn't be able
+  to edit because it is locked, and you cannot rename to an existing page.
+
+  > Well, there are a few more cases (like not renaming to a pruned
+  > filename, and not renaming _from_ a file that is not a known source
+  > file or is locked), but yes, that's essentially it.
+  > 
+  > PS, the first thing I do to any
+  > web form is type /etc/passwd and ../../../../etc/passwd into it. ;-) --[[Joey]]
index b3798599484f487f4fd73da62a784cf277dcec36..2215cc4b438cff50858c61a3147f41e109a63f7d 100644 (file)
@@ -14,8 +14,8 @@ Making this transition would fix two major warts:
 
 * The inability to use spaces in wikilinks or link text
 * The requirement to use a trailing space on a preprocessor directive
-  with no arguments, such as `\[[toc ]]`
+  with no arguments, such as `\[[!toc ]]`
 
 --[[JoshTriplett]]
 
-[[done]] in version 2.21, using the '!'-prefixed syntax. --[[JoshTriplett]]
\ No newline at end of file
+[[done]] in version 2.21, using the '!'-prefixed syntax. --[[JoshTriplett]]
index dda1ff5e9812ef1c9a4c5666fc36fd2257f2f701..f6c0fc0ec6cbe03227985f20e0ac4a6f1bbefc14 100644 (file)
@@ -1,2 +1,19 @@
 Err, is this really fixed in 2.21? I can't find it anywhere in 2.32.3 
 (debian unstable)
+
+-----
+
+I just did a `--dumpsetup` with the current version from the Git repository
+and the default option is
+
+    # use '!'-prefixed preprocessor directives?
+    prefix_directives => 0,
+
+My impression was that this should be enabled by default now.  --[[JasonBlevins]]
+
+> As stated in `debian/NEWS`:
+>> For backward compatibility with existing wikis,
+>> refix_directives currently defaults to false.  In ikiwiki 3.0,
+>> prefix_directives will default to true [...]
+> --[[intrigeri]]
+
index 467a7115a730494d3198d296690e45d5b8f6d19a..e63ded688baf82803b8f18823deb3b9eac3d35f1 100644 (file)
@@ -1,6 +1,6 @@
 [[plugins/search]] could provide [OpenSearch](http://www.opensearch.org/)
 metadata.  Various software supports OpenSearch (see the Wikipedia article on
-[[wikipedia OpenSearch]]); in particular, browsers like Firefox and Iceweasel
+[[!wikipedia OpenSearch]]); in particular, browsers like Firefox and Iceweasel
 will automatically discover an OpenSearch search and offer it in the search
 box.
 
index ff2997bee70e43431b0fd92e0c2ac80c30e457e4..f4023d6dd6cd439bbc1c744b6a86a54854d72652 100644 (file)
@@ -1,4 +1,4 @@
-Currently, the page title (either the name of the page or the title specified with `\[[meta title="..."]]`) shows up in a `<div class="header">`.  I tend to follow the [w3c guideline recommending the use of h1 for the title](http://www.w3.org/QA/Tips/Use_h1_for_Title); for this purpose, how about an option to make the page title an `<h1 class="header">`, and shift the markdown headings down by one (making # an h2, ## an h3, etc; or alternatively making # equivalent to `\[[meta title="..."]]`)?
+Currently, the page title (either the name of the page or the title specified with `\[[!meta title="..."]]`) shows up in a `<div class="header">`.  I tend to follow the [w3c guideline recommending the use of h1 for the title](http://www.w3.org/QA/Tips/Use_h1_for_Title); for this purpose, how about an option to make the page title an `<h1 class="header">`, and shift the markdown headings down by one (making # an h2, ## an h3, etc; or alternatively making # equivalent to `\[[!meta title="..."]]`)?
 
 > The reason I don't use a h1 for the navbar is that while it incorporates
 > the page title, it's not just a page title, it has the links to parent pages.
@@ -6,3 +6,9 @@ Currently, the page title (either the name of the page or the title specified wi
 > way, # is reserved for h1 if you choose to use headers in your page. --[[Joey]]
 
 [[done]]
+
+> For anyone interested, I've written a small plugin called [h1title][] that does the
+> latter, making `#` (only when on the first line) set the page title, removing it from
+> the page body. --[[JasonBlevins]], October 22, 2008
+
+ [h1title]: http://code.jblevins.org/ikiwiki/plugins.git/plain/h1title.pm
index 9d0524f1d93fa043825e3b6f2e7069cb519da6ba..c4f261d033358218d21997c07eceade822f146c1 100644 (file)
@@ -6,4 +6,4 @@ Instead, I wonder whether it would be possible to create an overlay directory su
 
 [[madduck]]: Update: I did try setting `templates` in `ikiwiki.setup` but could not get it to work. Then I found in the code that ikiwiki already checks that dir before the `/usr/share/ikiwiki` one, and tried it again, and now it works... sorry.
 
-Thus [[taglink done]].
\ No newline at end of file
+Thus [[!taglink done]].
\ No newline at end of file
index 7586c060bcd34264902a7d9b329528ab9e7e29f9..36161e8b4d35af2a5ced8a837c94330f24eb811a 100644 (file)
@@ -28,3 +28,40 @@ NicolasLimare
 > sidebar could be done as you describe using .shtml. --[[Joey]]
 
 [[wishlist]]
+
+> I have a plan for a way to avoid unecessary rebuilds caused by the
+> sidebar. The idea is to use wikistate to store what a sidebar renders to.
+> Then in the needsbuild hook, render sidebar(s) and compare with their
+> previous stored rendering. If a sidebar's rendered content has changed,
+> then all pages that display that sidebar need to be forced to be rebuilt.
+> 
+> Also, if there is no previous stored rendering for a sidebar, or
+> if there is a stored rendering for a sidebar page that no longer exists, then
+> the pages need to be rebuilt. (This should deal with the [[bugs/Building_a_sidebar_does_not_regenerate_the_subpages]] bug.
+> 
+> This would also save significant time, since the stored sidebar rendering
+> could just be dumped into the page by the pagetemplate hook. Current code
+> re-loads and renders the same sidebar file for every page built!
+> 
+> The sticky part is (relative) links on the sidebar. These would need to
+> be modified somehow depending on the page that the sidebar is placed on,
+> to not break the link.
+> 
+> Another wrinkle is changing subpage links on a sidebar. Suppose a sidebar
+> links to page `foo`. If page `bar/foo` exists, the sidebar on page bar will, 
+> currently, link to that page, in preference to a toplevel `foo`.
+> If `bar/foo` is removed, it will update to link to `foo`. With the new
+> scheme, the stored sidebar rendering is not for page `foo`, and so
+> the change of the `bar/foo` link will not be noticed or acted on.
+> Granted, it's unlikely that anyone relies on the current behavior. You
+> generally want links on a sidebar to link to the same place on every page
+> that displays it. So finding some way to force all links on a sidebar to 
+> be handled absolutely and documenting that would avoid this problem.
+>
+> So, one way to handle both the above problems would be to use the
+> pre-rendered sidebar for each page, but use a html parser to look for
+> links in it, and munge them to work as relative links on the page the
+> sidebar is being added to. Or, if the wiki's url is known, just do this
+> once when rendering the sidebar, adding the full url to the links.
+> (Maybe require `url` be set when using sidebar?)
+> --[[Joey]] 
index 8902f64263408c60f80dd7045e7eec11c03e848b..54a2f98addcc2775399be58fc64a410e18657290 100644 (file)
@@ -22,4 +22,4 @@ new blog post is created, and then the edit link would work fine.
 
 > I would really like for some additional TMP variables to be present in the rss template as well.  For the inline page template, the CTIME TMPL_VAR results in nice phrases like: <q>Posted late Tuesday morning, November 13th, 2007</q>, and it would be neat to let the planet Debian people see that as well :-) Manoj
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 11673a6d8693f7caf5fa739e677ff64e33288c0d..b62a9022b020da65bc5d39c4b63efdf9280b4a8a 100644 (file)
@@ -4,10 +4,16 @@ The configuration setting for Mercurial could be something like this:
 
     rawurl => "http://localhost:8000//raw-file/tip/\[[file]]",
 
-> What I want to do when I want to see if the raw source is either
+> What I do when I want to see if the raw source is either
 > click on the edit link, or click on history and navigate to it in the
 > history browser (easier to do in viewvc than in gitweb, IIRC).
 > Not that I'm opposed to the idea of a plugin that adds a Raw link
 > --[[Joey]]
 
-[[tag wishlist]]
+>> In [[todo/source_link]], Will does this via the CGI instead of delegating
+>> to gitweb/etc. I think Will's patch is a good approach, and have improved
+>> on it a bit in a git branch.
+
+>>> Since that is merged in now, I'm marking this [[done]] --[[Joey]] 
+
+[[!tag wishlist]]
diff --git a/doc/todo/RecentChanges_page_links_without_cgi_wrapper.mdwn b/doc/todo/RecentChanges_page_links_without_cgi_wrapper.mdwn
new file mode 100644 (file)
index 0000000..b371090
--- /dev/null
@@ -0,0 +1,26 @@
+Links to the changed page on RecentChanges only show up if the cgi wrapper is
+enabled. It would be nice if links were also generated on wikis that do not use
+the cgi. [[svend]]
+
+> It would be, but doing so would make updating the recentchanges page for
+> each commit a lot slower, or would result in there often being broken
+> links there.
+> 
+> The broken links would happen if a page is removed.
+> 
+> The speed issue is that currently each individual change in the
+> recentchanges page is built just once, when the change is made, and the
+> html for it is reused thereafter. To avoid broken links, it would need to
+> regenerate each change's html on each commit. That's 100x the overhead.
+> (Perhaps it's possible to be smarter about which need generation tho.)
+> 
+> The best way to approach this that I can see ATM is to use the
+> [[plugins/404]] plugin to handle the broken links and then recentchanges
+> could avoid explicitly using the CGI. But this doesn't meet your use case
+> of having no CGI.
+>
+> If you're willing to live with broken links to removed pages, I suppose
+> that could be made an option..
+> --[[Joey]] 
+
+[[!tag wishlist]]
diff --git a/doc/todo/Separate_OpenIDs_and_usernames.mdwn b/doc/todo/Separate_OpenIDs_and_usernames.mdwn
new file mode 100644 (file)
index 0000000..2cd52e8
--- /dev/null
@@ -0,0 +1,11 @@
+I see OpenID more as an authentication technology than as a human-friendly identifier. It would be cool if, in addition to my identity URL, I could also associate a username with my account. I'd then use the URL to log in, but all changes would be associated with the username I provide. Additionally, I could sign changes with my username, possibly change my identity URL and set a password. It would be nice if I could use my identity URL for authentication convenience and actually be known as nolan or thewordnerd on my wikis, rather than the somewhat less human http://thewordnerd.info. :)
+
+Separating username from identity URL would also let me change the URL later. It would be nice, for instance, if I could assign a username to my account and change the identity to my preferred thewordnerd.info once delegation is supported, without the potential of losing access to my account and contributions. :)
+
+I see this being implemented in one of two possible ways. The easiest seems like it'd involve splitting the fields, doing a simple OpenID verification as is done today, then allow setting of username on the preferences page. When crediting a user for a change, call a function that returns either the username or, if it is null, the identity URL. Then, allow logging into the same account with the username, but only if the password is non-blank. That seems like the most minimal and least invasive way of making the change.
+
+A slightly more complex next step would be to request sreg from the provider and, if provided, automatically set the identity's username and email address from the provided persona. If username login to accounts with blank passwords is disabled, then you have the best of both worlds. Passwordless signin, human-friendly attribution, automatic setting of preferences.
+
+Unfortunately I don't speak Perl, so hopefully someone thinks these suggestions are good enough to code up. I've hacked on openid code in Ruby before, so hopefully these changes aren't all that difficult to implement. Even if you don't get any data via sreg, you're no worse off than where you are now, so I don't think there'd need to be much in the way of error/sanity-checking of returned data. If it's null or not available then no big deal, typing in a username is no sweat.
+
+[[!tag wishlist]]
index 2d14c827d4c075a206deec24667cd136039ccaf3..4bc828e6ee703e1cfc3c933ea72610e91f757210 100644 (file)
@@ -1,4 +1,4 @@
-[[tag patch]]
+[[!tag patch plugins/calendar]]
 
 Here's my next version of the patch - still a work in progress.
 
@@ -6,7 +6,7 @@ It provides the following new features. The features are designed to preserve th
 
  * If you specify an event preprocessor in a post, such as:
 
-    [[event time="2008-06-24"]]
+    [[!event time="2008-06-24"]]
 
  That date will be used instead of the post creation time when displaying the calendar.
 
@@ -42,13 +42,13 @@ Longer term plans:
                 my %cache;
                 my %linkcache;
                @@ -32,6 +34,7 @@
-                sub import { #{{{
+                sub import {
                        hook(type => "needsbuild", id => "version", call => \&needsbuild);
                        hook(type => "preprocess", id => "calendar", call => \&preprocess);
                +       hook(type => "preprocess", id => "event", call => \&preprocess_event);
-                } #}}}
+                }
                 
-                sub is_leap_year (@) { #{{{
+                sub is_leap_year (@) {
                @@ -58,6 +61,7 @@
                        my $nmonth   = $params{nmonth};
                        my $pyear    = $params{pyear};
@@ -137,9 +137,9 @@ Longer term plans:
                        # finish off the week
                @@ -304,6 +333,18 @@
                        return $calendar;
-                } #}}}
+                }
                 
-               +sub preprocess_event (@) { #{{{
+               +sub preprocess_event (@) {
                +       my %params=@_;
                +       # if now time is given, use now
                +       $params{begin} = localtime($time)            unless defined $params{begin};
@@ -151,7 +151,7 @@ Longer term plans:
                +       return "<!-- $params{begin} -->";
                +} #}}
                +
-                sub preprocess (@) { #{{{
+                sub preprocess (@) {
                        my %params=@_;
                        $params{pages} = "*"            unless defined $params{pages};
                @@ -311,6 +352,8 @@
index 05f894dfe13afdbb94c613c0d418857dafb602f3..b9aec91123652a7cad007f49908b5cfaa76e7f56 100644 (file)
@@ -58,9 +58,9 @@ Other alternatives would be
 > I agree that a plugin would probably be more cumbersome, but it is very
 > doable. It might look something like this:
 
-       \[[link bar]]
+       \[[!link bar]]
 
-       \[[link bar=VeryLongPageName]]
+       \[[!link bar=VeryLongPageName]]
 
 >> This is, however, still missing specifying the link text, and adding that option would seem to me to complicate the plugin syntax a lot, unless support is added for the |-syntax for specifying a particular parameter to every plugin.
 
@@ -74,13 +74,13 @@ Other alternatives would be
 >> ... Returning to this, the syntax infact wouldn't be so bad with the |-syntax, given a short name for the plugin:
 
        [[whatever|ref 1]]
-       \[[ref 1=page_with_long_name]]
+       \[[!ref 1=page_with_long_name]]
 
 >>> A way to do this that doesn't need hacking at the preprocessor syntax
 >>> follows: --[[Joey]]
 
-       \[[link bar=1]]
-       \[[dest 1=page_with_long_name]]
+       \[[!link bar=1]]
+       \[[!dest 1=page_with_long_name]]
 
 >>>> But this doesn't work so well for links that aren't valid keys. Such
 >>>> as stuff with spaces in it. I'd like to be able to write any kind of
@@ -88,8 +88,8 @@ Other alternatives would be
 
 >>>>> You're right, and to fix that it could be turned around: --[[Joey]]
 
-       \[[link 1=bar]]
-       \[[dest 1=page_with_long_name]]
+       \[[!link 1=bar]]
+       \[[!dest 1=page_with_long_name]]
 
 >> It also shouldn't be difficult to support non-wiki links in this same
 >> way, so that you could still link everywhere in an uniform manner, as
diff --git a/doc/todo/Silence_monotone_warning.mdwn b/doc/todo/Silence_monotone_warning.mdwn
new file mode 100644 (file)
index 0000000..d875900
--- /dev/null
@@ -0,0 +1,17 @@
+A quick [[patch]] to silence a [[rcs/monotone]] warning I started seeing:
+
+    diff --git a/IkiWiki/Plugin/monotone.pm b/IkiWiki/Plugin/monotone.pm
+    index 4b9be31..9d4e280 100644
+    --- a/IkiWiki/Plugin/monotone.pm
+    +++ b/IkiWiki/Plugin/monotone.pm
+    @@ -55,7 +55,7 @@ sub checkconfig () {
+               error("Monotone version too old, is $version but required 0.38");
+       }
+     
+    -  if (length $config{mtn_wrapper}) {
+    +  if (defined $config{mtn_wrapper} && length $config{mtn_wrapper}) {
+               push @{$config{wrappers}}, {
+                       wrapper => $config{mtn_wrapper},
+                       wrappermode => (defined $config{mtn_wrappermode} ? $config{mtn_wrappermode} : "06755"),
+
+> Thanks, [[done]]
index 998d7f0c2844b35136f93d91a35b0d4ec32b1cdc..4489dd5d201e73c0f4ff199c5fe7730f0299026c 100644 (file)
@@ -21,4 +21,6 @@ that we're at the root of a (sub-)hierarchy.
 > 
 > IMHO, what you really want is [[Moving_pages]]. :-) --[[Joey]]
 
-[[tag wishlist]]
+>> This sounds like WONTFIX to me? --[[smcv]]
+
+[[!tag wishlist done]]
index 3afbc59bc2f3cc6b1f509f83647d80242138475a..f9685be73856c6a556a9cddb734b019bb52d5b81 100644 (file)
@@ -1,6 +1,6 @@
 Perhaps ikiwiki should support XML-RPC-based blogging, using the [standard
 MetaWeblog protocol](http://www.xmlrpc.com/metaWeblogApi).  This would allow
-the use of applets like [[debpkg gnome-blog]] to post to an ikiwiki blog.  The
+the use of applets like [[!debpkg gnome-blog]] to post to an ikiwiki blog.  The
 protocol supports multiple blog names, so one standard URL with page names as
 blog names would work. --[[JoshTriplett]]
 
@@ -9,6 +9,6 @@ blog names would work. --[[JoshTriplett]]
 
 >> I'd love to see support for this and would be happy to contribute towards a bounty (say US$100) :-).  [PmWiki](http://www.pmwiki.org/) has a plugin which [implements this](http://www.pmwiki.org/wiki/Cookbook/XMLRPC) in a way which seems fairly sensible as an end user.  --[[AdamShand]]
 
-[[tag soc]]
+[[!tag soc]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index bed8381bec1d01e1b09d3d017b90db87d99408df..10d94343fc48d6e788bb84da73b1b1cf930091f2 100644 (file)
@@ -1,4 +1,4 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 It'd be nice to be allowed to insert tabs into the textarea, as opposed to
 having to insert 4-spaces for lists/etc.  This would require JavaScript to
index 24f9054f749c683d2f59d48fdcf40fafff707346..8320f72a60812f12a22e8796e6eb6ace85ea56be 100644 (file)
@@ -2,7 +2,7 @@ I don't segregate my blog entries into a directory, but instead want
 my blog to simply consist of all pages that have been tagged. That is,
 I'd like to have my blog page look like this:
 
-       \[[inline pages="link(tag/*)"]]
+       \[[!inline pages="link(tag/*)"]]
 
 That doesn't work in ikiwiki 2.1, but I have it
 [working](http://www.cworth.org/blog) with the following patch:
@@ -20,7 +20,7 @@ That doesn't work in ikiwiki 2.1, but I have it
        index 38aa46a..cd42e8d 100644
        --- a/IkiWiki.pm
        +++ b/IkiWiki.pm
-       @@ -1082,10 +1082,15 @@ sub match_link ($$;@) { #{{{
+       @@ -1082,10 +1082,15 @@ sub match_link ($$;@) {
                my $links = $IkiWiki::links{$page} or return undef;
                return IkiWiki::FailReason->new("$page has no links") unless @$links;
                my $bestlink = IkiWiki::bestlink($from, $link);
@@ -38,7 +38,7 @@ That doesn't work in ikiwiki 2.1, but I have it
        +               }
                }
                return IkiWiki::FailReason->new("$page does not link to $link");
-        } #}}}
+        }
        -- 
        1.5.1.1.g6aead
 
diff --git a/doc/todo/Tags_list_in_page_footer_uses_basename.mdwn b/doc/todo/Tags_list_in_page_footer_uses_basename.mdwn
new file mode 100644 (file)
index 0000000..e2221bb
--- /dev/null
@@ -0,0 +1,8 @@
+Page footers contain a list of links to the page and a list of tags applied to the page.  The link list uses the full path to pages.  However, the tag list contains only the basename of the tag pages.  For instance, if I tag a page with person1/foo and person2/bar, the tag list will just list foo and bar without the necessary disambiguating prefixes.
+
+I think the tag list should always contain the full path to the tag, with the tagbase value removed.
+
+--[[JoshTriplett]]
+
+> What if tagbase is not used? I know this would clutter up the display of
+> my tags on several wikis, including this one. --[[Joey]]
diff --git a/doc/todo/Unit_tests.mdwn b/doc/todo/Unit_tests.mdwn
new file mode 100644 (file)
index 0000000..9c579a6
--- /dev/null
@@ -0,0 +1,10 @@
+Not sure about this TODO, but here it is anyway...
+
+It would be nice to have unit tests for IkiWiki.  This would make sure that we don't break things when adding more functionality.
+
+> mmm unit tests. --[[schmonz]]
+
+>> Ikiwiki has over 500 tests, most of them of the unit test variety. They
+>> are located in the 't' directory and are run by 'make test'. Most of the
+>> core ikiwiki functions are covered. Feel free to contribute more..
+>> --[[Joey]] [[done]]
diff --git a/doc/todo/Untrusted_push_in_Monotone.mdwn b/doc/todo/Untrusted_push_in_Monotone.mdwn
new file mode 100644 (file)
index 0000000..a8b1cd7
--- /dev/null
@@ -0,0 +1,28 @@
+As noted in [[tips/untrusted_git_push]] an untrusted push capability was added recently, but only implemented in git.
+(See also [[todo/rcs_updates_needed]])
+
+This note describes (but does not implement) an approach for this with the [[rcs/monotone]] rcs backend.
+
+----
+
+Monotone behaves a little differently to git in its networking.  Git allows anyone to try to push, and then
+check whether it is ok before finally accepting it.  Monotone has no way to accept or reject revisions
+in this way.  However, monotone does have the ability to mark revisions, and to ignore unmarked revisions.
+
+This marking capability can be used to achieve a somewhat similar effect to what happens with git.  The
+problem with this is that anyone could put anything into the monotone database, and while this wouldn't
+affect ikiwiki, it seems bad to leave open, untrusted storage on the web.
+
+The Plan
+=====
+
+In the `note_netsync_revision_received` hook in the monotone server, have the server check to make sure
+that either a) the revision is signed by someone trusted or, b) the revision is checked using the same
+hook that git uses in `pre-receive`.  If the revision passes the ikiwiki `pre-receive` check then the
+monotone hook signs the revision.  This gives that revision the 'ikiwiki seal of approval'.
+
+You'll also want to update the monotone trust hooks to only trust revisions signed by trusted people, or
+ikiwiki.
+
+Now anyone can upload a revision, but only those signed by a trusted person, or which pass the ikiwiki
+check and so get signed by the ikiwiki key, will be seen by ikiwiki.
diff --git a/doc/todo/Updated_bug_tracking_example.mdwn b/doc/todo/Updated_bug_tracking_example.mdwn
new file mode 100644 (file)
index 0000000..4fbb064
--- /dev/null
@@ -0,0 +1,136 @@
+I've put together an updated bug tracking example.  This example requires some recent
+patches of mine.  It requires [[todo/tracking_bugs_with_dependencies]], 
+[[todo/Allow_edittemplate_to_set_file_type]] and the second [[patch]] in
+[[todo/structured_page_data]] (the data plugin, not the form plugin).
+
+You'll then want to add/replace the following files in the software project example.  The
+heading is the name of the file.  I've commented all the directives.  Oh, and I don't
+have nice CSS for this yet. I did make sure that if I borrowed
+[Trac's](http://trac.edgewall.org/) css then it would display as nicely as theirs - the
+html is there if not the CSS.
+
+It might be worth adding some justification of what is going on here.  The datatable
+and data directives generate a nice tabular form for the structured data.  The HTML
+generated is the same as for Trac, except I've got fewer fields.  Adding more is trivial.
+
+I use data directives rather than links because the data directive allows separating
+dependencies from links.  We can specify 'bugs with all dependencies closed' without
+being confused by other links on the page.
+
+-- [[Will]]
+
+### templates/bug.mdwn
+
+    \[[!datatable class="bugtable" datalist="""
+    [[!data key="Reported by" link=""]]                                        [[!data key="Owned by" link=""]]
+    [[!data key="Depends on"]]
+    """]]
+    
+    ### Description
+    
+    This is a bug that needs solving.
+    
+    #### Steps to reproduce:
+    
+    #### What I expect to happen:
+    
+    #### What actually happens:
+    
+    #### What I have tried to narrow it down:
+    
+### bugs.mdwn
+
+    This is FooBar's bug list. Link bugs to \[[bugs/done]] when done.
+    
+    \[[!inline pages="bugs and ! bugs" feeds=no postform=yes 
+    postformtext="Report a bug:" rootpage="bugs"]]
+    
+    \[[!edittemplate template="templates/bug" match="bugs/* and !*/Discussion" silent=yes]]
+    
+    \[[!toggle id="all bugs" text="Show all bugs"]]
+    
+    \[[!toggle id="open bugs" text="Show open bugs"]]
+    
+    \[[!toggle id="ready bugs" text="Show ready bugs (open bugs with all dependencies closed)"]]
+    
+    \[[!toggleable id="ready bugs" text="""
+    #### Ready Bugs
+    
+    Open bugs with all dependencies closed.
+    
+    [[!inline pages="define(~open, ./bugs/* and !./bugs/done and !link(done) and !*/Discussion)
+    and ~open and !data_link(Depends on,~open)" actions=yes archive=yes show=0]]
+    """]]
+    
+    \[[!toggleable id="open bugs" text="""
+    #### Open Bugs
+    
+    [[!inline pages="./bugs/* and !./bugs/done and !link(done) 
+    and !*/Discussion" actions=yes archive=yes show=0]]
+    """]]
+    
+    \[[!toggleable id="all bugs" text="""
+    #### All Bugs
+    
+    [[!inline pages="./bugs/* and !./bugs/done and !*/Discussion"
+    actions=yes archive=yes show=0]]
+    """]]
+    
+### bugs/needs_more_bugs.mdwn
+
+    \[[!datatable class="bugtable" datalist="""
+    [[!data key="Reported by" link="John"]]                                    [[!data key="Owned by" link="Frank"]]
+    [[!data key="Depends on" link="bugs/fails_to_frobnicate"]]
+    """]]
+    
+    ### Description
+    
+    FooBar does not have enough bugs, which suggests that it's not a real Free
+    Software project. Please help create more bugs by adding code to FooBar!
+    :-)
+    
+    #### Steps to reproduce:
+    
+    Test frobnicate.
+    
+    #### What I expect to happen:
+    
+    It should fail.
+    
+    #### What actually happens:
+    
+    It works.
+    
+    #### What I have tried to narrow it down:
+    
+    I've added some code, but I'm not sure it was the right code.
+
+### bugs/fails_to_frobnicate.mdwn
+
+    \[[!datatable class="bugtable" datalist="""
+    [[!data key="Reported by" link="John"]]                                    [[!data key="Owned by" link="Frank"]]
+    [[!data key="Depends on"]]
+    """]]
+    
+    ### Description
+    
+    FooBar, when used with the `--frob` option, fails to properly frobnicate
+    output.
+    
+    > This is fixed in \[[news/version_1.0]]; marking this bug \[[done]].
+    
+    #### Steps to reproduce:
+    
+    Use FooBar with the `--frob` option.
+    
+    #### What I expect to happen:
+    
+    Lots of frobnication.
+    
+    #### What actually happens:
+    
+    Complete lack of frobnication
+    
+    #### What I have tried to narrow it down:
+    
+    Tested on Linux, MacOS and NetBSD.
index c0311bc92d9f8a7d3e2643e8fc7352f8a91c7dc3..7b4323de177cde72df7daf79d3f61e2bd6349fe4 100644 (file)
@@ -13,12 +13,12 @@ Second, the untainting of $configstring should allow newlines.
     +++ wiki-meta/perl/IkiWiki.pm Mon Jun 11 10:52:07 2007
     @@ -205,7 +205,7 @@
      
-     sub possibly_foolish_untaint ($) { #{{{
+     sub possibly_foolish_untaint ($) {
       my $tainted=shift;
     - my ($untainted)=$tainted=~/(.*)/;
     + my ($untainted)=$tainted=~/(.*)/s;
       return $untainted;
-     } #}}}
+     }
      
     
     Modified: wiki-meta/perl/IkiWiki/Wrapper.pm
index 842c87e2d1decbded0d39782660f45191d82d411..61b19d302f827007446d375b67912a5480252ad3 100644 (file)
@@ -1,4 +1,4 @@
-Here is a patch [[tag patch]] to add a *forward*ing functionality
+Here is a patch [[!tag patch]] to add a *forward*ing functionality
 to the [[`meta`_plugin|plugins/meta]].
 
 > [[done]], with some changes --[[Joey]]
@@ -22,7 +22,7 @@ I can also submit a Git patch, if desired.
 
 **OPT_DELAY** = delay=**D** | empty (*immediatelly*)
 
-\[[meta forward="**WHITHER**" **OPT_DELAY**]]
+\[[!meta forward="**WHITHER**" **OPT_DELAY**]]
 
 
 # Extensions and Ideas
index 09be409ac2ade71b74440945675178c1057a95bc..091e0a39be0560358b0640a60071363ed8dc4d6c 100644 (file)
@@ -38,4 +38,11 @@ well.
 There is a problem though if this navbar were included in a sidebar (the logical place): if a page is updated, the navbar needs to be rebuilt which causes the sidebar to be rebuilt, which causes the whole site to be rebuilt. Unless we can subscribe only to title changes, this will be pretty bad...
 
 --[[madduck]]
+
+> I've just written a plugin for a automatically created menu for use
+> [here](http://www.ff-egersdorf-wachendorf.de/). The source is at
+> [gitorious](http://gitorious.org/ikiwiki-plugins/automenu). The problem with
+> rebuilding remains unsolved but doesn't matter that much for me as I always
+> generate the web site myself, ie it's not really a wiki. --[[lnussel]]
+
 [[!tag wishlist]]
index 4bc3ffc8eb29fed615e46c8d4ceb115e0235c93f..09968382067c73d675fb11dc3458c21dcc05a895 100644 (file)
@@ -1,7 +1,24 @@
 When converting an existing blog to ikiwiki it would be useful to be able to preserve any existing UUIDs on posts, in order to [avoid flooding aggregators](/tips/howto_avoid_flooding_aggregators/).
 
-Also, it should be possible to change the canonical URL of a post, i.e. the atom `<link>` (e.g. leaving a redirector behind) while keeping the same UUID (so that aggregators don't get confused).
+Also, it should be possible to change the permalink (the Atom `<link>`) of a post (e.g. moving the content and leaving a redirector behind), while keeping the same Atom `<id>` (so that aggregators don't get confused).
 
-Ideally UUIDs for [blog posts](/ikiwiki/blog/) should be chosen when the post is created, and frozen permanently by checking them in along with the content.
+Ideally UUIDs for [[blog]] posts should be chosen when the post is created, and frozen permanently by checking them in along with the content.
 
 Perhaps ikiwiki's blogging functionality could be hooked up to the [meta plugin](/meta/plugin/), with a new meta keyword (uuid? feed-uuid? atom-uuid?) to achieve this.
+
+> I've now knocked together a [[patch]], which is in the "force-uuids" branch of git://git.debian.org/git/users/smcv/ikiwiki.git (see also [gitweb](http://git.debian.org/?p=users/smcv/ikiwiki.git;a=shortlog;h=refs/heads/force-uuids)).
+>
+> I'm not convinced that "uuid" is the best name for this functionality - the `<id>` in an Atom feed can be any URI, and one of the use-cases I have for this functionality in my own blog needs to have its `<id>` set to a URI that is not, in fact, its own address (it was a typo). "id" is a bit arrogant (forcing Atom terminology into a flat namespace!), "atom-id" is slightly misleading because it's also used for RSS... any ideas?
+>
+> While I was there, I noticed that the quality of the generated Atom/RSS feeds could be improved by making more use of the meta plugin if it's also enabled - would anyone object to me hacking on this some more?
+>
+> -[smcv](http://smcv.pseudorandom.co.uk/)
+
+> [[merged|done]], thank you!
+> 
+> I chose to use the term guid, since it's both a generic term that fits
+> very well and describes both using a uuid and an url, and also happens
+> to be the term rss uses. ;-)
+> 
+> Of course I'm happy if you can improve the feeds. They do already
+> use some meta information (author, copyright). --[[Joey]]
index 50c2fe16f654c35c6b888d4e8d7fe3e4fa96f63c..a0fe83e44f640b031fc3612bc325cf5a3bcd75ae 100644 (file)
@@ -1,8 +1,8 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 An option to have absolute urls in wikilinks instead of relative ones would be useful, 
 for pages included into other pages out of the wiki rendering process (shtml for example)
-since these pages can be included from a subdir. Ditto, links from \[[ inline ..]] or \[[map ..]].
+since these pages can be included from a subdir. Ditto, links from \[[!inline ..]] or \[[!map ..]].
 
 > You can make a wikilink absolute by prefixing it with a /, see 
 > [[ikiwiki/subpage/linkingrules/]]. Pagespecs match absolute by default. But what do
@@ -10,11 +10,11 @@ since these pages can be included from a subdir. Ditto, links from \[[ inline ..
 > change. --Ethan
 
 >> I want the "last pages" in my sidebar. and some links to a few special pages.
->> \[[inline ]] or \\[[map ]] in the sidebar is a bad idea, (because each update rebuilds
+>> \[[!inline ]] or \\[[!map ]] in the sidebar is a bad idea, (because each update rebuilds
 >> all the wiki), so I use server-side-include instead of the sidebar plugin; 
 >> this reduces the dependencies
 >> my sidebar is generated as http://foo.org/menu/index.html, so all the links generated by 
->> \[[inline ]] or \[[map ]] are relative to this position. 
+>> \[[!inline ]] or \[[!map ]] are relative to this position. 
 >> Included from http://foo.org/section/sub/blah/index.shtml, the links are broken.
 >>
 >> — NicolasLimare
index ea367a197e60328247668b1c2efc18f1369787a4..52031ffc1adfba02ebf62358b825224b933ce88b 100644 (file)
@@ -66,3 +66,5 @@ Tabbing isn't quite the same as a nice shortcut key.  There's always
 Conkeror...
 
 --[[JasonBlevins]], March 22, 2008 10:35 EDT
+
+[[!tag wishlist]]
diff --git a/doc/todo/add_forward_age_sorting_option_to_inline.mdwn b/doc/todo/add_forward_age_sorting_option_to_inline.mdwn
new file mode 100644 (file)
index 0000000..e91c5a4
--- /dev/null
@@ -0,0 +1,34 @@
+The names are a bit backwards, but I guess inverting the sense of age would make people angry :-)
+
+I do not believe copy-and-paste of 3 lines is copyrightable, but in any case feel free to include in ikiwiki under the same terms.
+[[DavidBremner]]
+
+You can already do do sort=age reverse=yes [[done]] --[[Joey]]
+
+<pre>
+From 2fb2b561a678616bb0054a2d7a9d29df11998bc2 Mon Sep 17 00:00:00 2001
+From: David Bremner <bremner@pivot.cs.unb.ca>
+Date: Fri, 29 Aug 2008 15:05:41 -0300
+Subject: [PATCH] add sort='youth' to inline plugin
+
+---
+ IkiWiki/Plugin/inline.pm |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
+index d2e5832..9e52712 100644
+--- a/IkiWiki/Plugin/inline.pm
++++ b/IkiWiki/Plugin/inline.pm
+@@ -194,6 +194,9 @@ sub preprocess_inline (@) {
+        elsif (! exists $params{sort} || $params{sort} eq 'age') {
+                @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+        }
++       elsif (! exists $params{sort} || $params{sort} eq 'youth') {
++               @list=sort { $pagectime{$a} <=> $pagectime{$b} } @list;
++       }
+        else {
+                return sprintf(gettext("unknown sort type %s"), $params{sort});
+        }
+--
+1.5.6.3
+</pre>
index 8ff7f122aac789cea250c46500568ced98a656ee..57ee99eb05238eeba230027824cea9fa0783f1c9 100644 (file)
@@ -25,6 +25,12 @@ rarer thing to want than unconnected top level pages. --[[Joey]]
 > <http://jameswestby.net/scratch/create.diff>
 > -- JamesWestby
 
+> For what it's worth, the following works:  
+> `\[[!inline pages=!* rss=no atom=no postform=yes postformtext="Add a new page titled:"]]`  
+> Add `rootpage=/` if you do this in `index.mdwn` to avoid creating subpages.
+> --[[JeremieKoenig]]
+
+
 Maybe a very simple PHP frontend for serving the
 statically generated pages, that would display a page editing form or
 something like that for non-existent pages, wouldn't be too bad a thing
index 4f7c969464f495719ee0177aa8d87d39589d0af8..125e74e7659e01e1d39c0d58d07a89f4772ee676 100644 (file)
@@ -1,5 +1,5 @@
 The aggregate plugin's handling of http 301 (moved permanently) could be
-improved. Per [[rfc 1945]]:
+improved. Per [[!rfc 1945]]:
 
 > The requested resource has been assigned a new permanent URL
 > and any future references to this resource should be done
index a4164fa253d6955dfee7e0a62c4624c4fcd294e3..272e146f4f4e0d331f0da79bedd1f29951902a4e 100644 (file)
@@ -3,3 +3,57 @@ The new internal page feature is designed for something like
 
 How to transition to it though? inlines of aggregated content would need to
 change their pagespecs to use `internal()`.
+
+> [[patch]] in git://git.debian.org/git/users/smcv/ikiwiki.git, branch "aggregate".
+> Migration is a two-step process: first change all your pagespecs to use `internal()`, then add `internalize="yes"` to all your aggregate invocations. --smcv.pseudorandom.co.uk
+
+> Thanks for working on this.
+> 
+> I see one problem, if internalize is flipped on and there are existing
+> aggregated pages, htmlfn will not return the right filename for those
+> pages when expiring them. Seems that `$was_internal` (or just the full
+> source filename) should be recorded on a per-guid basis. Could you do
+> that?
+> 
+> I'm weighing the added complexity of having an internalize option
+> (which people would have to add, and would probably forget), with just
+> making aggregate create all new pages as internal, and having a flag day
+> where all inlines and other uses of aggregated pages have to change
+> pagespecs to use `isinternal()`.
+> 
+> There are real bugs that are fixed by making
+> aggregated plugins internal, including:
+> - Avoids web edits to aggregated pages. (Arguably a security hole;
+>   though they can be locked..)
+> - Significant speed improvements.
+> - Less disk use.
+> 
+> If internal has to be manually enabled, people will forget to. I'd rather
+> not have to worry about these bugs in the future. So, I'm thinking flag
+> day. --[[Joey]]
+
+> OK, there's a simpler approach in the same repository, branch
+> "aggregateinternal". It just adds an aggregateinternal option
+> for the whole wiki.
+>
+> On a flag day, everyone has to change their inline directives
+> to use `internal()`, after which this option can be switched on.
+> When changing the option, you'll have to clean up the mess from
+> old aggregated pages by hand, and re-aggregate.
+>
+> If this is a direction you prefer, the next step would be to
+> add support for existing wikis setting this option - for instance
+> it could look for non-internal pages that were previously
+> aggregated, and convert them to internal, the first time aggregation
+> runs. --smcv
+
+> Sure, that seems reasonable. Perhaps `ikiwiki-transition` could be used
+> to move the pages, and even, possibly update the pagespecs (not sure how
+> it could figure out which ones tho). --[[Joey]]
+
+> I've patched ikiwiki-transition to have an aggregateinternal mode.
+> See my aggregateinternal branch, again.
+> "ikiwiki-transition aggregateinternal $setupfile" moves the pages around,
+> although it doesn't update the pagespecs (I wouldn't know how...) --[[smcv]]
+
+[[!tag patch done]]
index 6125bc413c1c294ea9b0656de7cd864148570f6f..7f51f79d0db4ce9454b8427172c3b2584e1f53b3 100644 (file)
@@ -1,3 +1,3 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 It would be cool if the CGI could be used to render dynamic pages. For instance, I might want to create a page with a `\[[map]]` according to a [[pagespec]] to be passed in the query string, instead of creating/hardcoding all possible pagespecs I might want to call.
index 9055c8a13e7fd6812ad32e7c2861e85a3d0f7775..61f311b8c5218e5e7247784d39c3fcc3e10a7865 100644 (file)
@@ -8,4 +8,6 @@ From the [apache documentation](http://httpd.apache.org/docs/2.2/custom-error.ht
 
 > Nice idea, I'll try to find time to add a plugin doing this. --[[Joey]]
 
+>> [[done]] some time ago, as the [[plugins/404]] plugin --[[smcv]]
+
 [[wishlist]]
diff --git a/doc/todo/allow_disabling_backlinks.mdwn b/doc/todo/allow_disabling_backlinks.mdwn
new file mode 100644 (file)
index 0000000..5dd4876
--- /dev/null
@@ -0,0 +1,18 @@
+This patch allows disabling the backlinks in the config file by setting nobacklinks to 0.
+
+It is backwards compatible, and by default enables backlinks in the generated pages.
+
+<pre>
+--- IkiWiki/Render.pm.orig2    2009-01-06 14:54:01.000000000 +1300
++++ IkiWiki/Render.pm  2009-01-06 14:55:08.000000000 +1300
+@@ -107,7 +107,8 @@
+               $template->param(have_actions => 1);
+       }
+-      my @backlinks=sort { $a->{page} cmp $b->{page} } backlinks($page);
++      my @backlinks=sort { $a->{page} cmp $b->{page} } backlinks($page)
++              unless defined $config{nobacklinks} && $config{nobacklinks} == 0;
+       my ($backlinks, $more_backlinks);
+       if (@backlinks <= $config{numbacklinks} || ! $config{numbacklinks}) {
+               $backlinks=\@backlinks;
+</pre>
index 8ef8a1533c923b56239be98cba28bf106e7bd7a6..a604182b1b40e3559df83533824014979df8f1ba 100644 (file)
@@ -9,4 +9,4 @@ comment form.
 > I agree that having this as an option is reasonable. Although it would
 > take a fair amount of work. --[[Joey]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
diff --git a/doc/todo/allow_site-wide_meta_definitions.mdwn b/doc/todo/allow_site-wide_meta_definitions.mdwn
new file mode 100644 (file)
index 0000000..70ccc2b
--- /dev/null
@@ -0,0 +1,74 @@
+[[!tag plugins/meta patch]]
+[[!template id=gitbranch branch=jon/defaultmeta author="[[Jon]]"]]
+
+I'd like to define [[plugins/meta]] values to apply across all pages
+site-wide unless the pages define their own: default values for meta
+definitions essentially.
+
+Here's a patch to achieve this (also in the "defaultmeta" branch of
+my github ikiwiki fork):
+
+    diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm
+    index b229592..3132257 100644
+    --- a/IkiWiki/Plugin/meta.pm
+    +++ b/IkiWiki/Plugin/meta.pm
+    @@ -13,6 +13,7 @@ sub import {
+       hook(type => "needsbuild", id => "meta", call => \&needsbuild);
+       hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1);
+       hook(type => "pagetemplate", id => "meta", call => \&pagetemplate);
+    +  hook(type => "scan", id => "meta", call => \&scan);
+     }
+     
+     sub getsetup () {
+    @@ -302,6 +303,15 @@ sub match {
+       }
+     }
+     
+    +sub scan() {
+    +  my %params = @_;
+    +  my $page = $params{page};
+    +    foreach my $type (map { s/^meta_//; $_ } grep /^meta_/, keys %config) {
+    +          $pagestate{$page}{meta}{$type} = $config{"meta_$type"}
+    +                  unless defined $pagestate{$page}{meta}{$type};
+    +  }
+    +}
+    +
+     package IkiWiki::PageSpec;
+     
+     sub match_title ($$;@) {
+    diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn
+    index 000f461..200c4b2 100644
+    --- a/doc/ikiwiki/directive/meta.mdwn
+    +++ b/doc/ikiwiki/directive/meta.mdwn
+    @@ -12,6 +12,12 @@ also specifies some additional sub-parameters.
+     The field values are treated as HTML entity-escaped text, so you can include
+     a quote in the text by writing `&quot;` and so on.
+     
+    +You can also define site-wide defaults for meta values by including them
+    +in your setup file, e.g.
+    +
+    +  meta_copyright => "Copyright 2007 by Joey Hess",
+    +  meta_license   => "GPL v2+",
+    +
+     Supported fields:
+     
+     * title
+
+-- [[Jon]]
+
+> This doesn't support multiple-argument meta directives like
+> `link=x rel=y`, or meta directives with special side-effects like
+> `updated`.
+>
+> The first could be solved (if you care) by a syntax like this:
+>
+>     meta_defaults => [
+>         { copyright => "© me" },
+>         { link => "about:blank", rel => "silly", },
+>     ]
+>
+> The second could perhaps be solved by invoking `meta::preprocess` from within
+> `scan` (which might be a simplification anyway), although this is complicated
+> by the fact that some (but not all!) meta headers are idempotent.
+> 
+> --[[smcv]]
index 7c2994cb9e0b1f88312f07f4aa3b8454be975d7d..b0524be5fcabfba5b66ef671ddebab6eb0645eb4 100644 (file)
@@ -15,3 +15,16 @@ Cheers,
 >> Mh.. well. I know this problem, too. I leave the Discussion sites open for no registrations, so that visitors can easily write a comment to this specific blog entry without the need for registration. (This would be the same behaviour, as many blogging engines are using). Maybe it is possible to wrote a plugin that would scan the text which is submitted via spamassassin or something similar. (Using this combined with known spam URLs would maybe reduce the load of the server if there are many webpages which are getting editted by someone). If you like this idea Joey I might be interested to write such a plugin after my exams this and the next month. :) -- [[Winnie]]
 
 You might look at the Wikipedia page on "Spam\_in\_blogs" for more ideas.  In particular, would it be possible to force a subset of the pages (by regex, but you'd choose the regex to match those pages which are publicly writable) to use rel="nofollow" in all links.
+
+> I just wanted to leave a link here to the [[todo/require_CAPTCHA_to_edit]] plugin patch.  Unfortunately that plugin currently interacts badly with the openid plugin. -- [[Will]]
+
+
+---
+
+Ikiwiki now has a checkcontent hook that plugins can use to see content
+that is being entered and check it for spam/whatever.
+
+There is a blogspam plugin that uses the blogspam.org service
+to check for common spam signatures. --[[Joey]] 
+
+[[done]]
diff --git a/doc/todo/apache_404_ErrorDocument_handler.mdwn b/doc/todo/apache_404_ErrorDocument_handler.mdwn
new file mode 100644 (file)
index 0000000..4ae1d1a
--- /dev/null
@@ -0,0 +1,25 @@
+Apache's ErrorDocument directive lets you write a CGI script that will be invoked for all 404s.
+IkiWiki could offer one as an optional wrapper; it would do much the same thing that the
+existing recentchanges_link (or [[generic___39__do__61__goto__39___for_CGI]]) does when
+encountering a nonexistent page.
+
+I think it'd probably have to be a separate CGI script because the environment with which
+404 handlers are invoked is somewhat odd, and because it needs to return a 404 status
+(having said that, it might make sense for `recentchanges_link` to return 404 rather than
+200 anyway if the page doesn't exist).
+
+> This turns out to be untrue, as long as the wrapper lets a couple of extra
+> environment variables through. --[[smcv]]
+
+This would give IkiWiki the behaviour of many other wikis, where visiting a page that
+does not yet exist prompts you to create it, without having to invoke the CGI for
+successful requests.
+
+Due to [a well-known MSIE misfeature](http://support.microsoft.com/default.aspx?scid=kb;en-us;Q294807),
+error output needs to be at least 512 bytes long, so some padding might also be required.
+
+Implemented in the 'goto' branch in my git repository. You can see this
+feature in action [on my blog](http://smcv.pseudorandom.co.uk/no/such/page/).
+--[[smcv]]
+
+[[done]]
diff --git a/doc/todo/applydiff_plugin.mdwn b/doc/todo/applydiff_plugin.mdwn
new file mode 100644 (file)
index 0000000..d26b0df
--- /dev/null
@@ -0,0 +1,110 @@
+[[!tag wishlist done]]
+
+[[!toc ]]
+
+Summary
+=======
+
+Allow a user to apply an arbitrary diff, in order to modify a given
+page (or, even better, a given set of pages).
+
+Rationale
+=========
+
+To edit intensively an ikiwiki-powered website can quickly get
+annoying for anybody meeting enough of the following conditions:
+
+* living mainly offline
+* having no commit access to the RCS backing up the site (BTW, please
+  note I can send my ssh public key to anyone who asks for, free of
+  charges)
+* hating web-browsers and despising textareas
+* loving in his/her own preferred `$EDITOR`
+
+... and when one gathers all of these defaults, she/he is on her/his
+way to get mad. Soon.
+
+Before it's too late, some dareful ones dream of the following
+playflow:
+
+1. Go online.
+1. Update local working copy.
+1. Go offline.
+1. `$EDITOR` : write, report, answer, propose
+1. Go online.
+1. Update local working copy (and optionally fix conflicts between
+   local changes and remote ones).
+1. Generate a diff.
+1. Use a web-browser to paste the diffs (or better, upload them into
+   a form) somewhere on the wiki, and click "Apply".
+1. git pull (to reflect locally the fact that the diff has been
+   applied to the remote repo)
+1. Go offline.
+
+(This is for sure a bit theoretical: the ones who dream of this would
+actually insert various steps about branching, merging and rebasing
+random stuff.)
+
+Design
+======
+
+This has to be thought very carefully, to avoid one to apply diffs to
+pages he/she is not allowed to edit. Restricting a given diff to
+modify only *one* page may be easier.
+
+Implementation
+==============
+
+Also see [[joey]]'s idea on [[users/xma/discussion]], to allow (filtered) anonymous push to this wiki's repository.
+
+> Ideally the filtering should apply the same constraints on what's pushed
+> as are applied to web edits. So locked pages can't be changed, etc.
+> 
+> That could be accomplished by making the git pre-receive hook be a
+> ikiwiki wrapper. A new `git_receive_wrapper` config setting could cause
+> the wrapper to be generated, with `$config{receive}` set to true.
+> 
+> When run that way, ikiwiki would call `rcs_receive`. In the case of git,
+> that would look at the received changes as fed into the hook on stdin,
+> and use `parse_diff_tree` to get a list of the files changed. Then it
+> could determine if the changes were allowed.
+> 
+> To do that, it should first look at what unix user received the
+> commit.  That could be mapped directly to an ikiwiki user. This would
+> typically be an unprivelidged user (that was set up just to allow
+> anonymous pushes), but you might also want to set up
+> separate users who have fewer limits on what they can push. And, of
+> course, pushes from the main user, who owns the wiki, would not be
+> checked at all. So, let's say `$config{usermap}` is a hash, something
+> like `{usera => "wikiusera", userb => "wikiuserb"}`, and pushes from
+> users not in the hash are not checked.
+> 
+> Then it seems like it would want to call `check_canedit` to test if an
+> edit to each changed page is allowed. Might also want to call
+> `check_canattach` and `check_canremove` if the attach and remove plugins
+> are enabled. All three expect to be passed a CGI and a CGI::Session
+> object, which is a bit problimatic here. So dummy the objects up? (To call
+> `check_canattach` the changed attachment would need to be extracted to a
+> temp file for it to check..)
+> 
+> If a change is disallowed, it would print out what was disallowed, and
+> exit nonzero. I think that git then discards the pushed objects (or maybe
+> they remain in the database until `git-gc` .. if so, that could be used
+> to DOS by uploading junk, so need to check this point).
+> 
+> Also, I've not verified that the objects have been recieved already when
+> whe pre-receive hook is called. Although the docs seem to say that is the
+> case. --[[Joey]]
+
+>> Update: The git pre-receive hook stuff is written, and seems to work.
+>> I think it makes more sense than using diffs, and so think this todo
+>> could probably be closed.
+>> --[[Joey]]
+
+>>> I agree, closing this. I really prefer this solution to the one I was
+>>> initially proposing.
+>>> Is this pre-receive hook already enabled on ikiwiki.info?
+>>> If not, do you plan to enable it at some point?
+>>> --[[intrigeri]]
+
+>>>> [[news/git_push_to_this_wiki]] gave me the answer. Well done! --[[intrigeri]]
index 430817d3f191ee0f62a29d7b86a87d549c6ab016..600c6cf7be58c043361d2d62c22222b9b07986e2 100644 (file)
@@ -11,4 +11,12 @@ nice to add:
   srcdir. This would allow the admin to review them, and manually
   add/delete them before they bloat history.
 
-[[tag wishlist]]
+> I'd be inclined to implement that one by writing them to a nominated
+> underlay, I think, rather than having them in the srcdir but not in
+> the VCS. My [[plugins/contrib/album]] plugin could benefit from this
+> functionality, although in that case the photos should probably just
+> stay in the underlay forever (I already use an underlay on my own
+> websites for photos and software releases, which are too big to want
+> them in the VCS permanently.) --[[smcv]]
+
+[[!tag wishlist]]
index fac450a2229a5bebc31cc24f9b4977132f3fdc94..f1d33114ff7518b6e0eab6af2601cbfa8930da99 100644 (file)
@@ -1,9 +1,125 @@
-It would be great if I could tell ikiwiki to automatically instantiate pages for each tag, according to a template, especially when `$tagbase` is set.
+It would be great if I could tell ikiwiki to automatically instantiate pages for each [[tag|/tags]], according to a template, especially when `$tagbase` is set.
 
 Tags are mainly specific to the object to which they’re stuck. However, I often use them the other way around, too: as concepts. And sometimes I’d like to see all pages related to a given concept (“tagged with a given tag”). The only way to do this with ikiwiki is to instantiate a page for each tag and slap a map on it. This is quite tedious and I’d really love to see Ikiwiki do so by default for all tags.
 
 Also see: <http://madduck.net/blog/2008.01.06:new-blog/> and <http://users.itk.ppke.hu/~cstamas/code/ikiwiki/autocreatetagpage/>
 
-[[tag wishlist]]
+[[!tag wishlist plugins/tag patch]]
 
 I would love to see this as well. -- dato
+
+---
+
+I have create a patch to [[tag.pm|plugins/tag]] for add the option for auto create tag pages.
+A new setting is used to enable or disable auto-create tag pages, `tag_autocreate`.
+The new tag file is created during the preprocess phase. 
+The new tag file is then complied during the change phase.
+
+_tag.pm from version 3.01_
+
+
+       --- tag.pm      2009-02-06 10:26:03.000000000 -0700
+       +++ tag_new.pm  2009-02-06 12:17:19.000000000 -0700
+       @@ -14,6 +14,7 @@
+                       hook(type => "preprocess", id => "tag", call => \&preprocess_tag, scan => 1);
+                       hook(type => "preprocess", id => "taglink", call => \&preprocess_taglink, scan => 1);
+                       hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
+       +       hook(type => "change", id => "tag", call => \&change);
+        }
+        
+        sub getopt () {
+       @@ -36,6 +37,36 @@
+                                                       safe => 1,
+                                                       rebuild => 1,
+                                       },
+       +               tag_autocreate => {
+       +                       type => "boolean",
+       +                       example => 0,
+       +                       description => "Auto-create the new tag pages, uses autotagpage.tmpl ",
+       +                       safe => 1,
+       +                       rebulid => 1,
+       +               },
+       +}
+       +
+       +my $autocreated_page = 0;
+       +
+       +sub gen_tag_page($)    {
+       +       my $tag=shift;
+       +
+       +       my $tag_file=$tag.'.'.$config{default_pageext};
+       +       return if (-f $config{srcdir}.$tag_file);
+       +
+       +       my $template=template("autotagpage.tmpl");
+       +       $template->param(tag => $tag);
+       +       writefile($tag_file, $config{srcdir}, $template->output);
+       +       $autocreated_page = 1;
+       +
+       +       if ($config{rcs}) {
+       +               IkiWiki::disable_commit_hook();
+       +               IkiWiki::rcs_add($tag_file);
+       +               IkiWiki::rcs_commit_staged(
+       +                       gettext("Automatic tag page generation"),
+       +                       undef, undef);
+       +               IkiWiki::enable_commit_hook();
+       +       }
+        }
+        
+        sub tagpage ($) {
+       @@ -47,6 +78,10 @@
+                                       $tag=~y#/#/#s; # squash dups
+                       }
+        
+       +       if (defined $config{tag_autocreate} && $config{tag_autocreate} ) {
+       +               gen_tag_page($tag);
+       +       }
+       +
+                       return $tag;
+        }
+        
+       @@ -125,4 +160,18 @@
+                       }
+        }
+        
+       +sub change(@) {
+       +       return unless($autocreated_page);
+       +       $autocreated_page = 0;
+       +
+       +       # This refresh/saveindex is to complie the autocreated tag pages
+       +       IkiWiki::refresh();
+       +       IkiWiki::saveindex();
+       +
+       +       # This refresh/saveindex is to fix the Tags link
+       +       # With out this additional refresh/saveindex the tag link displays ?tag
+       +       IkiWiki::refresh();
+       +       IkiWiki::saveindex();
+       +}
+       +
+
+
+This uses a [[template|wikitemplates]] called `autotagpage.tmpl`, here is my template file:
+
+    \[[!inline pages="link(<TMPL_VAR TAG>)" archive="yes"]]
+
+
+A quirk I have not figured out is during the `sub change`, see my comments in the code.
+I am not sure if that is the best way to handle it.
+
+[[!tag patch]]
+-- Jeremy Schultz <jeremy.schultz@uleth.ca>
+
+No, this doesn't help:
+
+       +       # This refresh/saveindex is to fix the Tags link
+       +       # With out this additional refresh/saveindex the tag link displays ?tag
+       +       IkiWiki::refresh();
+       +       IkiWiki::saveindex();
+
+On the second extra pass, it doesn't notice that it has to update the "?"-link. If I run ikiwiki once more, it is updated. I don't know yet how this should be fixed, because I don't know the internals of ikiwiki well enough. Something inhibits detecting the need to update in refresh() in Render.pm; perhaps, this condition: 
+
+               if (! $pagemtime{$page}) {
+                   ...
+                               push @add, $file;
+                   ...
+                }
+
+is not satisfied for the newly created tag page. I shall put debug msgs into Render.pm to find out better how it works. --Ivan Z.
index e9706653f23fa053a72836924bca8941f616c854..71b4b88f0263ca20c9810d47ad297561f2a9e6bb 100644 (file)
@@ -7,8 +7,11 @@ as the type argument.
 
 Together with the ability to have
 [[wiki-formatted_comments|wiki-formatted_comments_with_syntax_plugin]],
-this would allow the use of ikiwiki for [[wikipedia literate programming]].
+this would allow the use of ikiwiki for [[!wikipedia literate programming]].
 
 * I have started something along these lines see [[plugins/contrib/sourcehighlight]].  For some reason I started with source-highlight [[DavidBremner]]
 
 * I wonder if this is similar to what you want: <http://iki.u32.net/setup/Highlight_Code_Plugin/>
+
+> The new [[plugins/highlight]] plugin is in ikiwiki core and supports
+> source code files natively. [[done]] --[[Joey]] 
diff --git a/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion.mdwn b/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion.mdwn
new file mode 100644 (file)
index 0000000..64bc21e
--- /dev/null
@@ -0,0 +1,215 @@
+Here is another [[patch]] for this.  It is more up to date than either of the patches linked on the previous page.  It is most similar to [[plugins/contrib/sourcehighlight]].
+
+Updated to use fix noted in [[bugs/multiple_pages_with_same_name]].
+
+-- [[Will]]
+
+----
+I was trying to replace sourcehighlight with sourcecode. I had to modify the 
+htmlize call slightly so that it would work in a format directive.
+([modified version](http://pivot.cs.unb.ca/git/?p=ikiplugins.git;a=blob_plain;f=IkiWiki/Plugin/sourcecode.pm;hb=21fc57091edb9))
+
+> I haven't tested them, but those changes look sensible to me. -- [[Will]]
+
+I hit a wall the following example (the last commit in the above repo).
+
+    \[[!meta title="Solutions to assignment 1"]]
+
+    - [[!format cc """
+    test
+    """]]
+
+
+> I haven't actually tested this to see what the problem is.  How does this fail?
+> Does source-highlight barf on the non-c++ content?  Is there a wiki URL that shows the failure?  -- [[Will]]
+>> Here is the content div from the output page
+>> [[DavidBremner]]
+
+     <div id="content">
+     <p><ul>
+     <li><div id="sourcecode"></li>
+     </ul>
+     2beb4fd7289998159f61976143f66bb6</p>
+
+     <p></div></p>
+
+     </div>
+
+>>> That is quite strange.  I tested your version of the plugin.  I had to revert one your changes to get it to
+>>> work: the linenumber argument should not have a space at the end of it.  Once I made that change,
+>>> everything worked as expected.  The output I get for your example is below:
+
+    <div id="content">
+    <ul>
+    <li><div id="sourcecode"></li>
+    </ul>
+    
+    <pre><tt><span class="linenum">00001:</span> <span class="normal">test</span></tt></pre>
+    
+    <p></div></p>
+    
+    </div>
+
+>>> I don't know what is going wrong for you... source-highlight, Markdown or something else.
+>>>> It's a well-known bug in old versions of markdown. --[[Joey]] 
+>>> I do find it interesting the way the sourcecode `div` and the list get interleaved.  That
+>>> just looks like a Markdown thing though.
+>>> In any case, I've updated the patch below to include most of your changes.  -- [[Will]]
+
+----
+
+    #!/usr/bin/perl
+    # markup source files
+    # Originally by Will Uther
+    # With modifications by David Bremner
+    package IkiWiki::Plugin::sourcecode;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 2.00;
+    use open qw{:utf8 :std};
+    
+    my %metaheaders;
+    
+    sub import {
+        hook(type => "getsetup", id => "sourcecode", call => \&getsetup);
+        hook(type => "checkconfig", id => "sourcecode", call => \&checkconfig);
+        hook(type => "pagetemplate", id => "sourcecode", call => \&pagetemplate);
+    }
+    
+    sub getsetup () {
+        return 
+            plugin => {
+                safe => 1,
+                rebuild => 1, # format plugin
+            },
+            sourcecode_command => {
+                type => "string",
+                example => "/usr/bin/source-highlight",
+                description => "The command to execute to run source-highlight",
+                safe => 0,
+                rebuild => 1,
+            },
+            sourcecode_lang => {
+                type => "string",
+                example => "c,cpp,h,java",
+                description => "Comma separated list of suffixes to recognise as source code",
+                safe => 1,
+                rebuild => 1,
+            },
+            sourcecode_linenumbers => {
+                type => "boolean",
+                example => 1,
+                description => "Should we add line numbers to the source code",
+                safe => 1,
+                rebuild => 1,
+            },
+            sourcecode_css => {
+                type => "string",
+                example => "sourcecode_style",
+                description => "page to use as css file for source",
+                safe => 1,
+                rebuild => 1,
+            },
+    }
+    
+    sub checkconfig () {
+        if (! $config{sourcecode_lang}) {
+            error("The sourcecode plugin requires a list of suffixes in the 'sourcecode_lang' config option");
+        }
+    
+        if (! $config{sourcecode_command}) {
+            $config{sourcecode_command} = "source-highlight";
+        }
+    
+        if (! length `which $config{sourcecode_command} 2>/dev/null`) {
+            error("The sourcecode plugin is unable to find the $config{sourcecode_command} command");
+        }
+    
+        if (! $config{sourcecode_css}) {
+            $config{sourcecode_css} = "sourcecode_style";
+        }
+    
+        if (! defined $config{sourcecode_linenumbers}) {
+            $config{sourcecode_linenumbers} = 1;
+        }
+    
+        my %langs = ();
+    
+        open(LANGS, "$config{sourcecode_command} --lang-list|");
+        while (<LANGS>) {
+            if ($_ =~ /(\w+) = .+\.lang/) {
+                $langs{$1} = 1;
+            }
+        }
+        close(LANGS);
+    
+        foreach my $lang (split(/[, ]+/, $config{sourcecode_lang})) {
+            if ($langs{$lang}) {
+                hook(type => "htmlize", id => $lang, no_override=>1,
+                call => sub { htmlize(lang=>$lang, @_) }, 
+                keepextension => 1);
+            } else {
+                error("Your installation of source-highlight cannot handle sourcecode language $lang!");
+            }
+        }
+    }
+    
+    sub htmlize (@) {
+        my %params=@_;
+    
+        my $page = $params{page};
+    
+        eval q{use FileHandle};
+        error($@) if $@;
+        eval q{use IPC::Open2};
+        error($@) if $@;
+    
+        local(*SPS_IN, *SPS_OUT);  # Create local handles
+    
+        my @args;
+    
+        if ($config{sourcecode_linenumbers}) {
+            push @args, '--line-number';
+        }
+    
+        my $pid = open2(*SPS_IN, *SPS_OUT, $config{sourcecode_command},
+                        '-s', $params{lang},
+                        '-c', $config{sourcecode_css}, '--no-doc',
+                        '-f', 'xhtml',
+                        @args);
+    
+        error("Unable to open $config{sourcecode_command}") unless $pid;
+    
+        print SPS_OUT $params{content};
+        close SPS_OUT;
+    
+        my @html = <SPS_IN>;
+        close SPS_IN;
+    
+        waitpid $pid, 0;
+    
+        my $stylesheet=bestlink($page, $config{sourcecode_css}.".css");
+        if (length $stylesheet) {
+            push @{$metaheaders{$page}}, '<link href="'.urlto($stylesheet, $page).'"'.
+                ' rel="stylesheet"'.
+                ' type="text/css" />';
+        }
+    
+        return '<div id="sourcecode">'."\r\n".join("",@html)."\r\n</div>\r\n";
+    }
+    
+    sub pagetemplate (@) {
+        my %params=@_;
+    
+        my $page=$params{page};
+        my $template=$params{template};
+    
+        if (exists $metaheaders{$page} && $template->query(name => "meta")) {
+            # avoid duplicate meta lines
+            my %seen;
+            $template->param(meta => join("\n", grep { (! $seen{$_}) && ($seen{$_}=1) } @{$metaheaders{$page}}));
+        }
+    }
+    
+    1
diff --git a/doc/todo/avatar.mdwn b/doc/todo/avatar.mdwn
new file mode 100644 (file)
index 0000000..b8aa232
--- /dev/null
@@ -0,0 +1,47 @@
+[[!tag wishlist]]
+
+It would be nice if ikiwiki, particularly [[plugins/comments]]
+supported user avatar icons. I was considering adding a directive for this,
+as designed below.
+
+However, there is no *good* service for mapping openids to avatars --
+openavatar has many issues, including not supporting delegated openids, and
+after trying it, I don't trust it to push users toward. 
+Perhaps instead ikiwiki could get the email address from the openid
+provider, though I think the perl openid modules don't support the openid
+2.x feature that allows that.
+
+At the moment, working on this doesn't feel like a good use of my time.
+--[[Joey]]
+
+Hmm.. unless is just always used a single provider (gravatar) and hashed
+the openid. Then wavatars could be used to get a unique avatar per openid
+at least. --[[Joey]] 
+
+----
+
+The directive displays a small avatar image for a user. Pass it the
+email address, openid, or wiki username of the user.
+
+       \[[!avatar user@example.com]]
+       \[[!avatar http://joey.kitenet.net/]]
+       \[[!avatar user]]
+
+The avatars are provided by various sites. For email addresses, it uses a
+[gravatar](http://gravatar.com/). For openid,
+[openavatar](http://www.openvatar.com/) is used. For a wiki username, the
+user's email address is looked up and the gravatar for that user is
+displayed. (Of course, the user has to have filled in their email address
+on their Preferences page for that to work.)
+
+An optional second parameter can be included, containing additional
+options to pass in the 
+[gravatar url](http://en.gravatar.com/site/implement/url).
+For example, this asks for a smaller gravatar, and if a user does
+not have a gravatar, uses a cute auto-generated "wavatar" avatar.
+
+       \[[!gravatar user@example.com "size=40&default=wavatar"]]
+
+The `gravitar_options` setting in the setup file can be used to
+specify additional options to pass. So for example if you want
+to use wavatars everywhere, set it to "default=wavatar".
diff --git a/doc/todo/avoid_thrashing.mdwn b/doc/todo/avoid_thrashing.mdwn
new file mode 100644 (file)
index 0000000..45b11d8
--- /dev/null
@@ -0,0 +1,22 @@
+Problem: Suppose a server has 256 mb ram. Each ikiwiki process needs about
+15 mb, before it's loaded the index. (And maybe 25 after, but only one such
+process runs at any time). That allows for about 16 ikiwiki processes to
+run concurrently on a server, before it starts to swap. Of course, anything
+else that runs on the server and eats memory will affect this.
+
+One could just set `MaxClients 16` in the apache config, but then it's also
+limited to 16 clients serving static pages, which is silly. Also, 16 is
+optimistic -- 8 might be a saner choice. And then, what if something on the
+server decides to eat a lot of memory? Ikiwiki can again overflow memory 
+and thrash.
+
+It occurred to me that the ikiwiki cgi wrapper could instead do locking of
+its own (say of `.ikiwiki/cgilock`). The wrapper only needs a few kb to
+run, and it starts *fast*. So hundreds could be running waiting for a lock
+with no ill effects. Crank `MaxClients` up to 256? No problem..
+
+And there's no real reason to allow more than one ikiwiki cgi to run at a
+time. Since almost all uses of the CGI lock the index, only one can really
+be doing anything at a time. --[[Joey]]
+
+[[done]]
diff --git a/doc/todo/backlinks_result_is_lossy.mdwn b/doc/todo/backlinks_result_is_lossy.mdwn
new file mode 100644 (file)
index 0000000..11b5fbc
--- /dev/null
@@ -0,0 +1,13 @@
+[[!tag patch patch/core]]
+[[!template id=gitbranch branch=smcv/ready/among author="[[smcv]]"]]
+
+IkiWiki::backlinks returns a form of $backlinks{$page} that has undergone a
+lossy transformation (to get it in the form that page templates want), making
+it more difficult to use in other contexts (like pagestats).
+
+A commit on my `among` branch splits it into IkiWiki::backlink_pages
+(which returns the keys of $backlinks{$page}, and might be suitable for
+exporting) and IkiWiki::backlinks (which calls backlink_pages, then performs
+the same lossy transformation as before on the result).
+
+[[done]] --[[Joey]]
index 7dc767e7644486b740b55d9f0650a8e4e215b320..cb8dee6979f6faaf496052e60a6157f27e7bc071 100644 (file)
@@ -2,6 +2,15 @@ The pages in the basewiki should be fully self-documenting as far as what
 users need to know to edit pages in the wiki. [[ikiwiki/Formatting]]
 documents the basics, but doesn't include every preprocessor directive.
 
+> Thanks to Joey's work applying and fixing up my patches, this is mostly done.
+> The one thing I'd add above the way things currently work would be to add
+> the [[plugins/listdirectives]] plugin to [[plugins/goodstuff]]. 
+> Doing that requires making the decision about whether you really want the
+> documentation in every wiki - it is 200k.  -- [[Will]]
+
+>> I don't think that it needs to be in goodstuff to close this, though I
+>> might decide to add it to goodstuff later. [[done]] --[[Joey]]
+
 Note that there's a disctinction between being self-documenting for users,
 and being complete documentation for ikiwiki. The basewiki is _not_
 intended to be the latter, so it lacks the usage page, all the plugin
index aade457d054c9988e76650fbc7b2571e925120f3..69df27271a1bfe57caededcd631727a94c32000c 100644 (file)
@@ -51,13 +51,13 @@ Index: IkiWiki/Plugin/blogpost.pm
 +use POSIX;
 +use IkiWiki 2.00;
 +
-+sub import { #{{{
++sub import {
 +      hook(type => "checkconfig", id => "blogpost", call => \&checkconfig);
 +      hook(type => "authcgi", id => "blogpost", call => \&authcgi);
 +      hook(type => "canedit", id => "blogpost", call => \&canedit);
-+} # }}}
++}
 +
-+sub checkconfig () { #{{{
++sub checkconfig () {
 +      if (! defined $config{blogformat}){
 +              $config{blogformat} = 'posts/%Y/%m/%d/$title';
 +      }
@@ -72,9 +72,9 @@ Index: IkiWiki/Plugin/blogpost.pm
 +      if (! defined $config{blogusers}) {
 +              $config{blogusers} = (); # disallow all posting by default
 +      }
-+} #}}}
++}
 +
-+sub authcgi ($$) { #{{{
++sub authcgi ($$) {
 +      my $cgi=shift;
 +      my $session=shift;
 +
@@ -115,16 +115,16 @@ Index: IkiWiki/Plugin/blogpost.pm
 +              $cgi->param("page", $page);
 +      }
 +
-+} #}}}
++}
 +
-+sub blogpage ($) { #{{{
++sub blogpage ($) {
 +      my $title=shift;
 +      my $page=POSIX::strftime $config{blogformat}, localtime;
 +      $page =~ s/\$title/$title/;
 +      return $page;
-+} #}}}
++}
 +
-+sub canedit ($$$) { #{{{
++sub canedit ($$$) {
 +      my $page=shift;
 +      my $cgi=shift;
 +      my $session=shift;
@@ -136,7 +136,7 @@ Index: IkiWiki/Plugin/blogpost.pm
 +      return "" if ($config{blogusers} eq "*" ||
 +                    grep {$_ eq $user} $config{blogusers});
 +      return ("not allowed to blog, $user");
-+} #}}}
++}
 +
 +1
 Index: IkiWiki.pm
@@ -153,4 +153,4 @@ Index: IkiWiki.pm
  our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
 </pre>
 
-[[tag patch]]
+[[!tag patch patch/core]]
diff --git a/doc/todo/blogspam_training.mdwn b/doc/todo/blogspam_training.mdwn
new file mode 100644 (file)
index 0000000..f15eba5
--- /dev/null
@@ -0,0 +1,31 @@
+The [[blogspam plugin|plugins/blogspam]] is just great.
+
+However, it lacks support in the web interface to [train comments as
+SPAM](http://blogspam.net/api/classifyComment.html), when they were
+erroneously identified as ham.  It would be great to have such
+support, also in the spirit of helping
+[blogspam.net](http://blogspam.net) to get better and better.
+
+What would consist the most appropriate user interface is not entirely
+clear to me in the general case (wiki page editing).  The case of blog
+comments look easier to: when the admin user is logged in (and if the
+blogspam plugin is enabled), each comment can have an extra link "mark
+as SPAM" which would both delete/revert the comment and submit it to
+the configured blogspam server for training.
+
+> Comments can't have an extra link when the admin user is logged
+> in, because the admin user sees the same static pages as everyone
+> else (non-admins still see the "remove" link provided by the remove
+> plugin, too). Perhaps a better UI would be that the action of that
+> link was overridden by the blogspam plugin to go to a form with
+> a checkbox for "also submit as spam"? --[[smcv]]
+
+Similarly, ham training can be plugged directly into the current
+comment moderation interface. Each comment that gets approved by the
+admin, can be sent to blogspam.net as ham. If this is considered too
+"aggressive", this behaviour can need to be explicitly enabled by
+turning on a configuration option.
+
+-- [[Zack]]
+
+[[!tag wishlist]]
index 179ea2f24db7ced98c4838858af9c14277c8d668..a50c58d26d1deaee5a1a2dbbef66c09ed848371d 100644 (file)
@@ -56,15 +56,15 @@ and rcs_getctime and rcs_notify aren't written at all. --[[bma]]
             return @ret;
     }
     
-    sub rcs_update () { #{{{
+    sub rcs_update () {
             # Not needed.
-    } #}}}
+    }
     
-    sub rcs_prepedit ($) { #{{{
+    sub rcs_prepedit ($) {
             return "";
-    } #}}}
+    }
     
-    sub rcs_commit ($$$;$$) { #{{{
+    sub rcs_commit ($$$;$$) {
             my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
     
             if (defined $user) {
@@ -95,18 +95,18 @@ and rcs_getctime and rcs_notify aren't written at all. --[[bma]]
             system("bzr","whoami",$olduser);
     
             return undef; # success
-    } #}}}
+    }
     
-    sub rcs_add ($) { # {{{
+    sub rcs_add ($) {
             my ($file) = @_;
     
             my @cmdline = ("bzr", "add", "--quiet", "$config{srcdir}/$file");
             if (system(@cmdline) != 0) {
                     warn "'@cmdline' failed: $!";
             }
-    } #}}}
+    }
     
-    sub rcs_recentchanges ($) { #{{{
+    sub rcs_recentchanges ($) {
             my ($num) = @_;
     
             eval q{use CGI 'escapeHTML'};
@@ -153,15 +153,15 @@ and rcs_getctime and rcs_notify aren't written at all. --[[bma]]
             }
     
             return @ret;
-    } #}}}
+    }
     
-    sub rcs_notify () { #{{{
+    sub rcs_notify () {
             # TODO
-    } #}}}
+    }
     
-    sub rcs_getctime ($) { #{{{
+    sub rcs_getctime ($) {
             # TODO
-    } #}}}
+    }
     
     1
 
index caff547808afe9000a60b6f2db4ebe2f10f46162..0a036d3153dc0723d7562eceba03e7b77e671ed8 100644 (file)
@@ -1,6 +1,6 @@
 I am serving notice that I am starting work on a calendar plugin inspired by Blosxom's calendar plugin. The current plan is to create a plugin that looks through all the source files matching a certain pagespec, and optionally spit out a month view for the specified month (default to current), or spit out a year view for a given year (defaulting to the current year), of a list  of year with posts in them. The output would be a table, with the same CSS directives that the Blosxom plugin used to use (so that I can just reuse my css file).  The links would be created to a $config{archivedir}/$year or $config{archivedir}/$year-$month file, which can just have 
 
-     \[[inline pages="blog/* and !*/Discussion and creation_year($year) and creation_month($month)" rss="no" atom="no" show="0"]]
+     \[[!inline pages="blog/* and !*/Discussion and creation_year($year) and creation_month($month)" rss="no" atom="no" show="0"]]
 
 or some thing to generate a archive of postings. 
 
@@ -10,21 +10,21 @@ ManojSrivastava
 
 This plugin is inspired by the calendar plugin for Blosxom, but derivesno code from it. This plugin is essentially a fancy front end to archives of previous pages, usually used for blogs. It can produce a calendar for a given month, or a list of months for a given year. To invoke the calendar, just use the preprocessor directive:
 
-     \[[calendar ]]
+     \[[!calendar ]]
 
 or
 
-      \[[calendar type="month" pages="blog/* and !*/Discussion"]]
+      \[[!calendar type="month" pages="blog/* and !*/Discussion"]]
 
 or
 
-       \[[calendar type="year"  year="2005" pages="blog/* and !*/Discussion"]]
+       \[[!calendar type="year"  year="2005" pages="blog/* and !*/Discussion"]]
 
 
 The year and month entities in the out put have links to archive index pages, which are supposed to exist already. The idea is to create an archives hierarchy, rooted in the subdirectory specified in the site-wide customization variable, archivebase. archivebase defaults to "archives".  Links are created to pages "$archivebase/$year" and "$archivebase/$year/$month". The idea is to create annual and monthly indices, for example, by using something like this sample from my archives/2006/01.mdwn 
 
-          \[[meta title="Archives for 2006/01"]]
-          \[[inline rootpage="blog" atom="no" rss="no" show="0" pages="blog/* and !*/Discussion and creation_year(2006) and creation_month(01)" ]]
+          \[[!meta title="Archives for 2006/01"]]
+          \[[!inline rootpage="blog" atom="no" rss="no" show="0" pages="blog/* and !*/Discussion and creation_year(2006) and creation_month(01)" ]]
 
 I'll send in the patch via email.
 
@@ -38,7 +38,7 @@ mailed me, and my response to it. --[[Joey]]
 > > I'm sending in an updated package, and have removed the older version you had here.--ManojSrivastava
 
 
-[[tag patch]]
+[[!tag patch]]
 
 ----
 
index b294e594a43563a1cf7d9fcb821ca838f8b63293..694f676339a583398fa8e3bf6ed07d3e39996b09 100644 (file)
@@ -13,4 +13,4 @@ with all news or the one with the latest news only, I don't know yet.)
 >> wouldn't embed the feed link into `<head>` so that browsers can automatically
 >> find it.
 
-[[tag wishlist]]
+[[!tag wishlist]]
diff --git a/doc/todo/cas_authentication.mdwn b/doc/todo/cas_authentication.mdwn
new file mode 100644 (file)
index 0000000..8bf7042
--- /dev/null
@@ -0,0 +1,171 @@
+[[!tag patch wishlist]]
+
+ikiwiki should support [Central Authentication
+Service](http://www.ja-sig.org/products/cas/) authentication in order to use
+this <acronym title='Single Sign On'>SSO</acronym> mechanism very popular in
+universities web services.
+
+I have already written a first draft plugin supporting that authentication
+mechanism. It works for me with my university CAS service. I did not try it
+with other CAS server but it do not see any reason why it should not work.
+
+What is the best way to submit it to you (just in case it can help my patch
+follows) ?
+
+--[[/users/bbb]]
+
+> Inline here is ok; git-am by mail is ok; a git repo I can pull from also
+> ok.
+> 
+> This looks pretty acceptable as-is, but you need to put a copyright and
+> license statement at the top. I have a few questions that I'll insert
+> inline with the patch below. --[[Joey]]
+
+------------------------------------------------------------------------------
+    diff --git a/IkiWiki/Plugin/cas.pm b/IkiWiki/Plugin/cas.pm
+    new file mode 100644
+    index 0000000..ea189df
+    --- /dev/null
+    +++ b/IkiWiki/Plugin/cas.pm
+    @@ -0,0 +1,94 @@
+    +#!/usr/bin/perl
+    +# JaSIG CAS support by Bruno Beaufils <bruno@boulgour.com>
+    +package IkiWiki::Plugin::cas;
+    +
+    +use warnings;
+    +use strict;
+    +use IkiWiki 2.00;
+    +use AuthCAS;                  # http://search.cpan.org/~osalaun/AuthCAS-1.3.1/
+
+> In ikiwiki we generally deman-load perl modules only when they're used.
+> This avoids loading expensive modules when the CGI isn't doing
+> authentication. Can you do that with AuthCAS? Something like this before
+> the use of it: `eval q{use AuthCAS}; error $@ if $@`
+
+    +
+    +sub import {
+    +    hook(type => "getopt", id => "cas", call => \&getopt);
+    +    hook(type => "auth", id => "cas", call => \&auth);
+    +    hook(type => "formbuilder_setup", id => "cas", call => \&formbuilder_setup);
+    +}
+
+> Could you please use tabs for indentation of program flow?
+
+    +# FIXME: We should check_config to ensure that :
+    +# * cas_url and ca_file are present
+
+> Please fix that..
+
+    +# * no other auth plugin are present (at least passwordauth and openid)
+
+> Why would you want to make other auth plugins not work? Could a site not
+> legitimatly chose to use this and another auth method?
+
+    +sub getopt () {
+    +    eval q{use Getopt::Long};
+    +    error($@) if $@;
+    +    Getopt::Long::Configure('pass_through');
+    +    GetOptions("cas_url=s" => \$config{cas_url});
+    +    GetOptions("ca_file=s" => \$config{ca_file});
+    +}
+    +
+    +sub auth ($$) {
+    +    my $q=shift;
+    +    my $session=shift;
+    +
+    +    my $cas = new AuthCAS(casUrl => $config{'cas'}{'cas_url'},
+    +                          CAFile => $config{'cas'}{'ca_file'});
+    +
+    +    my $service = $config{'cgiurl'};
+    +    my $ticket = $q->param('ticket');
+    +
+    +    unless (defined($ticket)) {
+    +        $service .= "?$ENV{QUERY_STRING}";
+    +        my $login_url = $cas->getServerLoginURL($service);
+    +        debug("CAS: asking a Service Ticket for service $service");
+    +        IkiWiki::redirect($q, $login_url);
+    +        exit 0;
+    +    } else {
+    +        $service = $service . "?$ENV{QUERY_STRING}";
+    +        $service =~ s/\&ticket=$ticket//;
+    +        my $user = $cas->validateST($service, $ticket);
+    +        if (defined $user) {
+    +            debug("CAS: validating a Service Ticket ($ticket) for service $service");
+    +            $session->param(name=>$user);
+    +            $session->param(CASservice=>$service);
+    +            IkiWiki::cgi_savesession($session);
+    +        } else {
+    +            error("CAS failure: ".&AuthCAS::get_errors());
+    +        }
+    +    }
+    +}
+    +
+    +# I use formbuilder_setup and not formbuilder type in order to bypass the
+    +# Logout processing done in IkiWiki::CGI::cgi_prefs()
+    +sub formbuilder_setup (@) {
+    +    my %params=@_;
+    +    
+    +    my $form=$params{form};
+    +    my $session=$params{session};
+    +    my $cgi=$params{cgi};
+    +    my $buttons=$params{buttons};
+    +
+    +    my $cas = new AuthCAS(casUrl => $config{'cas'}{'cas_url'},
+    +                          CAFile => $config{'cas'}{'ca_file'});
+    +
+    +    if ($form->title eq "preferences") {
+    +        # Show the login
+    +        if (! defined $form->field(name => "name")) {
+    +            $form->field(name => "CAS ID",
+    +                         disabled => 1,
+    +                         value => $session->param("name"), 
+    +                         size => 50,
+    +                         force => 1,
+    +                         fieldset => "login");
+    +        }
+    +        
+    +        # Force a logout if asked
+    +        if ($form->submitted && $form->submitted eq 'Logout')
+    +        {
+    +            debug("CAS: asking to remove the Ticket Grant Cookie");
+    +            IkiWiki::redirect($cgi, $cas->getServerLogoutURL($config{'url'}));
+    +            $session->delete();
+    +            exit 0;
+    +        }
+    +    }
+    +}
+    +
+    +1
+    diff --git a/doc/plugins/cas.mdwn b/doc/plugins/cas.mdwn
+    new file mode 100644
+    index 0000000..2f2f53e
+    --- /dev/null
+    +++ b/doc/plugins/cas.mdwn
+    @@ -0,0 +1,18 @@
+    +[[ template id=plugin name=cas core=0 author="[[bbb]]"]]
+    +[[ tag type/auth]]
+    +
+    +This plugin allows users to use authentication offered by a
+    +[JaSIG](http://www.ja-sig.org) [<acronym title='Central Authentication
+    +Service'>CAS</acronym>](http://www.ja-sig.org/products/cas/) server to log
+    +into the wiki.
+    +
+    +The plugin needs the [[!cpan AuthCAS-1.3.1]] perl module.
+
+> Does it really need that specific version? I think you should lose the
+> version part.
+
+    +
+    +This plugin has two mandatory configuration option. You **must** set `--cas_url`
+    +to the url of a server offering CAS 2.0 authentication. You must also set the
+    +`--ca_file` to an absolute path to the file containing CA certificates used by
+    +the server (generally, aka under Debian, fixing that value to
+    +`/etc/ssl/certs/ca-certificates.crt` is sufficient).
+
+> It would be good to add commented-out examples of these to
+> ikiwiki.setup as well.
+
+    +This plugin is not enabled by default. It can not be used with other
+    +authentication plugin, such as [[passwordauth]] or [[openid]].
+
+------------------------------------------------------------------------------
diff --git a/doc/todo/clear_page_to_delete.mdwn b/doc/todo/clear_page_to_delete.mdwn
new file mode 100644 (file)
index 0000000..6bab6ef
--- /dev/null
@@ -0,0 +1,33 @@
+Would it make sense to automatically delete a page if it's edited and
+cleared to be entirely empty (or only have whitespace)? Discuss. --[[Joey]]
+
+ I'd say so; yes. A method of deleting pages via the web would be great; I
+can't think of a use of keeping blank pages around. What about vandalism --
+if someone blanks a page and deletes it and someone else wishes to restore
+it; or is undoing edits via the web a bigger issue? -- [[users/Jon]]
+
+Of course there's already a way to delete pages (remove plugin). So the
+question is really:
+
+* Does it make sense to have a second way to do it, by clearing the page?
+* Should it be enabled even if the full remove plugin isn't?
+
+Re vandalism in general, I am generally happy using git-revert to kill the
+offending change. --[[Joey]]
+
+I don't think we need a second way to delete pages, which would probably be
+used by the only few people who will learn it's possible by random
+documentation reading, find it useful, *and* remember it. -- [[intrigeri]]
+
+On the other hand, clearing the page's whole content essentially means deleting
+the page.  That's what the user intended to do in this case.  The information
+content of an empty vs. a deleted page is essentially the same, I'd say.  But
+having ikiwiki remove those stale pages would save some (minimal, admittedly)
+time needed for manual clean-up.  --[[tschwinge]]
+
+On EmacsWiki, a page is marked for deletion when it contains just the DeletedPage 
+keyword and if there were no page editions since XX days. Here, I use pages that
+can be empty everyday and filled all day long. It does not make sense to me to 
+delete these pages :). --[[xma]]
+
+I was not aware of [[plugins/remove]]. I don't think another method is necessary -- [[users/Jon]]
index acf2c2d49e1ba94ace50d83d01beccd37bdb10bb..ab2a6b51fc716460018199db3977d2333facd14b 100644 (file)
@@ -6,7 +6,7 @@ for SVN. If this is OK, I'll patch the other RCS modules, too.
 > recognise such commit messages when parsing the logs. Do that and extend
 > to the other modules and I'll accept it. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
 
 <pre>
 --- IkiWiki/Rcs/svn.pm  (revision 2650)
diff --git a/doc/todo/color_plugin.mdwn b/doc/todo/color_plugin.mdwn
new file mode 100644 (file)
index 0000000..19fba3b
--- /dev/null
@@ -0,0 +1,231 @@
+Recently I've wanted to colour some piece of text on my Ikiwiki page.
+It seems that Markdown can do it only using HTML tags, so I used
+`<span class="color">foo bar baz</span>`.
+
+However, in my opinion mixing Markdown syntax and HTML tags is rather ugly,
+so maybe we should create a new color plugin to add more color to Ikiwiki ;)
+I know that another Wikis have similar plugin, for example
+[WikiDot](http://www.wikidot.com/).
+
+I've noticed that htmlscrubber plugin strips `style` attribute, because of
+security, so probably we need to use `class` attribute of HTML. But then
+we have to customize our `local.css` file to add all color we want to use.
+It's not as easy in usage like color name or definition as plugin argument,
+but I don't have a better idea right now.
+
+What do you think about it? --[[Paweł|ptecza]]
+
+> Making a plugin preserve style attributes can be done, it just has to add
+> them after the sanitize step, which strips them. The general method is
+> adding placeholders first, and replacing them with the real html later.
+> 
+> The hard thing to me seems to be finding a syntax that is better than a
+> `<span>`. A preprocessor directive is not really any less ugly than html
+> tags, though at least it could play nicely with nested markdown: --[[Joey]]
+> 
+>      \[[!color red,green """
+>      Xmas-colored markdown here
+>      """]]
+
+>> I'm glad you like that idea. In my opinion your syntax looks good.
+>> Out of curiosity, why did you used 2 colors in your example? What is HTML
+>> result for it? ;)
+
+>>> I was thinking one would be foreground, the other background. Don't
+>>> know if setting the background makes sense or not.
+
+>> I can try to create that plugin, if you are too busy now. I'm not Perl
+>> hacker, but I wrote a lot of Perl scripts in my life and color plugin
+>> doesn't seem to be very hard task. --[[Paweł|ptecza]]
+
+>> Yes, it's a good intro plugin, have at it! --[[Joey]]
+
+---
+
+This is a RC1 of my `color` plugin. It works for me well, but all your
+comments are very welcome. --[[Paweł|ptecza]]
+
+> Sure, I have a couple.
+
+>> Great! Thank you very much! --[[Paweł|ptecza]]
+
+> The preprocess function is passed named parameters. The hack you have of
+> hardcoding use of `$_[0]` and `$_[2]` can fail at any time.
+
+>> But the problem is that arguments of my plugin don't have a name.
+>> How can I identify them in `params` hash?
+
+>> Similar hardcoded method I've found in `img` plugin :) But only one
+>> argument is not named there (image path).
+
+>>> I think I hadn't realized what you were doing there. The order
+>>> for unnamed parameters can in fact be relied on. 
+>>> 
+>>> --[[Joey]]
+
+>> Maybe I shouldn't use so simple plugin syntax? For following syntax
+>> I wouldn't have that problem:
+
+>>     \[[!color fg=white bg=red text="White text on red background"]]
+
+> `replace_preserved_style` is passed a single parameter, so its prototype
+> should be `($)`, not `(@)`.  Ditt `preserve_style`, it should have
+> `($$)`.
+
+>> OK, it will be fixed.
+
+> The sanitize hook is always passed `$params{content}`, so there should be
+> no reason to check that it exists. Also, it shouldn't be done in a
+> sanitize hook, since html sanitization could run _after_ that santize
+> hook. It should use a format hook.
+
+>> Probably you're right. It was rather paranoid checking ;) Thanks for
+>> the hook hint!
+
+> The preprocess hook needs to call `IkiWiki::preprocess` on the content
+> passed into it if you want to support nesting other preprocessor
+> directives inside the color directive. See `preprocess_toggleable` in the
+> toggle plugin, for example.
+> 
+> I'm not a big fan of the dummy text `COLORS { ... } SROLOC;TEXT { ... TXET }`
+> The method used by toggle of using two real `<div>`s seems slightly
+> better. --[[Joey]]
+
+>> I don't like that too, but I didn't have better idea :) Thank you for
+>> the hint! I'll take a look at `toggle` plugin.
+
+---
+
+And here is RC2 of that plugin. I've changed a plugin syntax, because the old
+seems to be too enigmatic and it was hard to me to handle unnamed parameters
+in not hardcoded way. I hope that my changes are acceptable for you.
+Of course, I'm open for discussion or exchange of ideas :) --[[Paweł|ptecza]]
+
+> One question, why the 2px padding for span.color? --[[Joey]]
+
+>> Sorry for a long silence, but I had Internet free summer holiday :)
+>> I did that, because backgrounded text without any padding looks
+>> strange for me ;) You can remove it if you don't like that padding.
+>> --[[Paweł|ptecza]]
+
+>>> Joey, will you add that plugin to Ikiwiki 2.61? :) --[[Paweł|ptecza]]
+
+>>>> I also had a long net-free summer holiday. :-) The [[patch]] is
+>>>> ready for integration (made a few minor changes). Is this GPL 2?
+>>>> --[[Joey]]
+
+>>>>> No problem. I guessed it, because I've not seen your commits
+>>>>> at [[RecentChanges]] page in last days and I subscribe your
+>>>>> [blog](http://kitenet.net/~joey/blog/entry/vacation/) :D
+>>>>> It's GPL-2+ like your Ikiwiki and the most external plugins.
+>>>>> --[[Paweł|ptecza]]
+
+       --- /dev/null   2008-06-21 02:02:15.000000000 +0200
+       +++ color.pm    2008-07-27 14:58:12.000000000 +0200
+       @@ -0,0 +1,69 @@
+       +#!/usr/bin/perl
+       +# Ikiwiki text colouring plugin
+       +# Paweł‚ Tęcza <ptecza@net.icm.edu.pl>
+       +package IkiWiki::Plugin::color;
+       +
+       +use warnings;
+       +use strict;
+       +use IkiWiki 2.00;
+       +
+       +sub import {
+       +       hook(type => "preprocess", id => "color", call => \&preprocess);
+       +       hook(type => "format",     id => "color", call => \&format);
+       +}
+       +
+       +sub preserve_style ($$$) {
+       +       my $foreground = shift;
+       +       my $background = shift;
+       +       my $text       = shift;
+       +
+       +       $foreground = defined $foreground ? lc($foreground) : '';
+       +       $background = defined $background ? lc($background) : '';
+       +       $text       = '' unless (defined $text);
+       +
+       +       # Validate colors. Only color name or color code are valid.
+       +       $foreground = '' unless ($foreground &&
+       +                               ($foreground =~ /^[a-z]+$/ || $foreground =~ /^#[0-9a-f]{3,6}$/));
+       +       $background = '' unless ($background &&
+       +                               ($background =~ /^[a-z]+$/ || $background =~ /^#[0-9a-f]{3,6}$/));
+       +
+       +       my $preserved = '';
+       +       $preserved .= '<span class="color">';
+       +       $preserved .= 'color: '.$foreground if ($foreground);
+       +       $preserved .= '; ' if ($foreground && $background);
+       +       $preserved .= 'background-color: '.$background if ($background);
+       +       $preserved .= '</span>';
+       +       $preserved .= '<span class="colorend">'.$text.'</span>';
+       +       
+       +       return $preserved;
+       +
+       +}
+       +
+       +sub replace_preserved_style ($) {
+       +       my $content = shift;
+       +
+       +       $content =~ s!<span class="color">((color: ([a-z]+|\#[0-9a-f]{3,6})?)?((; )?(background-color: ([a-z]+|\#[0-9a-f]{3,6})?)?)?)</span>!<span class="color" style="$1">!g;
+       +       $content =~ s!<span class="colorend">!!g;
+       +
+       +       return $content;
+       +}
+       +
+       +sub preprocess (@) {
+       +       my %params = @_;
+       +
+       +       # Preprocess the text to expand any preprocessor directives
+       +       # embedded inside it.
+       +       $params{text} = IkiWiki::preprocess($params{page}, $params{destpage},
+       +                               IkiWiki::filter($params{page}, $params{destpage}, $params{text}));
+       +
+       +       return preserve_style($params{foreground}, $params{background}, $params{text});
+       +}
+       +
+       +sub format (@) {
+       +       my %params = @_;
+       +
+       +       $params{content} = replace_preserved_style($params{content});
+       +       return $params{content};        
+       +}
+       +
+       +1
+       --- /dev/null   2008-06-21 02:02:15.000000000 +0200
+       +++ color.mdwn  2008-07-27 15:04:42.000000000 +0200
+       @@ -0,0 +1,25 @@
+       +\[[!template id=plugin name=color core=0 author="[[ptecza]]"]]
+       +
+       +This plugin can be used to color a piece of text on a page.
+       +It can be used to set the foreground and/or background color of the text.
+       +
+       +You can use a color name (e.g. `white`) or HTML code (e.g. `#ffffff`)
+       +to define colors. 
+       +
+       +Below are a few examples:
+       +
+       +    \[[!color foreground=white background=#ff0000 text="White text on red background"]]
+       +
+       +In the above example, the foreground color is defined as a word, while the background color is defined as a HTML
+       +color code.
+       +
+       +    \[[!color foreground=white text="White text on default color background"]]
+       +
+       +The background color is missing, so the text is displayed on default background.
+       +
+       +    \[[!color background=#ff0000 text="Default color text on red background"]]
+       +
+       +The foreground is missing, so the text has the default foreground color.
+       --- style.css-orig      2008-07-27 15:12:39.000000000 +0200
+       +++ style.css   2008-07-27 15:15:06.000000000 +0200
+       @@ -333,3 +333,7 @@
+               background: #eee; 
+               color: black !important;
+        }
+       +
+       +span.color {
+       +       padding: 2px;
+       +}
+
+[[done]]
index ed9db06214ec880025ac11c9380064395cf15cd1..87e57417e7f73fe43ac9ab2988480db51bfcc47f 100644 (file)
@@ -1,69 +1,3 @@
 I would like to allow comments on ikiwiki pages without CGI.
-I have in mind something like
 
-  * Use a pagetemplate hook  
-    in a plugin (DONE)
-  * add a mailto: url to each page matching some pagespec
-    (currently every page gets a comment footer)
-  * this mailto url goes to an address identifying the page  (something like
-    user-iki-FE653b@host.fqdn.tld).  (DONE) 
-    > I wonder if it would be more or less natural to put an encoded form
-    > of the page name in the email address? I'm thinking about something
-    > like `wikiname+index@host` or `wikiname+todo+comment_by_mail@host`.
-    > The basic transformation would be to call `titlepage($page)` (in the
-    > C locale), followed by replacing "/" with "+" (since "/" is not
-    > valid in mails). --[[Joey]]
-    >> I guess you are right, there is no point being more obscure 
-    >> than necessary.  I am leaning towards   [something](http://www.cs.unb.ca/~bremner/blog/posts/encoding) not        
-   >> calling titlepage but in the same spirit. --[[DavidBremner]]
-
-  * on the mail receiving end, these messages are either deleted, or ran through
-    a filter to be turned into blog posts.
-
-    - I'm thinking about how the filter should work. Within a 
-    mail client, or as a batch tool to scan a mailbox? How to    interact with version control, if at all?
-
-  * the same plugin can check for comments on a particular page next time the wiki 
-    is generated, and add a link. (more or less done)
-    > If the filter just checks in the posts into revision control, the
-    > post-commit hook would handle updating the wiki to include those
-    > posts as they come in. --[[Joey]]
-  * work in progress can be 
-
-   - [cloned](http://pivot.cs.unb.ca/git/ikiperl.git), or 
-   - [browsed](http://pivot.cs.unb.ca/git/?p=ikipostal.git;a=summary)
-  
-
-Any comments? Write them here or send them to [[DavidBremner]]
-
-> I don't want to derail this with too much blue-skying, but I was thinking
-> earlier that it would be nice if ikiwiki could do something sensible with
-> mailbox files, such as turning them into a (threaded?) blog display.
-> 
-> One reason I was thinking about that was just that it would be nice to 
-> be able to use ikiwiki for mailing list archives. But another reason was
-> that it would be nice to solve the problem described in
-> [[discussion_page_as_blog]]. For that you really want a threaded system,
-> and mailbox file formats already have threading.
-> 
-> If that were done, it would tie into what you're working on in an
-> interesting way, since the incoming mail would only need to be committed to
-> the appropriate mailbox file, with ikiwiki then running to process it.
-> --[[Joey]]
->> It is an interesting idea.  I like that it uses an arbitrary MUA 
->> as a "moderation" interface.  One thing it made me think about is 
->> how to encode reference (threading) information. One can of 
->> course encode this into local-part, but I wonder if it would be 
->> better to use header features of mailto (this could also be an 
->> alternative to tagged mail addresses for page references).  
->> Various client handling of mailto always seemed a bit fragile to 
->> me but maybe I am just behind the times.  Most headers are ignored, but
->> pseudo-headers in the body might work. For example: 
->>[test](mailto:bremner@somewhere.ca?body=X-Iki-Page:%20test%0AX-Iki-thread:%20foobar).  I hesitate to use the subject because every mail admin in the 
->> world seems to want to add things to the front of it. 
->> -- [[DavidBremner]]
->>> Although it is in python, just from reading the Debian ITP, it 
->>> looks like 
->>> [mnemosyne-blog](http://www.red-bean.com/~decklin/mnemosyne/)  
->>> might be an interesting backend to use or at least steal ideas 
->>> from :-)  --[[David Bremner]]
+> [[done]], see [[plugins/contrib/postal]]
diff --git a/doc/todo/comment_by_mail/discussion.mdwn b/doc/todo/comment_by_mail/discussion.mdwn
new file mode 100644 (file)
index 0000000..2b32f9d
--- /dev/null
@@ -0,0 +1,25 @@
+I am moving some of the "settled" discussion here, I hope that is 
+appropriate. --[[DavidBremner]]
+
+  > I wonder if it would be more or less natural to put an encoded form
+    > of the page name in the email address? I'm thinking about something
+    > like `wikiname+index@host` or `wikiname+todo+comment_by_mail@host`.
+    > The basic transformation would be to call `titlepage($page)` (in the
+    > C locale), followed by replacing "/" with "+" (since "/" is not
+    > valid in mails). --[[Joey]]
+    >> I guess you are right, there is no point being more obscure 
+    >> than necessary.  I am leaning towards   [something](http://www.cs.unb.ca/~bremner/blog/posts/encoding) not        
+   >> calling titlepage but in the same spirit. --[[DavidBremner]]
+
+In response to the suggestion by Joey to process mailboxes into blogs
+>> One thing it made me think about is 
+>> how to encode reference (threading) information. One can of 
+>> course encode this into local-part, but I wonder if it would be 
+>> better to use header features of mailto (this could also be an 
+>> alternative to tagged mail addresses for page references).  
+>> Various client handling of mailto always seemed a bit fragile to 
+>> me but maybe I am just behind the times.  Most headers are ignored, but
+>> pseudo-headers in the body might work. For example: 
+>>[test](mailto:bremner@somewhere.ca?body=X-Iki-Page:%20test%0AX-Iki-thread:%20foobar).  I hesitate to use the subject because every mail admin in the 
+>> world seems to want to add things to the front of it. 
+>> -- [[DavidBremner]]
diff --git a/doc/todo/comments.mdwn b/doc/todo/comments.mdwn
new file mode 100644 (file)
index 0000000..7a113be
--- /dev/null
@@ -0,0 +1,170 @@
+# Known issues with the [[plugins/comments]] plugin
+
+## Unimplemented
+
+* Instead of just a link to add a comment, it could have a form to enter
+  the title, similar to the form for adding a new blog post.
+
+  > I'm not sure this is so useful? On Livejournal titles are allowed on
+  > comments, but very rarely used (and indeed usually not very useful);
+  > it's hard enough to get some people to title their blog posts :-)
+  > --[[smcv]]
+
+## Won't fix
+
+* Because IkiWiki generates static HTML, we can't have a form inlined in
+  page.tmpl where the user fills in an entire comment and can submit it in
+  a single button-press, without being vulnerable to cross-site request forgery.
+  So I'll put this in as wontfix. --[[smcv]]
+
+  > Surely there's a way around that?
+  > A web 2.0 way comes to mind: The user clicks on a link
+  > to open the comment post form. While the nasty web 2.0 javascript :)
+  > is manipulating the page to add the form to it, it looks at the cookie
+  > and uses that to insert a sid field.
+  > 
+  > Or, it could have a mandatory preview page and do the CSRF check then.
+  > --[[Joey]]
+
+* It would be useful to have a pagespec that always matches all comments on
+  pages matching a glob. Something like `comment(blog/*)`.
+  Perhaps postcomment could also be folded into this? Then the pagespec
+  would match both existing comments, as well as new comments that are
+  being posted.
+
+  > Please see [[plugins/comments/discussion]]. If I've convinced you that
+  > internal pages are the way forward, then sure, we can do that, because
+  > people who can comment still won't be able to edit others' comments
+  > (one of my goals is that commenters can't put words into each other's
+  > mouths :-) )
+  >
+  > On the other hand, if you still want me to switch this plugin to "real"
+  > pages, or if internal pages might become editable in future, then
+  > configuring lockedit/anonok so a user X can add comments to blog pages
+  > would also let X edit/delete comments on blog pages (including those
+  > written by others) in arbitrary ways, which doesn't seem good. --[[smcv]]
+
+  > I had a look at implementing comment() and fell afoul of
+  > some optimisations that assume only internal() will be used to match
+  > internal pages. So probably this isn't worth doing. --[[Joey]]
+
+## Done
+
+* There is some common code cargo-culted from other plugins (notably inline and editpage) which
+  should probably be shared
+
+  > Actually, there's less of this now than there used to be - a lot of simple
+  > things that were shared have become unshareable as they became more
+  > complex. --[[smcv]]
+
+  > There's still goto. You have a branch for that. --[[Joey]] 
+
+  >> Now merged --[[smcv]]
+
+* The default template should have a (?) icon next to unauthenticated users (with the IP address
+  as title) and an OpenID icon next to OpenIDs
+
+  > Done in my comments git branch, at least as a mockup (using the (?),
+  > {x} and {*} smileys for anonymous, OpenID and login respectively).
+  > --[[smcv]]
+
+  >> I've improved this to use independent icons from the wikiicons
+  >> directory (untested!) --[[smcv]]
+
+  >>> The new code produces links like /wikiisons/openid.png, which
+  >>> fail if ikiwiki is not at the root of the web server. --[[Joey]]
+
+  >>>> Sorry, I should have spotted that (the assumption failed on my demo
+  >>>> site, but the push to that site was when I was on the way out, so I
+  >>>> didn't have time to investigate). As a note for other ikiwiki hackers,
+  >>>> I should have used
+  >>>> `<img src="<TMPL_VAR NAME=BASEURL>wikiicons/openid.png" />`. --[[smcv]]
+
+  >>> I got to wondering if the icons are needed. On my comments branch
+  >>> (not master), I've dropped the icons and info can be seen by hovering
+  >>> over the author's name. Idea being that you probably don't care how
+  >>> they authenticated unless something is weird, and in that case you
+  >>> can hover to check. Does that make sense, should I merge it?
+  >>> --[[Joey]]
+
+  >>>> Yeah, go ahead. I preferred my layout with the author before the
+  >>>> comment - perhaps that's Livejournal's influence :-) - but I can always
+  >>>> edit the templates for my own site. As long as the default is something
+  >>>> reasonable and both layouts are possible, I don't really mind.
+  >>>> Minimizing the number of "resource" files in the basewiki also seems
+  >>>> a good goal. --[[smcv]]
+
+* Previews always say "unknown IP address"
+
+  > Fixed in my comments branch by commits bc66a00b and 95b3bbbf --[[smcv]]
+
+* The Comments link in the "toolbar" is to `index.html#comments`, not the
+  desired `./#comments`
+
+  > Fixed in my comments branch by commit 0844bd0b; commits 5b1cf21a
+  > and c42f174e fix another `beautify_urlpath` bug and add a regression test
+  > --[[smcv]]
+
+
+* Now that inline has some comments-specific functionality anyway, it would
+  be good to output `<link rel="comments">` in Atom and the equivalent in RSS.
+
+  > Fixed in my comments branch by d0d598e4, 3feebe31, 9e5f504e --[[smcv]]
+
+
+* Add `COMMENTOPENID`: the authenticated/verified user name, if and only if it was an OpenID
+
+  > Done in my comments git branch --[[smcv]]
+
+  > Not seeing it there, which branch? --[[Joey]]
+
+  >> Bah, git push --all is not the default... 'comments' branch now (I've also rebased it).
+  >> Sorry, I'm on mobile Internet at the moment... --[[smcv]]
+
+  >>> merged by [[Joey]] in commit 0f03af38 --[[smcv]]
+
+* Should the comments be visually set off more from the page above?
+  Rather than just a horizontal rule, I'm thinking put the comments
+  in a box like is used for inlined pages.
+
+  > I did put them in a box in the CSS... I agree the default template
+  > could do with visual improvement though. --[[smcv]]
+
+  >> I'll consider this solved by [[Joey]]'s changes. --[[smcv]]
+
+* One can use inline to set up a feed of all comments posted to any page.
+  Using template=comment they are displayed right. Only problem
+  is there is no indication in that template of what page each comment in the
+  feed is a comment on. So, if a comment is inlined into a different page,
+  I think it should show a link back to the page commented on.
+  (BTW, the rss feed in this situation seems ok; there the link element
+  points back to the parent page.
+
+  > done --[[Joey]]
+
+* One of Joey's commit messages says "Not ideal, it would be nicer to jump to
+  the actual comment posted, but no anchor is available". In fact there is
+  an anchor - the `\[[_comment]]` preprocessing wraps the comment in a `<div>`
+  with id="comment_123" or something. I'll fix this, unless Joey gets there
+  first. --[[smcv]]
+
+  > done --[[Joey]]
+
+* If a spammer posts a comment, it is either impossible or hard to clean
+  up via the web. Would be nice to have some kind of link on the comment
+  that allows trusted users to remove it (using the remove plugin of
+  course).
+
+  > Won't the remove plugin refuse to remove internal pages? This would be
+  > a good feature to have, though. --[[smcv]]
+
+  > Here, FWIW, is the first ikiwiki comment spam I've seen:
+  > <http://waldeneffect.org/blog/Snake_bite_information/#blog/Snake_bite_information/comment_1>
+  > So that took about 10 days...
+  > --[[Joey]] 
+
+  >> Implemented in my 'comments' branch, please review. It turns out
+  >> [[plugins/remove]] is happy to remove internal pages, so it was quite
+  >> easy to do. --[[smcv]]
+
+  >>> done --[[Joey]] 
index e5e23531ec88257fa5afa6e4c71792994e5920f3..0d0f66da417f42d4df2bbfc0192678590ff9ffc1 100644 (file)
@@ -1,6 +1,6 @@
 I'd like to see some way to conditionally include wiki text based on
 whether the wiki enables or disables certain features.  For example,
-[[ikiwiki/formatting]], could use `\[[if (enabled smiley) """Also, because
+[[ikiwiki/formatting]], could use `\[[!if (enabled smiley) """Also, because
 this wiki has the smiley plugin enabled, you can insert \[[smileys]] and
 some other useful symbols."""]]`, and a standard template for [[plugins]]
 pages could check for the given plugin name to print "enabled" or
@@ -25,7 +25,7 @@ include an `else` clause; if so, you could label the text used if true as
 `then`.
 
 Syntax could vary greatly here, both for the
-[[ikiwiki/PreprocessorDirective]] and for the condition itself.
+[[ikiwiki/Directive]] and for the condition itself.
 
 > I think this is a good thing to consider, although conditionals tend to
 > make everything a lot more complicated, so I also want to KISS, and not
@@ -52,12 +52,12 @@ Syntax could vary greatly here, both for the
 > As to the syntax, to fit it into standard preprocessor syntax, it would
 > need to look something like this:
 >
->      \[[if test="enabled(smiley)" """foo"""]]
+>      \[[!if test="enabled(smiley)" """foo"""]]
 > 
 > --[[Joey]]
 
 >> [[ikiwiki/PageSpec]] syntax seems perfect, and your proposed syntax for the `if`
->> [[ikiwiki/PreprocessorDirective]] looks fine to me.
+>> [[ikiwiki/Directive]] looks fine to me.
 >>
 >> [[ikiwiki/PageSpec]]s don't give you `none` for free, since `!foo/*` as a boolean
 >> would mean "does any page not matching `foo/*` exist", not "does `foo/*`
@@ -70,12 +70,12 @@ Syntax could vary greatly here, both for the
 >>
 >> A few use cases for `included`, which I would really like to see:
 >>
->> * On the sidebar page, you could say something like \[[if test="!included"
+>> * On the sidebar page, you could say something like \[[!if test="!included"
 >>   """This page, without this help message, appears as a sidebar on all
 >>   pages."""]].  The help text would then only appear on the sidebar page
 >>   itself, not the sidebar included on all pages.
 >>
->> * On [[ikiwiki/blog]] entries, you could use `included` to implement a cut.
+>> * On [[blog]] entries, you could use `included` to implement a cut.
 >>   (Please don't take that as an argument against. :) ) For instance, you
 >>   could use included rather than [[plugins/toggle]] for the detailed
 >>   changelogs of ikiwiki, or to embed an image as a link in the feed rather
@@ -106,3 +106,23 @@ This is now completely [[todo/done]]! See [[plugins/conditional]].
 --[[Joey]]
 
 > You rock mightily. --[[JoshTriplett]]
+
+Is there a way to test features other than plugins? For example,
+to add to [[ikiwiki/Markdown]] something like
+
+    \[[!if test="enabled(multimarkdown)" then="You can also use..."]]
+
+(I tried it like that just to see if it would work, but I wasn't that lucky.)
+--ChapmanFlack
+
+> No, not supported. I really think that trying to conditionalise text on a
+> page for multimarkdown is a path to madness or unreadability though.
+> Perhaps it would be better to have .mmdwn files that can only contain
+> multimarkdown? --[[Joey]]
+
+>> Really, there was only one (or maybe two) pages I had in mind as appropriate
+>> places for conditional text based on multimarkdown&mdash;the underlay pages
+>> for 'markdown' and maybe also 'formatting', because those are the pages you
+>> look at when you're trying to find out how to mark stuff up for the wiki, so
+>> if MM is enabled, they need to at least mention it and have a link to the
+>> MM syntax guide.--ChapmanFlack
index 14ab4dac3906d7e3d6ee23f4d46611c110163ffd..c578bceafacc96ff12f8d2816130ab6715adf61d 100644 (file)
@@ -12,7 +12,7 @@ I can see two good ways to implement this.  Ideally, with
 [[conditional_text_based_on_ikiwiki_features]] available, ikiwiki could
 parse a page like conditionalpages.mdwn, which could contain a set of
 conditional-wrapped page names; that seems like the most elegant and
-ikiwiki-like approach.  Alternatively, [[/ikiwiki.setup]] could contain a
+ikiwiki-like approach.  Alternatively, ikiwiki.setup could contain a
 Perl-generated exclude option by default; that would work, but it seems
 hackish.
 
index 3ed50503a61bd00c51e23d8e39bc23eff18f6bb4..f8b1dbbaba7bd57857c9767d6acb3e4ad10e6413 100644 (file)
@@ -3,3 +3,8 @@ It would be nice if the sure could set the timezone of the wiki, and have ikiwik
 This is nice for shared hosting, and other situation where the user doesn't have control over the server timezone.
 
 > [[done]] via the ENV setting in the setup file. --[[Joey]]
+
+
+Example (ikiwiki.setup):
+
+    ENV => { TZ => "Europe/Sofia" }
diff --git a/doc/todo/copyright_based_on_pagespec.mdwn b/doc/todo/copyright_based_on_pagespec.mdwn
new file mode 100644 (file)
index 0000000..f15ad4b
--- /dev/null
@@ -0,0 +1,10 @@
+I think the following would be useful.  Have a plugin (pagecopyright? dunno about the name), configured
+by an "association-list"
+<pre>
+copyright_alist=>[ "*/Discussion" => "Comments copyright individual authors",
+                   "*"=> "Copyright 2008 Widget Co" ]
+</pre>
+
+And yes, I know about [[plugins/contrib/default_content_for___42__copyright__42___and___42__license__42__]]
+
+[[DavidBremner]]
index 082f0800c6c84a926476e0f09f72960f300408ff..565f3b16c9a35a788dfc85c88f579591ddbcfa72 100644 (file)
@@ -110,4 +110,4 @@ Index: IkiWiki/Plugin/inline.pm
 
 [[done]] --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
index d75dcd93256ae597a74151003503fced116bec28..76708e0da154808615c1c9c6826dd0fdb86b2d98 100644 (file)
@@ -1,4 +1,4 @@
-[[Blog|ikiwiki/blog]] feeds and index pages show the posted time (ctime), the actual blog entry pages only show the modified time.
+[[Blog]] feeds and index pages show the posted time (ctime), the actual blog entry pages only show the modified time.
 
 The user has to look at the history link to find when a blog item was posted.
 
@@ -7,3 +7,5 @@ It would be nice if blog entry post pages could include the ctime. -- [[Edward_B
 > I've committed a change that adds a CTIME variable to page.tmpl. I left
 > it commented out in the default template, since it seems like a bit of
 > clutter to me. Good enough? --[[Joey]]
+
+[[done]]
index c31ce105c467c7ca06a17ed4a5f54e3c9f32494c..985ae5f8b8660c4d78af693c314b95685c60af2f 100644 (file)
-Here's Thomas Schwinge unfinished darcs support for ikiwiki.
-
-(Finishing this has been suggested as a [[soc]] project.)
-
-> I haven't been working on this for months and also won't in the near
-> future.  Feel free to use what I have done so
-> far and bring it into an usable state!  Also, feel free to contact me
->  if there are questions.
-
--- [Thomas Schwinge](mailto:tschwinge@gnu.org)
-
-[[toggle text="show"]]
-[[toggleable text="""
-       # Support for the darcs rcs, <URL:http://darcs.net/>.
-       # Copyright (C) 2006  Thomas Schwinge <tschwinge@gnu.org>
-       #
-       # This program is free software; you can redistribute it and/or modify it
-       # under the terms of the GNU General Public License as published by the
-       # Free Software Foundation; either version 2 of the License, or (at your
-       # option) any later version.
-       #
-       # This program is distributed in the hope that it will be useful, but
-       # WITHOUT ANY WARRANTY; without even the implied warranty of
-       # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-       # General Public License for more details.
-       #
-       # You should have received a copy of the GNU General Public License along
-       # with this program; if not, write to the Free Software Foundation, Inc.,
-       # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-       
-       
-       # We're guaranteed to be the only instance of ikiwiki running at a given
-       # time.  It is essential that only ikiwiki is working on a particular
-       # repository.  That means one instance of ikiwiki and it also means that
-       # you must not `darcs push' into this repository, as this might create
-       # race conditions, as I understand it.
-       
-       
-       use warnings;
-       use strict;
-       use IkiWiki;
-       
-       package IkiWiki;
-       
-       
-       # Which darcs executable to use.
-       my $darcs = ($ENV{DARCS} or 'darcs');
-       
-       
-       # Internal functions.
-       
-       sub darcs_info ($$$) {
-           my $field = shift;
-           my $repodir = shift;
-           my $file = shift; # Relative to the repodir.
-       
-           my $child = open(DARCS_CHANGES, "-|");
-           if (! $child) {
-               exec($darcs, 'changes', '--repo=' . $repodir, '--xml-output', $file) or
-                   error('failed to run `darcs changes\'');
-           }
-       
-           # Brute force for now.  :-/
-           while (<DARCS_CHANGES>) {
-               last if /^<\/created_as>$/;
-           }
-           ($_) = <DARCS_CHANGES> =~ /$field=\'([^\']+)/;
-           $field eq 'hash' and s/\.gz//; # Strip away the `.gz' from `hash'es.
-       
-           close(DARCS_CHANGES) or error('`darcs changes\' exited ' . $?);
-       
-           return $_;
-       }
-       
-       
-       # Exported functions.
-       
-       sub rcs_update () {
-           # Not needed.
-       }
-       
-       sub rcs_prepedit ($) {
-           # Prepares to edit a file under revision control.  Returns a token that
-           # must be passed to rcs_commit() when the file is to be commited.  For us,
-           # this token the hash value of the latest patch that modifies the file,
-           # i.e. something like its current revision.  If the file is not yet added
-           # to the repository, we return TODO: the empty string.
-       
-           my $file = shift; # Relative to the repodir.
-       
-           my $hash = darcs_info('hash', $config{srcdir}, $file);
-           return defined $hash ? $hash : "";
-       }
-       
-       sub rcs_commit ($$$) {
-           # Commit the page.  Returns `undef' on success and a version of the page
-           # with conflict markers on failure.
-       
-           my $file = shift; # Relative to the repodir.
-           my $message = shift;
-           my $rcstoken = shift;
-       
-           # Compute if the ``revision'' of $file changed.
-           my $changed = darcs_info('hash', $config{srcdir}, $file) ne $rcstoken;
-       
-           # Yes, the following is a bit convoluted.
-           if ($changed) {
-               # TODO.  Invent a better, non-conflicting name.
-               rename("$config{srcdir}/$file", "$config{srcdir}/$file.save") or
-                   error("failed to rename $file to $file.save: $!");
-       
-               # Roll the repository back to $rcstoken.
-       
-               # TODO.  Can we be sure that no changes are lost?  I think that
-               # we can, if we make sure that the `darcs push' below will always
-               # succeed.
-       
-               # We need to revert everything as `darcs obliterate' might choke
-               # otherwise.
-               # TODO: `yes | ...' needed?  Doesn't seem so.
-               system($darcs, "revert", "--repodir=" . $config{srcdir}, "--all") and
-                   error("`darcs revert' failed");
-               # Remove all patches starting at $rcstoken.
-               # TODO.  Something like `yes | darcs obliterate ...' seems to be needed.
-               system($darcs, "obliterate", "--quiet", "--repodir" . $config{srcdir},
-                      "--match", "hash " . $rcstoken) and
-                          error("`darcs obliterate' failed");
-               # Restore the $rcstoken one.
-               system($darcs, "pull", "--quiet", "--repodir=" . $config{srcdir},
-                      "--match", "hash " . $rcstoken, "--all") and
-                          error("`darcs pull' failed");
-       
-               # We're back at $rcstoken.  Re-install the modified file.
-               rename("$config{srcdir}/$file.save", "$config{srcdir}/$file") or
-                   error("failed to rename $file.save to $file: $!");
-           }
-       
-           # Record the changes.
-           # TODO: What if $message is empty?
-           writefile("$file.log", $config{srcdir}, $message);
-           system($darcs, 'record', '--repodir=' . $config{srcdir}, '--all',
-                  '--logfile=' . "$config{srcdir}/$file.log",
-                  '--author=' . 'web commit <web-hurd@gnu.org>', $file) and
-                      error('`darcs record\' failed');
-       
-           # Update the repository by pulling from the default repository, which is
-           # master repository.
-           system($darcs, "pull", "--quiet", "--repodir=" . $config{srcdir},
-                  "--all") and error("`darcs pull' failed\n");
-       
-           # If this updating yields any conflicts, we'll record them now to resolve
-           # them.  If nothing is recorded, there are no conflicts.
-           $rcstoken = darcs_info('hash', $config{srcdir}, $file);
-           # TODO: Use only the first line here, i.e. only the patch name?
-           writefile("$file.log", $config{srcdir}, 'resolve conflicts: ' . $message);
-           system($darcs, 'record', '--repodir=' . $config{srcdir}, '--all',
-                  '--logfile=' . "$config{srcdir}/$file.log",
-                  '--author=' . 'web commit <web-hurd@gnu.org>', $file) and
-                      error('`darcs record\' failed');
-           my $conflicts = darcs_info('hash', $config{srcdir}, $file) ne $rcstoken;
-           unlink("$config{srcdir}/$file.log") or
-               error("failed to remove `$file.log'");
-       
-           # Push the changes to the main repository.
-           system($darcs, 'push', '--quiet', '--repodir=' . $config{srcdir}, '--all')
-               and error('`darcs push\' failed');
-           # TODO: darcs send?
-       
-           if ($conflicts) {
-               my $document = readfile("$config{srcdir}/$file");
-               # Try to leave everything in a consistent state.
-               # TODO: `yes | ...' needed?  Doesn't seem so.
-               system($darcs, "revert", "--repodir=" . $config{srcdir}, "--all") and
-                   warn("`darcs revert' failed.\n");
-               return $document;
-           } else {
-               return undef;
-           }
-       }
-       
-       sub rcs_add ($) {
-           my $file = shift; # Relative to the repodir.
-       
-           # Intermediate directories will be added automagically.
-           system($darcs, 'add', '--quiet', '--repodir=' . $config{srcdir},
-                  '--boring', $file) and error('`darcs add\' failed');
-       }
-       
-       sub rcs_recentchanges ($) {
-           warn('rcs_recentchanges() is not implemented');
-           return 'rcs_recentchanges() is not implemented';
-       }
-       
-       sub rcs_notify () {
-           warn('rcs_notify() is not implemented');
-       }
-       
-       sub rcs_getctime () {
-           warn('rcs_getctime() is not implemented');
-       }
-       
-       1
-"""]]
-
-This is my ([bma](bma@bmalee.eu)) darcs.pm - it's messy (my Perl isn't up to much) but seems to work. It uses just one repo, like the mercurial plugin (unlike the above version, which AIUI uses two).
-
-`rcs_commit()` uses backticks instead of `system()`, to prevent darcs' output being sent to the browser and mucking with the HTTP headers (`darcs record` has no --quiet option). And `rcs_recentchanges()` uses regexes rather than parsing darcs' XML output.
-
-[[toggle text="show" id="bma"]]
-[[toggleable id="bma" text="""
-
-       #!/usr/bin/perl
-       
-       use warnings;
-       use strict;
-       use IkiWiki;
-       use Date::Parse;
-       use open qw{:utf8 :std};
-       
-       package IkiWiki;
-       
-       sub rcs_update () { #{{{
-               # Do nothing - there's nowhere to update *from*.
-       } #}}}
-       
-       sub rcs_prepedit ($) { #{{{
-       } #}}}
-       
-       sub rcs_commit ($$$;$$) { #{{{
-               my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
-       
-               # $user should probably be a name and an email address, by darcs
-               # convention.
-               if (defined $user) {
-                       $user = possibly_foolish_untaint($user);
-               }
-               elsif (defined $ipaddr) {
-                       $user = "Anonymous from $ipaddr";
-               }
-               else {
-                       $user = "Anonymous";
-               }
-       
-               $message = possibly_foolish_untaint($message);
-               
-               # BUG: this outputs one line of text, and there's not a -q or --quiet
-               # option. Redirecting output to /dev/null works, but I still get the
-               # HTTP status and location headers displayed in the browser - is that
-               # darcs' fault or ikiwiki's?
-               # Doing it in backticks *works*, but I'm sure it could be done better.
-               my @cmdline = ("darcs", "record", "--repodir", "$config{srcdir}",
-                              "-a", "-m", "$message", "--author", "$user", $file);
-               `darcs record --repodir "$config{srcdir}" -a -m "$message" --author "$user" $file`; # Return value? Output? Who needs 'em?
-               #if (system(@cmdline) != 0) {
-               #       warn "'@cmdline' failed: $!";
-               #}
-       
-               return undef; # success
-               
-       sub rcs_add ($) { # {{{
-               my ($file) = @_;
-       
-               my @cmdline = ("darcs", "add", "--repodir", "$config{srcdir}", "-a", "-q", "$file");
-               if (system(@cmdline) != 0) {
-                       warn "'@cmdline' failed: $!";
-               }
-       } #}}}
-       
-       sub rcs_recentchanges ($) { #{{{
-               # TODO: This is horrible code. It doesn't work perfectly, and uses regexes
-               # rather than parsing Darcs' XML output.
-               my $num=shift;
-               my @ret;
-               
-               return unless -d "$config{srcdir}/_darcs";
-       
-               my $changelog = `darcs changes --xml --summary --repodir "$config{srcdir}"`;
-               $changelog = join("", split(/\s*\n\s*/, $changelog));
-               my @changes = split(/<\/patch>.*?<patch/m, $changelog);
-       
-       
-               foreach my $change (@changes) {
-                       $change =~ m/hash='(.*?)'/;
-                       my $rev = $1;
-                       $change =~ m/author='(.*?)'/;
-                       my $user = $1."\n";
-                       my $committype = "web";
-                       if($user =~ m/&lt;/) {
-                               # Author fields generated by darcs include an email address: look for the "<".
-                               $committype = "darcs";
-                               use HTML::Entities;
-                               $user = decode_entities $user;
-                       }
-                       $change =~ m/local_date='(.*?)'/;
-                       my $when = $1;
-                       $when=time - str2time($when, 'UTC');
-                       $change =~ m/<name>(.*?)<\/name>/g;
-                       my @message = {line => $1};
-                       foreach my $match ($change =~ m/<comment>(.*?)<\/comment>/gm) {
-                               push @message, {line => $1};
-                       }
-
-                       my @pages;
-                       foreach my $match ($change =~ m/<.*?_(file|directory)>(.*?)(<(added|removed)_lines.*\/>)*<\/.*?_(file|directory)>/g) {
-                               # My perl-fu is weak. I'm probably going about this all wrong, anyway.
-                               push @pages, {page => pagename($match)} if ( -f $config{srcdir}."/".$match || -d $config{srcdir}."/".$match) and not $match =~ m/^$/;
-                       }
-                       push @ret, { rev => $rev,
-                                       user => $user,
-                                       committype => $committype,
-                                       when => $when,
-                                       message => [@message],
-                                       pages => [@pages],
-                               }
-               }
-               return @ret;
-       } #}}}
-       
-       sub rcs_notify () { #{{{
-               # TODO
-       } #}}}
-       
-       sub rcs_getctime ($) { #{{{
-               error gettext("getctime not implemented");
-       } #}}}
-       
-       1
-
-
-
-"""]]
-
----
-
-Well, here's my version too. It only does getctime -- using a real XML parser, instead of regexp ugliness -- and maybe recentchanges, but that may be bitrotted, or maybe I never finished it, as I only need the getctime. As for actual commits, I have previously voiced my opinion, that this should be done by the plugin generating a patch bundle, and forwarding it to darcs in some way (`darcs apply` or even email to another host, possibly moderated), instead of the hacky direct modification of a working copy. It could also be faster to getctime in a batch. Just reading in all the changes the first time they're needed, might not be a big improvement in many cases, but if we got a batch request from ikiwiki, we could keep reaing the changes until all the files in this batch request have been met.  --[[tuomov]]
-
-[[toggle text="show" id="tuomov"]]
-[[toggleable id="tuomov" text="""
-<pre>
-#!/usr/bin/perl
-# Stubs for no revision control.
-
-use warnings;
-use strict;
-use IkiWiki;
-
-package IkiWiki;
-
-sub rcs_update () {
-}
-
-sub rcs_prepedit ($) {
-       return ""
-}
-
-sub rcs_commit ($$$) {
-       return undef # success
-}
-
-sub rcs_add ($) {
-}
-
-sub rcs_recentchanges ($) {
-       my $num=shift;
-       my @ret;
-       
-       eval q{use Date::Parse};
-       eval q{use XML::Simple};
-       
-       my $repodir=$config{srcdir};
-       
-       if (-d "$config{srcdir}/_darcs") {
-               my $child = open(LOG, "-|");
-               if (! $child) {
-                       exec("darcs", "changes", "--xml", 
-                            "--repodir", "$repodir",
-                            "--last", "$num")
-                       || error("darcs changes failed to run");
-               }
-               my $data=<LOG>;
-               close LOG;
-               
-               my $log = XMLin($data, ForceArray => 1);
-               
-               foreach my $patch ($log->{patch}) {
-                       my $date=$patch->{local_date};
-                       my $hash=$patch->{hash};
-                       my $when=concise(ago(time - str2time($date)));
-                       my @pages;
-                       
-                       my $child = open(SUMMARY, "-|");
-                       if (! $child) {
-                               exec("darcs", "annotate", "-s", "--xml", 
-                                    "--match", "hash: $hash",
-                                    "--repodir", "$repodir")
-                               || error("darcs annotate failed to run");
-                       }
-                       my $data=<SUMMARY>;
-                       close SUMMARY;
-               
-                       my $summary = XMLin("<lame>$data</lame>", ForceArray => 1);
-
-                       # TODO: find @pages
-                       
-                       push @ret, {
-                               #rev => $rev,
-                               user => $patch->{author},
-                               #committype => $committype,
-                               when => $when, 
-                               #message => [@message],
-                               pages => [@pages],
-                       }; # if @pages;
-                       return @ret if @ret >= $num;
-               }
-       }
-       
-       return @ret;
-}
-
-sub rcs_notify () {
-}
-
-sub rcs_getctime ($) {
-       my $file=shift;
-       
-       eval q{use Date::Parse};
-       eval q{use XML::Simple};
-       local $/=undef;
-       
-       # Sigh... doing things the hard way again
-       my $repodir=$config{srcdir};
-       
-       my $filer=substr($file, length($repodir));
-       $filer =~ s:^[/]+::;
-       
-       my $child = open(LOG, "-|");
-       if (! $child) {
-               exec("darcs", "changes", "--xml", "--reverse",
-                    "--repodir", "$repodir", "$filer")
-               || error("darcs changes $filer failed to run");
-       }
-       
-       my $data=<LOG>;
-       close LOG;
-       
-       my $log = XMLin($data, ForceArray => 1);
-       
-       my $datestr=$log->{patch}[0]->{local_date};
-       
-       if (! defined $datestr) {
-               warn "failed to get ctime for $filer";
-               return 0;
-       }
-       
-       my $date=str2time($datestr);
-       
-       debug("found ctime ".localtime($date)." for $file");
-       
-       return $date;
-}
-
-1
-</pre>
-"""]]
-
----
-
-I merged the two versions above and made some fixes; it is recording my web edits in darcs and showing a recent changes page.
-It is in a [darcs repository](http://joyful.com/darcsweb/darcsweb.cgi?r=ikiwiki-darcs), please send patches. --[[Simon_Michael]]
-
-> I'd like to see at least the following fixed before I commit this: --[[Joey]]
-> * Running `darcs record $filename` in backticks is not good (security)
->   The thing to do is to open stdout to /dev/null before execing darcs.
-> * Get `rcs_recentchanges_xml` working, parsing xml with regexps does
->   not seem like a maintenance win.
-> * `rcs_notify` should be removed, it's no longer used.
-> * Some form of conflict handling. Using darcs to attempt to merge
->   the changes is I gusss optional (although every other rcs backend,
->   including svn manages to do this), but it needs to at *least* detect
->   conflicts and return a page with conflict markers for the user to fix
->   the conflict.
-
-[[tag patch]]
+<http://khjk.org/~pesco/ikiwiki-darcs/> (now a darcs repo)
+
+I've taken all the good stuff from the above (now deleted --[[Joey]]) and added the missing hooks. The code hasn't seen a lot of testing, so some bugs are likely yet to surface. Also, I'm not experienced with perl and don't know where I should have used the function `possibly_foolish_untaint`.
+
+> Review of this one:
+> 
+> * Should use tab indentation. (fixed)
+> * `rcs_getctime` should not need to use a ctime cache (such a cache should 
+>   also not be named `.ikiwiki.ctimes`). `rcs_getctime` is run exactly
+>   once per page, ever, and the data is cached in ikiwiki's index. (fixed)
+> * I doubt that ENV{DARCS} will be available, since the wrapper clobbers> the entire
+>   environment. I'd say remove that. (fixed)
+> * I don't understand what `darcs_info` is doing, but it seems to be
+>   parsing xml with a regexp?
+> * Looks like `rcs_commit` needs a few improvements, as marked TODO
+> * `rcs_remove` just calls unlink? Does darcs record notice the file was removed
+>    and automatically commit the removal?
+> * Is the the darcs info in [[rcs/details]] still up-to-date re this version? (fixed)
+> --[[Joey]]
+
+> Update:
+>
+> I think I've addressed all of the above except for the XML parsing in `darcs_info`.
+> The function determines the md5 hash of the last patch the given file appears in.
+> That's indeed being done with regexps but my Perl isn't good enough for a quick recode
+> right now.
+>
+> As for the darcs info in [[rcs/details]], it does not accurately describe the way
+> this version works. It's similar, but the details differ slightly.
+> You could copy my description above to replace it.
+>
+>> done --[[Joey]] 
+> 
+> There is still some ironing to do, for instance the current version doesn't allow for
+> modifying attachments by re-uploading them via CGI ("darcs add failed"). Am I assuming
+> correctly that "adding" a file that's already in the repo should just be a no-op?
+> --pesco
+
+>> It should result in the new file contents being committed by
+>> `rcs_commit_staged`. For some revision control systems, which
+>> automatically commit modifications, it would be a no-op. --[[Joey]]
+
+>>> Done. --pesco
+
+----
+
+I've finally merged this into ikiwiki master. The plugin looks quite
+complete, with only the new `rcs_receive` hook missing, and I
+hope it works as good as it looks. :) If anyone wants to work on improving
+it, there are some TODOs as mentioned above that could still be improved.
+--[[Joey]] 
+
+[[!tag patch done]]
index 4264b5895d32621cb79d0e179a6f1c0a1d8d2fb2..5f33cde4ce1ec824f3f15366635088ccda21a8ca 100644 (file)
@@ -17,11 +17,11 @@ Index: IkiWiki/Plugin/datearchives.pm
 +use strict;
 +use IkiWiki;
 +
-+sub import { #{{{
++sub import {
 +    hook(type => "pagetemplate", id => "datearchives", call => \&pagetemplate, scan => 1);
-+} # }}}
++}
 +
-+sub pagetemplate (@) { #{{{
++sub pagetemplate (@) {
 +    my %args = @_;
 +    my $dt;
 +    eval {
@@ -37,7 +37,7 @@ Index: IkiWiki/Plugin/datearchives.pm
 +        $template->param(ctime => htmllink( $args{page}, $args{destpage}, $link, 0, 0,
 +                                            $template->param('ctime')));
 +       }
-+} # }}}
++}
 +
 +1
 </pre>
@@ -74,4 +74,4 @@ created and populated with the relevant posts. A [[ikiwiki/Pagespec]] works perf
 >>> might move it to the contributed plugins directory as it's a bit
 >>> specialised to be included in ikiwiki though. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
index 2f309dea56e665433e55330ffb0f007e216776a2..9d0fc92c9f891699175f3afe0dbbf4f92b9b9ba8 100644 (file)
@@ -126,7 +126,7 @@ Index: IkiWiki/Plugin/search.pm
 +  $PLUCENE_DIR = $config{wikistatedir}.'/plucene';  
 +}
 +
- sub import { #{{{
+ sub import {
 -       hook(type => "getopt", id => "hyperestraier",
 -               call => \&amp;getopt);
 -       hook(type => "checkconfig", id => "hyperestraier",
@@ -142,14 +142,14 @@ Index: IkiWiki/Plugin/search.pm
                 call => \&amp;change);
 -       hook(type => "cgi", id => "hyperestraier",
 -               call => \&amp;cgi);
- } # }}}
+ }
  
--sub getopt () { #{{{
+-sub getopt () {
 -        eval q{use Getopt::Long};
 -       error($@) if $@;
 -        Getopt::Long::Configure('pass_through');
 -        GetOptions("estseek=s" => \$config{estseek});
--} #}}}
+-}
  
 +sub writer {
 +  init();
@@ -165,20 +165,20 @@ Index: IkiWiki/Plugin/search.pm
 +    grep { defined pagetype($_) } @_;
 +}
 +
- sub checkconfig () { #{{{
+ sub checkconfig () {
         foreach my $required (qw(url cgiurl)) {
                 if (! length $config{$required}) {
 @@ -36,112 +58,55 @@
         }
- } #}}}
+ }
  
 -my $form;
--sub pagetemplate (@) { #{{{
+-sub pagetemplate (@) {
 -       my %params=@_;
 -       my $page=$params{page};
 -       my $template=$params{template};
 +#my $form;
-+#sub pagetemplate (@) { #{{{
++#sub pagetemplate (@) {
 +#      my %params=@_;
 +#      my $page=$params{page};
 +#      my $template=$params{template};
@@ -193,7 +193,7 @@ Index: IkiWiki/Plugin/search.pm
 +#
 +#              $template->param(searchform => $form);
 +#      }
-+#} #}}}
++#}
  
 -       # Add search box to page header.
 -       if ($template->query(name => "searchform")) {
@@ -205,9 +205,9 @@ Index: IkiWiki/Plugin/search.pm
 -
 -               $template->param(searchform => $form);
 -       }
--} #}}}
+-}
 -
- sub delete (@) { #{{{
+ sub delete (@) {
 -       debug(gettext("cleaning hyperestraier search index"));
 -       estcmd("purge -cl");
 -       estcfg();
@@ -219,9 +219,9 @@ Index: IkiWiki/Plugin/search.pm
 +    $reader->delete_term( Plucene::Index::Term->new({ field => "id", text => $_ }));
 +  }
 +  $reader->close;
- } #}}}
+ }
  
- sub change (@) { #{{{
+ sub change (@) {
 -       debug(gettext("updating hyperestraier search index"));
 -       estcmd("gather -cm -bc -cl -sd",
 -               map {
@@ -250,9 +250,9 @@ Index: IkiWiki/Plugin/search.pm
 +    $doc->add(Plucene::Document::Field->UnStored('text' => $data));
 +    $writer->add_document($doc);
 +  }
- } #}}}
+ }
 -
--sub cgi ($) { #{{{
+-sub cgi ($) {
 -       my $cgi=shift;
 -
 -       if (defined $cgi->param('phrase') || defined $cgi->param("navi")) {
@@ -260,10 +260,10 @@ Index: IkiWiki/Plugin/search.pm
 -               chdir("$config{wikistatedir}/hyperestraier") || error("chdir: $!");
 -               exec("./".IkiWiki::basename($config{cgiurl})) || error("estseek.cgi failed");
 -       }
--} #}}}
+-}
 -
 -my $configured=0;
--sub estcfg () { #{{{
+-sub estcfg () {
 -       return if $configured;
 -       $configured=1;
 -
@@ -301,9 +301,9 @@ Index: IkiWiki/Plugin/search.pm
 -       unlink($cgi);
 -       my $estseek = defined $config{estseek} ? $config{estseek} : '/usr/lib/estraier/estseek.cgi';
 -       symlink($estseek, $cgi) || error("symlink $estseek $cgi: $!");
--} # }}}
+-}
 -
--sub estcmd ($;@) { #{{{
+-sub estcmd ($;@) {
 -       my @params=split(' ', shift);
 -       push @params, "-cl", "$config{wikistatedir}/hyperestraier";
 -       if (@_) {
@@ -323,7 +323,7 @@ Index: IkiWiki/Plugin/search.pm
 -               open(STDOUT, "/dev/null"); # shut it up (closing won't work)
 -               exec("estcmd", @params) || error("can't run estcmd");
 -       }
--} #}}}
+-}
 -
 -1
 +1;
diff --git a/doc/todo/directive_docs.mdwn b/doc/todo/directive_docs.mdwn
new file mode 100644 (file)
index 0000000..2baa61b
--- /dev/null
@@ -0,0 +1,79 @@
+The current basewiki is not [[self-documenting|todo/basewiki_should_be_self_documenting]]. In particular, if
+[[plugins/listdirectives]] is used, it creates a list with a bunch of
+broken links to directives/*, pages that do not currently exist in the
+docwiki or basewiki.
+
+This could be fixed by adding a page for each directive under to
+`ikiwiki/directives`, and put those into a new underlay, which the plugin
+could enable. Rather a lot of work and maintenance to document all the
+directives like that.
+
+I also considered having it link to the plugin that defined the
+directive. Then all the plugins can be included in a new underlay, which
+both [[plugins/listdirectives]] and [[plugins/websetup]] could enable.
+(The latter could be improved by making the plugin names in the web setup
+be links to docs about each plugin..) 
+
+The problem I ran into doing that is that the existing plugin pages have a
+lot of stuff on them you probably don't want an underlay doing. The biggest
+issues were wikilinks to other pages in the docwiki (which would end up
+broken if the plugins were used as an underlay), and plugin pages that
+include examples of the plugin in use, which are sometimes rather expensive
+(eg, brokenlinks).
+
+Either way requires a lot of reorganisation/doc work, and an onging
+maintenance load.
+
+> Which has now been [[done]].  -- [[Will]]
+
+BTW, this patch would be needed for the second approach, to allow
+listdirectives to map from preprocessor directives back to the plugin that
+defined them:  --[[Joey]]
+
+    commit 0486b46a629cae19ce89492d5ac498bbf9b84f5f
+    Author: Joey Hess <joey@kodama.kitenet.net>
+    Date:   Mon Aug 25 15:38:51 2008 -0400
+    
+        record which plugins registered which hooks
+    
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index e476521..afe982a 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -493,6 +493,7 @@ sub loadplugins () {
+       return 1;
+     }
+     
+    +my $loading_plugin;
+     sub loadplugin ($) {
+       my $plugin=shift;
+     
+    @@ -502,14 +503,18 @@ sub loadplugin ($) {
+                        "$installdir/lib/ikiwiki") {
+               if (defined $dir && -x "$dir/plugins/$plugin") {
+                       require IkiWiki::Plugin::external;
+    +                  $loading_plugin=$plugin;
+                       import IkiWiki::Plugin::external "$dir/plugins/$plugin";
+    +                  $loading_plugin=undef;
+                       $loaded_plugins{$plugin}=1;
+                       return 1;
+               }
+       }
+     
+       my $mod="IkiWiki::Plugin::".possibly_foolish_untaint($plugin);
+    +  $loading_plugin=$plugin;
+       eval qq{use $mod};
+    +  $loading_plugin=undef;
+       if ($@) {
+               error("Failed to load plugin $mod: $@");
+       }
+    @@ -1429,6 +1434,9 @@ sub hook (@) {
+     
+       return if $param{no_override} && exists $hooks{$param{type}}{$param{id}};
+       
+    +  # Record which plugin was being loaded when the hook was defined.
+    +  $param{plugin}=$loading_plugin if defined $loading_plugin;
+    +
+       $hooks{$param{type}}{$param{id}}=\%param;
+       return 1;
+     }
index 577ced17d1edf538bd3ca54cd853d76176a7216b..990b7ddb3774980fbb081bf496c46fd85869e253 100644 (file)
@@ -30,4 +30,4 @@ I don't think that the nesting is very clear, I found it confusing..
 
 Would each page be its own individual blog? Or its own blog post? To me it seems like an entire wiki can be viewed as a blog, with threaded or unthreaded comments underneath.
 
-[[tag soc]]
+[[!tag soc done]]
index 10f7a066fdce972d6f64902b81fbe22653a4081d..c95fb0e20ecabdba5e98f409f01a141d5af745e7 100644 (file)
@@ -1 +1 @@
-[[inline pages="sandbox/castle/discussion/* and !sandbox/castle/discussion/*/*" rootpage="sandbox/castle/discussion"]]
\ No newline at end of file
+[[!inline pages="sandbox/castle/discussion/* and !sandbox/castle/discussion/*/*" rootpage="sandbox/castle/discussion"]]
\ No newline at end of file
index 65672f14ea93f7ab4d89ab14410df4c9104c31a9..48ca72a9cf177d66b0b36f7d21f5a2c7cce1cd75 100644 (file)
@@ -1,3 +1,3 @@
 I don't like foo. Have you tried living without foo?
 
-[[inline pages="sandbox/castle/discussion/Don__39__t_like_foo/*" rootpage="sandbox/castle/discussion/Don__39__t_like_foo"]]
\ No newline at end of file
+[[!inline pages="sandbox/castle/discussion/Don__39__t_like_foo/*" rootpage="sandbox/castle/discussion/Don__39__t_like_foo"]]
\ No newline at end of file
index 0ad5656a0b8dd4452d02d593240c3092bb149a13..7fcbe44b6d4c6e008686b1cdb3d0bdaa25ffbc93 100644 (file)
@@ -1,3 +1,3 @@
 recently fixed [[TODO]] items
 
-[[inline pages="link(todo/done) and !todo and !*/Discussion" sort=mtime show=10]]
+[[!inline pages="link(todo/done) and !todo and !*/Discussion" sort=mtime show=10 archive=yes]]
index ae31c1603a2aaf4814ceaa931aed7ff6900eafb6..4625da904a4c53331efde5ab85482fc993769716 100644 (file)
@@ -1,4 +1,4 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 Given that ikiwiki has a suggested use as a tool for developers, I was thinking it might be cool if ikiwiki had [Doxygen](http://www.doxygen.org/) support.  I'm not exactly sure how the integration would work.  Something along the lines of a plugin to support .dox files would be my first thought.  I'd leave generating the documentation from any source files for a separate run of Doxygen - it'd be easier and you probably don't want the source being edited over the web.
 
index fa0e23254fcf24fab1a625417ffb4fdc4e5ec31e..3c39484bc477da6cb9e45e70c2bec24606c8f8a4 100644 (file)
@@ -23,3 +23,13 @@ What's your opinion, Joey? I hope it's also useful for another ikiwiki lovers :)
 >>> Seems like a job for good ol' string interpolation.  rootpage="post/$current_year/$current_month/$current_day"
 >>> Ikiwiki could provide some vars, and it would be nice to write plugins to also provide vars.  Sort of like templates.
 >>> Does that feel OK? --[[sabr]]
+
+> I want the exact same thing.  My compromise was to create a `datedblog` module which overrides `inline`'s `sessioncgi` hook
+> with something that sets the new page name to `%Y-%m-%d.$page` and sets up a meta directive at the beginning of
+> the content, with the title you wanted.  Now if you use the `datedblog` module, you get dated blog entries.  But I'd
+> like to have traditional `inline` functionality too.  This would work great if there were a way to change the `do`
+> parameter in the `blogpost` template's form; if I could change it to `datedblog` instead of `blog` then I could hook
+> my datedblog module in nicely, without having to override anything.  What would be the right way to do that? --[[neale]]
+
+> This is basically the same request as
+> [[todo/inline_postform_autotitles]]. --[[smcv]]
diff --git a/doc/todo/edit_form:_no_fixed_size_for_textarea.mdwn b/doc/todo/edit_form:_no_fixed_size_for_textarea.mdwn
new file mode 100644 (file)
index 0000000..4c9c235
--- /dev/null
@@ -0,0 +1,34 @@
+At the moment the text area in the edit form has a fixed size of 20 rows.
+
+On longer pages its not very comfortable to edit pages with such a small box. The whole screen size should be used instead([example](http://img3.imagebanana.com/img/bl10u9mb/editingtodo_1241804460828.png)).
+
+> The whole screen width is used, via the following
+> from style.css:
+>
+>      {
+>       width: 100%;
+>      }
+>
+> Perhaps you have replaced it with a modified style sheet that does not
+> include that? --[[Joey]] [[!tag done]]
+
+>> The screen shot was made with http://ikiwiki.info/ where i didn't change anything. The width is optimally used. The problem is the height.
+
+>>> You confused me by talking about rows...  
+>>> I don't know how to allow CSS to resize a textarea
+>>> to the full browser height. The obvious `height: 75%;`
+>>> does not work, at least in firefox and epiphany.
+>>> 
+>>> Ah, of course, if it did work, it'd make it be 75% of
+>>> the full *page* height, and not the browser window height.
+>>>
+>>> According to
+>>> [this page](http://stackoverflow.com/questions/632983/css-height-if-textarea-as-a-percentage-of-the-viewport-height):
+>>>>>50% of what? Parent says ‘auto’, which means base it on the height of the child content. Which depends on the height on the parent. Argh! etc.
+>>>>>
+>>>>>So you have to give its parent a percentage height. And the parent's parent, all the way up to the root.
+>>> So, other than a javascript-based resizer, some very tricky and invasive CSS
+>>> seems to be needed. Please someone let me know if you succeed in doing that.
+>>> --[[Joey]] 
+
+>>>>>> the javascript approach would need to work something like this: you need to know about the "bottom-most" item on the edit page, and get a handle for that object in the DOM. You can then obtain the absolute position height-wise of this element and the absolute position of the bottom of the window to determine the pixel-difference. Then, you set the height of the textarea to (current height in px) + determined-value. This needs to be re-triggered on various resize events, at least for the window and probably for other elements too. I may have a stab at this at some point. -- [[Jon]]
diff --git a/doc/todo/else_parameter_for_map_plugin.mdwn b/doc/todo/else_parameter_for_map_plugin.mdwn
new file mode 100644 (file)
index 0000000..981e50d
--- /dev/null
@@ -0,0 +1,56 @@
+[[!tag patch done]]
+
+[[plugins/map]] (and I) could benefit from a bonus parameter:
+
+       else="Display this if no page matches the PageSpec"
+
+This was quite simple, so I implemented this (branch "map" in my
+ikiwiki repo, see my user page for the up-to-date URL). Not patched the
+documentation yet, I'm waiting for feedback first, but I'll do it for sure. -- [[intrigeri]]
+
+> Can't a [[plugins/conditional]] be for this?
+> --[[Joey]]
+
+>> Hmmm, what do you mean? Adding a syntax such as the one below?
+>> Or something else?
+
+        \[[!if test="map(" then="..." else="..."]]
+
+>> What would you write in the `then` clause?
+>> I'm not opposed at all to rewrite my two-liner, but I don't understand.
+>> --[[intrigeri]]
+
+       \[[!if  test="foo/*" then="""
+       [[!map pages="foo/*"]]
+       """ else="no pages"]]
+
+--[[Joey]]
+
+>>> I'm not convinced: the syntax you're proposing implies to duplicate
+>>> the pagespec (once in the test clause, and once in the map query), which I find
+>>> not only inelegant, which I can live with, but also tiring and unpractical:
+>>> my `else` suggestion
+>>> finds its roots in map queries with rather long pagespecs. On the other
+>>> hand, if I'm the only one using map in such a way, I can live with this
+>>> heavy duplicated syntax without bloating the map plugin with features
+>>> no-one but me needs. On the other other hand, the patch is a 3-liner.
+>>> I'm not fixed yet, I'll think about it. --[[intrigeri]]
+
+>>>> Write a [[plugins/template]] which accepts a pagespec and an
+>>>> "else" clause, and then you won't have to duplicate the
+>>>> pagespec. --[[JoshTriplett]]
+
+>>>> Yeah, the patch is obviously very simple. My problem with it really is
+>>>> that there would seem to be several other places in ikiwiki where
+>>>> someone might want to be able to handle an "else" case where a
+>>>> pagespec expands to nothing. And adding else cases for all of them
+>>>> could be a bit much. --[[Joey]]
+
+>>>>> Agreed, and tagging as done. For the record, here is the [[plugins/template]] I use:
+
+        \[[!if test="<TMPL_VAR raw_pages>"
+        then="""<TMPL_VAR intro>
+        [[!map pages="<TMPL_VAR raw_pages>"]]"""
+        else="<TMPL_VAR else>"]]
+
+>>>>> --[[intrigeri]]
index 4d377d3f66cb0605ef51c5809fb65f121ed575da..e302a49ed1a75dfefd6c7dd3f8b5de9c68310c71 100644 (file)
@@ -5,14 +5,14 @@
     @@ -26,7 +26,7 @@
      memoize("file_pruned");
      
-     sub defaultconfig () { #{{{
+     sub defaultconfig () {
     -       wiki_file_prune_regexps => [qr/\.\./, qr/^\./, qr/\/\./,
     +       wiki_file_prune_regexps => [qr/\.\./, qr/^\.(?!htaccess)/, qr/\/\.(?!htaccess)/,
                     qr/\.x?html?$/, qr/\.ikiwiki-new$/,
                     qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//],
            wiki_link_regexp => qr/\[\[(?:([^\]\|]+)\|)?([^\s\]#]+)(?:#([^\s\]]+))?\]\]/,
 
-[[tag patch]]
+[[!tag patch patch/core]]
 
 This lets the site administrator have a `.htaccess` file in their underlay
 directory, say, then get it copied over when the wiki is built. Without
@@ -37,7 +37,14 @@ Hi, I would like to have my htaccess files in svn repository so ikiwiki would ex
 That way I have revision control on that file too. That may be a security concern, but I trust everybody that has svn commit
 access and such .htaccess files should not be accessible through wiki cgi. Of course, it could default to 'off'.
 
-> See [[debbug 447267]] for a patch for this.
+> See [[!debbug 447267]] for a patch for this.
+
+>> It looks to me as though this functionality won't be included in ikiwiki
+>> unless someone who wants it takes responsibility for updating the patch
+>> from that Debian bug to be applicable to current versions, so that there's a
+>> setup file parameter for extra filenames to allow, defaulting to none
+>> (i.e. a less simplistic patch than the one at the top of this page).
+>> Joey, is this an accurate summary? --[[smcv]]
 
 ---
 
@@ -47,4 +54,8 @@ but I use ikiwiki with a very small group of people collaborating so svn/web acc
 and htaccess is for limiting access to some areas of wiki.   
 It should be off by default of course. --Max
 
-[[tag patch]]
+---
++1 I want `.htaccess` so I can rewrite some old Wordpress URLs to make feeds work again. --[[hendry]]
+
+---
++1 for various purposes (but sometimes the filename isn't `.htaccess`, so please make it configurable) --[[schmonz]]
diff --git a/doc/todo/fastcgi_or_modperl_installation_instructions.mdwn b/doc/todo/fastcgi_or_modperl_installation_instructions.mdwn
new file mode 100644 (file)
index 0000000..74dcaeb
--- /dev/null
@@ -0,0 +1,12 @@
+There has got to be a way to run the CGI wrapper under fastcgi or modperl (apache 2). Are there easy to follow instructions describing how to set this up?
+
+> AFAIK noone has done this. One immediate problem would be permissions;
+> the CGI wrapper runs setuid to you so it can write to the wiki -- if
+> running in fastcgi/modperl I guess it would run as the web server, unless
+> there's some way to control that. So you'd need to set up the perms
+> differenly, to let the web server commit changes to the wiki.
+> 
+> I've not looked at what code changes fastcgi or modperl would require in
+> ikiwiki. --[[Joey]]
+
+[[!tag wishlist]]
index 9a9106229d4f2f0943c8067cd556cbe49e9f3b34..8c9b18b19976a927ddd32a732cb0444508aaf036 100644 (file)
@@ -60,4 +60,4 @@ pagespec lock like the above prevents an edit or upload from happening,
 ikiwiki could display a reasonable message to the user, indicating what
 they've done wrong.)
 
-[[tag soc done]]
+[[!tag soc done]]
index 1ce52f0ca128922d54b247420548895da8012424..f85a956dbc65e4a771de4da50d3be83f03b5f976 100644 (file)
@@ -29,7 +29,7 @@ For images, videos, etc. it would be nice to have some kind of meta data file to
 height, compression, etc. which could be initially created by 'ikiwiki --generate-meta-stuff'. 
 Then PageSpec should be
 teached to use these. Galleries could then be generated by means of
-\[[inline pages="type(image/*) and year(2007)" template="gallery"]].  It
+\[[!inline pages="type(image/*) and year(2007)" template="gallery"]].  It
 should of course be possible to edit this information via ikiwiki.cgi and with any
 text editor (Name: value). This should also allow for creations of default .html pages with
 the image/video/file/... and a discussion page. Probably named image.mdwn and image/discussion.
index a8d34eadacb3c1ca1d26e6ede980f500dd74cea7..c7553f7dd2b8f368b5a1842cec10494f816a62a7 100644 (file)
@@ -1,3 +1,5 @@
+Reopening this for 3.0, to consider adding new functions.
+
 I don't want this interface to be too firm; it's ok for a plugin like
 `ddate` to redefine an internal function like IkiWiki::displaytime if it
 wants to.. But plugins that still access stuff through IkiWiki:: should be
@@ -5,38 +7,90 @@ aware that that stuff can change at any time and break them. Possibly without
 perl's type checking catching the breakage, in some cases. Plugins that
 only use exported symbols should not be broken by future ikiwiki changes.
 
-Functions used by only some plugins, undecided about exporting:
-
-* lockwiki, unlockwiki (aggregate)
-       Too internal to ever be exported.
-* loadindex (aggregate)
-       Too internal to ever be exported.
-* titlepage (aggregate)
-       Not until more than one thing uses it.
-* basename (polygen, inline, search, polygen)
-* dirname (linkmap, inline)
-       For basename and dirname, they could just use standard perl library
-       stuff. Howevever, ikiwiki's versions are slightly different and I'd
-       need to check if the standard versions work for the uses made in
-       these plugins. Inclined not to export.
-* abs2rel (linkmap, inline)
-       This *is* the library version, just optimised to work around a bug.
-       Don't export this.
-* possibly_foolish_untaint (aggregate, polygen)
-       Probably better to implement yourself.
-* htmlize
-* linkify
-* preprocess
-* filter
-       The 4 above are used by a few plugins, but problimatic since plugins 
-       typically also define functions with these names.. I also feel that
-       this part of ikiwiki needs some more work before it's set in stone.
-       These are always called together, in the same order, though
-       sometimes htmlize isn't included.
-
-Variables used by plugins but not exported yet:
+## Most often used functions, by number of calls from plugin code
+
+     27 IkiWiki::possibly_foolish_untaint
+
+Not very happy about exporting, it's not ikiwiki-specific,
+and plugins that need to untaint things should think about it, hard.
+
+     12 IkiWiki::userinfo_get
+      5 IkiWiki::userinfo_set
+
+Used by only 4 plugins, all of which are fairly core, so thinking
+don't export.
+
+     11 IkiWiki::preprocess
+      8 IkiWiki::filter
+      4 IkiWiki::linkify
+      4 IkiWiki::htmlize
+
+The page rendering chain. Note that it's very common to call `preprocess(filter(text))`,
+or `htmlize(linkify(preprocess(filter(text))))`, while `htmlize(linkify(preprocess(text))`
+is called less frequently, and it's also not unheard of to leave out a step and do
+`htmlize(preprocess(text))`. (I haven't checked if any of those cases are bugs.)
+
+It would be nice if the api could avoid exposing the details of the render chain,
+by providing a way to say "I have filtered text, and would like html", or "I have raw
+text and would like to get it up to the preprocess stage".
+
+Another problimatic thing is plugins often define functions named 'preprocess', etc.
+
+     12 IkiWiki::linkpage
+     11 IkiWiki::pagetitle
+      6 IkiWiki::titlepage
+
+These go together; linkpage is needed by all link plugins, and the others are used widely.
+All should be exported. (Done)
+
+      7 IkiWiki::saveindex
+      5 IkiWiki::loadindex
+
+Still too internal to ever be exported?
+
+      7 IkiWiki::redirect
+
+Only used by 4 plugins, and not in IkiWiki.pm itself, so probably not to be exported.
+
+      7 IkiWiki::dirname
+      4 IkiWiki::basename
+
+Not ikiwiki-specific, don't export.
+
+      6 IkiWiki::refresh
+
+Very internal, not part of IkiWiki.pm, don't export.
+
+      5 IkiWiki::yesno
+
+Not ikiwiki-specific, but worth exporting to get a consistent localised yes/no parser
+for directives.
+
+      5 IkiWiki::showform
+      4 IkiWiki::decode_form_utf8
+
+Only used by 3 fairly core plugins, not in IkiWiki.pm, don't export.
+
+      5 IkiWiki::rcs_update
+      4 IkiWiki::rcs_prepedit
+      5 IkiWiki::is_admin
+      5 IkiWiki::cgi_savesession
+      4 IkiWiki::cgiurl
+
+Not enough use, I think, to export.
+
+      5 IkiWiki::enable_commit_hook
+      5 IkiWiki::disable_commit_hook
+
+Deep internal magic, if exported people will use it wrong, only used by core plugins.
+
+      4 IkiWiki::check_canedit
+
+Probably needs to evolve more and be more widely used before being exported.
+
+## Variables used by plugins but not exported yet
 
 * %IkiWiki::pagecase (aggregate)
-* %IkiWIki::backlinks (pagestats)
+* %IkiWiki::backlinks (pagestats)
 
-[[todo/done]]
+[[done]] (until 4.0)..
index 45002f0c648fd48be1f3777679ee349bc7a0eb79..762f16646f5e195a63aa8c9b6376b45906e7b50c 100644 (file)
@@ -97,7 +97,7 @@ I've created an updated [patch](http://www.idletheme.org/code/patches/ikiwiki-fo
 --Ryan Koppenhaver
 
 ## Original patch
-[[tag patch]]
+[[!tag patch patch/core plugins/rst]]
 
 <pre>
 Index: debian/changelog
@@ -141,13 +141,13 @@ Index: IkiWiki/Plugin/rst.pm
  print html[html.find('<body>')+6:html.find('</body>')].strip();
  ";
  
- sub import { #{{{
+ sub import {
        hook(type => "htmlize", id => "rst", call => \&htmlize);
 +      hook(type => "htmlescape", id => "rst", call => \&htmlescape);
 +      hook(type => "htmlescapelink", id => "rst", call => \&htmlescapelink);
- } # }}}
+ }
  
-+sub htmlescapelink ($$;@) { #{{{
++sub htmlescapelink ($$;@) {
 +      my $url = shift;
 +      my $text = shift;
 +      my %params = @_;
@@ -158,15 +158,15 @@ Index: IkiWiki/Plugin/rst.pm
 +      else {
 +              return "`$text <$url>`_";
 +      }
-+} # }}}
++}
 +
-+sub htmlescape ($) { #{{{
++sub htmlescape ($) {
 +      my $html=shift;
 +      $html=~s/^/  /mg;
 +      return ".. raw:: html\n\n".$html;
-+} # }}}
++}
 +
- sub htmlize (@) { #{{{
+ sub htmlize (@) {
        my %params=@_;
        my $content=$params{content};
 Index: doc/plugins/write.mdwn
@@ -219,7 +219,7 @@ Index: doc/plugins/rst.mdwn
 -* reStructuredText does not allow raw html to be inserted into
 -  documents, but ikiwiki does so in many cases, including
 -  [[WikiLinks|ikiwiki/WikiLink]] and many
--  [[PreprocessorDirectives|ikiwiki/PreprocessorDirective]].
+-  [[Directives|ikiwiki/Directive]].
 +* Some bits of ikiwiki may still assume that markdown is used or embed html
 +  in ways that break reStructuredText. (Report bugs if you find any.)
  * It's slow; it forks a copy of python for each page. While there is a
@@ -272,7 +272,7 @@ Index: IkiWiki.pm
 +        return $hooks{htmlescapelink}{$type}{call}->($bestlink, $linktext);
 +      }
        return "<a href=\"$bestlink\">$linktext</a>";
- } #}}}
+ }
  
 @@ -628,6 +640,14 @@
                                preview => $preprocess_preview,
index f906312fe6ac883bdfba038bed17b49aee428a1e..ddacd91b526d157917bd5cc6a42271bee63d5745 100644 (file)
@@ -14,9 +14,9 @@
      package IkiWiki::Plugin::fortune;
 
      use warnings;
-    @@ -12,7 +18,13 @@ sub import { #{{{
+    @@ -12,7 +18,13 @@ sub import {
 
-     sub preprocess (@) { #{{{
+     sub preprocess (@) {
             $ENV{PATH}="$ENV{PATH}:/usr/games:/usr/local/games";
     -       my $f = `fortune 2>/dev/null`;
     +       my $f;
diff --git a/doc/todo/friendly_markup_names.mdwn b/doc/todo/friendly_markup_names.mdwn
new file mode 100644 (file)
index 0000000..f88e3c1
--- /dev/null
@@ -0,0 +1,13 @@
+On the edit form when you are creating a new page, you are given an option of
+page types that can be used. The string presented to the user here is not
+particularly friendly: e.g., mdwn, txtl... it would be nice if the drop-down
+contents were "Markdown", "Textile", etc. (the values in the option tags can
+remain the same).
+
+I've written a first-take set of patches for this. They are in
+git://github.com/jmtd/ikiwiki.git in the branch "friendly_markup_names".  [[!tag patch]]
+
+-- [[Jon]]
+
+[[merged|done]], TFTP! (I have not checked if any other format plugins
+would benefit from a longer name) --[[Joey]]
diff --git a/doc/todo/generated_po_stuff_not_ignored_by_git.mdwn b/doc/todo/generated_po_stuff_not_ignored_by_git.mdwn
new file mode 100644 (file)
index 0000000..1d24fd3
--- /dev/null
@@ -0,0 +1,7 @@
+[[!template id=gitbranch branch=smcv/gitignore author="[[smcv]]"]]
+[[!tag patch]]
+
+The recent merge of the po branch didn't come with a .gitignore.
+It eventually annoyed me enough to fix it :-) --[[smcv]]
+
+[[done]]
diff --git a/doc/todo/generic___39__do__61__goto__39___for_CGI.mdwn b/doc/todo/generic___39__do__61__goto__39___for_CGI.mdwn
new file mode 100644 (file)
index 0000000..26c5202
--- /dev/null
@@ -0,0 +1,35 @@
+The [[plugins/recentchanges]] plugin has a `do=recentchanges_link` feature that will
+redirect to a given wiki page, or an error page with a creation link.
+
+In the [[plugins/contrib/comments]] plugin I've found that it would be useful to do
+the same for users. For now I've just cloned the functionality into the comments
+plugin, but perhaps this functionality could be renamed to `do=goto` or
+something, and moved to `IkiWiki/CGI.pm`?
+
+> Now implemented as the 'goto' branch in my git repository, along with
+> [[apache_404_ErrorDocument_handler]]. --[[smcv]]
+
+>> Looks good, the only things I wonder are:
+>> * Should it be a separate plugin? In particular `cgi_page_from_404()` is
+>>   pretty big, and only works if apache is configured so seems somewhat
+>>   pluginaable.
+
+>>> I've split out `goto` and `apache404` plugins in the branch. I think
+>>> you're right that apache404 should be a plugin. If you think goto is small
+>>> and general enough to not be a plugin, just don't merge my most recent
+>>> patch! --[[smcv]]
+
+>> * I wish there were some way to generalize the workaround for the stupid
+>>   MSIE behavior. Actually, I wish we could ignore the MSIE stupidity,
+>>   as I tend to do, but perhaps it's too stupid in this case for that to
+>>   fly..
+>> * Is there any reason to require do=goto before checking for
+>>   `REDIRECT_STATUS`? Seems that if that code were moved
+>>   out of the enclosing if block, the apache 404 handler could
+>>   be set direct to the cgi, which seems simpler to remember.
+>> --[[Joey]] 
+
+>>> No, good point - the `REDIRECT_STATUS` check is sufficiently unambiguous
+>>> already. Fixed. --[[smcv]]
+
+[[done]]
index 0f2514e0c353d6e683d2e3a6c3d1f46974a6689d..65658d7c4291d9a0a8e450d6fcb483ce016e1162 100644 (file)
@@ -2,4 +2,6 @@ Would be nice to see a way of geotagging pages in an ikiwiki,
 and search/sort pages by distance to a given location, as well as
 showing page locations on a map (Google Map, OpenStreetMap, etc). -- [[users/vibrog]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
+
+> [[!cpan Geo::Coordinates::UTM]] would probably be useful. --[[smcv]]
index d811b8ea9b5f6853539942c75db96c16ad953259..ec7d61b90b28173e6f292ba8eba892960affe712 100644 (file)
@@ -21,4 +21,4 @@ Better to strip the path out in getctime, I guess.
 
 --[[Joey]]
 
-[[tag patch done]]
+[[!tag patch done]]
index 0d3f97fedfd7050fe57f949f70f5b9db9665e366..baa522adc38e5126e4de0bb0b9a087c734fd59e0 100644 (file)
@@ -4,4 +4,6 @@ on the semantics you want to imply (does a web edit constitute a commit by
 the user or by the script?), it could also set `GIT_COMMITTER_NAME` and
 `GIT_COMMITTER_EMAIL` to the same values.  --[[JoshTriplett]]
 
-> See [[debbug 451023]] for a [[patch]] --[[Joey]]
+> See [[!debbug 451023]] for a [[patch]] --[[Joey]]
+
+[[done]]
index 42cc8449efda7694cf3709dc2a6b115af8453246..dfb490bc21e18b4f67b7b4b511ddc82d25bd309c 100644 (file)
@@ -63,3 +63,36 @@ no determination of uniqueness)
 >>Sounds good to me, 
 >>
 >> --[[harningt]]
+
+> I think the thing to do is, as Josh suggested originally, use
+> GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL. Note that setting these
+> individually is best, so git can independently validate/sanitize both
+> (which it does do somewhat). Always put the username/openid/IP in
+> GIT_AUTHOR_NAME; if the user has configured an email address,
+> GIT_AUTHOR_EMAIL can also be set.
+> 
+> There is one thing yet to be solved, and that is how to tell the
+> difference between a web commit by 'Joey Hess <joey@kitenet.net>',
+> and a git commit by the same. I think we do want to differentiate these,
+> and the best way to do it seems to be to add a line to the end of the
+> commit message. Something like: "\n\nWeb-commit: true"
+> 
+> For backwards compatability, the code that parses the current stuff needs
+> to be left in. But it will need to take care to only parse that if the
+> commit isn't flagged as a web commit! Else web committers could forge
+> commits from others. --[[Joey]]
+> 
+> BTW, I decided not to use the user's email address in the commit, because
+> then the email becomes part of project history, and you don't really
+> expect that to happen when you give your email address on signup to a web
+> site.
+> 
+> The problem with leaving the email empty is that it confuses some things
+> that try to parse it, including: 
+> * cia (wants a username in there):
+> * git pull --rebase (?)
+> * github pushes to twitter ;-)
+> 
+> So while I tried that way at first, I'm now leaning toward encoding the
+> username in the email address. Like "user <user@web>", or
+> "joey <http://joey.kitenet.net/@web>".
index c55a4aa238349ce4097f959c28e40531b0635598..3f2514a99400f00db25c7acabeb0a2634f311355 100644 (file)
@@ -1,6 +1,6 @@
 How about a plugin providing a
-[[preprocessor_directive|ikiwiki/preprocessordirective]] to render a
-[[debpkg graphviz]] file as an image via one of the graphviz programs
+[[preprocessor_directive|ikiwiki/directive]] to render a
+[[!debpkg graphviz]] file as an image via one of the graphviz programs
 ("dot" by default) and include the resulting image on the page, using the
 "cmapx" image map format?  graphviz files themselves could also render the
 same way into an HTML file with the same basename as the graphviz file;
index 2ef231ddede9a3a73cc05cc233ebae02491bd2ad..7cf37fbb9e96e7e81429766c4fc512019c5ccd21 100644 (file)
@@ -12,7 +12,7 @@ while the default stays as it is now.
 > INSTALLMAN1DIR (though MakeMaker lacks one for man8). I'd prefer not
 > adding new variables where MakeMaker already has them. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch patch/core]]
 
 <pre>
 
diff --git a/doc/todo/hidden_links__47__tags.mdwn b/doc/todo/hidden_links__47__tags.mdwn
new file mode 100644 (file)
index 0000000..2a47493
--- /dev/null
@@ -0,0 +1,13 @@
+[[!tag wishlist]]
+
+I would like to have the possibility for hidden tags or links.
+Using the tag functionality I could group some news items for including them into other subpages. But I don't want the links or tags to show (and I don't want Tag lists like "Tags: ?mytag").
+The tagged items should not differ from the items, that are not tagged.  
+I didn't find any way to hide the tag list or links and I don't want to have to create a "hidden" page containing links to the pages and then using the backlink functionality, because this is more prone to errors. It's easier to forget adding a link on a second page than forgetting to add a needed tag to a new newsitem.  
+
+> I found out, that using the [[meta plugin|plugins/meta]] it is possible to create the hidden link, that I wanted.  
+-- [[users/Enno]]
+
+>> Yes, [[meta link|ikiwiki/directive/meta]] will not show up as a visible link on the page, while
+>> also not showing up in the list of tags of a page, so it seems what you
+>> want. [[done]] --[[Joey]] 
index 96bcd926bbfde716ccb494f82293651bf8b239a3..e376b840ec2cfd4293106b709e2b79df2e86f71a 100644 (file)
@@ -31,8 +31,8 @@
        Because [ [inlinepage] ] isn't separated by a blank line it gets treated as a block-level element. Hmm, will this stop all formatting, including *'s to em-tags? --[[JeroenSchot]]
 
     Ah didn't realize you meant it fixed it at the markdown level. I'll
-    think about making postprocessordirectives into
-    [[ikiwiki/preprocessordirective]]s instead, then I could use that fix (but I'm not
+    think about making postprocessor directives into
+    preprocessor directives instead, then I could use that fix (but I'm not
     sure how feasible it is to do that). --[[Joey]]
 
     Done.. inlining is now a preprocessor directive, happens before
diff --git a/doc/todo/httpauth_feature_parity_with_passwordauth.mdwn b/doc/todo/httpauth_feature_parity_with_passwordauth.mdwn
new file mode 100644 (file)
index 0000000..eb71cf8
--- /dev/null
@@ -0,0 +1,28 @@
+The only way to have a private ikiwiki, with a shared user database
+for static pages and CGI authentication, is to use
+[[plugins/httpauth]]. It would be good for httpauth to be on par with
+[[plugins/passwordauth]], i.e. to allow registering users, resetting
+passwords, and changing passwords; supporting some kind of
+`account_creation_password` configuration option would be nice, too.
+
+I'll probably propose patches implementing this at some point.
+I've not had a single look at the code yet, but it may be nice to factorize
+the relevant passwordauth code, instead of rewriting it completely in httpauth.
+
+-- [[intrigeri]]
+
+Well, on such a private wiki, one can neither register herself nor
+reset his password: the registration page, as any other page, would be
+forbidden to non-authenticated users. Admin users should then be
+enabled to:
+
+- register a new user
+- reset someone else's password
+
+In both cases, a brand new random password is sent by e-mail to the
+new user.
+
+An authenticated user should nevertheless be able to change his
+own password. -- [[intrigeri]]
+
+[[wishlist]]
index fc2d7f986c51c9677d3aaca5226437eb940586db..64130a616cc0648e7098fe88fac32834c6a28baf 100644 (file)
@@ -5,3 +5,5 @@ usable in browsers like w3m that don't support styled uls. ikiwiki does use
 styled uls for other things, such as the action bar, but displaying that as
 a simple unstyled list in a simple browser works well and makes sense. For
 parent links, it does not. --[[Joey]]
+
+[[done]]
index dabba6914c2d6783639d566561a87669e99c75f8..f5e6f8cd7a4f8fa9f290f887d59fea625c3601f6 100644 (file)
@@ -3,7 +3,7 @@ providing the usedirs option for output. The remaining patch, discussed
 below, concerns wanting to use foo/index.mdwn source files and get an
 output page name of foo, rather than foo/index. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
 
 ---
 
@@ -91,15 +91,15 @@ page "A/B/index.html" is treated as "A/B".
     +++ ikidev/IkiWiki.pm       2007-02-25 15:05:22.328852000 -0800
     @@ -192,6 +192,12 @@
         return $untainted;
-     } #}}}
+     }
 
-    +sub titlename($;@) { #{{{
+    +sub titlename($;@) {
     +   my $page = shift;
     +   $page =~ s!/index$!!;
     +   return pagetitle(basename($page), @_);
-    +} #}}}
+    +}
     +
-     sub basename ($) { #{{{
+     sub basename ($) {
         my $file=shift;
 
 
@@ -117,8 +117,10 @@ diff -ru ikiwiki-2.4/IkiWiki.pm ikiwiki/IkiWiki.pm
        $page=~s/\Q.$type\E*$// if defined $type;
 +      $page=~s/\/index$// if $page =~ /\/index$/;
        return $page;
- } #}}}
+ }
  
 </pre>
 
-This just makes it so that all files named foo/index become pages called foo, which is the desired effect. I haven't tested everything so far, so be careful! But you can see it working at http://ikidev.betacantrips.com/one/ again, as before. --Ethan
\ No newline at end of file
+This just makes it so that all files named foo/index become pages called foo, which is the desired effect. I haven't tested everything so far, so be careful! But you can see it working at http://ikidev.betacantrips.com/one/ again, as before. --Ethan
+
+[[done]], the indexpages setting enables this.
diff --git a/doc/todo/inline:_numerical_ordering_by_title.mdwn b/doc/todo/inline:_numerical_ordering_by_title.mdwn
new file mode 100644 (file)
index 0000000..3d7424b
--- /dev/null
@@ -0,0 +1,254 @@
+Could you please add numerical ordering by title to [[inline|plugins/inline]]
+plugin? Now I can do only alphabetical order by title, but sometime it's not enough.
+
+> Implemented, see [[natural_sorting]] [[!tag done]] --[[Joey]] 
+
+BTW, it seems that ordering by title is rather ordering by filename of page.
+For me "title" means title of page I can set using `title` parameter
+of [[meta|plugins/meta]] plugin :)
+
+Why do I need that feature? I've just been migrating an info site of our university
+[mail system](http://poczta.uw.edu.pl/) to Ikiwiki from very static, console handling
+Makefile+[WML](http://thewml.org/)+XML+XSL=HTML solution. I have many news files
+(`1.mdwn`, `2.mdwn`, etc.) and unfortunately I did very stupid thing. I've commited
+all of them in the same revision of our Subversion repo...
+
+Now I have a problem with sorting these files using inline plugin. I can't do
+sorting by age, because both old and young news files have the same age. I can't
+sort by title too. For example, when I sort them by title, then `9.mdwn` page is
+between `90.mdwn` and `89.mdwn` pages... It sucks, of course. Sorting by mtime
+also is not a solution for me, because it means that I can't touch/fix old news
+anymore.
+
+Do you have any idea how to workaround that issue? --[[Paweł|ptecza]]
+
+> Delete all files. Add files back one at a time, committing after adding
+> each file. Sort by date. --[[Joey]]
+
+>> The simplest solutions are the best :D Thanks for the hint! I didn't
+>> want to do it before, because I was affaid that my Subversion keeps
+>> old date of creation of file. --[[Paweł|ptecza]]
+
+> Maybe you can rename `9.mdwn` to `09.mdwn`? See `rename(1)`, it renames multiple files
+> in one go. --[[buo]]
+
+>> Thanks for your suggestion! But what about if number of my news files grows to 100+?
+
+>>     $ ls
+>>     09.mdwn  100.mdwn  101.mdwn  102.mdwn  89.mdwn  90.mdwn
+
+>> I don't want to rename all previous files to add `0` prefix. --[[Paweł|ptecza]]
+
+>>> Rather than adding 0's or or a 'sorttype' parameter, I'd just fix the sort order.
+>>> Both MacOS and Windows use a smarter sort order than just lexical in their
+>>> file browsers (e.g. <http://support.microsoft.com/default.aspx?kbid=319827>,
+>>> <http://docs.info.apple.com/article.html?artnum=300989>).
+>>>
+>>> The [Unicode Collation algorithm](http://en.wikipedia.org/wiki/Unicode_collation_algorithm)
+>>> would seem to be a reasonable sort order.  (See also <http://www.unicode.org/unicode/reports/tr10/>.)
+>>> Unfortunately the standard perl implementation, [Unicode::Collate](http://perldoc.perl.org/Unicode/Collate.html)
+>>> doesn't handle the optional [numbers](http://www.unicode.org/unicode/reports/tr10/#Customization)
+>>> extension which is what you want.  --[[Will]]
+
+---
+
+Below is my simple patch. Feel free to use it or comment!
+
+I have also 2 considerations for inline sorting:
+
+1. Maybe changing name of `sort` parameter to `sortby` or `sortkey` will
+   be good idea?
+
+   > No, that would break existing wikis. --[[Joey]]
+   >> It's no problem. You just have `ikiwiki-transition` utility :D --[[Paweł|ptecza]]
+
+1. Maybe you should use `title` sort key for title from meta plugin and `name`, 
+   `filename`, `page` or `pagename` for page names? In the future you can also
+   sort by meta author, license or another key.
+
+   > There are many places in ikiwiki that do not use meta title info and
+   > could. I'd prefer to deal with that issue as a whole, not here,
+   > --[[Joey]]
+
+--[[Paweł|ptecza]]
+
+    --- inline.pm-orig  2008-09-02 09:53:20.000000000 +0200
+    +++ inline.pm       2008-09-02 10:09:02.000000000 +0200
+    @@ -186,7 +186,15 @@
+        }
+
+        if (exists $params{sort} && $params{sort} eq 'title') {
+    -           @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
+    +           if (! $params{sorttype} || $params{sorttype} eq 'lexical') {
+    +                   @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
+    +           }
+    +           elsif ($params{sorttype} eq 'numeric') {
+    +                   @list=sort { pagetitle(basename($a)) <=> pagetitle(basename($b)) } @list;
+    +           }
+    +           else {
+    +                   return sprintf(gettext("unknown sort type %s"), $params{sorttype});
+    +           }
+        }
+        elsif (exists $params{sort} && $params{sort} eq 'mtime') {
+                @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
+    @@ -195,7 +203,7 @@
+                @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+        }
+        else {
+    -           return sprintf(gettext("unknown sort type %s"), $params{sort});
+    +           return sprintf(gettext("unknown sort key %s"), $params{sort});
+        }
+
+        if (yesno($params{reverse})) {
+
+> To users, "sort" already determines the type of sort. It can be by title,
+> or by date, etc. Adding a separate "sorttype" value is thus fairly
+> confusing. --[[Joey]]
+
+>> OK. I will be more careful when I play with inline plugin :) --[[Paweł|ptecza]]
+
+---
+
+Joey, have you forgotten about that request? ;) --[[Paweł|ptecza]]
+
+> Okie.  Here is a different [[patch]] based on my comment above.  It doesn't introduce
+> a new key, but rather changes the title sorting order. Two caveats:
+
+ * I've only tested this in `inline`, not the other places I changed the sort order.
+ * I'm unsure if the regexp used in the split should be `/(-?\d+)/` instead of `/(\d+)/`.
+    As written, '-' is interpreted as a hyphen rather than a minus sign.
+
+> --[[Will]]
+
+>> I"m not comfortable with tossing out perl's default collator and trying
+>> to maintain some other one going forward. Especially not for such an
+>> edge case. --[[Joey]]
+
+>> Hi Will! Your idea looks interesting for me, but I'm affraid that it's too big
+>> change in Ikiwiki... Maybe I'm wrong? ;) What do you think, Joey? --[[Paweł|ptecza]]
+
+>>> It isn't that big a change.  It is just supplying a sort order to the sort.  The
+>>> patch is a little larger because I then went through and made that sort
+>>> order available in other places where it makes sense.  (Looking at the
+>>> patch again briefly, I should have also used it in the `map` plugin.)
+>>>
+>>> If you wanted a simple patch, you could just move the `titlecmp` function
+>>> into the inline plugin and only use it there.  The problem with that is that
+>>> it only fixes the inline plugin. -- [[Will]]
+
+>>>> Will, I agree with you that it's improved way of sort order. But on the other
+>>>> hand I prefer to be careful when I change something in a several places,
+>>>> because I don't want to break any working things when I fix one thing.
+>>>> I hope that Joey agree with us too and all Ikiwiki users will be happy
+>>>> after applying your patch ;) --[[Paweł|ptecza]]
+
+----
+
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index c0f5dea..d001f8d 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -20,7 +20,7 @@ use Exporter q{import};
+     our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
+                      bestlink htmllink readfile writefile pagetype srcfile pagename
+                      displaytime will_render gettext urlto targetpage
+    -           add_underlay
+    +           add_underlay titlecmp
+                      %config %links %pagestate %renderedfiles
+                      %pagesources %destsources);
+     our $VERSION = 2.00; # plugin interface version, next is ikiwiki version
+    @@ -835,6 +835,42 @@ sub titlepage ($) {
+       return $title;
+     }
+     
+    +sub titlecmp ($$) {
+    +  my $titleA=shift;
+    +  my $titleB=shift;
+    +  
+    +  my @listA=split(/(\d+)/,$titleA);
+    +  my @listB=split(/(\d+)/,$titleB);
+    +  
+    +  while (@listA && @listB) {
+    +          # compare bits of text
+    +          my $a = shift @listA;
+    +          my $b = shift @listB;
+    +          my $c = ($a cmp $b);
+    +          return $c if ($c);
+    +
+    +          if (@listA && @listB) {
+    +                  # compare numbers
+    +                  $a = shift @listA;
+    +                  $b = shift @listB;
+    +                  $c = $a <=> $b;
+    +                  return $c if ($c);
+    +                  
+    +                  # 01 is different to 1
+    +                  $c = (length($a) <=> length($b));
+    +                  return $c if ($c);
+    +
+    +                  $c = ($a cmp $b);
+    +                  return $c if ($c);
+    +          }
+    +  }
+    +  
+    +  return 1 if (@listA);
+    +  return -1 if (@listB);
+    +  
+    +  return 0;
+    +}
+    +
+     sub linkpage ($) {
+       my $link=shift;
+       my $chars = defined $config{wiki_file_chars} ? $config{wiki_file_chars} : "-[:alnum:]+/.:_";
+    diff --git a/IkiWiki/Plugin/brokenlinks.pm b/IkiWiki/Plugin/brokenlinks.pm
+    index 37752dd..ccaa399 100644
+    --- a/IkiWiki/Plugin/brokenlinks.pm
+    +++ b/IkiWiki/Plugin/brokenlinks.pm
+    @@ -59,7 +59,7 @@ sub preprocess (@) {
+                       map {
+                               "<li>$_</li>"
+                       }
+    -                  sort @broken)
+    +                  sort titlecmp @broken)
+               ."</ul>\n";
+     }
+     
+    diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
+    index 8efef3f..263e7a6 100644
+    --- a/IkiWiki/Plugin/inline.pm
+    +++ b/IkiWiki/Plugin/inline.pm
+    @@ -192,7 +192,7 @@ sub preprocess_inline (@) {
+       }
+     
+       if (exists $params{sort} && $params{sort} eq 'title') {
+    -          @list=sort { pagetitle(basename($a)) cmp pagetitle(basename($b)) } @list;
+    +          @list=sort { titlecmp(pagetitle(basename($a)),pagetitle(basename($b))) } @list;
+       }
+       elsif (exists $params{sort} && $params{sort} eq 'mtime') {
+               @list=sort { $pagemtime{$b} <=> $pagemtime{$a} } @list;
+    diff --git a/IkiWiki/Plugin/orphans.pm b/IkiWiki/Plugin/orphans.pm
+    index b910758..10a1d87 100644
+    --- a/IkiWiki/Plugin/orphans.pm
+    +++ b/IkiWiki/Plugin/orphans.pm
+    @@ -56,7 +56,7 @@ sub preprocess (@) {
+                               htmllink($params{page}, $params{destpage}, $_,
+                                        noimageinline => 1).
+                               "</li>"
+    -                  } sort @orphans).
+    +                  } sort titlecmp @orphans).
+               "</ul>\n";
+     }
+     
+    diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
+    index ceb7c84..00798e1 100644
+    --- a/IkiWiki/Render.pm
+    +++ b/IkiWiki/Render.pm
+    @@ -89,7 +89,7 @@ sub genpage ($$) {
+               $template->param(have_actions => 1);
+       }
+     
+    -  my @backlinks=sort { $a->{page} cmp $b->{page} } backlinks($page);
+    +  my @backlinks=sort { titlecmp($a->{page}, $b->{page}) } backlinks($page);
+       my ($backlinks, $more_backlinks);
+       if (@backlinks <= $config{numbacklinks} || ! $config{numbacklinks}) {
+               $backlinks=\@backlinks;
diff --git a/doc/todo/inline_plugin:_ability_to_override_feed_name.mdwn b/doc/todo/inline_plugin:_ability_to_override_feed_name.mdwn
new file mode 100644 (file)
index 0000000..df5bf91
--- /dev/null
@@ -0,0 +1,29 @@
+If RSS and Atom are enabled by default, the [[plugins/contrib/comments]]
+plugin generates a feed, perhaps `/sandbox/index.atom` for comments on the
+sandbox. If a blog is added to the page, the blog will steal the name
+`/sandbox/index.atom` and the comments plugin's feed will change to
+`/sandbox/index.atom2`.
+
+If `\[[!inline]]` gained a parameter `feedname` or something, the comments
+plugin could use `feedname=comments` to produce `/sandbox/comments.atom`
+instead (this would just require minor enhancements to rsspage(),
+atompage() and targetpage()).
+
+As a side benefit, [my blog](http://smcv.pseudorandom.co.uk/) could go back
+to its historical Atom feed URL of `.../feed.atom` (which is currently a
+symlink to `index.atom` :-) )
+
+On sites not using `usedirs` the current feed is `/sandbox.atom`, and we
+could perhaps change it to `/sandbox-comments.atom` or
+`/sandbox/comments.atom` if `feedname=comments` is given.
+
+--[[smcv]]
+
+> This is slightly hard to do, because you have to worry about 
+> conflicting pages setting feedname, which could cause ikiwiki to blow up.
+> 
+> Particularly for the non-usedirs case, where a page `sandbox/comments`
+> would produce the same feed as sandbox with `feedname=comments`.
+> --[[Joey]]
+
+> [[done]] as feedfile option --[[Joey]]
diff --git a/doc/todo/inline_plugin:_hide_feed_buttons_if_empty.mdwn b/doc/todo/inline_plugin:_hide_feed_buttons_if_empty.mdwn
new file mode 100644 (file)
index 0000000..d046c0c
--- /dev/null
@@ -0,0 +1,7 @@
+      < joeyh> 03:49:19> also, I think it may be less visually confusing to 
+               drop the rss/atom buttons for comments when there are none yet
+
+This seems to me like something that applies to the [[plugins/inline]] plugin in general, rather than the [[plugins/contrib/comments]] plugin specifically. --[[smcv]]
+
+>> [[done]] as emptyfeeds option, not on by default for inline, but I think
+>> it should be for comments --[[Joey]]
diff --git a/doc/todo/inline_plugin:_specifying_ordered_page_names.mdwn b/doc/todo/inline_plugin:_specifying_ordered_page_names.mdwn
new file mode 100644 (file)
index 0000000..bbde04f
--- /dev/null
@@ -0,0 +1,21 @@
+[[!template id=gitbranch branch=smcv/ready/inline-pagenames author="[[smcv]]"]]
+
+A [[!taglink patch]] in my git repository (the inline-pagenames branch) adds
+the following parameter to the [[ikiwiki/directive/inline]] directive:
+
+> * `pagenames` - If given instead of `pages`, this is interpreted as a
+>    space-separated list of links to pages (with the same
+>   [[ikiwiki/SubPage/LinkingRules]] as in a [[ikiwiki/WikiLink]]), and they are inlined
+>   in exactly the order given: the `sort` and `pages` parameters cannot be used
+>   in conjunction with this one.
+
+This is on my [[wishlist]] for my [[plugins/contrib/album]] plugin, which currently
+uses it internally (as it has already collected the pages in order). It could also
+be useful for other things, like [[todo/wikitrails]]. --[[smcv]]
+
+[[!tag plugins/inline]]
+
+> It's sort of a pity that a pagespec like "a or b or c" doesn't somehow
+> match to (a, b, c) in that order, but I don't see how that would be
+> generally possible. While this feels a bit like bloat and inline already
+> has far too many parameters, I have [[merged|done]] it. --[[Joey]] 
diff --git a/doc/todo/inline_postform_autotitles.mdwn b/doc/todo/inline_postform_autotitles.mdwn
new file mode 100644 (file)
index 0000000..39713eb
--- /dev/null
@@ -0,0 +1,67 @@
+[[!tag wishlist patch plugins/inline]]
+[[!template id=gitbranch branch=chrysn/patches author="[[chrysn]]"]]
+
+for postforms in inlines of pages which follow a certain scheme, it might not
+be required to set the title for each individual post, but to automatically set
+the title and show no input box prompting for it.
+this can either be based on timestamp formatting, or use the already existing
+munging mechanism, which appends numbers to page titles in case that page
+already exists.
+
+two patches ([1], [2]) set inline up for that, adding an additional `autotitle`
+parameter. if that is given, the regular input of the inline postform will be
+replaced with a hidden input of that text. in addition, the empty title is
+permitted (both for autotitle and regular titles, as they go in the same GET
+parameter, `title`). as the empty page title is illegal, munging is used,
+resulting in ascending numeric page titles to be created.
+
+the second patch is actually a one-liner, filtering the title through strftime.
+
+> Something similar was requested in [[todo/more_customisable_titlepage_function]],
+> in which [[Joey]] outlined a similar solution.
+>
+> What's your use-case for not prompting for the title at all? I can see
+> [[madduck]]'s requirement for the title he typed in (say, "foo")
+> being transformed into 2009/07/26/foo or something (I name blog posts
+> like that myself), but I can't quite see the use for *entirely* automatic
+> titles.
+>
+> However, if that's really what you want, I suspect your code could be
+> extended so it also solves madduck's second request on
+> [[todo/more_customisable_titlepage_function]].
+>
+> --[[smcv]]
+
+### potential user interaction issues
+
+this has two side effects which have to be considered: first, the empty page
+title is accepted also in normal postforms (previously, this resulted in a "bad
+page name" error); second, entering a percent sign in that field might result
+in unexpexted strftime substitution (strftime might not even substitute for
+common uses of percent as in "reach 10% market share", but might in others as
+in "the 10%-rule").
+
+both can be circumvented by using another GET parameter for autotexts, as
+implemented in [3].
+> this patch still does not work perfectly; especially, it should make a
+> distinction between "autotitle is set but equal ''" (in which case it
+> should create a page named `1.mdwn`, and "autotitle is not set, and title is
+> equal ''" (in which case it should display the old error message) --[[chrysn]]
+
+### potential security issues
+
+* the autotitle's value is directly output through the template (but that's
+  done in other places as well, so i assume it's safe)
+* i don't know if anything bad can happen if unfiltered content is passed to
+  POSIX::strftime.
+
+### further extension
+
+having a pre-filled input field instead of an unchangable hidden input might be
+cool (eg for creating an entry with yesterday's date), but would be a bit of a
+problem with static pages. javascript could help with the date part, but name
+munging would be yet another thing.
+
+[1]: http://github.com/github076986099/ikiwiki/commit/b568eb257a3ef5ff49a84ac00a3a7465b643c1e1
+[2]: http://github.com/github076986099/ikiwiki/commit/34bc82f232be141edf036d35e8ef5aa289415072
+[3]: http://github.com/github076986099/ikiwiki/commit/40dc10a4ec7809e401b4497c2abccfba30f7a2af
diff --git a/doc/todo/inlines_inheriting_links.mdwn b/doc/todo/inlines_inheriting_links.mdwn
new file mode 100644 (file)
index 0000000..c53da51
--- /dev/null
@@ -0,0 +1,39 @@
+[[!tag wishlist]]
+
+Continuing the ideas in [[bugs/Inline doesn't wikilink to pages]].
+
+I thought of a use case for another feature: making [[ikiwiki/directive/inline]] inherit the link relations of the included pages (optionally, say, with `inheritlinks=yes`). For example, if I want to list `elements/*` that have been linked to in any of `new_stuff/*`, I could try to write a [[ikiwiki/pagespec]] like
+`elements/* and backlink(new_stuff/*)`.
+
+This is not yet possible, as discussed in [[todo/tracking_bugs_with_dependencies]].
+
+It would be possible to work around this limitation of pagespecs if it was possible to create a page `all_new_stuff` with `\[[!inline pages="new_stuff/*" inheritlinks=yes]]`: then the desired pagespec would be expressed as `elements/* and backlink(all_new_stuff)`.
+
+> Or, instead of specifying whether to inherit at the place of the inline, add more relations (`inline`, `backinline`) and relation composition (say, `*`, or haskell-ish `$` in order not confuse with the glob `*`) and explicitly write in the pagespecs that you want to follow the inline relation backwards: `elements/* and backlink$backinline(all_new_stuff)` or, equivalently, if [["classes"|todo/tracking_bugs_with_dependencies]] are implemented in pagespecs: `elements/* and backlink(backinline(all_new_stuff))`. Of course, this suggestion requires the powerful extension to pagespecs, but it gives more flexibility, and the possibility to avoid redundant information: the same pagespec at two places -- the inline and the other matching construction.
+>
+> BTW, adding more relations -- the `inline` relation among them -- would satisfy [[the other feature request|bugs/Inline doesn't wikilink to pages]]. --Ivan Z.
+
+This is not just an ugly workaround. The availability of this feature has some reason: the classes of pages you want to refer to "recursively" (in that kind of complex pagespecs) tend to have some meaning themselves. So, I might indeed want to have a page like `all_new_stuff`, it would be useful for me. And at the same time I would like to write pagespecs like `elements/* and backlink(all_new_stuff)` -- and using the proposed feature in [[todo/tracking_bugs_with_dependencies/]] would be less clean because then I would have to enter the same information at two places: the possibly complex pagespec in the inline. And having redundant information leads to inconsistency.
+
+So in a sense, in some or most cases, it would indeed be cleaner to "store" the definition of a class of pages referred to in complex pagespecs as a separate object. And the most natural representation for this definition of a class of pages (adhering to the principle of wiki that what you mean is entered/stored in its most natural representation, not through some hidden disconnected code) is making a page with an inline/map/or the like, so that at the same time you store the definition and you see what it is (the set of pages is displayed to you).
+
+I would actually use it in my current "project" in ikiwiki: I actually edit a set of materials as a set of subpages `new_stuff/*`, and I also want to have a combined view of all of them (made through inline), and at another page, I want to list what has been linked to in  `new_stuff/*` and what hasn't been linked to.--Ivan Z.
+
+> I see where you're coming from, but let's think about
+> immplementation efficiency for a second. 
+> 
+> In order for inline inheritlinks=yes to work,
+> the inline directive would need to be processed
+> during the scan pass.
+> 
+> When the directive was processed there, it would need
+> to determine which pages get inlined (itself a moderatly
+> expensive operation), and then determine which pages
+> each of them link to. Since the scan pass is unordered,
+> those pages may not have themselves been scanned yet.
+> So to tell what they link to, inline would have to load
+> each of them, and scan them.
+> 
+> So there's the potential for this to slow
+> down a wiki build by about a factor of 2.
+> --[[Joey]] 
diff --git a/doc/todo/interactive_todo_lists.mdwn b/doc/todo/interactive_todo_lists.mdwn
new file mode 100644 (file)
index 0000000..22b9295
--- /dev/null
@@ -0,0 +1,49 @@
+This is a fleshed out todo based on discussions at
+[[forum/managing_todo_lists]].
+
+I would like to have TODO lists inside ikiwiki wikis. This would mean:
+
+* a new markup plugin to support a language suitable for TODO lists (OPML,
+  XOXO are two possible candidates)
+* some javascript to provide interactive editing.
+
+As [[chrysn]] pointed out on the forum page, this has some crossover with
+[[structured page data]]. In particular, if the markup language chosen had a
+concept of invalid markup (existing plugins just tend to ignore stuff that
+isn't explicitly part of their markup) we would need to sensibly handle that.
+Perhaps rejecting web edits and providing context help on why the edit was
+rejected, although that sounds like a significant headache.
+
+I have started working on this, albeit slowly. A proof of concept is at
+<http://dev.jmtd.net/outliner/>.
+
+There are two git repositories associated with my WIP: one contains the
+javascript, the plugin, the changes made to page templates; the other contains
+the contents of that wiki-site (so the test todos and the contents of bugs/
+which forms a sort-of todo list for the todo list :) ) I will endeavour to get
+mirrors of those repos up on github or similar asap.
+
+-- [[Jon]]
+
+----
+
+Just to report the WIP plugin for this is now in a reasonably good state. I ended
+up just inventing a new markup language -- for now, items are divided by newlines
+and lists are one-dimensional, for simplicity. I got fed up thinking about how to
+handle the structured data issues / needing a lot of boilerplate around items and
+the implications for the "new item" dialogue.
+
+Still quite a lot to do though!
+
+-- [[Jon]]
+
+I've pushed a copy of the work in progress which consists of
+
+ * A change to page.tmpl
+ * A javascript underlay directory + javascript file
+ * a few CSS bits in a local.css
+ * a plugin
+
+to <http://github.com/jmtd/ikiwiki_todolist/>
+
+-- [[Jon]]
index d5f7dbfadc5b7c09d782ea7f6cd6225d64aafdb6..fed3f63b69b3b667750b917bea6e886f734052f0 100644 (file)
@@ -1,3 +1,19 @@
+ikiwiki should be fully internationalized.
+
+----
+
+As to the hardcoded strings in ikiwiki, I've internationalized the program,
+and there is a po/ikiwiki.pot in the source that can be translated.
+--[[Joey]]
+
+----
+
+> The now merged po plugin handles l10n of wiki pages. The only missing
+> piece now is l10n of the templates.
+> --[[Joey]]
+
+----
+
 From [[Recai]]:
 > Here is my initial work on ikiwiki l10n infrastructure (I'm sending it
 > before finalizing, there may be errors).
@@ -54,46 +70,3 @@ kullanıcının ait IP adresi: <TMPL_VAR REMOTE_ADDR>[2] <TMPL_VAR WIKIURL>
 This could be easily worked around in tmpl_process3, but I wouldn't like to
 maintain a separate utility.
 
-----
-
-As to the hardcoded strings in ikiwiki, I've internationalized the program,
-and there is a po/ikiwiki.pot in the source that can be translated.
---[[Joey]]
-
-----
-
-Danish l10n of templates and basewiki is available with the following commands:
-
-    git clone http://source.jones.dk/ikiwiki.git newsite
-    cd newsite
-    make
-
-Updates are retrieved with this single command:
-
-    make
-
-Right now the l10n is maintained by manually comparing against each new upstream release, and
-updating both the master mirror and the l10n as needed.
-
-Work is in progress to semi-automate this to still check manually for updates, but maintain the
-l10n as PO files - to allow more translations to more than the few languages I know about myself.
-
-As upstream ikiwiki is now maintained in GIT too, keeping the master mirror in sync with upstream
-could probably be automated even more - but an obstacle seems to be that content is not maintained
-separately but as an integral part of upstream source (GIT seems to not support subscribing to
-only parts of a repository).
-
-For example use, here's how to roll out a clone of the [Redpill support site](http://support.redpill.dk/):
-
-    mkdir -p ~/private_webdata
-    git clone http://source.redpill.dk/support.git ~/private_webdata/support.redpill.dk
-    cd ~/private_webdata/support.redpill.dk
-    make
-    mkdir -p ~/public_websites/support.redpill.dk
-    mkdir -p ~/public_websites/source.redpill.dk/support_content.git/hooks
-    mkdir -p ~/public_cgi/support.redpill.dk
-    make install
-
-(Redpill support is inspired by <http://help.riseup.net> but needs to be reusable for several similarly configured networks)
-
---[[JonasSmedegaard]]
index 2d1a56696244ed2d2c0878f80dba2a4bae7e2940..90bfbef3b49ca6532e9cdc0351fb154e3a27fa17 100644 (file)
@@ -1,5 +1,5 @@
 Here is a patch for the [[plugins/meta]] plugin. It adds the possibility to define the language 
-used for a page, with \[[meta lang="ja"]]
+used for a page, with \[[!meta lang="ja"]]
 
 It doesn't insert the langage information in the xhtml meta elements, but defines a LANG
 variable to use in the templates, for example with
@@ -54,7 +54,7 @@ This may be useful for sites with a few pages in different languages, but no ful
  my %authorurl;
 +my %lang;
  
- sub import { #{{{
+ sub import {
         hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1);
 @@ -100,6 +101,11 @@
                 $meta{$page}.='<link href="'.encode_entities($value).
@@ -75,10 +75,27 @@ This may be useful for sites with a few pages in different languages, but no ful
 +       $template->param(lang => $lang{$page})
 +               if exists $lang{$page} && $template->query(name => "lang");
  
- } # }}}
+ }
 </pre>
 
 > Please resolve lang somewhere reusable rather than within meta plugin: It is certainly usable outside
 > the scope of the meta plugin as well. --[[JonasSmedegaard]]
 
-[[tag wishlist patch plugins/meta translation]]
+>> I don't see any problem with having this in meta? meta is on by default, and
+>> other plugins are free to use it or even depend on it (e.g. inline does).
+>>
+>> My only comments on this patch beyond what Joey said are that the page
+>> language could usefully go into `$pagestate{$page}{meta}{lang}` for other
+>> plugins to be able to see it (is that what you meant?), and that
+>> restricting to 2 characters is too restrictive (HTML 4.01 mentions
+>> `en`, `en-US` and `i-navajo` as possible language codes).
+>> This slightly complicates parsing the locale to get the default language:
+>> it'll need `tr/_/-/` after the optional `.encoding` is removed.
+>> --[[smcv]]
+
+>>> Now that po has been merged, this patch should probably also be adapted
+>>> so that the po plugin forces the meta::lang of every page to what po
+>>> thinks it should be. Perhaps [[the_special_po_pagespecs|ikiwiki/pagespec/po]]
+>>> should also work with meta-assigned languages? --[[smcv]]
+
+[[!tag wishlist patch plugins/meta translation]]
index 01d927552850db2306ac3c29179c61e6cd35676b..4363003c1e58de11155843155c5f06b312e970d5 100644 (file)
@@ -1,16 +1,20 @@
 How about a plugin adding a
-[[preprocessor_directive|ikiwiki/preprocessordirective]] to render some given LaTeX
+[[preprocessor_directive|ikiwiki/directive]] to render some given LaTeX
 and include it in the page?  This could either render the LaTeX as a PNG via
-[[debpkg dvipng]] and include the resulting image in the page, or perhaps
+[[!debpkg dvipng]] and include the resulting image in the page, or perhaps
 render via [HeVeA](http://pauillac.inria.fr/~maranget/hevea/index.html),
 [TeX2page](http://www.ccs.neu.edu/~dorai/tex2page/tex2page-doc.html), or
 similar. Useful for mathematics, as well as for stuff like the LaTeX version
 of the ikiwiki [[/logo]].
 
+> [[users/JasonBlevins]] has also a plugin for including [[LaTeX]] expressions (by means of `itex2MML`) -- [[plugins/mdwn_itex]] (look at his page for the link). --Ivan Z.
+
 ----
 
 ikiwiki could also support LaTeX as a document type, again rendering to HTML.
 
+> [[users/JasonBlevins]] has also a [[plugins/pandoc]] plugin (look at his page for the link): in principle, [Pandoc](http://johnmacfarlane.net/pandoc/) can read and write [[LaTeX]]. --Ivan Z.
+
 ----
 
 Conversely, how about adding a plugin to support exporting to LaTeX?
@@ -23,12 +27,19 @@ Conversely, how about adding a plugin to support exporting to LaTeX?
 
 >>> Have a look at [pandoc](http://code.google.com/p/pandoc/).  It can make PDFs via pdflatex. --[[roktas]]
 
+>>>> Interesting, just yesterday I was playing with pandoc to make PDFs from my Markdown. Could someone advise me on how to embed these PDFs into ikiwiki? I need some guidance in implementing this. --[[JosephTurian]]
+
+>>>> [[users/JasonBlevins]] has a [[plugins/pandoc]] plugin (look at his page for the link). --Ivan Z.
+
 ----
 
 [here](http://ng.l4x.org/gitweb/gitweb.cgi?p=ikiwiki.git/.git;a=blob;f=IkiWiki/Plugin/latex.pm) is a first stab at
 a latex plugin. Examples [here](http://ng.l4x.org/latex/). Currently without image support for hevea. And the latex2html
 output has the wrong charset and no command line switch to change that. Dreamland.
 
+As this link is not working, I setted a mirror here: <a href="http://satangoss.sarava.org/ikiwiki/latex.pm">http://satangoss.sarava.org/ikiwiki/latex.pm</a>.
+
+
 ----
 
 Okay, now is the time for a mid term report i think.
@@ -197,7 +208,7 @@ This are of course the minority of people (but I guess also the minority of peop
 
 
 > I'm thinking about renameing the preprocessor directive to teximg.
-> \[[teximg code="" alt="foo"]] makes sense.. Would it make sense to rename
+> \[[!teximg code="" alt="foo"]] makes sense.. Would it make sense to rename
 > the whole plugin, or do you think that other tex stuff should go in this
 > same plugin?
 
@@ -216,5 +227,5 @@ Ah yes.. sorry forgot to update the plugin in my public_html folder %-). This wa
 > 
 > --[[Joey]]
 
-[[tag soc]]
-[[tag wishlist]]
+[[!tag soc]]
+[[!tag wishlist]]
index 94351fe5c3c2380924a071b900533c05b0c535e7..b220c8f6b7191135dd3e03896338d532ed1c1dba 100644 (file)
@@ -2,4 +2,4 @@ Is there any reason why the inline plugin's template parameter couldn't take any
 
 --[[madduck]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 7ac4c0771e0bfaf2823e2e53ed925dd0384c6e82..c3eb09e52356b5ab82dbf34e30597d8a803e816f 100644 (file)
@@ -5,4 +5,4 @@ For `aggregate` to work, I have to have the `html` plugin enabled, and this allo
 
 --[[madduck]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index d5b53e0824a49d184b5c64cf51920458c36cb553..6df3bfdcee0b7f629076a81c6b68f70ddcafce07 100644 (file)
@@ -2,15 +2,15 @@ Pages could have a `linktitle` (perhaps via [[plugins/meta]]), and
 [[wikilinks|ikiwiki/wikilink]] could use that title by default when linking
 to the page.  That would allow pages to have a simple, easily linkable name
 (without spaces, for instance), but use the proper title for links.  For
-example, [[ikiwiki/PreprocessorDirective]] could use the `linktitle`
+example, [[ikiwiki/Directive]] could use the `linktitle`
 "preprocessor directive", and pages for [[users]] could have `linktitle`s
 that put spaces in their names.
 
 Ideally, perhaps two versions of the title could exist, one for general
 use, and an optional one for if the case in the actual link starts with an
-uppercase letter.  That would allow [[ikiwiki/preprocessordirective]] to
+uppercase letter.  That would allow [[ikiwiki/directive]] to
 use the link text "preprocessor directive", but
-[[ikiwiki/PreprocessorDirective]] to use the link text "Preprocessor
+[[ikiwiki/Directive]] to use the link text "Preprocessor
 Directive", for use at the beginnings of sentences.  If the second version
 did not exist, the first version would apply to both cases. However, that
 also seems like potential overkill, and less important than the basic
diff --git a/doc/todo/location_of_external_plugins.mdwn b/doc/todo/location_of_external_plugins.mdwn
new file mode 100644 (file)
index 0000000..c28003e
--- /dev/null
@@ -0,0 +1,24 @@
+Would it be possible to make the installation location for the external
+plugins (those talked to via xmlrpc) configurable? Currently, they are
+installed into (and later expected to be in) /usr/lib/ikiwiki/plugins. For
+the Fedora package (which I maintain), I move them to
+/usr/libexec/ikiwiki/plugins. While not covered by the FHS, this seems to
+be a more appropriate place, see:
+https://fedoraproject.org/wiki/Packaging/Guidelines#Libexecdir.
+
+> This would need to be a build time configuration setting so the directory
+> is built into ikiwiki for use at runtime. --[[Joey]]
+
+As a side note, the accompanying proxy.py might better be placed into some directory on the python path.
+
+> If someone can show how to do so without needing a Setup.py and all the
+> pain that using one entails.. --[[Joey]]
+
+>> At the very least I don't think proxy.py should be on the `sys.path`
+>> under its current name. If it was renamed to ikiwiki_proxy or some such,
+>> possibly; but I think it's more appropriate to have it in an
+>> ikiwiki-specific directory (a "private module") since it's not useful for
+>> anything outside ikiwiki, and putting it in the same directory as the
+>> external plugins means it's automatically in their `sys.path` without
+>> needing special configuration. --[[smcv]]
+>> (a mostly-inactive member of Debian's Python modules packaging team)
diff --git a/doc/todo/location_of_ikiwiki-w3m.cgi.mdwn b/doc/todo/location_of_ikiwiki-w3m.cgi.mdwn
new file mode 100644 (file)
index 0000000..8ca925b
--- /dev/null
@@ -0,0 +1,3 @@
+The `ikiwiki-w3m.cgi` script is installed (hard-coded) into `/usr/lib/w3m/cgi-bin`. On Fedora however, the w3m package expects it in `/usr/libexec/w3m/cgi-bin`. So, it would be nice if the destination for this script could be configured.
+
+> You can use `W3M_CGI_BIN now`. [[done]] --[[Joey]]
diff --git a/doc/todo/matching_different_kinds_of_links.mdwn b/doc/todo/matching_different_kinds_of_links.mdwn
new file mode 100644 (file)
index 0000000..26c5a07
--- /dev/null
@@ -0,0 +1,47 @@
+[[!tag wishlist]]
+
+As noted in [[todo/tag_pagespec_function]], there is a "misbehavior" of a `tagged()` pagespec: it matches even pages which have plain links to the tag page.
+
+And in general, it would be quite useful to be able to distinguish different kinds of links: one more kind, in addition to "tag", is "bug dependency" noted in [[todo/structured_page_data#another_kind_of_links]] and [[todo/tracking_bugs_with_dependencies#another_kind_of_links]].
+
+It could distinguish the links by the `rel=` attribute. ([[Tags already receive a special rel-class|todo/rel_attribute_for_links]].) This means there is a general need for a syntax to specify user-defined rel-classes on wikilink (then bug deps would simply use their special rel-class, either directly, or through a special directive like `\[[!depends ]]`), and to refer to them in pagespecs (in forward and backward direction).
+
+Besides pagespecs, the `rel=` attribute could be used for styles. --Ivan Z.
+
+> FWIW, the `add_link` function introduced in a recent
+> release adds an abstraction that could be used to get
+> part of the way there to storing data about different types of
+> links. That function could easily be extended to take an optional
+> third parameter specifying the link type.
+> 
+> Then there's the question of how to store and access the data. `%links`
+> does not offer a good way to add additional information about links.
+> Now, we could toss `%links` entirely and switch to an accessor function,
+> but let's think about not doing that..
+> 
+> The data that seems to be needed is basically a deep hash, so
+> one could check `$linktype{$page}{tag}{$link}` to see if
+> the page contains a link of the given type. (Note that pages could
+> contain links that were duplicates except for their types.)
+> 
+> There would be some data duplication, unfortuantly, but if `%linktype`
+> is not populated for regular wikilinks, it would at least be limited to
+> tags and other unusual link types, so not too bad.
+> 
+> `%linktype` could be stored in `%pagestate`.. if so
+> the actual use might look like `$pagestate{$page}{linktype}{tag}{$link}`.
+> That could be implemented by the tag plugin right now
+> with no core changes. (BTW, then I originally wrote tag, pagestate
+> was not available, which is why I didn't make it differentiate from
+> normal links.) Might be better to go ahead and add the variable to
+> core though. --[[Joey]] 
+
+I saw somewhere else here some suggestions for the wiki-syntax for specifying the relation name of a link. One more suggestion---[the syntax used in Semantic MediaWiki](http://en.wikipedia.org/wiki/Semantic_MediaWiki#Basic_usage), like this:
+
+<pre>
+... the capital city is \[[Has capital::Berlin]] ...
+</pre>
+
+So a part of the effect of [[`\[[!taglink TAG\]\]`|plugins/tag]] could be represented as something like `\[[tag::TAG]]` or (more understandable relation name in what concerns the direction) `\[[tagged::TAG]]`.
+
+I don't have any opinion on this syntax (whether it's good or not)...--Ivan Z.
diff --git a/doc/todo/mbox.mdwn b/doc/todo/mbox.mdwn
new file mode 100644 (file)
index 0000000..a6af0c3
--- /dev/null
@@ -0,0 +1,18 @@
+I'd like to be able to drop an unmodified RFC2822 email message into ikiwiki, and get it formatted to HTML. Something like this: <http://lwn.net/Articles/287056/>
+
+> We're discussing doing just that (well, whole mailboxes, really) over in
+> [[comment_by_mail]] --[[Joey]]
+>> The 
+>> [[plugins/contrib/mailbox]]
+>> plugin is roughly feature complete at this point.  It can read mbox, maildir, and
+>> MH folders, does threading, and deals with MIME (now with 
+>> pagespec based sanity checking).  No doubt lots of things could be 
+>> be improved, and it hasn't been tested a great deal. Formatting of the body could be attempted
+>> as well. -- [[DavidBremner]]
+>>> One hitch I noticed was that it is not currently possible to treat a maildir
+>>> or an MH directory as a page (i.e. just call it foo.mh and have it transformed 
+>>> to page foo). I'm not sure if this is possible and worthwhile to fix. 
+>>  It is certainly workable
+>>> to use a \[[!mailbox ]] directive. -- [[DavidBremner]]
+
+[[done]]
diff --git a/doc/todo/mdwn_preview.mdwn b/doc/todo/mdwn_preview.mdwn
new file mode 100644 (file)
index 0000000..c20314c
--- /dev/null
@@ -0,0 +1,305 @@
+The [StackOverflow](http://stackoverflow.com/) site uses markdown for markup.
+It has a fancy javascript thing for showing a real-time preview of what the user
+is editing. It would be nice if ikiwiki could support this, too. The thing they
+use on StackOverflow is supposed to be free software, so it should be easy to
+add to ikiwiki.
+
+> See [[wikiwyg]]. Note that I do not have a copy of the code for that, or
+> it'd be in ikiwiki already. --[[Joey]] 
+
+>> I just had a brief look at the [[wikiwyg]] page and the link to the plugin was
+>> broken.  The StackOverflow site uses the [WMD](http://wmd-editor.com/) editor,
+>> which seems to be related to the [ShowDown](http://attacklab.net/showdown/)
+>> javascript port of Markdown.  Interestingly, [WMD source](http://wmd.googlecode.com/)
+>> is now available under an MIT license, though it is supposedly undergoing heavy
+>> refactoring.  It looks like there was previous discussion ( [[todo/Add_showdown_GUI_input__47__edit]] )
+>> about a showdown plugin.  Maybe a WMD plugin would be worthwhile.  I might
+>> look into it if I have time on the weekend. -- [[Will]]
+
+[[!tag wishlist]]
+
+>>> Below is a simple plugin/[[patch]] to make use of the WMD editor.
+
+>>>> Now added to ikiwiki, thanks! --[[Joey]] 
+
+>>> Turns out it isn't hard at all to
+>>> get a basic version going (which doesn't handle directives at all, nor does it swtich itself off when you're
+>>> editing something other than Markdown source).  I've
+>>> removed the done tag so this is visible as a patch. -- [[Will]]
+
+>>>> Hmm, it would be good if it turned off for !mdwn. Although this could
+>>>> be difficult for a new page, since there is a dropdown selector to
+>>>> choose the markup language then. But it should be doable for editing an
+>>>> existing page.
+
+>>>>> I agree.  I'm working on this for for both new pages and existing pages.
+>>>>> It shouldn't be hard once I get WMD going through the javascript API.
+>>>>> At the moment that is inexplicably failing, and I haven't had time to have a good look at why.
+>>>>> I may not get a chance to look at this again for a few weeks.
+
+>>>> Can I get a license statement (ie, GPL-2+) ffrom you for the plugin?
+>>>> --[[Joey]] 
+
+>>>>> Certainly.  You're free to use the code I posted below under the GPL-2+ license.  You'll note
+>>>>> however that I haven't said anything about the WMD code itself.  The WMD web page says:
+
+>>>>>> "I'm refactoring the code, and will be releasing WMD under the MIT license soon. For now you can download the most recent release (wmd-1.0.1.zip) and use it freely."
+
+>>>>> It might be best to contact <support@attacklab.net> to for an explicit license on that if you want to include it.
+>>>>> -- [[Will]]
+
+> So, I wonder if I should add a copy of the WMD source to ikiwiki, or rely
+> on the user or distribution providing it. It does not seem to be packaged
+> for Debian yet. Hmm, I also can't find any copyright or license info in
+> the zip file. --[[Joey]] 
+
+>> This is a good question.  My thought is that it will probably not be packaged any time soon,
+>> so you're better off adding it to IkiWiki.  I'd contact the author of WMD and ask them.  They
+>> may have more insight.  -- [[Will]]
+
+Note that the WMD plugin does **not** handle directives.  For this reason the normal `preview` button
+remains.  Some CSS to clean up the display of the live WMD preview would be good.
+
+> Can you elucidate the CSS comment -- or will it be obvious what you mean
+> when I try it? Is it what's needed for the live preview? --[[Joey]]
+
+>> In the version of the plugin below, a new `div` is added just below the form.  WMD
+>> populates this div with the HTML it generates from the Markdown source.  This is not very
+>> pretty at the moment - it appears in the same place as the preview used to, but with no
+>> header or anything.  Any standard IkiWiki preview will appear below the WMD live preview.
+>> I recommend having a look at <http://wmd-editor.com/examples/splitscreen>
+>> for what a little CSS could achieve.  -- [[Will]]
+
+> Hmm, now that I've tried it, I notice that it does live preview by
+> default, below the edit window. Which is nice, but then if I hit the
+> preview button, I get two previews.. which is confusing. (Also, minor,
+> but: the live preview is missing the "Page Preview:" header.) --[[Joey]] 
+
+> I wonder how annoying it would be to add some kind of simplistic wikilink
+> support to wmd's preview? And/or a wikilink button? While not supporting
+> directies is fine, not supporting wikilinks in a wiki seems a bit
+> lacking. It may also entice novide users to not use wikilinks and instead
+> use the hyperlinks that wmd does support. --[[Joey]] 
+
+> Bug: When I preview, all the text in the edit field seems to be
+> converted from mdwn to html. I think that wmd is converting the mdwn
+> into html when the form is posted, so it would also save like that.
+> I assume that is designed for websites that do not use markdown
+> internally. Doesn't it have a setting to leave it as markdown?
+>> Found setting, fixed. --[[Joey]] 
+
+>>> As I noted above, I've been working on the non-markdown page issue.
+>>> Below is my a new javascript file that I'm using, and below that a patch
+>>> to enable it.  This patch makes the normal usage prettier - you get
+>>> a side panel with the live preview in it.  It also adds a new config
+>>> option, `wmd_use101api`, which turns on code that tries to use the
+>>> wmd api.  At the moment this code doesn't seem to work - moreover the
+>>> code that uses the new API dies early, so any code after that point is
+>>> completely untested.  I will not
+>>> get a chance to look at this again soon though, so I thought I'd post
+>>> my progress so far.  -- [[Will]]
+
+
+Place the following file in `underlays/wmd/wmd-ikiwiki.js`.
+
+----
+
+    // This is some code to interface the WMD interface 1.0.1 with IkiWiki
+    // The WMD interface is planned to change, so this file will likely need
+    // updating in future.
+    
+    if (useWMDinterface) {
+       wmd_options = { autostart: false, output: "Markdown" };
+       var instance = null;
+    
+       hook("onload", initwmd);
+    } else {
+       var typeSelector = document.getElementById("type");
+       
+       var currentType = getType(typeSelector);
+       
+       if (currentType == "mdwn") {
+               wmd_options = { output: "Markdown" };
+               document.getElementById("wmd-preview-container").style.display = 'none';
+       } else {
+               wmd_options = { autostart: false };
+               document.getElementById("wmd-preview-container").style.display = 'block';
+       }
+    }
+    
+    function initwmd() {
+       if (!Attacklab || !Attacklab.wmd) {
+               alert("WMD hasn't finished loading!");
+               return;
+       }
+       
+       var typeSelector = document.getElementById("type");
+       
+       var currentType = getType(typeSelector);
+       
+       if (currentType == "mdwn") {
+               window.setTimeout(enableWMD,10);
+       }
+       
+       typeSelector.onchange=function() {
+               var docType=getType(this);
+               
+               if (docType=="mdwn") {
+                       enableWMD();
+               } else {
+                       disableWMD();
+               }
+       }
+    }
+    
+    function getType(typeSelector)
+    {
+       if (typeSelector.nodeName.toLowerCase() == 'input') {
+               return typeSelector.getAttribute('value');
+       } else if (typeSelector.nodeName.toLowerCase() == 'select') {
+               return typeSelector.value;
+               // return typeSelector.options[typeSelector.selectedIndex].innerText;
+       }
+       return "";
+    }
+    
+    function enableWMD()
+    {
+       var editContent = document.getElementById("editcontent");
+       var previewDiv = document.getElementById("wmd-preview");
+       var previewDivContainer = document.getElementById("wmd-preview-container");
+       
+       previewDivContainer.style.display = 'block';
+       // editContent.style.width = previewDivContainer.style.width;
+       
+       /***** build the preview manager *****/
+       var panes = {input:editContent, preview:previewDiv, output:null};
+       var previewManager = new Attacklab.wmd.previewManager(panes);
+    
+       /***** build the editor and tell it to refresh the preview after commands *****/
+       var editor = new Attacklab.wmd.editor(editContent,previewManager.refresh);
+    
+       // save everything so we can destroy it all later
+       instance = {ta:editContent, div:previewDiv, ed:editor, pm:previewManager};
+    }
+    
+    function disableWMD()
+    {
+       document.getElementById("wmd-preview-container").style.display = 'none';
+    
+       if (instance != null) {
+               instance.pm.destroy();
+               instance.ed.destroy();
+               // inst.ta.style.width='100%'
+       }
+       instance = null;
+    }
+
+
+----
+
+    diff --git a/IkiWiki/Plugin/wmd.pm b/IkiWiki/Plugin/wmd.pm
+    index 9ddd237..743a0b8 100644
+    --- a/IkiWiki/Plugin/wmd.pm
+    +++ b/IkiWiki/Plugin/wmd.pm
+    @@ -17,6 +17,13 @@ sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+    +                  rebuild => 1,
+    +          },
+    +          wmd_use101api => {
+    +                  type => "boolean",
+    +                  description => "Use the advanced, but unstable, WMD api for markdown preview.",
+    +                  safe => 0,
+    +                  rebuild => 0,
+               },
+     }
+     
+    @@ -24,29 +31,25 @@ sub formbuilder_setup (@) {
+       my %params=@_;
+       my $form=$params{form};
+     
+    -  return if ! defined $form->field("do");
+    +  return unless defined $form->field("do");
+       
+       return unless $form->field("do") eq "edit" ||
+    -                  $form->field("do") eq "create" ||
+    -                  $form->field("do") eq "comment";
+    -
+    -  $form->tmpl_param("wmd_preview", "<div class=\"wmd-preview\"></div>\n".
+    -          include_javascript(undef, 1));
+    -}
+    -
+    -sub include_javascript ($;$) {
+    -  my $page=shift;
+    -  my $absolute=shift;
+    -
+    -  my $wmdjs=urlto("wmd/wmd.js", $page, $absolute);
+    -  return <<"EOF"
+    -<script type="text/javascript">
+    -wmd_options = {
+    -  output: "Markdown"
+    -};
+    -</script>
+    -<script src="$wmdjs" type="text/javascript"></script>
+    -EOF
+    +                          $form->field("do") eq "create" ||
+    +                          $form->field("do") eq "comment";
+    +
+    +  my $useAPI = $config{wmd_use101api}?'true':'false';
+    +  my $ikiwikijs = urlto("ikiwiki.js", undef, 1);
+    +  my $wmdIkiwikijs = urlto("wmd-ikiwiki.js", undef, 1);
+    +  my $wmdjs = urlto("wmd.js", undef, 1);
+    +
+    +  my $previewScripts = <<"EOS";
+    +          <script type="text/javascript">useWMDinterface=$useAPI;</script>
+    +          <script src="$ikiwikijs" type="text/javascript"></script>
+    +          <script src="$wmdIkiwikijs" type="text/javascript"></script>
+    +          <script src="$wmdjs" type="text/javascript"></script>
+    +EOS
+    +
+    +  $form->tmpl_param("wmd_preview", $previewScripts);
+     }
+     
+     1
+    diff --git a/doc/style.css b/doc/style.css
+    index a6e6734..36c2b13
+    --- a/doc/style.css
+    +++ b/doc/style.css
+    @@ -76,9 +76,16 @@ div.tags {
+       float: right;
+     }
+     
+    +/*
+     #editcontent {
+       width: 100%;
+     }
+    +*/
+    +
+    +#wmd-preview-container {
+    +  width: 49%;
+    +  float: right;
+    +}
+     
+     img {
+       border-style: none;
+    diff --git a/templates/editpage.tmpl b/templates/editpage.tmpl
+    index b1cf015..1d2f080 100644
+    --- a/templates/editpage.tmpl
+    +++ b/templates/editpage.tmpl
+    @@ -15,6 +15,14 @@ Page type: <TMPL_VAR FIELD-TYPE>
+     <TMPL_VAR FIELD-PAGE>
+     <TMPL_VAR FIELD-TYPE>
+     </TMPL_IF>
+    +<TMPL_IF NAME="WMD_PREVIEW">
+    +<div id="wmd-preview-container">
+    +<div  class="header">
+    +<span>Live preview:</span>
+    +</div>
+    +<div class="wmd-preview" id="wmd-preview"></div>
+    +</div>
+    +</TMPL_IF>
+     <TMPL_VAR FIELD-EDITCONTENT><br />
+     <TMPL_IF NAME="CAN_COMMIT">
+     Optional comment about this change:<br />
index 0a1098f70fe3ff3d922ac949ebd61865a47a2d05..e71c8106adc832fb30203868174cd857a79450e3 100644 (file)
@@ -1,6 +1,3 @@
-* Need to get post commit hook working (or an example of how to use it.)
-  * See below. --[[bma]]
-* rcs_notify is not implemented (not needed in this branch --[[Joey]])
 * Is the code sufficiently robust? It just warns when mercurial fails.
 * When rcs_commit is called with a $user that is an openid, it will be
   passed through to mercurial -u. Will mercurial choke on this?
   It seems that with the current mercurial commit code, it will always
   blindly overwrite the current file with the web edited version, losing
   any other changes.
+* `rcs_commit_staged`, `rcs_rename`, `rcs_remove`, and `rcs_diff` are not
+  implemented for mercurial, and so attachments, remove and rename plugins
+  and recentchangesdiff cannot be used with it. (These should be fairly
+  easy to add..)
 
 Posthook: in `$srcdir/.hg/hgrc`, I have the following
 
@@ -32,6 +33,62 @@ This should update the working directory and run ikiwiki every time a change is
 > It can deadlock if the post-commit hook runs with --refresh in the
 > former case. --[[Joey]]
 
+The problem with --post-commit is that if you delete some pages in $SRC, ikiwiki --setup setupfile --post-commit will not delete them in $DEST. --[[users/weakish]]
+
+> You should really be using a setup file that has `mercurial_wrapper`
+> set, and running the wrapper generated by that from your hook.
+> That will work. I think that the `--setup --post-commit` on the command
+> line is currently broken and does the same expensive rebuild process as --setup
+> alone (which doesn't delete files from $DEST either). Will fix that.
+> (fixed)
+> --[[Joey]] 
+
+>> Mercurial doesn't support put hooks in .hg/hooks/* (like git). In Mercurial, the only way to run
+>> your own hooks is specifying them in the hgrc file. (Or write a new extension.)
+>> I guess use a very long command will work.
+>> (e.g. ikiwiki --post-commit --a-lot-of-switches --set var=value $SRC $DEST)
+>> (Fortunately ikiwiki supports --set var=value so without --setup works.)
+>>
+>> Alternative is always editing via cgi or pushing.  Never work on the $SRC/repo directly.
+>> --[[users/weakish]]
+
+>>> I don't see anything preventing you from using a setup file with
+>>> `mercurial_wrapper => ".hg/ikiwiki-hook",` and then modifying the hgrc
+>>> to run that wrapper. --[[Joey]] 
+
+>> Thanks for pointing out this.  I have some stupid misunderstanding on the
+>> usage of mercurial_wrapper before.  The wrapper works nicely! --[[weakish]]
+
+I add the following to .hg/hgrc:(I use changegroup since I don't think we need refresh per changeset, please point out if I am wrong.)
+
+    [hooks]
+    changegroup = hg update >&2 && ikiwiki --setup path.to.setup.file --refresh
+    post-commit = path.to.the.mercurial.wrapper
+
+-----
+
+I have no idea when the deadlock will happen.  --[[users/weakish]]
+
+> For the deadlock to occur, a edit has to be made via the web.
+> 
+> Ikiwiki,
+> running as a CGI, takes a lock on the wiki, and commits the edit,
+> continuing to run in the background, with the lock still held.
+> When the edit is committed, the hg hook runs, running `ikwiki --refresh`.
+> Nearly the first thing that process does it try to lock the wiki..
+> which is already locked. This lock is taken in a blocking manner,
+> thus the deadlock -- the cgi is waiting for the commit to finish before
+> dropping the lock, and the commit is blocked waiting for the lock to be
+> released.
+> 
+> --post-commit avoids this problem by checking if the cgi is running
+> and avoiding doing anything in that case. (While still handing the
+> refresh if the commit was not made by the CGI.)
+> So in that case, the commit finishes w/o ikiwiki doing anything,
+> and the ikiwiki CGI handles the wiki refresh.
+> --[[Joey]]  
+
+
 ***
 
 I have a few notes on mercurial usage after trying it out for a while:
index a09a48a641949c7ab9cd3ccf8b22f37ba1e2fd0d..9e112317f01fe4f2466d9b9652d18f04133fedb3 100644 (file)
@@ -1,9 +1,9 @@
-The following patch adds an 'rcsid' parameter to the Meta plugin, to allow inclusion 
+The following patch adds an 'rcsid' parameter to the [[!taglink plugins/Meta]] plugin, to allow inclusion 
 of CVS/SVN-style keywords (like '$Id$', etc.) from the source file in the page template.
 
 > So the idea is you'd write something like:
 > 
->      \[[meta rcsid="$Id$"]]
+>      \[[!meta rcsid="$Id$"]]
 > 
 > And this would be put at the bottom of the page or somewhere like that by
 > the template?
@@ -26,7 +26,7 @@ of CVS/SVN-style keywords (like '$Id$', etc.) from the source file in the page t
      my %copyright;
     +my %rcsid;
  
-     sub import { #{{{
+     sub import {
         hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1);
     @@ -110,6 +111,9 @@
             $meta{$page}.="<link rel=\"copyright\" href=\"#page_copyright\" />\n";
index bf81913300a1066550212a424647c0e1aab20761..361f0035188e9624a00853fc8dbfc1536599d6a0 100644 (file)
@@ -1,7 +1,7 @@
 There should be a way to add metadata to a page. Probably a plugin could do
 this, for example:
 
-       \[[meta foo="bar"]]
+       \[[!meta foo="bar"]]
 
 Uses for this include:
 
@@ -11,9 +11,9 @@ Uses for this include:
   except it doesn't have to show up in the page text.
 * Recording page licenses.
 
-[[meta link=done]]
-[[meta title="supporting metadata..."]]
-[[meta author="Joey Hess"]]
-[[meta link="foo.css" rel="stylesheet" type="text/css"]]
+[[!meta link=done]]
+[[!meta title="supporting metadata..."]]
+[[!meta author="Joey Hess"]]
+[[!meta link="foo.css" rel="stylesheet" type="text/css"]]
 
 [[todo/done]]
index fe47ab52f438aae2f722286bb99c989359dcb0b1..c2dd5fbf46315088025ae50716c62d1eca81c940 100644 (file)
@@ -18,7 +18,7 @@ turn on feeds for recentchanges.
             # Allow generating feeds even if not generated by default?
             #allowrss => 1,
 
-[[tag patch]]
+[[!tag patch]]
 
 > Hmm, recentchanges is just a blog. Of course the word "blog" is perhaps
 > being used in too broad a sense here, since it tends to imply personal
diff --git a/doc/todo/mirrorlist_with_per-mirror_usedirs_settings.mdwn b/doc/todo/mirrorlist_with_per-mirror_usedirs_settings.mdwn
new file mode 100644 (file)
index 0000000..6ca9962
--- /dev/null
@@ -0,0 +1,24 @@
+I've got a wiki that is built at two places:
+
+* a static copy, aimed at being viewed without any web server, using
+  a web browser's `file:///` urls => usedirs is disabled to get nice
+  and working links
+* an online copy, with usedirs enabled in order to benefit from the
+  language negotiation using the po plugin
+
+I need to use mirrorlist on the static copy, so that one can easily
+reach the online, possibly updated, pages. But as documented, "pages are
+assumed to exist in the same location under the specified url on each
+mirror", so the generated urls are wrong.
+
+My `mirrorlist` branch contains a patch that allows one to configure usedirs
+per-mirror. Note: the old configuration format is still supported, so this should
+not break existing wikis.
+
+OT: as a bonus, this branch contains a patch to support {hashes,arrays} of
+{hashes,arrays} in `$config`, which I missed a bit when writing the po plugin,
+and decided this time it was really needed to implement this feature.
+
+--[[intrigeri]]
+
+[[!tag patch]]
index a85630ea35ef183a6abe3de63b4fc1f0351d4954..cecac7a94010dec37e9caf6b4eec4c414c426d4a 100644 (file)
@@ -4,9 +4,9 @@ has a child). Basically, you give it a page called missingparents.mdwn,
 something like this:
 
 <pre>
-[[missingparents pages="posts/* and !posts/*/*" generate="""[[template id=year text="$page"]]"""]]
-[[missingparents pages="posts/*/* and !posts/*/*/*" generate="""[[template id=month text="$page"]]"""]]
-[[missingparents pages="posts/*/*/* and !posts/*/*/*/*" generate="""[[template id=day text="$page"]]"""]]
+[[!missingparents pages="posts/* and !posts/*/*" generate="""[[!template id=year text="$page"]]"""]]
+[[!missingparents pages="posts/*/* and !posts/*/*/*" generate="""[[!template id=month text="$page"]]"""]]
+[[!missingparents pages="posts/*/*/* and !posts/*/*/*/*" generate="""[[!template id=day text="$page"]]"""]]
 </pre>
 
 And it scans the whole wiki for pages that match the pagespecs but are missing
@@ -82,15 +82,15 @@ Index: IkiWiki/Plugin/missingparents.pm
 +my %ownfiles;
 +my @pagespecs;
 +
-+sub import { #{{{
++sub import {
 +      hook(type => "checkconfig", id => "missingparents", call => \&checkconfig);
 +      hook(type => "needsdelete", id => "missingparents", call => \&needsdelete);
 +      hook(type => "needsbuild", id => "missingparents", call => \&needsbuild);
 +      hook(type => "savestate", id => "missingparents", call => \&savestate);
 +      hook(type => "preprocess", id => "missingparents", call => \&preprocess_missingparents);
-+} # }}}
++}
 +
-+sub checkconfig () { #{{{
++sub checkconfig () {
 +      IkiWiki::preprocess("missingparents", "missingparents",
 +              readfile(srcfile("missingparents.mdwn")));
 +      loadstate();
@@ -99,13 +99,13 @@ Index: IkiWiki/Plugin/missingparents.pm
 +                      unlink $config{srcdir}.'/'.$file;
 +              }
 +      }
-+} #}}}
++}
 +
-+sub preprocess_missingparents (@) { #{{{
++sub preprocess_missingparents (@) {
 +      my %params=@_;
 +
 +      if (! defined $params{pages} || ! defined $params{generate}) {
-+              return "[[missingparents ".gettext("missing pages or generate parameter")."]]";
++              return "[[!missingparents ".gettext("missing pages or generate parameter")."]]";
 +      }
 +
 +      push @pagespecs, \%params;
@@ -115,10 +115,10 @@ Index: IkiWiki/Plugin/missingparents.pm
 +      #translators: is text for pages that match that pagespec.
 +      return sprintf(gettext("missingparents in %s will be %s"), 
 +                     '`'.$params{pages}.'`', '`\\'.$params{generate}.'`');
-+} # }}}
++}
 +
 +my $state_loaded=0;
-+sub loadstate() { #{{{
++sub loadstate() {
 +      my $filename = "$config{wikistatedir}/missingparents";
 +      if (-e $filename) {
 +              open (IN, $filename) ||
@@ -132,9 +132,9 @@ Index: IkiWiki/Plugin/missingparents.pm
 +
 +              $state_loaded=1;
 +      }
-+} #}}}
++}
 +
-+sub savestate() { #{{{
++sub savestate() {
 +      my $filename = "$config{wikistatedir}/missingparents.new";
 +      my $cleanup = sub { unlink ($filename) };
 +      open (OUT, ">$filename") || error("open $filename: $!", $cleanup);
@@ -143,9 +143,9 @@ Index: IkiWiki/Plugin/missingparents.pm
 +      }
 +      rename($filename, "$config{wikistatedir}/missingparents") ||
 +              error("rename $filename: $!", $cleanup);
-+} #}}}
++}
 +
-+sub needsdelete (@) { #{{{
++sub needsdelete (@) {
 +      my $files=shift;
 +      
 +      my @mydel;
@@ -167,9 +167,9 @@ Index: IkiWiki/Plugin/missingparents.pm
 +      foreach my $page (@mydel){
 +              push @{$files}, $page;
 +      }
-+} #}}}
++}
 +
-+sub check_matches($) { #{{{
++sub check_matches($) {
 +      my $page = shift;
 +      return if $IkiWiki::pagesources{$page};
 +
@@ -183,9 +183,9 @@ Index: IkiWiki/Plugin/missingparents.pm
 +              return $output;
 +      }
 +      return "";
-+} #}}}
++}
 +
-+sub needsbuild ($) { #{{{
++sub needsbuild ($) {
 +      my $files=shift;
 +      my @new;
 +
@@ -209,7 +209,7 @@ Index: IkiWiki/Plugin/missingparents.pm
 +              $ownfiles{$file} = 1;
 +              push @{$files}, $file;
 +      }
-+} #}}}
++}
 +
 +1
 Index: IkiWiki.pm
@@ -227,18 +227,18 @@ Index: IkiWiki.pm
  our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
 @@ -330,6 +336,30 @@
                error("failed renaming $newfile to $destdir/$file: $!", $cleanup);
- } #}}}
+ }
  
-+sub newpage($$) { #{{{
++sub newpage($$) {
 +      my $file=shift;
 +      my $page=shift;
 +
 +      $pagemtime{$page} = $pagectime{$page} = time;
 +      $pagesources{$page} = $file;
 +      $pagecase{lc $page} = $page;
-+} #}}}
++}
 +
-+sub delpage($) { #{{{
++sub delpage($) {
 +      my $page=shift;
 +      $links{$page}=[];
 +      $renderedfiles{$page}=[];
@@ -251,11 +251,11 @@ Index: IkiWiki.pm
 +                      delete $destsources{$_};
 +                      }
 +              }
-+} #}}}
++}
 +
  my %cleared;
- sub will_render ($$;$) { #{{{
+ sub will_render ($$;$) {
        my $page=shift;
 </pre>
 
-[[tag patch]]
+[[!tag patch patch/core]]
diff --git a/doc/todo/modify_page_filename_in_plugin.mdwn b/doc/todo/modify_page_filename_in_plugin.mdwn
new file mode 100644 (file)
index 0000000..a13c8b6
--- /dev/null
@@ -0,0 +1,35 @@
+I'm writing a plugin to wikify c/c++ code.
+
+By default ikiwiki generates xxx.html for a file called xxx.c.
+
+The problem is that I occasionally have xxx.c and xxx.h in the same directory and there's a filename collision.
+
+My solution is to allow plugins to provide a hook that sets the pagename. --[[/users/bstpierre]]
+
+> You might also find the solution to [[bugs/multiple_pages_with_same_name]] helps you.  That patch is already applied. -- [[Will]]
+
+    --- /usr/share/perl5/IkiWiki.pm.ORIG    2008-10-03 14:12:50.000000000 -0400
+    +++ /usr/share/perl5/IkiWiki.pm 2008-10-07 11:57:26.000000000 -0400
+    @@ -196,11 +196,32 @@
+
+     sub pagename ($) {
+            my $file=shift;
+
+            my $type=pagetype($file);
+    +
+    +   if(defined $type &&
+    +      exists $hooks{pagename} &&
+    +      exists $hooks{pagename}{$type}) {
+    +
+    +      return $hooks{pagename}{$type}{call}($file);
+    +
+    +   } else {
+    +
+            my $page=$file;
+            $page=~s/\Q.$type\E*$// if defined $type;
+            return $page;
+    +   }
+     }
+
+     sub htmlpage ($) {
+
index ea914e9ed2a601e54122fceb1176131b6b4298f5..cace27d63a4c70973f75aecff60e8122be77a3f3 100644 (file)
@@ -15,6 +15,8 @@ Here's the one-liner:
 
 > applied --[[Joey]]
 
+----
+
 The following adds a div element with class="trailer" around the meta-information
 added after an inlined page (namely: the post date, the tags, and the actions):
 
@@ -36,13 +38,13 @@ added after an inlined page (namely: the post date, the tags, and the actions):
     +
     +</div>
 
-[[tag patch]]
+[[!tag patch]]
 
 > Unfortunately, the inlinepage content passes through markdown, and markdown
 > gets confused by these nested div's and puts p's around one of them, generating
 > broken html. If you can come up with a way to put in the div that passes
 > the test suite, or a fix to markdown, I will accept it, but the above patch
-> fails the test suite. --[[Joey]] 
+> fails the test suite. --[[Joey]]
 
 >> Just a note...  This discrepancy doesn't exist in [pandoc](http://code.google.com/p/pandoc/) as
 >> demonstrated in the relevant [page](http://code.google.com/p/pandoc/wiki/PandocVsMarkdownPl).
@@ -53,7 +55,7 @@ added after an inlined page (namely: the post date, the tags, and the actions):
 >> alternatives is always a good thing and perhaps, the fact that pandoc can make markdown->LaTeX
 >> conversion may lead to new possibilities. --[[Roktas]]
 
->>> I confirm that this ([[debbug 405058]]) has just been fixed in markdown
+>>> I confirm that this ([[!debbug 405058]]) has just been fixed in markdown
 >>> [`1.0.2b7`](http://packages.debian.org/experimental/web/markdown) (BTW, thanks to your bug
 >>> report Joey).  FYI, I've observed some performance drop with `1.0.2b7` compared to `1.0.1`,
 >>> especially noticable with big files.  This was also confirmed by someone else, for example,
@@ -64,6 +66,16 @@ added after an inlined page (namely: the post date, the tags, and the actions):
 >>>> to at least get into debian testing before I make ikiwiki depend on it
 >>>> though. --[[Joey]]
 
+>> This Markdown issue seems to have been worked around by the optimization
+>> in which \[[!inline]] is replaced with a placeholder, and the
+>> placeholder is later replaced by the HTML. Meanwhile, this patch
+>> has been obsoleted by applying a similar one (wrapping things in a div
+>> with class inlinefooter). That was the last remaining unapplied patch
+>> on this page, so I think this whole page can be considered [[done]].
+>> --[[smcv]]
+
+----
+
 I'd like a class attribute on the `<span>` tag surrounding wikilinks
 that refer to non-existent pages, in Ikiwiki.pm:htmllink, so that such
 broken links can be styled more dramatically with CSS. --Jamey
index 51b5607465f0c74f1306ca8592ebb49b0988f36f..97fefbafc761ae7b9e163eddd7520c60b67ec223 100644 (file)
@@ -2,7 +2,9 @@ I understand the `IkiWiki::titlepage` function is used to generate filenames fro
 
 I imagine two things: a lookup hash and a template.
 
-Since `IkiWiki::titlepage` basically translates characters, it would be cool to be able to define a lookup hash in the configuration, which would be consulted before falling back to the generic `__xx__` `ord()` representation of a letter. For instance, in German, I might prefer to have 'Ã\83¤' become 'ae' instead of something illegible.
+Since `IkiWiki::titlepage` basically translates characters, it would be cool to be able to define a lookup hash in the configuration, which would be consulted before falling back to the generic `__xx__` `ord()` representation of a letter. For instance, in German, I might prefer to have 'ä' become 'ae' instead of something illegible.
+
+> This is [[todo/unaccent_url_instead_of_encoding]]. --[[smcv]]
 
 Second, maybe a template could be honoured. The template could have a slot `%s` where the calculated title goes, and it could contain `strftime` symbols as well as variables, which get interpolated on use.
 
@@ -10,6 +12,11 @@ Another option would be a function I could define in the setup file, or an exter
 
 -- [[madduck]]
 
+> This somewhat resembles [[todo/inline_postform_autotitles]].
+> Another way to do this, suggested in that todo, would be to
+> pre-fill the title field with YYYY/MM/DD/ using Javascript.
+> --[[smcv]]
+
 I don't think that changing titlepage is a good idea, there are
 compatability problems.
 
@@ -28,4 +35,8 @@ is that having the directive appear in the edit box for a new page could
 confuse the user. The title could be passed on in a hidden field, and
 prepended to the page when it's saved..
 
+--[[Joey]]
+
+> I'll pass on these comments to the two similar todo items. --[[smcv]]
+
 [[wishlist]]
diff --git a/doc/todo/more_flexible_inline_postform.mdwn b/doc/todo/more_flexible_inline_postform.mdwn
new file mode 100644 (file)
index 0000000..bc8bc08
--- /dev/null
@@ -0,0 +1,18 @@
+Using the [[plugins/inline]] plugin, you can get an inline-postform for
+creating new pages.
+
+It would be quite nice to have the flexibility to do this outside of the
+inline directive.
+
+I've got a proof-of-concept hacked inline comment submission example at
+<http://dev.jmtd.net/comments/> for example. I've just copied the HTML from
+the post form and stuck it inside a [[plugins/toggle]].
+
+(Before Simon completed the comments plugin, I thought this would the a
+logical first step towards doing comment-like things with inlined pages).
+
+-- [[Jon]]
+
+> Perhaps what we need is a `postform` plugin/directive that inline depends
+> on (automatically enables); its preprocess method could automatically be
+> invoked from preprocess_inline when needed. --[[smcv]]
index 92cbe84ff40922a725a5d07e0eee967a074ba04e..22d4cd4ff5c9aadfcd6f8767e93bf799fa91ca56 100644 (file)
@@ -12,3 +12,5 @@ plugin changes page content without any younger page being involved. And
 editing one of the html templates and rebuilding the wiki can change every
 page. All of these need to be reflected in the file mtime to avoid caching
 problems.
+
+[[!tag wishlist]]
index 00623be3911d36009d1630ce29666c1c7a6c29f8..0538f894c23da74410b9ff2a357f1f17e215bbfb 100644 (file)
@@ -14,4 +14,4 @@ would be impractical to say the least.
 
 --[[bma]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
diff --git a/doc/todo/multiple_repository_support.mdwn b/doc/todo/multiple_repository_support.mdwn
new file mode 100644 (file)
index 0000000..0625dba
--- /dev/null
@@ -0,0 +1,15 @@
+I'd like to be able to use one git repository for my basic website, and
+another one for the big files (pictures, videos), and another one for temp
+files. This way I'd not bloat the basic repo, and I could toss temp files
+up, and throw the temp repo away periodically.
+
+For this to work really well, ikiwiki would need multiple repository
+support. Possibly it could be tied into 'mr'?
+
+Another thought is that it would be good if ikiwiki could determine the
+type of repo a subdirectory is in by itself, eliminating the need to
+manually configure it in the setup file.
+
+--[[Joey]]
+
+[[!tag wishlist]]
index d165eebafff5ecbe93360b888020dfbdf4ef190e..72783c556d3ddcaeeb6dfa616de918cefdcd312e 100644 (file)
@@ -1,5 +1,5 @@
 > Another useful feature might be to be able to choose a different [[template|wikitemplates]]
-> file for some pages; [[blog|ikiwiki/blog]] pages would use a template different from the
+> file for some pages; [[blog]] pages would use a template different from the
 > home page, even if both are managed in the same repository, etc.
 
 Well, that would probably be fairly easy to add if it used [[pagespecs|ikiwiki/pagespec]] to
diff --git a/doc/todo/natural_sorting.mdwn b/doc/todo/natural_sorting.mdwn
new file mode 100644 (file)
index 0000000..5df17e9
--- /dev/null
@@ -0,0 +1,21 @@
+[[!tag wishlist]]
+[[!tag patch]]
+
+the inline plugin's sorting is plain lexical, thich may not be appropriate for
+page titles if they have numeric components. the
+[Sort::Naturally](http://search.cpan.org/dist/Sort-Naturally/) perl module
+provides an algorithm for that.
+
+there is a
+[patch](http://git.ikiwiki.info/?p=ikiwiki;a=commit;h=55b83cb7bd1cd7c60bb45dc22c3745dd80a63fed)
+attached that makes the [[plugins/inline]] plugin use Sort::Naturally if sort
+is set to "title_natural".
+
+the current patch uses `require Sort::Naturally`, so
+[libsort-naturally-perl](http://packages.debian.org/libsort-naturally-perl)
+does not become a dependency; it might be worth suggesting, though.
+
+> See also: [[inline:_numerical_ordering_by_title]] (I probably prefer your
+> approach..) --[[Joey]] 
+
+> [[applied|done]]
diff --git a/doc/todo/need_global_renamepage_hook.mdwn b/doc/todo/need_global_renamepage_hook.mdwn
new file mode 100644 (file)
index 0000000..e3cec4a
--- /dev/null
@@ -0,0 +1,115 @@
+As documented in [[plugins/write]], the current `renamepage` hook is
+heavily oriented towards updating links in pages' content:  it is run
+once per page linking to the renamed page.
+
+That's fine, but it can't be used to trigger more general actions on
+page rename. E.g. it won't be run at all if the page being renamed is
+an orphan one.
+
+This is a real issue for the [[plugins/contrib/po]] development: what
+I'm about to achieve is:
+
+- when a master page is renamed, the plugin takes notice of it (using
+  the `rename` hook), and later renames the translation pages
+  accordingly (in the `change` hook)
+- when a master page is deleted, the plugin deletes its translations
+  (using the `delete` hook)
+
+With the current `renamepage` hook behavior, combining these two goals
+has an annoying drawback: a plugin can't notice an orphan master page
+has been renamed, so instead of renaming (and preserving) its
+translations, it considers the oldpage as deleted, and deletes its
+translations. Game over.
+
+It may seem like a corner case, but I want to be very careful when
+deleting files automatically in `srcdir`, which is not always under
+version control.
+
+As a sad workaround, I can still disable any deletion in `srcdir`
+when it is not under version control. But I think ikiwiki deserves
+a global `renamepage` hook that would be run once per rename
+operation.
+
+My proposal is thus:
+
+- keep the documented `renamepage` hook as it is
+- use something inspired by the trick `preprocess` uses: when `hook`
+  is passed an optional "global" parameter, set to a true value, the
+  declared `renamepage` hook is run once per rename operation, and is
+  passed named parameters: `src`, `srcfile`, `dest` and `destfile`.
+
+I'm of course volunteering to implement this, or anything related that
+would solve my problem. Hmmm? --[[intrigeri]]
+
+> I think it would be better to have a different hook that is called for
+> renames, since the two hook actions are very different (unlike the
+> preprocess hook, which does a very similar thing in scan mode).
+> 
+> Just calling it `rename` seems like a reasonable name, by analogy with
+> the `delete` and `change` hooks.
+> 
+> It might make sense to rename `renamepage` to `renamelink` to make it
+> clearer what it does. (I'm not very worried about this breaking things, at
+> this point.) --[[Joey]]
+
+>> In my `po` branch, I renamed `renamepage` to `renamelink`, and
+>> created a `rename` hook that is passed a reference to `@torename`.
+>> --[[intrigeri]]
+
+>>> As Joey highlights it on [[plugins/contrib/po]], it's too late to
+>>> merge such a change, as the 3.x plugin API is released and should
+>>> not be broken. I will thus keep the existing `renamepage` as it
+>>> is, and call `rename` the global hook I need. --[[intrigeri]]
+
+>>>> [[Done]] in my `po` branch. --[[intrigeri]]
+
+I think I see a problem in the rename hook. The hook is called
+before the plugin adds any subpages to the set of pages to rename.
+So, if the user choses to rename subpages, po will not notice
+they are moving, and will not move their po files.
+Perhaps the hooks should be moved to come after subpages are added.
+This would, though, mean that if the hook somehow decides to add
+entirely other pages to the list, their subpages would not be
+automatically added.
+
+I also have some qualms about the design of the hook. In particular,
+passing the mutable array reference probably makes it impossible
+to use from external plugins. Instead it could return any additional
+rename hashes it wants to add. Or, if the ability to modify existing
+hashes is desired, it could return the full set of hashes.
+
+--[[Joey]] 
+
+> I fixed the last part, i.e. a rename hook function now returns the
+> full set of hashes. As I also converted it to take named parameters,
+> such a function still is passed a reference to the original array,
+> though, because one can't build a hash containing an array of hashes
+> as a value, without passing this array as a reference.
+> 
+>> Sure.
+> 
+> I'm not entirely sure about your first concern. Calling the hook
+> before or after the subpages addition both have their own problems.
+> 
+> What about running the hook before *and* after the subpages
+> addition, with an additional `when` named parameter, so that
+> a given hook function can choose to act only before or after, or both?
+> 
+> --[[intrigeri]]
+>> 
+>> Have you thought about making the hook be run once *per* file that is
+>> selected to be renamed? This would even handle the case where two
+>> plugins use the hook; plugin A would see when plugin B adds a new file
+>> to be renamed. And the subpage renaming stuff could probably be moved
+>> into the rename hook too. --[[Joey]] 
+>>>
+>>> I've implemented this nice solution in my po branch, please review.
+>>> I'm slowly coming back to do the last bits needed to get my po and
+>>> meta branch merged.  --[[intrigeri]]
+
+>>>> It looks good. I made some small changes to it in my own po branch.
+>>>> Nothing significant really. If this were not tied up in the po branch,
+>>>> I've have merged it to master already. --[[Joey]] 
+
+>>>> Thanks, this is great :) --[[intrigeri]]
index 7e7ef3a49bec60ad1bd4c784d286f043dcfe5d40..b5080dc3ca22ef24ad87de301f3cc7b0f584b567 100644 (file)
@@ -11,8 +11,8 @@ nesting, a new syntax would be needed. Maybe something xml-like?
 >
 > For example, I *think* you can unambiguously parse the following:
 >
->     \[[if test="enabled(template) and templates/foo" then="""
->     [[template id=foo content="""Flying Purple People Eater"""]]
+>     \[[!if test="enabled(template) and templates/foo" then="""
+>     [[!template id=foo content="""Flying Purple People Eater"""]]
 >     """]]
 >
 > --[[JoshTriplett]]
diff --git a/doc/todo/online_configuration.mdwn b/doc/todo/online_configuration.mdwn
new file mode 100644 (file)
index 0000000..02a8c6e
--- /dev/null
@@ -0,0 +1,28 @@
+It should be possible to configure ikiwiki online, in the wiki admin's
+preferences form. Rather than the current situation where most settings are
+in ikiwiki.setup, and one or two (like locked pages and upload limits) in
+the admin preferences.
+
+In theory, every setting could be configured there. In practice, some
+settings, like `srcdir` and `destdir` are ones you want to keep far away
+from editing via the web.
+
+The underlying work has been done to privide metadata about all options via
+getsetup hooks, so it's just a matter of writing a web interface plugin.
+
+The plugin could have these config options:
+
+       # list of options to include in web setup (safe = all things with safe = 1)
+       websetup_include => [qw{safe}],
+       # list of options to exclude from web setup
+       websetup_exclude => [qw{option_baz}],
+       # list of plugins that cannot be enabled/disabled via the web
+       # interface
+       websetup_force_plugins => [qw{git svn bzr mercurial monotone tla}]
+
+Leaning toward just making it write out to the same setup file, rather than
+writing to a subsidiary setup file. However, this would mean that any
+comments in the file would be lost, and that it couldn't be used if the
+setup file had weird stuff (perl code, etc).
+
+[[!tag wishlist done]]
index 582c03ef1f3fc63850270f1c4e74232ff796e47c..b8c4fa0dabdf387dcd23a4015750f2fa18f37922 100644 (file)
@@ -3,6 +3,13 @@ Ikiwiki has already been optimised a lot, however..
 * Look at splitting up CGI.pm. But note that too much splitting can slow
   perl down.
 
+  > It's split enough, or possibly more than enough, now. :-)
+
 * The backlinks calculation code is still O(N^2) on the number of pages.
   If backlinks info were stored in the index file, it would go down to
   constant time for iterative builds, though still N^2 for rebuilds.
+
+  > Seems to be O(Num Pages * Num Links in Page), or effectively O(N)
+  > pages for most wikis.
+
+[[done]]
diff --git a/doc/todo/overriding_displayed_modification_time.mdwn b/doc/todo/overriding_displayed_modification_time.mdwn
new file mode 100644 (file)
index 0000000..160d315
--- /dev/null
@@ -0,0 +1,27 @@
+Some aggregators, like Planet, sort by mtime rather than ctime. This
+means that posts with modified content come to the top (which seems odd
+to me, but is presumably what the aggregator's author or operator
+wants),
+
+> Hah! That's so charitable I hope you can deduct it from your taxes. ;-)
+> --[[Joey]] 
+
+but it also means that posts with insignificant edits (like
+adding tags) come to the top too. Atom defines `<updated>` to be the date
+of the last *significant* change, so it's fine that ikiwiki defaults to
+using the mtime, but it would be good to have a way for the author to
+say "that edit was insignificant, don't use that mtime".
+
+> Yes, this is a real limitiation of ikiwiki's atom support. --[[Joey]] 
+
+See smcv's 'updated' branch for a basic implementation, which only affects
+the Atom `<updated>` field or the RSS equivalent.
+
+Other places the updated metadata item could be used (opinions on whether
+each should use it or not, please):
+
+* sorting by mtime in the inline directive
+* displaying "last edited" on ordinary pages
+
+> Tending toward no for both, but willing to be convinced otherwise..
+> [[merged|done]] --[[Joey]]  
diff --git a/doc/todo/page_edit_disable.mdwn b/doc/todo/page_edit_disable.mdwn
new file mode 100644 (file)
index 0000000..a6977e7
--- /dev/null
@@ -0,0 +1,53 @@
+Disabling some of action URLs is not possible now without creating own
+version of `templates/page.tmpl` file. For example, how to disable
+displaying `EDITURL`, `RECENTCHANGESURL` or `PREFSURL` without
+touching original `page.tmpl` template?
+
+Now I can only enable/disable `HISTORYURL` and `DISCUSSIONLINK`.
+It's not hard for me, but I think that the way to do it can be
+confusing for another Ikiwiki users. For example, if I don't
+want `HISTORYURL`, then I need to comment `historyurl` hash
+in setup file. But if I want to disable discussions, then I need
+to set `discussion=0` there. So, you can see that we don't have
+one common method here.
+
+Maybe Ikiwiki setup file should has more hashes for action URLs,
+for example `edit=[01]`, `recentchanges=[01]`, `prefs=[01]`
+and `history=[01]`?
+
+If you are curious why I need that features, I can clarify it.
+I'm building "parallel" version of my site. It means that I want
+to have one editable version for internal users and second only
+readable version (+ search feature) for external users. I build
+both versions on secure, internal machine from the same pages,
+of course, and separated setup files and different templates.
+The readable version of the site will be rsynced to clustered WWW
+front-ends immediately via `post-commit` hook file or periodically
+by Cron. I haven't decided how to do it yet. --[[Paweł|ptecza]]
+
+> You disable display of recentchanges by disabling that plugin.
+
+>> Thanks for the hint! I didn't think about it :)
+
+> You disable edit and preferences by not enabling a cgiurl at all.
+
+>> Yes, I've just discovered it. Unfortunately I need cgiurl,
+>> because I would like to use searching feature also for read-only
+>> pages.
+
+> Maybe page editing will become a plugin some day, or be made
+> configurable -- there are a few things like searching and websetup
+> (and possibly the poll plugin, aggregate webtrigger, and pingee)
+> that it may make sense to enable a cgi for even if you don't want to
+> allow page editing. --[[Joey]]
+
+>> I'm glad you agree that it may make sense :) --[[Paweł|ptecza]]
+
+>> We're in a similar situation with http://web.monkeysphere.info 
+>> - wanting cgiurl so that our recentchanges page displays links, 
+>> but not wanting to enable editing of pages (since we're also 
+>> rsync'ing the html pages to mirrors) --[[Jamie]]
+
+editpage plugin implemented, [[done]] --[[Joey]]
+
+>> Joey, you're great! Thank you very, very, very much! :D --[[Paweł|ptecza]]
index 49f84c952561f1cf6ccdb615fba786147cadee07..6f67769f40ec26b3238d9925a07ce3d937a06acd 100644 (file)
@@ -1 +1,3 @@
 It would be nice to be able to delete pages online.
+
+> [[done]] though the [[plugins/remove]] plugin. --[[Will]]
index c2de20a341a86c0ad6b1e41cbf2e3a79a7b3f9a4..cf28bec964b386e77b68094ce7f92df19b38bbd5 100644 (file)
@@ -1,5 +1,5 @@
 Might be nice to support automatically generating an index based on headers
 in a page, for long pages. This could be done as a sanitize hook that
-parsed the html, with a preprocessordirective that controlled it.
+parsed the html, with a directive that controlled it.
 
 [[todo/done]]
index 62bb3ea29ec08ebb50fff308609096ecd97ff44e..00030cce61093192797a46a545389c324cf46078 100644 (file)
@@ -57,7 +57,7 @@ diff -urNX ignorepats ikiwiki/IkiWiki/Plugin/relative.pm ikidev/IkiWiki/Plugin/r
 +
 +package IkiWiki::PageSpec;
 +
-+sub match_relative($$;@) { #{{{
++sub match_relative($$;@) {
 +      my $parent = shift;
 +      my $spec = shift;
 +      my %params = @_;
@@ -69,29 +69,33 @@ diff -urNX ignorepats ikiwiki/IkiWiki/Plugin/relative.pm ikidev/IkiWiki/Plugin/r
 +              }
 +      }
 +      return IkiWiki::FailReason->new("$parent can't match $spec against anything");
-+} #}}}
++}
 +
-+sub match_has_child($$;@) { #{{{
++sub match_has_child($$;@) {
 +      my $page = shift;
 +      my $childname = shift;
 +      my $spec;
-+      if ($childname) { #{{{
++      if ($childname) {
 +              $spec = "$page/$childname or $page/*/$childname";
-+      } #}}}
-+      else { #{{{
++      }
++      else {
 +              $spec = "$page/*";
-+      } #}}}
++      }
 +
 +      return match_relative($page, $spec, @_);
-+} #}}}
++}
 +
 +1
 </pre>
 
-[[tag patch]]
+[[!tag patch]]
 
-> This looks really interesting.  It reminds me of XPath and its conditionals.
+> This looks really interesting.  It reminds me of [[!wikipedia XPath]] and its conditionals.
 > Those might actually work well adapted to pagespecs.  For instance, to write
 > "match any page with a child blah", you could just write *[blah] , or if you
 > don't want to use relative-by-default in the conditionals, *[./blah].
 > -- [[JoshTriplett]]
+
+> And it [[!taglink also_reminds_me|pagespec_in_DL_style]] of [[!wikipedia description logics]]: of course, given the relation `subpage` one could write a description-logic-style formula which would define the class of pages that are ("existentially") in a given relation (`subpage` or `inverse(subpage)*subpage`) to a certain other class of pages (e.g., named "blah") ("existentially" means there must exist a page, e.g., named "blah", which is in the given relation to the candidate).
+
+> Probably the model behind XPath is similar (although I don't know enough to say this definitely).--Ivan Z.
diff --git a/doc/todo/pagestats_among_a_subset_of_pages.mdwn b/doc/todo/pagestats_among_a_subset_of_pages.mdwn
new file mode 100644 (file)
index 0000000..fd15d6a
--- /dev/null
@@ -0,0 +1,29 @@
+[[!tag patch plugins/pagestats]]
+[[!template id=gitbranch branch=smcv/ready/among author="[[smcv]]"]]
+
+My `among` branch fixes [[todo/backlinks_result_is_lossy]], then uses that
+to provide pagestats for links from a subset of pages. From the docs included
+in the patch:
+
+> The optional `among` parameter limits counting to pages that match a
+> [[ikiwiki/PageSpec]]. For instance, to display a cloud of tags used on blog
+> entries, you could use:
+>
+>     \[[!pagestats pages="tags/*" among="blog/posts/*"]]
+>
+> or to display a cloud of tags related to Linux, you could use:
+> 
+>     \[[!pagestats pages="tags/* and not tags/linux" among="tagged(linux)"]]
+
+I use this on my tag pages on one site, with the following template:
+
+    \[[!pagestats pages="tags/* and !tags/<TMPL_VAR raw_tag>
+        and !tags/photogallery"
+      among="tagged(<TMPL_VAR raw_tag>)"]]
+
+    \[[!inline pages="tagged(<TMPL_VAR raw_tag>)"
+      archive="yes" quick="yes" reverse="yes" timeformat="%x"]]
+
+--[[smcv]]
+
+> [[merged|done]] thanks --[[Joey]] 
index 266686605428bf3e555e80f7e9558c1f05595f6f..2425645d94e3665da2e263e2aec349172da5c8da 100644 (file)
@@ -67,4 +67,4 @@ automatically.
 >>> Sure, a plugin is just a perl library so can easily be packaged
 >>> separately.
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 4bbda6565425e76e42bf8c11739f51e775180f65..29f28ca3246a853ee585beddc6348246c43b24fa 100644 (file)
@@ -1,4 +1,4 @@
-[[tag wishlist]]
+[[!tag wishlist plugins/passwordauth]]
 
 For sending out password reminder emails, the [[plugins/passwordauth]] plugin currently uses
 the *[Mail::Sendmail](http://search.cpan.org/perldoc?Mail::Sendmail)* module.
@@ -24,7 +24,7 @@ in the ikiwiki source code, where emailing is done.
 
 --[[tschwinge]]
 
-> One that is in Debian is [[cpan Email::Send]], which can do SMTP and
+> One that is in Debian is [[!cpan Email::Send]], which can do SMTP and
 > sendmail and some other methods and falls back through methods until one
 > succeeds. I haven't tried to use it but it looks like a feasable
 > candidate.
@@ -34,13 +34,13 @@ in the ikiwiki source code, where emailing is done.
 
 OK, so I'll have a look at replacing all email handling with *Email::Send*.
 
-[[tag patch]]
+[[!tag patch]]
 *<http://www.thomas.schwinge.homeip.net/tmp/ikiwiki-sendmail.patch>*
 
 Remaining TODOs:
 
   * Resolve TODOs as denoted inside the patch.
-  * Is it worthwhile to use and depend on [[cpan Return::Value]]
+  * Is it worthwhile to use and depend on [[!cpan Return::Value]]
     just for this bit of functionality?
   * Debian news file.
   * ikiwiki news file.
@@ -52,3 +52,10 @@ Remaining TODOs:
 > lost it. --[[Joey]]
 
 Resent.  --[[tschwinge]]
+
+> Debian now has Mail::Sender, Mail::SendEasy, and Email::Sender
+> (which, according to its dpkg description, "replaces the old and sometimes
+> problematic Email::Send library, which did a decent job at handling very
+> simple email sending tasks, but was not suitable for serious use, for a
+> variety of reasons"). Are any of those any better? It's unfortunate that
+> there doesn't seem to be a clear "best practice"... --[[smcv]]
diff --git a/doc/todo/paste_plugin.mdwn b/doc/todo/paste_plugin.mdwn
new file mode 100644 (file)
index 0000000..83384a8
--- /dev/null
@@ -0,0 +1,36 @@
+It was suggested that using ikiwiki as an alternative to pastebin services
+could be useful, especially if you want pastes to not expire and be
+cloneable.
+
+All you really need is a special purpose ikiwiki instance that you commit
+to by git. But a web interface for pasting could also be nice.
+
+There could be a directive that inserts a paste form onto a page. The form
+would have a big textarea for pasting into, and might also have a file
+upload button (for uploading instead of pasting). It could also copy the
+page edit form's dropdown of markup types, which would be especially useful
+if using the highlight plugin to support programming languages. The default
+should probably be txt, not mdwn, if the txt plugin is enabled.
+
+(There's a lot of overlap between that and editpage of course .. similar
+to the overlap between the comment form and editpage.)
+
+When posted, the form would just come up with a new, numeric subpage
+of the page it appears on, and save the paste there.
+
+Another thing that might be useful is a "copy" (or "paste as new") action
+on the action bar. This would take an existing paste and copy it into the
+paste edit form, for editing and saving under a new id.
+
+---
+
+A sample wiki configuration using this might be:
+
+* enable highlight and txt
+* enable anonok so anyone can paste; lock anonymous users down to only
+  creating new pastes, not editing other pages
+* disable modification of existing pastes (how? disabling editpage would
+  work, but that would disallow setting up anonymous git push)
+* enable comments, so that each paste can be commented on
+* enable getsource, so the source to a paste can easily be downloaded
+* optionally, enable untrusted git push
diff --git a/doc/todo/pedigree_plugin.mdwn b/doc/todo/pedigree_plugin.mdwn
new file mode 100644 (file)
index 0000000..1977c3d
--- /dev/null
@@ -0,0 +1,194 @@
+After realizing (thanks to
+[[Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename]])
+that I needed some kind of "parentlinks on steroids", I wrote a new
+plugin, called pedigree.
+
+This plugin provides a bunch of loops that one can use in his/her
+`HTML::Template`'s to iterate over all or a subset of a page's
+parents. Inside these loops, half a dozen variables are made
+available, in addition to `PAGE` and `URL` that are already provided
+by parentlinks.
+
+Amongst many possibilities, one can e.g. simply use this plugin to
+give every parent link a different `class=` attribute, depending
+either on its depth in the path leading to the current page, or on its
+distance to it.
+
+The code and documentation (including simple and complex usage
+examples) are in the 'pedigree' Git branch in this repo:
+
+       git://repo.or.cz/ikiwiki/intrigeri.git
+
+Seems there is also a [gitweb](http://repo.or.cz/w/ikiwiki/intrigeri.git).
+
+> Ok, I'll take a look. BTW, could you allow user joey on repo.or.cz
+> push access to the main ikiwiki repo you set up there? --[[Joey]]
+
+>> I did not. The main ikiwiki repo on repo.or.cz seems to have been
+>> been setup by johannes.schindelin@gmx.de ; mine is what they call
+>> a "fork" (but it's not, obviously). -- intrigeri
+
+Any opinions on the idea/design/implementation?
+
+> Seems that there should be a more generic way to do `PEDIGREE_BUT_ROOT`
+> and `PEDIGREE_BUT_TWO_OLDEST` (also `is_second_ancestor`,
+> `is_grand_mother` etc). One way would be to include in `PEDIGREE`
+> a set of values like `depth_1`, `depth_2`, etc. The one corresponding
+> to the `absdepth` would be true. This would allow a template like this:
+
+       <TMPL_LOOP NAME="PEDIGREE">
+         <TMPL_IF NAME="depth_1">
+           </TMPL_ELSE>
+           <TMPL_IF NAME="depth_2">
+           </TMPL_ELSE>
+             <TMPL_VAR PAGE> /* only showing pages 2 levels deep */
+           </TMPL_IF>
+         </TMPL_IF>
+       </TMPL_LOOP>
+
+> The only missing information would be `reldepth`, but in the above
+> example the author of that template knows that it's `absdepth - 1`
+> (Things would be a lot nicer if `HTML::Template` had equality tests!)
+> 
+> Since this would make it more generic and also fix your one documented
+> bug, I can see no reason not to do it. ;-) --[[Joey]]
+
+>> Thanks for your comments. I'll answer soon. (Grrr, I really
+>> need to find a way to edit this wiki offline, every minute
+>> online costs bucks to me, my old modem gently weeps,
+>> and I hate webbrowsers.) -- intrigeri
+
+>>> Well, I maybe didn't get your idea properly; I may be missing 
+>>> something obvious, but:
+
+>>> * I don't understand how this would replace `is_grand_mother`. As a template
+>>>   writer, I don't know, given an absolute array index (and this is the only
+>>>   piece of data your solution gives me), if it will be e.g. the before-last
+>>>   (how do I say this in correct English?) element of an array whose
+>>>   (variable) size is unknown to me.
+>>> * Knowing that `reldepth`'s value is, in a given loop, always equal to
+>>>   `absdepth - 1` is of little use to me (as a template writer): how do I use
+>>>   this piece of information programmatically in my templates, if I want all
+>>>   links with `reldepth==2` to be given the same style? I guess some bits of
+>>>   Javascript might do the trick, but if it's getting so complicated, I'll
+>>>   just style my parentlinks another way.
+
+>>>> Perhaps I misunderstood what `is_grand_mother` is supposed to do. The
+>>>> docs were not very clear to me. If it's supposed to be 2 down from
+>>>> the page, (and not from the root), this could be achieved by reversing
+>>>> the `depth_n` variables. So the page gets `depth_1` set, its parent gets
+>>>> `depth_2` set, etc. If you want to be able to include/exclude
+>>>> from both ends, you could also have a `height_n` that is 1 for the
+>>>> root, and counts upwards. --[[Joey]]
+
+>>> In my understanding, your suggestion gives us little more than can already
+>>> be achieved anyway with `HTML::Template`'s `loop_context_vars` (i.e.
+>>> `__first__`, `__last__` and `__counter__`). The only added bonus is doing
+>>> custom stuff for an arbitrary element in the loop, chosen by its absolute
+>>> depth. Please correct me if needed.
+
+>>> (Intermezzo: in the meantime, to suit my personal real-world needs, I added
+>>> a `DISTANCE` loop-variable. Quoting the documentation, it's "thedistance,
+>>> expressed in path elements, from the current page to the current path
+>>> element; e.g. this is 1 for the current page's mother, 2 for its
+>>> grand-mother, etc.".)
+
+>>> Anyway, your comments have made me think of other ways to simplify a bit
+>>> this plugin, which admittedly provides too much overlapping functionality.
+>>> Bellow is my reasoning.
+
+>>> In one of my own real world examples, my two main use cases are :
+
+>>> * the "full-blown example" provided in the documentation (i.e.
+>>>   displaying every parent but mother and grand'ma as a group, and giving
+>>>   every of these two last ones their dedicated div);
+>>> * skipping the two oldest parents, and inside what's left, displaying the
+>>>   three youngest parents (i.e. mother, grand'ma and grand'grand'ma), each
+>>>   one with a dedicated style;
+
+>>> Both of these can be achieved by combining `PEDIGREE`, `DISTANCE`, and some
+>>> CSS tricks to hide some parts of the list. `IS_MOTHER` and
+>>> `IS_GRAND_MOTHER`, as well as `PEDIGREE_BUT_TWO_OLDEST`, would be convenient
+>>> shortcuts, but I do not formally need them.
+
+>>> So... it seems things can be simplified greatly:
+
+>>> * I initially added `RELDEPTH` for completeness, but I'm not sure anyone
+>>>   would use it. Let's give it up.
+>>> * Once `RELDEPTH` is lost (modulo Git tendencies to preserve history), the
+>>>   known bug is gone as well, and `PEDIGREE_BUT_ROOT` and
+>>>   `PEDIGREE_BUT_TWO_OLDEST` are now only convenient shortcuts functions;
+>>>   they could as well disappear, if you prefer to.
+
+>>> It appears then that I'd be personally happy with the single `PEDIGREE` loop
+>>> (renamed to `PARENTLINKS`), providing only `PAGE`, `URL`, `ABSDEPTH` (maybe
+>>> renamed to `DEPTH`), and `DISTANCE`. This would make my templates a bit more
+>>> complicated to write and read, but would also keep the plugin's code to the
+>>> bare minimum. Let's say it is my up-to-date proposal. (Well, if the various
+>>> shortcuts don't really annoy you, I'd be glad to keep them ;)
+
+>>>> This sounds fairly similar to what I just described above. (I called
+>>>> DISTANCE "height".) I don't know about the CSS tricks; seems like if
+>>>> `DEPTH_n` and `DISTANCE_n` are provided, you can test for them inside
+>>>> the loop using HTML::Template's lame testing, and isolate any page or
+>>>> range of pages. --[[Joey]]
+
+>>>>> Ok, I definitely like this idea, as an effective and generic
+>>>>> page-range selection tool; this seems the way to go to me.
+
+>>>>> But if you discard the `DEPTH` and `HEIGHT`
+>>>>> counters, we lack a way to **style**, for example, every parent link
+>>>>> depending on its depth or height; one can do this for arbitrary
+>>>>> parents (chosen by their height or depth), but *not* for *any* parent,
+>>>>> since there is no way to express, with HTML::Template, something like
+>>>>> "display the name of the only `DEPTH_n` variable that is currently
+>>>>> true". So I am in favor of keeping the `DEPTH` and `HEIGHT` counters,
+>>>>> to allow constructs like:
+
+       <TMPL_LOOP NAME="PARENTLINKS">
+       <a href="<TMPL_VAR NAME="URL">" class="parentdistance<TMPL_VAR NAME="DISTANCE">">
+         <TMPL_VAR NAME="PAGE">
+       </a> / 
+       </TMPL_LOOP>
+
+>>>>> This seems to me a nice functionality bonus, and should not
+>>>>> imply too bloated code. I'm thus going to rewrite the plugin
+>>>>> with only `PEDIGREE`, `DEPTH`, `HEIGHT`, `DEPTH_n` and
+>>>>> `HEIGHT_n`. -- intrigeri
+
+>>>>>> Done, and pushed in my pedigree branch. Update: I've also done and
+>>>>>> pushed two commits that rename the plugin and replace 
+>>>>>> the core parentlinks with this one. --[[intrigeri]]
+
+(I'll try never to rebase this branch, but writing this plugin has
+been a pretext for me to start learning Git, so...)
+
+To finish with, it seems no plugin bundled with ikiwiki uses the current
+parentlinks implementation, so one could event think of moving it from the
+core to this plugin (which should then be enabled by default, since the
+default templates do use parentlinks ;).
+
+> I think that moving parentlinks out to a plugin is a good idea.
+> However, if it's done, I think the plugin should be named parentlinks,
+> and should continue to use the same template variables as are used now,
+> to avoid needing to change custom templates. Pedigree is a quite nice
+> name, but renaming it to parentlinks seems to be the way to go to me.
+> --[[Joey]]
+
+>> Agreed. -- intrigeri
+
+>> Just commited a testsuite for this plugin, BTW. It's nearly twice 
+>> big as the plugin itself, I'm wondering... -- intrigeri
+
+Merged, nice work. (Overkill having a test suite. ;-) --[[Joey]] 
+
+> Thanks. If the testsuite reveals itself to be harder to maintain than
+> the plugin, my ego won't be offended to see it removed. It's been
+> nice to find a way, step by step, to work with you on this small
+> plugin thing. I'm starting to feel a bit at home in ikiwiki
+> sourcetree, which is great since I may have to start working on some
+> more ambitious ikiwiki stuff, such as the ~multilingual wiki
+> (master language + translations) support. Expect news from me on
+> this front in the next weeks. --[[intrigeri]]
+
+[[!tag patch done]]
diff --git a/doc/todo/pingback_support.mdwn b/doc/todo/pingback_support.mdwn
new file mode 100644 (file)
index 0000000..b10366b
--- /dev/null
@@ -0,0 +1,39 @@
+A "pingback" is a system whereby URLs you might reference in a blog post are
+contacted by the blog publishing software at publishing time (i.e., once) so
+that they might update a list of "pingbacks" to the URL. The originating
+URL's blog software might then display a list of pingbacks, or an excerpt of
+the text from your blog, perhaps interleaved with comments, etc.
+
+At a technical level, external URLs are extracted from your blog post by the
+blogging software, fetched, inspected for information to determine whether the
+remote server is configured to support pingbacks (look for link tags, or HTTP
+headers) and the relevant pingback URL sent an XML-RPC packet.
+
+There are other technologies to achieve the same thing: trackbacks predate
+pingbacks but are more vulnerable to spam due to design problems.
+
+The spec for pingbacks is at <http://www.hixie.ch/specs/pingback/pingback>.
+
+I would like to somehow use pingbacks in conjunction with ikiwiki. I suppose
+this could be achieved using a commit hook and some external software in which
+case I will consider this done with an entry in [[tips]]; otherwise a
+[[plugins|plugin]] to implement pingbacks would be great.
+
+-- [[Jon]] (Wed Jan 14 13:48:47 GMT 2009)
+
+> I think it's now possible to implement trackback and pingback receiving
+> support in ikiwiki. One easy way to do it would be to hook it into the
+> existing [[plugins/comments]] plugin -- each pingback/trackback that
+> ikiwiki recieves would result in the creation if a new comment, which
+> would be subject to the usual comment filtering (ie, blogspam) and
+> moderation and would then show up amoung the other, regular comments on
+> the page.
+>
+> (One wrinkle: would need to guard against duplicate pings. Maybe by
+> checking existing comments for any that have the same url?)
+> 
+> As for sending trackbacks and pingbacks, this could fairly easily be
+> implemented using a `editcontent` hook. Since this hook is called
+> whenever a page is posted or edited, and gets the changed content, it can
+> simply scan it for urls (may have to htmlize first?), and send pings to
+> all urls found. --[[Joey]] 
index 8bfd6a6540df9b7d881eb01bb1961db47c41de86..b3e3a78892e246c03ff2334ff7b86d76f3bc1012 100644 (file)
@@ -1,15 +1,75 @@
 Suggestions of ideas for plugins:
 
+* enable editable, non-htmlized files
+
+    Some months ago, before upgrading my wiki, I used svn to check in an XML file
+    and a companion XSL file for client-side styling. That was cool, ikiwiki
+    copied them over unchanged and the file could be linked to as `\[[foo|foo.xml]]`.
+
+    I even had the XSL produce an `Edit` link at the top, because I wanted a simple
+    way for a web user to edit the XML. But I had to hack stuff to make the edit CGI
+    not say `foo.xml is not an editable page`.
+
+    I did that in a kind of slash-and-burn way, and apparently that's the one change
+    that was uncommitted when I upgraded ikiwiki, so now it's in the same place
+    as the wikiwyg project. On the bright side, that's a chance to think about how to
+    do it better.
+
+    Any suggestions for appropriate uses of existing plugins, or the plugin API,
+    to selectively add to the set of files in the working copy that the edit CGI
+    will consider editable? --ChapmanFlack 17July2008
+
+    > It looks like 80% of the job would be accomplished by hooking `htmlize` for
+    > the `.xml` extension. That would satisfy the `pagetype` test that causes
+    > the edit CGI to say `not an editable page`. (That happens too early for a
+    > `canedit` hook.) The `htmlize` hook could just
+    > copy in to out unchanged (this is an internal wiki, I'm not thinking hard
+    > about evil XML content right now). For extra credit, an `editcontent` hook
+    > could validate the XML. (Can an `editcontent` hook signal a content error?)
+
+    > The tricky bit seems to be to register the fact that the target file should
+    > have extension `.xml` and not `.html`.  Maybe what's needed is a generalized
+    > notion of an `htmlize` hook, one that specifies its output extension as well
+    > as its input, and isn't assumed to produce html? --ChapmanFlack 17July2008
+
+    > Belay that, there's nothing good about trying to use `htmlize` for this; too
+    > many html-specific assumptions follow. For now I'm back to an embarrassing quick
+    > hack that allows editing my xml file.  But here's the larger generalization I
+    > think this is driving at:
+
+    > IkiWiki is currently a tool that can compile a wiki by doing two things:
+    > 1. Process files of various input types _foo_ into a single output type, html, by
+    >    finding suitable _foo_->html plugins, applying various useful transformations
+    >    along the way.
+    > 1. Process files of other input types by copying them with no useful transformations at all.
+
+    > What it could be: a tool that compiles a wiki by doing this:
+    > 1. Process files of various input types _foo_ into various output types _bar_, by
+    >    finding suitable _foo_->_bar_ plugins, applying various useful transformations along
+    >    the way, but only those that apply to the _foo_->_bar_ conversion.
+    > 1. The second case above is now just a special case of 1 where _foo_->_foo_ for any
+    >    unknown _foo_ is just a copy, and no other transformations apply.
+
+    > In some ways this seems like an easy and natural generalization. `%renderedfiles`
+    > is already mostly there, keeping the actual names of rendered files without assuming
+    > an html extension. There isn't a mechanism yet to say which transformations for
+    > linkification, preprocessing, etc., apply to which in/out types, but it could be
+    > easily added without a flag day. Right now, they _all_ apply to any input type for
+    > which an `htmlize` hook exists, and _none_ otherwise. That rule could be retained
+    > with an optional hook parameter available to override it.
+
+    > The hard part is just that right now the assumption of html as the one destination
+    > type is in the code a lot. --ChapmanFlack
+
+    >> Readers who bought this also liked: [[format_escape]], [[multiple_output_formats]]
+    >> --[[JeremieKoenig]]
+
 * list of registered users - tricky because it sorta calls for a way to rebuild the page when a new user is registered. Might be better as a cgi?
 > At best, this could only show the users who have logged in, not all
 > permitted by the current auth plugin(s).  HTTP auth would need
 > web-server-specific code to list all users, and openid can't feasibly do so
 > at all. --[[JoshTriplett]]
 
-* It would be nice to be able to have a button to show "Differences" (or 
-  "Show Diff") when editing a page. Is that an option that can be enabled?
-  Using a plugin?
-
 * For PlaceWiki I want to be able to do some custom plugins, including one
   that links together subpages about the same place created by different
   users. This seems to call for a plugin that applies to every page w/o any
index e73e6c09ef970096ab8751d9feac1bebd9bb3af5..1542f39ae05e3377fc61369c3c200d6168a5c3f5 100644 (file)
@@ -7,14 +7,14 @@ which can't be made through the web interface:
 
 Of course in these cases, you can add your request to a discussion page
 and wait for someone with the access/confidence to apply them.
-Maybe this can be enhanced with a [[ikiwiki/PreprocessorDirective]]:
+Maybe this can be enhanced with a [[ikiwiki/Directive]]:
 
 <pre>
-\[[suggest op=merge dstfile=trunk srcfile=branches/jk oldrev=1234 newrev=1342]]
+\[[!suggest op=merge dstfile=trunk srcfile=branches/jk oldrev=1234 newrev=1342]]
 
-\[[suggest op=move srcpage=/blog dstpage=/blog_support]]
+\[[!suggest op=move srcpage=/blog dstpage=/blog_support]]
 
-\[[suggest patch="""
+\[[!suggest patch="""
 Index: IkiWiki/CGI.pm
 ===================================================================
 --- IkiWiki/CGI.pm      (révision 4119)
diff --git a/doc/todo/pretty-print_OpenIDs_even_if_not_enabled.mdwn b/doc/todo/pretty-print_OpenIDs_even_if_not_enabled.mdwn
new file mode 100644 (file)
index 0000000..3d4338a
--- /dev/null
@@ -0,0 +1,29 @@
+A feature I originally requested on
+[[a_related_bug|bugs/openid_no_longer_pretty-prints_OpenIDs]]:
+
+    Allow the openid plugin to be loaded but disabled, for its side-effect of defining IkiWiki::openiduser
+    
+    On various sites I have two IkiWiki instances running from the same
+    repository: one accessible via http and only accepting openid logins,
+    and one accessible via authenticated https and only accepting httpauth.
+    Ideally, the https version should still pretty-print OpenIDs seen in
+    git history.
+
+--[[smcv]]
+
+> I wonder if an option is the best approach. Maybe it would be better to
+> simply move `openiduser` into `userlink`, and thus always support openid
+> usernames whether the plugin is enabled or not. --[[Joey]]
+
+>> OK, implemented that as 'smcv/always-openid'; if you don't think that's
+>> bloating the IkiWiki core too much, please consider merging. The poll on
+>> [[news/openid]] indicates fairly strong support for *only* accepting OpenID
+>> logins, so I think recognising OpenIDs can reasonably be considered core
+>> functionality! --[[smcv]]
+
+>>> That seemed easier than expected, [[done]].
+>>> (I do wonder if the call to openiduser still needs to be evaled --
+>>> it was probably only evaled before in case it was not available, but
+>>> I have not carefully checked it to make sure it doesn't ever die. --[[Joey]] 
+
+[[!tag patch]]
diff --git a/doc/todo/progressbar_plugin.mdwn b/doc/todo/progressbar_plugin.mdwn
new file mode 100644 (file)
index 0000000..12aef5e
--- /dev/null
@@ -0,0 +1,132 @@
+I would like to add next plugin to Ikiwiki. It's `progressbar` or simply `progress`.
+I'm not sure what plugin name better is, probably that shorter ;) I know that
+[DokuWiki](http://wiki.splitbrain.org/plugin:progressbar) has similar plugin,
+so I think it can be useful also for Ikiwiki users.
+
+Here is proposition of the plugin syntax:
+
+    \[[!progress done=50]]
+
+Of course, `done` argument is integer from 0 to 100. 
+
+A here is its HTML result:
+
+    <div class="progress">
+      <div class="progress-done" style="width: 50%">50%</div>
+    </div>
+
+Note: I was trying with `<span>` tags too, but that tag is inline, so I can't
+set `width` property for it.
+
+> In the poll plugin, I ended up using a `<hr>` for the progress-like
+> thing. One reason I did so is because it actually works in text-mode
+> browsers (w3m, lynx), that do not support css or colorized
+> divs. Since the hr is an element they display, just setting its width can
+> make a basic progress-type display. The style then makes it display
+> better in more capable browsers.
+> 
+> The other advantage to that approach is that the htmlscrubber lets
+> through the `class` and `width` fields, that are all that are needed for
+> it to work. No need to work around htmlscrubber.
+> 
+> So I suggest adapting this to use similar html. --[[Joey]]
+
+>> I just had a brief play with this.  It seems there are some trade-offs involved.
+>> The `width` attribute of an `<hr>` tag is deprecated, but that's not the big one.
+>> I can't see how to place text next to an `<hr>` tag.  I note that in the
+>> [[plugins/poll]] plugin there is text above and below the 'graph line', but none
+>> on the same line as the graph.  I prefer the way the current code renders,
+>> with the percentage complete appearing as text inside the graph.
+>>
+>> So, if we use `hr` we get:
+>>
+>> - Graph line on text / non-css browsers
+>> - No percentage complete text on the same line as the graph line
+>> - Deprecated HTML
+>>
+>> If we use `div` we get:
+>>
+>> - Need to clean up after HTMLScrubber (which is not hard - already implemented)
+>> - Get the percentage written as text on text / non-css browsers
+>> - Get the percentage on the same line as the graph in css browsers
+>>
+>> I'm strongly in favour of having the percentage text label on the graph, and on
+>> text based browsers I think having the text label is enough -- the lack of the line
+>> in that case doesn't bother me.
+>> So, given the choice between the two suggested techniques, I'd take the second and
+>> stay with div... unless you know how to get text next to (or within) an `<hr>` tag. -- [[Will]]
+
+Default CSS styles for the plugin can be like below:
+
+    div.progress {
+            border: 1px solid #ddd;
+            /* border: 2px solid #ddd; */
+            width: 200px;
+            background: #fff;
+            padding: 2px;
+            /* padding: 0px; */
+            border: 2px solid #aaa;
+            background: #eee;
+    }
+    div.progress-done {
+            height: 14px;
+            background: #ff6600;
+            font-size: 12px;
+            text-align: center;
+            vertical-align: middle;
+    }
+
+You can use alternative, commented CSS code for `div.progress` if you dislike
+padding around done strip.
+
+Any comments? --[[Paweł|ptecza]]
+
+> Please make sure to always set a foreground color if a background color is
+> set, and use '!important' so the foreground color can be overridden. (CSS
+> best practices) --[[Joey]]
+
+>> Below is the CSS I've been using -- [[Will]]
+
+    div.progress {
+       margin-top: 1ex;
+       margin-bottom: 1ex;
+       border: 1px solid #888;
+       width: 400px;
+       background: #eee;
+       color: black !important;
+       padding: 1px;
+    }
+    div.progress-done {
+       background: #ea6 !important;
+       color: black !important;
+       text-align: center;
+       padding: 1px;
+    }
+
+> This looks like a nice idea.  If I could add one further suggestion: Allow your
+> ratio to be a pair of pagespecs.  Then you could have something like:
+
+    \[[!progress totalpages="bugs/* and backlink(milestoneB)" donepages="bugs/* and backlink(milestoneB) and !link(bugs/done)"]]
+
+> to have a progress bar marking how many bugs were compete for a
+> particular milestone.  -- [[Will]]
+
+>> Thanks a lot for your comment, Will! It seems very interesting for me.
+>> I need to think more about improving that plugin. --[[Paweł|ptecza]]
+
+>> Attached is a [[patch]] (well, source) for this.  You also need to add the proposed CSS above to `style.css`.
+>> At the moment this plugin interacts poorly with the [[plugins/htmlscrubber]] plugin.
+>> HTMLScrubber plugin removes the `style` attribute from the `progress-done` `div` tag, and so it defaults
+>> to a width of 100%. -- [[Will]]
+
+>>> Thank you for the code! I know how to fix that problem, because I had
+>>> the same issue while writing [[todo/color_plugin]] :) --[[Paweł|ptecza]]
+
+>>>> Ahh - good idea.  Patch updated to work with HTMLScrubber. --[[Will]]
+
+>>>>> I like it, but I think that Joey should take a look at that patch too :)
+>>>>> --[[Paweł|ptecza]]
+
+>>>>>> Reviewed, looks excellent, added. [[done]] --[[Joey]]
+
+>>>>>>> Thanks a lot for you and Will! :) [[Paweł|ptecza]]
index f34ed77c6dcb60ccb4abc45a10a745ac476459b9..6e0cd51e6c1b031d5cfc32206fcc791bd3b11539 100644 (file)
@@ -37,4 +37,4 @@ more users, the number of such requests will also increase. --[[madduck]]
 >> can use that as an alternative. I'm happy to chat about this, ping me..
 >> --[sm](http://joyful.com)
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 43700337d72fae3a55ada8820aa47374cb89f878..39a35d0c6088f97c19f62dbc0ba07739321985c2 100644 (file)
@@ -1,3 +1,8 @@
 It would rock if I could view diffs from the web without going via feeds. I envision toggle-style buttons on the recentchanges page, or just links to the CGI, which then displays the diff... --[[madduck]]
 
-[[tag wishlist]]
+> The diffs are actually there, enabled by the `recentchangesdiff`
+> plugin, but they are hidden in the XHTML version by the stylesheet.
+> You might try a user stylesheet with `div.diff { display: block }`.
+> --[[JasonBlevins]]
+
+[[!tag wishlist]]
diff --git a/doc/todo/provide_sha1_for_git_diffurl.mdwn b/doc/todo/provide_sha1_for_git_diffurl.mdwn
new file mode 100644 (file)
index 0000000..01aa512
--- /dev/null
@@ -0,0 +1,26 @@
+This [[patch]] allows for `\[[sha1]]` substitution in the `diffurl`
+for git repositories.  This is useful for use with [cgit][] which has
+diffurls of the following form:
+
+    /project.git/diff/\[[file]]?id=\[[sha1_commit]]
+
+ [cgit]: http://hjemli.net/git/cgit/
+
+    diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm
+    index 5bef928..164210d 100644
+    --- a/IkiWiki/Plugin/git.pm
+    +++ b/IkiWiki/Plugin/git.pm
+    @@ -518,6 +518,7 @@ sub rcs_recentchanges ($) {
+     
+                       my $diffurl = defined $config{'diffurl'} ? $config{'diffurl'} : "";
+                       $diffurl =~ s/\[\[file\]\]/$file/go;
+    +                  $diffurl =~ s/\[\[sha1\]\]/$sha1/go;
+                       $diffurl =~ s/\[\[sha1_parent\]\]/$ci->{'parent'}/go;
+                       $diffurl =~ s/\[\[sha1_from\]\]/$detail->{'sha1_from'}/go;
+                       $diffurl =~ s/\[\[sha1_to\]\]/$detail->{'sha1_to'}/go;
+
+> [[done]], but I called it `sha1_commit` since I think that's what it's
+> actually a sha1 of. --[[Joey]]
+
+>> I was at a loss for something more descriptive...I like that much
+>> better :) Thanks! --[[JasonBlevins]]
index 11ce139b43f336dbbee9ca39911eb7311c157c5d..c6d83a519ac0d8513ce5013638c95a772066197d 100644 (file)
@@ -20,7 +20,7 @@ The fix is simply to call `bzr` with the _--quiet_ switch. Something like this a
     > 
 
 
-[[tag patch]]
+[[!tag patch]]
 
 > [[done]], although I left off the escapeHTML thing which seems to be in
 > your patch by accident.
index 3793f7533fa497357e2a7cdc237dd719893decf4..3cc5725168ff1d7a7323cdf1532d1507d0add3b8 100644 (file)
@@ -3,7 +3,7 @@ I have used it probably over hundred times but needs some work.
 
 <http://www.reedmedia.net/~reed/tmp-sfhkcjkfrfh/rcs.pm>
 
-[[tag patch]]
+[[!tag patch]]
 
 > Clearly needs some cleanup and perhaps some of the missing stubs
 > implemented, before it can be included into ikiwiki. 
diff --git a/doc/todo/rcs_updates_needed.mdwn b/doc/todo/rcs_updates_needed.mdwn
new file mode 100644 (file)
index 0000000..472a580
--- /dev/null
@@ -0,0 +1,10 @@
+I've added three new functions to the ikiwiki VCS interface to support
+renaming and removing files using the web interface. The mercurial and 
+tla [[rcs]] backends need implementions of these functions.
+
+(The maintainers of these backends have been mailed. --[[Joey]])
+
+Also, currently git is the only VCS to have support for
+[[untrusted_push|tips/untrusted_git_push]]. It _may_ be possible to
+implement it for other DVCS, if they offer a hook that can be used to check
+incoming pushes early.
index 91128a860faffcfe7b66780238ee3b1e6d11e84f..25a8ea4dbf973e365357b670f54bc0f3a333439b 100644 (file)
@@ -92,7 +92,7 @@ your pages. --Ethan
 Here's a full design for redoing recentchanges, based on Ethan's ideas:
 
 * Add a recentchanges plugin that has a preprocessor directive:
-       \[[recentchanges num=100 pages=* template=recentchanges.tmpl]]
+       \[[!recentchanges num=100 pages=* template=recentchanges.tmpl]]
   If put on the [[recentchanges]] page, this would result in up to 100
   recentchanges/change_$id.mdwn files being created.
 * Which means the plugin has to store state and use a checkconfig hook
diff --git a/doc/todo/redirect_automatically_after_rename.mdwn b/doc/todo/redirect_automatically_after_rename.mdwn
new file mode 100644 (file)
index 0000000..1cbb824
--- /dev/null
@@ -0,0 +1,10 @@
+In some wikis, (e.g. Mediawiki) after [[renaming|plugins/rename]] 
+a page, the old page still exist but only redirect to the
+new page.  This is convenient since external sites may
+have links pointing to the old url.  
+
+If [[plugins/meta]] plugin is enabled, users can manually edit the
+page, and put in '\[[!meta redir=newpage]]', but this is
+not very convenient.
+
index 331721b559c24651534abe4ca0bae23b8ce2712f..3b4cea436d9fdb269629c114379345ce7869cebe 100644 (file)
@@ -16,4 +16,4 @@ This can also help for css decoraton. An example of these patches in use: http:/
 
 — NicolasLimare
 
-[[tag wishlist]]
+[[!tag wishlist]]
diff --git a/doc/todo/relative_pagespec_deficiency.mdwn b/doc/todo/relative_pagespec_deficiency.mdwn
new file mode 100644 (file)
index 0000000..4500581
--- /dev/null
@@ -0,0 +1,8 @@
+While a relative pagespec like `./posts/*` will work, when used in a page
+such as `bdale/blog`, you cannot do
+`created_after(./posts/foo)` -- only `glob()` supports relative page
+references.
+
+The other pagespec functions should too, where appropriate.
+
+[[done]]
index 247801a8dfa9596c9e7308f68af318e132730e19..fe9e49ce2154012ee4611e1c09d0def0e1efdeda 100644 (file)
@@ -1,2 +1,4 @@
 In version 2.16, several redir pages were put in for [[basewiki]] pages
 that were moved. These redirs should be removed later. --[[Joey]]
+
+[[done]]
index c73b53e53f338264a318e866599364b10bcdd45f..c4e78ca0bb7147eba8765b5185820f3beb279eda 100644 (file)
@@ -1,4 +1,4 @@
-[[tag wishlist]]
+[[!tag wishlist]]
 
 HTML::Template is an okay templating kit, but it lacks a lot of powerful
 features and thus makes it rather hard to give an ikiwiki site a consistent
@@ -54,3 +54,7 @@ the templates. I'd prefer not having to touch Perl though...
 -----
 
 Yes, Template::Toolkit is very powerful. But I think it's somehow overkill for a wiki. HTML::Template can keep things simple, though.  --[weakish](http://weakish.int.eu.org/blog/)
+
+I'd have to agree that Template::Toolkit is overkill and personally I'm not a fan, but it is very popular (there is even a book) and the new version (3) is alleged to be much more nimble than current version.  --[[ajt]]
+
+HTML::Template's HTML-like markup prevents me from editing templates in KompoZer or other WYSIWYG HTML editors.  The editor tries to render the template markup rather than display it verbatim, and large parts of the template become invisible.  A markup syntax that doesn't confuse editors (such as Template::Toolkit's "[% FOO %]") may promote template customization.  The ability to replace the template engine would be within the spirit of ikiwiki's extensibility. --Rocco
index e42ac259c31e40286dba53b3ec9fd9fcee74b78a..83ba07eb0f8bcd8e9c110c8d5b213fdb139c3229 100644 (file)
@@ -2,6 +2,8 @@ I don't necessarily trust all OpenID providers to stop bots.  I note that ikiwik
 
 I imagine a plugin that modifies the login screen to use <http://recaptcha.net/>.  You would then be required to fill in the captcha as well as log in in the normal way.
 
+-- [[users/Will]]
+
 > I hate CAPTCHAs with a passion. Someone else is welcome to write such a
 > plugin.
 >
@@ -55,7 +57,7 @@ ignored.
 > This is still not fixed.  I would have thought the following patch would
 > have fixed this second issue, but it doesn't.
 
-(code snipped as a working patch is below)
+(code snipped as a working [[patch]] is below)
 
 >> What seems to be happing here is that the openid plugin defines a
 >> validate hook for openid_url that calls validate(). validate() in turn
@@ -89,15 +91,15 @@ ignored.
 
 --- a/IkiWiki/Plugin/openid.pm
 +++ b/IkiWiki/Plugin/openid.pm
-@@ -18,6 +18,7 @@ sub getopt () { #{{{
+@@ -18,6 +18,7 @@ sub getopt () {
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
        GetOptions("openidsignup=s" => \$config{openidsignup});
 +      GetOptions("openidneedscaptcha=s" => \$config{openidneedscaptcha});
- } #}}}
+ }
  
- sub formbuilder_setup (@) { #{{{
-@@ -61,6 +62,7 @@ sub formbuilder_setup (@) { #{{{
+ sub formbuilder_setup (@) {
+@@ -61,6 +62,7 @@ sub formbuilder_setup (@) {
                        # Skip all other required fields in this case.
                        foreach my $field ($form->field) {
                                next if $field eq "openid_url";
@@ -105,7 +107,7 @@ ignored.
                                $form->field(name => $field, required => 0,
                                        validate => '/.*/');
                        }
-@@ -96,6 +98,18 @@ sub validate ($$$;$) { #{{{
+@@ -96,6 +98,18 @@ sub validate ($$$;$) {
                }
        }
  
@@ -150,19 +152,19 @@ use warnings;
 use strict;
 use IkiWiki 2.00;
 
-sub import { #{{{
+sub import {
        hook(type => "formbuilder_setup", id => "recaptcha", call => \&formbuilder_setup);
-} # }}}
+}
 
-sub getopt () { #{{{
+sub getopt () {
        eval q{use Getopt::Long};
        error($@) if $@;
        Getopt::Long::Configure('pass_through');
        GetOptions("reCaptchaPubKey=s" => \$config{reCaptchaPubKey});
        GetOptions("reCaptchaPrivKey=s" => \$config{reCaptchaPrivKey});
-} #}}}
+}
 
-sub formbuilder_setup (@) { #{{{
+sub formbuilder_setup (@) {
        my %params=@_;
 
        my $form=$params{form};
@@ -272,7 +274,7 @@ EOTAGS
                                });
                }
        }
-} # }}}
+}
 
 # The following function is borrowed from
 # Captcha::reCAPTCHA by Andy Armstrong and are under the PERL Artistic License
@@ -323,4 +325,3 @@ sub check_answer {
 }
 
 1;
-
index 5e4ba212e859269c1a89be2f02c72287b8a31ce9..66ed581444c9e4d5d6770ea61898aa1166b35540 100644 (file)
@@ -32,4 +32,4 @@ Change queues would be wiki pages as well (probably using [[inlines|plugins/inli
 >
 > -- [[JoshTriplett]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
diff --git a/doc/todo/rewrite_ikiwiki_in_haskell.mdwn b/doc/todo/rewrite_ikiwiki_in_haskell.mdwn
new file mode 100644 (file)
index 0000000..204c48c
--- /dev/null
@@ -0,0 +1,68 @@
+[[!tag wishlist blue-sky]]
+
+In the long term, I have been considering rewriting ikiwiki in haskell.
+It's appealing for a lot of reasons, including:
+
+* No need to depend on a C compiler and have wrappers. Instead, ikiwiki
+  binaries could be built on demand to do the things wrappers are used for
+  now (cgi, post-commit, etc).
+* Potentially much faster. One problem with the now very modular ikiwiki is
+  that it has to load up dozens of perl modules each time it runs, which
+  means both opening lots of files and evaluating them. A haskell version
+  could run from one pre-compiled file. Other speed efficienies are also
+  likely with haskell. For example, pandoc is apparently an order of
+  magnitude faster than perl markdown implementations.
+* Many plugins could be written in pure functional code, with no side
+  effects. Not all of them, of course.
+* It should be much easier to get ikiwiki to support parallel compilation
+  on multi-core systems using haskell.
+* A rewrite would be an opportunity to utterly break compatability and
+  redo things based on experience. Since the haskell libraries used for
+  markdown, templates, etc, are unlikely to be very compatable with the perl
+  versions, and since perl plugins obviously wouldn't work, and perl setup
+  files wouldn't be practical to keep, a lot of things would unavoidably
+  change, and at that point changinge everything else I can think of
+  probably wouldn't hurt (much).
+
+  - Re templates, it would be nice to have a template library that
+    doesn't use html-ish templating tags, since those are hard for users to
+    edit in html editors currently.
+  - This would be a chance to make WikiLinks with link texts read
+    "the right way round" (ie, vaguely wiki creole compatably).
+  - The data structures would probably be quite different.
+  - I might want to drop a lot of the command-line flags, either
+    requiring a setup file be used for those things, or leaving the
+    general-purpose `--set var=value` flag.
+  - Sometimes the current behavior of `--setup` seems confusing; it might
+    only cause a setup file to be read, and not force rebuild mode.
+  - Hard to say how the very high level plugin interface design would change,
+    but at the least some of the names of hooks could stand a rename, and
+    their parameter passing cleaned up.
+
+We know that a big, break-the-world rewrite like this can be a very
+bad thing for a project to attempt. It would be possible to support
+external plugins written in haskell today, without any rewrite; and a few
+of the benefits could be obtained by, eg, making the mdwn plugin be a
+haskell program that uses pandoc. I doubt that wouod be a good first step
+to converting ikiwiki to haskell, because such a program would have very
+different data structures and intercommuniucation than a pure haskell
+version.
+
+Some other things to be scared about:
+
+* By picking perl, I made a lot of people annoyed (and probably turned
+  several people away from using ikiwiki). But over time there turned out
+  to be a lot of folks who knew perl already (even if rustily), and made
+  some *very* useful contributions. I doubt there's as large a pool of haskell
+  programmers, and it's probably harder for a python user to learn haskell
+  than perl if they want to contribute to ikiwiki.
+* It might be harder for users of hosting services to install a haskell based
+  ikiwiki than the perl version. Such systems probably don't have ghc and
+  a bunch of haskell libraries. OTOH, it might be possible to build a
+  static binary at home and upload it, thus avoiding a messy installation
+  procedure entirely.
+* I can barely code in haskell yet. I'm probably about 100x faster at
+  programming in perl. I need to get some more practical experience before
+  I´m fast and seasoned enough in haskell to attempt such a project.
+  (And so far, progress at learning has been slow and I have not managed
+  to write anything serious in haskell.) --[[Joey]] 
diff --git a/doc/todo/rewrite_ikiwiki_in_haskell/discussion.mdwn b/doc/todo/rewrite_ikiwiki_in_haskell/discussion.mdwn
new file mode 100644 (file)
index 0000000..1edebe4
--- /dev/null
@@ -0,0 +1,14 @@
+Ok, I have to admit, I have no idea if this is an April fool's joke or not.  
+Congratulations for demonstrating that April fools jokes can still be subtle
+(whether intentionally or not!) -- [[Jon]]
+
+> Having said all that, have you looked at erlang? Have you heard of couchdb?
+> I'd strongly recommend looking at that. -- [[Jon]]
+
+>> I've glanced at couchdb, but don't see how it would tie in with ikiwiki.
+>> --[[Joey]] 
+
+
+>>> It doesn't really. I recently (re-)read about couchdb and thought that
+>>> what it was trying to do had some comparisons with the thinking going on
+>>> in [[todo/structured_page_data]]. -- [[Jon]]
index 3f56a10e0c3979ec44ef62935d16b23c5958371b..f0138cb728538f95792c7994e8fc97b734767401 100644 (file)
@@ -18,7 +18,7 @@ A few pointers and I might be able to implement this myself. -- JamesWestby
 > Now, the description field currently defaults to the wiki name,
 > and that could indeed stand to be made configurable. Since the
 > current (svn) version of ikiwiki supports long, word-wrapped
-> blocks of text as parameters to [[ikiwiki/PreProcessorDirective]]s, seems
+> blocks of text as parameters to [[ikiwiki/Directive]]s, seems
 > to me the best way would be to simple modify inline.pm to make the
 > descripion configurable by such parameter, with a fallback to the
 > wiki name. You'll need to modify rsspage.tmpl to use whatever new
index 0e5edb520947335b6d4e5cb93ff14c044ed82ea6..cf1708c34bcb0a5174d18765bcf5f169e2fc6726 100644 (file)
@@ -1,4 +1,4 @@
-The [[plugin/search]] plugin could use xapian terms to allow some special
+The [[plugins/search]] plugin could use xapian terms to allow some special
 searches. For example, "title:foo", or "link:somepage", or "author:foo", or
 "copyright:GPL".
 
diff --git a/doc/todo/section-numbering.mdwn b/doc/todo/section-numbering.mdwn
new file mode 100644 (file)
index 0000000..3a2d232
--- /dev/null
@@ -0,0 +1,7 @@
+[[!tag wishlist]]
+
+Optional automatic section numbering would help reading: otherwise, a reader (like me) gets lost in the structure of a long page.
+
+I guess it is implementable with complex CSS... but one has first to compose this CSS in any case. So, this wish still has a todo status. --Ivan Z.
+
+And another aspect why this is related to ikiwiki, not just authoring a CSS, is that the style of the numbers (genereated by CSS probably) should match the style of the numbers in ikiwiki's [[plugins/toc]]. --Ivan Z.
index d03d374119d4f0db40646ea34ce98abcadd2b74f..952e84608e4be06803ae265d22c46a555c53e7a3 100644 (file)
@@ -1,19 +1,19 @@
-[[plugins/shortcut]] creates link shortcut [[ikiwiki/PreprocessorDirective]]s,
+[[plugins/shortcut]] creates link shortcut [[ikiwiki/Directive]]s,
 which substitute their argument into the specified shortcut URL to generate
 the link target, and use the argument as the link text.  For example, given
-the example [[shortcuts]], `\[[wikipedia ikiwiki]]` generates a link to
+the example [[shortcuts]], `\[[!wikipedia ikiwiki]]` generates a link to
 <http://en.wikipedia.org/wiki/ikiwiki>, with the link text "ikiwiki".  This
 works well in many cases; however, for things like the `debbug` example, it
 simply uses the number as the link text, which does not always provide
 enough context to understand the link at first glance.  For example,
-`\[[debbug 397501]]` generates a link to <http://bugs.debian.org/397501>,
+`\[[!debbug 397501]]` generates a link to <http://bugs.debian.org/397501>,
 with just "397501" as the link text.  While [[plugins/template]] provides a
 general solution for arbitrary cases, it would help to have a simple option
 via the shortcut plugin to set the link text, with a `%s` substitution.
-Thus, something like `\[[shortcut name=debbug
+Thus, something like `\[[!shortcut name=debbug
 url="http://bugs.debian.org/%s" desc="bug #%s"]]` might suffice on a
 Debian-specific wiki to indicate a bug number, while a more general wiki
-might use something like `\[[shortcut name=debbug
+might use something like `\[[!shortcut name=debbug
 url="http://bugs.debian.org/%s" desc="Debian bug #%s"]]`.
 
 > [[todo/done]] --[[Joey]]
index daec3696a05119e06dbb23d5af4b2387f3779449..4454043154e3e787f2a141cc75fd952d87d12b92 100644 (file)
@@ -6,39 +6,39 @@ Consider the "All files in this package search" on
 To create a "debfiles" [[shortcut|shortcuts]] that takes a package name, you
 could just hardcode the architecture and distribution:
 
-    \[[shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=unstable&arch=i386"]]
-    \[[debfiles ikiwiki]]
+    \[[!shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=unstable&arch=i386"]]
+    \[[!debfiles ikiwiki]]
 
 But what if you could have them as optional parameters instead?  The syntax
 for the invocation should look like this:
 
-    \[[debfiles ikiwiki dist=testing]]
+    \[[!debfiles ikiwiki dist=testing]]
 
 Some possible syntax choices for the shortcut definition:
 
-    \[[shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%(dist)s&arch=%(arch)s" dist="unstable" arch="i386"]]
-    \[[shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%(dist=unstable)s&arch=%(arch=i386)s"]]
-    \[[shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%{dist=unstable}&arch=%{arch=i386}"]]
-    \[[shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=$*&searchmode=filelist&case=insensitive&version=${dist=unstable}&arch=${arch=i386}"]]
+    \[[!shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%(dist)s&arch=%(arch)s" dist="unstable" arch="i386"]]
+    \[[!shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%(dist=unstable)s&arch=%(arch=i386)s"]]
+    \[[!shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=%s&searchmode=filelist&case=insensitive&version=%{dist=unstable}&arch=%{arch=i386}"]]
+    \[[!shortcut name=debfiles url="http://packages.debian.org/cgi-bin/search_contents.pl?word=$*&searchmode=filelist&case=insensitive&version=${dist=unstable}&arch=${arch=i386}"]]
 
 --[[JoshTriplett]]
 
 Well, you can already do this kind of thing with templates. Invocation does
 look different:
 
-    \[[template id=debfiles package=ikiwiki dist=testing]]
+    \[[!template id=debfiles package=ikiwiki dist=testing]]
 
 --[[Joey]]
 
 > I think I would find templates sufficient, if:
 >
 > 1. I could use the name of the template as a preprocessor directive
->    (`\[[templatename ...]]`), rather than using the `template` directive
->    with an `id` argument (`\[[template id=templatename]]`).
+>    (`\[[!templatename ...]]`), rather than using the `template` directive
+>    with an `id` argument (`\[[!template id=templatename]]`).
 > 2. Template invocation allowed bare values in addition to `key=value`
 >    arguments, and template definition supported some means to access the
->    value.  This would allow `\[[debfiles ikiwiki]]` rather than
->    `\[[debfiles package=ikiwiki]]`.
+>    value.  This would allow `\[[!debfiles ikiwiki]]` rather than
+>    `\[[!debfiles package=ikiwiki]]`.
 > 3. I could use ikiwiki syntax in the template, not just HTML and
 >    HTML::Template.  (If I can already do that, then [[/plugins/template]]
 >    should make that more clear.)
index 93f9651a4b75866c5e40317e2a7aca2684cc7520..8615b2754b7e20e6b49c201329a29530fd130e0a 100644 (file)
@@ -11,7 +11,7 @@ Window System protocol".  --[[JoshTriplett]]
 > If I don't understand this, can you give an HTML example? --[[JeremyReed]]
 
 >> The problem is like that in [[bugs/shortcuts_don't_escape_from_Markdown]]. We would like to use 
->> the shortcuts plugin but add a descriptive text -- in this case \[[xcbgit src/xcb.xsd|XML Schema...]]
+>> the shortcuts plugin but add a descriptive text -- in this case \[[!xcbgit src/xcb.xsd|XML Schema...]]
 >> The file src/xcb.xsd could be any url, and the point of shortcuts is that you get to shorten it.
 >> --Ethan
 
@@ -22,7 +22,7 @@ Window System protocol".  --[[JoshTriplett]]
 >>> However, I want to define a [[plugins/shortcut]] to save the typing.  If I
 >>> define something like `protogit` pointing to
 >>> `http://gitweb.freedesktop.org/?p=xcb/proto.git;a=blob;hb=HEAD;f=%s`, then
->>> I can write `\[[protogit src/xcb.xsd]]`; however, I then can't change the
+>>> I can write `\[[!protogit src/xcb.xsd]]`; however, I then can't change the
 >>> link text to anything other than what the shortcut defines as the link
 >>> text. I want to write something like
 >>> `\[[XML Schema for the X Window System Protocol|protogit src/xcb.xsd]]`,
@@ -44,22 +44,22 @@ Window System protocol".  --[[JoshTriplett]]
 
 ---
 
-One possible alternative, would be a general `\[[url ]]` scheme for all kinds of links. As mentioned in [[Short_wikilinks]], I have wanted a way to enter links to the wiki with markdown-style references,
+One possible alternative, would be a general `\[[!url ]]` scheme for all kinds of links. As mentioned in [[Short_wikilinks]], I have wanted a way to enter links to the wiki with markdown-style references,
 specifying the actual target elsewhere from the text, with just a short reference in the text. To facilitate automatic conversion from earlier (already markdownised) "blog", I finally ended up writing a custom plugin that simply gets the location of wikipage, and use markdown mechanisms:
 
     Here [is][1] a link.
 
-      [1]: [[l a_page_in_the_wiki]]
+      [1]: [[!l a_page_in_the_wiki]]
 
-    Obviously [this]([[l another_page]]) also works, although the syntax is quite cumbersome.
+    Obviously [this]([[!l another_page]]) also works, although the syntax is quite cumbersome.
 
 So that the 'l' plugin inserts the location the page there, and markdown does the rest. My plugin currently fails if it can't find the page, as that is sufficient for my needs. Differing colouring for non-existing pages is not doable in a straightforward manner with this approach.
 
-For external links, that is no concern, however. So you could define for each shortcut an alternative directive, that inserts the URL. Perhaps `\[[url shortcutname params]]` or `\[[@shortcutname params]]` (if the preprocessor supported the @), and this could be extended to local links in an obvious manner: `\[[url page]]` or `\[[@page]]`. Now, if you could just get rid off the parantheses for markdown, for the short inline links --[[tuomov]] (who'd really rather not have two separate linking mechanisms: ikiwiki's heavy syntax and markdown's lighter one).
+For external links, that is no concern, however. So you could define for each shortcut an alternative directive, that inserts the URL. Perhaps `\[[!url shortcutname params]]` or `\[[@shortcutname params]]` (if the preprocessor supported the @), and this could be extended to local links in an obvious manner: `\[[!url page]]` or `\[[@page]]`. Now, if you could just get rid off the parantheses for markdown, for the short inline links --[[tuomov]] (who'd really rather not have two separate linking mechanisms: ikiwiki's heavy syntax and markdown's lighter one).
 
 ---
 
-I've added code to make the \[[foo 123]] syntax accept a _desc_
+I've added code to make the \[[!foo 123]] syntax accept a _desc_
 parameter. I've named it like this to signal that it overrides the
 _desc_ provided at description time. `%s` is expanded here as well.
 
index c8e138820dc96299fbf2ab29d376806f0673bff3..56a74029ec7b80051786b5f925c9157b75752292 100644 (file)
@@ -16,8 +16,8 @@ It sounds like you're looking for templates, not shortcuts. --[[Joey]]
 > `url` still seems reasonable, and simple.  You could also use such shortcuts
 > without markup at all, as an abbreviation mechanism:
 > 
->     \[[shortcut name=spi desc="Software in the Public Interest, Inc."]]].
->     \[[shortcut name=sosp desc="Symposium on Operating System Principles"]]].
->     \[[shortcut name=cacm desc="Communications of the ACM"]]].
+>     \[[!shortcut name=spi desc="Software in the Public Interest, Inc."]]].
+>     \[[!shortcut name=sosp desc="Symposium on Operating System Principles"]]].
+>     \[[!shortcut name=cacm desc="Communications of the ACM"]]].
 >
 > --[[JoshTriplett]]
index 9804351118c63c35c9343b5cf73d75c7f28eb164..4b4e267f0030df6ab86a8e3cac8c26a6613a50fb 100644 (file)
@@ -18,8 +18,8 @@ Couldn't isolate the cause, but some sources for this problem may be:
 
 Other special things in my templates and site:
 
-* a sidebar with \[[include pages="notes/\*" template=foo]] while notes.mdwn has 
-  a \[[include pages="notes/*"]] and uses the sidebar; removed it, doesn't change
+* a sidebar with \[[!include pages="notes/\*" template=foo]] while notes.mdwn has 
+  a \[[!include pages="notes/*"]] and uses the sidebar; removed it, doesn't change
 * a template (biblio.tmpl) calling the "img" plugin with a template parameter as the
   image filename; removed it, doesn't change
 * some strange games with tags whose page calls a "map" directive to show other tags
@@ -79,4 +79,239 @@ I can think about reducung the size of my wiki source and making it available on
 > 
 > --[[Joey]]
 
-[[tag wishlist]]
+[[!template id=gitbranch branch=smcv/ready/optimize-depends author="[[smcv]]"]]
+
+>> I've been looking at optimizing ikiwiki for a site using
+>> [[plugins/contrib/album]] (which produces a lot of pages) and it seems
+>> that checking which pages depend on which pages does take a significant
+>> amount of time. The optimize-depends branch in my git repository
+>> avoids using `pagespec_merge()` for this (indeed it's no longer used
+>> at all), and instead represents dependencies as a list of pagespecs
+>> rather than a single pagespec. This does turn out to be faster, although
+>> not as much as I'd like. --[[smcv]]
+
+>>> [[Merged|done]] --[[smcv]]
+
+>>> I just wanted to note that there is a whole long discussion of dependencies and pagespecs on the [[todo/tracking_bugs_with_dependencies]] page. -- [[Will]]
+
+>>>> Yeah, I had a look at that (as the only other mention of `pagespec_merge`).
+>>>> I think I might have solved some of the problems mentioned there,
+>>>> actually - `pagespec_merge` no longer needs to exist in my branch (although
+>>>> I haven't actually deleted it), because the "or" operation is now done in
+>>>> the Perl code, rather than by merging pagespecs and translating. --[[smcv]]
+
+[[!template id=gitbranch branch=smcv/ready/remove-pagespec-merge author="[[smcv]]"]]
+
+>>>>> I've now added a patch to the end of that branch that deletes
+>>>>> `pagespec_merge` almost entirely (we do need to keep a copy around, in
+>>>>> ikiwiki-transition, but that copy doesn't have to be optimal or support
+>>>>> future features like [[tracking_bugs_with_dependencies]]). --[[smcv]]
+
+---
+
+Some questions on your optimize-depends branch. --[[Joey]]
+
+In saveindex it still or'd together the depends list, but the `{depends}`
+field seems only useful for backwards compatability (ie, ikiwiki-transition
+uses it still), and otherwise just bloats the index.
+
+> If it's acceptable to declare that downgrading IkiWiki requires a complete
+> rebuild, I'm happy with that. I'd prefer to keep the (simple form of the)
+> transition done automatically during a load/save cycle, rather than
+> requiring ikiwiki-transition to be run; we should probably say in NEWS
+> that the performance increase won't fully apply until the next
+> rebuild. --[[smcv]]
+
+>> It is acceptable not to support downgrades.
+>> I don't think we need a NEWS file update since any sort of refresh,
+>> not just a full rebuild, will cause the indexdb to be loaded and saved,
+>> enabling the optimisation. --[[Joey]]
+
+>>> A refresh will load the current dependencies from `{depends}` and save
+>>> them as-is as a one-element `{dependslist}`; only a rebuild will replace
+>>> the single complex pagespec with a long list of simpler pagespecs.
+>>> --[[smcv]]
+
+Is an array the right data structure? `add_depends` has to loop through the
+array to avoid dups, it would be better if a hash were used there. Since
+inline (and other plugins) explicitly add all linked pages, each as a
+separate item, the list can get rather long, and that single add_depends
+loop has suddenly become O(N^2) to the number of pages, which is something
+to avoid..
+
+> I was also thinking about this (I've been playing with some stuff based on the
+> `remove-pagespec-merge` branch).  A hash, by itself, is not optimal because
+> the dependency list holds two things: page names and page specs.  The hash would
+> work well for the page names, but you'll still need to iterate through the page specs.
+> I was thinking of keeping a list and a hash.  You use the list for pagespecs
+> and the hash for individual page names.  To make this work you need to adjust the
+> API so it knows which you're adding.  -- [[Will]]
+
+> I wasn't thinking about a lookup hash, just a dedup hash, FWIW.
+> --[[Joey]]
+
+>> I was under the impression from previous code review that you preferred
+>> to represent unordered sets as lists, rather than hashes with dummy
+>> values. If I was wrong, great, I'll fix that and it'll probably go
+>> a bit faster. --[[smcv]]
+
+>>> It depends, really. And it'd certianly make sense to benchmark such a
+>>> change. --[[Joey]]
+
+>>>> Benchmarked, below. --[[smcv]]
+
+Also, since a lot of places are calling add_depends in a loop, it probably
+makes sense to just make it accept a list of dependencies to add. It'll be
+marginally faster, probably, and should allow for better optimisation
+when adding a lot of depends at once.
+
+> That'd be an API change; perhaps marginally faster, but I don't
+> see how it would allow better optimisation if we're de-duplicating
+> anyway? --[[smcv]]
+
+>> Well, I was thinking that it might be sufficient to build a `%seen`
+>> hash of dependencies inside `add_depends`, if the places that call
+>> it lots were changed to just call it once. Of course the only way to
+>> tell is benchmarking. --[[Joey]]
+
+>>> It doesn't seem that it significantly affects performance either way.
+>>> --[[smcv]]
+
+In Render.pm, we now have a triply nested loop, which is a bit
+scary for efficiency. It seems there should be a way to
+rework this code so it can use the optimised `pagespec_match_list`,
+and/or hoist some of the inner loop calculations (like the `pagename`)
+out.
+
+> I don't think the complexity is any greater than it was: I've just
+> moved one level of "loop" out of the generated Perl, to be
+> in visible code. I'll see whether some of it can be hoisted, though.
+> --[[smcv]]
+
+>> The call to `pagename` is the only part I can see that's clearly
+>> run more often than before. That function is pretty inexpensive, but..
+>> --[[Joey]]
+
+>>> I don't see anything that can be hoisted without significant refactoring,
+>>> actually. Beware that there are two pagename calls in the loop: one for
+>>> `$f` (which is the page we might want to rebuild), and one for `$file`
+>>> (which is the changed page that it might depend on). Note that I didn't
+>>> choose those names!
+>>>
+>>> The three loops are over source files, their lists of dependency pagespecs,
+>>> and files that might have changed. I see the following things we might be
+>>> doing redundantly:
+>>>
+>>> * If `$file` is considered as a potential dependency for more than
+>>>   one `$f`, we evaluate `pagename($file)` more than once. Potential fix:
+>>>   cache them (this turns out to save about half a second on the docwiki,
+>>>   see below).
+>>> * If several pages depend on the same pagespec, we evaluate whether each
+>>>   changed page matches that pagespec more than once: however, we do so
+>>>   with a different location parameter every time, so repeated calls are,
+>>>   in the general case, the only correct thing to do. Potential fix:
+>>>   perhaps special-case "page x depends on page y and nothing else"
+>>>   (i.e. globs that have no wildcards) into a separate hash? I haven't
+>>>   done anything in this direction.
+>>> * Any preparatory work done by pagespec_match (converting the pagespec
+>>>   into Perl, mostly?) is done in the inner loop; switching to
+>>>   pagespec_match_list (significant refactoring) saves more than half a
+>>>   second on the docwiki.
+>>>
+>>> --[[smcv]]
+
+Very good catch on img/meta using the wrong dependency; verified in the wild!
+(I've cherry-picked those bug fixes.)
+
+----
+
+Benchmarking results: I benchmarked by altering docwiki.setup to switch off
+verbose, running "make clean && ./Makefile.PL && make", and timing one rebuild
+of the docwiki followed by three refreshes. Before each refresh I used
+`touch plugins/*.mdwn` to have something significant to refresh.
+
+I'm assuming that "user" CPU time is the important thing here (system time was
+relatively small in all cases, up to 0.35 seconds per run).
+
+master at the time of rebasing: 14.20s to rebuild, 10.04/12.07/14.01s to
+refresh. I think you can see the bug clearly here - the pagespecs are getting
+more complicated every time!
+
+> I can totally see a bug here, and it's one I didn't think existed. Ie,
+> I thought that after the first refresh, the pagespec should stabalize,
+> and what it stabalized to was probably unnecessarily long, but not
+> growing w/o bounds!
+> 
+> a) Explains why ikiwiki.info has been so slow lately. Well that and some
+>    other things that overloaded the system.
+> b) Suggests to me we will probably want to force a rebuild on upgrade
+>    when fixing this (via the mechanism in the postinst).
+>
+> I've investigated why the pagespecs keep growing: When page A changes,
+> its old depends are cleared. Then
+> page B that inlines A gets rebuilt, and its old depends are also cleared.
+> But page B also inlines page C; which means C gets re-rendered. And this
+> happens w/o its old depends being cleared, so C's depends are doubled.
+> --[[Joey]]
+
+After the initial optimization: 14.27s to rebuild, 8.26/8.33/8.26 to refresh.
+Success!
+
+Not pre-joining dependencies actually took about ~0.2s more; I don't know why.
+I'm worried that duplicates will just build up (again) in less simple cases,
+though, so 0.2s is probably a small price to pay for that not happening (it
+might well be experimental error, for that matter).
+
+> It's weird that the suggested optimisations to
+> `add_depends` had no effect. So, the commit message to
+> b6fcb1cb0ef27e5a63184440675d465fad652acf is actually wrong.. ? --[[Joey]] 
+
+>> I'll try benchmarking again on the non-public wiki where I had the 4%
+>> speedup. The docwiki is so small that 4% is hard to measure... --[[smcv]]
+
+Not saving {depends} to the index, using a hash instead of a list to
+de-duplicate, and allowing add_depends to take an arrayref instead of a single
+pagespec had no noticable positive or negative effect on this test.
+
+> I see e4cd168ebedd95585290c97ff42234344bfed46c is still in your branch
+> though. I don't like using an arrayref, it could just take `($page, @depends)`.
+> and I don't see the need to keep it if it doesn't currently help.
+
+>> I'll drop it. --[[smcv]]
+
+> Is there any reason to keep 7227c2debfeef94b35f7d81f42900aa01820caa3
+> if it doesn't improve speed?
+> --[[Joey]] 
+
+>> I'll try benchmarking on a more complex wiki and see whether it has a
+>> positive or negative effect. It does avoid being O(n**2) in number of
+>> dependencies. --[[smcv]]
+
+Memoizing the results of pagename brought the rebuild time down to 14.06s
+and the refresh time down to 7.96/7.92/7.92, a significant win.
+
+> Ok, that seems safe to memoize. (It's a real function and it isn't
+> called with a great many inputs.) Why did you chose to memoize it
+> explicitly rather than adding it to the memoize list at the top?
+
+>> It does depend on global variables, so using Memoize seemed like asking for
+>> trouble. I suppose what I did is equivalent to Memoize though... --[[smcv]]
+
+Refactoring to use pagespec_match_list looks more risky from a code churn
+point of view; rebuild now takes 14.35s, but refresh is only 7.30/7.29/7.28,
+another significant win.
+
+--[[smcv]]
+
+> I had mostly convinced myself that
+> `pagespec_match_list` would not lead to a speed gain here. My reasoning
+> was that you want to stop after finding one match, while `pagespec_match_list`
+> checks all pages for matches. So what we're seeing is that
+> on a rebuild, `@changed` is all pages, and not short-circuiting leads
+> to unnecessary work. OTOH, on refresh, `@changed` is small and I suppose
+> `pagespec_match_list`'s other slight efficiencies win out somehow.
+> 
+> Welcome to the "I made ikiwiki twice as fast
+> and all I got was this lousy git sha1sum" club BTW :-) --[[Joey]] 
+
+[[!tag wishlist patch patch/core]]
index 7b3dbbd5567162c1b3e90d00126cf2190056b176..3ff8b9ef6d54c67c9bd70c4d9edff3b3234ad7c4 100644 (file)
@@ -2,8 +2,8 @@ Either [[plugins/template]] or [[plugins/shortcut]] should support some form
 of very simple text parsing or regex application, to make it possible to write
 shortcuts like these:
 
-    [[mmlist listname@lists.example.org]] -> <listname@example.org> ([mailman page] (http://lists.example.org/mailman/listinfo/listname)
-    [[debcl packagename]] -> [packagename changelog](http://packages.debian.org/changelogs/pool/main/p/packagename/current/changelog)
+    [[!mmlist listname@lists.example.org]] -> <listname@example.org> ([mailman page] (http://lists.example.org/mailman/listinfo/listname)
+    [[!debcl packagename]] -> [packagename changelog](http://packages.debian.org/changelogs/pool/main/p/packagename/current/changelog)
 
 For shortcut definitions, a `match` parameter could supply a regex, and then the `url` and `desc` parameters could make use of the named or numbered groups from the match.
 
index 06f1a83580b035dbf253d42d7b8553a8c03aac4a..f37d75ccb5f1d9b3af1e0ff51433f23fa62b59d8 100644 (file)
@@ -1,7 +1,7 @@
 How about a skip option for [[plugins/inline]]?  This would allow things like the following:
 
-    \[[inline pages="news/*" show="5"]]
-    \[[inline pages="news/*" skip="5" show="5" archive="yes"]]
+    \[[!inline pages="news/*" show="5"]]
+    \[[!inline pages="news/*" skip="5" show="5" archive="yes"]]
 
 > I just wrote a patch. --Ethan
 
index a55a6614111e285be2d4133495e3c41925c0c207..06c06e19110f3f79c3f5c402d6483c76d267a2b0 100644 (file)
@@ -1,11 +1,11 @@
-Several [[ikiwiki/PreprocessorDirective]]s take ikiwiki-formatted text as arguments,
+Several [[ikiwiki/Directive]]s take ikiwiki-formatted text as arguments,
 such as the `then` and `else` arguments of the new `if` directive, or the
 `desc` argument of the `shortcut` directive.  However, smileys do not work in
 these arguments.
 
-Since the arguments to [[ikiwiki/PreprocessorDirective]]s might use the same syntax as
+Since the arguments to [[ikiwiki/Directive]]s might use the same syntax as
 smileys for a different meaning, smiley substitution should not happen until
-after [[ikiwiki/PreprocessorDirective]]s.
+after [[ikiwiki/Directive]]s.
 
 --[[JoshTriplett]]
 
diff --git a/doc/todo/softlinks.mdwn b/doc/todo/softlinks.mdwn
new file mode 100644 (file)
index 0000000..9c5e3fa
--- /dev/null
@@ -0,0 +1,14 @@
+If I have a filesystem soft-link, e.g. "foo.mdwn" links to "bar.mdwn", it doesn't work.
+The page "foo/" does not exist.
+
+This is too bad, because sometimes it is convenient to have several different names for the same page.
+
+Could softlinks be handled gracefully by ikiwiki?
+
+> Soft links are explicitly not handled by IkiWiki as a [[security]] measure.  If you want several names for
+> the same page, I suggest using the [[ikiwiki/directive/meta]] directive to make one page redirect to
+> another.  -- [[Will]]
+
+>> Will is right. I don't plan to support symlinks. [[done]] --[[Joey]]
+
+>> With the appropriate template, inline can also help copy pages around [[DavidBremner]]
index 40886be5565ba58a82f9268c272d13e041a29da0..dfc2766cc73f673aab9fb9b208d5157db22fbf40 100644 (file)
@@ -1,3 +1,137 @@
 How about a direct link from the page header to the source of the latest version, to avoid the need to either use edit or navigate to the current version via the history link?
 
- I'd like this too (and might try to implement it). -- [[jondowland]]
+ I'd like this too (and might try to implement it). -- [[users/jon]]
+
+I just implemented this.  There is one [[patch]] to the default page template, and a new plugin.  -- [[Will]]
+
+All of this code is licensed under the GPLv2+. -- [[Will]]
+
+> The use of sessioncgi here seems undesirable: on wikis where anonymity is
+> not allowed, you'll be asked to log in. Couldn't you achieve the same thing
+> by loading the index with IkiWiki::loadindex, like [[plugins/goto]] does?
+> --[[smcv]]
+
+[[!template id=gitbranch branch=smcv/ready/getsource
+  author="[[Will]]/[[smcv]]"]]
+[[done]]
+
+>> I've applied the patch below in a git branch, fixed my earlier criticism,
+>> and also fixed a couple of other issues I noticed:
+>>
+>> * missing pages could be presented better as a real 404 page
+>> * the default Content-type should probably be UTF-8 since the rest of
+>>   IkiWiki tends to assume that
+>> * emitting attachments (images, etc.) as text/plain isn't going to work :-)
+>>
+>> Any opinions on my branch? I think it's ready for merge, if Joey approves.
+>>
+>> --[[smcv]]
+
+>>> I need a copyright&license statement, so debian/copyright can be updated for
+>>> the plugin, before I can merge this. Otherwise ready. --[[Joey]]
+
+>>> That looks like a nice set of fixes.  One more that might be worthwhile: instead of reading the page source into a var, and then writing it out later, it might be nice to just
+>>>  `print readfile(srcfile(pagesources{$page}));` at the appropriate point. -- [[Will]]
+
+>>>> OK, I've committed that. --[[smcv]]
+
+----
+
+    diff --git a/templates/page.tmpl b/templates/page.tmpl
+    index f2f9c34..3176bed 100644
+    --- a/templates/page.tmpl
+    +++ b/templates/page.tmpl
+    @@ -46,6 +46,9 @@
+     <TMPL_IF NAME="HISTORYURL">
+     <li><a href="<TMPL_VAR HISTORYURL>">History</a></li>
+     </TMPL_IF>
+    +<TMPL_IF NAME="GETSOURCEURL">
+    +<li><a href="<TMPL_VAR GETSOURCEURL>">Get Source</a></li>
+    +</TMPL_IF>
+     <TMPL_IF NAME="PREFSURL">
+     <li><a href="<TMPL_VAR PREFSURL>">Preferences</a></li>
+     </TMPL_IF>
+
+----
+
+    #!/usr/bin/perl
+    package IkiWiki::Plugin::getsource;
+    
+    use warnings;
+    use strict;
+    use IkiWiki;
+    use open qw{:utf8 :std};
+    
+    sub import {
+       hook(type => "getsetup", id => "getsource", call => \&getsetup);
+       hook(type => "pagetemplate", id => "getsource", call => \&pagetemplate);
+       hook(type => "sessioncgi", id => "getsource", call => \&cgi_getsource);
+    }
+    
+    sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1,
+               },
+               getsource_mimetype => {
+                       type => "string",
+                       example => "application/octet-stream",
+                       description => "Mime type for returned source.",
+                       safe => 1,
+                       rebuild => 0,
+               },
+    }
+    
+    sub pagetemplate (@) {
+       my %params=@_;
+    
+       my $page=$params{page};
+       my $template=$params{template};
+    
+       if (length $config{cgiurl}) {
+               $template->param(getsourceurl => IkiWiki::cgiurl(do => "getsource", page => $page));
+               $template->param(have_actions => 1);
+       }
+    }
+    
+    sub cgi_getsource ($$) {
+       my $cgi=shift;
+       my $session=shift;
+    
+       # Note: we use sessioncgi rather than just cgi
+       # because we need $IkiWiki::pagesources{} to be
+       # populated.
+       
+       return unless (defined $cgi->param('do') &&
+                                       $cgi->param("do") eq "getsource");
+    
+       IkiWiki::decode_cgi_utf8($cgi);
+    
+       my $page=$cgi->param('page');
+    
+       if ($IkiWiki::pagesources{$page}) {
+               
+               my $data = IkiWiki::readfile(IkiWiki::srcfile($IkiWiki::pagesources{$page}));
+               
+               if (! $config{getsource_mimetype}) {
+                       $config{getsource_mimetype} = "text/plain";
+               }
+               
+               print "Content-Type: $config{getsource_mimetype}\r\n";
+               
+               print ("\r\n");
+               
+               print $data;
+               
+               exit 0;
+       }
+       
+       error("Unable to find page source for page: $page");
+    
+       exit 0;
+    }
+    
+    1
+
+[[done]] --[[smcv]]
diff --git a/doc/todo/structured_page_data.mdwn b/doc/todo/structured_page_data.mdwn
new file mode 100644 (file)
index 0000000..72bfd8d
--- /dev/null
@@ -0,0 +1,628 @@
+This is an idea from [[JoshTriplett]].  --[[Joey]]
+
+Some uses of ikiwiki, such as for a bug-tracking system (BTS), move a bit away from the wiki end
+of the spectrum, and toward storing structured data about a page or instead
+of a page. 
+
+For example, in a bug report you might want to choose a severity from a
+list, enter a version number, and have a bug submitter or owner recorded,
+etc. When editing online, it would be nice if these were separate fields on
+the form, rather than the data being edited in the big edit form.
+
+There's a tension here between remaining a wiki with human-editable source
+files, containing freeform markup, and more structured data storage. I
+think that it would be best to include the structured data in the page,
+using a directive. Something like:
+
+       part of page content
+       \[[data yaml="<arbitrary yaml here>"]]
+       rest of page content 
+
+As long as the position of the directive is not significant, it could be
+stripped out when web editing, the yaml used to generate/populate form fields, 
+and then on save, the directive regenerated and inserted at top/bottom of
+the page.
+
+Josh thinks that yaml is probably a good choice, but the source could be a
+`.yaml` file that contains no directives, and just yaml. An addition
+complication in this scenario is, if the yaml included wiki page formatted content,
+ikiwiki would have to guess or be told what markup language it used.
+
+Either way, the yaml on the page would encode fields and their current content.
+Information about data types would be encoded elsewhere, probably on a
+parent page (using a separate directive). That way, all child pages could
+be forced to have the same fields.
+
+There would be some simple types like select, boolean, multiselect, string, wiki markup.
+Probably lists of these (ie, list of strings). Possibly more complex data
+structures.
+
+It should also be possible for plugins to define new types, and the type
+definitions should include validation of entered data, and how to prompt
+the user for the data.
+
+This seems conceptually straightforward, if possibly quite internally
+complex to handle the more complicated types and validation.
+
+One implementation wrinkle is how to build the html form. The editpage.tmpl
+currently overrides the standard [[!cpan CGI::FormBuilder]] generated form,
+which was done to make the edit page be laid out in a nice way. This,
+however, means that new fields cannot be easily added to it using
+[[!cpan CGI::FormBuilder]]. The attachment plugin uses the hack of bouilding
+up html by hand and dumping it into the form via a template variable. 
+
+It would be nice if the type implementation code could just use
+FormBuilder, since its automatic form generation, and nice field validation
+model is a perfect match for structured data. But this problem with
+editpage.tmpl would have to be sorted out to allow that.
+
+Additional tie-ins:
+
+* Pagespecs that can select pages with a field with a given value, etc.
+  This should use a pagespec function like field(fieldname, value).  The
+  semantics of this will depend on the type of the field; text fields will
+  match value against the text, and link fields will check for a link
+  matching the pagespec value.
+* The search plugin could allow searching for specific fields with specific
+  content. (xapian term search is a good fit).
+
+See also:
+
+[[tracking_bugs_with_dependencies]]
+
+> I was also thinking about this for bug tracking.  I'm not sure what
+> sort of structured data is wanted in a page, so I decided to brainstorm
+> use cases:
+>
+> * You just want the page to be pretty.
+> * You want to access the data from another page.  This would be almost like
+>     like a database lookup, or the OpenOffice Calc [VLookup](http://wiki.services.openoffice.org/wiki/Documentation/How_Tos/Calc:_VLOOKUP_function) function.
+> * You want to make a pagespec depend upon the data.  This could be used
+>    for dependancy tracking - you could match against pages listed as dependencies,
+>    rather than all pages linked from a given page.
+>
+>The first use case is handled by having a template in the page creation.  You could
+
+
+
+
+>have some type of form to edit the data, but that's just sugar on top of the template.
+>If you were going to have a web form to edit the data, I can imagine a few ways to do it:
+>
+> * Have a special page type which gets compiled into the form.  The page type would
+>    need to define the form as well as hold the stored data.
+> * Have special directives that allow you to insert form elements into a normal page.
+>
+>I'm happy with template based page creation as a first pass...
+>
+>The second use case could be handled by a regular expression directive. eg:
+>
+> \[[regex spec="myBug" regex="Depends: ([^\s]+)"]]
+>
+> The directive would be replaced with the match from the regex on the 'myBug' page... or something.
+>
+>The third use case requires a pagespec function.  One that matched a regex in the page might work.
+>Otherwise, another option would be to annotate links with a type, and then check the type of links in
+>a pagespec.  e.g. you could have `depends` links and normal links.
+>
+>Anyway, I just wanted to list the thoughts.  In none of these use cases is straight yaml or json the
+>obvious answer.  -- [[Will]]
+
+>> Okie.  I've had a play with this.  A 'form' plugin is included inline below, but it is only a rough first pass to
+>> get a feel for the design space.
+>>
+>> The current design defines a new type of page - a 'form'.  The type of page holds YAML data
+>> defining a FormBuilder form.  For example, if we add a file to the wiki source `test.form`:
+
+    ---
+    fields:
+      age:
+        comment: This is a test
+        validate: INT
+        value: 15
+
+>> The YAML content is a series of nested hashes.  The outer hash is currently checked for two keys:
+>> 'template', which specifies a parameter to pass to the FromBuilder as the template for the
+>> form, and 'fields', which specifies the data for the fields on the form.
+>> each 'field' is itself a hash.  The keys and values are arguments to the formbuilder form method.
+>> The most important one is 'value', which specifies the value of that field.
+>>
+>> Using this, the plugin below can output a form when asked to generate HTML.  The Formbuilder
+>> arguments are sanitized (need a thorough security audit here - I'm sure I've missed a bunch of
+>> holes).  The form is generated with default values as supplied in the YAML data.  It also has an
+>> 'Update Form' button at the bottom.
+>>
+>>  The 'Update Form' button in the generated HTML submits changed values back to IkiWiki.  The
+>> plugin captures these new values, updates the YAML and writes it out again.  The form is
+>> validated when edited using this method.  This method can only edit the values in the form.
+>> You cannot add new fields this way.
+>>
+>> It is still possible to edit the YAML directly using the 'edit' button.  This allows adding new fields
+>> to the form, or adding other formbuilder data to change how the form is displayed.
+>>
+>> One final part of the plugin is a new pagespec function.  `form_eq()` is a pagespec function that
+>> takes two arguments (separated by a ',').  The first argument is a field name, the second argument
+>> a value for that field.  The function matches forms (and not other page types) where the named
+>> field exists and holds the value given in the second argument.  For example:
+    
+    \[[!inline pages="form_eq(age,15)" archive="yes"]]
+    
+>> will include a link to the page generated above.
+
+>>> Okie, I've just made another plugin to try and do things in a different way.
+>>> This approach adds a 'data' directive.  There are two arguments, `key` and `value`.
+>>> The directive is replaced by the value.  There is also a match function, which is similar
+>>> to the one above.  It also takes two arguments, a key and a value.  It returns true if the
+>>> page has that key/value pair in a data directive.  e.g.:
+
+    \[[!data key="age" value="15"]]
+
+>>> then, in another page:
+
+    \[[!inline pages="data_eq(age,15)" archive="yes"]]
+
+>>> I expect that we could have more match functions for each type of structured data,
+>>> I just wanted to implement a rough prototype to get a feel for how it behaves.  -- [[Will]]
+
+>> Anyway, here are the plugins.  As noted above these are only preliminary, exploratory, attempts. -- [[Will]]
+
+>>>> I've just updated the second of the two patches below.  The two patches are not mutually
+>>>> exclusive, but I'm leaning towards the second as more useful (for the things I'm doing). -- [[Will]]
+
+I think it's awesome that you're writing this code to explore the problem
+space, [[Will]] -- and these plugins are good stabs at at least part of it.
+Let me respond to a few of your comments.. --[[Joey]]
+
+On use cases, one use case is a user posting a bug report with structured
+data in it. A template is one way, but then the user has to deal with the
+format used to store the structured data. This is where a edit-time form
+becomes essential.
+
+> This was the idea with the 'form' plugin.  With the 'data' plugin I was exploring
+> a different approach: try to keep the markup simple enough that the user can edit
+> the markup directly, and still have that be ok.  I admit it is a stretch, but I thought
+> it worth exploring.
+
+Another use case is, after many such bugs have been filed,
+wanting to add a new field to each bug report. To avoid needing to edit
+every bug report it would be good if the fields in a bug report were
+defined somewhere else, so that just that one place can be edited to add
+the new field, and it will show up in each bug report (and in each bug
+report's edit page, as a new form field).
+
+> If I was going to do that, I'd use a perl script on a checked out
+> workspace.  I think you're describing a rare operation and
+> so I'd be happy not having a web interface for it.  Having said that,
+> if you just wanted to change the form for *new* pages, then you
+> can just edit the template used to create new pages.
+
+Re the form plugin, I'm uncomfortable with tying things into
+[[!cpan CGI::FormBuilder]] quite so tightly as you have.
+
+> Yeah :).  But I wanted to explore the space and that was the
+> easiest way to start.
+
+CGI::FormBuilder
+could easily change in a way that broke whole wikis full of pages. Also,
+needing to sanitize FormBuilder fields with security implications is asking
+for trouble, since new FormBuilder features could add new fields, or
+add new features to existing fields (FormBuilder is very DWIM) that open
+new security holes. 
+
+> There is a list of allowed fields.  I only interpret those.
+
+I think that having a type system, that allows defining specific types,
+like "email address", by writing code (that in turn can use FormBuilder),
+is a better approach, since it should avoid becoming a security problem.
+
+> That would be possible.  I think an extension to the 'data' plugin might
+> work here.
+
+One specific security hole, BTW, is that if you allow the `validate` field,
+FormBuilder will happily treat it as a regexp, and we don't want to expose
+arbitrary perl regexps, since they can at least DOS a system, and can
+probably be used to run arbitrary perl code.
+
+> I validate the validate field :).  It only allows validate fields that match
+> `/^[\w\s]+$/`.  This means you can really only use the pre-defined
+> validation types in FormBuilder.
+
+The data plugin only deals with a fairly small corner of the problem space,
+but I think does a nice job at what it does. And could probably be useful
+in a large number of other cases.
+
+> I think the data plugin is more likely to be useful than the form plugin.
+> I was thinking of extending the data directive by allowing an 'id' parameter.
+> When you have an id parameter, then you can display a small form for that
+> data element.  The submission handler would look through the page source
+> for the data directive with the right id parameter and edit it.  This would
+> make the data directive more like the current 'form' plugin.
+
+> That is making things significantly more complex for less significant gain though. --[[Will]]
+
+> Oh, one quick other note.  The data plugin below was designed to handle multiple
+> data elements in a single directive.  e.g.
+
+    \[[!data key="Depends on" link="bugs/bugA" link="bugs/bugB" value=6]]
+
+> would match `data_eq(Depends on,6)`, `data_link(Depends on,bugs/bugA)`, `data_link(Depends on,bugs/bugB)`
+> or, if you applied the patch in [[todo/tracking_bugs_with_dependencies]] then you can use 'defined pagespecs'
+> such as `data_link(Depends on,~openBugs)`. <a id="another_kind_of_links" />The ability to label links like this allows separation of
+> dependencies between bugs from arbitrary links.
+>> This issue (the need for distinguished kinds of links) has also been brought up in other discussions: [[tracking_bugs_with_dependencies#another_kind_of_links]] (deps vs. links) and [[tag_pagespec_function]] (tags vs. links). --Ivan Z.
+
+----
+
+    #!/usr/bin/perl
+    # Interpret YAML data to make a web form
+    package IkiWiki::Plugin::form;
+    
+    use warnings;
+    use strict;
+    use CGI::FormBuilder;
+    use IkiWiki 2.00;
+    
+    sub import {
+       hook(type => "getsetup", id => "form", call => \&getsetup);
+       hook(type => "htmlize", id => "form", call => \&htmlize);
+       hook(type => "sessioncgi", id => "form", call => \&cgi_submit);
+    }
+    
+    sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+    }
+    
+    sub makeFormFromYAML ($$$) {
+       my $page = shift;
+       my $YAMLString = shift;
+       my $q = shift;
+    
+       eval q{use YAML};
+       error($@) if $@;
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       
+       my ($dataHashRef) = YAML::Load($YAMLString);
+       
+       my @fields = keys %{ $dataHashRef->{fields} };
+       
+       unshift(@fields, 'do');
+       unshift(@fields, 'page');
+       unshift(@fields, 'rcsinfo');
+       
+       # print STDERR "Fields: @fields\n";
+       
+       my $submittedPage;
+       
+       $submittedPage = $q->param('page') if defined $q;
+       
+       if (defined $q && defined $submittedPage && ! ($submittedPage eq $page)) {
+               error("Submitted page doensn't match current page: $page, $submittedPage");
+       }
+       
+       error("Page not backed by file") unless defined $pagesources{$page};
+       my $file = $pagesources{$page};
+       
+       my $template;
+       
+       if (defined $dataHashRef->{template}) {
+               $template = $dataHashRef->{template};
+       } else {
+               $template = "form.tmpl";
+       }
+       
+       my $form = CGI::FormBuilder->new(
+               fields => \@fields,
+               charset => "utf-8",
+               method => 'POST',
+               required => [qw{page}],
+               params => $q,
+               action => $config{cgiurl},
+               template => scalar IkiWiki::template_params($template),
+               wikiname => $config{wikiname},
+               header => 0,
+               javascript => 0,
+               keepextras => 0,
+               title => $page,
+       );
+       
+       $form->field(name => 'do', value => 'Update Form', required => 1, force => 1, type => 'hidden');
+       $form->field(name => 'page', value => $page, required => 1, force => 1, type => 'hidden');
+       $form->field(name => 'rcsinfo', value => IkiWiki::rcs_prepedit($file), required => 1, force => 0, type => 'hidden');
+       
+       my %validkey;
+       foreach my $x (qw{label type multiple value fieldset growable message other required validate cleanopts columns comment disabled linebreaks class}) {
+               $validkey{$x} = 1;
+       }
+    
+       while ( my ($name, $data) = each(%{ $dataHashRef->{fields} }) ) {
+               next if $name eq 'page';
+               next if $name eq 'rcsinfo';
+               
+               while ( my ($key, $value) = each(%{ $data }) ) {
+                       next unless $validkey{$key};
+                       next if $key eq 'validate' && !($value =~ /^[\w\s]+$/);
+               
+                       # print STDERR "Adding to field $name: $key => $value\n";
+                       $form->field(name => $name, $key => $value);
+               }
+       }
+       
+       # IkiWiki::decode_form_utf8($form);
+       
+       return $form;
+    }
+    
+    sub htmlize (@) {
+       my %params=@_;
+       my $content = $params{content};
+       my $page = $params{page};
+    
+       my $form = makeFormFromYAML($page, $content, undef);
+    
+       return $form->render(submit => 'Update Form');
+    }
+    
+    sub cgi_submit ($$) {
+       my $q=shift;
+       my $session=shift;
+       
+       my $do=$q->param('do');
+       return unless $do eq 'Update Form';
+       IkiWiki::decode_cgi_utf8($q);
+    
+       eval q{use YAML};
+       error($@) if $@;
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       
+       my $page = $q->param('page');
+       
+       return unless exists $pagesources{$page};
+       
+       return unless $pagesources{$page} =~ m/\.form$/ ;
+       
+       return unless IkiWiki::check_canedit($page, $q, $session);
+    
+       my $file = $pagesources{$page};
+       my $YAMLString = readfile(IkiWiki::srcfile($file));
+       my $form = makeFormFromYAML($page, $YAMLString, $q);
+    
+       my ($dataHashRef) = YAML::Load($YAMLString);
+    
+       if ($form->submitted eq 'Update Form' && $form->validate) {
+               
+               #first update our data structure
+               
+               while ( my ($name, $data) = each(%{ $dataHashRef->{fields} }) ) {
+                       next if $name eq 'page';
+                       next if $name eq 'rcs-data';
+                       
+                       if (defined $q->param($name)) {
+                               $data->{value} = $q->param($name);
+                       }
+               }
+               
+               # now write / commit the data
+               
+               writefile($file, $config{srcdir}, YAML::Dump($dataHashRef));
+    
+               my $message = "Web form submission";
+    
+               IkiWiki::disable_commit_hook();
+               my $conflict=IkiWiki::rcs_commit($file, $message,
+                       $form->field("rcsinfo"),
+                       $session->param("name"), $ENV{REMOTE_ADDR});
+               IkiWiki::enable_commit_hook();
+               IkiWiki::rcs_update();
+    
+               require IkiWiki::Render;
+               IkiWiki::refresh();
+    
+               IkiWiki::redirect($q, "$config{url}/".htmlpage($page)."?updated");
+    
+       } else {
+               error("Invalid data!");
+       }
+    
+       exit;
+    }
+    
+    package IkiWiki::PageSpec;
+    
+    sub match_form_eq ($$;@) {
+       my $page=shift;
+       my $argSet=shift;
+       my @args=split(/,/, $argSet);
+       my $field=shift @args;
+       my $value=shift @args;
+    
+       my $file = $IkiWiki::pagesources{$page};
+       
+       if ($file !~ m/\.form$/) {
+               return IkiWiki::FailReason->new("page is not a form");
+       }
+       
+       my $YAMLString = IkiWiki::readfile(IkiWiki::srcfile($file));
+    
+       eval q{use YAML};
+       error($@) if $@;
+    
+       my ($dataHashRef) = YAML::Load($YAMLString);
+    
+       if (! defined $dataHashRef->{fields}->{$field}) {
+               return IkiWiki::FailReason->new("field '$field' not defined in page");
+       }
+    
+       my $formVal = $dataHashRef->{fields}->{$field}->{value};
+    
+       if ($formVal eq $value) {
+               return IkiWiki::SuccessReason->new("field value matches");
+       } else {
+               return IkiWiki::FailReason->new("field value does not match");
+       }
+    }
+    
+    1
+
+----
+
+    #!/usr/bin/perl
+    # Allow data embedded in a page to be checked for
+    package IkiWiki::Plugin::data;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 2.00;
+    
+    my $inTable = 0;
+    
+    sub import {
+       hook(type => "getsetup", id => "data", call => \&getsetup);
+       hook(type => "needsbuild", id => "data", call => \&needsbuild);
+       hook(type => "preprocess", id => "data", call => \&preprocess, scan => 1);
+       hook(type => "preprocess", id => "datatable", call => \&preprocess_table, scan => 1);   # does this need scan?
+    }
+    
+    sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => 1, # format plugin
+               },
+    }
+    
+    sub needsbuild (@) {
+       my $needsbuild=shift;
+       foreach my $page (keys %pagestate) {
+               if (exists $pagestate{$page}{data}) {
+                       if (exists $pagesources{$page} &&
+                           grep { $_ eq $pagesources{$page} } @$needsbuild) {
+                               # remove state, it will be re-added
+                               # if the preprocessor directive is still
+                               # there during the rebuild
+                               delete $pagestate{$page}{data};
+                       }
+               }
+       }
+    }
+    
+    sub preprocess (@) {
+       my @argslist = @_;
+       my %params=@argslist;
+       
+       my $html = '';
+       my $class = defined $params{class}
+                       ? 'class="'.$params{class}.'"'
+                       : '';
+       
+       if ($inTable) {
+               $html = "<th $class >$params{key}:</th><td $class >";
+       } else {
+               $html = "<span $class >$params{key}:";
+       }
+       
+       while (scalar(@argslist) > 1) {
+               my $type = shift @argslist;
+               my $data = shift @argslist;
+               if ($type eq 'link') {
+                       # store links raw
+                       $pagestate{$params{page}}{data}{$params{key}}{link}{$data} = 1;
+                       my $link=IkiWiki::linkpage($data);
+                       add_depends($params{page}, $link);
+                       $html .= ' ' . htmllink($params{page}, $params{destpage}, $link);
+               } elsif ($type eq 'data') {
+                       $data = IkiWiki::preprocess($params{page}, $params{destpage}, 
+                               IkiWiki::filter($params{page}, $params{destpage}, $data));
+                       $html .= ' ' . $data;
+                       # store data after processing - allows pagecounts to be stored, etc.
+                       $pagestate{$params{page}}{data}{$params{key}}{data}{$data} = 1;
+               }
+       }
+               
+       if ($inTable) {
+               $html .= "</td>";
+       } else {
+               $html .= "</span>";
+       }
+       
+       return $html;
+    }
+    
+    sub preprocess_table (@) {
+       my %params=@_;
+    
+       my @lines;
+       push @lines, defined $params{class}
+                       ? "<table class=\"".$params{class}.'">'
+                       : '<table>';
+    
+       $inTable = 1;
+    
+       foreach my $line (split(/\n/, $params{datalist})) {
+               push @lines, "<tr>" . IkiWiki::preprocess($params{page}, $params{destpage}, 
+                       IkiWiki::filter($params{page}, $params{destpage}, $line)) . "</tr>";
+       }
+    
+       $inTable = 0;
+    
+       push @lines, '</table>';
+    
+       return join("\n", @lines);
+    }
+    
+    package IkiWiki::PageSpec;
+    
+    sub match_data_eq ($$;@) {
+       my $page=shift;
+       my $argSet=shift;
+       my @args=split(/,/, $argSet);
+       my $key=shift @args;
+       my $value=shift @args;
+    
+       if (! exists $IkiWiki::pagestate{$page}{data}) {
+               return IkiWiki::FailReason->new("page does not contain any data directives");
+       }
+       
+       if (! exists $IkiWiki::pagestate{$page}{data}{$key}) {
+               return IkiWiki::FailReason->new("page does not contain data key '$key'");
+       }
+       
+       if ($IkiWiki::pagestate{$page}{data}{$key}{data}{$value}) {
+               return IkiWiki::SuccessReason->new("value matches");
+       } else {
+               return IkiWiki::FailReason->new("value does not match");
+       }
+    }
+    
+    sub match_data_link ($$;@) {
+       my $page=shift;
+       my $argSet=shift;
+       my @params=@_;
+       my @args=split(/,/, $argSet);
+       my $key=shift @args;
+       my $value=shift @args;
+    
+       if (! exists $IkiWiki::pagestate{$page}{data}) {
+               return IkiWiki::FailReason->new("page $page does not contain any data directives and so cannot match a link");
+       }
+       
+       if (! exists $IkiWiki::pagestate{$page}{data}{$key}) {
+               return IkiWiki::FailReason->new("page $page does not contain data key '$key'");
+       }
+       
+       foreach my $link (keys %{ $IkiWiki::pagestate{$page}{data}{$key}{link} }) {
+               # print STDERR "Checking if $link matches glob $value\n";
+               if (match_glob($link, $value, @params)) {
+                       return IkiWiki::SuccessReason->new("Data link on page $page with key $key matches glob $value: $link");
+               }
+       }
+    
+       return IkiWiki::FailReason->new("No data link on page $page with key $key matches glob $value");
+    }
+    
+    1
diff --git a/doc/todo/structured_page_data/discussion.mdwn b/doc/todo/structured_page_data/discussion.mdwn
new file mode 100644 (file)
index 0000000..bc7f392
--- /dev/null
@@ -0,0 +1 @@
+How about using JSON? YAML is popular in the Perl world, but the Web 2.0 world seems more excited about using JSON for data serialization. I find it easier to edit JSON by hand than YAML. -- [[Edward|/users/Edward_Betts]]
index 51a409963efa533f11579d2cab73f0c40e06376c..b73155c985b0053e1db28bcd611e842e130b0cf4 100644 (file)
@@ -7,7 +7,7 @@ AFAICS, my web browser already has a built-in monospace font, which I can
 see in action in the preformatted patch below. So I don't see why the
 default style sheet should do this. --[[Joey]]
 
-[[tag patch]]
+[[!tag patch]]
 
 <pre>
 diff --git a/basewiki/style.css b/basewiki/style.css
index b0ebf5b9e6ae5b51c99d2fa004af2aafc5323b36..5a1e1286df4faa271f1d18b8546669fe1050cade 100644 (file)
@@ -12,7 +12,7 @@ And there is a perl module:   Text::WikiCreole
 
 Syntax file for vim: http://www.peter-hoffmann.com/code/vim/  (Since a typical ikiwiki user usually use external editors. :))
 
-> Should be pretty easy to add a plugin to do it using [[cpan
+> Should be pretty easy to add a plugin to do it using [[!cpan
 > Text::WikiCreole]]. --[[Joey]]
 
 [[done]]
index a59f9ad5ac86edab5e1527f266565764c1e826dc..18ce4e106e34b0e649c39b17bfcddb41b72f4f60 100644 (file)
@@ -1,8 +1,8 @@
-I think it would be useful for ikiwiki to support [[debpkg sdf]] input,
+I think it would be useful for ikiwiki to support [[!debpkg sdf]] input,
 which can be converted and rendered to many formats.
 I should add, however, that SDF allows executing arbitrary perl code
 from its documents; which means some sanitization would need to occur
 before the document is fed to sdf.
 --[[JeremieKoenig]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 8476d1b44f8abdb5b9c38e7de7947acdd9de9511..006b6fd5ea895be29fec48ec2bc2a248880906f7 100644 (file)
@@ -1,4 +1,4 @@
-ikiwiki should support writing plugins in other languages
+ikiwiki should support [[writing plugins in other languages|plugins/write/external]]
 
 > [[done]] !!
 
index 50bc17ba3ff9e8077bfac56ebfc73ba3a1bef193..aae0b3008060994160b2b7207eedd46130fdd3a2 100644 (file)
@@ -45,6 +45,8 @@ Is this simple enough to be sensible?
 
 >>> As a side note, the feature described above (having a form not to add a page but to expand it in a formated way) would be useful for other things when the content is short (timetracking, sub-todo list items, etc..) --[[hb]]
 
+# [[MarceloMagallon]]'s implementation
+
 I've been looking into this.  I'd like to implement a "blogcomments"
 plugin.  Looking at the code, I think the way to go is to have a
 formbuilder_setup hook that uses a different template instead of the
@@ -62,7 +64,7 @@ So, I have some code, included below.  For some reason that I don't quite get it
 
 What I ended up doing is write something like this to the page:
 
-    [[blogcomment from="""Username""" timestamp="""12345""" subject="""Some text""" text="""the text of the comment"""]]
+    [[!blogcomment from="""Username""" timestamp="""12345""" subject="""Some text""" text="""the text of the comment"""]]
 
 Each comment is processed to something like this:
 
@@ -80,7 +82,7 @@ Each comment is processed to something like this:
 
 -- [[MarceloMagallon]]
 
-# Code
+## Code
 
     #!/usr/bin/perl
     package IkiWiki::Plugin::comments;
@@ -89,14 +91,14 @@ Each comment is processed to something like this:
     use strict;
     use IkiWiki '1.02';
 
-    sub import { #{{{
+    sub import {
         hook(type => "formbuilder_setup", id => "comments",
             call => \&formbuilder_setup);
         hook(type => "preprocess", id => "blogcomment",
             call => \&preprocess);  
-    } # }}}
+    }
 
-    sub formbuilder_setup (@) { #{{{
+    sub formbuilder_setup (@) {
         my %params=@_;
         my $cgi = $params{cgi};
         my $form = $params{form};   
@@ -133,12 +135,12 @@ Each comment is processed to something like this:
             $cgi->param('comments') : '';
         my $comment=$cgi->param('blogcomment');
 
-        $content.=qq{[[blogcomment from="""$name""" timestamp="""$timestamp""" subject="""$subject""" text="""$comment"""]]\n\n};
+        $content.=qq{[[!blogcomment from="""$name""" timestamp="""$timestamp""" subject="""$subject""" text="""$comment"""]]\n\n};
         $content=~s/\n/\r\n/g;
         $form->field(name => "editcontent", value => $content, force => 1);
-    } # }}}
+    }
 
-    sub preprocess (@) { #{{{
+    sub preprocess (@) {
         my %params=@_;
 
         my ($text, $date, $from, $subject, $r);
@@ -157,6 +159,62 @@ Each comment is processed to something like this:
         $r .= "</dl>\n" . $text . "</div>\n";
 
         return $r;
-    } # }}}
+    }
     
-    1;
\ No newline at end of file
+    1;
+
+# [[smcv]]'s implementation
+
+I've started a smcvpostcomment plugin (to be renamed to postcomment if people like it, but I'm namespacing it while it's still experimental) which I think more closely resembles what Joey was after. The code is cargo-culted from a mixture of editpage and inline's "make a blog post" support - it has to use a lot of semi-internal IkiWiki:: functions (both of those plugins do too). It doesn't fully work yet, but I'll try to get it into a state where it basically works and can be published in the next week or two.
+
+My approach is:
+
+* Comments are intended to be immutable after posting (so, only editable by direct committers), so they go on internal pages (*._comment); these internal pages are checked in to the RCS (although later I might make this optional)
+
+* ?do=smcvpostcomment (in the CGI script) gives a form that lets logged-in users (later, optionally also anonymous users) create a new comment
+
+* \[[!smcvpostcomment]] just inserts a "Post comment" button into the current page, which goes to ?do=smcvpostcomment - it's intended to be used in conjunction with an \[[!inline]] that will display the comments
+
+* The title (subject line), author and authorurl are set with \[[!meta]] directives, just like the way aggregate does it (which means I'll probably have to disallow the use of those \[[!meta]] directives in the body of the comment, to avoid spoofing - obviously, spoofing can be detected by looking at RecentChanges or gitweb, but the expectation for blog-style comments is that the metadata seen in the comment can be trusted)
+
+* The initial plan is to have comments hard-coded to be in Markdown, with further directives not allowed - I'll relax this when I've worked out what ought to be allowed!
+
+I've also updated Marcelo's code (above) to current ikiwiki, and moved it to a "marceloblogcomment" namespace - it's in the "marcelocomments" branch of my repository (see <http://git.debian.org/?p=users/smcv/ikiwiki.git;a=log;h=refs/heads/marcelocomments>). I had to reconstitute the .tmpl file, which Marcelo didn't post here.
+
+--[[smcv]]
+
+OK, the postcomment branch in my repository contains an implementation. What
+do you think so far? Known issues include:
+
+* The combination of RSS/Atom links and the "post new comment..." button is
+  ugly - I need a way to integrate the "new comment" button into the feed links
+  somehow, like the way inline embeds its own "new blog post..." feature
+  (I don't think the current way really scales, though)
+
+* There are some tweakables (whether to commit comments into the VCS, whether
+  wikilinks are allowed, whether directives are allowed) that are theoretically
+  configurable, but are currently hard-coded
+
+* The wikilink/directive disarming doesn't work unless you have
+  prefixdirectives set (which I just realised)
+
+* \[[!smcvpostcomment]] now displays the comments too, by invoking \[[!inline]]
+  with suitable parameters - but it does so in a very ugly way
+
+* Start-tags in a comment with no corresponding end-tag break page formatting
+  (unless htmltidy is enabled - inline and aggregate have the same problem)
+
+* There is no access control, so anonymous users can always comment, and so
+  can all logged-in users. Perhaps we need to extend canedit() to support
+  different types of edit? Or perhaps I should ignore canedit() and make the
+  access control configurable via a parameter to \[[!smcvpostcomment]]?
+  I'd like to be able to let anonymous (or at least non-admin) users comment
+  on existing pages, but not edit or create pages (but perhaps I'm being too
+  un-wikiish).
+
+--[[smcv]]
+
+I've updated smcvpostcomment and publicised it as [[plugins/contrib/comments]]. --[[smcv]]
+
+> While there is still room for improvement and entirely other approaches,
+> I am calling this done since smcv's comments plugin is ready. --[[Joey]] 
diff --git a/doc/todo/syntax_highlighting.mdwn b/doc/todo/syntax_highlighting.mdwn
new file mode 100644 (file)
index 0000000..3d12282
--- /dev/null
@@ -0,0 +1,120 @@
+There's been a lot of work on contrib syntax highlighting plugins. One should be
+picked and added to ikiwiki core.
+
+We want to support both converting whole source files into wiki
+pages, as well as doing syntax highlighting as a preprocessor directive 
+(which is either passed the text, or reads it from a file). But,
+the [[ikiwiki/directive/format]] directive makes this easy enough to 
+do if the plugin only supports whole source files. So, syntax plugins
+do no really need their own preprocessor directive, unless it makes
+things easier for the user.
+
+## The big list of possibilities
+
+* [[plugins/contrib/highlightcode]] uses [[!cpan Syntax::Highlight::Engine::Kate]],
+  operates on whole source files only, has a few bugs (see
+  [here](http://u32.net/Highlight_Code_Plugin/), and needs to be updated to
+  support [[bugs/multiple_pages_with_same_name]]. (Currently a 404 :-( )
+* [[!cpan IkiWiki-Plugin-syntax]] only operates as a directive.
+  Interestingly, it supports multiple highlighting backends, including Kate
+  and Vim.
+* [[plugins/contrib/syntax]] only operates as a directive
+  ([[not_on_source_code_files|automatic_use_of_syntax_plugin_on_source_code_files]]),
+  and uses [[!cpan Text::VimColor]].
+* [[plugins/contrib/sourcehighlight]] uses source-highlight, and operates on
+  whole source files only. Needs to be updated to
+  support [[bugs/multiple_pages_with_same_name]].
+* [[sourcecode|todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion]]
+  also uses source-highlight, and operates on whole source files.
+  Updated to work with the fix for [[bugs/multiple_pages_with_same_name]].  Untested with files with no extension, e.g. `Makefile`.
+* [[users/jasonblevins]]'s code plugin uses source-highlight, and supports both
+  whole file and directive use.
+
+* [hlsimple](http://pivot.cs.unb.ca/git/?p=ikiplugins.git;a=blob_plain;f=IkiWiki/Plugin/hlsimple.pm;hb=HEAD) is a wrapper for the the perl module [[!cpan Syntax::Highlight::Engine::Simple]].  This is pure perl, pretty simple, uses css. It ought to be pretty fast (according to the author, and just because it is not external).
+On the other hand, there are not many predefined languages yet.  Defining language syntaxes is about as much 
+work as source-highlight, but in perl.  I plan to package the base module for debian. Perhaps after the author 
+releases the 5 or 6 language definitions he has running on his web site, it might be suitable for inclusion in ikiwiki. [[DavidBremner]]
+
+* [[plugins/highlight]] uses [highlight](http://www.andre-simon.de) via
+  its swig bindings. It optionally supports whole files, but also
+  integrates with the format directive to allow formatting of *any* of
+  highlight's supported formats. (For whole files, it uses either
+  keepextension or noextension, as appropriate for the type of file.)
+
+## General problems / requirements
+
+* Using non-perl syntax highlighting backends is slower. All things equal,
+  I'd prefer either using a perl module, or a multiple-backend solution that
+  can use a perl module as one option. (Or, if there's a great highlighter
+  python module, we could use an external plugin..)
+
+  Of course, some perl modules are also rather slow.. Kate, for example
+  can only process about 33 lines of C code, or 14 lines of
+  debian/changelog per second. That's **30 times slower than markdown**!
+
+  By comparison, source-highlight can do about 5000 lines of C code per
+  second... And launching the program 100 times on an empty file takes about
+  5 seconds, which isn't bad. And, it has a C++ library, which it
+  seems likely perl bindings could be written for, to eliminate 
+  even that overhead.
+  > [highlight](http://www.andre-simon.de) has similar features to source-highlight, and swig bindings
+  > that should make it trivial in principle to call from perl.  I like highlight a bit better because 
+  > it has a pass-through feature that I find very useful.  My memory is unfortunately a bit fuzzy as to how
+  > well the swig bindings work. [[DavidBremner]]
+
+* Engines that already support a wide variety of file types are of
+  course preferred. If the engine doesn't support a particular type
+  of file, it could fall back to doing something simple like
+  adding line numbers. (IkiWiki-Plugin-syntax does this.)
+* XHTML output.
+* Emitting html that uses CSS to control the display is preferred,
+  since it allows for easy user customization. (Engine::Simple does
+  this; Kate can be configured to do it; source-highlight can be 
+  made to do it via the switches `--css /dev/null --no-doc`)
+* Nothing seems to support 
+  [[wiki-formatted_comments|wiki-formatted_comments_with_syntax_plugin]]
+  inside source files. Doing this probably means post-processing the 
+  results of the highlighting engine, to find places where it's highlighted
+  comments, and then running them through the ikiwiki rendering pipeline.
+  This seems fairly doable with [[!cpan Syntax::Highlight::Engine::Kate]],
+  at least.
+* The whole-file plugins tend to have a problem that things that look like
+  wikilinks in the source code get munged into links by ikiwiki, which can
+  have confusing results. Similar problem with preprocessor directives.
+  One approach that's also been requested for eg,
+  [[plugins/contrib/mediawiki]] is to allow controlling which linkification
+  types a page type can have on it.
+
+  > The previous two points seem to be related.  One thought: instead of
+  > getting the source from the `content` parameter, the plugin could
+  > re-load the page source.  That would stop directives/links from
+  > being processed in the source.  As noted above, comments
+  > could then be parsed for directives/links later.
+  >
+  > Would it be worth adding a `nodirectives` option when registering
+  > an htmlize hook that switches off directive and link processing before
+  > generating the html for a page?
+
+* The whole-file plugins all get confused if there is a `foo.c` and a `foo.h`.
+  This is trivially fixable now by passing the keepextension option when
+  registering the htmlize hooks, though. There's also a noextension option
+  that should handle the
+  case of source files with names that do not contain an extension (ie,
+  "Makefile") -- in this case you just register the while filename
+  in the htmlize hook.
+* Whole-file plugins register a bunch of htmlize hooks. The wacky thing
+  about it is that, when creating a new page, you can then pick "c" or
+  "h" or "pl" etc from the dropdown that normally has "Markdown" etc in it.
+  Is this a bug, or a feature? Even if a feature, plugins with many
+  extensions make the dropdown unusable.. 
+
+  Perhaps the thing to do here is to use the new `longname` parameter to
+  the format hook, to give them all names that will group together at or
+  near the end of the list. Ie: "Syntax: perl", "Source code: c", etc.
+
+---
+
+I'm calling this [[done]] since I added the [[plugins/highlight]]
+plugin. There are some unresolved issues touched on here,
+but they either have the own other bug reports, or are documented
+as semi-features in the docs to the plugin. --[[Joey]] 
diff --git a/doc/todo/syntax_highlighting/discussion.mdwn b/doc/todo/syntax_highlighting/discussion.mdwn
new file mode 100644 (file)
index 0000000..27cb708
--- /dev/null
@@ -0,0 +1,28 @@
+sourcehighlight is annoyingly slow, but it does support wiki directives 
+in comments. See [here](http://www.cs.unb.ca/~bremner/teaching/java_examples/snippet/ListMerge/)
+for an example (tags).
+
+> I think that is just a result of it expanding directives, and wikilinks,
+> everywhere in the file, which is generally a possible problem..
+> --[[Joey]]
+
+* * * * *
+
+I think having the option to choose source code page types from the
+dropdown list is definitely a feature.  This gives users an easy way
+to contribute programs (say `.pl` files) or code snippets (like, for
+example, the Elisp area of the EmacsWiki).  Actually, would there any
+other way to create a `.pl` file without write access to the
+repository?  --[[JasonBlevins]]
+
+> Well, you can upload them as an attachment if the wiki is configured to
+> allow it. Having them in the drop down becomes a problem when there are
+> so many wacky extensions in there that you can't find anything.
+> --[[Joey]]
+
+>> I should just note that the
+>> [[sourcecode|todo/automatic_use_of_syntax_plugin_on_source_code_files/discussion]]
+>> plugin only adds the file extensions listed in the config.  This shouldn't cause
+>> massive drop-down menu pollution.  -- [[Will]]
+
+>>> That seems to be the way to go! --[[Joey]] 
diff --git a/doc/todo/table_with_header_column.mdwn b/doc/todo/table_with_header_column.mdwn
new file mode 100644 (file)
index 0000000..e9fad9c
--- /dev/null
@@ -0,0 +1,7 @@
+Tables support a header row or no header, but do not support a header column.
+
+> I have proposed a patch to the table plugin that enable such behaviour: [[table/discussion|plugins/table/discussion]].
+>
+> -- [[AlexandreDupas]]
+
+>> [[applied|done]]
diff --git a/doc/todo/tag_pagespec_function.mdwn b/doc/todo/tag_pagespec_function.mdwn
new file mode 100644 (file)
index 0000000..3604a83
--- /dev/null
@@ -0,0 +1,41 @@
+Implementing tags in terms of links is clever, but it would be nice if it was
+opaque in both directions: tagging and matching tags. Writing pagespecs to
+find out which pages are tagged with a given name means that the pagespec is
+tied to whatever the tagbase is.
+
+This patch adds a pagespec function 'tag' which lets you write pagespecs to
+match tagged pages independent of whatever the tagbase is set to.
+
+ -- [[users/Jon]] 2009/02/17
+
+> So, this looks good, appreciate the patch.
+> 
+> The only problem I see is it could be confusing if `tag(foo)` matched
+> a page that just linked to the tag via a wikilink, w/o actually tagging it.
+
+>> (My [[!taglink wishlist]].) Yes, this is confusing and not nice. I observed this misbehavior, because I wanted to match two different lists of pages (only tagged or linked in any way), but it didn't work. Would this feature require a complex patch? --Ivan Z.
+
+>>> If you link to a page 'foo' which happens to be a tag then the page you link from will turn up in the set of pages returned by tagged(foo). The only way to avoid this would be for the tag plugin to not use wikilinks as an implementation method. That itself would not be too hard to do, but there might be people relying on the older behaviour. A better alternative might be to have a "tag2" plugin (or a better name) which implements tagging entirely separately. -- [[Jon]]
+>>>> I see; at least, your response is encouraging (that it's not hard). I could even find some work that can give similar features: [[structured page data#another_kind_of_links]] -- they envisage a pagespec like `data_link(Depends on,bugs/bugA)`, thus a "separation of dependencies between bugs from arbitrary links".
+
+>>>> Indeed, having many relations that can be used in the formulas defining classes of objects (like pagespecs here) is a commonly imagined thing, so this would be a nice feature. (I'll be trying out the patches there first, probably.) In general, extending the language of pagespecs to something more powerful (like [[!wikipedia description logics]]) seems to be a nice possible feature. I saw more discussions of ideas [[!taglink about_the_extension_of_the_pagespec_language_in_the_direction_similar_to_description_logics|pagespec_in_DL_style]] somewhere else here. --Ivan Z.
+
+> One other thing, perhaps it should be called `tagged()`? --[[Joey]] 
+
+[[!tag patch done]]
+
+    --- a/plugins/IkiWiki/Plugin/tag.pm        2009-02-16 11:30:11.000000000 +0000
+    +++ b/plugins/IkiWiki/Plugin/tag.pm        2009-02-17 15:40:03.000000000 +0000
+    @@ -125,4 +125,12 @@
+       }
+     }
+     
+    +package IkiWiki::PageSpec;
+    +
+    +sub match_tag ($$;@) {
+    +  my $page = shift;
+    +  my $glob = shift;
+    +    return match_link($page, IkiWiki::Plugin::tag::tagpage($glob));
+    +}
+    +
+     1
index 044ba2e8af8d02da363215e9622a23f0248698d7..80240ec5ac5a89d2f9042f88ec4b386df772fbb3 100644 (file)
@@ -1,7 +1,7 @@
 Feature idea: I'd like to be able to tag pages in an ikiwiki blog with a
 publication date, and have the option of building a blog that excludes
 publication dates in the future.  (meta pubdate= ?)
+
 I'm using ikiwiki on git for a "tip of the day" RSS feed, and I'd like to
 be able to queue up a bunch of items instead of literally putting in one
 tip per day.  In the future I think this will come in handy for other
@@ -12,6 +12,29 @@ on vacation".
 > is a wiki compiler, if something causes content to change based on the
 > date, then the wiki needs to be rebuilt periodically. So you'd need a
 > cron job or something.
-> 
-> Implemeting this feature probably needs 
-> [[todo/plugin_dependency_calulation]] to be implemented. --[[Joey]]
+>
+> Thinking about this some more, if you're going to have a cron job, you
+> could just set up a branch containing the future post. The branch could
+> have a name like 20080911. Then have the cron job git merge the day's
+> branch, if any, into master each day. And voila, post is completly hidden
+> until published. You'd want to avoid merge conflicts in your cron job ..
+> but they'd be unlikely if you limited yourself to just adding new
+> pages. Alternatively, for larger organisations wishing to deploy more
+> sweeping changes on a given date, replace cron job with intern.. ;-)
+> --[[Joey]]
+
+> > Good approach if you have one day on which a big change goes through, but
+> > often the reason for tagging with a publication date is so that you can
+> > dribble out articles one per day when you're gone for a week.  Branches are easy
+> > in git, but it would still be an extra step to switch branches every time
+> > you edit a different day's article.
+> >
+> > And just to make it a little harder, some sites might want an internal 
+> > copy of the wiki that _does_ build the future pages, just tags them with the publication
+> > date, for previewing.
+> > 
+> > One more reason to have publication date: if you move a page from your old CMS to ikiwiki
+> > and want to have it show up in the right order in RSS feeds.
+> >
+> > I no longer have the original wiki for which I wanted this feature, but I can
+> > see using it on future ones. -- [[DonMarti]]
index 682acfa1f6d07a2759c859216e747ad919c5a379..ee9151116d564e77ce0c0d726617d2a2a2e97304 100644 (file)
@@ -1,4 +1,4 @@
-Stuff still needing to be done with tags:
+Stuff still needing to be done with [[/tags]]:
 
 * It's unfortunate that the rss category (tag) support doesn't include
   a domain="" attribute in the category elements. That would let readers
diff --git a/doc/todo/target_filter_for_brokenlinks.mdwn b/doc/todo/target_filter_for_brokenlinks.mdwn
new file mode 100644 (file)
index 0000000..137277c
--- /dev/null
@@ -0,0 +1,9 @@
+[[!tag wishlist]]
+
+Currently, [[plugins/brokenlinks]] supports filtering by the place where a broken wikilink is used.
+
+Filtering by the target of the broken link would also be useful, e.g.,
+
+    \[[!brokenlinks matching="tagbase/*"]]
+
+would list the tags not yet "filled out". --Ivan Z.
index 6820be5cc3964fa01736f3989af1e20a290221b0..bfc130d69d79e793b1bdd31c51118f26d9160dc1 100644 (file)
@@ -10,6 +10,6 @@
        +       debug("ctime for '$file': ". localtime($ctime));
         
                return $ctime;
-        } #}}}
+        }
 
-[[tag patch done]]
+[[!tag patch done]]
index f78d08b44831170eabdfb1086f6a16750a3d758c..b6b082cfe75b073b861f25159c8e9663ce0aa9a2 100644 (file)
@@ -1,4 +1,7 @@
 * Need to get post commit hook code working.
 * Need some example urls for web based diffs.
+* `rcs_commit_staged`, `rcs_rename`, `rcs_remove`, are not
+  implemented for tla, and so attachments, remove and rename plugins
+  cannot be used with it. (These should be fairly easy to add..)
 
-[[tag rcs/tla]]
+[[!tag rcs/tla]]
index 33d161ee196581c1209cb324c2c81ae99b83a978..2fe819682253efb6632f0d4204663f5bea6b0394 100644 (file)
@@ -1,6 +1,29 @@
 A simple plugin to allow per-page customization of a template by passing paramaters to HTML::Template. For those times when a whole pagetemplate is too much work. --Ethan
 
-[[tags patch]]
+[[!tag patch]]
+
+> The implementation looks fine to me (assuming it works with current ikiwiki),
+> apart from the "XXX" already noted in the patch. The design could reasonably
+> be considered premature generalization, though - how often do you actually
+> need to define new tmplvars?
+>
+> As for the page/destpage/preview thing, it would be good if the preprocess
+> hook could distinguish between software-supplied and user-supplied
+> parameters (the [[plugins/tag]] plugin could benefit from this too). Perhaps
+> the IkiWiki core could be modified so that
+> `hook(type => "preprocess", splitparams => 1, ...)` would invoke preprocess
+> with { page => "foo", destpage => "bar", ... } as a special first argument,
+> and the user-supplied parameters as subsequent arguments? Then plugins like
+> tag could use:
+>
+>     my $ikiparams = shift;
+>     my %params = @_;
+>
+>     add_tags($ikiparams->{page}, keys %params);
+>
+> --[[smcv]]
+
+----
 
     #!/usr/bin/perl
     package IkiWiki::Plugin::tmplvars;
@@ -11,12 +34,12 @@ A simple plugin to allow per-page customization of a template by passing paramat
 
     my %tmplvars;
 
-    sub import { #{{{
+    sub import {
            hook(type => "preprocess", id => "tmplvars", call => \&preprocess);
            hook(type => "pagetemplate", id => "tmplvars", call => \&pagetemplate);
-    } # }}}
+    }
 
-    sub preprocess (@) { #{{{
+    sub preprocess (@) {
            my %params=@_;
 
            if ($params{page} eq $params{destpage}) {
@@ -34,9 +57,9 @@ A simple plugin to allow per-page customization of a template by passing paramat
                    }
            }
     
-    } # }}}
+    }
     
-    sub pagetemplate (@) { #{{{
+    sub pagetemplate (@) {
             my %params=@_;
             my $template = $params{template};
 
@@ -47,6 +70,6 @@ A simple plugin to allow per-page customization of a template by passing paramat
             }
 
             return undef;
-    } # }}}
+    }
 
     1
diff --git a/doc/todo/tmplvars_plugin/discussion.mdwn b/doc/todo/tmplvars_plugin/discussion.mdwn
new file mode 100644 (file)
index 0000000..93cb9b4
--- /dev/null
@@ -0,0 +1 @@
+I find this plugin quite usefull. But one thing, I would like to be able to do is set a tmplvar e.g. in a sidebar so that it affects all Pages this sidebar is used in. --martin
diff --git a/doc/todo/toc_plugin:_set_a_header_ceiling___40__opposite_of_levels__61____41__.mdwn b/doc/todo/toc_plugin:_set_a_header_ceiling___40__opposite_of_levels__61____41__.mdwn
new file mode 100644 (file)
index 0000000..547c7a8
--- /dev/null
@@ -0,0 +1,3 @@
+It would be nice if the [[plugins/toc]] plugin let you specify a header level "ceiling" above which (or above and including which) the headers would not be incorporated into the toc.
+
+Currently, the levels=X parameter lets you tweak how deep it will go for small headers, but I'd like to chop off the h1's (as I use them for my page title) -- [[Jon]]
index 35290fc38bc556d4753355218df2721151f98958..4891a1197194d78acb3a2739515014d2469a8f88 100644 (file)
@@ -1,6 +1,6 @@
 It would be great if I could to this:
 
-     \[[toc levels=3 skip=1]]
+     \[[!toc levels=3 skip=1]]
 
 I use h1 for big title on each page, and don't want it in my toc on that page.
 
@@ -10,7 +10,7 @@ That way I could have toc for h2 and h3 and h1 is skipped bacause it is big titl
 > another option is added, I wonder why you're using a h1 for a title on
 > each page when the page name already appears at the top of each page. And
 > if the page name isn't right for the title, you can use 
-> \[[meta title="foo"]] to override it. And this purposefully doesn't show
+> \[[!meta title="foo"]] to override it. And this purposefully doesn't show
 > up in the toc. --[[Joey]]
 
 >> aaaahhh, I made a mistake. U used some other page.tmpl and title was hidden,
index cbbf7e6fdff77be6c2c51784ca08d5bd0ae4303c..dbad39c7527b25aa9781d001c19b0e8a6a0676c3 100644 (file)
@@ -1,6 +1,6 @@
 It would be nice if one could set the initial state of the toggleable area.
---[[[rdennis]]
+--[[rdennis]]
 
-[[tag plugins/toggle]]
+[[!tag plugins/toggle]]
 
 [[done]]
diff --git a/doc/todo/tracking_bugs_with_dependencies.mdwn b/doc/todo/tracking_bugs_with_dependencies.mdwn
new file mode 100644 (file)
index 0000000..bfdbf08
--- /dev/null
@@ -0,0 +1,756 @@
+[[!tag patch patch/core]]
+
+I like the idea of [[tips/integrated_issue_tracking_with_ikiwiki]], and I do so on several wikis.  However, as far as I can tell, ikiwiki has no functionality which can represent dependencies between bugs and allow pagespecs to select based on dependencies.  For instance, I can't write a pagespec which selects all bugs with no dependencies on bugs not marked as done.  --[[JoshTriplett]]
+
+> I started having a think about this.  I'm going to start with the idea that expanding
+> the pagespec syntax is the way to attack this.  It seems that any pagespec that is going
+> to represent "all bugs with no dependencies on bugs not marked as done" is going to
+> need some way to represent "bugs not marked as done" as a collection of pages, and
+> then represent "bugs which do not link to pages in the previous collection".
+>
+> One way to do this would be to introduce variables into the pagespec, along with
+> universal and/or existential [[!wikipedia Quantification]].  That looks quite complex.
+>
+>> I thought about this briefly, and got about that far.. glad you got
+>> further. :-) --[[Joey]]
+
+>> Or, one [[!taglink could_also_refer|pagespec_in_DL_style]] to the language of [[!wikipedia description logics]]: their formulas actually define classes of objects through quantified relations to other classes. --Ivan Z.
+> 
+> Another option would be go with a more functional syntax.  The concept here would
+> be to allow a pagespec to appear in a 'pagespec function' anywhere a page can.  e.g.
+> I could pass a pagespec to `link()` and that would return true if there is a link to any
+> page matching the pagespec.  This makes the variables and existential quantification
+> implicit.  It would allow the example requested above:
+>
+>> `bugs/* and !*/Discussion and !link(bugs/* and !*/Discussion and !link(done))`
+>
+> Unfortunately, this is also going to make the pagespec parsing more complex because
+> we now need to parse nested sets of parentheses to know when the nested pagespec
+> ends, and that isn't a regular language (we can't use regular expression matching for
+> easy parsing).
+>
+>> Also, it may cause ambiguities with page names that contain parens
+>> (though some such ambigutities already exist with the pagespec syntax).
+>
+> One simplification of that would be to introduce some pagespec [[shortcuts]].  We could
+> then allow pagespec functions to take either pages, or named pagespec shortcuts.  The
+> pagespec shortcuts would just be listed on a special page, like current [[shortcuts]].
+> (It would probably be a good idea to require that shortcuts on that page can only refer
+> to named pagespecs higher up that page than themselves.  That would stop some
+> looping issues...)  These shortcuts would be used as follows: when trying to match
+> a page (without globs) you look to see if the page exists.  If it does then you have a
+> match.  If it doesn't, then you look to see if a similarly named pagespec shortcut
+> exists.  If it does, then you check that pagespec recursively to see if you have a match.
+> The ordering requirement on named pagespecs stops infinite recursion.
+>
+> Does that seem like a reasonable first approach?
+>
+> -- [[Will]]
+
+>> Having a separate page for the shortcuts feels unwieldly.. perhaps
+>> instead the shortcut could be defined earlier in the scope of the same
+>> pagespec that uses it?
+>> 
+>> Example: `define(~bugs, bugs/* and !*/Discussion) and define(~openbugs, ~bugs and !link(done)) and ~openbugs and !link(~openbugs)`
+
+>>> That could work.  parens are only ever nested 1 deep in that grammar so it is regular and the current parsing would be ok.
+
+>> Note that I made the "~" explicit, not implicit, so it could be left out. In the case of ambiguity between
+>> a definition and a page name, the definition would win.
+
+>>> That was my initial thought too :), but when implementing it I decided that requiring the ~ made things easier.  I'll probably require the ~ for the first pass at least.
+
+>> So, equivilant example: `define(bugs, bugs/* and !*/Discussion) and define(openbugs, bugs and !link(done)) and openbugs and !link(openbugs)`
+>> 
+
+>> Re recursion, it is avoided.. but building a pagespec that is O(N^X) where N is the
+>> number of pages in the wiki is not avoided. Probably need to add DOS prevention.
+>>  --[[Joey]]
+
+>>> If you memoize the outcomes of the named pagespecs you can make in O(N.X), no?
+>>> -- [[Will]]
+
+>>>> Yeah, guess that'd work. :-)
+
+> <a id="another_kind_of_links" />One quick further thought.  All the above discussion assumes that 'dependency' is the
+> same as 'links to', which is not really true.  For example, you'd like to be able to say
+> "This bug does not depend upon [ [ link to other bug ] ]" and not have a dependency.
+> Without having different types of links, I don't see how this would be possible.
+>
+> -- [[Will]]
+
+>> I saw that this issue is targeted at by the work on [[structured page data#another_kind_of_links]]. --Ivan Z.
+
+Okie - I've had a quick attempt at this.  Initial patch attached.  This one doesn't quite work.
+And there is still a lot of debugging stuff in there.
+
+At the moment I've added a new preprocessor plugin, `definepagespec`, which is like
+shortcut for pagespecs.  To reference a named pagespec, use `~` like this:
+
+    [ [!definepagespec name="bugs" spec="bugs/* and !*/Discussion"]]
+    [ [!definepagespec name="openbugs" spec="~bugs and !link(done)"]]
+    [ [!definepagespec name="readybugs" spec="~openbugs and !link(~openbugs)"]]
+
+At the moment the problem is in `match_link()` when we're trying to find a sub-page that
+matches the appropriate page spec.  There is no good list of pages available to iterate over.
+
+    foreach my $nextpage (keys %IkiWiki::pagesources)
+
+does not give me a good list of pages.  I found the same thing when I was working on
+this todo [[todo/Add_a_plugin_to_list_available_pre-processor_commands]].
+
+> I'm not sure why iterating over `%pagesources` wouldn't work here, it's the same method
+> used by anything that needs to match a pagespec against all pages..? --[[Joey]]
+
+>> My uchecked hypothesis is that %pagesources is created after the refresh hook.
+>> I've also been concerned about how globally defined pagespec shortcuts would interact with
+>> the page dependancy system.  Your idea of internally defined shortcuts should fix that. -- [[Will]]
+
+>>> You're correct, the refresh hook is run very early, before pagesources
+>>> is populated. (It will be partially populated on a refresh, but will
+>>> not be updated to reflect new pages.) Agree that internally defined
+>>> seems the way to go. --[[Joey]]
+
+Immediately below is a patch which seems to basically work.  Lots of debugging code is still there
+and it needs a cleanup, but I thought it worth posting at this point.  (I was having problems
+with old style glob lists, so i just switched them off for the moment.)
+
+The following three inlines work for me with this patch:
+
+    Bugs:
+    
+    [ [!inline pages="define(~bugs, bugs/* and ! */Discussion) and ~bugs" archive="yes"]]
+    
+    OpenBugs:
+    
+    [ [!inline pages="define(~bugs, bugs/* and ! */Discussion) and define(~openbugs,~bugs and !link(done)) and ~openbugs" archive="yes"]]
+    
+    ReadyBugs:
+    
+    [ [!inline pages="define(~bugs, bugs/* and ! */Discussion) and define(~openbugs,~bugs and !link(done)) and define(~readybugs,~openbugs and !link(~openbugs)) and ~readybugs" archive="yes"]]
+
+> Nice! Could the specfuncsref be passed in %params? I'd like to avoid
+> needing to change the prototype of every pagespec function, since several
+> plugins define them too. --[[Joey]]
+
+>> Maybe - it needs more thought.  I also considered it when I was going though changing all those plugins :).
+>> My concern was that `%params` can contain other user-defined parameters,
+>> e.g. `link(target, otherparameter)`, and that means that the specFuncs could be clobbered by a user (or other
+>> weird security hole).  I thought it better to separate it, but I didn't think about it too hard.  I might move it to
+>> the first parameter rather than the second.  Ikiwiki is my first real perl hacking and I'm still discovering
+>> good ways to write things in perl.
+>>
+>>>> `%params` contains the parameters passed to `pagespec_match`, not
+>>>> user-supplied parameters. The user-supplied parameter to a function
+>>>> like `match_glob()` or `match_link()` is passed in the second positional parameter. --[[Joey]]
+
+>>>>> OK.  That seems reasonable then.  The only problem is that my PERLfu is not strong enough to make it
+>>>>> work.  I really have to wonder what substance was influencing the designers of PERL...
+>>>>> I can't figure out how to use the %params.  And I'm pissed off enough with PERL that I'm not going
+>>>>> to try and figure it out any more.  There are two patches below now.  The first one uses an extra
+>>>>> argument and works.  The second one tries to use %params and doesn't - take your pick :-). -- [[Will]]
+
+>> What do you think is best to do about `is_globlist()`?  At the moment it requires that the 'second word', as
+>> delimited by a space and ignoring parens, is 'and' or 'or'.  This doesn't hold in the above example pagespecs (so I just hard wired it to 0 to test my patch).
+>> My thought was just to search for 'and' or 'or' as words anywhere in the pagespec.  Thoughts?
+
+>>> Dunno, we could just finish deprecating it. Or change the regexp to
+>>> skip over spaces in parens. (`/[^\s]+\s+([^)]+)/`) --[[Joey]]
+
+>>>> I think I have a working regexp now.
+
+>> Oh, one more thing.  In pagespec_translate (now pagespec_makeperl), there is a part of the regular expression for `# any other text`.
+>> This contained `()`, which has no effect.  I replaced that with `\(\)`, but that is a change in the definition of pagespecs unrelated to the
+>> rest of this patch. In a related change, commands were not able to contain `)` in their parameters.  I've extended that so the cannot
+>> contain `(` or `)`.  -- [[Will]]
+
+>>> `[^\s()]+` is a character class matching all characters not spaces or
+>>> parens. Since the pervious terminals in the regexp consume most
+>>> occurances of an open paren or close paren, it's unlikely for one to
+>>> get through to that part of the regexp. For example, "foo()" will be
+>>> matched by the command matcher; "(foo)" will be matched by the open
+>>> paren literal terminal. "foo(" and "foo)" can get through to the
+>>> end, and would be matched as a page name, if it didn't exclude parens.
+>>>
+>>> So why exclude them? Well, consider "foo and(bar and baz)". We don't
+>>> want it to match "and(" as a page name!
+>>> 
+>>> Escaping the parens in the character class actually changes nothing; the
+>>> changed character class still matches all characters not spaces or
+>>> parens. (Try it!).
+>>> 
+>>> Re commands containing '(', I don't really see any reason not to
+>>> allow that, unless it breaks something. --[[Joey]]
+
+>>>> Oh, I didn't realise you didn't need to escape parens inside [].  All else I
+>>>> I understood.  I have stopped commands from containing parens because
+>>>> once you allow that then you might have a extra level of depth in the parsing
+>>>> of define() statements. -- [[Will]]
+
+>>> Updated patch.  Moved the specFuncsRef to the front of the arg list.  Still haven't thought through the security implications of
+>>> having it in `%params`.  I've also removed all the debugging `print` statements.  And I've updated the `is_globlist()` function.
+>>> I think this is ready for people other than me to have a play.  It is not well enough tested to commit just yet.
+>>> -- [[Will]]
+
+I've lost track of the indent level, so I'm going back to not indented - I think this is a working [[patch]] taking into
+account all comments above (which doesn't mean it is above reproach :) ).  --[[Will]]
+
+> Very belated code review of last version of the patch:
+> 
+> * `is_globlist` is no longer needed
+
+>> Good :)
+
+> * I don't understand why the pagespec match regexp is changed
+>   from having flags `igx` to `ixgs`. Don't see why you
+>   want `.` to match '\n` in it, and don't see any `.` in the regexp 
+>   anyway?
+
+>> Because you have to define all the named pagespecs in the pagespec, you sometimes end up with very long pagespecs.  I found it useful to split them over multiple lines.  That didn't work at one point and I added the 's' to make it work.  I may have further altered the regex since then to make the 's' redundant.  Remove it and see if multi-line pagespecs still work. :)
+
+>>> Well, I can tell you that multi-line pagespecs are supported w/o
+>>> your patch .. I use them all the time. The reason I find your
+>>> use of `/s` unlikely is because without it `\s` already matches
+>>> a newline. Only if you want to treat a newline as non-whitespace
+>>> is `/s` typically necessary. --[[Joey]] 
+
+> * Some changes of `@_` to `%params` in `pagespec_makeperl` do not
+>   make sense to me. I don't see where \%params is defined and populated,
+>   except with `\$params{specFunc}`.
+
+>> I'm not a perl hacker.  This was a mighty battle for me to get going.
+>> There is probably some battlefield carnage from my early struggles
+>> learning perl left here. Part of this is that @_ / @params already
+>> existed as a way of passing in extra parameters.  I didn't want to
+>> pollute that top level namespace - just at my own parameter (a hash)
+>> which contained the data I needed.
+
+>>> I think I understand how the various `%params`
+>>> (there's not just one) work in your code now, but it's really a mess.
+>>> Explaining it in words would take pages.. It could be fixed by,
+>>> in `pagespec_makeperl` something like:
+>>> 
+>>>    my %specFuncs;
+>>>    push @_, specFuncs => \%specFuncs;
+>>> 
+>>> With that you have the hash locally available for populating
+>>> inside `pagespec_makeperl`, and when the `match_*` functions
+>>> are called the same hash data will be available inside their
+>>> `@_` or `%params`. No need to change how the functions are called
+>>> or do any of the other hacks.
+>>>
+>>> Currently, specFuncs is populated by building up code
+>>> that recursively calls `pagespec_makeperl`, and is then
+>>> evaluated when the pagespec gets evaluated. My suggested
+>>> change to `%params` will break that, but that had to change 
+>>> anyway.
+>>>
+>>> It probably has a security hole, and is certianly inviting
+>>> one, since the pagespec definition is matched by a loose regexp (`.*`)
+>>> and then subject to string interpolation before being evaluated
+>>> inside perl code. I recently changed ikiwiki to never interpolate
+>>> user-supplied strings when translating pagespecs, and that
+>>> needs to happen here too. The obvious way, it seems to me,
+>>> is to not generate perl code, but just directly run perl code that
+>>> populates specFuncs.
+
+>>>> I don't think this is as bad as you make out, but your addition of the
+>>>> data array will break with the recursion my patch adds in pagespec_makeperl.
+>>>> To fix that I'll need to pass a reference to that array into pagespec_makeperl.
+>>>> I think I can then do the same thing to $params{specFuncs}.  -- [[Will]]
+
+>>>>> You're right -- I did not think the recursive case through.
+>>>>> --[[Joey]] 
+
+> * Seems that the only reason `match_glob` has to check for `~` is
+>   because when a named spec appears in a pagespec, it is translated
+>   to `match_glob("~foo")`. If, instead, `pagespec_makeperl` checked
+>   for named specs, it could convert them into `check_named_spec("foo")`
+>   and avoid that ugliness.
+
+>> Yeah - I wanted to make named specs syntactically different on my first pass.  You are right in that this could be made a fallback - named specs always override pagenames.
+
+> * The changes to `match_link` seem either unecessary, or incomplete.
+>   Shouldn't it check for named specs and call
+>   `check_named_spec_existential`?
+
+>>  An earlier version did.  Then I realised it wasn't actually needed in that case - match_link() already included a loop that was like a type of existential matching.  Each time through the loop it would
+>> call match_glob().  match_glob() in turn will handle the named spec.  I tested this version briefly and it seemed to work.  I remember looking at this again later and wondering if I had mis-understood
+>> some of the logic in match_link(), which might mean there are cases where you would need an explicit call to check_named_spec_existential() - I never checked it properly after having that thought.
+
+>>> In the common case, `match_link` does not call `match_glob`,
+>>> because the link target it is being asked to check for is a single
+>>> page name, not a glob.
+
+>>>> A named pagespec should fall into the glob case.  These two pagespecs should be the same:
+
+    link(a*)
+
+>>>> and
+
+    define(aStar, a*) and link(~aStar)
+
+>>>> In the first case, we want the pagespec to match any page that links to a page matching the glob.
+>>>> In the second case, we want the pagespec to match any page that links to a page matching the named spec.
+>>>> match_link() was already doing existential part.  The patches to this code were simply to remove the `lc()`
+>>>> call from the named pagespec name.  Can that `lc` be removed entirely? -- [[Will]]
+
+>>>>> I think we could get rid of it. `bestlink` will lc it itself
+>>>>> if the uppercase version does not exist; `match_glob` matches
+>>>>> insensitively.
+>>>>> --[[Joey]] 
+
+> * Generally, the need to modify `match_*` functions so that they
+>   check for and handle named pagespecs seems suboptimal, if
+>   only because there might be others people may want to use named
+>   pagespecs with. It would be possible to move this check
+>   to `pagespec_makeperl`, by having it check if the parameter
+>   passed to a pagespec function looked like a named pagespec.
+>   The only issue is that some pagespec functions take a parameter
+>   that is not a page name at all, and it could be weird
+>   if such a parameter were accidentially interpreted as a named
+>   pagespec. (But, that seems unlikely to happen.)
+
+>> Possibly.  I'm not sure which I prefer between the current solution and that one.  Each have advantages and disadvantages.
+>> It really isn't much code for the match functions to add a call to check_named_spec_existential().
+
+>>> But if a plugin adds its own match function, it has
+>>> to explicitly call that code to support named pagespecs.
+
+>>>> Yes, and it can do that in just three lines of code.  But if we automatically check for named pagespecs all the time we
+>>>> potentially break any matching function that doesn't accept pages, or wants to use multiple arguments.
+
+>>>>> 3 lines of code, plus the functions called become part of the API,
+>>>>> don't forget about that..
+>>>>>
+>>>>> Yes, I think that is the tradeoff, the question is whether to export
+>>>>> the additional complexity needed for that flexability.
+>>>>>
+>>>>> I'd be suprised if multiple argument pagespecs become necessary..
+>>>>> with the exception of this patch there has been no need for them yet.
+>>>>>
+>>>>> There are lots of pagespecs that take data other than pages,
+>>>>> indeed, that's really the common case. So far, none of them 
+>>>>> seem likely to take data that starts with a `~`. Perhaps
+>>>>> the thing to do would be to check if `~foo` is a known,
+>>>>> named pagespec, and if not, just pass it through unchanged.
+>>>>> Then there's little room for ambiguity, and this also allows
+>>>>> pagespecs like `glob(~foo*)` to match the literal page `~foo`.
+>>>>> (It will make pagespec_merge even harder tho.. see below.)
+>>>>> --[[Joey]] 
+
+>>>>>> I've already used multi-argument pagespec match functions in
+>>>>>> my data plugin.  It is used for having different types of links.  If
+>>>>>> you want to have multiple types of links, then the match function
+>>>>>> for them needs to take both the link name and the link type.
+>>>>>> I'm trying to think of a way we could have both - automatically
+>>>>>> handle the existential case unless the function indicates somehow
+>>>>>> that it'll do it itself.  Any ideas?  -- [[Will]]
+
+> * I need to check if your trick to avoid infinite recursion
+>   works if there are two named specs that recursively
+>   call one-another. I suspect it does, but will test this
+>   myself..
+
+>> It worked for me. :)
+
+> * I also need to verify if memoizing the named pagespecs has
+>   really guarded against very expensive pagespecs DOSing the wiki..
+
+> --[[Joey]] 
+
+>>  There is one issue that I've been thinking about that I haven't raised anywhere (or checked myself), and that is how this all interacts with page dependencies.
+>>  Firstly, I'm not sure anymore that the `pagespec_merge` function will continue to work in all cases.
+
+>>> The problem I can see there is that if two pagespecs
+>>> get merged and both use `~foo` but define it differently,
+>>> then the second definition might be used at a point when
+>>> it shouldn't (but I haven't verified that really happens).
+>>> That could certianly be a show-stopper. --[[Joey]] 
+
+>>>> I think this can happen in the new closure based code.  I don't think this could happen in the old code.  -- [[Will]]
+
+>>>> Even if that works, this is a good argument for having a syntactic difference between named pagespecs and normal pages.
+>>>> If you're joining two pagespecs with 'or', you don't want a named pagespec in the first part overriding a page name in the
+>>>> second part.  Oh, and I assume 'or' has the right operator precedence that "a and b or c" is "(a and b) or c", and not "a and (b or c)" -- [[Will]]
+
+>>>>> Looks like its bracketed in the code anyway... -- [[Will]]
+
+>>>> Perhaps the thing to do is to have a `clear_defines()`
+>>>> function, then merging `A` and `B` yields `(A) or (clear_defines() and (B))`
+>>>> That would deal with both the cases where `A` and `B` differently
+>>>> define `~foo` as well as with the case where `A` defines `~foo` while
+>>>> `B` uses it to refer to a literal page.
+>>>> --[[Joey]]
+
+>>>>> I don't think this will work with the new patch, and I don't think it was needed with the old one.
+>>>>> Under the old patch, pagespec_makeperl() generated a string of unevaluated, self-contained, perl
+>>>>> code.  When a new named pagespec was defined, a recursive call was made to get the perl code
+>>>>> for the pagespec, and then that code was used to add something like `$params{specFuncs}->{name} = sub {recursive code} and `
+>>>>> to the result of the calling function.  This means that at pagespec testing time, when this code is executed, the
+>>>>> specFuncs hash is built up as the pagespec is checked.  In the case of the 'or' used above, later redefinitions of
+>>>>> a named pagespec would have redefined the specFunc at the right time.  It should have just worked.  However...
+
+>>>>> Since my original patch, you started using closures for security reasons (and I can see the case for that).  Unfortunately this
+>>>>> means that the generated perl code is no longer self-contained - it needs to be evaluated in the same closure it was generated
+>>>>> so that it has access to the data array.  To make this work with the recursive call I had two options: a) make the data array a
+>>>>> reference that I pass around through the pagespec_makeperl() functions and have available when the code is finally evaluated
+>>>>> in pagespec_translate(), or b) make sure that each pagespec is evaluated in its correct closure and a perl function is returned, not a
+>>>>> string containing unevaluated perl code.
+
+>>>>> I went with option b).  I did it in such a way that the hash of specfuncs is built up at translation time, not at execution time.  This
+>>>>> means that with the new code you can call specfuncs that get defined out of order:
+
+    ~test and define(~test, blah)
+
+>>>>> but it also means that using a simple 'or' to join two pagespecs wont work.  If you do something like this:
+
+    ~test and define(~test, foo) and define(~test, baz)
+
+>>>>> then the last definition (baz) takes precedence.
+>>>>> In the process of writing this I think I've come up with a way to change this back the way it was, still using closures. -- [[Will]]
+
+>>> My [[remove-pagespec-merge|should_optimise_pagespecs]] branch has now
+>>> solved all this by deleting the offending function :-) --[[smcv]]
+
+>>  Secondly, it seems that there are two types of dependency, and ikiwiki
+>>  currently only handles one of them.  The first type is "Rebuild this
+>>  page when any of these other pages changes" - ikiwiki handles this.
+>>  The second type is "rebuild this page when set of pages referred to by
+>>  this pagespec changes" - ikiwiki doesn't seem to handle this.  I
+>>  suspect that named pagespecs would make that second type of dependency
+>>  more important.  I'll try to come up with a good example. -- [[Will]]
+
+>>> Hrm, I was going to build an example of this with backlinks, but it
+>>> looks like that is handled as a special case at the moment (line 458 of
+>>> render.pm).  I'll see if I can breapk
+>>> things another way.  Fixing this properly would allow removal of that special case. -- [[Will]]
+
+>>>> I can't quite understand the distinction you're trying to draw
+>>>> between the two types of dependencies. Backlinks are a very special
+>>>> case though and I'll be suprised if they fit well into pagespecs.
+>>>> --[[Joey]] 
+
+>>>>> The issue is that the existential pagespec matching allows you to build things that have similar
+>>>>> problems to backlinks.
+>>>>> e.g. the following inline:
+
+    \[[!inline pages="define(~done, link(done)) and link(~done)" archive=yes]]
+
+>>>>> includes any page that links to a page that links to done.  Now imagine I add a new link to 'done' on
+>>>>> some random page somewhere - a page which some other page links to which didn't previously get included - the set of pages accepted by the pagespec, and hence the set of
+>>>>> pages inlined, will change.  But, there is no dependency anywhere on the page that I altered, so
+>>>>> ikiwiki will not rebuild the page with the inline in it.  What is happening is that the page that I altered affects
+>>>>> the set of pages matched by the pagespec without itself being matched by the pagespec, and hence included in the dependency list.
+
+>>>>> To make this work well, I think you need to recognise two types of dependencies for each page (and no
+>>>>> special cases for particular types of links, eg backlinks).  The first type of dependency says, "The content of
+>>>>> this page depends upon the content of these other pages".  The `add_depends()` in the shortcuts
+>>>>> plugin is of this form: any time the shortcuts page is edited, any page with a shortcut on it
+>>>>> is rebuilt.  The inline plugin also needs to add dependencies of this form to detect when the inlined
+>>>>> content changes.  By contrast, the map plugin does not need a dependency of this form, because it
+>>>>> doesn't actually care about the content of any pages, just which pages it needs to include (which we'll handle next).
+
+>>>>> The second type of dependency says, "The content of this page depends upon the exact set of pages matched
+>>>>> by this pagespec".  The first type of dependency was about the content of some pages, the second type is about
+>>>>> which pages get matched by a pagespec.  This is the type of dependency tracking that the map plugin needs.
+>>>>> If the set of pages matched by map pagespec changes, then the page with the map on it needs to be rebuilt to show a different list of pages.
+>>>>> Inline needs this type of dependency as well as the previous type - This type handles a change in which pages
+>>>>> are inlined, the previous type handles a change in the content of any of those pages.  Shortcut does not need this type of
+>>>>> dependency.  Most of the places that use `add_depends()` seem to need this type of dependency rather than the first type.
+
+>>>>>> Note that inline and map currently achieve the second type of dependency by
+>>>>>> explicitly calling `add_depends` for each page the displayed.
+>>>>>> If any of those pages are removed, the regular pagespec would not
+>>>>>> match them -- since they're gone. However, the explicit dependency
+>>>>>> on them does cause them to match. It's an ugly corner I'd like to
+>>>>>> get rid of. --[[Joey]]
+
+>>>>> Implementation Details:  The first type of dependency can be handled very similarly to the current
+>>>>> dependency system.  You just need to keep a list of pages that the content depends upon.  You could
+>>>>> keep that list as a pagespec, but if you do this you might want to check that the pagespec doesn't change,
+>>>>> possibly by adding a dependency of the second type along with the dependency of the first type.
+
+>>>>>> An example of the current system not tracking enough data is 
+>>>>>> where A inlines B which inlines C. A change to C will cause B to
+>>>>>> rebuild, but A will not "notice" that B has implicitly changed.
+>>>>>> That example suggests it might be fixable without explicitly storing
+>>>>>> data, by causing a rebuild of B to be treated as a change to B.
+>>>>>> --[[Joey]] 
+
+>>>>> The second type of dependency is a little more tricky.  For each page, we'd need a list of pagespecs that
+>>>>> the page depended on, and for each pagespec you'd want to store the list of pages that currently match it.
+>>>>> On refresh, you'd need to check each pagespec to see if the set of pages that match it has changed, and if
+>>>>> that set has changed, then rebuild the dependent page(s).  Oh, and for this second type of dependency, I
+>>>>> don't think you can merge pagespecs.  If I wanted to know if either "\*" or "link(done)" changes, then just checking
+>>>>> to see if the set of pages matched by "\* or link(done)" changes doesn't work.
+
+>>>>> The current system works because even though you usually want dependencies of the second type, the set of pages
+>>>>> referred to by a pagespec can only change if one of those pages itself changes.  i.e. A dependency check of the
+>>>>> first type will catch a dependency change of the second type with current pagespecs.
+>>>>> This doesn't work with backlinks, and it doesn't work with existential matching.  Backlinks are currently special-cased.  I don't know
+>>>>> how to special-case existential matching - I suspect you're better off just getting the dependency tracking right.
+
+>>>>> I also tried to come up with other possible solutions: e.g. can we find the dependencies for a pagespec?  That
+>>>>> would be the set of pages where a change on one of those pages could lead to a change in the set of pages matched by the pagespec.
+>>>>> For old-style pagespecs without backlinks, the dependency set for a pagespec is the same as the set of pages the pagespec matches.
+>>>>> Unfortunately, with existential matching, the set of pages that each
+>>>>> pagespec depends upon can quickly become "*", which is not very useful.  -- [[Will]]
+
+Patch updated to use closures rather than inline generated code for named pagespecs.  Also includes some new use of ErrorReason where appropriate. -- [[Will]]
+
+> * Perl really doesn't need forward declarations, honest!
+
+>> It complained (warning, not error) when I didn't use the forward declaration. :(
+
+> * I have doubts about memoizing the anonymous sub created by
+>   `pagespec_translate`.
+
+>> This is there explicitly to make sure that runtime is polynomial and not exponential.
+
+> * Think where you wrote `+{}` you can just write `{}`
+
+>> Possibly :) -- [[Will]]
+
+----
+
+    diff --git a/IkiWiki.pm b/IkiWiki.pm
+    index 061a1c6..1e78a63 100644
+    --- a/IkiWiki.pm
+    +++ b/IkiWiki.pm
+    @@ -1774,8 +1774,12 @@ sub pagespec_merge ($$) {
+       return "($a) or ($b)";
+     }
+     
+    -sub pagespec_translate ($) {
+    +# is perl really so dumb it requires a forward declaration for recursive calls?
+    +sub pagespec_translate ($$);
+    +
+    +sub pagespec_translate ($$) {
+       my $spec=shift;
+    +  my $specFuncsRef=shift;
+     
+       # Convert spec to perl code.
+       my $code="";
+    @@ -1789,7 +1793,9 @@ sub pagespec_translate ($) {
+               |
+                       \)              # )
+               |
+    -                  \w+\([^\)]*\)   # command(params)
+    +                  define\(\s*~\w+\s*,((\([^()]*\)) | ([^()]+))+\) # define(~specName, spec) - spec can contain parens 1 deep
+    +          |
+    +                  \w+\([^()]*\)   # command(params) - params cannot contain parens
+               |
+                       [^\s()]+        # any other text
+               )
+    @@ -1805,10 +1811,19 @@ sub pagespec_translate ($) {
+               elsif ($word eq "(" || $word eq ")" || $word eq "!") {
+                       $code.=' '.$word;
+               }
+    -          elsif ($word =~ /^(\w+)\((.*)\)$/) {
+    +          elsif ($word =~ /^define\(\s*(~\w+)\s*,(.*)\)$/s) {
+    +                  my $name = $1;
+    +                  my $subSpec = $2;
+    +                  my $newSpecFunc = pagespec_translate($subSpec, $specFuncsRef);
+    +                  return if $@ || ! defined $newSpecFunc;
+    +                  $specFuncsRef->{$name} = $newSpecFunc;
+    +                  push @data, qq{Created named pagespec "$name"};
+    +                  $code.="IkiWiki::SuccessReason->new(\$data[$#data])";
+    +          }
+    +          elsif ($word =~ /^(\w+)\((.*)\)$/s) {
+                       if (exists $IkiWiki::PageSpec::{"match_$1"}) {
+                               push @data, $2;
+    -                          $code.="IkiWiki::PageSpec::match_$1(\$page, \$data[$#data], \@_)";
+    +                          $code.="IkiWiki::PageSpec::match_$1(\$page, \$data[$#data], \@_, specFuncs => \$specFuncsRef)";
+                       }
+                       else {
+                               push @data, qq{unknown function in pagespec "$word"};
+    @@ -1817,7 +1832,7 @@ sub pagespec_translate ($) {
+               }
+               else {
+                       push @data, $word;
+    -                  $code.=" IkiWiki::PageSpec::match_glob(\$page, \$data[$#data], \@_)";
+    +                  $code.=" IkiWiki::PageSpec::match_glob(\$page, \$data[$#data], \@_, specFuncs => \$specFuncsRef)";
+               }
+       }
+     
+    @@ -1826,7 +1841,7 @@ sub pagespec_translate ($) {
+       }
+     
+       no warnings;
+    -  return eval 'sub { my $page=shift; '.$code.' }';
+    +  return eval 'memoize (sub { my $page=shift; '.$code.' })';
+     }
+     
+     sub pagespec_match ($$;@) {
+    @@ -1839,7 +1854,7 @@ sub pagespec_match ($$;@) {
+               unshift @params, 'location';
+       }
+     
+    -  my $sub=pagespec_translate($spec);
+    +  my $sub=pagespec_translate($spec, +{});
+       return IkiWiki::ErrorReason->new("syntax error in pagespec \"$spec\"")
+               if $@ || ! defined $sub;
+       return $sub->($page, @params);
+    @@ -1850,7 +1865,7 @@ sub pagespec_match_list ($$;@) {
+       my $spec=shift;
+       my @params=@_;
+     
+    -  my $sub=pagespec_translate($spec);
+    +  my $sub=pagespec_translate($spec, +{});
+       error "syntax error in pagespec \"$spec\""
+               if $@ || ! defined $sub;
+       
+    @@ -1872,7 +1887,7 @@ sub pagespec_match_list ($$;@) {
+     sub pagespec_valid ($) {
+       my $spec=shift;
+     
+    -  my $sub=pagespec_translate($spec);
+    +  my $sub=pagespec_translate($spec, +{});
+       return ! $@;
+     }
+     
+    @@ -1919,6 +1934,68 @@ sub new {
+     
+     package IkiWiki::PageSpec;
+     
+    +sub check_named_spec($$;@) {
+    +  my $page=shift;
+    +  my $specName=shift;
+    +  my %params=@_;
+    +
+    +  return IkiWiki::ErrorReason->new("Unable to find specFuncs in params to check_named_spec()!")
+    +          unless exists $params{specFuncs};
+    +
+    +  my $specFuncsRef=$params{specFuncs};
+    +
+    +  return IkiWiki::ErrorReason->new("Named page spec '$specName' is not valid")
+    +          unless (substr($specName, 0, 1) eq '~');
+    +
+    +  if (exists $specFuncsRef->{$specName}) {
+    +          # remove the named spec from the spec refs
+    +          # when we recurse to avoid infinite recursion
+    +          my $sub = $specFuncsRef->{$specName};
+    +          delete $specFuncsRef->{$specName};
+    +          my $result = $sub->($page, %params);
+    +          $specFuncsRef->{$specName} = $sub;
+    +          return $result;
+    +  } else {
+    +          return IkiWiki::ErrorReason->new("Page spec '$specName' does not exist");
+    +  }
+    +}
+    +
+    +sub check_named_spec_existential($$$;@) {
+    +  my $page=shift;
+    +  my $specName=shift;
+    +  my $funcref=shift;
+    +  my %params=@_;
+    +
+    +  return IkiWiki::ErrorReason->new("Unable to find specFuncs in params to check_named_spec_existential()!")
+    +                  unless exists $params{specFuncs};
+    +  my $specFuncsRef=$params{specFuncs};
+    +  
+    +  return IkiWiki::ErrorReason->new("Named page spec '$specName' is not valid")
+    +          unless (substr($specName, 0, 1) eq '~');
+    +
+    +  if (exists $specFuncsRef->{$specName}) {
+    +          # remove the named spec from the spec refs
+    +          # when we recurse to avoid infinite recursion
+    +          my $sub = $specFuncsRef->{$specName};
+    +          delete $specFuncsRef->{$specName};
+    +          
+    +          foreach my $nextpage (keys %IkiWiki::pagesources) {
+    +                  if ($sub->($nextpage, %params)) {
+    +                          my $tempResult = $funcref->($page, $nextpage, %params);
+    +                          if ($tempResult) {
+    +                                  $specFuncsRef->{$specName} = $sub;
+    +                                  return IkiWiki::SuccessReason->new("Existential check of '$specName' matches because $tempResult");
+    +                          }
+    +                  }
+    +          }
+    +          
+    +          $specFuncsRef->{$specName} = $sub;
+    +          return IkiWiki::FailReason->new("No page in spec '$specName' was successfully matched");
+    +  } else {
+    +          return IkiWiki::ErrorReason->new("Named page spec '$specName' does not exist");
+    +  }
+    +}
+    +
+     sub derel ($$) {
+       my $path=shift;
+       my $from=shift;
+    @@ -1937,6 +2014,10 @@ sub match_glob ($$;@) {
+       my $glob=shift;
+       my %params=@_;
+       
+    +  if (substr($glob, 0, 1) eq '~') {
+    +          return check_named_spec($page, $glob, %params);
+    +  }
+    +
+       $glob=derel($glob, $params{location});
+     
+       my $regexp=IkiWiki::glob2re($glob);
+    @@ -1959,8 +2040,9 @@ sub match_internal ($$;@) {
+     
+     sub match_link ($$;@) {
+       my $page=shift;
+    -  my $link=lc(shift);
+    +  my $fullLink=shift;
+       my %params=@_;
+    +  my $link=lc($fullLink);
+     
+       $link=derel($link, $params{location});
+       my $from=exists $params{location} ? $params{location} : '';
+    @@ -1975,25 +2057,37 @@ sub match_link ($$;@) {
+               }
+               else {
+                       return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
+    -                          if match_glob($p, $link, %params);
+    +                          if match_glob($p, $fullLink, %params);
+                       $p=~s/^\///;
+                       $link=~s/^\///;
+                       return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
+    -                          if match_glob($p, $link, %params);
+    +                          if match_glob($p, $fullLink, %params);
+               }
+       }
+       return IkiWiki::FailReason->new("$page does not link to $link");
+     }
+     
+     sub match_backlink ($$;@) {
+    -  return match_link($_[1], $_[0], @_);
+    +  my $page=shift;
+    +  my $backlink=shift;
+    +  my @params=@_;
+    +
+    +  if (substr($backlink, 0, 1) eq '~') {
+    +          return check_named_spec_existential($page, $backlink, \&match_backlink, @params);
+    +  }
+    +
+    +  return match_link($backlink, $page, @params);
+     }
+     
+     sub match_created_before ($$;@) {
+       my $page=shift;
+       my $testpage=shift;
+       my %params=@_;
+    -  
+    +
+    +  if (substr($testpage, 0, 1) eq '~') {
+    +          return check_named_spec_existential($page, $testpage, \&match_created_before, %params);
+    +  }
+    +
+       $testpage=derel($testpage, $params{location});
+     
+       if (exists $IkiWiki::pagectime{$testpage}) {
+    @@ -2014,6 +2108,10 @@ sub match_created_after ($$;@) {
+       my $testpage=shift;
+       my %params=@_;
+       
+    +  if (substr($testpage, 0, 1) eq '~') {
+    +          return check_named_spec_existential($page, $testpage, \&match_created_after, %params);
+    +  }
+    +
+       $testpage=derel($testpage, $params{location});
+     
+       if (exists $IkiWiki::pagectime{$testpage}) {
index 8b6941310fc6659c65f143723549ed0bdf66b13f..14bb437824f802e3c2832b74f7b72d810d256daf 100644 (file)
@@ -8,7 +8,7 @@ I think this (untested) patch might just do the trick:
 
     --- a/IkiWiki/Plugin/edittemplate.pm
     +++ b/IkiWiki/Plugin/edittemplate.pm
-    @@ -46,8 +46,13 @@ sub preprocess (@) { #{{{
+    @@ -46,8 +46,13 @@ sub preprocess (@) {
 
       $pagestate{$params{page}}{edittemplate}{$params{match}}=$params{template};
 
@@ -21,10 +21,14 @@ I think this (untested) patch might just do the trick:
     +       else {
     +               return '';
     +       }
-    } # }}}
+    }
 
-    sub formbuilder (@) { #{{{
+    sub formbuilder (@) {
 
 --[[madduck]]
 
-[[tags wishlist patch]]
+[[!tags wishlist patch]]
+
+[[done]], though the patch I eventually applied uses "silent" as the
+parameter name. Sorry for forgetting about this patch until someone else
+implemented it too. --[[Joey]]
index 91ac4ba857625b75bfc383109190e9afe676b039..dd162a0845bbb227f125b02bd92daadc065f4e96 100644 (file)
@@ -1,5 +1,5 @@
 The [[typography_plugin|plugins/typography]] could support configuration of
-which translations to make.  [[cpan Text::Typography]] supports fine-grained
+which translations to make.  [[!cpan Text::Typography]] supports fine-grained
 control of which translations to make, so [[plugins/typography]] just needs to
 expose this somehow. --[[JoshTriplett]]
 
index fbba893c5c8d20aa690eea0b7640d88bd95ecca1..e5ad34335b630f6dbc4d0c65cb2443e28b68b832 100644 (file)
@@ -4,6 +4,21 @@ This works right from a technical point of view, but the URLs will become ugly.
 So I made a patch which unaccent chars: <http://users.itk.ppke.hu/~cstamas/code/ikiwiki/unaccentpagetitlenames/>
 This is a one liner change, but requires a bit of reordering in the code.
 
-[[cstamas]]
+--[[cstamas]]
 
-[[tag wishlist patch]]
+> This was previously requested in [[todo/more_customisable_titlepage_function]],
+> in which [[Joey]] said "I don't think that changing titlepage is a good idea,
+> there are compatability problems".
+>
+> The problem is that altering titlepage changes the meaning of your wiki,
+> by resolving all wiki links to different page names. That means that:
+>
+> * unaccenting can't be automatic, it has to be a configuration option
+>   (so you don't accidentally get different behaviour by installing
+>   Text::Unaccent)
+> * upgrading Text::Unaccent becomes risky, as I doubt it guarantees to
+>   have stable rules for how to transliterate into ASCII!
+>
+> --[[smcv]]
+
+[[!tag wishlist patch patch/core]]
diff --git a/doc/todo/unified_temporary_file__47__directory_handling.mdwn b/doc/todo/unified_temporary_file__47__directory_handling.mdwn
new file mode 100644 (file)
index 0000000..ca63fbe
--- /dev/null
@@ -0,0 +1,19 @@
+Many plugins seem to create temporary files. Although it is not much code, it is duplicated, and a 
+typical place for security bugs.  Would it be worthwhile to have library functions for creating temporary files 
+and directories?  If nothing else, it would serve as documentation of the "official way".
+
+Off to cut and paste :-) --[[DavidBremner]]
+
+> Hmm, I see only three users of temp files in all ikiwiki:
+> * hnb uses `File::Temp::mkstemp` to create two temp file handles.
+> * teximg uses `File::Temp::tempdir` to create a temporary directory.
+> * attachment retrieves a temp file from `CGI::tmpFileName`.
+> These are three quite different uses of temp files, not subject to
+> unification. Using `File::Temp` (and avoiding the posibly insecure
+> `mktemp`, `tmpname`, and `tempnam` functions) is probably as unified as
+> can be managed. --[[Joey]]
+
+>> OK, fair enough. Somehow the code in teximg made me think it was
+>> all a bit complicated. But after I played with it a bit more (and used File::Temp)
+>> I tend to agree, there is no real problem there to fix.  
+>> Feel free to mark [[done]] [[DavidBremner]]
index c5fe28f4b08de32537a07bb9cad2973ad0aa7975..d292a1184892132e880365370900f8c71fc0243c 100644 (file)
@@ -15,7 +15,7 @@ ManojSrivastava
 
 > I think you could now implement "toplvl" using [[conditionals|/plugins/conditional]]:
 >
->     \[[if test="destpage(/index)" then="""...""" else="""..."""]]
+>     \[[!if test="destpage(/index)" then="""...""" else="""..."""]]
 >
 > --[[JoshTriplett]]
 
@@ -33,6 +33,12 @@ ManojSrivastava
 > > directory,  which is not very easy for a plain ol' user.  Not everyone is the
 > >  sysadmin of their own machines with access to system dirs. --ManojSrivastava
 
+>>> It seems worth mentioning here that the `libdir` configuration parameter
+>>> lets you install additional plugins in a user-controlled directory
+>>> (*libdir*`/IkiWiki/Plugin`), avoiding needing root; indeed, a full local
+>>> ikiwiki installation without any involvement from the sysadmin is
+>>> [[possible|tips/DreamHost]]. --[[smcv]]
+
 <pre>
                 varioki => {'motto'    => '"Manoj\'s musings"',
                         'arrayvar' => '[0, 1, 2, 3]',
@@ -157,9 +163,9 @@ ManojSrivastava
 +=cut
 +
 +
-+sub import { #{{{
++sub import {
 +      hook(type => "pagetemplate", id => "varioki", call => \&pagetemplate);
-+} # }}}
++}
 +
 +
 +=pod
@@ -175,7 +181,7 @@ ManojSrivastava
 +
 +=cut
 +
-+sub pagetemplate (@) { #{{{
++sub pagetemplate (@) {
 +      my %params=@_;
 +      my $page=$params{page};
 +      my $template=$params{template};
@@ -207,7 +213,7 @@ ManojSrivastava
 +             $template->param("$var" =>"$value");
 +           }
 +        }
-+} # }}}
++}
 +
 +1;
 +
@@ -263,4 +269,4 @@ ManojSrivastava
 +
 </pre>
 
-[[tag patch]]
+[[!tag patch]]
diff --git a/doc/todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both.mdwn b/doc/todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both.mdwn
new file mode 100644 (file)
index 0000000..65b7cd9
--- /dev/null
@@ -0,0 +1,29 @@
+It looks like all links in websites are absolute paths, this has some limitations:
+
+* If connecting to website via https://... all links will take you back to http://
+* Makes it harder to mirror website via HTML version, as all links have to be updated.
+
+It would be good if relative paths could be used instead, so the transport method isn't changed unless specifically requested.
+
+-- Brian May
+
+> Er, which absolute links are you talking about? If you view the source
+> to this page, you'll find links such as "../favicon.ico", "../style.css",
+> "../../", and "../". The only absolute links are to CGIs and the w3c DTD.
+> --[[Joey]]
+
+>> The problem is within the CGI script. The links within the HTML page are all absolute, including links to the css file.
+>> Having a http links within a HTML page retrieved using https upset most browsers (I think). Also if I push cancel on the edit page in https, I end up at at http page. -- Brian May
+
+>>> Ikiwiki does not hardcode http links anywhere. If you don't want
+>>> it to use such links, change your configuration to use https
+>>> consistently. --[[Joey]]
+
+Errr... That is not a solution, that is a work around. ikiwiki does not hard code the absolute paths, but absolute paths are hard coded in the configuration file. If you want to serve your website so that the majority of users can see it as http, including in rss feeds (this allows proxy caches to cache the contents and has reduced load requirements), but editing is done via https for increased security, it is not possible. I have some ideas how this can be implemented (as ikiwiki has the absolute path to the CGI script and the absolute path to the destination, it should be possible to generate a relative path from one to the other), although some minor issues still need to be resolved. -- Brian May
+
+I noticed the links to the images on <http://ikiwiki.info/recentchanges/> are also absolute, that is <http://ikiwiki.info/wikiicons/diff.png>; this seems surprising, as the change.tmpl file uses &lt;TMPL_VAR BASEURL&gt;
+which seems to do the right thing in page.tmpl, but not for change.tmpl. Where is BASEURL set? -- Brian May
+
+> The use of an absolute baseurl in change.tmpl is a special case. --[[Joey]]
+
+[[wishlist]]
index 3dd59f162f92ad9a412b08a3ee15a05ef6528c1f..c865bf73810fb8a1d0542533f2d2757f22ccb407 100644 (file)
@@ -9,4 +9,4 @@ MoinMoin has a simple implementation of this, [click here to see an example](htt
 
 --[[AdamShand]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
index 08ca61b0ccde803b830a3677757e22851eae80fa..7a4a295d4ad7cd354a65af5f9777c375ba5cd733 100644 (file)
@@ -1 +1,9 @@
-[[Wishlist]] item: I'd love to see the ability to optionally switch back to wiki syntax within the comments of code pretty-printed with the [[plugins/contrib/syntax]] plugin.  This would allow the use of links and formatting in comments.
+[[Wishlist]] item: I'd love to see the ability to optionally switch back to
+wiki syntax within the comments of code pretty-printed with the
+[[plugins/contrib/syntax]] plugin.  This would allow the use of links and
+formatting in comments.
+
+> You can do this using the [[plugins/highlight]] plugin, but you have
+> to explicitly put a format directive in the comment to do it. Thus,
+> I'm leaving this open for now.. ideally, comments would be detected,
+> and formatted as markdown. --[[Joey]] 
diff --git a/doc/todo/wikitrails.mdwn b/doc/todo/wikitrails.mdwn
new file mode 100644 (file)
index 0000000..ca97c94
--- /dev/null
@@ -0,0 +1,41 @@
+## summary
+at times it is useful to have a guided tour or trail through a subset of the pages of a wiki; in pmwiki, this is implemented as [wikitrails](http://www.pmwiki.org/wiki/PmWiki/WikiTrails).
+
+i'm working on a python xmlrpc plugin for ikiwiki to support wikitrails, both as a navigation feature (have "forward" and "back" links based on a sequence) and a modified inline that includes all pages in the trail with appropriate modifications (suitable for printing if necessary).
+
+the current status is published on `git://github.com/github076986099/ikiwiki-plugins.git`; as of now, i don't have a public demo of it.
+
+feedback on both the concept and the code is very much appreciated by [[discussion]] or [email](mailto:chrysn@fsfe.org).
+
+## usage
+
+two preprocessor commands are provided:
+
+### \[[!trail index="my_indexpage"]]
+
+embeds a navigation object with forward and back links as well as an indicator of the current position in the trail.
+
+if index is not specified, a suitable page up the path is used.
+
+this works very well together with the [[sidebar|plugins/sidebar]] plugin if the pages in a directory are roughly the same as the pages in the trail and the `index` is directory index page; just put the \[[!trail]] in the sidebar.
+
+### \[[!trailinclude index="my_indexpage"]]
+
+all pages linked from the index page are included in the same way as \[[!inline]] does, but in the proper sequence, with headings according to the indent in the source page and adoptions for the headings inside the page (a level 2 heading in a page that is a sub-sub-chapter in the whole trail will become a level 5 heading when trailincluded).
+
+## the index page
+
+the index page is parsed as markdown; numbered lists and "`*`" bulleted lists are discovered.
+
+## current issues
+
+ * rebuilding --- currently, there is no propper rebuilding of pages (will use `will_render` and `add_depends`). care has to be taken of how not yet created pages play into this.
+ * inline recursion --- there is simply no guard yet
+ * navigation layout --- has to be both flexible and usable-by-default
+ * heading shifting
+  * currently only works for markdown
+  * can break the limit of html's six heading levels
+ * search for index page is currently next to hardcoded
+ * reading the index --- markdown syntax parsing is currently on a it-can-use-what-i-produce level; maybe integrate with existing mdwn parser
+ * uses undocumented titlepage command
+   > Don't worry about that, titlepage isn't going anywhere, and will probably before a formal part of the api next time I consider api changes. --[[Joey]]
diff --git a/doc/todo/wikitrails/discussion.mdwn b/doc/todo/wikitrails/discussion.mdwn
new file mode 100644 (file)
index 0000000..9dbbb6b
--- /dev/null
@@ -0,0 +1,80 @@
+This is a nice idea, I do have my gripes about the imeplementation.
+
+Assuming that the index's list is in mdwn format is not ideal. I guess the
+other way to do it would be to make the index be a directive, something
+like: \[[!trail pages="foo bar baz"]]. Assuming that a flat trail structure
+is enough, otherwise you'd have to get more fancy.
+
+The trailinclude seems a bit redundant with inline, and wanting to inline
+together all pages in a trail for printing or whatever seems like an
+unusual use case anyway?
+
+The !trail directive could be simplified to just \[[!trail my_indexpage]].
+But I wonder if needing to add this directive to every page is the best
+approach. Alternate approach would be to make the trail index cause 
+breadcrums to be automatically inserted at the top of every page on the
+trail. (You'd have to use a directive to define the index for that to work.)
+
+--[[Joey]]
+
+----
+
+Revisiting this, after effectively reimplementing a small version of it
+in [[plugins/contrib/album]]: it occurs to me that might be a more
+"ikiwiki-like" way we could get this functionality.
+
+In the index page, you either want an [[ikiwiki/directive/inline]], or
+a list of links. In the former case, maybe we could extend inline like
+this:
+
+    \[[!inline ... blah blah ... trail=yes]]
+
+to make it remember the pages it inlined, in order, in the pagestate;
+in the latter case, we could replace the wikilinks with a directive,
+an operation something like this in diff notation:
+
+    - \[[one]] - the unit
+    - \[[two]] - the base of binary
+    - \[[three|3]] - is a crowd
+    + \[[!trailitem one]] - the unit
+    + \[[!trailitem two]] - the base of binary
+    + \[[!trailitem three|3]] - is a crowd
+
+and have that directive remember the pages in order.
+
+In both cases, a scan() hook could clear the list before starting to
+scan, then the inline or trailitem preprocessor directive could run in
+the scan stage as well as the render stage (in the case of inline,
+there'd be a very early return if trail=yes was not given, and
+an early return after collecting and sorting the pages if not
+actually rendering).
+
+This would mean that the contents of the trail, and a list of
+trails in which each page can be found, would already be in
+the pagestate by the time any page was rendered, so we'd be able
+to use them for output, either in a pagetemplate() hook or
+a \[[!trail]] preprocessor directive.
+
+This way, my album plugin could be turned inside out: instead
+of precomputing the pages to be inlined, then using
+[[pagenames|todo/inline plugin: specifying ordered page names]]
+to get them into the inline, it could just do the inline, then
+incorporate the output of \[[!trail]] into the template rendered
+for \[[!albumimage]] on each viewer page. (Also, the viewers
+wouldn't necessarily need to reference the album, only the other
+way round.)
+
+Using a pagetemplate() hook to stuff the next/previous links
+into page.tmpl would actually be a bit unfortunate for \[[!album]],
+because that plugin definitely wants to style the next/previous
+links as a thumbnail, which means there'd have to be a way to
+affect the style - perhaps by arranging for album's pagetemplate
+hook to run *after* trail's, or perhaps by having trail's
+pagetemplate hook disable itself for pages that contain
+a \[[!trail]] directive.
+
+I have now implemented this at [[plugins/contrib/trail]].
+What do you think? I'm still not sure how it would relate
+to [[plugins/contrib/album]], but if trail is reviewed
+and approved in principle, I'll try to adapt album as
+outlined above. --[[smcv]]
index f2af47e276719e52b7758d8d518dc85a37eb4847..839986c7b69a96c7980941a74cb128a1c959dd3b 100644 (file)
@@ -22,11 +22,11 @@ other way to feed it the actual source for a page, this seems like a
 problem. According to the developers, it is possible to do that, and start
 off in WikiText mode.
 
-[[tag soc]]
+[[!tag soc]]
 
-[[tag wishlist]]
+[[!tag wishlist]]
 
-[[tag patch]]
+[[!tag patch]]
 
 Project IkiWiki::WIKIWYG v1.6 - <http://ikiwiki.xbaud.com/>
 ===========================================================
@@ -57,3 +57,8 @@ The plugin can be downloaded from <http://ikiwiki.xbaud.com/wikiwyg-1.6.tar.gz>
 * Personalized settings
 
 [Wikiwyg]: http://www.wikiwyg.net/
+
+> As noted in [[discussion]], the url above doesn't work, and I stupidly
+> lost my copy of this before merging it. I hope that this plugin will turn
+> back up. In the meantime, there is a wmd plugin that accomplishes the
+> same basic task of WSYWIG markdown editing. --[[Joey]] 
index cbf969471afc977d358cc095db6f576a5595111a..304b3962095361a549a68f8c3ef199f69490146e 100644 (file)
@@ -90,6 +90,7 @@ changes.diff:
     I have to use the IkiWiki package instead of IkiWiki::Plugin::Wikiwyg? Or would a 
     better approach be to just copy that function into the Wikiwyg plugin?
     * You can just call `IkiWiki::pagetitle()`.
+      > Note: pagetitle is now exported.
 
 wikiwyg.tar.gz
 
index 58a8f4b48a521d678b5b6ad3d90d51f905af38b8..d869a682172eb560a950d10656d614d6af583bc3 100644 (file)
@@ -1,9 +1,9 @@
 If you want to translate your wiki into another language, there are
-essentailly three peices needed for a complete translation:
+essentially three pieces needed for a complete translation:
 
 1. The messages in the ikiwiki program itself need to be translated.
    Ikiwiki is internationalised, and most such messages are already marked
-   with `gettext()`. THe source tarball includes a creates a `po/ikiwiki.pot`
+   with `gettext()`. The source tarball includes a `po/ikiwiki.pot`
    that can be copied and translated as a po file. All very standard.
 
    Note that a few things in the source are not currently translated. These
@@ -22,11 +22,25 @@ essentailly three peices needed for a complete translation:
    * The names and values of parameters, both to the program, in the setup
      file, and in preprocessor directives.
 
+1. The [[basewiki]] needs to be translated. The
+   [[plugins/contrib/po]] ikiwiki plugin will allow translating
+   wikis using po files and can be used for this.
+
+   There is now a website, [l10n.ikiwiki.info](http://l10n.ikiwiki.info)
+   that both demos the translated basewiki, and allows easy translation of
+   it.
+
+   To generate the po and pot files for translating the basewiki,
+   get ikiwiki's source, edit the `po/underlay.setup` file,
+   adding your language. Then run 'make -C po underlays`.
+   This will generate many po files under `po/underlays`. The first
+   ones you'll want to translate are in the `po/underlays/basewiki` directory,
+   which is really not very large, just a few thousand words.
+   After that is done, you can tackle those under
+   `po/underlays/directives`, which are a much larger (tens of
+   thousands of words).
+
 1. The templates also need to be translated. Some work has been done on an
    infrastructure for maintaining translated templates, as documented in
    [[todo/l10n]], but until that's complete, you'd need to copy and
    translate the templates by hand.
-
-1. The [[basewiki]] itself needs to be translated. Whether to only translate
-   the page contents, or also translate the page names, is an open
-   question.
index 26097b5559dbcd48ebea1a20c6eddd256ed90276..35e8fd0542be20f994507d098d8610c44412cf44 100644 (file)
@@ -17,15 +17,8 @@ updating my PO file? Should I send it to you for every ikiwiki issue?
 Maybe you should give write access to ikiwiki repository for translators
 of PO files?
 
-  > I recently set up a git repository mirroring the main svn repository (see
-  > [[download]]) and one idea is that perhaps translators can use that for a
-  > distributed revision control system that I can merge back from into svn.
-  > I can set up accounts for svn, but as it's on my own personal server and
-  > not a sourceforge/alioth like thing, it's a bit of a pain and maintenance
-  > burden for me.
-
-  >> OK, I've picked up Subversion for your ikiwiki, so I can get into
-  >> Git now ;)
+  > We use git now, so you can clone my repo, commit to your clone, and
+  > use git to mail me patches. --[[Joey]] 
 
 3. What is the best way to update my PO file when you do some changes in
 `ikiwiki.pot` file? Should I translate my PO file from scratch or
@@ -94,4 +87,4 @@ translators. Thank you! :) --[[Paweł|ptecza]]
 > size limits. This is generally done by adding comments in the pot file,
 > and I've turned that on, and added a few. --[[Joey]]
 
->> Thank you very much! It also will be a big help for me. --[[Paweł|ptecza]]
\ No newline at end of file
+>> Thank you very much! It also will be a big help for me. --[[Paweł|ptecza]]
index 2b104bcdb5597659f08c734046ba89ddd711741c..0c618de5c1eac91ac31b11407c90cc4585e0cab6 100644 (file)
@@ -6,7 +6,7 @@ ikiwiki - a wiki compiler
 
 ikiwiki [options] source destination
 
-ikiwiki --setup configfile
+ikiwiki --setup setupfile
 
 # DESCRIPTION
 
@@ -30,6 +30,26 @@ These options control the mode that ikiwiki operates in.
 
   Force a rebuild of all pages.
 
+* --setup setupfile
+
+  In setup mode, ikiwiki reads the config file, which is really a perl
+  program that can call ikiwiki internal functions.
+
+  The default action when --setup is specified is to automatically generate
+  wrappers for a wiki based on data in a setup file, and rebuild the wiki.
+  If you only want to build any changed pages, you can use --refresh with
+  --setup.
+
+* --dumpsetup setupfile
+
+  Causes ikiwiki to write to the specified setup file, dumping out
+  its current configuration.
+
+* --wrappers
+
+  If used with --setup --refresh, this makes it also update any configured
+  wrappers.
+
 * --cgi
 
   Enable [[CGI]] mode. In cgi mode ikiwiki runs as a cgi script, and
@@ -50,23 +70,6 @@ These options control the mode that ikiwiki operates in.
 
   Note that the generated wrapper will ignore all command line parameters.
 
-* --setup configfile
-
-  In setup mode, ikiwiki reads the config file, which is really a perl
-  program that can call ikiwiki internal functions.
-
-  [[ikiwiki.setup]] is an example of such a config file.
-
-  The default action when --setup is specified is to automatically generate
-  wrappers for a wiki based on data in a config file, and rebuild the wiki.
-  If you only want to build any changed pages, you can use --refresh with
-  --setup.
-
-* --wrappers
-
-  If used with --setup --refresh, this makes it also update any configured
-  wrappers.
-
 * --aggregate
 
   If the [[plugins/aggregate]] plugin is enabled, this makes ikiwiki poll
@@ -100,13 +103,14 @@ These options control the mode that ikiwiki operates in.
 # CONFIG OPTIONS
 
 These options configure the wiki. Note that [[plugins]] can add additional
-configuration options of their own.
+configuration options of their own. All of these options and more besides can
+also be configured using a setup file.
 
-* --wikiname
+* --wikiname name
 
   The name of the wiki, default is "wiki".
 
-* --templatedir
+* --templatedir dir
 
   Specify the directory that the page [[templates|wikitemplates]] are stored in.
   Default is `/usr/share/ikiwiki/templates`, or another location as configured at
@@ -118,7 +122,7 @@ configuration options of their own.
   ikiwiki. Old versions of templates do not always work with new ikiwiki
   versions.
 
-* --underlaydir
+* --underlaydir dir
 
   Specify the directory that is used to underlay the source directory.
   Source files will be taken from here unless overridden by a file in the
@@ -163,24 +167,24 @@ configuration options of their own.
 * --rss, --norss
 
   If rss is set, ikiwiki will default to generating RSS feeds for pages
-  that inline a [[ikiwiki/blog]].
+  that inline a [[blog]].
 
 * --allowrss
 
   If allowrss is set, and rss is not set, ikiwiki will not default to
-  generating RSS feeds, but setting `rss=yes` in the blog can override
-  this default and generate a feed.
+  generating RSS feeds, but setting `rss=yes` in the inline directive can
+  override this default and generate a feed.
 
 * --atom, --noatom
 
   If atom is set, ikiwiki will default to generating Atom feeds for pages
-  that inline a [[ikiwiki/blog]].
+  that inline a [[blog]].
 
 * --allowatom
 
   If allowatom is set, and rss is not set, ikiwiki will not default to
-  generating Atom feeds, but setting `atom=yes` in the blog can override
-  this default and generate a feed.
+  generating Atom feeds, but setting `atom=yes` in the inline directive can
+  override this default and generate a feed.
 
 * --pingurl URL
 
@@ -289,7 +293,7 @@ configuration options of their own.
 * --prefix-directives, --no-prefix-directives
 
   Toggle new '!'-prefixed syntax for preprocessor directives.  ikiwiki currently
-  defaults to --no-prefix-directives.
+  defaults to --prefix-directives.
 
 * --w3mmode, --no-w3mmode
 
@@ -304,19 +308,37 @@ configuration options of their own.
 
 * --getctime
 
-  Pull last changed time for each new page out of the revision control
+  Pull creation time for each new page out of the revision control
   system. This rarely used option provides a way to get the real creation
   times of items in weblogs, such as when building a wiki from a new
-  Subversion checkout. It is unoptimised and quite slow. It is best used
+  VCS checkout. It is unoptimised and quite slow. It is best used
   with --rebuild, to force ikiwiki to get the ctime for all pages.
 
 * --set var=value
   
   This allows setting an arbitrary configuration variable, the same as if it
-  were set via a configuration file. Since most options can be configured
+  were set via a setup file. Since most options can be configured
   using command-line switches, you will rarely need to use this, but it can be
   useful for the odd option that lacks a command-line switch.
 
+# EXAMPLES
+
+* ikiwiki --setup my.setup
+
+  Completly (re)build the wiki using the specified setup file.
+
+* ikiwiki --setup my.setup --refresh
+
+  Refresh the wiki, using settings from my.setup, and avoid
+  rebuilding any pages that have not changed. This is faster.
+
+* ikiwiki --setup my.setup --refresh --wrappers
+
+  Refresh the wiki, including regnerating all wrapper programs,
+  but do not rebuild all pages. Useful if you have changed something
+  in the setup file that does not need a full wiki rebuild to update
+  all pages, but that you want to immediatly take effect.
+
 # ENVIRONMENT
 
 * CC
@@ -333,4 +355,4 @@ configuration options of their own.
 
 Joey Hess <joey@ikiwiki.info>
 
-Warning: this page is automatically made into ikiwiki's man page via [mdwn2man](http://ikiwiki.info/cgi-bin/viewvc.cgi/trunk/mdwn2man?root=ikiwiki&view=markup).  Edit with care
+Warning: this page is automatically made into ikiwiki's man page via [mdwn2man](http://git.ikiwiki.info/?p=ikiwiki;a=blob;f=mdwn2man;hb=HEAD).  Edit with care
index 5121dd90c529a5c6beea0ddf35ffe4277b75cb3d..cc3cf5268a129a5d32a9af2380548b415046aad6 100644 (file)
@@ -6,6 +6,6 @@ comments.
 
 List of users
 =============
-[[inline pages="users/* and !users/*/* and !*/Discussion" 
+[[!inline pages="users/* and !users/*/* and !*/Discussion" 
 feeds=no archive=yes sort=title template=titlepage
 rootpage="users" postformtext="Add yourself as an ikiwiki user:"]]
diff --git a/doc/users/Christine_Spang.mdwn b/doc/users/Christine_Spang.mdwn
new file mode 100644 (file)
index 0000000..223e973
--- /dev/null
@@ -0,0 +1 @@
+Running ikiwiki on her [homepage](http://spang.cc/) and [blog](http://blog.spang.cc/).
index 9b543562899d7ccad20508e2500a730ce90ddf40..b32927a1c312b13f632506deaf3fbcd09baf5a7f 100644 (file)
@@ -1,4 +1,9 @@
 My watchlist:
 
-[[inline pages="todo/allow_wiki_syntax_in_commit_messages todo/shortcut_with_different_link_text" archive="yes" sort="mtime" atom="yes"]]
+[[!inline archive="yes" sort="mtime" atom="yes" pages="
+todo/allow_wiki_syntax_in_commit_messages*
+todo/shortcut_with_different_link_text*
+todo/structured_page_data*
+tips/convert_mediawiki_to_ikiwiki*
+"]]
 
diff --git a/doc/users/Jimmy_Tang.mdwn b/doc/users/Jimmy_Tang.mdwn
new file mode 100644 (file)
index 0000000..a1402bc
--- /dev/null
@@ -0,0 +1 @@
+<http://www.sgenomics.org/~jtang>
index 3b741d52635ceb10f9b82428a79c39b20c02f316..c058b13b0d4b21216a8e9e2e1bf12de106bd5cb4 100644 (file)
@@ -1,3 +1,3 @@
-[[meta title="Karl Mowatt-Wilson"]]
+[[!meta title="Karl Mowatt-Wilson"]]
 
 Working on an [asciidoc](http://www.methods.co.nz/asciidoc/) plugin for ikiwiki so I can use it for my [website](http://mowson.org/karl), where I'm documenting how to run linux on the HP/Compaq Evo T20 'thin client'.
\ No newline at end of file
diff --git a/doc/users/StevenBlack.mdwn b/doc/users/StevenBlack.mdwn
new file mode 100644 (file)
index 0000000..ea7a6a9
--- /dev/null
@@ -0,0 +1,5 @@
+It feels like there are a lot of people named Steven Black. While I'm just one of many with my name, sometimes it is actually just me and I've forgotten that I had an account somewhere.
+
+I'm not a doctor, though I would certainly trust any doctor, dentist, or philosopher named Steven Black. (There are several.)
+
+I *am* a huge Ikiwiki fan. I've had my eye on it for many years for personal projects (though I never quite got around to installing it). Recently, however, I managed to convince my coworkers that it would be a good idea for an internal wiki. Boy was I right. The thing is practically designed to be the perfect developer-centered wiki.
index a01bcba9959d4f283cb3e14cecc623e1e154207a..71e257db49261a3ccf607ac6ab9202a9f387a79e 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Taylor Killian"]]
+[[!meta title="Taylor Killian"]]
 
 Hi,
 
diff --git a/doc/users/TimBosse.mdwn b/doc/users/TimBosse.mdwn
new file mode 100644 (file)
index 0000000..bd459cc
--- /dev/null
@@ -0,0 +1 @@
+<http://bosboot.org>
diff --git a/doc/users/Tim_Lavoie.mdwn b/doc/users/Tim_Lavoie.mdwn
new file mode 100644 (file)
index 0000000..90df011
--- /dev/null
@@ -0,0 +1 @@
+Hey... I'm just starting to use ikiwiki, but am happy to find it repeatedly doing the sorts of things in a way which makes sense to me. (e.g. most pages are static, DVCS for file store etc.)
diff --git a/doc/users/Will.mdwn b/doc/users/Will.mdwn
new file mode 100644 (file)
index 0000000..9c46edc
--- /dev/null
@@ -0,0 +1,24 @@
+I started using Ikiwiki as a way to replace [Trac](http://trac.edgewall.org/) when using [Monotone](http://monotone.ca/).  Version control has been an interest of mine for a while and I wrote most of the ikiwiki [[rcs/monotone]] plugin.  I'm not actively working on the Monotone plugin any more.
+
+Lately I've been using Ikiwiki for other things and seem to be scratching a few itches here and there. :)
+
+I generally use my [[ikiwiki/openid]] login when editing here: <http://www.cse.unsw.edu.au/~willu/>
+
+Generic License Grant
+-----------------
+
+Unless otherwise specified, any code that I post to this wiki I release under the GPL2+.  Any non-code patches I post are released under [[standard ikiwiki licenses|freesoftware]].
+
+------
+
+### Open Bugs:
+
+[[!inline pages="link(users/Will) and bugs/* and !bugs/done and !bugs/discussion and !link(patch) and !link(bugs/done) and !bugs/*/*" archive="yes" feeds="no" ]]
+
+### Open ToDos:
+
+[[!inline pages="link(users/Will) and todo/* and !todo/done and !todo/discussion and !link(patch) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]
+
+### Unapplied Patches:
+
+[[!inline pages="link(users/Will) and (todo/* or bugs/*) and !bugs/done and !bugs/discussion and !todo/done and !todo/discussion and link(patch) and !link(bugs/done) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]
index 267edbdde5b05b8bb944c8469ac975185d505530..6127a8d70c81cd67af8b007ca2cbced7ef502661 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Adam Shand"]]
+[[!meta title="Adam Shand"]]
 
 New IkiWiki user, long time wiki user. :-)
 
diff --git a/doc/users/ajt.mdwn b/doc/users/ajt.mdwn
new file mode 100644 (file)
index 0000000..bc47040
--- /dev/null
@@ -0,0 +1,20 @@
+[[!meta title="Adam Trickett"]]
+
+# Adam Trickett
+
+## "ajt"
+
+I'm a long time hacker of sorts, I like to program in Perl on Debian systems but work pays me to program in ABAP (COBOL) on SAP.
+
+I like wikis and I'm currently in love with ikiwiki, having moved my home intranet from a home made template solution to ikiwiki over a weekend. I'm using ikiwiki more like a web content management system (e.g. RedDot) rather than a traditional wiki.
+
+### My Links
+
+* [iredale dot net](http://www.iredale.net/) my web server and main blog
+* [ajt](http://www.perlmonks.org/index.pl?node_id=113686) my Perkmonks home node
+* [ajt](http://use.perl.org/~ajt) my use Perl home
+* [ATRICKETT](http://search.cpan.org/~atrickett/) my CPAN folder
+* [ajt](http://www.debian-administration.org/users/ajt) my Debian-Administration home (good site btw)
+* [drajt](http://www.linkedin.com/in/drajt) my LinkedIn profile
+* [drajt](http://www.slideshare.net/drajt) my "Slidespace" on SlideShare
+* [AdamTrickett](http://www.hants.lug.org.uk/cgi-bin/wiki.pl?AdamTrickett) my wiki page on my LUG's site
diff --git a/doc/users/alexander.mdwn b/doc/users/alexander.mdwn
new file mode 100644 (file)
index 0000000..b2894a9
--- /dev/null
@@ -0,0 +1 @@
+I use ikiwiki to organize information - projects, reading notes, outlines, todo lists, etc. 
index 0c49df4b611e896a55a036667994b71bcdda6a5e..5632806b4efd83bdffa1197f9d7b0b814175a8d0 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Arpit Jain"]]
+[[!meta title="Arpit Jain"]]
 Hi, 
 
 I am Arpit Jain. I am final year B.Tech/M.Tech(Dual Degree) student at Department of Computer Science and Engineering, Indian Institute of Technology, Kharagpur. 
index 4bda44b582e68a23889c0a374b83bce84a4f6b85..933ba78e196fc148cd91288c6bc77463af89edd7 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Bruno Beaufils"]]
+[[!meta title="Bruno Beaufils"]]
 
 Bruno Beaufils is **<bruno@boulgour.com>**.
 
diff --git a/doc/users/bstpierre.mdwn b/doc/users/bstpierre.mdwn
new file mode 100644 (file)
index 0000000..327d250
--- /dev/null
@@ -0,0 +1 @@
+Brian St. Pierre is **<brian@bstpierre.org>**
diff --git a/doc/users/cfm.mdwn b/doc/users/cfm.mdwn
new file mode 100644 (file)
index 0000000..4feab96
--- /dev/null
@@ -0,0 +1 @@
+I maintain a [home page](http://www.panix.com/~cfm/ "Cory Myers").
index 37e97314bf7e35010045752964137892fd3c209e..ec0e1451e17dfe0a549b2e8ab8020d6896018ff8 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Chris Green"]]
+[[!meta title="Chris Green"]]
 
 Chris is Chris Green, an ancient C/C++/Java programmer, I started around 1982 or 1983.
 
diff --git a/doc/users/cord.mdwn b/doc/users/cord.mdwn
new file mode 100644 (file)
index 0000000..c8775d6
--- /dev/null
@@ -0,0 +1 @@
+http://Cord.de
index 935a529cf36236621a117c80e76ee24ad95493ee..87b49ebf9d641b747f66d171376c72bcfd11c300 100644 (file)
@@ -1,3 +1,3 @@
-[[meta title="Adeodato Simó"]]
+[[!meta title="Adeodato Simó"]]
 
 <http://chistera.yi.org/~adeodato>
diff --git a/doc/users/dom.mdwn b/doc/users/dom.mdwn
new file mode 100644 (file)
index 0000000..c754356
--- /dev/null
@@ -0,0 +1,3 @@
+<http://www.larted.org.uk/~dom>
+
+Just another ikiwiki user.
diff --git a/doc/users/donmarti.mdwn b/doc/users/donmarti.mdwn
new file mode 100644 (file)
index 0000000..bafec71
--- /dev/null
@@ -0,0 +1,2 @@
+Don Marti home page: <http://zgp.org/~dmarti/>  email: <dmarti@zgp.org>
+
diff --git a/doc/users/harishcm.mdwn b/doc/users/harishcm.mdwn
new file mode 100644 (file)
index 0000000..47f28c8
--- /dev/null
@@ -0,0 +1 @@
+Using ikiwiki for my yet to be publish personal website :)
index cbb588cd8a3a3b253ebd890f0200d9f11ccd4207..d4ef0765892d543572679e0da688668edc4f0536 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Thomas Harning Jr"]]
+[[!meta title="Thomas Harning Jr"]]
 
 I began using ikiwiki since it ties into git... and so far it's working great!
 
index 7811ab7d80792c52dae24c7d9e1fc465af97f412..c3e52da6d3a444c2adafc52b32264588a7cdc85f 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Hugues Bernard"]]
+[[!meta title="Hugues Bernard"]]
 
 For now I'm using ikiwiki just for my personal needs :
 
index 6dfa6a23b251f69f66d0a9fe6cc41d2d6e14b6d5..15c065e45f6bbb9239477c3b27273bbc2c81b2d9 100644 (file)
@@ -1,4 +1,5 @@
 I'd love to see any notes you have on using ikiwiki for GTD.  Would you
 consider documenting them?  Perhaps we could turn the result into a
 [[tip|tips]]. -[[JoshTriplett]]
-> Well, certainly. Basically it's just inline + tag feature. I'm going to have more time in May for ikiwiki, I hope. 
\ No newline at end of file
+> Well, certainly. Basically it's just inline + tag feature. I'm going to have more time in May for ikiwiki, I hope. 
+> > Any news about that ?
diff --git a/doc/users/hendry.mdwn b/doc/users/hendry.mdwn
new file mode 100644 (file)
index 0000000..8deaaaf
--- /dev/null
@@ -0,0 +1 @@
+[Kai Hendry](http://hendry.iki.fi/)
diff --git a/doc/users/intrigeri.mdwn b/doc/users/intrigeri.mdwn
new file mode 100644 (file)
index 0000000..8fa9965
--- /dev/null
@@ -0,0 +1,4 @@
+intrigeri AT boum.org, already loving ikiwiki.
+
+* [gnupg key](http://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc)
+* Git repository with various ikiwiki {feature, bugfix}-branches : `git://gaffer.ptitcanardnoir.org/ikiwiki.git`
index 52420f7c9fdf910dd8dc3a6d3e81c667451cbad4..b50e4844a04f30a21fd3c3d9e2b00fb94a3ca3d6 100644 (file)
+[[!meta title="Jason Blevins"]]
+
 I'm currently hosting a private ikiwiki for keeping research notes
-which, with some patches and a (currently unreleased) plugin, will
-convert inline LaTeX expressions to MathML.  I'm working towards a
+which, with some patches and a plugin (below), will
+convert inline [[todo/LaTeX]] expressions to [[MathML]].  I'm working towards a
 patchset and instructions for others to do the same.
 
-There is one thing that needs to be decided first: whether or not to
-include [[sanitization|todo/svg]] of MathML in htmlscrubber (and while
-we're at it, why not SVG).
+I've setup a test ikiwiki [here](http://xbeta.org/colab/) where I've
+started keeping a few notes on my progress.  There is an example of
+inline [[todo/SVG]] on the homepage (note that the logo scales along with the
+font size).  There are a few example mathematical expressions in the
+[sandbox](http://xbeta.org/colab/sandbox/).  The MathML is generated
+automatically from inline LaTeX expressions using an experimental
+plugin I'm working on.
 
 My (also MathML-enabled) homepage: <http://jblevins.org/> (still using
 Blosxom...maybe one day I'll convert it to ikiwiki...)
+
+Current ikiwki issues of interest:
+
+ * [[bugs/recentchanges_feed_links]]
+ * [[bugs/HTML_inlined_into_Atom_not_necessarily_well-formed]]
+ * [[plugins/toc/discussion]]
+ * [[todo/BibTeX]]
+ * [[todo/svg]]
+ * [[todo/Option_to_make_title_an_h1?]]
+ * [[bugs/SVG_files_not_recognized_as_images]]
+
+## Plugins
+
+These plugins are experimental.  Use them at your own risk.  Read the
+perldoc documentation for more details.  Patches and suggestions are
+welcome.
+
+ * [mdwn_itex][] - Works with the [[`mdwn`|plugins/mdwn]] plugin to convert inline [[todo/LaTeX]]
+   expressions to [[MathML]] using `itex2MML`.
+
+ * [h1title][] - If present, use the leading level 1 Markdown header to
+   set the page title and remove it from the page body.
+
+ * [code][] - Whole file and inline code snippet [[todo/syntax highlighting]]
+   via GNU Source-highlight.  The list of supported file extensions is
+   configurable.  There is also some preliminary [documentation][code-doc].
+   See the [FortranWiki](http://fortranwiki.org) for examples.
+
+ * [metamail][] - a plugin for loading metadata from [[email]]-style
+   headers at top of a file (e.g., `title: Page Title` or
+   `date: November 2, 2008 11:14 EST`).
+
+ * [pandoc][] - [[ikiwiki/Markdown]] page processing via [Pandoc](http://johnmacfarlane.net/pandoc/) (a Haskell library for converting from one markup format to another).  [[todo/LaTeX]] and
+   [[reStructuredText|plugins/rst]] are optional.
+
+ * [path][] - Provides path-specific template conditionals such as
+   `IS_HOMEPAGE` and `IN_DIR_SUBDIR`.
+
+ [mdwn_itex]: http://code.jblevins.org/ikiwiki/plugins.git/plain/mdwn_itex.pm
+ [h1title]: http://code.jblevins.org/ikiwiki/plugins.git/plain/h1title.pm
+ [code]: http://code.jblevins.org/ikiwiki/plugins.git/plain/code.pm
+ [code-doc]: http://code.jblevins.org/ikiwiki/plugins.git/plain/code.text
+ [metamail]: http://code.jblevins.org/ikiwiki/plugins.git/plain/metamail.pm
+ [pandoc]: http://code.jblevins.org/ikiwiki/plugins.git/plain/pandoc.pm
+ [path]: http://code.jblevins.org/ikiwiki/plugins.git/plain/path.pm
+
+
+## MathML and SVG support
+
+So far, I've made some notes on sanitizing MathML and SVG via
+htmlscrubber on the [[todo/svg]] todo item.
+
+I've also worked out some content-negotiation issues.  First of all,
+one needs to modify the default templates to use the
+XHTML+MathML+SVG doctype (see e.g., this [patch][template-patch]).
+For most browsers, the content type of the pages should be
+`application/xhtml+xml`.  The solution is easy if you want to
+just send `application/xhtml+xml` to everybody:
+just change the content type of `.html` files across the board.
+
+However, if you want to support browsers that don't accept
+`application/xhtml+xml` (and those that will but say they
+don't, such as IE with the MathPlayer plugin), then one
+needs a `mod_rewrite` rule like the following:
+
+    RewriteCond %{HTTP_ACCEPT} application\/xhtml\+xml [OR]
+    RewriteCond %{HTTP_USER_AGENT} (W3C.*Validator|MathPlayer)
+    RewriteRule \.html$ - [T=application/xhtml+xml]
+
+This solves the problem of MathML and inline SVG in static pages
+but some additional work is required for dynamically generated
+pages, like page previews, that are generated by `ikiwiki.cgi`.
+We need to allow `ikiwiki.cgi` to set the content type dynamically
+based on the `HTTP_CONTENT_TYPE` environment variable
+(e.g., with the following [patch][cgi-patch]).  Then, the following
+rewrite rules can pass the correct content type to ikiwiki:
+
+    RewriteCond %{HTTP_ACCEPT} application\/xhtml\+xml [OR]
+    RewriteCond %{HTTP_USER_AGENT} (W3C.*Validator|MathPlayer)
+    RewriteRule ikiwiki.cgi$ - [T=application/xhtml+xml]
+
+One final critical issue is that a production-ready setup needs to
+implement some sort of on-the-fly error handling.  If a user submits
+an invalid LaTeX expression or SVG code (not malicious, just invalid)
+and saves the page, then browsers like Firefox will halt processing of
+the page, preventing any further viewing or editing.  A less than
+optimal solution is to force users to preview the page before saving.
+That way if someone introduces invalid XHTML then they can't save the
+page in the first place (unless they post directly to the right URL).
+
+ [template-patch]: http://xbeta.org/gitweb/?p=xbeta/ikiwiki.git;a=blobdiff;f=templates/page.tmpl;h=380ef699fa72223744eb5c1ee655fb79aa6bce5b;hp=9084ba7e11e92a10528b2ab12c9b73cf7b0f40a7;hb=416d5d1b15b94e604442e4e209a30dee4b77b684;hpb=ececf4fb8766a4ff7eff943b3ef600be81a0df49
+ [cgi-patch]: http://xbeta.org/gitweb/?p=xbeta/ikiwiki.git;a=commitdiff;h=fa538c375250ab08f396634135f7d79fce2a9d36
diff --git a/doc/users/jelmer.mdwn b/doc/users/jelmer.mdwn
new file mode 100644 (file)
index 0000000..1f2f71a
--- /dev/null
@@ -0,0 +1 @@
+[Jelmer Vernooij](http://samba.org/~jelmer/)
index b3871a5ce37e0cd2b60b1d96f729a26ee1a4c846..8cfa5fc591bfa9d87e35d1492ea4cdee2fc44e19 100644 (file)
@@ -1,3 +1,3 @@
-[[meta title="Jeremy Reed"]]
+[[!meta title="Jeremy Reed"]]
 
 I am testing ikiwiki. I made a RCS plugin.
\ No newline at end of file
index 48227551a3493628ce30ba948427c15011e14beb..134aa21d1212b1b8f2c87ab4e8f53dfcbfeba0e0 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Joey Hess"]]
+[[!meta title="Joey Hess"]]
 
 Joey Hess is <a href="mailto:joey@kitenet.net">joey@kitenet.net</a>. 
 His web page is [here](http://kitenet.net/~joey/).
diff --git a/doc/users/jogo.mdwn b/doc/users/jogo.mdwn
new file mode 100644 (file)
index 0000000..2a65779
--- /dev/null
@@ -0,0 +1,3 @@
+I'm looking at Ikiwiki, searching the best Wiki. The only other one I've found is [werc](http://werc.cat-v.org/).
+
+email: `jogo matabio net`.
diff --git a/doc/users/jon.mdwn b/doc/users/jon.mdwn
new file mode 100644 (file)
index 0000000..551d476
--- /dev/null
@@ -0,0 +1,27 @@
+[[!meta title="Jon Dowland"]]
+I'm looking at ikiwiki both for my personal site but also as a
+team-documentation management system for a small-sized group of UNIX
+sysadmins.
+
+* my edits should appear either as 'Jon' (if I've used
+  [[tips/untrusted_git_push]]) or 'jmtd.net' (or once upon a time
+  'alcopop.org/me/openid/' or 'jondowland').
+* My [homepage](http://jmtd.net/) is powered by ikiwiki
+
+I gave a talk at the [UK UNIX User's Group](http://www.ukuug.org/) annual
+[Linux conference](http://www.ukuug.org/events/linux2008/) about organising
+system administrator documentation. Roughly a third of this talk was
+discussing IkiWiki in some technical detail and suggesting it as a good piece
+of software for this task.
+
+ * slides at <http://www.staff.ncl.ac.uk/jon.dowland/unix/docs/>.
+
+I am also working on some ikiwiki hacks:
+
+* an alternative approach to [[plugins/comments]] (see
+  [[todo/more flexible inline postform]] for one piece of the puzzle;
+  <http://dev.jmtd.net/comments/> for some investigation into making the post
+  form more integrated)
+* a system for [[forum/managing_todo_lists]] (see also
+  [[todo/interactive todo lists]] and <http://dev.jmtd.net/outliner/> for the
+  current WIP).
index e23804027d051c65552d18b3593b2b6ee28f384c..6119e7d4936a0fbe593c5d3d6ca6451d6c9fa65f 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Jonas Smedegaard"]]
+[[!meta title="Jonas Smedegaard"]]
 
 Jonas Smedegaard is a Debian developer, like joey. A big fan of this novel approach to wiki: serving as pages static!
 
diff --git a/doc/users/jondowland.mdwn b/doc/users/jondowland.mdwn
deleted file mode 100644 (file)
index d5aa6d0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-A new ikiwiki user, looking at ikiwiki both for his personal site but also as a team-documentation management system for a small-sized group of UNIX sysadmins.
-
-* (currently non-ikiwiki) Homepage: <http://alcopop.org/>
-* potential future (ikiwiki) Homepage: <http://jmtd.net/>
diff --git a/doc/users/josephturian.mdwn b/doc/users/josephturian.mdwn
new file mode 100644 (file)
index 0000000..5ad6829
--- /dev/null
@@ -0,0 +1,10 @@
+Joseph Turian is a scientist. You can email him at
+    lastname at gmail dot com
+
+* Academic: <http://www-etud.iro.umontreal.ca/~turian/>
+
+He hopes to set up ikiwiki and organize his thoughts.
+
+He also imagines adding wacky NLP and machine learning to ikiwiki.
+
+In more hazy dreams, he hopes that ikiwiki is someday ported to python.
index 9afadc5882061816817160484c9e60d3e272c371..f85c068c301efdb1aa09e637ace765d3a0690922 100644 (file)
@@ -1,10 +1,15 @@
-[[meta title="Josh Triplett"]]
+[[!meta title="Josh Triplett"]]
 
-Josh Triplett; `josh@{freedesktop.org,kernel.org,psas.pdx.edu}`.
+Email: `josh@{joshtriplett.org,freedesktop.org,kernel.org,psas.pdx.edu}`.
+
+[Josh Triplett's homepage](http://joshtriplett.org)
 
 Proud user of ikiwiki.
 
-Currently working on scripts to convert MoinMoin and TWiki wikis to ikiwikis
-backed by a git repository, including full history.
+Currently working on scripts to convert MoinMoin and TWiki wikis to
+ikiwikis backed by a git repository, including full history.
+Available from the following repositories, though not well-documented:
 
-> I've written about how I converted from Mediawiki here: <http://iki.u32.net/Mediawiki_Conversion/>  Are you ever going to release your scripts?  --[[sabr]]
+    git clone git://svcs.cs.pdx.edu/git/wiki2iki/moin2iki
+    git clone git://svcs.cs.pdx.edu/git/wiki2iki/html-wikiconverter
+    git clone git://svcs.cs.pdx.edu/git/wiki2iki/twiki
diff --git a/doc/users/jrblevin.mdwn b/doc/users/jrblevin.mdwn
new file mode 100644 (file)
index 0000000..4eb250b
--- /dev/null
@@ -0,0 +1 @@
+[[!meta redir=users/jasonblevins]]
diff --git a/doc/users/jwalzer.mdwn b/doc/users/jwalzer.mdwn
new file mode 100644 (file)
index 0000000..e66ad1a
--- /dev/null
@@ -0,0 +1,3 @@
+Jan Walzer started to look on ikiwiki just recently.
+
+Read [here](http://wa.lzer.net/wiki/ikiwiki/whyikiwiki/) why he uses ikiwiki.
index d818d8b9cfed77d3cf5cbc29843894a51cdc131c..7960b3b21524f21eac521240f9f190ae49baf619 100644 (file)
@@ -1,2 +1,2 @@
-[[meta title="Kyle MacLea"]]
+[[!meta title="Kyle MacLea"]]
 [Kyle MacLea](http://kitenet.net/~kyle) was an early adopter of **ikiwiki**.  He really likes it, especially for his [FamilyWiki](http://kitenet.net/~kyle/family/wiki) and [Emigration Registry](http://kitenet.net/~kyle/family/registry).
\ No newline at end of file
index 22e6b8b3efe2f580bef5fec3146334fdaa2a5503..c423703af194a62c15f61f922e3e22607c555abb 100644 (file)
@@ -5,5 +5,5 @@ My sites:
 
 I track this site with the following feed:
 
-[[inline pages="internal(recentchanges/change_*) and !author(http://madduck.net/)" 
+[[!inline pages="internal(recentchanges/change_*) and !author(http://madduck.net/)" 
 feedonly=yes atom=no]]
index 3cc75b9ee570e9798a024b1ce6945fb997224ed9..f59e9a1ae7b9cea3290a36aaef410c1404502e73 100644 (file)
@@ -1,3 +1,3 @@
-[[meta title="Marcelo E. Magallon"]]
+[[!meta title="Marcelo E. Magallon"]]
 
 Marcelo E. Magallon &lt;marcelo dot magallon in Google Mail&gt;
\ No newline at end of file
diff --git a/doc/users/neale.mdwn b/doc/users/neale.mdwn
new file mode 100644 (file)
index 0000000..5245c2c
--- /dev/null
@@ -0,0 +1,10 @@
+I used IkiWiki to supplant some custom journal software.  I like that it uses
+the filesystem, my intent is to make journal entries as future-proof as
+possible.  I'll probably start using it for generation of entire sites, soon.
+
+Things generated by IkiWiki with some fancypants stylesheets:
+
+* [woozle.org](http://woozle.org/)
+* [My page](http://woozle.org/~neale/)
+* [Amy's blog](http://woozle.org/~aim/blog/)
+* [Heidi's blog](http://woozle.org/~heidi/blog/)
diff --git a/doc/users/nolan.mdwn b/doc/users/nolan.mdwn
new file mode 100644 (file)
index 0000000..64b405e
--- /dev/null
@@ -0,0 +1 @@
+Hi, I'm Nolan. I'll add more later.
index e03cadbb5746f32532f489221efa1763489256df..627a9fdc302897f9dc63b97a6a691853c21799be 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Per Olofsson"]]
+[[!meta title="Per Olofsson"]]
 
 Per Olofsson
 
index bbb2bf1ecb2feef785ec3ffe6b3339c6a4fd8793..3f6fd39e8c13e8eb99e280edc8335e760898b15e 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Paweł Tęcza"]]
+[[!meta title="Paweł Tęcza"]]
 
 My name is Paweł Tęcza. Currently I work as mail system administrator,
 C/Perl programmer and computer projects designer at Warsaw University, Poland.
@@ -13,6 +13,9 @@ but now I rather prefer Ubuntu, because it has faster release cycle
 than Debian and I don't want to wait more then 1 year for new stable
 release.
 
-I'm also author of ikiwiki backports for Debian 'sarge'. You can find
-this and another my backports at
-[public GPA's Debian packages archive](http://gpa.net.icm.edu.pl/debian/).
+I'm also author of unofficial ikiwiki backports. In the past I was
+rebuilding ikiwiki source package for Debian Sarge and Ubuntu Gutsy.
+Now I do the same for Ubuntu Hardy. You can find this and another
+my backports at [public GPA's Ubuntu packages archive](http://gpa.net.icm.edu.pl/ubuntu/).
+
+I love using Ikiwiki and bug reporting ;)
index 8741c6f3688055b0ae3cfa4e8879b7ca3f2877cd..c5a1a2066e2c03ee431f335719a2159c7b2c734f 100644 (file)
@@ -1,4 +1,4 @@
-[[toc ]]
+[[!toc ]]
 
 ### My name
 
@@ -16,7 +16,7 @@ a wiki that doesn't suck.
 
 Thanks to [[madduck]], I track this site with the following feed:
 
-[[inline pages="internal(recentchanges/change_*) and !author(http://sabr.myopenid.com/)" 
+[[!inline pages="internal(recentchanges/change_*) and !author(http://sabr.myopenid.com/)" 
 feedonly=yes rss=no atom=yes]]
 
 ### Tests
diff --git a/doc/users/schmonz.mdwn b/doc/users/schmonz.mdwn
new file mode 100644 (file)
index 0000000..8273bdb
--- /dev/null
@@ -0,0 +1,3 @@
+[Amitai Schlair](http://www.columbia.edu/~ays2105/) recently discovered ikiwiki and finds himself using it for all sorts of things. His attempts at contributing:
+
+[[!map pages="link(users/schmonz) and plugins/* and !*/Discussion"]]
diff --git a/doc/users/seanh.mdwn b/doc/users/seanh.mdwn
new file mode 100644 (file)
index 0000000..d093c2f
--- /dev/null
@@ -0,0 +1 @@
+seanh is an ikiwiki user.
diff --git a/doc/users/simonraven.mdwn b/doc/users/simonraven.mdwn
new file mode 100644 (file)
index 0000000..5fc2471
--- /dev/null
@@ -0,0 +1,8 @@
+## personal/site info
+
+New ikiwiki site at my web site, blog, kisikew.org home site, for indigenews, and our indigenous-centric wiki (mostly East Coast/Woodlands area). Mediawiki stuff was imported successfully (as noted on this web site).
+
+## ikiwiki branch at github
+
+Maintain my own branch, partly to learn about VCS, git, ikiwiki, Debian packaging, and Perl. I don't recommend anyone pull from it, as I use third-party plugins included on this site that people may not want in a default installation of ikiwiki. This is why I don't push to Joey's -- so it's nothing personal, I just don't want to mess things up for other people, from my mistakes and stumbles.
+
diff --git a/doc/users/smcv.mdwn b/doc/users/smcv.mdwn
new file mode 100644 (file)
index 0000000..59d1aff
--- /dev/null
@@ -0,0 +1,10 @@
+Website: [pseudorandom.co.uk](http://www.pseudorandom.co.uk/)
+
+Blog: [smcv.pseudorandom.co.uk](http://smcv.pseudorandom.co.uk/)
+
+My repository containing ikiwiki branches:
+
+* gitweb: http://git.pseudorandom.co.uk/smcv/ikiwiki.git
+* anongit: git://git.pseudorandom.co.uk/git/smcv/ikiwiki.git
+
+Currently thinking about a [[users/smcv/gallery]] plugin.
diff --git a/doc/users/smcv/gallery.mdwn b/doc/users/smcv/gallery.mdwn
new file mode 100644 (file)
index 0000000..d80fc3b
--- /dev/null
@@ -0,0 +1,348 @@
+This plugin has now been implemented as [[plugins/contrib/album]]; this
+page has older thoughts about it.
+
+## Requirements
+
+This plugin formats a collection of images into a photo gallery,
+in the same way as many websites: good examples include the
+PHP application [Gallery](http://gallery.menalto.com/), Flickr,
+and Facebook's Photos "application".
+
+The web UI I'm trying to achieve consists of one
+[HTML page of thumbnails](http://www.pseudorandom.co.uk/2008/2008-03-08-panic-cell-gig/)
+as an entry point to the gallery, where each thumbnail links to
+[a "viewer" HTML page](http://www.pseudorandom.co.uk/2008/2008-03-08-panic-cell-gig/img_0068/)
+with a full size image, next/previous thumbnail links, and
+[[plugins/comments]].
+
+(The Summer of Code [[plugins/contrib/gallery]] plugin does the
+next/previous UI in Javascript using Lightbox, which means that
+individual photos can't be bookmarked in a meaningful way, and
+the best it can do as a fallback for non-Javascript browsers
+is to provide a direct link to the image.)
+
+Other features that would be good to have:
+
+* minimizing the number of separate operations needed to make a gallery -
+  editing one source file per gallery is acceptable, editing one
+  source file per photo is not
+
+* keeping photos outside source code control, for instance in an
+  underlay
+
+* assigning [[tags|ikiwiki/directive/tag]] to photos, providing a
+  superset of Facebook's "show tagged photos of this person" functionality
+
+* constructing galleries entirely via the web by uploading attachments
+
+* inserting grouping (section headings) within a gallery; as in the example
+  linked above, I'd like this to split up the thumbnails but not the
+  next/previous trail
+
+* rendering an `<object>/<embed>` arrangement to display videos, and possibly
+  thumbnailing them in the same way as totem-video-thumbnailer
+  (my camera can record short videos, so some of my web photo galleries
+  contain them)
+
+My plan is to have these directives:
+
+* \[[!gallery]] registers the page it's on as a gallery, and displays all
+  photos that are part of this gallery but not part of a \[[!gallerysection]]
+  (below).
+
+  All images (i.e. `*.png *.jpg *.gif`) that are attachments to the gallery page
+  or its subpages are considered to be part of the gallery.
+
+  Optional arguments:
+
+  * filter="[[ikiwiki/PageSpec]]": only consider images to be part of the
+    gallery if they also match this filter
+
+  * sort="date|filename": order in which to sort the images
+
+* \[[!gallerysection filter="[[ikiwiki/PageSpec]]"]] displays all photos in the
+  gallery that match the filter
+
+So,
+[the gallery I'm using as an example](http://www.pseudorandom.co.uk/2008/2008-03-08-panic-cell-gig/)
+could look something like this:
+
+    \[[!gallery]]
+    <!-- replaced with one uncategorized photo -->
+
+    # Gamarra
+
+    \[[!gallerysection filter="link(sometag)"]]
+    <!-- all the Gamarra photos -->
+
+    # Smokescreen
+
+    \[[!gallerysection filter="link(someothertag)"]]
+    <!-- all the Smokescreen photos -->
+
+    <!-- ... -->
+
+## Implementation ideas
+
+The next/previous part this plugin overlaps with [[todo/wikitrails]].
+
+A \[[!galleryimg]] directive to assign metadata to images might be necessary, so
+the gallery page can contain something like:
+
+    \[[!galleryimg p1010001.jpg title="..." caption="..." tags="foo"]]
+    \[[!galleryimg p1010002.jpg title="..." caption="..." tags="foo bar"]]
+
+However, allowing other pages to push in metadata like that will make
+dependency tracking difficult.
+
+Making the viewer pages could be rather tricky. Here are some options:
+"synthesize source pages for viewers" is the one I'm leaning towards at the
+moment.
+
+### Viewers' source page is the gallery
+
+One possibility is to write out the viewer pages as a side-effect of
+preprocessing the \[[!gallery]] directive. The proof-of-concept implementation
+below does this.  However, this does mean the viewer pages can't have tags or
+metadata of their own and can't be matched by [[pagespecs|ikiwiki/pagespec]] or
+[[wikilinks|ikiwiki/wikilink]].
+
+It might be possible to implement tagging by using \[[!galleryimg]] to assign
+the metadata to the *images* instead of their viewers; however, that would
+require hacking up both `IkiWiki::htmllink` and `IkiWiki::urlto` to redirect
+links to the image (e.g. from the \[[!map]] on a tag page) to become links to
+the viewer page.
+
+Modifications to the comments plugin would also be required, to make it allow
+comments written to `foo/bar/comment_1._comment` even though the page foo/bar
+does not really exist, and display comments on the viewer pages even though
+they're not real pages. (Writing comments to `foo/bar.jpg/*._comment` is not
+an option!)
+
+### Synthesize source pages for viewers
+
+(Edited to add: this is what [[plugins/contrib/album]] implements. --[[smcv]])
+
+Another is to synthesize source pages for the viewers. This means they can have
+tags and metadata, but trying to arrange for them to be scanned etc. correctly
+without needing another refresh run is somewhat terrifying.
+[[plugins/autoindex]] can safely create source pages because it runs in
+the refresh hook, but I don't really like the idea of a refresh hook that scans
+all source pages to see if they contain \[[!gallery]]...
+
+The photo galleries I have at the moment, like the Panic Cell example above,
+are made by using an external script to parse XML gallery descriptions (lists
+of image filenames, with metadata such as titles), and using this to write
+IkiWiki markup into a directory which is then used as an underlay. This is a
+hack, but it works. The use of XML is left over from a previous attempt at
+solving the same problem using Django.
+
+Perhaps a better approach would be to have a setupfile option that names a
+particular underlay directory (meeting the objective of not having large
+photos under source code control) and generates a source page for each file
+in that directory during the refresh hook. The source pages could be in the
+underlay until they are edited (e.g. tagged), at which point they would be
+copied into the source-code-controlled version in the usual way.
+
+> Coming back to this: a specialized web UI to mark attachments as part of
+> the gallery would make this easy too - you'd put the photos in the
+> underlay, then go to the CGI and say "add all". --[[smcv]]
+
+The synthetic source pages can be very simple, using the same trick as my
+[[plugins/comments]] plugin (a dedicated [[directive|ikiwiki/directives]]
+encapsulating everything the plugin needs). If the plugin automatically
+gathers information like file size, pixel size, date etc. from the images, then
+only the human-edited information and a filename reference need to be present
+in the source page; with some clever lookup rules based on the filename of
+the source page, not even the photo's filename is necessarily needed.
+
+> Coming back to this later: the clever lookup rules make dependency tracking
+> hard, though. --[[smcv]]
+
+    \[[!meta title="..."]]
+    \[[!meta date="..."]]
+    \[[!meta copyright="..."]]
+    \[[!tag ...]]
+
+    \[[!galleryimageviewer p1010001.jpg]]
+
+However, this would mean that editing tags and other metadata would require
+editing pages individually. Rather than trying to "fix" that, perhaps it would
+be better to have a special CGI interface for bulk tagging/metadata editing.
+This could even be combined with a bulk upload form (a reasonable number of
+file upload controls - maybe 20 - with metadata alongside each).
+
+Uploading multiple images is necessarily awkward due to restrictions placed on
+file upload controls by browsers for security reasons - sites like Facebook
+allow whole directories to be uploaded at the same time, but they achieve this
+by using a signed Java applet with privileged access to the user's filesystem.
+
+I've found that it's often useful to be able to force the creation time of
+photos (my camera's battery isn't very reliable, and it frequently decides that
+the date is 0000-00-00 00:00:00), so treating the \[[!meta date]] of the source
+page and the creation date of the photo as synonymous would be useful.
+
+### Images are the viewer's source - special filename extension
+
+Making the image be the source page (and generate HTML itself) would be
+possible, but I wouldn't want to generate a HTML viewer for every `.jpg` on a
+site, so either the images would have to have a special extension (awkward for
+uploads from Windows users) or the plugin would have to be able to change
+whether HTML was generated in some way (not currently possible).
+
+### Images are the viewer's source - alter `ispage()`
+
+It might be possible to hack up `ispage()` so some, but not all, images are
+considered to "be a page":
+
+* srcdir/not-a-photo.jpg → destdir/not-a-photo.jpg
+* srcdir/gallery/photo.jpg → destdir/gallery/photo/index.html
+
+Perhaps one way to do this would be for the photos to appear in a particular
+underlay directory, which would also fulfil the objective of having photos not
+be version-controlled:
+
+* srcdir/not-a-photo.jpg → destdir/not-a-photo.jpg
+* underlay/gallery/photo.jpg → destdir/gallery/photo/index.html
+
+## Proof-of-concept implementation of "viewers' source page is the gallery"
+
+    #!/usr/bin/perl
+    package IkiWiki::Plugin::gallery;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 2.00;
+    
+    sub import {
+       hook(type => "getsetup", id => "gallery",  call => \&getsetup);
+       hook(type => "checkconfig", id => "gallery", call => \&checkconfig);
+       hook(type => "preprocess", id => "gallery",
+               call => \&preprocess_gallery, scan => 1);
+       hook(type => "preprocess", id => "gallerysection",
+               call => \&preprocess_gallerysection, scan => 1);
+       hook(type => "preprocess", id => "galleryimg",
+               call => \&preprocess_galleryimg, scan => 1);
+    }
+    
+    sub getsetup () {
+       return
+               plugin => {
+                       safe => 1,
+                       rebuild => undef,
+               },
+    }
+    
+    sub checkconfig () {
+    }
+    
+    # page that is a gallery => array of images
+    my %galleries;
+    # page that is a gallery => array of filters
+    my %sections;
+    # page that is an image => page name of generated "viewer"
+    my %viewers;
+    
+    sub preprocess_gallery {
+       # \[[!gallery filter="!*/cover.jpg"]]
+       my %params=@_;
+    
+       my $subpage = qr/^\Q$params{page}\E\//;
+    
+       my @images;
+    
+       foreach my $page (keys %pagesources) {
+               # Reject anything not a subpage or attachment of this page
+               next unless $page =~ $subpage;
+    
+               # Reject non-images
+               # FIXME: hard-coded list of extensions
+               next unless $page =~ /\.(jpg|gif|png|mov)$/;
+    
+               # Reject according to the filter, if any
+               next if (exists $params{filter} &&
+                       !pagespec_match($page, $params{filter},
+                               location => $params{page}));
+    
+               # OK, we'll have that one
+               push @images, $page;
+    
+               my $viewername = $page;
+               $viewername =~ s/\.[^.]+$//;
+               $viewers{$page} = $viewername;
+    
+               my $filename = htmlpage($viewername);
+               will_render($params{page}, $filename);
+       }
+    
+       $galleries{$params{page}} = \@images;
+    
+       # If we're just scanning, don't bother producing output
+       return unless defined wantarray;
+    
+       # actually render the viewers
+       foreach my $img (@images) {
+               my $filename = htmlpage($viewers{$img});
+               debug("rendering image viewer $filename for $img");
+               writefile($filename, $config{destdir}, "# placeholder");
+       }
+    
+       # display a list of "loose" images (those that are in no section);
+       # this works because we collected the sections' filters during the
+       # scan stage
+    
+       my @loose = @images;
+    
+       foreach my $filter (@{$sections{$params{page}}}) {
+               my $_;
+               @loose = grep { !pagespec_match($_, $filter,
+                               location => $params{page}) } @loose;
+       }
+    
+       my $_;
+       my $ret = "<ul>\n";
+       foreach my $img (@loose) {
+               $ret .= "<li>";
+               $ret .= "<a href=\"" . urlto($viewers{$img}, $params{page});
+               $ret .= "\">$img</a></li>\n"
+       }
+       return "$ret</ul>\n";
+    }
+    
+    sub preprocess_gallerysection {
+       # \[[!gallerysection filter="friday/*"]]
+       my %params=@_;
+    
+       # remember the filter for this section so the "loose images" section
+       # won't include these images
+       push @{$sections{$params{page}}}, $params{filter};
+    
+       # If we're just scanning, don't bother producing output
+       return unless defined wantarray;
+    
+       # this relies on the fact that we ran preprocess_gallery once
+       # already, during the scan stage
+       my @images = @{$galleries{$params{page}}};
+       @images = grep { pagespec_match($_, $params{filter},
+                       location => $params{page}) } @images;
+    
+       my $_;
+       my $ret = "<ul>\n";
+       foreach my $img (@images) {
+               $ret .= "<li>";
+               $ret .= htmllink($params{page}, $params{destpage},
+                       $viewers{$img});
+               $ret .= "</li>";
+       }
+       return "$ret</ul>\n";
+    }
+    
+    sub preprocess_galleryimg {
+       # \[[!galleryimg p1010001.jpg title="" caption="" tags=""]]
+       my $file = $_[0];
+       my %params=@_;
+    
+       return "";
+    }
+    
+    1
diff --git a/doc/users/svend.mdwn b/doc/users/svend.mdwn
new file mode 100644 (file)
index 0000000..69d8358
--- /dev/null
@@ -0,0 +1,4 @@
+[[!meta title="Svend Sorensen"]]
+
+* [website](http://www.ciffer.net/~svend/)
+* [blog](http://www.ciffer.net/~svend/blog/)
index e9478ade2db7d41317b64c014f4093cf532a7be3..bb5cef6a668cdb34bca031d2539b3bc74acc0cf0 100644 (file)
@@ -1,17 +1,11 @@
-[[meta title="Thomas Schwinge"]]
+[[!meta title="Thomas Schwinge"]]
 # Thomas Schwinge
 
 <tschwinge@gnu.org>  
 <http://www.thomas.schwinge.homeip.net/>
 
-
-With respect to *[[ikiwiki]]* I'm currently working on...
-
-* setting it up for the [GNU Hurd's web pages](http://www.gnu.org/software/hurd/);
-* setting it up as a replacement for the GNU Hurd's previous wiki (TWiki): <http://bddebian.com/~wiki/>;
-
-... and all that while trying to preserve the previous content's history,
-which is stored in a CVS repository for the web pages and a RCS repository
-for the wiki.
-
-Read [About the TWiki to ikiwiki conversion](http://www.bddebian.com/~wiki/about_the_twiki_to_ikiwiki_conversion/).
+I have converted the [GNU Hurd](http://www.gnu.org/software/hurd/)'s previous
+web pages and previous wiki pages to a *[[ikiwiki]]* system; and all that while
+preserving the previous content's history, which was stored in a CVS repository
+for the HTML web pages and a TWiki RCS repository for the wiki; see
+<http://www.gnu.org/software/hurd/colophon.html>.
index 43404bf403f8b5382bd080cbe09a2a1e77a9736a..fe5d860b108eb4dc09bf80616e8970eb62bb184c 100644 (file)
@@ -1,4 +1,4 @@
-[[meta title="Victor Moral"]]
+[[!meta title="Victor Moral"]]
 
 I'm a spanish perl programmer and linux system administrator. 
 
diff --git a/doc/users/weakish.mdwn b/doc/users/weakish.mdwn
new file mode 100644 (file)
index 0000000..ccd5665
--- /dev/null
@@ -0,0 +1 @@
+email: weakish@gmail.com
diff --git a/doc/users/weakishjiang.mdwn b/doc/users/weakishjiang.mdwn
new file mode 100644 (file)
index 0000000..0cafb46
--- /dev/null
@@ -0,0 +1,4 @@
+[My blog](http://millenniumdark.blog.ubuntu.org.cn)
+
+> So, you're learning haskell. You know, I want to add support for haskell
+> external plugins to ikiwiki.. :-) --[[Joey]] 
diff --git a/doc/users/xma.mdwn b/doc/users/xma.mdwn
new file mode 100644 (file)
index 0000000..89f2ff7
--- /dev/null
@@ -0,0 +1,28 @@
+[[!meta title="Xavier Maillard"]]
+# Xavier Maillard
+
+I just started using [[ikiwiki]] for my own webspace at http://maillard.mobi/~xma/wiki
+
+I am learning how to effectively use it.
+
+Anyway, [[ikiwiki]] is really *awesome* !
+
+## More about me
+
+I am CLI user living in the linux console. More precisely, I live in an [[GNU_Emacs]] frame all day long. My main computer is an EeePC 901 running Slackware GNU/Linux 12.1. I do not have X installed (too lazy) but when in X, I am running an instance of [[CLFSWM]].
+
+## Contacting me
+
+Various channels to contact me:
+
+- mail: xma@gnu.org
+- jabber: xma01@jabber.fr
+- mobile: +33 621-964-362 (I only anwser to people I know though)
+
+Voila.
+
+## Plans
+
+I am planning to make a presentation of [[ikiwiki]]to my [local LUG](http://lolica.org) for our next montly meeting. Any help would be greatly appreciated.
+
+We are discussing to replace our old unmaintained (and unmaintainable) [SPIP](http://spip.net) website with a wiki. This is why I would like using ikiwiki ;)
diff --git a/doc/users/xma/discussion.mdwn b/doc/users/xma/discussion.mdwn
new file mode 100644 (file)
index 0000000..34adbf8
--- /dev/null
@@ -0,0 +1,18 @@
+How do you edit this wiki (I mean [ikiwiki]) without the web browser ? Is there a way to git clone/pull/push and thus to use our favorite [text editor](http://www.gnu.org/software/emacs) ? --[[xma]]
+
+> You can clone ikiwiki's [[git]] repo. I have not implemented a way to
+> allow users to push doc wiki only changesets anonymously, but you can
+> mails changesets to me. --[[Joey]]
+> > How can I send you the changesets ? (git command) --[[xma]]
+> > > `git-format-patch` --[[Joey]]
+
+> > > > Glad to hear I can mail changesets to you, since I wrote the [[todo/applydiff_plugin]] wishlist entry. --[[intrigeri]]
+
+> It would be nice to have a git recieve hook that
+> checked that a commit contained only changes to .mdwn or other allowed
+> extensions.. if someone writes up a good one, I'd be willing to deploy it
+> for ikiwiki. --[[Joey]]
+
+> > I'll think about it. It may solve some of my offline-being issues. --[[intrigeri]]
+
+>>>> Now developed! --[[Joey]]
index e088561581b580bfa11fe4eb4e2dbbd391df2d34..5f5cbbff927476d1ca85d74657d26f9560d8c5e4 100644 (file)
@@ -17,19 +17,13 @@ use IkiWiki::Setup::Standard {
        cgiurl => 'ikiwiki.cgi',
        rcs => "",
 
-       wrappers => [
-               {
-                       # The cgi wrapper.
-                       cgi => 1,
-                       # The wrapper must be put in ~/.ikiwiki/wrappers/, since
-                       # ikiwiki-w3m.cgi only looks in this one location.
-                       # The wrapper can be given any name as long as it's 
-                       # in that directory.
-                       wrapper => "$ENV{HOME}/.ikiwiki/wrappers/ikiwiki.cgi",
-                       wrappermode => "0755",
-               },
-       ],
-       
+       # The wrapper must be put in ~/.ikiwiki/wrappers/, since
+       # ikiwiki-w3m.cgi only looks in this one location.
+       # The wrapper can be given any name as long as it's 
+       # in that directory.
+       cgi_wrapper => "$ENV{HOME}/.ikiwiki/wrappers/ikiwiki.cgi",
+       cgi_wrappermode => "0755",
+
        add_plugins => [qw{anonok}],
        rss => 1,
        atom => 1,
index c8f43d08e25d767be8396a6998545b2757c7d8b6..a3bfe1098340f0374e839b0a8a95ee3e637542bc 100644 (file)
Binary files a/doc/wikiicons/openidlogin-bg.gif and b/doc/wikiicons/openidlogin-bg.gif differ
diff --git a/doc/wikiicons/search-bg.gif b/doc/wikiicons/search-bg.gif
new file mode 100644 (file)
index 0000000..02f9da4
Binary files /dev/null and b/doc/wikiicons/search-bg.gif differ
index b03fc10a1bd7f5f288715bc8417145a4e5b80b1f..6c0480cea0630d2183efea5435d81204f8bd0cc1 100644 (file)
@@ -14,13 +14,14 @@ located in /usr/share/ikiwiki/templates by default.
 * `change.tmpl` - Used to create a page describing a change made to the wiki.
 * `passwordmail.tmpl` - Not a html template, this is used to
   generate a mail with an url the user can use to reset their password.
-* `rsspage.tmpl` - Used for generating rss feeds for [[blogs|ikiwiki/blog]].
+* `rsspage.tmpl` - Used for generating rss feeds for [[blogs|blog]].
 * `rssitem.tmpl` - Used for generating individual items on rss feeds.
 * `atompage.tmpl` - Used for generating atom feeds for blogs.
 * `atomitem.tmpl` - Used for generating individual items on atom feeds.
 * `inlinepage.tmpl` - Used for adding a page inline in a blog
   page.
 * `archivepage.tmpl` - Used for listing a page in a blog archive page.
+* `microblog.tmpl` - Used for showing a microblogging post inline.
 * `blogpost.tmpl` - Used for a form to add a post to a blog (and a rss/atom links)
 * `feedlink.tmpl` - Used to add rss/atom links if blogpost.tmpl is not used.
 * `aggregatepost.tmpl` - Used by the [[plugins/aggregate]] plugin to create
@@ -29,6 +30,14 @@ located in /usr/share/ikiwiki/templates by default.
   form to wiki pages.
 * `searchquery.tmpl` - This is an omega template, used by the
   [[plugins/search]] plugin.
+* `comment.tmpl` - This template is used to display a comment
+  by the [[plugins/comments]] plugin.
+* `editcomment.tmpl` - This template is the comment post form for the
+  [[plugins/comments]] plugin.
+* `commentmoderation.tmpl` - This template is used to produce the comment
+  moderation form.
+* `recentchanges.tmpl` - This template is used for listing a change
+  on the RecentChanges page.
 
 The [[plugins/pagetemplate]] plugin can allow individual pages to use a
 different template than `page.tmpl`.
diff --git a/doc/wikitemplates/discussion.mdwn b/doc/wikitemplates/discussion.mdwn
new file mode 100644 (file)
index 0000000..f97444e
--- /dev/null
@@ -0,0 +1,46 @@
+## Place for local templates
+Where does one put any locally modified templates for an individual ikiwiki? --Ivan Z.
+
+> You can put them whereever you like; the `templatedir` controls
+> where ikiwiki looks for them. --[[Joey]] 
+
+Thank you for your response! My question arose out of my intention to make
+custom templates for a wiki--specifically suited for the kind of  content
+it will have--so, that would mean I would want to distribute them through
+git together with other content of the wiki. So, for this case the
+separation of conceptually ONE thing (the content, the templates, and the
+config option which orders to use these templates) into THREE separate
+files/repos (the main content repo, the repo with templates, and the config
+file) is not convenient: instead of distributing a single repo, I have to
+tell people to take three things if they want to replicate this wiki. How
+would you solve this inconvenience? Perhaps, a default location of the
+templates *inside* the source repo would do?--Ivan Z.
+
+> I would avoid putting the templates in a subdirectory of the ikiwiki srcdir.
+> (I'd also avoid putting the ikiwiki setup file there.)
+> While it's safe to do either in some cases, there are configurations where
+> it's unsafe. For example, a malicious user could use attachment handling to
+> replace those files with their own, bad versions.
+> 
+> So, two ideas for where to put the templatedir and ikiwiki setup. 
+
+> * The easiest option is to put your wiki content in a subdirectory
+>   ("wiki", say) and point `srcdir` at that.
+>   then you can have another subdirectory for the wikitemplates,
+>   and put the setup file at the top.
+> * Another option if using git would be to have a separate branch,
+>   in the same git repository, that holds wikitemplates and the setup file.
+>   Then you check out the repository once to make the `srcdir` available,
+>   and have a second checkout, of the other branch, to make the other stuff
+>   available.
+> 
+> Note that with either of these methods, you have to watch out if
+> giving other direct commit access to the repository. They could
+> still edit the setup file and templates, so only trusted users should
+> be given access. (It is, however, perfectly safe to let people edit
+> the wiki via the web, and is even safe to configure
+> [[tips/untrusted_git_push]] to such a repository.) --[[Joey]]
+
+Thanks, that's a nice and simple idea: to have a subdirectory! I'll try it. --Ivan Z.
+
+A [[!taglink wish|wishlist]]: the ikiwiki program could be improved so that it follows the same logic as git in looking for its config: it could ascend directories until it finds an `.ikiwiki/` directory with `.ikiwiki/setup` and then uses that configuration. Now I'm tired to always type `ikiwiki --setup path/to/the/setup --refresh` when working in my working clone of the sources; I'd like to simply type `ikiwiki` instead, and let it find the setup file. The default location to look for templates could also be made to be a sibling of the setup file: `.ikiwiki/templates/`. --Ivan Z.
index 6c3c601b19863f0f2e6d1ddc401484266ea75f32..6275037606bb7bf67031359511db794b99a75298 100644 (file)
@@ -1,6 +1,6 @@
-These [[todo]] items constitute a wishlist of all kinds of features and
+These [[todo]] tagged 'wishlist' encompass all kinds of features and
 improvements people would like to see in ikiwiki. Good patches for any of
 these will likely be accepted.
 
-[[inline pages="todo/* and !todo/done and !link(todo/done) and
+[[!inline pages="todo/* and !todo/done and !link(todo/done) and
 link(wishlist) and !link(patch) and !todo/*/*" archive=yes show=0]]
index 0a6a86678e7591f4c3178cbe0e8c5e2236ac3148..52421e50111ff7045504c442ffde3c7b3b1a5dc5 100644 (file)
@@ -6,14 +6,15 @@ use IkiWiki::Setup::Standard {
        srcdir => "doc",
        destdir => "html",
        templatedir => "templates",
+       underlaydirbase => "underlays",
        underlaydir => "underlays/basewiki",
-       wrappers => [],
        discussion => 0,
-       exclude => qr/\/discussion/,
+       exclude => qr/\/discussion|bugs\/*|todo\/*/,
        locale => '',
        verbose => 1,
        syslog => 0,
        userdir => "users",
        usedirs => 0,
+       prefix_directives => 1,
        add_plugins => [qw{goodstuff version haiku polygen fortune}],
 }
diff --git a/gitremotes b/gitremotes
new file mode 100755 (executable)
index 0000000..91bf2fe
--- /dev/null
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+# Parses list of remotes in doc/git.mdwn, configures git to use them
+# all, and fetches updates from them.
+
+my $error=0;
+
+open (IN, "doc/git.mdwn") || die "doc/git.mdwn: $!";
+while (<IN>) {
+       if (/^\*\s+\[?\[?(\w+)(?:\|\w+)?\]?\]?\s+`([^>]+)`/) {
+               # note that the remote name has to be a simple word (\w)
+               # for security/sanity reasons
+               my $remote=$1;
+               my $url=$2;
+
+               # check configured url to deal with it changing
+               my $info=`git remote show -n $remote`;
+               my ($oldurl)=$info=~/URL: (.*)/m;
+               if ($oldurl ne $url) {
+                       system("git remote rm $remote 2>/dev/null");
+                       $error |= system("git", "remote", "add", "-f", $remote, $url);
+               }
+               else {
+                       $error |= system("git", "fetch", $remote);
+               }
+       }
+}
+close IN;
+
+exit $error;
index d249e5e754c00a36ee29b6b6d667017c6b71bdda..7f82e717715ef8f446f941f36a154757d6f106ec 100755 (executable)
@@ -4,9 +4,9 @@ set -e
 rcs="$1"
 srcdir="$2"
 repository="$3"
-       
+
 usage () {
-       echo "usage: ikiwiki-makerepo svn|git srcdir repository" >&2
+       echo "usage: ikiwiki-makerepo svn|git|monotone|darcs srcdir repository" >&2
        echo "       ikiwiki-makerepo bzr|mercurial srcdir" >&2
        exit 1
 }
@@ -21,11 +21,15 @@ if [ ! -d "$srcdir" ]; then
 fi
 
 if [ "$rcs" != mercurial ] && [ "$rcs" != bzr ]; then
+       if [ -z "$repository" ]; then
+               echo "you need to specify both a srcdir and a repository for $rcs" >&2
+               usage
+       fi
        if [ -e "$repository" ]; then
                echo "repository $repository already exists, aborting" >&2 
                exit 1
        fi
-       repository="$(perl -e 'use Cwd q{abs_path}; $r=shift; $r=~s/\/*$//; print abs_path($r)' $repository)"
+       repository="$(perl -e 'use Cwd; $r=shift; $r=getcwd.q{/}.$r if $r!~m!^/!; print $r' "$repository")"
        if [ -z "$repository" ]; then
                echo "internal error finding repository abs_path" >&2
                exit 1
@@ -71,7 +75,7 @@ mercurial)
        hg init "$srcdir"
        cd "$srcdir"
        echo .ikiwiki > .hgignore
-       hg add * .hgignore
+       hg add
        hg commit -m "initial import"
        echo "Directory $srcdir is now set up as a mercurial repository"
 ;;
@@ -79,10 +83,68 @@ bzr)
        bzr init "$srcdir"
        cd "$srcdir"
        echo .ikiwiki > .bzrignore
-       bzr add * .bzrignore
+       bzr add
        bzr commit -m "initial import"
        echo "Directory $srcdir is now set up as a bzr repository"
 ;;
+monotone)
+       if [ -e "$srcdir/_MTN" ]; then
+               echo "$srcdir already seems to be a monotone working copy" >&2
+               exit 1
+       fi
+
+       mkdir -p "$(dirname "$repository")"
+       mtn db init -d "$repository"
+
+       cleaned_srcdir=$(basename "$srcdir" | tr -s "[:space:]" "_" | sed 's/_$//g')
+       reverse_hostname=$( (hostname -f 2>/dev/null || hostname) |\
+               tr  "." "\n" | ( tac 2>/dev/null || tail -r ) | tr "\n" "." )
+       branch_name="$reverse_hostname$cleaned_srcdir"
+       mtn setup -d "$repository" -b "$branch_name" "$srcdir"
+
+       cd "$srcdir"
+       echo \.ikiwiki$ > .mtn-ignore
+       mtn add -R .
+       # this expects that you already have a working mtn environment
+       # with a default key floating around...
+       mtn ci -m "initial import"
+       echo "Directory $srcdir is now set up as a monotone repository"
+       echo ""
+       echo "Note: If your monotone key has a passphrase, you need to configure"
+       echo "monotone to automatically use it. Otherwise, web commits to ikiwiki"
+       echo "will fail."
+       echo ""
+       echo "You can create a $srcdir/_MTN/monotonerc"
+       echo "containing the passphrase:"
+       echo ""
+       echo "function get_passphrase (branchname)"
+       echo '    return "passphrasehere"'
+       echo "end"
+;;
+darcs)
+       if [ -e "$srcdir/_darcs" ]; then
+               echo "$srcdir already seems to be a darcs repository" >&2
+               exit 1
+       fi
+
+       mkdir -p "$repository"
+       (cd "$repository" && darcs initialize)
+
+       mkdir -p "$srcdir"
+       cd "$srcdir"
+       darcs initialize
+       echo .ikiwiki >> _darcs/prefs/boring
+       darcs record -a -l -q -m "initial import"
+       darcs pull -a -q "$repository"
+       darcs push -a -q "$repository"
+       echo "Directory $srcdir is now a branch of darcs repo $repository"
+
+       # set up master repo's apply hook and tell user to adjust it if desired
+       darcsdefaults="$repository/_darcs/prefs/defaults"
+       echo "Preconfiguring apply hook in $darcsdefaults - adjust as desired!"
+       echo "apply posthook $repository/_darcs/ikiwiki-wrapper" >> "$darcsdefaults"
+       echo "apply run-posthook" >> "$darcsdefaults"
+;;
 *)
        echo "Unsupported revision control system $rcs" >&2
        usage
index e02c3aaedceb0a206a920c166600332d4eeac3c0..8a20cf655f021b328eef5afe509a75908f202d2a 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -i
+#!/usr/bin/perl
 use warnings;
 use strict;
 use IkiWiki;
@@ -42,20 +42,30 @@ sub handle_directive {
 }
 
 sub prefix_directives {
-       $/=undef; # process whole files at once
-       
-       while (<>) {
-               s{$regex}{handle_directive($1, $2, $3, $4)}eg;
-               print;
+       loadsetup(shift);
+
+       IkiWiki::loadplugins();
+       IkiWiki::checkconfig();
+       IkiWiki::loadindex();
+
+       if (! %pagesources) {
+               error "ikiwiki has not built this wiki yet, cannot transition";
+       }
+
+       foreach my $page (values %pagesources) {
+               next unless defined pagetype($page) &&
+                           -f $config{srcdir}."/".$page;
+               my $content=readfile($config{srcdir}."/".$page);
+               my $oldcontent=$content;
+               $content=~s{$regex}{handle_directive($1, $2, $3, $4)}eg;
+               if ($oldcontent ne $content) {
+                       writefile($page, $config{srcdir}, $content);
+               }
        }
 }
 
 sub indexdb {
-       $config{wikistatedir}=shift()."/.ikiwiki";
-
-       if (! defined $config{wikistatedir}) {
-               usage();                
-       }
+       setstatedir(shift);
 
        # Note: No lockwiki here because ikiwiki already locks it
        # before calling this.  
@@ -74,12 +84,8 @@ sub indexdb {
 }
 
 sub hashpassword {
-       $config{wikistatedir}=shift()."/.ikiwiki";
+       setstatedir(shift);
 
-       if (! defined $config{wikistatedir}) {
-               usage();                
-       }
-       
        eval q{use IkiWiki::UserInfo};
        eval q{use Authen::Passphrase::BlowfishCrypt};
        if ($@) {
@@ -99,12 +105,141 @@ sub hashpassword {
        }
 }
 
+sub aggregateinternal {
+       loadsetup(shift);
+       require IkiWiki::Plugin::aggregate;
+       IkiWiki::checkconfig();
+       IkiWiki::Plugin::aggregate::migrate_to_internal();
+}
+
+sub setupformat {
+       my $setup=shift;
+
+       loadsetup($setup);
+       IkiWiki::checkconfig();
+       
+       # unpack old-format wrappers setting into new fields
+       my $cgi_seen=0;
+       my $rcs_seen=0;
+       foreach my $wrapper (@{$config{wrappers}}) {
+               if ($wrapper->{cgi}) {
+                       if ($cgi_seen) {
+                               die "don't know what to do with second cgi wrapper ".$wrapper->{wrapper}."\n";
+                       }
+                       $cgi_seen++;
+                       print "setting cgi_wrapper to ".$wrapper->{wrapper}."\n";
+                       $config{cgi_wrapper}=$wrapper->{wrapper};
+                       $config{cgi_wrappermode}=$wrapper->{wrappermode}
+                               if exists $wrapper->{wrappermode};
+               }
+               elsif ($config{rcs}) {
+                       if ($rcs_seen) {
+                               die "don't know what to do with second rcs wrapper ".$wrapper->{wrapper}."\n";
+                       }
+                       $rcs_seen++;
+                       print "setting $config{rcs}_wrapper to ".$wrapper->{wrapper}."\n";
+                       $config{$config{rcs}."_wrapper"}=$wrapper->{wrapper};
+                       $config{$config{rcs}."_wrappermode"}=$wrapper->{wrappermode}
+                               if exists $wrapper->{wrappermode};
+               }
+               else {
+                       die "don't know what to do with wrapper ".$wrapper->{wrapper}."\n";
+               }
+       }
+
+       IkiWiki::Setup::dump($setup);
+}
+
+sub moveprefs {
+       my $setup=shift;
+
+       loadsetup($setup);
+       IkiWiki::checkconfig();
+
+       eval q{use IkiWiki::UserInfo};
+       error $@ if $@;
+
+       foreach my $field (qw{allowed_attachments locked_pages}) {
+               my $orig=$config{$field};
+               foreach my $admin (@{$config{adminuser}}) {
+                       my $a=IkiWiki::userinfo_get($admin, $field);
+                       if (defined $a && length $a &&
+                           # might already have been moved
+                           (! defined $orig || $a ne $orig)) {
+                               if (defined $config{$field} &&
+                                   length $config{$field}) {
+                                       $config{$field}=IkiWiki::pagespec_merge($config{$field}, $a);
+                               }
+                               else {
+                                       $config{$field}=$a;
+                               }
+                       }
+               }
+       }
+
+       my %banned=map { $_ => 1 } @{$config{banned_users}}, IkiWiki::get_banned_users();
+       $config{banned_users}=[sort keys %banned];
+
+       IkiWiki::Setup::dump($setup);
+}
+
+sub deduplinks {
+       loadsetup(shift);
+       IkiWiki::loadplugins();
+       IkiWiki::checkconfig();
+       IkiWiki::loadindex();
+       foreach my $page (keys %links) {
+               my %l;
+               $l{$_}=1 foreach @{$links{$page}};
+               $links{$page}=[keys %l]
+       }
+       IkiWiki::saveindex();
+}
+
+sub setstatedir {
+       my $dirorsetup=shift;
+
+       if (! defined $dirorsetup) {
+               usage();                
+       }
+
+       if (-d $dirorsetup) {
+               $config{wikistatedir}=$dirorsetup."/.ikiwiki";
+       }
+       elsif (-f $dirorsetup) {
+               loadsetup($dirorsetup);
+       }
+       else {
+               error("ikiwiki-transition: $dirorsetup does not exist");
+       }
+
+       if (! -d $config{wikistatedir}) {
+               error("ikiwiki-transition: $config{wikistatedir} does not exist");
+       }
+}
+       
+sub loadsetup {
+       my $setup=shift;
+       if (! defined $setup) {
+               usage();
+       }
+
+       require IkiWiki::Setup;
+
+       %config = IkiWiki::defaultconfig();
+       IkiWiki::Setup::load($setup);
+}
+
 sub usage {
        print STDERR "Usage: ikiwiki-transition type ...\n";
        print STDERR "Currently supported transition subcommands:\n";
-       print STDERR "  prefix_directives file\n";
-       print STDERR "  indexdb srcdir\n";
-       print STDERR "  hashpassword srcdir\n";
+       print STDERR "\tprefix_directives setupfile ...\n";
+       print STDERR "\taggregateinternal setupfile\n";
+       print STDERR "\tsetupformat setupfile\n";
+       print STDERR "\tmoveprefs setupfile\n";
+       print STDERR "\thashpassword setupfile|srcdir\n";
+       print STDERR "\tindexdb setupfile|srcdir\n";
+       print STDERR "\tdeduplinks setupfile\n";
        exit 1;
 }
 
@@ -114,12 +249,24 @@ my $mode=shift;
 if ($mode eq 'prefix_directives') {
        prefix_directives(@ARGV);
 }
-if ($mode eq 'hashpassword') {
+elsif ($mode eq 'hashpassword') {
        hashpassword(@ARGV);
 }
 elsif ($mode eq 'indexdb') {
        indexdb(@ARGV);
 }
+elsif ($mode eq 'aggregateinternal') {
+       aggregateinternal(@ARGV);
+}
+elsif ($mode eq 'setupformat') {
+       setupformat(@ARGV);
+}
+elsif ($mode eq 'moveprefs') {
+       moveprefs(@ARGV);
+}
+elsif ($mode eq 'deduplinks') {
+       deduplinks(@ARGV);
+}
 else {
        usage();
 }
@@ -152,7 +299,7 @@ sub oldloadindex {
                        $pagemtime{$page}=$items{mtime}[0];
                        $oldlinks{$page}=[@{$items{link}}];
                        $links{$page}=[@{$items{link}}];
-                       $depends{$page}=$items{depends}[0] if exists $items{depends};
+                       $depends{$page}={ $items{depends}[0] => 1 } if exists $items{depends};
                        $destsources{$_}=$page foreach @{$items{dest}};
                        $renderedfiles{$page}=[@{$items{dest}}];
                        $pagecase{lc $page}=$page;
@@ -177,3 +324,25 @@ sub oldloadindex {
        
        return close($in);
 }
+
+# Used to be in IkiWiki/UserInfo, but only used here now.
+sub get_banned_users () {
+       my @ret;
+       my $userinfo=userinfo_retrieve();
+       foreach my $user (keys %{$userinfo}) {
+               push @ret, $user if $userinfo->{$user}->{banned};
+       }
+       return @ret;
+}
+
+# Used to be in IkiWiki, but only used here (to migrate admin prefs into the
+# setup file) now.
+sub pagespec_merge ($$) {
+       my $a=shift;
+       my $b=shift;
+
+       return $a if $a eq $b;
+       return "($a) or ($b)";
+}
+
+1
index 0f3f0bcc6497f2b6f6b73cf6821f01847bb6925c..a6425f011c6a7e04c281cdfe8f70094d302818e5 100755 (executable)
@@ -5,6 +5,8 @@ use warnings;
 use strict;
 use English;
 
+my $remove=(@ARGV && $ARGV[0] eq '-r');
+
 my $username=getpwuid($REAL_USER_ID);
 if (! defined $username || ! length $username) {
        die "unable to determine user name for UID $REAL_USER_ID\n";
@@ -15,7 +17,8 @@ if (! -e $wikilist) {
        die "$wikilist does not exist\n";
 }
 
-my $removed=0;
+my $changed=0;
+my $seen=0;
 my @lines;
 open (my $list, "<$wikilist") || die "read $wikilist: $!";
 while (<$list>) {
@@ -23,7 +26,10 @@ while (<$list>) {
        if (/^\s*([^\s]+)\s*$/) {
                my $user=$1;
                if ($user eq $username) {
-                       $removed=1;             
+                       if (! $remove) {
+                               $seen=1;
+                               push @lines, $_;
+                       }
                }
                else {
                        push @lines, $_;
@@ -33,16 +39,24 @@ while (<$list>) {
                push @lines, $_;
        }
 }
-close $list || die "error reading $list: $!";
-open ($list, ">$wikilist") || die "write $wikilist: $!";
-foreach (@lines) {
-       print $list "$_\n";
+if (! $seen && ! $remove) {
+       push @lines, $username;
+       $changed=1;
 }
-if ($removed) {
-       print "removed user $username from $wikilist\n";
+if ($changed) {
+       close $list || die "ikiwiki-update-wikilist: error reading $list: $!\n";
+       open ($list, ">$wikilist") || die "ikiwiki-update-wikilist: cannot write to $wikilist\n";
+       foreach (@lines) {
+               print $list "$_\n";
+       }
+       if ($remove) {
+               print "ikiwiki-update-wikilist: removed user $username from $wikilist\n";
+       }
+       else {
+               print "ikiwiki-update-wikilist: added user $username to $wikilist\n";
+       }
+       close $list || die "ikiwiki-update-wikilist: error writing $wikilist: $!\n";
 }
 else {
-       print $list "$username\n";
-       print "added user $username to $wikilist\n";
+       print "ikiwiki-update-wikilist: no changes need to be made\n";
 }
-close $list || die "error writing $list: $!";
index e0a59182422ae0d2aaa1b69d15fa3463f144d9c8..4e9b812f852cb4b9805c51d7af6c0d0576d8a976 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -T
+#!/usr/bin/perl
 $ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
 delete @ENV{qw{IFS CDPATH ENV BASH_ENV}};
 
@@ -9,17 +9,29 @@ use strict;
 use lib '.'; # For use in nonstandard directory, munged by Makefile.
 use IkiWiki;
 
-sub usage () { #{{{
-       die gettext("usage: ikiwiki [options] source dest"), "\n";
-} #}}}
+sub usage () {
+       die gettext("usage: ikiwiki [options] source dest"), "\n",
+           gettext("       ikiwiki --setup configfile"), "\n";
+}
 
-sub getconfig () { #{{{
+sub getconfig () {
        if (! exists $ENV{WRAPPED_OPTIONS}) {
                %config=defaultconfig();
                eval q{use Getopt::Long};
                Getopt::Long::Configure('pass_through');
                GetOptions(
-                       "setup|s=s" => \$config{setup},
+                       "setup|s=s" => sub {
+                               require IkiWiki::Setup;
+                               my $verbose=$config{verbose};
+                               my $syslog=$config{syslog};
+                               IkiWiki::Setup::load($_[1]);
+                               $config{setupverbose}=$config{verbose};
+                               $config{setupsyslog}=$config{syslog};
+                               $config{verbose}=$verbose || $config{setupverbose};
+                               $config{syslog}=$syslog;
+                               $config{setup}=1;
+                       },
+                       "dumpsetup|s=s" => \$config{dumpsetup},
                        "wikiname=s" => \$config{wikiname},
                        "verbose|v!" => \$config{verbose},
                        "syslog!" => \$config{syslog},
@@ -27,7 +39,8 @@ sub getconfig () { #{{{
                        "refresh!" => \$config{refresh},
                        "post-commit" => \$config{post_commit},
                        "render=s" => \$config{render},
-                       "wrappers!" => \$config{wrappers},
+                       "wrappers!" => \$config{genwrappers},
+                       "wrappergroup=s" => \$config{wrappergroup},
                        "usedirs!" => \$config{usedirs},
                        "prefix-directives!" => \$config{prefix_directives},
                        "getctime" => \$config{getctime},
@@ -45,7 +58,6 @@ sub getconfig () { #{{{
                        "adminemail=s" => \$config{adminemail},
                        "timeformat=s" => \$config{timeformat},
                        "sslcookie!" => \$config{sslcookie},
-                       "httpauth!" => \$config{httpauth},
                        "userdir=s" => \$config{userdir},
                        "htmlext=s" => \$config{htmlext},
                        "libdir=s" => \$config{libdir},
@@ -68,14 +80,11 @@ sub getconfig () { #{{{
                                $config{wrappermode}=possibly_foolish_untaint($_[1])
                        },
                        "plugin=s@" => sub {
-                               push @{$config{plugin}}, $_[1];
+                               push @{$config{add_plugins}}, $_[1];
                        },
                        "disable-plugin=s@" => sub {
                                push @{$config{disable_plugins}}, $_[1];
                        },
-                       "pingurl=s" => sub {
-                               push @{$config{pingurl}}, $_[1];
-                       },
                        "set=s" => sub {
                                my ($var, $val)=split('=', $_[1], 2);
                                if (! defined $var || ! defined $val) {
@@ -87,14 +96,19 @@ sub getconfig () { #{{{
                                print "ikiwiki version $IkiWiki::version\n";
                                exit;
                        },
+                       "help|h" => sub { $SIG{__WARN__}=sub {}; die },
                ) || usage();
 
-               if (! $config{setup} && ! $config{render}) {
+               if (! $config{setup}) {
                        loadplugins();
-                       usage() unless @ARGV == 2;
-                       $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
-                       $config{destdir} = possibly_foolish_untaint(shift @ARGV);
-                       checkconfig();
+                       if (@ARGV == 2) {
+                               $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
+                               $config{destdir} = possibly_foolish_untaint(shift @ARGV);
+                               checkconfig();
+                       }
+                       else {
+                               usage() unless $config{dumpsetup};
+                       }
                }
        }
        else {
@@ -104,17 +118,58 @@ sub getconfig () { #{{{
                if ($@) {
                        error("WRAPPED_OPTIONS: $@");
                }
+               delete $ENV{WRAPPED_OPTIONS};
+
                loadplugins();
                checkconfig();
        }
-} #}}}
+}
 
-sub main () { #{{{
+sub main () {
        getconfig();
        
        if ($config{setup}) {
+               delete $config{setup};
+               loadplugins();
+               checkconfig();
+
+               if (@{$config{wrappers}} && 
+                   ! $config{render} && ! $config{dumpsetup} &&
+                   ((! $config{refresh} && ! $config{post_commit})
+                    || $config{genwrappers})) {
+                       debug(gettext("generating wrappers.."));
+                       require IkiWiki::Wrapper;
+                       my %origconfig=(%config);
+                       foreach my $wrapper (@{$config{wrappers}}) {
+                               %config=(%origconfig, %{$wrapper});
+                               $config{verbose}=$config{setupverbose}
+                                       if exists $config{setupverbose};
+                               $config{syslog}=$config{setupsyslog}
+                                       if exists $config{setupsyslog};
+                               delete @config{qw(setupsyslog setupverbose wrappers genwrappers rebuild)};
+                               checkconfig();
+                               if (! $config{cgi} && ! $config{post_commit} &&
+                                   ! $config{test_receive}) {
+                                       $config{post_commit}=1;
+                               }
+                               gen_wrapper();
+                       }
+                       %config=(%origconfig);
+               }
+               
+               # setup implies a wiki rebuild by default
+               if (! $config{refresh} && ! $config{render} &&
+                   ! $config{post_commit}) {
+                       $config{rebuild}=1;
+               }
+       }
+
+       if ($config{dumpsetup}) {
+               $config{srcdir}="" if ! defined $config{srcdir};
+               $config{destdir}="" if ! defined $config{destdir};
+               $config{syslog}=1 if $config{setupsyslog};
                require IkiWiki::Setup;
-               setup();
+               IkiWiki::Setup::dump($config{dumpsetup});
        }
        elsif ($config{wrapper}) {
                lockwiki();
@@ -123,7 +178,10 @@ sub main () { #{{{
        }
        elsif ($config{cgi}) {
                require IkiWiki::CGI;
-               cgi();
+               eval {cgi()};
+               if ($@) {
+                       cgierror($@);
+               }
        }
        elsif ($config{render}) {
                require IkiWiki::Render;
@@ -132,14 +190,25 @@ sub main () { #{{{
        elsif ($config{post_commit} && ! commit_hook_enabled()) {
                # do nothing
        }
+       elsif ($config{test_receive}) {
+               require IkiWiki::Receive;
+               IkiWiki::Receive::test();
+       }
        else {
+               if ($config{rebuild}) {
+                       debug(gettext("rebuilding wiki.."));
+               }
+               else {
+                       debug(gettext("refreshing wiki.."));
+               }
                lockwiki();
                loadindex();
                require IkiWiki::Render;
                rcs_update();
                refresh();
                saveindex();
+               debug(gettext("done"));
        }
-} #}}}
+}
 
 main;
index fa93e672d86f24c1e253d20717e4c09b19109be1..be7aba8b929807db3a6b56a6846e7d34b3c79a25 100755 (executable)
@@ -101,16 +101,15 @@ sub import {
        # stage of ikiwiki.
        rpc_call("hook", type => "preprocess", id => "externaldemo", call => "preprocess");
 
-       # Here's an example of how to inject an arbitrary function into
-       # ikiwiki. Ikiwiki will be able to call bob() just like any other
-       # function. Note use of automatic memoization.
-       rpc_call("inject", name => "IkiWiki::bob", call => "bob",
-               memoize => 1);
-
        # Here's an exmaple of how to access values in %IkiWiki::config.
        print STDERR "url is set to: ".
                rpc_call("getvar", "config", "url")."\n";
 
+       # Here's an example of how to inject an arbitrary function into
+       # ikiwiki. Note use of automatic memoization.
+       rpc_call("inject", name => "IkiWiki::bob",
+               call => "formattime", memoize => 1);
+
        print STDERR "externaldemo plugin successfully imported\n";
 }
 
index 350b76dfa4c7a06aae2b0b75b6758111fae61d8b..a2d07ebcf57069dfea0a12c936fa91080dcb9184 100755 (executable)
@@ -28,11 +28,15 @@ def rst2html(proxy, *kwargs):
                                                })
     return '\n'.join(parts['html_body'].splitlines()[1:-1])
 
+def getsetup(proxy, *kwargs):
+    return 'plugin', { 'safe' : 1, 'rebuild' : 1 }
+
 import sys
 def debug(s):
     sys.stderr.write(__name__ + ':DEBUG:%s\n' % s)
     sys.stderr.flush()
 
 proxy = IkiWikiProcedureProxy(__name__, debug_fn=None)
+proxy.hook('getsetup', getsetup)
 proxy.hook('htmlize', rst2html)
 proxy.run()
index 5ee5a1b9890d8b2b60ae67686aa1f841a7531d01..1e51f9dd347c79e738d4aa9b4ef33da86aeafbfa 100755 (executable)
--- a/pm_filter
+++ b/pm_filter
@@ -7,14 +7,14 @@ BEGIN {
 }
 
 if (/INSTALLDIR_AUTOREPLACE/) {
-       $_=qq{my \$installdir="$prefix";};
+       $_=qq{our \$installdir="$prefix";};
 }
 elsif (/VERSION_AUTOREPLACE/) {
        $_=qq{our \$version="$ver";};
 }
 elsif (/^use lib/) {
        # The idea here is to figure out if the libdir the Makefile.PL
-       # was configure to use is in perl's normal search path.
+       # was configured to use is in perl's normal search path.
        # If not, hard code it into ikiwiki.
        if ((grep { $_ eq $libdir } @INC) &&
             (! exists $ENV{PERL5LIB} || ! length $ENV{PERL5LIB} ||
@@ -25,8 +25,8 @@ elsif (/^use lib/) {
                $_="use lib '$libdir';\n";
        }
 }
-elsif ($. == 1 && ($ENV{NOTAINT} || ! exists $ENV{NOTAINT}) && m{^(#!.*perl.*?) -T$}) {
-       $_=qq{$1\n};
+elsif ($. == 1 && ($ENV{NOTAINT}=0) && m{^(#!.*perl.*?)$}) {
+       $_=qq{$1 -T\n};
 }
 elsif (/^\$ENV{PATH}="(.*)";/) {
        $_="\$ENV{PATH}=\"$1:$prefix/bin\";\n";
index 013cdf26834e9f8679b82ae9e7252b56cff9f6fc..dfb018c81eea6377d901a65d11b783f1de0c6883 100644 (file)
@@ -1,34 +1,49 @@
 # List here all source files with translatable strings.
 POTFILES=$(sort $(shell find ../IkiWiki -type f -name \*.pm)) \
-       ../ikiwiki.in ../IkiWiki.pm
+       ../ikiwiki.in ../IkiWiki.pm ../auto.setup
 
 POFILES=$(wildcard *.po)
 MOFILES=$(POFILES:.po=.mo)
 
-all: ikiwiki.pot mo
+# Translated underlays can only be generated if po4a is available.
+TRANSLATED_UNDERLAYS=$(shell if perl -e 'use Locale::Po4a::Common' 2>/dev/null; then echo ../underlays/locale; fi)
+
+all: ikiwiki.pot mo $(TRANSLATED_UNDERLAYS)
 
 mo: $(MOFILES)
 
 install: all
+       # Normal mo files for program translation.
        for file in $(MOFILES); do \
                lang=`echo $$file | sed 's/\.mo//'`; \
                install -d $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/; \
                install -m 0644 $$file $(DESTDIR)$(PREFIX)/share/locale/$$lang/LC_MESSAGES/ikiwiki.mo; \
        done
+       
+       # Underlay translation via po files that go in special per-language
+       # underlays.
+       for file in `cd underlays && find . -type f -name \*.po`; do \
+               lang=`echo $$file | sed -e 's/.po$$//' -e 's/.*\\.//'`; \
+               dir=`dirname "$(DESTDIR)$(PREFIX)/share/ikiwiki/po/$$lang/$$file"`; \
+               install -d $$dir; \
+               install -m 0644 underlays/$$file $$dir; \
+       done
 
 ikiwiki.pot: $(POTFILES)
        @if perl -e '($$ver)=`xgettext -V | head -n 1`=~/.*\s+([0-9]+\.[0-9]+)/; die "gettext $$ver too old, not updating the pot file\n" if $$ver < 0.16'; then \
                echo "Rebuilding the pot file"; \
-               xgettext $(POTFILES) -o ikiwiki.pot -Lperl --add-comments=translators; \
+               xgettext --from-code=UTF-8 $(POTFILES) -o ikiwiki.pot -Lperl --add-comments=translators; \
        fi
 
 clean:
-       rm -f $(MOFILES) messages messages.mo
+       rm -f $(MOFILES) messages messages.mo *_stamp
+       rm -rf html underlays/.ikiwiki $(TRANSLATED_UNDERLAYS)
+       find underlays -name \*.mdwn -or -name \*.pot | xargs rm -f
 
 %.mo: %.po
        msgfmt -o $@ $<
 
-%.po:
+%.po: ikiwiki.pot
        @echo -n "Merging ikiwiki.pot and $@"
        @msgmerge $@ ikiwiki.pot -o $@.new 2>&1
 # Typically all that changes was a date or line number. I'd prefer not to
@@ -46,3 +61,34 @@ check:
                printf "$$lang: "; \
                msgfmt -o /dev/null -c -v --statistics $$lang.po;\
        done
+
+underlays_copy_stamp:
+       # copy all the files we want to translate into a srcdir
+       for file in `cd ..; find underlays -follow -name \*.mdwn`; do \
+               install -d $$(dirname $$file); \
+               cp -aL ../$$file $$file 2>/dev/null || \
+               install -m 644 ../$$file $$file; \
+       done
+       install -d underlays/directives/ikiwiki/directive
+       for file in `cd ..; find doc/ikiwiki/directive/ -maxdepth 1 -type f`; do \
+               cp -a ../$$file underlays/directives/ikiwiki/directive ||  \
+               install -m 644 ../$$file underlays/directives/ikiwiki/directive; \
+       done
+       install -d underlays/empty
+       touch $@
+
+underlays: ../ikiwiki.out underlays_copy_stamp
+       ../ikiwiki.out -libdir .. -setup underlay.setup -refresh
+
+../ikiwiki.out: ../Makefile
+       make -C .. ikiwiki.out
+
+../Makefile: ../Makefile.PL
+       cd .. && ./Makefile.PL
+
+$(TRANSLATED_UNDERLAYS): po2wiki_stamp
+po2wiki_stamp: po2wiki underlays_copy_stamp
+       PERL5LIB=.. ./po2wiki underlay.setup
+       touch $@
+
+.PHONY: underlays
index 75dfb7823f3db91ee5a82775137cedd79f438007..d29f8172341f40a2ecf1b03a1fb163d405a9d5c6 100644 (file)
--- a/po/bg.po
+++ b/po/bg.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki-bg\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-01-12 01:19+0200\n"
 "Last-Translator: Damyan Ivanov <dam@modsodtsys.com>\n"
 "Language-Team: Bulgarian <dict@fsa-bg.org>\n"
@@ -16,263 +16,498 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: KBabel 1.11.4\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Първо трябва да влезете."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 #, fuzzy
 msgid "Preferences"
 msgstr "Предпочитанията са запазени."
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Предпочитанията са запазени."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "дискусия"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Достъпът ви е забранен."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "създаване на %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Грешка"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "промяна на %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Достъпът ви е забранен."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, fuzzy, perl-format
 msgid "missing %s parameter"
 msgstr "липсващ параметър „id” на шаблона"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "нов източник"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "съобщения"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "ново"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "премахване на „%s” (на %s дни)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "премахване на „%s”"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "е обработен нормално от %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "проверка на източника „%s”"
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "не е намерен източник на адрес „%s”"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 #, fuzzy
 msgid "feed not found"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "данните от източника предизвикаха грешка в модула XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "създаване на нова страницa „%s”"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "готово"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Грешка при изпращане на поща"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Грешка при изпращане на поща"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "грешка при запис на файла „%s”: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Няма „счупени” връзки!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "създаване на %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "премахване на старата страница „%s”"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "създаване на %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "промяна на %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "не е указан файл на обвивката"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "грешка при обработване на шаблона"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "грешшка в приставката „fortune”"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "липсващ параметър „id” на шаблона"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
 #, fuzzy
-msgid "failed to find url in html"
-msgstr "приставката „googlecalendar” не намери URL в HTML-кода"
+msgid "not a page"
+msgstr "грешка при четене на „%s”: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "При използване на приеставката „search” е необходимо е да се укаже %s"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 #, fuzzy
 msgid "failed to run graphviz"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "не е инсталиран polygen"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, fuzzy, perl-format
 msgid "failed to read %s: %s"
 msgstr "грешка при запис на файла „%s”: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, fuzzy, perl-format
 msgid "failed to resize: %s"
 msgstr "грешка при запис на файла „%s”: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "грешка при запис на файла „%s”: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 "Когато се използва „--rss” или „--atom” трябва да се укаже и "
 "местоположението на уикито посредством параметъра „--url”"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "шаблонът „%s” не е намерен"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "липсващ параметър „id” на шаблона"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "непознат вид сортиране „%s”"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Дискусия"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "модулът „RPC::XML::Client” не е намерен; източникът не е проверен"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 #, fuzzy
 msgid "failed to run dot"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr ""
 "Страницата „%s” е заключена от потребителя „%s” и не може да бъде променяна"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "грешка при зареждането на perl-модула „Markdown.pm” (%s) или „/usr/bin/"
 "markdown” (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 #, fuzzy
 msgid "stylesheet not found"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Огледала"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Огледало"
 
@@ -280,59 +515,200 @@ msgstr "Огледало"
 msgid "more"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "функцията „getctime” не е реализирана"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Получаване на OpenID номер"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Всички страници имат връзки от други страници."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Акаунтът е създаден. Можете да влезете."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Грешка при създаване на акаунта."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Грешка при изпращане на поща"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Паролата ви е изпратена по пощата."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "промяна на %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "модулът „RPC::XML::Client” не е намерен; източникът не е проверен"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "промяна на %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "крешка при компилиране на файла %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "крешка при компилиране на файла %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "крешка при компилиране на файла %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "грешка при запис на файла „%s”: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "грешка при запис на файла „%s”: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "грешка при запис на файла „%s”: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "гласуване"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Общо гласове:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "не е инсталиран polygen"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "грешка при изпълнението на poligen"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "грешшка в приставката „fortune”"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr ""
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr ""
 
@@ -388,46 +764,127 @@ msgstr ""
 msgid "%A night"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr ""
+"Страницата „%s” е заключена от потребителя „%s” и не може да бъде променяна"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "липÑ\81ваÑ\89 Ð¿Ð°Ñ\80амеÑ\82Ñ\8aÑ\80 â\80\9eidâ\80\9d Ð½Ð° Ñ\88аблона"
+msgid "no change to the file name was specified"
+msgstr "не Ðµ Ñ\83казан Ñ\84айл Ð½Ð° Ð¾Ð±Ð²Ð¸Ð²ÐºÐ°Ñ\82а"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "При използване на приеставката „search” е необходимо е да се укаже %s"
+msgid "%s already exists"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "изчистване на индекса за търсене на hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "обновяване на индекса за търсене на hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "обновяване на страницата „%s”"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "обновяване на страниците от уики „%s”: %s от потребител „%s”"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 #, fuzzy
 msgid "missing name or url parameter"
 msgstr "препратката няма указани параметрите „name” или „url”"
@@ -435,177 +892,225 @@ msgstr "препратката няма указани параметрите 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, fuzzy, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "препратката „%s” сочи към „%s”"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 #, fuzzy
 msgid "failed to parse any smileys"
 msgstr "няма разпознати усмивки; изключване на приставката „smiley”"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 #, fuzzy
 msgid "parse error"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
+#: ../IkiWiki/Plugin/sparkline.pm:104
 #, fuzzy
-msgid "bad height value"
+msgid "invalid height value"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 #, fuzzy
 msgid "missing width parameter"
 msgstr "липсващ параметър „id” на шаблона"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
+#: ../IkiWiki/Plugin/sparkline.pm:115
 #, fuzzy
-msgid "bad width value"
+msgid "invalid width value"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 #, fuzzy
 msgid "failed to run php"
 msgstr "приставката „linkmap”: грешка при изпълнение на „dot”"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, fuzzy, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "грешка при запис на файла „%s”: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 #, fuzzy
 msgid "missing id parameter"
 msgstr "липсващ параметър „id” на шаблона"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "шаблонът „%s” не е намерен"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 #, fuzzy
 msgid "failed to process:"
 msgstr "грешка при обработване на шаблона"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "грешка при запис на файла „%s”: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "функцията „getctime” не е реализирана"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "пропускане на невалидното име на файл „%s”"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "пропускане на невалидното име на файл „%s”"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "премахване на старата страница „%s”"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "сканиране на „%s”"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "обновяване на страницата „%s”"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "обновяване на страницата „%s”, съдържаща препратки към „%s”"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "обновяване на страницата „%s”, зависеща от „%s”"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "обновяване на „%s” и осъвременяване на обратните връзки"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "премахване на „%s” понеже не се генерира от „%s”"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: неуспех при обновяване на страницата „%s”"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "грешка при четене на „%s”: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "генериране на обвивки..."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "обновяване на уики..."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "осъвременяване на уики..."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "готово"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -620,21 +1125,14 @@ msgstr "не може да бъде създадена обвивка, коят
 msgid "wrapper filename not specified"
 msgstr "не е указан файл на обвивката"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "грешка при запис на файла „%s”: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "крешка при компилиране на файла %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "успешно генериране на %s"
@@ -643,29 +1141,109 @@ msgstr "успешно генериране на %s"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "формат: ikiwiki [опции] източник местоназначение"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "генериране на обвивки..."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "обновяване на уики..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "осъвременяване на уики..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Дискусия"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr ""
 "При използване на пареметъра „--cgi” е необходимо да се укаже и "
 "местоположението на уикито чрез параметъра „--url”"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Грешка"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "открита е циклична завидимост при %s на „%s” на дълбочина %i"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "грешка при четене на „%s”: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "дискусия"
+
+#~ msgid "rendering %s"
+#~ msgstr "обновяване на страницата „%s”"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr ""
+#~ "При използване на приеставката „search” е необходимо е да се укаже %s"
+
+#, fuzzy
+#~ msgid "failed to find url in html"
+#~ msgstr "приставката „googlecalendar” не намери URL в HTML-кода"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "е обработен нормално от %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "Паролата ви е изпратена по пощата."
+
+#~ msgid "polygen failed"
+#~ msgstr "грешка при изпълнението на poligen"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "изчистване на индекса за търсене на hyperestraier"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "обновяване на индекса за търсене на hyperestraier"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -690,9 +1268,6 @@ msgstr "открита е циклична завидимост при %s на 
 #~ "изпълнява като „svn post-commit hook”. Няма да бъдат разпратени "
 #~ "известявания"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "обновяване на страниците от уики „%s”: %s от потребител „%s”"
-
 #, fuzzy
 #~ msgid "%s not found"
 #~ msgstr "шаблонът „%s” не е намерен"
index d93a3edbac41ca2802d89664a765e22e5b5f8da0..657d2852c9668b29754c3b4e189a4a91f00427ca 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-05-09 21:21+0200\n"
 "Last-Translator: Miroslav Kure <kurem@debian.cz>\n"
 "Language-Team: Czech <debian-l10n-czech@lists.debian.org>\n"
@@ -15,253 +15,489 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Nejprve se musíte přihlásit."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr "přihlášení selhalo; možná si musíte povolit cookies?"
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr "Přihlášení"
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr "Předvolby"
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr "Správce"
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Nastavení uloženo."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "%s není editovatelná stránka"
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "diskuse"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Jste vyhoštěni."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "vytvářím %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Chyba"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "upravuji %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Jste vyhoštěni."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "chybí parametr %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "nový zdroj"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "příspěvky"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "nový"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "expiruji %s (stará %s dnů)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "expiruji %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "zpracováno ok %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "kontroluji zdroj %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "nemohu najít zdroj na %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr "zdroj nebyl nalezen"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "(neplatné UTF-8 bylo ze zdroje odstraněno)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "zdroj shodil XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "vytvářím novou stránku %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "hotovo"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Nepodařilo se odeslat email."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Nepodařilo se odeslat email."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "nelze změnit velikost: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Žádné porušené odkazy!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "vytvářím %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr "parametr %s je vyžadován"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "odstraňuji starou stránku %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "%s není editovatelná stránka"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "vytvářím %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "upravuji %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "šablona %s nebyla nalezena"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "jméno souboru s obalem nebylo zadáno"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "nepodařilo se zpracovat:"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "fortune selhal"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
-msgstr "v html se nepodařilo nalézt url"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "chybí hodnoty"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+#, fuzzy
+msgid "not a page"
+msgstr "nemohu číst %s: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "%s není editovatelná stránka"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Při používání vyhledávacího modulu musíte zadat %s"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr "nepodařilo se spustit graphviz"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "program není platným programem graphviz"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "polygen není nainstalován"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "chybná velikost \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "nelze číst %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr "nelze změnit velikost: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "nelze změnit velikost: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr "Při používání --rss nebo --atom musíte pomocí --url zadat url k wiki"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "zdroj nebyl nalezen"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "chybí parametr %s"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "neznámý typ řazení %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "Přidat nový příspěvek nazvaný:"
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "neexistující šablona %s"
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Diskuse"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "RPC::XML::Client nebyl nalezen, nepinkám"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "nepodařilo se spustit dot"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr "Stránka %s je zamknutá uživatelem %s a nelze ji měnit"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "selhalo nahrání perlového modulu Markdown.pm (%s) nebo /usr/bin/markdown (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "styl nebyl nalezen"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "zdroj nebyl nalezen"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "zdroj nebyl nalezen"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Zrcadla"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Zrcadlo"
 
@@ -269,59 +505,200 @@ msgstr "Zrcadlo"
 msgid "more"
 msgstr "více"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime není implementováno"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr "Přihlásit pomocí"
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Získat OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Na každou stránku vede odkaz z jiné stránky."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Vytvoření účtu bylo úspěšné. Nyní se můžete přihlásit."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Chyba při vytváření účtu."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Nepodařilo se odeslat email."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Vaše heslo vám bylo zasláno."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "upravuji %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "RPC::XML::Client nebyl nalezen, nepinkám"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, fuzzy, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s není editovatelná stránka"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "upravuji %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "nelze zkompilovat %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "nelze zkompilovat %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "nelze zkompilovat %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "nelze změnit velikost: %s"
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "nelze zapsat %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "nepodařilo se spustit dot"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "nelze číst %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "hlasovat"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Celkem hlasů:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "polygen není nainstalován"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "polygen selhal"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "fortune selhal"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "chybí vzorec"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "neznámý vzorec"
 
@@ -377,216 +754,349 @@ msgstr "%A pozdě večer"
 msgid "%A night"
 msgstr "%A v noci"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "%A během odpoledního čaje"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "o půlnoci"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "%A o poledni"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "Stránka %s je zamknutá uživatelem %s a nelze ji měnit"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, fuzzy, perl-format
+msgid "%s is not a file"
+msgstr "%s není editovatelná stránka"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "chybí hodnoty"
+msgid "no change to the file name was specified"
+msgstr "jméno souboru s obalem nebylo zadáno"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Při používání vyhledávacího modulu musíte zadat %s"
+msgid "%s already exists"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "zpracovávám %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "čistím vyhledávací index hyperestraieru"
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "aktualizace %s (%s) uživatelem %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "aktualizuji vyhledávací index hyperestraieru"
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "chybí parametr jméno nebo url"
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "zkratka %s odkazuje na <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr "nepodařilo se rozpoznat žádné smajlíky"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr "chyba rozpoznávání"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+#, fuzzy
+msgid "invalid featurepoint diameter"
 msgstr "chybný průměr zvýrazněného bodu (featurepoint)"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+#, fuzzy
+msgid "invalid featurepoint location"
 msgstr "chybné umístění zvýrazněného bodu (featurepoint)"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "chybí hodnoty"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+#, fuzzy
+msgid "invalid height value"
 msgstr "chybná výška"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
 msgstr "chybí parametr šířka (width)"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+#, fuzzy
+msgid "invalid width value"
 msgstr "chybná šířka"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "nepodařilo se spustit php"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "nemohu najít soubor"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "neznámý formát dat"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "prázdná data"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Stáhnout zdrojová data"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "zpracovávání selhalo na řádku %d: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr "chybí parametr id"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "šablona %s nebyla nalezena"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr "nepodařilo se zpracovat:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 #, fuzzy
 msgid "missing tex code"
 msgstr "chybí hodnoty"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "nelze změnit velikost: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "getctime není implementováno"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:256
+#, fuzzy
+msgid "main"
+msgstr "Správce"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "přeskakuji chybné jméno souboru %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "přeskakuji chybné jméno souboru %s"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "odstraňuji starou stránku %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "prohledávám %s"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "zpracovávám %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "zpracovávám %s, která odkazuje na %s"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "zpracovávám %s, která závisí na %s"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "zpracovávám %s, aby se aktualizovaly zpětné odkazy"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "odstraňuji %s, již není zpracovávána %s"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: nelze zpracovat %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "nemohu číst %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "generuji obaly..."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "znovu vytvářím wiki..."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "obnovuji wiki..."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "hotovo"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -601,21 +1111,14 @@ msgstr "nemohu vytvořit obal, který využívá soubor setup"
 msgid "wrapper filename not specified"
 msgstr "jméno souboru s obalem nebylo zadáno"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "nelze zapsat %s: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "nelze zkompilovat %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "%s byl úspěšně vytvořen"
@@ -624,27 +1127,108 @@ msgstr "%s byl úspěšně vytvořen"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "použití: ikiwiki [volby] zdroj cíl"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "generuji obaly..."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "znovu vytvářím wiki..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "obnovuji wiki..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Diskuse"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr "Při použití --cgi musíte pomocí --url zadat url k wiki"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Chyba"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "Byla rozpoznána smyčka direktivy %s na %s v hloubce %i"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "nemohu číst %s: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "diskuse"
+
+#~ msgid "rendering %s"
+#~ msgstr "zpracovávám %s"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "Při používání vyhledávacího modulu musíte zadat %s"
+
+#~ msgid "bad size \"%s\""
+#~ msgstr "chybná velikost \"%s\""
+
+#~ msgid "failed to find url in html"
+#~ msgstr "v html se nepodařilo nalézt url"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "zpracováno ok %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "Vaše heslo vám bylo zasláno."
+
+#~ msgid "polygen failed"
+#~ msgstr "polygen selhal"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "čistím vyhledávací index hyperestraieru"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "aktualizuji vyhledávací index hyperestraieru"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -666,9 +1250,6 @@ msgstr "Byla rozpoznána smyčka direktivy %s na %s v hloubce %i"
 #~ "REV není nastavena, není spuštěna ze svn post-commit, nemohu zaslat "
 #~ "oznámení"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "aktualizace %s (%s) uživatelem %s"
-
 #~ msgid "%s not found"
 #~ msgstr "%s nenalezen"
 
index 6aa4ee3e8b6088457dff808abcd55063b0c48986..b4e06535bbc4e550af2dcc1dc33bb8582837c96a 100644 (file)
--- a/po/da.po
+++ b/po/da.po
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# Danish translations for ikiwiki package
+# Copyright (C) 2008 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: ikiwiki\n"
+"Project-Id-Version: ikiwiki 3.14159\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-11 00:48-0500\n"
-"PO-Revision-Date: 2008-02-11 00:12+0100\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
+"PO-Revision-Date: 2009-07-23 01:07+0200\n"
 "Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
-"Language-Team: Danish <dansk@klid.dk>\n"
+"Language-Team: None\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
 "X-Poedit-Language: Danish\n"
 "X-Poedit-Country: DENMARK\n"
 "X-Poedit-SourceCharset: utf-8\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Du skal først logge på."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+"mulig opsætningsfejl: sslcookie er sat, men du forsøger at logge på via "
+"http, ikke https"
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
-msgstr "Pålogning fejlede, måske skal du tillade infokager (cookies)?"
+msgstr "Pålogning mislykkedes, måske skal du tillade infokager (cookies)?"
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr "Din kørsel (login session) er udløbet"
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr "Pålogning"
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr "Indstillinger"
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr "Admin"
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Indstillinger gemt"
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "%s er ikke en redigérbar side"
-
-#: ../IkiWiki/CGI.pm:384 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:242 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:176
-msgid "discussion"
-msgstr "diskussion"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Du er banlyst."
 
-#: ../IkiWiki/CGI.pm:431
-#, perl-format
-msgid "creating %s"
-msgstr "opretter %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Fejl"
 
-#: ../IkiWiki/CGI.pm:449 ../IkiWiki/CGI.pm:467 ../IkiWiki/CGI.pm:477
-#: ../IkiWiki/CGI.pm:511 ../IkiWiki/CGI.pm:555
-#, perl-format
-msgid "editing %s"
-msgstr "redigerer %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr "Indsamling udløst via web."
 
-#: ../IkiWiki/CGI.pm:644
-msgid "You are banned."
-msgstr "Du er banlyst."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr "Intet at gøre lige nu, alle fødninger er tidssvarende!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:101
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "mangler parametren %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:128
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "ny fødning"
 
-#: ../IkiWiki/Plugin/aggregate.pm:142
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "indlæg"
 
-#: ../IkiWiki/Plugin/aggregate.pm:144
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "nyt"
 
-#: ../IkiWiki/Plugin/aggregate.pm:309
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "udløber %s (%s dage gammel)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:316
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "udløber %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:345
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "korrekt dannet ved %s"
+msgid "last checked %s"
+msgstr "senest undersøgt %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:349
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "undersøger fødning %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:354
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "kunne ikke finde fødning ved %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:369
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr "fødning ikke fundet"
 
-#: ../IkiWiki/Plugin/aggregate.pm:380
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "(defekt UTF-8 fjernet fra fødning)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:386
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr "(fødningselementer omgået (escaped))"
 
-#: ../IkiWiki/Plugin/aggregate.pm:392
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "fødning fik XML::Feed til at bryde sammen!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:466
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "opretter ny side %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr "sletter bundt.."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "færdig"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr "Skal angive %s"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Oprettelse af bundt i S3 mislykkedes: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Arkivering af fil i S3 mislykkedes: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "Sletning af fil fra S3 mislykkedes: "
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr "der er allerede en side ved navn %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr "forhindret af allowed_attachments"
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr "dårligt vedhæftningsfilnavn"
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr "vedhæftningsoplægning"
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr "automatisk indeks-dannelse"
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+"Beklager, men det ligner spam til <a href=\"http://blogspam.net/\">blogspam</"
+"a>: "
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr "%s fra %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Ingen henvisninger der ikker fungerer!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr "Ikke-understøttet sideformat %s"
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr "kommentar skal have indhold"
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr "Anonym"
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr "dårligt sidenavn"
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr "kommenterer på %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr "siden '%s' eksisterer ikke, så du kan ikke kommentere"
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr "kommentarer på side '%s' er lukket"
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr "kommentar gemt for moderering"
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr "Din kommentar vil blive tilføjet efter moderatorgenemsyn"
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr "Tilføjede en kommentar"
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr "Tilføjede en kommentar: %s"
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr "du er ikke logget på som en administrator"
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr "Kommentarmoderering"
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr "kommentarkoderering"
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr "Kommentarer"
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr "parametren %s er krævet"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr "ingen tekst blev kopieret i denne side"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr "ingen tekst blev kopieret i denne side med id %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr "fjerner gammelt smugkig %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "%s er ikke en redigérbar side"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "opretter %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "redigerer %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 msgid "template not specified"
 msgstr "skabelon %s ikke angivet"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 msgid "match not specified"
 msgstr "sammenligning ikke angivet"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr "redigeringsskabelon %s registreret for %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 msgid "failed to process"
 msgstr "dannelsen mislykkedes"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr "skal angive format og tekst"
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "spådom (fortune) fejlede"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
-msgstr "lokalisering af url i html mislykkedes"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr "manglende side"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr "Siden %s eksisterer ikke."
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+#, fuzzy
+msgid "not a page"
+msgstr "kan ikke få sider til at passe sammen: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "%s er ikke en redigérbar side"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr "Du har ikke lov til at ændre %s"
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr "du kan ikke påvirke en fil med modus %s"
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr "du har ikke lov til at ændre modus for filer"
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Skal angive %s når udvidelsen %s bruges"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr "Tolkning af URL mislykkedes, kan ikke afgøre domænenavn"
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr "graphviz-kørsel mislykkedes"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "prog er ikke et gyldigt graphviz-program"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr "tohighlight indeholder ukendt filtype '%s'"
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr "Kildekode: %s"
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+"advarsel: highlight perl modul ikke tilgængelig: falder tilbage til simpel "
+"gennemkørsel"
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr "Image::Magick ikke installeret"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "forkert størrelse \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr "forkert størrelsesformat \"%s\" (burde være WxH)"
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "læsning af %s mislykkedes: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr "Ændring af størrelse mislykkedes: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, perl-format
 msgid "failed to determine size of image %s"
-msgstr "Vurdering af størrelse på billede mislykkedes: %s"
+msgstr "Vurdering af billedstørrelse mislykkedes: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:44
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr "Skal angive url til wiki med --url når --rss eller --atom anvendes"
 
-#: ../IkiWiki/Plugin/inline.pm:136
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr "sideredigering er ikke tilladt"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+msgid "missing pages parameter"
+msgstr "mangler pages-parametren"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr "Sort::Naturally krævet for title_natural sortering"
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "ukendt sorteringsform %s"
 
-#: ../IkiWiki/Plugin/inline.pm:201
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "Tilføj nyt indlæg med følgende titel:"
 
-#: ../IkiWiki/Plugin/inline.pm:217
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "ikke-eksisterende skabelon: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:250 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Diskussion"
-
-#: ../IkiWiki/Plugin/inline.pm:468
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "RPC::XML::Client ikke fundet, pinger ikke"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "dot-kørsel mislykkedes"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
+#: ../IkiWiki/Plugin/lockedit.pm:47
 #, perl-format
-msgid "%s is locked by %s and cannot be edited"
-msgstr "%s er låst af %s og kan ikke redigeres"
+msgid "%s is locked and cannot be edited"
+msgstr "%s er låst og kan ikke redigeres"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+"multimarkdown er aktiveret, men Text::MultiMarkdown er ikke installeret"
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "Indlæsning af perl-modulet Markdown.pm (%s) eller /usr/bin/markdown (%s) "
 "mislykkedes"
 
-#: ../IkiWiki/Plugin/meta.pm:132
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "stilsnit (stylesheet) ikke fundet"
 
-#: ../IkiWiki/Plugin/meta.pm:158
+#: ../IkiWiki/Plugin/meta.pm:196
 msgid "redir page not found"
 msgstr "henvisningsside ikke fundet"
 
-#: ../IkiWiki/Plugin/meta.pm:171
+#: ../IkiWiki/Plugin/meta.pm:210
 msgid "redir cycle is not allowed"
 msgstr "ring af henvisninger er ikke tilladt"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Spejle"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Spejl"
 
@@ -268,59 +508,206 @@ msgstr "Spejl"
 msgid "more"
 msgstr "mere"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime ikke implementeret"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr "Log på med"
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Skaf en OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
-msgstr "Alle sider henvises til fra andre sider."
+#: ../IkiWiki/Plugin/orphans.pm:45
+msgid "All pages have other pages linking to them."
+msgstr "Alle sider har henvisninger fra andre sider."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr "dårlig eller manglende skabelon"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Konto korrekt oprettet. Nu kan du logge på."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Fejl ved kontooprettelse."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+"Ingen emailadresse, så kan ikke sende adgangskodenulstillingsinstruktioner."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Afsendelse af mail mislykkedes"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Din adgangskode er blevet sendt til dig."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr "Du har fået tilsendt adgangskodenulstillingsinstruktioner."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr "Ukorrekt adgangskodenumstillings-URL"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr "adgangskodenulstilling afvist"
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr "Ping modtaget."
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr "kræver 'from'- og 'to'-parametre"
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, perl-format
+msgid "Will ping %s"
+msgstr "vil pinge %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr "ignorerer ping-direktiv for wiki %s (denne wiki er %s)"
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+msgid "LWP not found, not pinging"
+msgstr "LWP ikke fundet, pinger ikke"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s er ikke en gyldig sprogkode"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+"%s er ikke en gyldig værdi for po_link_to, falder tilbage til "
+"po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+"po_link_to=negotiated kræver at usedirs er aktiveret, falder tilbage til "
+"po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr "gendanner alle sider for at korrigere meta titler"
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, perl-format
+msgid "building %s"
+msgstr "danner %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr "opdaterer PO-filer"
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+"Kan ikke fjerne en oversættelse. Fjern i stedet hovedsiden, så fjernes dens "
+"oversættelser også."
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+"Kan ikke omdøbe en oversættelse. Omdøb i stedet hovedsiden, så omdøbes dens "
+"oversættelser også."
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr "POT-filen %s eksisterer ikke"
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "kopiering af POT-filen til %s mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, perl-format
+msgid "failed to update %s"
+msgstr "opdatering af %s mislykkedes"
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:858
+#, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "kopiering af POT-filen til %s mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr "N/A"
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, perl-format
+msgid "failed to translate %s"
+msgstr "oversættelse af %s mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr "forældede PO filer fjernet"
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, perl-format
+msgid "failed to write %s"
+msgstr "skrivning af %s mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+msgid "failed to translate"
+msgstr "oversættelse mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, perl-format
+msgid "failed to read %s"
+msgstr "læsning af %s mislykkedes"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+"forkert gettext-data, gå tilbage til forrige side og fortsæt redigering"
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "stem"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Samlede stemmer:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "polygen ikke installeret"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "polygen fejlede"
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
+msgstr "kommando fejlede"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "manglende formular"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "ukendt formular"
 
@@ -376,213 +763,347 @@ msgstr "sent %A aften"
 msgid "%A night"
 msgstr "%A nat"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "ved tetid %A"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "ved midnat"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "midt på dagen %A"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
-msgid "missing page"
-msgstr "manglende side"
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr "ugyldig procentværdi %s"
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr "Kræver enten parametre `percent` eller `totalpages og `donepages`"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr "(Diff trunkeret)"
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
 #, perl-format
-msgid "The page %s does not exist."
-msgstr "Siden %s eksisterer ikke."
+msgid "%s does not exist"
+msgstr "%s eksisterer ikke"
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/remove.pm:38
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Skal angive %s når søgeudvidelsen bruges"
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s er ikke i srcdir, så kan ikke blive slettet"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr "%s er ikke en fil"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr "bekræft at %s bliver fjernet"
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr "Vælg vedhæftning der skal slettes."
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr "fjernet"
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr "%s er ikke i srcdir, så kan ikke blive omdøbt"
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr "ingen ændring til filnavnet blev angivet"
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "renser hyperestraier søgeindeks"
+#: ../IkiWiki/Plugin/rename.pm:68
+#, perl-format
+msgid "illegal name"
+msgstr "ugyldigt navn"
+
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr "%s eksisterer allerede"
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr "%s eksisterer allerede på disken"
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, perl-format
+msgid "rename %s"
+msgstr "omdøb %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr "Omdøb også UnderSider og vedhæftninger"
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr "Kun en vedhæftning kan blive omdøbt ad gangen."
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr "Vælg vedhæftningen som skal omdøbes."
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr "omdøb %s til %s"
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr "opdatering til omdøbning af %s til %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr "behøver Digest::SHA1 til indeks %s"
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "opdaterer hyperestraier søgeindeks"
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr "søg"
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
-msgstr "genvejsudvidelsen vil ikke fungere uden en shortcuts.mdwn"
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr "genvejsudvidelsen vil ikke fungere uden %s"
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "manglende navn eller url parameter"
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "genvej %s viser til <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr "afkodning af smileys mislykkedes"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr "afkodningsfejl"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
-msgstr "dårlig featurepoint-parameter diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
+msgstr "forkert featurepoint-parameter diameter"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
-msgstr "dårlig featurepoint-parameter location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
+msgstr "forkert featurepoint-parameter location"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "manglende værdier"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+msgid "invalid height value"
 msgstr "forkert højdeværdi"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
 msgstr "manglende breddeparameter"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+msgid "invalid width value"
 msgstr "forkert breddeværdi"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "php-kørsel mislykkedes"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "kan ikke finde fil"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "ukendt dataformat"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "blanke data"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Direkte datanedlastning"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "afkodningsfejl på linje %d: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr "manglende id-parameter"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "skabelon %s ikke fundet"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr "dannelsen mislykkedes:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr "manglende tex-kode"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr "kode indeholder ikke-tilladte latec-kommandoer"
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 msgid "failed to generate image from code"
 msgstr "billedopbygning fra kode mislykkedes"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
-msgstr "(kan ikke omskiftes i et smugkig)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr "udvidelse"
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "getctime ikke implementeret"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr "aktivér %s?"
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr "opsætningsfilen for denne wiki er ukendt"
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr "primær"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr "udvidelser"
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+"Opsætningsændringerne vist nedenfor kræver wiki-genopbygning for at træde i "
+"kraft."
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+"For at opsætningsændringerne vist nedenfor træder fuldt ud i kraft, skal du "
+"muligvis genopbygge wikien."
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr "Fejl: %s returnerede ikke-nul (%s). Dropper opsætningsændringer."
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr "kan ikke afgøre id for ikke-tillidsfulde skribent %s"
 
-#: ../IkiWiki/Render.pm:274 ../IkiWiki/Render.pm:295
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr "dårligt filnavn %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+"symbolsk lænke fundet i srcdir-sti (%s) -- sæt allow_symlinks_before_srcdir "
+"for at tillade dette"
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "udelader forkert filnavn %s"
 
-#: ../IkiWiki/Render.pm:350
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr "%s har flere mulige kildesider"
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "fjerner gammel side %s"
 
-#: ../IkiWiki/Render.pm:391
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "gennemlæser %s"
 
-#: ../IkiWiki/Render.pm:396
+#: ../IkiWiki/Render.pm:447
 #, perl-format
-msgid "rendering %s"
-msgstr "danner %s"
-
-#: ../IkiWiki/Render.pm:417
-#, perl-format
-msgid "rendering %s, which links to %s"
+msgid "building %s, which links to %s"
 msgstr "danner %s, som henviser til %s"
 
-#: ../IkiWiki/Render.pm:438
+#: ../IkiWiki/Render.pm:468
 #, perl-format
-msgid "rendering %s, which depends on %s"
+msgid "building %s, which depends on %s"
 msgstr "danner %s, som afhænger af %s"
 
-#: ../IkiWiki/Render.pm:477
+#: ../IkiWiki/Render.pm:507
 #, perl-format
-msgid "rendering %s, to update its backlinks"
+msgid "building %s, to update its backlinks"
 msgstr "danner %s, for at opdatere dens krydshenvisninger (backlinks)"
 
-#: ../IkiWiki/Render.pm:489
+#: ../IkiWiki/Render.pm:519
 #, perl-format
-msgid "removing %s, no longer rendered by %s"
+msgid "removing %s, no longer built by %s"
 msgstr "fjerner %s, ikke længere dannet af %s"
 
-#: ../IkiWiki/Render.pm:515
+#: ../IkiWiki/Render.pm:543
 #, perl-format
-msgid "ikiwiki: cannot render %s"
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: kan ikke danne %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "kan ikke læse %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "bygger wrappers.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr "du skal angive et wikinavn (som indeholder alfanumeriske tegn)"
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "genopbygger wiki..."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr "revisionskontrolsystem %s ikke understøttet"
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "genopfrisker wiki..."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr "opsætning af depotet med ikiwiki-makerepo mislykkedes"
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "færdig"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr "** Deaktiverer udvidelse %s, da den fejler med denne besked:"
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -597,21 +1118,14 @@ msgstr "kan ikke oprette en wrapper som bruger en opsætningsfil"
 msgid "wrapper filename not specified"
 msgstr "wrapper-navn ikke angivet"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "skrivning ad %s mislykkedes: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "kompilering af %s mislykkedes"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "Korrekt bygget %s"
@@ -620,23 +1134,77 @@ msgstr "Korrekt bygget %s"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "brug: ikiwiki [valg] kilde mål"
 
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr "       ikiwiki --setup opsætningsfil"
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr "brug: --set var=værdi"
 
-#: ../IkiWiki.pm:130
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "bygger wrappers.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "genopbygger wiki..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "genopfrisker wiki..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Diskussion"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr "Skal angive url til wiki med --url når der bruges --cgi"
 
-#: ../IkiWiki.pm:217 ../IkiWiki.pm:218
-msgid "Error"
-msgstr "Fejl"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr "kan ikke bruge flere samtidige RCS-udvidelser"
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+"indlæsning af ekstern udvidelse krævet af udvidelsen %s mislykkedes: %s"
+
+#: ../IkiWiki.pm:1243
+#, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
+msgstr "forudberegningssløkke fundet på %s ved dybde %i"
+
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr "ja"
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:772
+#: ../IkiWiki.pm:1915
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
-msgstr "%s forudberegningssløkke fundet på %s ved dybde %i"
+msgid "cannot match pages: %s"
+msgstr "kan ikke få sider til at passe sammen: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr "Hvad skal wikien hedde?"
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr "wiki"
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr "Hvilket revisionskontrolsystem skal bruges?"
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr "Hvilken bruger (wiki konto eller openid) skal være administrator?"
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr "Hvad er webserverens domænenavn?"
+
+#~ msgid "discussion"
+#~ msgstr "diskussion"
index ca6001949ff55128b264e40536f47a134ce0c9e0..51c1b0fca2f791907c6167b94e295fb4867f32e6 100644 (file)
--- a/po/de.po
+++ b/po/de.po
 # German translation of the ikiwiki language file resulting in de.po
 # Copyright © 2008 Kai Wasserbäch <debian@carbon-project.org>
+# Copyright © 2008-2009 Kurt Gramlich <kurt@skolelinux.de>
 # This file is distributed under the same license as the ikiwiki package.
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: ikiwiki 2.40\n"
-"Report-Msgid-Bugs-To: ikiwiki@packages.debian.org\n"
-"POT-Creation-Date: 2008-02-24 16:02-0500\n"
-"PO-Revision-Date: 2008-03-03 21:22+0100\n"
-"Last-Translator: Kai Wasserbäch <debian@carbon-project.org>\n"
+"Project-Id-Version: ikiwiki 3.14159\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
+"PO-Revision-Date: 2009-07-23 01:07+0100\n"
+"Last-Translator: Kurt Gramlich <kurt@skolelinux.de>\n"
 "Language-Team: German <debian-l10n-german@lists.debian.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Sie müssen sich zuerst anmelden."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+"vermutliche Fehlkonfiguration: sslcookie ist gesetzt, aber Sie versuchen "
+"sich via http anzumelden, nicht https"
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
-msgstr "Anmeldung fehlgeschlagen, möglicherweise müssen Sie zuvor Cookies aktivieren?"
+msgstr ""
+"Anmeldung fehlgeschlagen, möglicherweise müssen Sie zuvor Cookies aktivieren?"
+
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr "Ihre Anmeldezeit ist abgelaufen."
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr "Anmelden"
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr "Einstellungen"
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr "Administrator"
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Einstellungen gespeichert."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "%s ist keine bearbeitbare Seite"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Sie sind ausgeschlossen worden."
 
-#: ../IkiWiki/CGI.pm:384 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:237 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:172
-msgid "discussion"
-msgstr "Diskussion"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Fehler"
 
-#: ../IkiWiki/CGI.pm:440
-#, perl-format
-msgid "creating %s"
-msgstr "erstelle %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr "Das Web löst die Zusammenstellung aus"
 
-#: ../IkiWiki/CGI.pm:458 ../IkiWiki/CGI.pm:476 ../IkiWiki/CGI.pm:486
-#: ../IkiWiki/CGI.pm:520 ../IkiWiki/CGI.pm:564
-#, perl-format
-msgid "editing %s"
-msgstr "bearbeite %s"
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr "Es gibt nichts zu tun, alle Vorlagen (feeds) sind aktuell!"
 
-#: ../IkiWiki/CGI.pm:653
-msgid "You are banned."
-msgstr "Sie sind ausgeschlossen worden."
-
-#: ../IkiWiki/Plugin/aggregate.pm:101
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "Parameter %s fehlt"
 
-#: ../IkiWiki/Plugin/aggregate.pm:128
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
-msgstr "neuer Feed"
+msgstr "neue Vorlage (feed)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:142
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "Beiträge"
 
-#: ../IkiWiki/Plugin/aggregate.pm:144
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "neu"
 
-#: ../IkiWiki/Plugin/aggregate.pm:309
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "%s läuft aus (%s Tage alt)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:316
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "%s läuft aus"
 
-#: ../IkiWiki/Plugin/aggregate.pm:345
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "normal verarbeitet um %s"
+msgid "last checked %s"
+msgstr "zuletzt geprüft %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:349
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
-msgstr "überprüfe Feed %s ..."
+msgstr "überprüfe Vorlage (feed) %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:354
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
-msgstr "konnte Feed unter %s nicht finden"
+msgstr "konnte Vorlage (feed) unter %s nicht finden"
 
-#: ../IkiWiki/Plugin/aggregate.pm:369
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
-msgstr "Feed nicht gefunden"
+msgstr "Vorlage (feed) nicht gefunden"
 
-#: ../IkiWiki/Plugin/aggregate.pm:380
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
-msgstr "(ungültiges UTF-8 wurde aus dem Feed entfernt)"
+msgstr "(ungültiges UTF-8 wurde aus der Vorlage (feed) entfernt)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:386
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
-msgstr "(Feedentitäten maskiert)"
+msgstr "(Einträge in der Vorlage (feed) wurden maskiert)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:392
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
-msgstr "Feed führte zum Absturz von XML::Feed!"
+msgstr "Vorlage (feed) führte zum Absturz von XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:466
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "erstelle neue Seite %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr "lösche Behälter (bucket)..."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "fertig"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr "%s muss angegeben werden"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Konnte Behälter (bucket) in S3 nicht anlegen: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Konnte die Datei nicht in S3 speichern: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "Konnte die Datei nicht in S3 löschen: "
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr "eine Seite mit dem Namen %s existiert bereits"
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr "durch allowed_attachements verboten"
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr "fehlerhafter Dateiname für Anhang"
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr "Anhang hochladen"
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr "automatische Index-Erstellung"
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+"Entschuldigung, aber <a href=\"http://blogspam.net/\">blogspam</a> stuft das "
+"als Spam ein: "
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr "%s von %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
-msgstr "Es gibt keine ungültigen Links!"
+msgstr "Es gibt keine ungültigen Verweise!"
+
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr "nicht unterstütztes Seitenformat %s"
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr "ein Kommentar sollte Inhalt haben"
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr "Anonym"
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr "fehlerhafter Seitenname"
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr "kommentiere %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+"Seite %s existiert nicht, Sie können sie deshalb auch nicht kommentieren"
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr "Kommentare zur Seite %s sind gesperrt"
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr "Der Kommentar wurde zur Moderation gespeichert"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr "Ihr Kommentar wird nach Moderation verschickt"
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr "Kommentar hinzugefügt"
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr "Kommentar hinzugefügt: %s"
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr "Sie sind nicht als Administrator angemeldet"
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr "Kommentar-Moderation"
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr "Kommentar-Moderation"
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr "Kommentare"
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr "der Parameter %s wird benötigt"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr "es wurde kein Text in diese Seite kopiert"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr "es wurde kein Text in diese Seite mit der id %s kopiert"
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr "entferne alte Vorschau %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "Seite %s kann nicht bearbeitet werden"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "erstelle %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "bearbeite %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 msgid "template not specified"
 msgstr "Vorlage nicht angegeben"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 msgid "match not specified"
 msgstr "Übereinstimmung nicht angegeben"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
-msgstr "»edittemplate« %s registriert für %s"
+msgstr "edittemplate %s für %s registriert"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 msgid "failed to process"
-msgstr "Bearbeitung fehlgeschlagen"
+msgstr "Ablauf fehlgeschlagen"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr "Format und Text müssen spezifiziert werden"
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
-msgstr "»fortune« fehlgeschlagen"
+msgstr "fortune fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr "fehlende Seite"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr "Die Seite %s existiert nicht."
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
-msgstr "URL in HTML nicht gefunden"
+#: ../IkiWiki/Plugin/getsource.pm:73
+#, fuzzy
+msgid "not a page"
+msgstr "Kann die Seiten nicht zuordnen: %s"
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "Seite %s kann nicht bearbeitet werden"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr "Sie dürfen %s nicht verändern"
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr "Sie können eine Datei mit den Zugriffsrechten %s nicht nutzen"
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr "Sie dürfen die Zugriffsrechte der Datei nicht ändern"
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "%s muss angegeben werden, wenn die %s Erweiterung verwandt wird"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr "auswerten der URL fehlgeschlagen, konnte Domainnamen nicht feststellen"
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
-msgstr "konnte graphviz nicht ausführen"
+msgstr "graphviz konnte nicht ausgeführt werden"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "prog ist kein gültiges graphviz-Programm"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "falsche Größe \"%s\""
+msgid "tohighlight contains unknown file type '%s'"
+msgstr "tohighlight enteilt unbekannten Dateityp '%s'"
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr "Quellcode: %s"
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+"Warnung: das highlight Perlmodul ist nicht verfügbar; greife zurück auf pass "
+"through"
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr "Image::Magick ist nicht installiert"
+
+#: ../IkiWiki/Plugin/img.pm:72
+#, perl-format
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr "falsches Format in \"%s\" für size (sollte BxH sein)"
+
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "Lesen von %s fehlgeschlagen: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr "Größenänderung fehlgeschlagen: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, perl-format
 msgid "failed to determine size of image %s"
 msgstr "Größe des Bildes %s konnte nicht festgestellt werden."
 
-#: ../IkiWiki/Plugin/inline.pm:44
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
-msgstr "Die URL zum Wiki muss mit --url angegeben werden, wenn --rss oder --atom genutzt wird"
+msgstr ""
+"Die URL zum Wiki muss mit --url angegeben werden, wenn --rss oder --atom "
+"genutzt wird"
+
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr "bearbeiten der Seiten nicht erlaubt"
 
-#: ../IkiWiki/Plugin/inline.pm:136
+#: ../IkiWiki/Plugin/inline.pm:155
+msgid "missing pages parameter"
+msgstr "fehlender Seitenparameter"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr "Sort::Naturally wird benötigt für title_natural sort"
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "Unbekannter Sortierungstyp %s"
 
-#: ../IkiWiki/Plugin/inline.pm:196
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "Füge einen neuen Beitrag hinzu. Titel:"
 
-#: ../IkiWiki/Plugin/inline.pm:212
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "nicht-vorhandene Vorlage %s"
 
-#: ../IkiWiki/Plugin/inline.pm:245 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Diskussion"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
-msgstr "RPC::XML::Client nicht gefunden, pinge nicht"
+msgstr "RPC::XML::Client nicht gefunden, führe Ping nicht aus"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "dot konnte nicht ausgeführt werden"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
+#: ../IkiWiki/Plugin/lockedit.pm:47
 #, perl-format
-msgid "%s is locked by %s and cannot be edited"
-msgstr "%s wurde von %s gesperrt und kann nicht bearbeitet werden"
+msgid "%s is locked and cannot be edited"
+msgstr "%s ist gesperrt und kann nicht bearbeitet werden"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+"multimarkdown ist eingeschaltet, aber Text::MultiMarkdown ist nicht "
+"installiert"
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
-msgstr "Laden des des Perl-Moduls »Markdown.pm« (%s) oder von »/usr/bin/markdown« (%s) fehlgeschlagen"
+msgstr ""
+"laden des Perlmoduls Markdown.pm (%s) oder /usr/bin/markdown (%s) "
+"fehlgeschlagen"
 
-#: ../IkiWiki/Plugin/meta.pm:132
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "Stylesheet nicht gefunden"
 
-#: ../IkiWiki/Plugin/meta.pm:158
+#: ../IkiWiki/Plugin/meta.pm:196
 msgid "redir page not found"
 msgstr "Umleitungsseite nicht gefunden"
 
-#: ../IkiWiki/Plugin/meta.pm:171
+#: ../IkiWiki/Plugin/meta.pm:210
 msgid "redir cycle is not allowed"
 msgstr "Zyklische Umleitungen sind nicht erlaubt"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Spiegel"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Spiegel"
 
@@ -262,59 +509,209 @@ msgstr "Spiegel"
 msgid "more"
 msgstr "mehr"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime ist nicht implementiert"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr "Anmelden mit"
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Eine OpenID anfordern"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
-msgstr "Alle Seiten sind von anderen Seiten aus verlinkt."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
+msgstr "Alle Seiten haben mindenstens einen Verweis von einer anderen Seite."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr "fehlerhafte oder fehlende Vorlage"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Kontoerstellung erfolgreich. Sie können sich jetzt anmelden."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Konto konnte nicht erstellt werden."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+"es gibt keine E-Mail Adresse, deshalb kann keine Anweisung zum Zurücksetzen "
+"des Passwortes zugeschickt werden."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Es konnte keine E-Mail versandt werden"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Ihr Passwort wurde Ihnen via E-Mail zugesandt."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr "Ihnen wurden Anweisungen zum Zurücksetzen des Passworts zugesandt."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr "fehlerhafte URL zum Zurücksetzen des Passworts"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr "zurücksetzen des Passworts abgelehnt"
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr "Ping empfangen."
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr "erfordert die Parameter 'from' und 'to'"
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, perl-format
+msgid "Will ping %s"
+msgstr "werde Ping an %s senden"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr "Ignoriere die ping Anweisung für das Wiki %s (dieses Wiki ist %s)"
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+msgid "LWP not found, not pinging"
+msgstr "LWP nicht gefunden, führe Ping nicht aus"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s ist keine gültige Sprachkodierung"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+"%s ist kein gültiger Wert für po_link_to, greife zurück auf "
+"po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+"po_link_to=negotiated benötigt usedirs eingeschaltet, greife zurück auf "
+"po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr "um die meta-titeln zu reparieren werden alle Seiten neu erstellt"
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, perl-format
+msgid "building %s"
+msgstr "erzeuge %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr "PO-Dateien aktualisiert"
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+"Übersetzung kann nicht entfernt werden. Wenn die Master Seite entfernt wird, "
+"werden auch ihre Übersetzungen entfernt."
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+"Eine Übersetzung kann nicht umbenannt werden. Wenn die Master Seite "
+"unbenannt wird, werden auch ihre Übersetzungen unbenannt."
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr "POT-Datei (%s) existiert nicht"
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "kopieren der POT-Datei nach %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, perl-format
+msgid "failed to update %s"
+msgstr "aktualisieren von %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "kopieren der POT-Datei nach %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr "N/A"
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, perl-format
+msgid "failed to translate %s"
+msgstr "übersetzen von %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr "überflüssige PO-Dateien wurden entfernt"
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, perl-format
+msgid "failed to write %s"
+msgstr "schreiben von %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+msgid "failed to translate"
+msgstr "übersetzen fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, perl-format
+msgid "failed to read %s"
+msgstr "lesen von %s fehlgeschlagen"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+"ungültige gettext Datei, gehe zurück zur vorherigen Seite um weiter zu "
+"arbeiten"
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "abstimmen"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Alle Stimmen:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "polygen ist nicht installiert"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "polygen fehlgeschlagen"
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
+msgstr "Befehl fehlgeschlagen"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "fehlende Formel"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "unbekannte Formel"
 
@@ -324,11 +721,11 @@ msgstr "unbekannte Formel"
 #. translators: %A- is the name of the previous day.
 #: ../IkiWiki/Plugin/prettydate.pm:15
 msgid "late %A- night"
-msgstr "spät am %A- in der Nacht"
+msgstr "%A- spät in der Nacht"
 
 #: ../IkiWiki/Plugin/prettydate.pm:17
 msgid "in the wee hours of %A- night"
-msgstr "in den frühen Morgenstunden %A-"
+msgstr "%A- in den frühen Morgenstunden"
 
 #: ../IkiWiki/Plugin/prettydate.pm:20
 msgid "terribly early %A morning"
@@ -352,7 +749,7 @@ msgstr "zur Mittagszeit am %A"
 
 #: ../IkiWiki/Plugin/prettydate.pm:29
 msgid "%A afternoon"
-msgstr "am %A Nachmittag"
+msgstr "%A am Nachmittag"
 
 #: ../IkiWiki/Plugin/prettydate.pm:32
 msgid "late %A afternoon"
@@ -370,213 +767,355 @@ msgstr "am späten %A Abend"
 msgid "%A night"
 msgstr "%A Nacht"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "zur Teezeit am %A"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "um Mitternacht"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "am Nachmittag des %A"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
-msgid "missing page"
-msgstr "fehlende Seite"
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr "unzulässiger Prozentwert %s"
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+"es werden entweder `percent` oder `totalpages` und `donepages` Parameter "
+"benötigt"
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr "(Diff wurde gekürzt)"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
 #, perl-format
-msgid "The page %s does not exist."
-msgstr "Die Seite %s exisitiert nicht."
+msgid "%s does not exist"
+msgstr "%s existiert nicht"
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s ist nicht im srcdir und kann deshalb nicht gelöscht werden"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr "%s ist keine Datei"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr "bestätigen Sie die Entfernung von %s"
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr "Bitte wählen Sie die zu entfernenden Anhänge aus."
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr "entfernt"
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr "%s ist nicht im srcdir und kann deshalb nicht umbenannt werden"
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr "es wurde keine Änderung des Dateinamens angegeben"
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "%s muss angegeben werden, wenn die Sucherweiterung verwandt wird"
+msgid "illegal name"
+msgstr "unzulässiger Name"
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "bereinige hyperestraier-Suchindex"
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr "%s existiert bereits"
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr "%s existiert bereits auf der Festplatte"
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, perl-format
+msgid "rename %s"
+msgstr "benenne %s um"
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "aktualisiere hyperestraier-Suchindex"
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr "Auch Unterseiten (SubPages) und Anhänge umbenennen"
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
-msgstr "das »shortcut«-Plugin funktioniert nicht ohne eine »shortcuts.mdwn«"
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr "Es kann immer nur ein Anhang gleichzeitig umbenannt werden."
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr "Bitte wählen Sie den Anhang aus, der umbenannt werden soll."
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr "benenne %s in %s um"
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr "aktualisiert zum Umbenennen von %s nach %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr "benötige Digest::SHA1 um einen Index von %s zu erstellen"
+
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr "suchen"
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr "die shortcut Erweiterung wird ohne %s nicht funktionieren"
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "fehlender Name oder URL-Parameter"
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
-msgstr "Shortcut %s zeigt auf <i>%s</i>"
+msgstr "Tastenkürzel %s verweist nach <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
-msgstr "Smileys konnten nicht geparst werden"
+msgstr "Smileys konnten nicht ausgewertet werden"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
-msgstr "Parse-Fehler"
+msgstr "Auswertungsfehler"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
-msgstr "fehlerhafter »featurepoint«-Durchmesser"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
+msgstr "ungültiger featurepoint diameter"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
-msgstr "fehlerhafter »featurepoint«-Ort"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
+msgstr "ungültige featurepoint location"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "fehlende Werte"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
-msgstr "fehlerhafte Höhenangaben"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+msgid "invalid height value"
+msgstr "ungültige Wert für height"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
-msgstr "fehlender Breitenparameter"
+msgstr "fehlender Parameter für width"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
-msgstr "fehlerhafte Breitenangabe"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+msgid "invalid width value"
+msgstr "ungültige Wert für width"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "konnte PHP nicht ausführen"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "konnte Datei nicht finden"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "unbekanntes Datenformat"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "keine Daten"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Direkter Daten-Download"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
-msgstr "Parse-Fehler in Zeile %d: %s"
+msgstr "Auswertungsfehler in Zeile %d: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
-msgstr "fehlender »id«-Parameter"
+msgstr "fehlender Parameter id"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "Vorlage %s nicht gefunden"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
-msgstr "Verarbeitung fehlgeschlagen von:"
+msgstr "Fehler beim Ablauf:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr "fehlender TeX-Code"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr "Code enthält verbotene LaTeX-Befehle"
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 msgid "failed to generate image from code"
 msgstr "konnte kein Bild aus dem Code erzeugen"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
-msgstr "(nicht aus-/einklappbar im Vorschaumodus)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr "Erweiterung"
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "getctime ist nicht implementiert"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr "%s aktivieren?"
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr "Die Einrichtungsdatei für dieses Wiki ist unbekannt"
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr "Hauptseite"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr "Erweiterungen"
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+"Die unten aufgeführten Konfigurationsänderungen erfordern ein Neubau des "
+"Wikis, um wirksam zu werden."
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+"Damit die unten aufgeführten Konfigurationsänderungen insgesamt wirksam "
+"werden, kann es notwendig sein, das Wikis neu zu bauen."
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+"Fehler: %s endet mit nicht Null (%s). Die Änderungen an der Konfiguration "
+"wurden verworfen."
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+"id des nicht vertrauenswürdigen Absenders %s konnte nicht feststellt werden"
+
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr "fehlerhafter Dateiname %s"
 
-#: ../IkiWiki/Render.pm:279 ../IkiWiki/Render.pm:300
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+"symbolischer Verweis im srcdir Pfad (%s) gefunden -- setzen Sie "
+"allow_symlinks_before_srcdir, um dies zu erlauben"
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "überspringe fehlerhaften Dateinamen %s"
 
-#: ../IkiWiki/Render.pm:355
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr "%s hat mehrere mögliche Quellseiten"
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "entferne alte Seite %s"
 
-#: ../IkiWiki/Render.pm:396
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "durchsuche %s"
 
-#: ../IkiWiki/Render.pm:401
-#, perl-format
-msgid "rendering %s"
-msgstr "erzeuge %s"
-
-#: ../IkiWiki/Render.pm:422
+#: ../IkiWiki/Render.pm:447
 #, perl-format
-msgid "rendering %s, which links to %s"
-msgstr "erzeuge %s, was auf %s verweist"
+msgid "building %s, which links to %s"
+msgstr "erzeuge %s, die auf %s verweist"
 
-#: ../IkiWiki/Render.pm:443
+#: ../IkiWiki/Render.pm:468
 #, perl-format
-msgid "rendering %s, which depends on %s"
-msgstr "erzeuge %s, das von %s abhängt"
+msgid "building %s, which depends on %s"
+msgstr "erzeuge %s, die von %s abhängt"
 
-#: ../IkiWiki/Render.pm:482
+#: ../IkiWiki/Render.pm:507
 #, perl-format
-msgid "rendering %s, to update its backlinks"
-msgstr "erzeuge %s, um dessen Rücklinks zu aktualisieren"
+msgid "building %s, to update its backlinks"
+msgstr "erzeuge %s, um dessen Rückverweise zu aktualisieren"
 
-#: ../IkiWiki/Render.pm:494
+#: ../IkiWiki/Render.pm:519
 #, perl-format
-msgid "removing %s, no longer rendered by %s"
+msgid "removing %s, no longer built by %s"
 msgstr "entferne %s, wird nicht länger von %s erzeugt"
 
-#: ../IkiWiki/Render.pm:520
+#: ../IkiWiki/Render.pm:543
 #, perl-format
-msgid "ikiwiki: cannot render %s"
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: kann %s nicht erzeugen"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "kann %s nicht lesen: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "erzeuge Wrapper.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
+"Sie müssen einen Wiki-Namen eingeben (der alphanumerische Zeichen enthält)"
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "erzeuge Wiki neu.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr "nicht unterstütztes Versionskontrollsystem %s"
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "aktualisiere Wiki.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr "erstellen des Depots mit ikiwiki-makerepo ist fehlgeschlagen"
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "fertig"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
+"** Erweiterung %s wurde ausgeschaltet, weil sie mit der folgenden Meldung "
+"fehlgeschlagen ist:"
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -591,46 +1130,95 @@ msgstr "Kann keinen Wrapper erzeugen, der eine Einrichtungsdatei verwendet"
 msgid "wrapper filename not specified"
 msgstr "Dateiname des Wrappers nicht angegeben"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "schreiben von %s fehlgeschlagen: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "erzeugen von %s fehlgeschlagen"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "%s wurde erfolgreich erstellt"
 
 #: ../ikiwiki.in:13
 msgid "usage: ikiwiki [options] source dest"
-msgstr "Benutzung: ikiwiki [Optionen] Quelle Ziel"
+msgstr "Aufruf: ikiwiki [Optionen] Quelle Ziel"
+
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr "       ikiwiki --setup Konfigurationsdatei"
 
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
-msgstr "Benutzung: --set Variable=Wert"
+msgstr "Aufruf: --set Variable=Wert"
+
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "erzeuge Wrapper.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "erzeuge Wiki neu.."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "aktualisiere Wiki.."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Diskussion"
 
-#: ../IkiWiki.pm:115
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
-msgstr "Es muss eine URL zum Wiki mit --url angegeben werden, wenn --cgi verwandt wird"
+msgstr ""
+"Es muss eine URL zum Wiki mit --url angegeben werden, wenn --cgi verwandt "
+"wird"
 
-#: ../IkiWiki.pm:184 ../IkiWiki.pm:185
-msgid "Error"
-msgstr "Fehler"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
+"Es können nicht mehrere Versionskontrollsystem-Erweiterungen verwandt werden"
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr "Laden der für %s benötigten externen Erweiterung fehlgeschlagen: %s"
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:735
+#: ../IkiWiki.pm:1243
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
-msgstr "Präprozessorschleife %s auf Seite %s in Tiefe %i erkannt"
+msgid "preprocessing loop detected on %s at depth %i"
+msgstr "Präprozessorschleife auf %s in Tiefe %i erkannt"
+
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr "ja"
+
+#: ../IkiWiki.pm:1915
+#, perl-format
+msgid "cannot match pages: %s"
+msgstr "Kann die Seiten nicht zuordnen: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr "Wie soll das Wiki heißen?"
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr "Wiki"
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr "Welches Versionskontrollsystem soll verwandt werden?"
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr "Wer (Wiki-Konto oder OpenID) soll Administrator sein?"
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr "Wie lautet der Domainname des Webservers?"
+
+#~ msgid "discussion"
+#~ msgstr "Diskussion"
index 19a2fde56130f805d64556c7a3569b68e8575655..77f1cea6e3bb3666c8e66703dd8eb2cbfcb174d7 100644 (file)
--- a/po/es.po
+++ b/po/es.po
+# translation of es.po to
 # ikiwiki spanish translation
-# Copyright (C) 2007 The Free Software Foundation, Inc
+# Copyright (C) 2007, 2009 The Free Software Foundation, Inc
 # This file is distributed under the same license as the ikiwiki package.
 #
-# Víctor Moral <victor@taquiones.net>, 2007.
+# Víctor Moral <victor@taquiones.net>, 2007, 2009.
+# Victor Moral <victor@taquiones.net>, 2009.
 msgid ""
 msgstr ""
 "Project-Id-Version: es\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
-"PO-Revision-Date: 2008-03-06 11:07+0100\n"
-"Last-Translator: Víctor Moral <victor@taquiones.net>\n"
-"Language-Team: Spanish <es@li.org>\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
+"PO-Revision-Date: 2009-06-14 12:32+0200\n"
+"Last-Translator: Victor Moral <victor@taquiones.net>\n"
+"Language-Team:  <en@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Antes es necesario identificarse."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+"probablemente algo está mal configurado: la característica 'sslcookie' está "
+"activa, pero está intentando registrarse en el sistema vía el protocolo "
+"'http' y no 'https'"
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 "registro fallido, ¿ tal vez necesita activar las cookies en el navegador ?"
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr "Su registro en el sistema ha expirado."
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr "Identificación"
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr "Preferencias"
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr "Administración"
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Las preferencias se han guardado."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "la página %s no es modificable"
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "comentarios"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Ha sido expulsado."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "creando página %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Error"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "modificando página %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr "Contenido añadido activado vía web."
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Ha sido expulsado."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
+"¡ No hay nada que hacer, todas las fuentes de noticias están actualizadas !"
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "falta el parámetro %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "nueva entrada"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "entradas"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "nuevo"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "%s caducada (%s días de antigüedad)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "%s caducada"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "proceso completado con éxito a %s"
+msgid "last checked %s"
+msgstr "última comprobación el %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "comprobando fuente de datos %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "no puedo encontrar la fuente de datos en %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr "fuente de datos no encontrada"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "(una secuencia UTF-8 inválida ha sido eliminada de la fuente de datos)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr "(los caracteres especiales de la fuente de datos están exceptuados)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "¡ la fuente de datos ha provocado un error fatal en XML::Feed !"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "creando nueva página %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr "borrando el directorio.."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "completado"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr "Debe especificar %s"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Creación de directorio en S3 fallida: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "No puedo guardar el archivo en S3: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "No puedo borrar archivo en S3: "
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr "ya existe una página de nombre %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr "prohibido por la claúsula allowed_attachments"
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr "nombre de archivo adjunto erróneo"
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr "enviado el adjunto"
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr "creación de índice automática"
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+"Lo siento, pero el analizador <a href=\"http://blospam.net\">blogspam</a> "
+"dice que el texto puede ser spam."
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr "%s desde la página %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "¡ No hay enlaces rotos !"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr "formato de página %s no soportado"
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr "Un comentario debe tener algún contenido"
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr "Anónimo"
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr "nombre de página erróneo"
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr "creando comentarios en la página %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr "la página '%s' no existe, así que no se puede comentar sobre ella"
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr "los comentarios para la página '%s' están cerrados"
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr "comentario guardado a la espera de aprobación"
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr "Su comentario será publicado después de que el moderador lo revise"
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr "Añadir un comentario"
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr "Comentario añadido: %s"
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr "No está registrado como un administrador"
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr "Aprobación de comentarios"
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr "aprobación de comentarios"
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr "Comentarios"
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr "el parámetro %s es obligatorio"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr "no se ha copiado ningún texto en esta página"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr "no se ha copiado ningún texto con el identificador %s en esta pagina"
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr "eliminando la antigua previsualización %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "la página %s no es modificable"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "creando página %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "modificando página %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 msgid "template not specified"
 msgstr "falta indicar la plantilla (template)"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 msgid "match not specified"
 msgstr "falta indicar la coincidencia de páginas (match)"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr "plantilla de edición %s registrada para %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 msgid "failed to process"
 msgstr "fallo en el proceso"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr "se deben especificar tanto el formato como el texto"
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "el programa fortune ha fallado"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr "página no encontrada"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr "No existe la página %s."
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+#, fuzzy
+msgid "not a page"
+msgstr "no encuentro páginas coincidentes: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "la página %s no es modificable"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr "No puede cambiar %s"
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr "no puede actuar sobre un archivo con permisos %s"
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr "No puede cambiar los permisos de acceso de un archivo"
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Es obligatorio indicar %s cuando se utiliza el complemento de búsqueda"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
 msgstr ""
-"El complemento googlecalendar no ha encontrado un URL en el código html "
+"Error en el análisis del URL, no puedo determinar el nombre del dominio"
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr "no he podido ejecutar el programa graphviz "
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "prog no es un programa graphviz válido "
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "tamaño erróneo \"%s\""
+msgid "tohighlight contains unknown file type '%s'"
+msgstr "la directiva tohighlight contiene el tipo de archivo desconocido '%s' "
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr "Código fuente: %s"
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+"aviso: el módulo Perl hightlight no está disponible; retrocedo la entrada "
+"para continuar el proceso. "
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr "El complemento Image::Magick no ha sido instalado"
+
+#: ../IkiWiki/Plugin/img.pm:72
+#, perl-format
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "no puedo leer de %s: %s "
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
-msgstr "redimensionado fallido: %s"
+msgstr "dimensionamiento fallido: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, perl-format
 msgid "failed to determine size of image %s"
 msgstr "no he podido determinar el tamaño de la imagen %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 "Es obligatorio indicar un url al wiki cuando se usan los parámetros --rss ó "
 "--atom"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr "no está permitida la modificación de páginas"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+msgid "missing pages parameter"
+msgstr "falta el parámetro pages"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+"Se necesita el módulo Sort::Naturally para el tipo de ordenación "
+"title_natural"
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "no conozco este tipo de ordenación %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "Añadir una entrada nueva titulada:"
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "la plantilla %s no existe "
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Comentarios"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "No he encontrado el componente RPC::XML::Client, no envío señal alguna"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "no he podido ejecutar el programa dot"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
+#: ../IkiWiki/Plugin/lockedit.pm:47
 #, perl-format
-msgid "%s is locked by %s and cannot be edited"
-msgstr "La página %s está bloqueada por %s y no puede modificarse"
+msgid "%s is locked and cannot be edited"
+msgstr "La página %s está bloqueada y no puede modificarse"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+"el modo multimarkdown está activo, pero no está instalado Text::MultiMarkdown"
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "no he podido cargar el módulo Perl Markdown.pm (%s) ó no he podido ejecutar "
 "el programa /usr/bin/markdown (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "hoja de estilo no encontrada "
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 msgid "redir page not found"
 msgstr "falta la página a donde redirigir"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 msgid "redir cycle is not allowed"
 msgstr "ciclo de redirección no permitido"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Réplicas"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Réplica"
 
@@ -269,59 +515,202 @@ msgstr "Réplica"
 msgid "more"
 msgstr "ver más"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "la funcionalidad getctime no está incluida"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr "Identificarse mediante "
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Consiga un identificador OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Todas las páginas están referenciadas entre sí."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr "plantilla errónea ó no existente"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Cuenta de usuario creada con éxito. Ahora puede identificarse."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Error creando la cuenta de usuario."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+"No tengo dirección de correo electrónica, así que no puedo enviar "
+"instrucciones para reiniciar la contraseña"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "No he podido enviar el mensaje de correo electrónico"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Se le ha enviado su contraseña por correo electrónico."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+"Las instrucciones para reiniciar la contraseña se le han enviado por correo "
+"electrónico"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr "el url para reiniciar la contraseña es incorrecto"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr "reinicio de contraseña denegado"
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr "Recibida una señal ping."
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr "los parámetros 'from' y 'to' son obligatorios"
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, perl-format
+msgid "Will ping %s"
+msgstr "Informaremos a %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr "Ignorando directiva 'ping' para el wiki %s (este wiki es %s)"
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+msgid "LWP not found, not pinging"
+msgstr "No he encontrado el componente LWP, no envío señal alguna"
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, fuzzy, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s no es un archivo"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "Informaremos a %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, fuzzy, perl-format
+msgid "POT file (%s) does not exist"
+msgstr "No existe la página %s."
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "ha fallado la compilación del programa %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "ha fallado la compilación del programa %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "ha fallado la compilación del programa %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "dimensionamiento fallido: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "dimensionamiento fallido: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "no he podido ejecutar el programa dot"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "no puedo leer de %s: %s "
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "Votar"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Recuento de votos:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "El complemento polygen no ha sido instalado"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "El programa polygen ha fallado"
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
+msgstr "la ejecución del programa ha fallado"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "falta la fórmula"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "fórmula desconocida "
 
@@ -377,215 +766,356 @@ msgstr "a última hora de la tarde del $A"
 msgid "%A night"
 msgstr "la noche del %A"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "el %A a la hora del té"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "a medianoche"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "el %A a media tarde"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
-msgid "missing page"
-msgstr "página no encontrada"
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr "%s es un valor erróneo para un porcentaje"
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr "son necesarios los parámetros 'donepages' y 'percent' ó 'totalpages'"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr "(Lista de diferencias truncada)"
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
 #, perl-format
-msgid "The page %s does not exist."
+msgid "%s does not exist"
 msgstr "No existe la página %s."
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/remove.pm:38
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Es obligatorio indicar %s cuando se utiliza el complemento de búsqueda"
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s no está en el directorio fuente por lo que no puede ser borrada"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr "%s no es un archivo"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr "confirme el borrado de %s"
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr "Por favor seleccione los adjuntos que serán borrados."
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr "borrado"
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr "%s no está en el directorio fuente por lo que no puede ser renombrado"
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr "no se ha indicado cambio alguno en el nombre del archivo"
+
+#: ../IkiWiki/Plugin/rename.pm:68
+#, perl-format
+msgid "illegal name"
+msgstr "nombre no válido"
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "limpiando el índice de búsquedas de hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr "%s ya existe"
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr "%s ya existe en el disco"
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, perl-format
+msgid "rename %s"
+msgstr "cambiando de nombre %s"
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "actualizando el índice de búsquedas de hyperstraier"
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr "También cambia de nombre las subpáginas y los adjuntos"
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
-msgstr "el complemento shortcut no funciona sin una página shortcuts.mdwn"
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr "Únicamente un adjunto puede ser renombrado a la vez."
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr "Por favor, seleccione el adjunto al que cambiar el nombre."
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr "%s cambia de nombre a %s"
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr "actualizado el cambio de nombre de %s a %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr "se necesita la instalación de Digest::SHA1 para indexar %s"
+
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr "buscar"
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr "el complemento shortcut no funcionará si no existe la página %s"
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "shortcut necesita el parámetro 'name' ó el parámetro 'url'"
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "El atajo %s apunta a <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr "Algunos emoticonos tienen errores"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr "error de análisis "
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+#, fuzzy
+msgid "invalid featurepoint diameter"
 msgstr "diámetro inválido "
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+#, fuzzy
+msgid "invalid featurepoint location"
 msgstr "localización errónea "
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "faltan valores"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+#, fuzzy
+msgid "invalid height value"
 msgstr "valor incorrecto para la altura"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
 msgstr "falta el parámetro que indica el ancho"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+#, fuzzy
+msgid "invalid width value"
 msgstr "valor incorrecto para el ancho"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "error fatal invocando el programa php"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "no puedo encontrar el archivo"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "formato de datos desconocido"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "sin datos"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Enlace directo para descarga"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "error de análisis en la línea %d: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr "falta el parámetro \"id\""
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "no he encontrado la plantilla %s"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr "se ha producido un error fatal mientras procesaba la plantilla:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr "falta el código tex"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr "el código incluye órdenes latex anuladas"
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 msgid "failed to generate image from code"
 msgstr "no he podido crear la imagen desde el código"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
-msgstr "(no se puede cambiar en el modo de previsualización)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr "complemento"
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "la funcionalidad getctime no está incluida"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr "¿ activar %s ?"
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr "El archivo de configuración para este wiki es desconocido"
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr "principal"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr "complementos"
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+"Los cambios en la configuración que se muestran más abajo precisan una "
+"reconstrucción del wiki para tener efecto."
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+"Para que los cambios en la configuración mostrados más abajo tengan efecto, "
+"es posible que necesite reconstruir el wiki."
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+"Error: el programa %s finaliza con un código mayor que cero (%s). Descarto "
+"los cambios en la configuración."
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr "no puedo determinar el identificador de un usuario no fiable como %s"
+
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr "el nombre de archivo %s es erróneo"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+"encontrado un enlace simbólico en la ruta del directorio fuente (%s) -- use "
+"la directiva allow_symlinks_before_srcdir para permitir la acción"
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "ignorando el archivo %s porque su nombre no es correcto"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr "%s tiene mútiples páginas fuente posibles"
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "eliminando la antigua página %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "explorando %s"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "convirtiendo %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "convirtiendo la página %s, la cual referencia a %s"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "convirtiendo la página %s, la cual depende de %s"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr ""
 "convirtiendo la página %s para actualizar la lista de páginas que hacen "
 "referencia a ella."
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "eliminando la página %s puesto que ya no se deriva de %s"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
-msgstr "ikwiki: no puedo convertir la página %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
+msgstr "ikiwiki: no puedo convertir la página %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "no puedo leer el archivo %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "generando programas auxiliares.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr "debe escribir un nombre wiki (que contiene caracteres alfanuméricos)"
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "reconstruyendo el wiki.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr "el sistema de control de versiones %s no está soportado"
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "actualizando el wiki.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr "no he podido crear un repositorio con el programa ikiwiki-makerepo"
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "completado"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
+"** Desactivando el complemento %s dado que está fallando con este mensaje:"
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -601,21 +1131,14 @@ msgstr ""
 msgid "wrapper filename not specified"
 msgstr "el programa envoltorio no ha sido especificado"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "no puedo escribir en %s: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "ha fallado la compilación del programa %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "creado con éxito el programa envoltorio %s"
@@ -624,62 +1147,95 @@ msgstr "creado con éxito el programa envoltorio %s"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "uso: ikiwiki [opciones] origen destino"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr "       ikiwiki --setup archivo_de_configuración"
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr "uso: --set variable=valor"
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "generando programas auxiliares.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "reconstruyendo el wiki.."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "actualizando el wiki.."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Comentarios"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr ""
 "Es obligatorio especificar un url al wiki con el parámetro --url si se "
 "utiliza el parámetro --cgi"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Error"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr "no puedo emplear varios complementos rcs"
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr "no he podido cargar el complemento externo %s necesario para %s"
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:1243
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr ""
-"se ha detectado un bucle de preprocesado %s en la página %s en la vuelta "
+"se ha detectado en la página %s un bucle de preprocesado en la iteración "
 "número %i"
 
-#~ msgid ""
-#~ "REV is not set, not running from mtn post-commit hook, cannot send "
-#~ "notifications"
-#~ msgstr ""
-#~ "La variable de entorno REV no está definida, por lo que no puede "
-#~ "funcionar svn post-commit desde monotone; no puedo enviar ninguna "
-#~ "notificación"
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr "si"
 
-#~ msgid "REV is not a valid revision identifier, cannot send notifications"
-#~ msgstr ""
-#~ "REV no es un identificador de revisión válido, por lo que no puedo enviar "
-#~ "ninguna notificación"
+#: ../IkiWiki.pm:1915
+#, perl-format
+msgid "cannot match pages: %s"
+msgstr "no encuentro páginas coincidentes: %s"
 
-#~ msgid ""
-#~ "REV is not set, not running from svn post-commit hook, cannot send "
-#~ "notifications"
-#~ msgstr ""
-#~ "La variable de entorno REV no está definida, por lo que no puede "
-#~ "funcionar svn post-commit; no puedo enviar ninguna notificación"
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr "¿ Qué nombre tendrá el wiki ?"
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr "wiki"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "actualizado el wiki %s y la página %s por el usuario %s"
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr "¿ Qué sistema de control de versiones empleará ?"
 
-#~ msgid "link is no longer supported"
-#~ msgstr "el metadato link ya no puede usarse"
+#: ../auto.setup:20
+#, fuzzy
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+"¿ Qué usuario del wiki (ó qué identificador openid) será el empleado como "
+"administrador ? "
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr "¿ Cuál es el dominio para el servidor web ?"
 
-#~ msgid "%s not found"
-#~ msgstr "no he encontrado la plantilla %s "
+#, fuzzy
+#~ msgid "discussion"
+#~ msgstr "Comentarios"
 
-#~ msgid "What's this?"
-#~ msgstr "¿ Qué es esto ?"
+#~ msgid "rendering %s"
+#~ msgstr "convirtiendo %s"
+
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr ""
+#~ "Es obligatorio indicar %s cuando se utiliza el complemento de búsqueda de "
+#~ "google"
 
-#~ msgid "(use FirstnameLastName)"
-#~ msgstr "(utilice la forma NombreApellidos)"
+#~ msgid "bad size \"%s\""
+#~ msgstr "tamaño erróneo \"%s\""
index 438200a49e0a86f647f66be23e7388077a5f8512..df3b238915732492c0f10a23b88e5da99e31a6e9 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
 # Cyril Brulebois <cyril.brulebois@enst-bretagne.fr>, 2007.
 msgid ""
 msgstr ""
-"Project-Id-Version: \n"
+"Project-Id-Version: ikiwiki 3.141\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-04-16 18:36-0400\n"
-"PO-Revision-Date: 2008-04-29 17:46+0200\n"
-"Last-Translator: Christian Perrier <bubulle@debian.org>\n"
+"POT-Creation-Date: 2009-08-25 18:43-0400\n"
+"PO-Revision-Date: 2009-08-17 10:06+0200\n"
+"Last-Translator: Philippe Batailler <philippe.batailler@free.fr>\n"
 "Language-Team: French <debian-l10n-french@lists.debian.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 1.11.4\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Vous devez d'abord vous identifier."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+"Erreur de configuration probable : sslcookie est positionné mais vous tentez "
+"de vous connecter avec http au lieu de https"
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
-msgstr "Échec de l'identification, vous devriez peut-être autoriser les cookies."
+msgstr "Échec de l'identification, vous devez autoriser les cookies."
 
-#: ../IkiWiki/CGI.pm:173 ../IkiWiki/CGI.pm:499
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
 msgid "Your login session has expired."
 msgstr "Session d'authentification expirée."
 
-#: ../IkiWiki/CGI.pm:194
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr "S’identifier"
 
-#: ../IkiWiki/CGI.pm:195
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr "Préférences"
 
-#: ../IkiWiki/CGI.pm:196
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr "Administrateur"
 
-#: ../IkiWiki/CGI.pm:248
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Les préférences ont été enregistrées."
 
-#: ../IkiWiki/CGI.pm:306
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "%s n'est pas une page éditable"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Vous avez été banni."
 
-#: ../IkiWiki/CGI.pm:410 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:265 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:172
-msgid "discussion"
-msgstr "Discussion"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1269
+msgid "Error"
+msgstr "Erreur"
 
-#: ../IkiWiki/CGI.pm:466
-#, perl-format
-msgid "creating %s"
-msgstr "Création de %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr "Agrégation déclenchée par le web"
 
-#: ../IkiWiki/CGI.pm:484 ../IkiWiki/CGI.pm:512 ../IkiWiki/CGI.pm:522
-#: ../IkiWiki/CGI.pm:556 ../IkiWiki/CGI.pm:601
-#, perl-format
-msgid "editing %s"
-msgstr "Édition de %s"
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr "Rien à faire pour le moment, tous les flux sont à jour !"
 
-#: ../IkiWiki/CGI.pm:691
-msgid "You are banned."
-msgstr "Vous avez été banni."
-
-#: ../IkiWiki/Plugin/aggregate.pm:101
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "Paramètre %s manquant"
 
-#: ../IkiWiki/Plugin/aggregate.pm:128
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "Nouveau flux"
 
-#: ../IkiWiki/Plugin/aggregate.pm:142
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "Articles"
 
-#: ../IkiWiki/Plugin/aggregate.pm:144
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "Nouveau"
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "Fin de validité de %s (date de %s jours)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:314
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "Fin de validité de %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:341
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "A été correctement traité à %s"
+msgid "last checked %s"
+msgstr "dernière vérification : %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:345
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "Vérification du flux %s..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:350
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "Impossible de trouver de flux à %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:365
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr "Flux introuvable "
 
-#: ../IkiWiki/Plugin/aggregate.pm:376
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "(chaîne UTF-8 non valable supprimée du flux)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:382
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr "(échappement des entités de flux)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:388
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "Plantage du flux XML::Feed !"
 
-#: ../IkiWiki/Plugin/aggregate.pm:462
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "Création de la nouvelle page %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr "Suppression du compartiment S3 (« bucket »)..."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "Terminé"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr "Vous devez spécifier %s"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+msgid "Failed to create S3 bucket: "
+msgstr "Impossible de créer un compartiment S3 :"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+msgid "Failed to save file to S3: "
+msgstr "Impossible de sauvegarder le fichier dans le compartiment S3 :"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+msgid "Failed to delete file from S3: "
+msgstr "Échec lors de la suppression du fichier sur S3 :"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr "Il existe déjà une page nommée %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr "Action interdite par allowed_attachments"
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr "Nom de la pièce jointe incorrect"
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr "Envoi de la pièce jointe"
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr "Génération de l'index automatique"
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+"Désolé, mais cela ressemble à un « spam » selon les critères de <a href="
+"\"http://blogspam.net/\">blogspam</a> : "
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr "%s sur %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
-msgstr "Il n'existe pas de lien cassé !"
+msgstr "Aucun lien cassé !"
+
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr "Format de page non reconnu %s"
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr "Un commentaire doit avoir un contenu."
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr "Anonyme"
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr "Nom de page incorrect"
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr "Faire un commentaire sur %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr "La page '%s' n'existe pas, commentaire impossible."
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr "Le commentaire pour la page '%s' est terminé."
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr "Le commentaire a été enregistré, en attente de « modération »"
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr "Votre commentaire sera publié après vérification par le modérateur"
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr "Commentaire ajouté"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr "Commentaire ajouté : %s"
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr "Vous n'êtes pas authentifié comme administrateur"
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr "Modération du commentaire"
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr "modération du commentaire"
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr "Commentaires"
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
-msgstr "le paramètre %s est obligatoire"
+msgstr "Le paramètre %s est obligatoire"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr "Aucun texte n'a été copié dans cette page"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr "Aucun texte n'a été copié dans cette page avec l'identifiant %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr "Suppression de l'ancienne prévisualisation %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "%s n'est pas une page éditable"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "Création de %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "Édition de %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 msgid "template not specified"
 msgstr "modèle (« template ») non indiqué"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 msgid "match not specified"
 msgstr "correspondance non indiquée"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr "edittemplate %s enregistré pour %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 msgid "failed to process"
 msgstr "Échec du traitement"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr "le format et le texte doivent être indiqués"
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "Échec du lancement de « fortune »"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
-msgstr "Échec dans la recherche d'une URL dans le Code HTML"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr "Page manquante"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr "La page %s n'existe pas."
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+msgid "not a page"
+msgstr "Ce n'est pas une page."
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "%s est une pièce jointe, pas une page."
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr "Vous n'êtes pas autorisé à modifier %s"
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr "Vous ne pouvez pas modifier un fichier dont le mode est %s"
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr "Vous n'êtes pas autorisé à modifier le mode des fichiers"
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Vous devez indiquer %s lors de l'utilisation du greffon %s."
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr "Impossible d'analyser l'URL, pas de nom de domaine"
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr "Échec du lancement de graphviz"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "Ce programme n'est pas un programme graphviz valable"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "taille incorrecte « %s »"
+msgid "tohighlight contains unknown file type '%s'"
+msgstr "tohighlight contient un type de fichier inconnu : '%s'"
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr "Code source : %s"
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+"Avertissement : le module perl « highlight » n'est pas disponible. "
+"Continuation malgré tout."
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr "Image::Magick n'est pas installé"
+
+#: ../IkiWiki/Plugin/img.pm:72
+#, perl-format
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr "Format de la taille incorrect \"%s\", (devrait être LxH)"
+
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "Échec de la lecture de %s : %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr "Échec du redimensionnement : %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, perl-format
 msgid "failed to determine size of image %s"
 msgstr "Échec de la détermination de la taille de l'image : %s"
 
-#: ../IkiWiki/Plugin/inline.pm:46
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 "Vous devez indiquer l'URL du wiki par --url lors de l'utilisation de --rss "
 "ou --atom"
 
-#: ../IkiWiki/Plugin/inline.pm:153
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr "Modification de page interdite"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+msgid "missing pages parameter"
+msgstr "Paramètre « pages » manquant"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr "Les paramètres %s et %s ne peuvent être utilisés ensemble."
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr "Sort::Naturally est nécessaire pour un tri « title_natural »"
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "Type de tri %s inconnu"
 
-#: ../IkiWiki/Plugin/inline.pm:224
+#: ../IkiWiki/Plugin/inline.pm:329
 msgid "Add a new post titled:"
 msgstr "Ajouter un nouvel article dont le titre est :"
 
-#: ../IkiWiki/Plugin/inline.pm:240
+#: ../IkiWiki/Plugin/inline.pm:349
 #, perl-format
 msgid "nonexistant template %s"
-msgstr "Le modèle (« template ») %s n'existe pas"
+msgstr "Le modèle de page %s n'existe pas"
 
-#: ../IkiWiki/Plugin/inline.pm:273 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Discussion"
-
-#: ../IkiWiki/Plugin/inline.pm:500
+#: ../IkiWiki/Plugin/inline.pm:614
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "RPC::XML::Client introuvable, pas de réponse au ping"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "Échec du lancement de dot"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
+#: ../IkiWiki/Plugin/lockedit.pm:47
 #, perl-format
-msgid "%s is locked by %s and cannot be edited"
-msgstr "%s est verrouillé par %s et ne peut être édité"
+msgid "%s is locked and cannot be edited"
+msgstr "%s est verrouillé et ne peut être modifié"
+
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr "mulitmarkdown est activé mais Text::Multimarkdown n'est pas installé"
 
-#: ../IkiWiki/Plugin/mdwn.pm:42
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "Échec du chargement du module Perl Markdown.pm (%s) ou de /usr/bin/markdown "
 "(%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:132
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "Feuille de style introuvable "
 
-#: ../IkiWiki/Plugin/meta.pm:166
+#: ../IkiWiki/Plugin/meta.pm:196
 msgid "redir page not found"
-msgstr "Page de redirection introuvable "
+msgstr "Page de redirection introuvable"
 
-#: ../IkiWiki/Plugin/meta.pm:179
+#: ../IkiWiki/Plugin/meta.pm:210
 msgid "redir cycle is not allowed"
 msgstr "Redirection cyclique non autorisée"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Miroirs"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Miroir"
 
@@ -274,59 +503,214 @@ msgstr "Miroir"
 msgid "more"
 msgstr "lire la suite"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime n'est pas implémenté"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr "S'identifier en tant que"
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Obtenir un compte OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+msgid "All pages have other pages linking to them."
 msgstr "Toutes les pages sont liées à d'autres pages."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
-msgstr "Modèle incorrect ou manquant"
+msgstr "Modèle de page incorrect ou manquant"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Le compte a été créé. Vous pouvez maintenant vous identifier."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Erreur lors de la création du compte."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+"Aucune adresse indiquée. Impossible d'envoyer les instructions pour "
+"réinitialiser le mot de passe."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
-msgstr "Échec de l'envoi du courriel"
+msgstr "Impossible d'envoyer un courriel"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+"Vous avez reçu un message contenant les instructions pour réinitialiser le "
+"mot de passe"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr "Adresse pour la réinitialisation du mot de passe incorrecte"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr "réinitialisation du mot de passe refusée"
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr "Ping reçu"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Votre mot de passe vous a été envoyé par courriel."
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr "les paramètres « from » et « to » sont nécessaires."
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, perl-format
+msgid "Will ping %s"
+msgstr "va envoyer un ping à %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr "Les instructions du wiki %s sont ignorées (ce wiki est %s)"
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+msgid "LWP not found, not pinging"
+msgstr "LWP est introuvable. Pas de réponse au ping"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+"Note : ancienne version de po4a détectée. Il est recommandé d'installer la "
+"version 0.35."
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s n'est pas un code de langue valable"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+"%s n'est pas une valeur correcte pour po_link_to, retour à la valeur par "
+"défaut."
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+"po_link_to=negotiated nécessite que usedirs soit activé, retour à "
+"po_link_to=default."
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+"Reconstruction de toutes les pages pour corriger les titres (greffon "
+"« meta »)."
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, perl-format
+msgid "building %s"
+msgstr "construction de %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr "Fichiers PO mis à jour."
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+"Impossible de supprimer cette traduction. Si la page maître est supprimée, "
+"alors ses traductions seront supprimées."
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+"Impossible de renommer cette traduction. Si la page maître est renommée, "
+"alors ses traductions pourront être renommées."
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr "Le fichier POT %s n'existe pas."
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "Impossible de copier le fichier PO underlay dans %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, perl-format
+msgid "failed to update %s"
+msgstr "Impossible de mettre à jour %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "Impossible de copier le fichier POT dans %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr "N/A"
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, perl-format
+msgid "failed to translate %s"
+msgstr "Impossible de traduire %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr "Fichiers PO obsolètes supprimés."
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, perl-format
+msgid "failed to write %s"
+msgstr "Impossible de modifier %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+msgid "failed to translate"
+msgstr "Impossible de traduire"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, perl-format
+msgid "failed to read %s"
+msgstr "Impossible de lire %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+"Données gettext incorrectes, retour à la page précédente pour la poursuite "
+"des modifications."
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "Voter"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Total des suffrages :"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "polygen n'est pas installé"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "Échec du lancement de polygen"
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
+msgstr "Échec de la commande"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "formule manquante"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "formule inconnue"
 
@@ -368,231 +752,367 @@ msgstr "%A après-midi"
 
 #: ../IkiWiki/Plugin/prettydate.pm:32
 msgid "late %A afternoon"
-msgstr "tard l'après-midi de %A"
+msgstr "tard dans l'après-midi de %A"
 
 #: ../IkiWiki/Plugin/prettydate.pm:33
 msgid "%A evening"
-msgstr "%A soir"
+msgstr "%A en soirée"
 
 #: ../IkiWiki/Plugin/prettydate.pm:35
 msgid "late %A evening"
-msgstr "tard %A soir"
+msgstr "tard %A en soirée"
 
 #: ../IkiWiki/Plugin/prettydate.pm:37
 msgid "%A night"
 msgstr "%A, durant la nuit"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "%A, à l'heure du thé"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "à minuit"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "%A, à midi"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
-msgid "missing page"
-msgstr "Page manquante"
-
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/progress.pm:34
 #, perl-format
-msgid "The page %s does not exist."
-msgstr "La page %s n'existe pas."
+msgid "illegal percent value %s"
+msgstr "pourcentage %s illégal"
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+"L'un des paramètres « percent », « totalpages » ou « donepages » est nécessaire."
 
-#: ../IkiWiki/Plugin/recentchangesdiff.pm:26
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
 msgid "(Diff truncated)"
 msgstr "(fichier de différences tronqué)"
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr "%s n'existe pas"
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s n'est pas dans srcdir et ne peut donc pas être supprimé"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr "%s n'est pas un fichier"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr "Suppression de %s confirmée"
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr "Veuillez choisir la pièce jointe à supprimer"
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr "supprimé"
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr "%s n'est pas dans srcdir. Impossible de le renommer"
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr "Aucun changement dans le nom du fichier n'a été spécifié"
+
+#: ../IkiWiki/Plugin/rename.pm:68
+#, perl-format
+msgid "illegal name"
+msgstr "Appellation interdite"
+
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr "%s existe déjà"
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr "%s existe déjà sur le disque"
+
+#: ../IkiWiki/Plugin/rename.pm:122
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Vous devez indiquer %s lors de l'utilisation du greffon de recherche"
+msgid "rename %s"
+msgstr "%s renommé"
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "Nettoyage de l'index de recherche de hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr "« SubPages » et attachements renommés."
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "Mise à jour de l'index de recherche de hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr "Modification de pièce jointe : une seule à la fois"
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
-msgstr "Le greffon de raccourci (« shortcut ») ne fonctionnera pas sans shortcuts.mdwn"
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr "Veuillez sélectionner la pièce jointe à renommer"
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr "Renomme %s en %s"
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr "mise à jour, suite au changement de %s en %s"
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr "Digest::SHA1 est nécessaire pour indexer %s"
+
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr "recherche"
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr "Le greffon « shortcut » ne fonctionnera pas sans %s"
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "Il manque le paramètre nom ou URL."
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "Le raccourci %s pointe vers <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:32
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr "Aucun smiley n'a pu être analysé"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr "Erreur d'analyse"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
 msgstr "Diamètre du point incorrect"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
 msgstr "Emplacement du point incorrect"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "Il manque des valeurs"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+msgid "invalid height value"
 msgstr "Hauteur incorrecte"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
-msgstr "Le paramètre de largeur manque dans le modèle (« template »)"
+msgstr "Le paramètre largeur manque"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+msgid "invalid width value"
 msgstr "Largeur incorrecte"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "Échec du lancement de php"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "Fichier introuvable"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "Format de données inconnu"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
-msgstr "Données vides"
+msgstr "Pas de données"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Téléchargement direct des données"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "Erreur d'analyse à la ligne %d : %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr "Paramètre d'identification manquant"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
-msgstr "Modèle (« template ») %s introuvable "
+msgstr "Modèle de page %s introuvable"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr "Échec du traitement :"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr "Il manque le code TeX"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr "Le code comporte des commandes LaTeX non permises"
 
-#: ../IkiWiki/Plugin/teximg.pm:88
+#: ../IkiWiki/Plugin/teximg.pm:128
 msgid "failed to generate image from code"
 msgstr "Échec de la création de l'image à partir du code"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
-msgstr "(non permutable en mode prévisualisation)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr "greffon"
 
-#: ../IkiWiki/Rcs/Stub.pm:69
-msgid "getctime not implemented"
-msgstr "getctime n'est pas implémenté"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr "activer %s ?"
 
-#: ../IkiWiki/Render.pm:289 ../IkiWiki/Render.pm:310
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr "Le fichier de configuration de ce wiki n'est pas connu"
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr "Partie principale"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr "Greffons"
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+"Les changements de configuration ci-dessous nécessitent une recompilation du "
+"wiki pour prendre effet"
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+"Pour que les changements de configuration ci-dessous prennent effet vous "
+"devez recompiler le wiki"
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr "Erreur : %s s'est terminé anormalement (%s). Modifications ignorées."
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+"Impossible de déterminer l'identifiant de %s, (enregistrement non fiable)"
+
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr "Nom de fichier incorrect %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+"Lien symbolique trouvé dans l'adresse de srcdir (%s) -- pour l'autoriser, "
+"activez le paramètre « allow_symlinks_before_srcdir »."
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "Omission du fichier au nom incorrect %s"
 
-#: ../IkiWiki/Render.pm:365
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr "%s peut être associé à plusieurs pages source."
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "Suppression de l'ancienne page %s"
 
-#: ../IkiWiki/Render.pm:406
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
-msgstr "Parcours de %s"
+msgstr "Examen de %s"
 
-#: ../IkiWiki/Render.pm:411
+#: ../IkiWiki/Render.pm:447
 #, perl-format
-msgid "rendering %s"
-msgstr "Affichage de %s"
+msgid "building %s, which links to %s"
+msgstr "Reconstruction de %s, qui est lié à %s"
 
-#: ../IkiWiki/Render.pm:432
+#: ../IkiWiki/Render.pm:473
 #, perl-format
-msgid "rendering %s, which links to %s"
-msgstr "Affichage de %s, qui est lié à %s"
+msgid "building %s, which depends on %s"
+msgstr "Reconstruction de %s, qui dépend de %s"
 
-#: ../IkiWiki/Render.pm:453
+#: ../IkiWiki/Render.pm:513
 #, perl-format
-msgid "rendering %s, which depends on %s"
-msgstr "Affichage de %s, qui dépend de %s"
+msgid "building %s, to update its backlinks"
+msgstr "Reconstruction de %s, afin de mettre à jour ses rétroliens"
 
-#: ../IkiWiki/Render.pm:492
+#: ../IkiWiki/Render.pm:525
 #, perl-format
-msgid "rendering %s, to update its backlinks"
-msgstr "Affichage de %s, afin de mettre à jour ses rétroliens"
+msgid "removing %s, no longer built by %s"
+msgstr "Suppression de %s, qui n'est plus rendu par %s"
 
-#: ../IkiWiki/Render.pm:504
+#: ../IkiWiki/Render.pm:549
 #, perl-format
-msgid "removing %s, no longer rendered by %s"
-msgstr "Suppression de %s, qui n'est plus affiché par %s"
-
-#: ../IkiWiki/Render.pm:530
-#, perl-format
-msgid "ikiwiki: cannot render %s"
-msgstr "ikiwiki : impossible d'afficher %s"
+msgid "ikiwiki: cannot build %s"
+msgstr "ikiwiki : impossible de reconstruire %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "Lecture impossible de %s : %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "Création des fichiers CGI..."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
+"Vous devez spécifier un nom de wiki (contenant des caractères "
+"alphanumériques)"
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "Reconstruction du wiki..."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr "Système de contrôle de version non reconnu : %s"
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "Rafraîchissement du wiki..."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr "Échec lors de la création du dépôt avec ikiwiki-makerepo"
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "Terminé"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
+"** Désactivation du greffon %s, l'installation a échoué avec le message "
+"suivant :"
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -601,27 +1121,21 @@ msgstr "%s ne semble pas être exécutable"
 
 #: ../IkiWiki/Wrapper.pm:20
 msgid "cannot create a wrapper that uses a setup file"
-msgstr "Impossible de créer un fichier CGI utilisant un fichier de configuration"
+msgstr ""
+"Impossible de créer un fichier CGI utilisant un fichier de configuration"
 
 #: ../IkiWiki/Wrapper.pm:24
 msgid "wrapper filename not specified"
-msgstr "Le nom de fichier de l'enrobage n'a pas été indiqué"
-
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "Échec de l'écriture de %s : %s"
+msgstr "Le nom du fichier CGI n'a pas été indiqué"
 
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "Échec de la compilation de %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "%s a été créé avec succès"
@@ -630,26 +1144,91 @@ msgstr "%s a été créé avec succès"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "Syntaxe : ikiwiki [options] source destination"
 
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr "       ikiwiki --setup fichier de configuration"
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr "Syntaxe : -- set var=valeur"
 
-#: ../IkiWiki.pm:117
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "Création des fichiers CGI..."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "Reconstruction du wiki..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "Rafraîchissement du wiki..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Discussion"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr ""
-"Vous devez indiquer une URL vers le wiki par --url lors de l'utilisation de "
-"--cgi"
+"Vous devez indiquer l'URL du wiki par --url lors de l'utilisation de --cgi"
 
-#: ../IkiWiki.pm:186 ../IkiWiki.pm:187
-msgid "Error"
-msgstr "Erreur"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr "Impossible d'utiliser plusieurs systèmes de contrôle des versions"
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr "Impossible de charger le greffon externe nécessaire au greffon %s : %s"
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:1251
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
-msgstr "%s une boucle a été détectée dans le prétraitement de %s, à la profondeur %i"
+msgid "preprocessing loop detected on %s at depth %i"
+msgstr "Une boucle de prétraitement a été détectée sur %s à hauteur de %i"
+
+#: ../IkiWiki.pm:1791
+msgid "yes"
+msgstr "oui"
+
+#: ../IkiWiki.pm:1915
+#, perl-format
+msgid "cannot match pages: %s"
+msgstr "Impossible de trouver les pages %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr "Nom du wiki :"
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr "wiki"
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr "Système de contrôle de version utilisé :"
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr "Identifiant de l'administrateur (utilisateur du wiki ou openid) :"
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr "Nom de domaine du serveur HTTP :"
+
+#~ msgid "discussion"
+#~ msgstr "Discussion"
+
+#~ msgid "rendering %s"
+#~ msgstr "Reconstruction de %s"
+
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "Vous devez indiquer %s lors de l'utilisation du greffon « google »."
+
+#~ msgid "bad size \"%s\""
+#~ msgstr "taille incorrecte « %s »"
 
+#~ msgid "<p class=\"error\">Error: %s exited nonzero (%s)"
+#~ msgstr ""
+#~ "<p class=\"erreur\">Erreur : %s s'est terminé, valeur de sortie nonzero (%"
+#~ "s)"
index 0efa3c0387996c3088eba9500337b34d24ea50ef..d7e6eaa6aeee748a1afa39fa381bbb45ea077257 100644 (file)
--- a/po/gu.po
+++ b/po/gu.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki-gu\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-01-11 16:05+0530\n"
 "Last-Translator: Kartik Mistry <kartik.mistry@gmail.com>\n"
 "Language-Team: Gujarati <team@utkarsh.org>\n"
@@ -15,253 +15,489 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "તમારે પ્રથમ લોગ ઇન થવું પડશે."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr "પ્રવેશ નિષ્ફળ, કદાચ તમારી કુકીઓ સક્રિય બનાવવી પડશે?"
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 #, fuzzy
 msgid "Preferences"
 msgstr "પ્રાથમિકતાઓ સંગ્રહાઇ."
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "પ્રાથમિકતાઓ સંગ્રહાઇ."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "%s એ સુધારી શકાય તેવું પાનું નથી"
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "ચર્ચા"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "તમારા પર પ્રતિબંધ છે."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "%s બનાવે છે"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "ક્ષતિ"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "%s સુધારે છે"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "તમારા પર પ્રતિબંધ છે."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr "ખોવાયેલ %s વિકલ્પ"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "નવું ફીડ"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "પોસ્ટ"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "નવું"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "જુનું કરે છે %s (%s દિવસો જુનું)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "જુનું કરે છે %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "આના પર બરાબર છે %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "ફીડ %s ચકાસે છે ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "%s પર ફીડ મળી શક્યું નહી"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr "ફીડ મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, fuzzy, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "ફીડમાંથી અયોગ્ય રીતે UTF-8 નીકાળેલ છે"
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "ફીડ ભાંગી ગયું XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "નવું પાનું %s બનાવે છે"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "સંપૂર્ણ"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "મેઇલ મોકલવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "મેઇલ મોકલવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "માપ બદલવામાં નિષ્ફળ: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "અહીં કોઇ તૂટેલ કડી નથી!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "%s બનાવે છે"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, fuzzy, perl-format
 msgid "%s parameter is required"
 msgstr "\"test\" અને \"then\" વિકલ્પો જરૂરી છે"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "જુનાં પાનાં દૂર કરે છે %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "%s એ સુધારી શકાય તેવું પાનું નથી"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "%s બનાવે છે"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "%s સુધારે છે"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "ટેમ્પલેટ %s મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "આવરણ ફાઇલનામ સ્પષ્ટ કરેલ નથી"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "ક્રિયા કરવામાં નિષ્ફળ:"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "ભવિષ્ય નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
-msgstr "htmlમાં યુઆરએલ શોધવામાં નિષ્ફળ"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "ખોવાયેલ કિંમતો"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+#, fuzzy
+msgid "not a page"
+msgstr "વાંચી શકાતી નથી %s: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "%s એ સુધારી શકાય તેવું પાનું નથી"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "જ્યારે શોધ પ્લગઇન ઉપયોગ કરતા હોવ ત્યારે %s સ્પષ્ટ કરવું જ પડશે"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr "ગ્રાફવિઝ ચલાવવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "કાર્યક્રમએ યોગ્ય ગ્રાફવિઝ કાર્યક્રમ નથી"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "પોલિગોન સ્થાપિત નથી"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "અયોગ્ય માપ \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr "%s વાંચવામાં નિષ્ફળ: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr "માપ બદલવામાં નિષ્ફળ: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "માપ બદલવામાં નિષ્ફળ: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr "--rss અથવા --atom ઉપયોગ કરતી વખતે વીકીમાં --url ઉપયોગ કરવું જ પડશે"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "ફીડ મળ્યું નહી"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "ખોવાયેલ %s વિકલ્પ"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "અજાણ્યો ગોઠવણી પ્રકાર %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "આ શિર્ષકથી નવું પોસ્ટ ઉમેરો:"
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "અસ્તિત્વમાં ન હોય તેવું ટેમ્પલેટ %s"
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "ચર્ચા"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "RPC::XML::Client મળ્યું નહી, પિંગ કરવામાં આવતું નથી"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr "ડોટ ચલાવવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr "%s એ %s દ્વારા તાળું મરાયેલ છે અને તેમાં સુધારો કરી શકાશે નહી"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr "Markdown.pm પર્લ મોડ્યુલ (%s) અથવા /usr/bin/markdown (%s) લાવવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr "સ્ટાઇલશીટ મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "ફીડ મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "ફીડ મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "મિરરો"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "મિરર"
 
@@ -269,59 +505,200 @@ msgstr "મિરર"
 msgid "more"
 msgstr "વધુ"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime અમલમાં મૂકાયેલ નથી"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "ઓપનઆઇડી મેળવો"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "બધા પાનાંઓ બીજા પાનાંઓ વડે જોડાયેલ છે."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "ખાતું બનાવવાનું સફળ. તમે હવે લોગઇન કરી શકો છો."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "ખાતું બનાવવામાં ક્ષતિ."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "મેઇલ મોકલવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "તમારો પાસવર્ડ તમને ઇમેઇલ કરવામાં આવ્યો છે."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "%s સુધારે છે"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "RPC::XML::Client મળ્યું નહી, પિંગ કરવામાં આવતું નથી"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, fuzzy, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s એ સુધારી શકાય તેવું પાનું નથી"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "%s સુધારે છે"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "%s કમ્પાઇલ કરવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "%s કમ્પાઇલ કરવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "%s કમ્પાઇલ કરવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "માપ બદલવામાં નિષ્ફળ: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "%s લખવામાં નિષ્ફળ: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "ડોટ ચલાવવામાં નિષ્ફળ"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "%s વાંચવામાં નિષ્ફળ: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "મત"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "કુલ મત:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "પોલિગોન સ્થાપિત નથી"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "પોલિગોન નિષ્ફળ"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "ભવિષ્ય નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "ખોવાયેલ સૂત્ર"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "અજાણ્યું સૂત્ર"
 
@@ -378,216 +755,348 @@ msgstr "મોડા %A સાંજે"
 msgid "%A night"
 msgstr "%A રાત્રે"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "ચા ના સમયે %A પર"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "મધ્યરાત્રે"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "બપોરે %A પર"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s એ %s દ્વારા તાળું મરાયેલ છે અને તેમાં સુધારો કરી શકાશે નહી"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, fuzzy, perl-format
+msgid "%s is not a file"
+msgstr "%s એ સુધારી શકાય તેવું પાનું નથી"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "àª\96à«\8bવાયà«\87લ àª\95િàª\82મતà«\8b"
+msgid "no change to the file name was specified"
+msgstr "àª\86વરણ àª«àª¾àª\87લનામ àª¸à«\8dપષà«\8dàª\9f àª\95રà«\87લ àª¨àª¥à«\80"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "જ્યારે શોધ પ્લગઇન ઉપયોગ કરતા હોવ ત્યારે %s સ્પષ્ટ કરવું જ પડશે"
+msgid "%s already exists"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "રેન્ડર કરે છે %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "%s નો સુધારો %s નાં %s વડે"
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "હાયપરસ્ટ્રેઇઝર શોધ અનુક્રમણિકા સાફ કરે છે"
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "હાયપરસ્ટ્રેઇઝર શોધ અનુક્રમણિકા સુધારે છે"
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr "ખોવાયેલ નામ અથવા યુઆરએલ વિકલ્પ"
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "ટુંકોરસ્તો %s એ <i>%s</i> નો નિર્દેશ કરે છે"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr "કોઇપણ સ્માઇલીઓ ઉકેલવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr "ઉકેલવામાં ક્ષતિ"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+#, fuzzy
+msgid "invalid featurepoint diameter"
 msgstr "ખરાબ લાક્ષણિકબિંદુ વ્યાસ"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+#, fuzzy
+msgid "invalid featurepoint location"
 msgstr "ખરાબ લાક્ષણિકબિંદુ સ્થિતિ"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "ખોવાયેલ કિંમતો"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+#, fuzzy
+msgid "invalid height value"
 msgstr "ખરાબ ઉંચાઇ કિંમત"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
 msgstr "ખોવાયેલ પહોળાઇ વિકલ્પ"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+#, fuzzy
+msgid "invalid width value"
 msgstr "ખરાબ પહોળાઇ કિંમત"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr "php ચલાવવામાં નિષ્ફળ"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "ફાઇલ મળી શકી નહી"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "અજાણ્યો માહિતી પ્રકાર"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "ખાલી માહિતી"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "સીધી માહિતી ડાઉનલોડ"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "ઉકેલવાનું લીટી %d પર નિષ્ફળ: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr "ખોવાયેલ આઇડી વિકલ્પ"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "ટેમ્પલેટ %s મળ્યું નહી"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr "ક્રિયા કરવામાં નિષ્ફળ:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 #, fuzzy
 msgid "missing tex code"
 msgstr "ખોવાયેલ કિંમતો"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "માપ બદલવામાં નિષ્ફળ: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "getctime અમલમાં મૂકાયેલ નથી"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "ખરાબ ફાઇલ નામ છોડી દે છે %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "ખરાબ ફાઇલ નામ છોડી દે છે %s"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "જુનાં પાનાં દૂર કરે છે %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "%s શોધે છે"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "રેન્ડર કરે છે %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "રેન્ડર કરે છે %s, જે %s સાથે જોડાણ ધરાવે છે"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "રેન્ડર કરે છે %s, જે %s પર આધારિત છે"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "રેન્ડર કરે છે %s, તેનાં પાછળનાં જોડાણો સુધારવા માટે"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "દૂર કરે છે %s, હવે %s વડે રેન્ડર કરાતું નથી"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: %s રેન્ડર કરી શકાતું નથી"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "વાંચી શકાતી નથી %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "આવરણ બનાવે છે.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "વીકી ફરીથી બનાવે છે.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "વીકીને તાજી કરે છે.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "સંપૂર્ણ"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -602,21 +1111,14 @@ msgstr "ગોઠવણ ફાઇલનો ઉપયોગ કરે છે ત
 msgid "wrapper filename not specified"
 msgstr "આવરણ ફાઇલનામ સ્પષ્ટ કરેલ નથી"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "%s લખવામાં નિષ્ફળ: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "%s કમ્પાઇલ કરવામાં નિષ્ફળ"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "સફળતાપૂર્વક પેદા કરેલ છે %s"
@@ -625,27 +1127,108 @@ msgstr "સફળતાપૂર્વક પેદા કરેલ છે %s"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "ઉપયોગ: ikiwiki [વિકલ્પો] source dest"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "આવરણ બનાવે છે.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "વીકી ફરીથી બનાવે છે.."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "વીકીને તાજી કરે છે.."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "ચર્ચા"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr "જ્યારે --cgi ઉપયોગ કરતાં હોય ત્યારે વીકીનું યુઆરએલ સ્પષ્ટ કરવું જ પડશે"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "ક્ષતિ"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "%s પર શોધાયેલ લુપ  %s પર ચલાવે છે %i ઉંડાણ પર"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "વાંચી શકાતી નથી %s: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "ચર્ચા"
+
+#~ msgid "rendering %s"
+#~ msgstr "રેન્ડર કરે છે %s"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "જ્યારે શોધ પ્લગઇન ઉપયોગ કરતા હોવ ત્યારે %s સ્પષ્ટ કરવું જ પડશે"
+
+#~ msgid "bad size \"%s\""
+#~ msgstr "અયોગ્ય માપ \"%s\""
+
+#~ msgid "failed to find url in html"
+#~ msgstr "htmlમાં યુઆરએલ શોધવામાં નિષ્ફળ"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "આના પર બરાબર છે %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "તમારો પાસવર્ડ તમને ઇમેઇલ કરવામાં આવ્યો છે."
+
+#~ msgid "polygen failed"
+#~ msgstr "પોલિગોન નિષ્ફળ"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "હાયપરસ્ટ્રેઇઝર શોધ અનુક્રમણિકા સાફ કરે છે"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "હાયપરસ્ટ્રેઇઝર શોધ અનુક્રમણિકા સુધારે છે"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -664,9 +1247,6 @@ msgstr "%s પર શોધાયેલ લુપ  %s પર ચલાવે છ
 #~ msgstr ""
 #~ "REV ગોઠવેલ નથી, svn post-commit hook માંથી ચાલતું નથી, નોંધ મોકલી શકાશે નહી"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "%s નો સુધારો %s નાં %s વડે"
-
 #~ msgid "%s not found"
 #~ msgstr "ટેમ્પલેટ %s મળ્યું નહી"
 
index e8b9c810422c92a1c5bf7d6947cb1532dd0df246..29a2d508cb94480b7fb619d40544cd7d6b1fbf4c 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-07-06 19:16-0400\n"
+"POT-Creation-Date: 2009-08-25 18:43-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,304 +16,475 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:140
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:172
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:190 ../IkiWiki/CGI.pm:525
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
 msgid "Your login session has expired."
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:211
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:212
+#: ../IkiWiki/CGI.pm:190
 msgid "Preferences"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:213
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:267
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:325
-#, perl-format
-msgid "%s is not an editable page"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:436 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:266 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:162
-msgid "discussion"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:492
-#, perl-format
-msgid "creating %s"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:538 ../IkiWiki/CGI.pm:548
-#: ../IkiWiki/CGI.pm:582 ../IkiWiki/CGI.pm:627
-#, perl-format
-msgid "editing %s"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:721
-msgid "You are banned."
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1269
+msgid "Error"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:53
+#: ../IkiWiki/Plugin/aggregate.pm:84
 msgid "Aggregation triggered via web."
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:62
+#: ../IkiWiki/Plugin/aggregate.pm:93
 msgid "Nothing to do right now, all feeds are up-to-date!"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:134
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, perl-format
 msgid "missing %s parameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:168
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:182
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:184
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:347
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:354
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:381
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
+msgid "last checked %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:385
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:390
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:405
+#: ../IkiWiki/Plugin/aggregate.pm:503
 msgid "feed not found"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:416
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:422
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:428
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:502
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:30
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
 msgid "deleting bucket.."
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:37 ../IkiWiki/Setup/Standard.pm:89
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
 msgid "done"
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:46
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
 #, perl-format
 msgid "Must specify %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:85
-msgid "Failed to create bucket in S3: "
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+msgid "Failed to create S3 bucket: "
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:170
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
 msgid "Failed to save file to S3: "
 msgstr ""
 
-#: ../IkiWiki/Plugin/amazon_s3.pm:192
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
 msgid "Failed to delete file from S3: "
 msgstr ""
 
-#: ../IkiWiki/Plugin/attachment.pm:95
-msgid "bad attachment filename"
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/attachment.pm:118
-msgid "attachment rejected"
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
 msgstr ""
 
-#: ../IkiWiki/Plugin/attachment.pm:147
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
 msgid "attachment upload"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr ""
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 msgid "template not specified"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 msgid "match not specified"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 msgid "failed to process"
 msgstr ""
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
-msgid "failed to find url in html"
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+msgid "not a page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
 msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 msgid "failed to run graphviz"
 msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:56
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:66 ../IkiWiki/Plugin/img.pm:70
-#: ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, perl-format
 msgid "failed to read %s: %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:73
+#: ../IkiWiki/Plugin/img.pm:90
 #, perl-format
 msgid "failed to resize: %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:104
+#: ../IkiWiki/Plugin/img.pm:119
 #, perl-format
 msgid "failed to determine size of image %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:47
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:106
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:155
 msgid "missing pages parameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:154
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:225
+#: ../IkiWiki/Plugin/inline.pm:329
 msgid "Add a new post titled:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:241
+#: ../IkiWiki/Plugin/inline.pm:349
 #, perl-format
 msgid "nonexistant template %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:274 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr ""
-
-#: ../IkiWiki/Plugin/inline.pm:504
+#: ../IkiWiki/Plugin/inline.pm:614
 msgid "RPC::XML::Client not found, not pinging"
 msgstr ""
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 msgid "failed to run dot"
 msgstr ""
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
+#: ../IkiWiki/Plugin/lockedit.pm:47
 #, perl-format
-msgid "%s is locked by %s and cannot be edited"
+msgid "%s is locked and cannot be edited"
 msgstr ""
 
-#: ../IkiWiki/Plugin/mdwn.pm:28
+#: ../IkiWiki/Plugin/mdwn.pm:44
 msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/mdwn.pm:51
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/meta.pm:137
+#: ../IkiWiki/Plugin/meta.pm:158
 msgid "stylesheet not found"
 msgstr ""
 
-#: ../IkiWiki/Plugin/meta.pm:171
+#: ../IkiWiki/Plugin/meta.pm:196
 msgid "redir page not found"
 msgstr ""
 
-#: ../IkiWiki/Plugin/meta.pm:184
+#: ../IkiWiki/Plugin/meta.pm:210
 msgid "redir cycle is not allowed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr ""
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr ""
 
@@ -321,93 +492,196 @@ msgstr ""
 msgid "more"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr ""
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr ""
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+msgid "All pages have other pages linking to them."
 msgstr ""
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:223
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:226
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:233
+#: ../IkiWiki/Plugin/passwordauth.pm:258
 msgid "No email address, so cannot email password reset instructions."
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:265
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:267
+#: ../IkiWiki/Plugin/passwordauth.pm:294
 msgid "You have been mailed password reset instructions."
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:302
+#: ../IkiWiki/Plugin/passwordauth.pm:329
 msgid "incorrect password reset url"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:305
+#: ../IkiWiki/Plugin/passwordauth.pm:332
 msgid "password reset denied"
 msgstr ""
 
-#: ../IkiWiki/Plugin/pingee.pm:21
+#: ../IkiWiki/Plugin/pingee.pm:30
 msgid "Ping received."
 msgstr ""
 
-#: ../IkiWiki/Plugin/pinger.pm:37
+#: ../IkiWiki/Plugin/pinger.pm:53
 msgid "requires 'from' and 'to' parameters"
 msgstr ""
 
-#: ../IkiWiki/Plugin/pinger.pm:42
+#: ../IkiWiki/Plugin/pinger.pm:58
 #, perl-format
 msgid "Will ping %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/pinger.pm:45
+#: ../IkiWiki/Plugin/pinger.pm:61
 #, perl-format
 msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/pinger.pm:61
+#: ../IkiWiki/Plugin/pinger.pm:77
 msgid "LWP not found, not pinging"
 msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:65
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, perl-format
+msgid "building %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, perl-format
+msgid "failed to update %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, perl-format
+msgid "failed to translate %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, perl-format
+msgid "failed to write %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1058
+msgid "failed to translate"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, perl-format
+msgid "failed to read %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:73
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
 msgstr ""
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr ""
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr ""
 
@@ -463,209 +737,340 @@ msgstr ""
 msgid "%A night"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
-msgid "missing page"
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchanges.pm:78
-#, perl-format
-msgid "The page %s does not exist."
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchangesdiff.pm:26
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
 msgid "(Diff truncated)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:20
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
 #, perl-format
-msgid "Must specify %s when using the search plugin"
+msgid "%s does not exist"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:170
+#: ../IkiWiki/Plugin/remove.pm:38
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:68
+#, perl-format
+msgid "illegal name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, perl-format
+msgid "rename %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/search.pm:182
 #, perl-format
 msgid "need Digest::SHA1 to index %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:203
+#: ../IkiWiki/Plugin/search.pm:217
 msgid "search"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/shortcut.pm:44
 msgid "missing name or url parameter"
 msgstr ""
 
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr ""
 
-#: ../IkiWiki/Plugin/smiley.pm:32
+#: ../IkiWiki/Plugin/smiley.pm:43
 msgid "failed to parse any smileys"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 msgid "parse error"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
-msgid "bad height value"
+#: ../IkiWiki/Plugin/sparkline.pm:104
+msgid "invalid height value"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 msgid "missing width parameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
-msgid "bad width value"
+#: ../IkiWiki/Plugin/sparkline.pm:115
+msgid "invalid width value"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 msgid "failed to run php"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, perl-format
 msgid "parse fail at line %d: %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 msgid "missing id parameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr ""
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 msgid "failed to process:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:88
+#: ../IkiWiki/Plugin/teximg.pm:128
 msgid "failed to generate image from code"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:69
-msgid "getctime not implemented"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:286 ../IkiWiki/Render.pm:307
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:361
+#: ../IkiWiki/Render.pm:294
 #, perl-format
-msgid "removing old page %s"
+msgid "%s has multiple possible source pages"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:401
+#: ../IkiWiki/Render.pm:380
 #, perl-format
-msgid "scanning %s"
+msgid "removing old page %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:406
+#: ../IkiWiki/Render.pm:421
 #, perl-format
-msgid "rendering %s"
+msgid "scanning %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:427
+#: ../IkiWiki/Render.pm:447
 #, perl-format
-msgid "rendering %s, which links to %s"
+msgid "building %s, which links to %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:448
+#: ../IkiWiki/Render.pm:473
 #, perl-format
-msgid "rendering %s, which depends on %s"
+msgid "building %s, which depends on %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:487
+#: ../IkiWiki/Render.pm:513
 #, perl-format
-msgid "rendering %s, to update its backlinks"
+msgid "building %s, to update its backlinks"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:499
+#: ../IkiWiki/Render.pm:525
 #, perl-format
-msgid "removing %s, no longer rendered by %s"
+msgid "removing %s, no longer built by %s"
 msgstr ""
 
-#: ../IkiWiki/Render.pm:523
+#: ../IkiWiki/Render.pm:549
 #, perl-format
-msgid "ikiwiki: cannot render %s"
+msgid "ikiwiki: cannot build %s"
 msgstr ""
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
 msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:79
-msgid "rebuilding wiki.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
 msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:82
-msgid "refreshing wiki.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
+
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
 msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
@@ -681,21 +1086,14 @@ msgstr ""
 msgid "wrapper filename not specified"
 msgstr ""
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr ""
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr ""
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr ""
@@ -704,23 +1102,73 @@ msgstr ""
 msgid "usage: ikiwiki [options] source dest"
 msgstr ""
 
-#: ../ikiwiki.in:82
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:124
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr ""
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr ""
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr ""
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr ""
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr ""
 
-#: ../IkiWiki.pm:193 ../IkiWiki.pm:194
-msgid "Error"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1251
+#, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:764
+#: ../IkiWiki.pm:1791
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "cannot match pages: %s"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
 msgstr ""
diff --git a/po/it.po b/po/it.po
new file mode 100644 (file)
index 0000000..c740fb0
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,1205 @@
+# Italian translation of ikiwiki.
+# This file is distributed under the same license as the ikiwiki package.
+# Luca Bruno <lucab@debian.org>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: Ikiwiki\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-08-25 18:43-0400\n"
+"PO-Revision-Date: 2009-08-16 11:01+0100\n"
+"Last-Translator: Luca Bruno <lucab@debian.org>\n"
+"Language-Team: Italian TP <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../IkiWiki/CGI.pm:113
+msgid "You need to log in first."
+msgstr "Occorre prima effettuare l'accesso."
+
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+"possibile errore di configurazione: sslcookie è impostato, ma si sta "
+"tentando un accesso via http, non https"
+
+#: ../IkiWiki/CGI.pm:149
+msgid "login failed, perhaps you need to turn on cookies?"
+msgstr "errore nell'accesso, probabilmente i cookie sono disabilitati?"
+
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr "La sessione è scaduta."
+
+#: ../IkiWiki/CGI.pm:189
+msgid "Login"
+msgstr "Entra"
+
+#: ../IkiWiki/CGI.pm:190
+msgid "Preferences"
+msgstr "Preferenze"
+
+#: ../IkiWiki/CGI.pm:191
+msgid "Admin"
+msgstr "Amministrazione"
+
+#: ../IkiWiki/CGI.pm:231
+msgid "Preferences saved."
+msgstr "Preferenze salvate."
+
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Avete ricevuto un ban."
+
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1269
+msgid "Error"
+msgstr "Errore"
+
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr "Aggregazione attivata dal web."
+
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
+"Nessuna azione da intraprendere, tutti i notiziari sono già aggiornati."
+
+#: ../IkiWiki/Plugin/aggregate.pm:220
+#, perl-format
+msgid "missing %s parameter"
+msgstr "parametro %s mancante"
+
+#: ../IkiWiki/Plugin/aggregate.pm:255
+msgid "new feed"
+msgstr "nuovo notiziario"
+
+#: ../IkiWiki/Plugin/aggregate.pm:269
+msgid "posts"
+msgstr "articoli"
+
+#: ../IkiWiki/Plugin/aggregate.pm:271
+msgid "new"
+msgstr "nuovo"
+
+#: ../IkiWiki/Plugin/aggregate.pm:441
+#, perl-format
+msgid "expiring %s (%s days old)"
+msgstr "in scadenza %s (vecchio di %s giorni)"
+
+#: ../IkiWiki/Plugin/aggregate.pm:448
+#, perl-format
+msgid "expiring %s"
+msgstr "in scadenza %s"
+
+#: ../IkiWiki/Plugin/aggregate.pm:475
+#, perl-format
+msgid "last checked %s"
+msgstr "ultimo controllo %s"
+
+#: ../IkiWiki/Plugin/aggregate.pm:479
+#, perl-format
+msgid "checking feed %s ..."
+msgstr "controllo notiziario %s..."
+
+#: ../IkiWiki/Plugin/aggregate.pm:484
+#, perl-format
+msgid "could not find feed at %s"
+msgstr "impossibile trovare il notiziario %s"
+
+#: ../IkiWiki/Plugin/aggregate.pm:503
+msgid "feed not found"
+msgstr "notiziario non trovato"
+
+#: ../IkiWiki/Plugin/aggregate.pm:514
+#, perl-format
+msgid "(invalid UTF-8 stripped from feed)"
+msgstr "(codifica UTF-8 non valida eliminata dal notiziario)"
+
+#: ../IkiWiki/Plugin/aggregate.pm:522
+#, perl-format
+msgid "(feed entities escaped)"
+msgstr "(entità del notiziario espanse con escape)"
+
+#: ../IkiWiki/Plugin/aggregate.pm:530
+msgid "feed crashed XML::Feed!"
+msgstr "il notiziario ha fatto andare in crash XML::Feed."
+
+#: ../IkiWiki/Plugin/aggregate.pm:616
+#, perl-format
+msgid "creating new page %s"
+msgstr "creazione nuova pagina %s"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr "eliminazione contenitore..."
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "fatto"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr "Occorre specificare %s"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+msgid "Failed to create S3 bucket: "
+msgstr "Impossibile creare il contenitore S3: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+msgid "Failed to save file to S3: "
+msgstr "Impossibile salvare il file sul S3: "
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+msgid "Failed to delete file from S3: "
+msgstr "Impossibile eliminare il file dal S3: "
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr "esiste già una pagina chiamata %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr "non permesso da allowed_attachments"
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr "nome file dell'allegato non valido"
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr "carica allegato"
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr "generazione automatica dell'indice"
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+"È stato riconosciuto come spam da <a href=\"http://blogspam.net/\">blogspam</"
+"a>: "
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
+#, perl-format
+msgid "%s from %s"
+msgstr "%s da %s"
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
+msgid "There are no broken links!"
+msgstr "Non ci sono collegamenti rotti."
+
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr "formato pagina %s non supportato"
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr "i commenti devono avere un contenuto"
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr "Anonimo"
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr "nome pagina non valido"
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, perl-format
+msgid "commenting on %s"
+msgstr "commento su %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr "la pagina «%s» non esiste, impossibile commentarla"
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr "i commenti per la pagina «%s» sono chiusi"
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr "commento trattenuto per moderazione"
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr "Il commento sarà pubblicato dopo la verifica del moderatore"
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr "Aggiunto commento"
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr "Aggiunto commento: %s"
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr "non siete autenticati come amministratore"
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr "Moderazione commenti"
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr "moderazione commento"
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr "Commenti"
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
+#, perl-format
+msgid "%s parameter is required"
+msgstr "parametro %s necessario"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr "nessun testo è stato copiato in questa pagina"
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr "nessun testo è stato copiato in questa pagina con l'id %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, perl-format
+msgid "removing old preview %s"
+msgstr "rimozione vecchia anteprima %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "%s non è una pagina modificabile"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "creazione %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "modifica %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
+msgid "template not specified"
+msgstr "modello non specificato"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:54
+msgid "match not specified"
+msgstr "corrispondenza non specificata"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:62
+#, perl-format
+msgid "edittemplate %s registered for %s"
+msgstr "edittemplate %s registrato per %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:133
+msgid "failed to process"
+msgstr "errore nell'elaborazione"
+
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr "occorre specificare formato e testo"
+
+#: ../IkiWiki/Plugin/fortune.pm:27
+msgid "fortune failed"
+msgstr "errore nel fortune"
+
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+msgid "missing page"
+msgstr "pagina mancante"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr "La pagina %s non esiste."
+
+#: ../IkiWiki/Plugin/getsource.pm:73
+msgid "not a page"
+msgstr "non è una pagina"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "%s è un allegato, non una pagina."
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr "non è permesso modificare %s"
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr "non è permesso lavorare su un file in modalità %s"
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr "non è permesso cambiare la modalità del file"
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Occorre specificare %s quando si usa il plugin %s"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+"Errore nell'interpretazione dell'URL, impossibile determinare il nome del "
+"dominio"
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
+msgid "failed to run graphviz"
+msgstr "errore nell'eseguire graphviz"
+
+#: ../IkiWiki/Plugin/graphviz.pm:94
+msgid "prog not a valid graphviz program"
+msgstr "prog non è un programma graphviz valido"
+
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr "tohighlight contiene il tipo di file sconosciuto «%s»"
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr "Sorgente: %s"
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+"attenzione: modulo perl highlight non trovato, verrà passato inalterato"
+
+#: ../IkiWiki/Plugin/img.pm:63
+msgid "Image::Magick is not installed"
+msgstr "Image::Magick non è installato"
+
+#: ../IkiWiki/Plugin/img.pm:72
+#, perl-format
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr "Formato dimensione «%s» non valido (dovrebbe essere LxA)"
+
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
+#, perl-format
+msgid "failed to read %s: %s"
+msgstr "impossibile leggere %s: %s"
+
+#: ../IkiWiki/Plugin/img.pm:90
+#, perl-format
+msgid "failed to resize: %s"
+msgstr "impossibile ridimensionare: %s"
+
+#: ../IkiWiki/Plugin/img.pm:119
+#, perl-format
+msgid "failed to determine size of image %s"
+msgstr "impossibile determinare la dimensione dell'immagine %s"
+
+#: ../IkiWiki/Plugin/inline.pm:92
+msgid "Must specify url to wiki with --url when using --rss or --atom"
+msgstr ""
+"Occorre specificare l'url del wiki tramite --url quando si usa --rss o --atom"
+
+#: ../IkiWiki/Plugin/inline.pm:138
+msgid "page editing not allowed"
+msgstr "modifica della pagina non ammessa"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+msgid "missing pages parameter"
+msgstr "parametro pagine mancante"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr "i parametri %s e %s non possono essere usati insieme"
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr "Sort::Naturally è richiesto per l'ordinamento title_natural"
+
+#: ../IkiWiki/Plugin/inline.pm:223
+#, perl-format
+msgid "unknown sort type %s"
+msgstr "ordinamento %s sconosciuto"
+
+#: ../IkiWiki/Plugin/inline.pm:329
+msgid "Add a new post titled:"
+msgstr "Aggiungere un nuovo articolo dal titolo:"
+
+#: ../IkiWiki/Plugin/inline.pm:349
+#, perl-format
+msgid "nonexistant template %s"
+msgstr "modello %s non esistente"
+
+#: ../IkiWiki/Plugin/inline.pm:614
+msgid "RPC::XML::Client not found, not pinging"
+msgstr "RPC::XML::Client non trovato, impossibile inviare ping"
+
+#: ../IkiWiki/Plugin/linkmap.pm:106
+msgid "failed to run dot"
+msgstr "impossibile eseguire dot"
+
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, perl-format
+msgid "%s is locked and cannot be edited"
+msgstr "%s è bloccata e non può essere modificata"
+
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+"multimarkdown è stato abilitato, ma Text::MultiMarkdown non è aggiornato"
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
+#, perl-format
+msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
+msgstr ""
+"impossibile caricare il modulo perl Markdown.pm (%s) o /usr/bin/markdown (%s)"
+
+#: ../IkiWiki/Plugin/meta.pm:158
+msgid "stylesheet not found"
+msgstr "foglio di stile non trovato"
+
+#: ../IkiWiki/Plugin/meta.pm:196
+msgid "redir page not found"
+msgstr "pagina di reindirizzamento non trovata"
+
+#: ../IkiWiki/Plugin/meta.pm:210
+msgid "redir cycle is not allowed"
+msgstr "ciclo di reindirizzamento non ammesso"
+
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
+msgid "Mirrors"
+msgstr "Mirror"
+
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
+msgid "Mirror"
+msgstr "Mirror"
+
+#: ../IkiWiki/Plugin/more.pm:8
+msgid "more"
+msgstr "altro"
+
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime non implementata"
+
+#: ../IkiWiki/Plugin/openid.pm:61
+msgid "Log in with"
+msgstr "Accedi tramite"
+
+#: ../IkiWiki/Plugin/openid.pm:64
+msgid "Get an OpenID"
+msgstr "Ottieni un OpenID"
+
+#: ../IkiWiki/Plugin/orphans.pm:45
+msgid "All pages have other pages linking to them."
+msgstr "Tutte le pagine hanno collegamenti in entrata da altre pagine."
+
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
+msgid "bad or missing template"
+msgstr "modello errato o mancante"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:248
+msgid "Account creation successful. Now you can Login."
+msgstr "Account creato con successo. È ora possibile effettuare l'accesso."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:251
+msgid "Error creating account."
+msgstr "Errore nella creazione dell'account."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+"Nessun indirizzo email, impossibile inviare per email le istruzioni per "
+"reimpostare la password."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
+msgid "Failed to send mail"
+msgstr "Impossibile spedire il messaggio"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+"Il messaggio con le istruzioni per reimpostare la password è stato inviato."
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr "url per il reset della password non corretto"
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr "reset della password non permesso"
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr "Ping ricevuto."
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr "sono richiesti i parametri \"to\" e \"from\""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, perl-format
+msgid "Will ping %s"
+msgstr "Verrà inviato un ping a %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr "Ignorata la richiesta di ping per il wiki %s (questo wiki è %s)"
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+msgid "LWP not found, not pinging"
+msgstr "LWP non trovato, ping non inviato"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+"attenzione: è presente un vecchio po4a. Si raccomanda di aggiornare almeno "
+"alla versione 0.35."
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr "%s non è una codifica di lingua valida"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+"%s non è un valore per po_link_to valido, verrà utilizzato po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+"po_link_to=negotiated richiede che venga abilitato usedirs, verrà utilizzato "
+"po_link_to=default"
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr "rigenerazione di tutte le pagine per sistemare i meta-titoli"
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, perl-format
+msgid "building %s"
+msgstr "compilazione di %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr "file PO aggiornati"
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+"Impossibile eliminare una traduzione. Tuttavia, se la pagina principale è "
+"stata eliminata anche le traduzioni lo saranno."
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+"Impossibile rinominare una traduzione. Tuttavia, se la pagina principale è "
+"stata rinominata anche le traduzioni lo saranno."
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr "Il file POT (%s) non esiste"
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "impossibile copiare il file PO di underlay in %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, perl-format
+msgid "failed to update %s"
+msgstr "impossibile aggiornare %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "impossibile copiare il file POT in %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr "N/D"
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, perl-format
+msgid "failed to translate %s"
+msgstr "impossibile tradurre %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr "file PO obsoleti rimossi"
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, perl-format
+msgid "failed to write %s"
+msgstr "impossibile scrivere %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+msgid "failed to translate"
+msgstr "impossibile tradurre"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, perl-format
+msgid "failed to read %s"
+msgstr "impossibile leggere %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+"dati gettext non validi, tornare alle pagina precedente per continuare le "
+"modifiche"
+
+#: ../IkiWiki/Plugin/poll.pm:69
+msgid "vote"
+msgstr "voto"
+
+#: ../IkiWiki/Plugin/poll.pm:77
+msgid "Total votes:"
+msgstr "Voti totali:"
+
+#: ../IkiWiki/Plugin/polygen.pm:41
+msgid "polygen not installed"
+msgstr "polygen non è installato"
+
+#: ../IkiWiki/Plugin/polygen.pm:60
+msgid "command failed"
+msgstr "errore nel comando"
+
+#: ../IkiWiki/Plugin/postsparkline.pm:41
+msgid "missing formula"
+msgstr "formula mancante"
+
+#: ../IkiWiki/Plugin/postsparkline.pm:48
+msgid "unknown formula"
+msgstr "formula sconosciuta"
+
+#. translators: These descriptions of times of day are used
+#. translators: in messages like "last edited <description>".
+#. translators: %A is the name of the day of the week, while
+#. translators: %A- is the name of the previous day.
+#: ../IkiWiki/Plugin/prettydate.pm:15
+msgid "late %A- night"
+msgstr "%A- a tarda notte"
+
+#: ../IkiWiki/Plugin/prettydate.pm:17
+msgid "in the wee hours of %A- night"
+msgstr "%A prima dell'alba"
+
+#: ../IkiWiki/Plugin/prettydate.pm:20
+msgid "terribly early %A morning"
+msgstr "%A mattina molto presto"
+
+#: ../IkiWiki/Plugin/prettydate.pm:22
+msgid "early %A morning"
+msgstr "%A mattina presto"
+
+#: ../IkiWiki/Plugin/prettydate.pm:25
+msgid "mid-morning %A"
+msgstr "%A metà mattina"
+
+#: ../IkiWiki/Plugin/prettydate.pm:26
+msgid "late %A morning"
+msgstr "%A mattina tardi"
+
+#: ../IkiWiki/Plugin/prettydate.pm:27
+msgid "at lunch time on %A"
+msgstr "%A all'ora di pranzo"
+
+#: ../IkiWiki/Plugin/prettydate.pm:29
+msgid "%A afternoon"
+msgstr "%A pomeriggio"
+
+#: ../IkiWiki/Plugin/prettydate.pm:32
+msgid "late %A afternoon"
+msgstr "%A pomeriggio tardo"
+
+#: ../IkiWiki/Plugin/prettydate.pm:33
+msgid "%A evening"
+msgstr "%A sera"
+
+#: ../IkiWiki/Plugin/prettydate.pm:35
+msgid "late %A evening"
+msgstr "%A sera tardi"
+
+#: ../IkiWiki/Plugin/prettydate.pm:37
+msgid "%A night"
+msgstr "%A notte"
+
+#: ../IkiWiki/Plugin/prettydate.pm:101
+msgid "at teatime on %A"
+msgstr "%A all'ora di merenda"
+
+#: ../IkiWiki/Plugin/prettydate.pm:105
+msgid "at midnight"
+msgstr "a mezzanotte"
+
+#: ../IkiWiki/Plugin/prettydate.pm:108
+msgid "at noon on %A"
+msgstr "%A a mezzogiorno"
+
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr "valore percentuale %s non ammesso"
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+"occorrono alternativamente i parametri \"percent\" o \"totalpages\" e "
+"\"donepages\""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr "(Diff troncato)"
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr "%s non esiste"
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s non è in src, quindi non può essere eliminato"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr "%s non è un file"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr "conferma rimozione di %s"
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr "Selezionare l'allegato da rimuovere."
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr "rimosso"
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr "%s non è in src, quindi non può essere rinominato"
+
+#: ../IkiWiki/Plugin/rename.pm:62
+msgid "no change to the file name was specified"
+msgstr "non è stata specificata nessuna modifica al nome del file"
+
+#: ../IkiWiki/Plugin/rename.pm:68
+#, perl-format
+msgid "illegal name"
+msgstr "nome non valido"
+
+#: ../IkiWiki/Plugin/rename.pm:73
+#, perl-format
+msgid "%s already exists"
+msgstr "%s esiste già"
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr "%s già presente su disco"
+
+#: ../IkiWiki/Plugin/rename.pm:122
+#, perl-format
+msgid "rename %s"
+msgstr "rinomina di %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr "Rinomina anche SottoPagine e allegati"
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr "Si può rinominare un solo allegato alla volta."
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr "Selezionare l'allegato da rinominare."
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr "rinomina %s in %s"
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, perl-format
+msgid "update for rename of %s to %s"
+msgstr "aggiornamento per rinomina di %s in %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr "è necessario Digest::SHA1 per l'indice di %s"
+
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr "cerca"
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr "il plugin scorciatoia non può funzionare senza %s"
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
+msgid "missing name or url parameter"
+msgstr "parametro nome o url mancante"
+
+#. translators: This is used to display what shortcuts are defined.
+#. translators: First parameter is the name of the shortcut, the second
+#. translators: is an URL.
+#: ../IkiWiki/Plugin/shortcut.pm:54
+#, perl-format
+msgid "shortcut %s points to <i>%s</i>"
+msgstr "la scorciatoia %s punta a <i>%s</i>"
+
+#: ../IkiWiki/Plugin/smiley.pm:43
+msgid "failed to parse any smileys"
+msgstr "impossibile interpretare gli smile"
+
+#: ../IkiWiki/Plugin/sparkline.pm:72
+msgid "parse error"
+msgstr "errore nell'interpretazione"
+
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
+msgstr "Diametro featurepoint non valido"
+
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
+msgstr "Posizione featurepoint non valida"
+
+#: ../IkiWiki/Plugin/sparkline.pm:99
+msgid "missing values"
+msgstr "valori mancanti"
+
+#: ../IkiWiki/Plugin/sparkline.pm:104
+msgid "invalid height value"
+msgstr "valore altezza non valido"
+
+#: ../IkiWiki/Plugin/sparkline.pm:111
+msgid "missing width parameter"
+msgstr "parametro larghezza mancante"
+
+#: ../IkiWiki/Plugin/sparkline.pm:115
+msgid "invalid width value"
+msgstr "valore larghezza non valido"
+
+#: ../IkiWiki/Plugin/sparkline.pm:153
+msgid "failed to run php"
+msgstr "impossibile eseguire php"
+
+#: ../IkiWiki/Plugin/table.pm:31
+msgid "cannot find file"
+msgstr "impossibile trovare il file"
+
+#: ../IkiWiki/Plugin/table.pm:87
+msgid "unknown data format"
+msgstr "formato dati sconosiuto"
+
+#: ../IkiWiki/Plugin/table.pm:95
+msgid "empty data"
+msgstr "nessun dato"
+
+#: ../IkiWiki/Plugin/table.pm:114
+msgid "Direct data download"
+msgstr "Scaricamento diretto dei dati"
+
+#: ../IkiWiki/Plugin/table.pm:148
+#, perl-format
+msgid "parse fail at line %d: %s"
+msgstr "errore di interpretazione alla riga %d: %s"
+
+#: ../IkiWiki/Plugin/template.pm:29
+msgid "missing id parameter"
+msgstr "parametro id mancante"
+
+#: ../IkiWiki/Plugin/template.pm:36
+#, perl-format
+msgid "template %s not found"
+msgstr "modello %s non trovato"
+
+#: ../IkiWiki/Plugin/template.pm:55
+msgid "failed to process:"
+msgstr "errore nell'elaborazione:"
+
+#: ../IkiWiki/Plugin/teximg.pm:70
+msgid "missing tex code"
+msgstr "codice tex mancante"
+
+#: ../IkiWiki/Plugin/teximg.pm:77
+msgid "code includes disallowed latex commands"
+msgstr "nel codice sono presenti comandi latex non permessi"
+
+#: ../IkiWiki/Plugin/teximg.pm:128
+msgid "failed to generate image from code"
+msgstr "impossibile generare l'immagine dal codice"
+
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
+msgstr "plugin"
+
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr "abilitare %s?"
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr "il file di setup di questo wiki non è noto"
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr "principale"
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr "plugin"
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+"Le sottostanti modifiche alla configurazione richiedono la ricompilazione "
+"del wiki."
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+"Affinché le sottostanti modifiche alla configurazione abbiano effetto, "
+"occorre ricostruire il wiki."
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr "Errore: %s è terminato con errore (%s). Modifiche al setup scartate."
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr "impossibile determinare l'id del committer non fidato %s"
+
+#: ../IkiWiki/Receive.pm:85
+#, perl-format
+msgid "bad file name %s"
+msgstr "nome file %s scorretto"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+"collegamento simbolico trovato nel percorso srcdir (%s) -- impostare "
+"allow_symlinks_before_srcdir per abilitare questa configurazione"
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
+#, perl-format
+msgid "skipping bad filename %s"
+msgstr "ignorato il file dal nome scorretto %s"
+
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr "%s ha diverse pagine sorgenti possibili"
+
+#: ../IkiWiki/Render.pm:380
+#, perl-format
+msgid "removing old page %s"
+msgstr "rimozione della vecchia pagina %s"
+
+#: ../IkiWiki/Render.pm:421
+#, perl-format
+msgid "scanning %s"
+msgstr "scansione %s"
+
+#: ../IkiWiki/Render.pm:447
+#, perl-format
+msgid "building %s, which links to %s"
+msgstr "compilazione di %s, che è collegato a %s"
+
+#: ../IkiWiki/Render.pm:473
+#, perl-format
+msgid "building %s, which depends on %s"
+msgstr "compilazione di %s, che dipende da %s"
+
+#: ../IkiWiki/Render.pm:513
+#, perl-format
+msgid "building %s, to update its backlinks"
+msgstr "compilazione di %s, per aggiornare i collegamenti ai precedenti"
+
+#: ../IkiWiki/Render.pm:525
+#, perl-format
+msgid "removing %s, no longer built by %s"
+msgstr "rimozione di %s, non più richiesto da %s"
+
+#: ../IkiWiki/Render.pm:549
+#, perl-format
+msgid "ikiwiki: cannot build %s"
+msgstr "ikiwiki: impossibile compilare %s"
+
+#. translators: The first parameter is a filename, and the second
+#. translators: is a (probably not translated) error message.
+#: ../IkiWiki/Setup.pm:19
+#, perl-format
+msgid "cannot read %s: %s"
+msgstr "impossibile leggere %s: %s"
+
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr "occorre inserire un wikiname (contente caratteri alfanumerici)"
+
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr "sistema di controllo di revisione %s non supportato"
+
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr "impossibile creare un repository tramite ikiwiki-makerepo"
+
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
+"** Plugin %s disabilitato, a causa della seguente segnalazione di errore:"
+
+#: ../IkiWiki/Wrapper.pm:16
+#, perl-format
+msgid "%s doesn't seem to be executable"
+msgstr "%s non sembra essere eseguibile"
+
+#: ../IkiWiki/Wrapper.pm:20
+msgid "cannot create a wrapper that uses a setup file"
+msgstr "impossibile creare un contenitore che utilizzi un file di setup"
+
+#: ../IkiWiki/Wrapper.pm:24
+msgid "wrapper filename not specified"
+msgstr "nome del file del contenitore non specificato"
+
+#. translators: The parameter is a C filename.
+#: ../IkiWiki/Wrapper.pm:152
+#, perl-format
+msgid "failed to compile %s"
+msgstr "errore nel compilare %s"
+
+#. translators: The parameter is a filename.
+#: ../IkiWiki/Wrapper.pm:172
+#, perl-format
+msgid "successfully generated %s"
+msgstr "%s generato con successo"
+
+#: ../ikiwiki.in:13
+msgid "usage: ikiwiki [options] source dest"
+msgstr "utilizzo: ikiwiki [opzioni] sorgente destinazione"
+
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr "       ikiwiki --setup configfile"
+
+#: ../ikiwiki.in:91
+msgid "usage: --set var=value"
+msgstr "utilizzo: --set var=valore"
+
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "generazione contenitori..."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "ricostruzione wiki..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "aggiornamento wiki..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Discussione"
+
+#: ../IkiWiki.pm:494
+msgid "Must specify url to wiki with --url when using --cgi"
+msgstr "Occorre specificare l'url del wiki tramite --url quando si usa --cgi"
+
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr "impossibile usare più plugin rcs"
+
+#: ../IkiWiki.pm:569
+#, perl-format
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr "impossibile caricare il plugin esterno per il plugin %s: %s"
+
+#: ../IkiWiki.pm:1251
+#, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
+msgstr "ciclo del preprocessore individuato su %s alla profondità %i"
+
+#: ../IkiWiki.pm:1791
+msgid "yes"
+msgstr "sì"
+
+#: ../IkiWiki.pm:1915
+#, perl-format
+msgid "cannot match pages: %s"
+msgstr "impossibile trovare pagine corrispondenti: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr "Quale sarà il nome del wiki?"
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr "wiki"
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr "Che sistema di controllo di revisione usare?"
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr "Quale utente (openid o del wiki) sarà l'amministratore?"
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr "Qual è il nome del dominio del server web?"
index 934881b8925b4637ca78bb6167cd8fe1cad584f9..6ecda8d888cdfa1f7ba3f189c7ad4cbd81a2f193 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki 1.51\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-04-27 22:05+0200\n"
 "Last-Translator: Pawel Tecza <ptecza@net.icm.edu.pl>\n"
 "Language-Team: Debian L10n Polish <debian-l10n-polish@lists.debian.org>\n"
@@ -16,266 +16,501 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Proszę najpierw zalogować się."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 "Nieudane logowanie. Proszę sprawdzić czy w przeglądarce włączone są "
 "ciasteczka (ang. cookies)"
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 #, fuzzy
 msgid "Preferences"
 msgstr "Preferencje zapisane."
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Preferencje zapisane."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr "Strona %s nie może być edytowana"
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "dyskusja"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Twój dostęp został zabroniony przez administratora."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "tworzenie %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Błąd"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "edycja %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Twój dostęp został zabroniony przez administratora."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, fuzzy, perl-format
 msgid "missing %s parameter"
 msgstr "brakujący parametr %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "nowy kanał RSS"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "wpisy"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "nowy wpis"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "wygasający wpis %s (ma już %s dni)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "wygasający wpis %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "kanał RSS przetworzony w dniu %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "sprawdzanie kanału RSS %s..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "nie znaleziono kanału RSS pod adresem %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 #, fuzzy
 msgid "feed not found"
 msgstr "nieznaleziony kanał RSS"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, fuzzy, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr "Nieprawidłowe kodowanie UTF-8 usunięte z kanału RSS"
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "awaria kanału RSS w module XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "tworzenie nowej strony %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "gotowe"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Awaria w trakcie wysyłania wiadomości"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Awaria w trakcie wysyłania wiadomości"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "awaria w trakcie zmiany rozmiaru: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Wszystkie odnośniki są aktualne!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "tworzenie %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, fuzzy, perl-format
 msgid "%s parameter is required"
 msgstr "Parametry \"test\" i \"then\" są wymagane"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "usuwanie starej strony %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr "Strona %s nie może być edytowana"
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "tworzenie %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "edycja %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "nieznaleziony szablon %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "nieokreślona nazwa pliku osłony"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "awaria w trakcie przetwarzania:"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "awaria fortunki"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "brakujące wartości"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
 #, fuzzy
-msgid "failed to find url in html"
-msgstr "awaria w trakcie wyszukiwania adresu URL na stronie HTML"
+msgid "not a page"
+msgstr "awaria w trakcie odczytu %s: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, fuzzy, perl-format
+msgid "%s is an attachment, not a page."
+msgstr "Strona %s nie może być edytowana"
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
+
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Wtyczka do wyszukiwarka wymaga podania %s"
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 #, fuzzy
 msgid "failed to run graphviz"
 msgstr "awaria w trakcie uruchamiania wtyczki graphviz"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr "prog nie jest poprawnym programem graphviz"
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "wtyczka polygen nie jest zainstalowana"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
-msgstr "nieprawidłowy rozmiar \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
+msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, fuzzy, perl-format
 msgid "failed to read %s: %s"
 msgstr "awaria w trakcie odczytu %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, fuzzy, perl-format
 msgid "failed to resize: %s"
 msgstr "awaria w trakcie zmiany rozmiaru: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "awaria w trakcie zmiany rozmiaru: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 "Użycie parametru --rss lub --atom wymaga podania adresu URL do wiki za "
 "pomocą parametru --url"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "nieznaleziony kanał RSS"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "brakujący parametr %s"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "nieznany sposób sortowania %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr "Tytuł nowego wpisu"
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr "brakujący szablon %s"
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Dyskusja"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "Nieznaleziony moduł RPC::XML::Client, brak możliwości pingowania"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 #, fuzzy
 msgid "failed to run dot"
 msgstr "awaria w trakcie uruchamiania dot"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr ""
 "strona %s jest tymczasowo zablokowana przez użytkownika %s i nie może być "
 "teraz edytowana"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "Awaria w trakcie ładowania perlowego modułu Markdown.pm (%s) lub "
 "uruchamiania programu /usr/bin/markdown (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 #, fuzzy
 msgid "stylesheet not found"
 msgstr "nieznaleziony szablon ze stylami CSS"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "nieznaleziony kanał RSS"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "nieznaleziony kanał RSS"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Kopie lustrzane"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Kopia lustrzana"
 
@@ -283,59 +518,200 @@ msgstr "Kopia lustrzana"
 msgid "more"
 msgstr "więcej"
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "niedostępna funkcja getctime"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Pobierz OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Dla każdej strony istnieje odnośnik z innej strony"
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Konto założone pomyślnie. Teraz można zalogować się."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Błąd w trakcie zakładania konta."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Awaria w trakcie wysyłania wiadomości"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Wiadomość z hasłem została wysłana."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "edycja %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "Nieznaleziony moduł RPC::XML::Client, brak możliwości pingowania"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, fuzzy, perl-format
+msgid "%s is not a valid language code"
+msgstr "Strona %s nie może być edytowana"
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "edycja %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "awaria w trakcie kompilowania %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "awaria w trakcie kompilowania %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "awaria w trakcie kompilowania %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "awaria w trakcie zmiany rozmiaru: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "awaria w trakcie zapisu %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "awaria w trakcie uruchamiania dot"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "awaria w trakcie odczytu %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "głosuj"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Oddane głosy:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "wtyczka polygen nie jest zainstalowana"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "awaria wtyczki polygen"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "awaria fortunki"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr "brakująca reguła"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr "nieznana reguła"
 
@@ -392,46 +768,128 @@ msgstr "późnym wieczorem w %A"
 msgid "%A night"
 msgstr "nocą w %A"
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr "w porze śniadaniowej w %A"
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr "o północy"
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr "w południe w %A"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr ""
+"strona %s jest tymczasowo zablokowana przez użytkownika %s i nie może być "
+"teraz edytowana"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, fuzzy, perl-format
+msgid "%s is not a file"
+msgstr "Strona %s nie może być edytowana"
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "brakujące wartości"
+msgid "no change to the file name was specified"
+msgstr "nieokreślona nazwa pliku osłony"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Wtyczka do wyszukiwarka wymaga podania %s"
+msgid "%s already exists"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "czyszczanie indeksu z wynikami wtyczki hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "renderowanie %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "aktualizacja stron wiki %s: %s przez użytkownika %s"
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "aktualizacja indeksu z wynikami wtyczki hyperestraier"
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 #, fuzzy
 msgid "missing name or url parameter"
 msgstr "brakujący parametr name lub url"
@@ -439,178 +897,228 @@ msgstr "brakujący parametr name lub url"
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, fuzzy, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "skrót %s wskazuje na adres <i>%s</i>"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 #, fuzzy
 msgid "failed to parse any smileys"
 msgstr "awaria w trakcie przetwarzania emitoikonki"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 #, fuzzy
 msgid "parse error"
 msgstr "błąd w trakcie przetwarzania"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+#, fuzzy
+msgid "invalid featurepoint diameter"
 msgstr "nieprawidłowa średnica dla featurepoint"
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+#, fuzzy
+msgid "invalid featurepoint location"
 msgstr "nieprawidłowe położenie dla featurepoint"
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr "brakujące wartości"
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
+#: ../IkiWiki/Plugin/sparkline.pm:104
 #, fuzzy
-msgid "bad height value"
+msgid "invalid height value"
 msgstr "nieprawidłowa wysokość"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 #, fuzzy
 msgid "missing width parameter"
 msgstr "brakujący parametr width"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
+#: ../IkiWiki/Plugin/sparkline.pm:115
 #, fuzzy
-msgid "bad width value"
+msgid "invalid width value"
 msgstr "nieprawidłowa szerokość"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 #, fuzzy
 msgid "failed to run php"
 msgstr "awaria w trakcie uruchamiania php"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr "nie można znaleźć pliku"
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr "nieznany format danych"
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr "brak danych"
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr "Bezpośrednie pobieranie danych"
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, fuzzy, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "awaria w trakcie przetwarzania linii %d: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 #, fuzzy
 msgid "missing id parameter"
 msgstr "brakujący parametr id"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "nieznaleziony szablon %s"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 #, fuzzy
 msgid "failed to process:"
 msgstr "awaria w trakcie przetwarzania:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 #, fuzzy
 msgid "missing tex code"
 msgstr "brakujące wartości"
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "awaria w trakcie zmiany rozmiaru: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "niedostępna funkcja getctime"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "pomijanie nieprawidłowej nazwy pliku %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "pomijanie nieprawidłowej nazwy pliku %s"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "usuwanie starej strony %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "skanowanie %s"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "renderowanie %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "renderowanie %s z odnośnikiem do %s"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "renderowanie %s zależącego od %s"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "renderowanie %s w celu aktualizacji powrotnych odnośników"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "usuwanie %s nie tworzonego już przez %s"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: awaria w trakcie tworzenia %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "awaria w trakcie odczytu %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "tworzenie osłon..."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "przebudowywanie wiki..."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "odświeżanie wiki..."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "gotowe"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -625,21 +1133,14 @@ msgstr "awaria w trakcie tworzenia osłony używającej pliku konfiguracyjnego"
 msgid "wrapper filename not specified"
 msgstr "nieokreślona nazwa pliku osłony"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "awaria w trakcie zapisu %s: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "awaria w trakcie kompilowania %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "pomyślnie utworzono %s"
@@ -648,29 +1149,111 @@ msgstr "pomyślnie utworzono %s"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "użycie: ikiwiki [parametry] źródło cel"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "tworzenie osłon..."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "przebudowywanie wiki..."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "odświeżanie wiki..."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Dyskusja"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr ""
 "Użycie parametru --cgi wymaga podania adresu URL do wiki za pomocą parametru "
 "--url"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Błąd"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "polecenie preprocesora %s wykryte w %s na głębokości %i"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "awaria w trakcie odczytu %s: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "dyskusja"
+
+#~ msgid "rendering %s"
+#~ msgstr "renderowanie %s"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "Wtyczka do wyszukiwarka wymaga podania %s"
+
+#~ msgid "bad size \"%s\""
+#~ msgstr "nieprawidłowy rozmiar \"%s\""
+
+#, fuzzy
+#~ msgid "failed to find url in html"
+#~ msgstr "awaria w trakcie wyszukiwania adresu URL na stronie HTML"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "kanał RSS przetworzony w dniu %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "Wiadomość z hasłem została wysłana."
+
+#~ msgid "polygen failed"
+#~ msgstr "awaria wtyczki polygen"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "czyszczanie indeksu z wynikami wtyczki hyperestraier"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "aktualizacja indeksu z wynikami wtyczki hyperestraier"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -692,9 +1275,6 @@ msgstr "polecenie preprocesora %s wykryte w %s na głębokości %i"
 #~ "Brak możliwości wysłania powiadomień od Subversion przez \"haczyk\" post-"
 #~ "commit z powodu nieustawionego parametru REV"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "aktualizacja stron wiki %s: %s przez użytkownika %s"
-
 #, fuzzy
 #~ msgid "%s not found"
 #~ msgstr "nie znaleziono %s"
diff --git a/po/po2wiki b/po/po2wiki
new file mode 100755 (executable)
index 0000000..6b84f7d
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+# This program uses the po plugin's internals to convert the po files that
+# it generates back into translated wiki source files that can be used as a
+# underlay for a non-English wiki.
+use warnings;
+use strict;
+use IkiWiki;
+
+# Load the passed setup file and initialize ikiwiki config.
+%config=IkiWiki::defaultconfig();
+require IkiWiki::Setup;
+IkiWiki::Setup::load(shift);
+IkiWiki::loadplugins();
+IkiWiki::checkconfig();
+
+require IkiWiki::Render;
+IkiWiki::srcdir_check();
+my ($files, $pages)=IkiWiki::find_src_files();
+
+foreach my $file (@$files) {
+       my $page=pagename($file);
+       $pagesources{$page}=$file; # used by po plugin functions
+}
+
+foreach my $ll (keys %{$config{po_slave_languages}}) {
+       $config{destdir}="../underlays/locale/$ll";
+
+       foreach my $file (@$files) {
+               my $page=pagename($file);
+               my ($masterpage, $lang) = IkiWiki::Plugin::po::_istranslation($page);
+               next unless defined $lang && $lang eq $ll;
+               
+               my $content=IkiWiki::Plugin::po::po_to_markup($page, readfile(srcfile($file)));
+               # avoid wasting space if the page is not translated at all
+               my $mastercontent=readfile(srcfile($pagesources{$masterpage}));
+               if ($content ne $mastercontent) {
+                       writefile($masterpage.".".$config{default_pageext},
+                               $config{destdir}, $content);
+               }
+       }
+}
index 7990184dd7536a8b5c081c63808eb1e7f5489a8b..075de56d0e4066305d7a5d9aeddab5c42d63ef9d 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-01-10 23:47+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -15,260 +15,495 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Du måste logga in först."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 #, fuzzy
 msgid "Preferences"
 msgstr "Inställningar sparades."
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Inställningar sparades."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "diskussion"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Du är bannlyst."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "skapar %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Fel"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "redigerar %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Du är bannlyst."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, fuzzy, perl-format
 msgid "missing %s parameter"
 msgstr "mall saknar id-parameter"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "ny kanal"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "inlägg"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "ny"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "låter %s gå ut (%s dagar gammal)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "låter %s gå ut"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "behandlad ok på %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "kontrollerar kanalen %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "kunde inte hitta kanalen på %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 #, fuzzy
 msgid "feed not found"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "kanalen kraschade XML::Feed!"
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "skapar nya sidan %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "klar"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Misslyckades med att skicka e-post"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Misslyckades med att skicka e-post"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "misslyckades med att skriva %s: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Det finns inga trasiga länkar!"
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "skapar %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "tar bort gammal sida %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "skapar %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "redigerar %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "filnamn för wrapper har inte angivits"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "misslyckades med att behandla mall:"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "fortune misslyckades"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "mall saknar id-parameter"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
 #, fuzzy
-msgid "failed to find url in html"
-msgstr "googlecalendar misslyckades med att hitta url i html"
+msgid "not a page"
+msgstr "kan inte läsa %s: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Måste ange %s när sökinsticket används"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 #, fuzzy
 msgid "failed to run graphviz"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "polygen inte installerad"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, fuzzy, perl-format
 msgid "failed to read %s: %s"
 msgstr "misslyckades med att skriva %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, fuzzy, perl-format
 msgid "failed to resize: %s"
 msgstr "misslyckades med att skriva %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "misslyckades med att skriva %s: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr "Måste ange url till wiki med --url när --rss eller --atom används"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "mallen %s hittades inte"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "mall saknar id-parameter"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "okänd sorteringstyp %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Diskussion"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "RPC::XML::Client hittades inte, pingar inte"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 #, fuzzy
 msgid "failed to run dot"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr "%s är låst av %s och kan inte redigeras"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr ""
 "misslyckades med att läsa in Perl-modulen Markdown.pm (%s) eller /usr/bin/"
 "markdown (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 #, fuzzy
 msgid "stylesheet not found"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Speglar"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Spegel"
 
@@ -276,59 +511,200 @@ msgstr "Spegel"
 msgid "more"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "getctime inte implementerad"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Skaffa ett OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Alla sidor länkas till av andra sidor."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Kontot har skapats. Du kan nu logga in."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Fel vid skapandet av konto."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Misslyckades med att skicka e-post"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Ditt lösenord har skickats till dig via e-post."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "redigerar %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "RPC::XML::Client hittades inte, pingar inte"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "redigerar %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "misslyckades med att kompilera %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "misslyckades med att kompilera %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "misslyckades med att kompilera %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "misslyckades med att skriva %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "misslyckades med att skriva %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "linkmap misslyckades att köra dot"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "misslyckades med att skriva %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "röst"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Antal röster:"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "polygen inte installerad"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "polygen misslyckades"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "fortune misslyckades"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr ""
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr ""
 
@@ -384,46 +760,126 @@ msgstr ""
 msgid "%A night"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s är låst av %s och kan inte redigeras"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "mall saknar id-parameter"
+msgid "no change to the file name was specified"
+msgstr "filnamn för wrapper har inte angivits"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Måste ange %s när sökinsticket används"
+msgid "%s already exists"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "rensar hyperestraier-sökindex"
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "uppdaterar hyperestraier-sökindex"
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "ritar upp %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "uppdatering av %s, %s av %s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 #, fuzzy
 msgid "missing name or url parameter"
 msgstr "genväg saknar parameter för namn eller url"
@@ -431,177 +887,225 @@ msgstr "genväg saknar parameter för namn eller url"
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, fuzzy, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "genvägen %s pekar på %s"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 #, fuzzy
 msgid "failed to parse any smileys"
 msgstr "misslyckades med att tolka smilisar, inaktiverar instick"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 #, fuzzy
 msgid "parse error"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
+#: ../IkiWiki/Plugin/sparkline.pm:104
 #, fuzzy
-msgid "bad height value"
+msgid "invalid height value"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 #, fuzzy
 msgid "missing width parameter"
 msgstr "mall saknar id-parameter"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
+#: ../IkiWiki/Plugin/sparkline.pm:115
 #, fuzzy
-msgid "bad width value"
+msgid "invalid width value"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 #, fuzzy
 msgid "failed to run php"
 msgstr "linkmap misslyckades att köra dot"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, fuzzy, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "misslyckades med att skriva %s: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 #, fuzzy
 msgid "missing id parameter"
 msgstr "mall saknar id-parameter"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "mallen %s hittades inte"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 #, fuzzy
 msgid "failed to process:"
 msgstr "misslyckades med att behandla mall:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "misslyckades med att skriva %s: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "getctime inte implementerad"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "hoppar över felaktigt filnamn %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "hoppar över felaktigt filnamn %s"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "tar bort gammal sida %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "söker av %s"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "ritar upp %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "ritar upp %s, vilken länkar till %s"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "ritar upp %s, vilken är beroende av %s"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "ritar upp %s, för att uppdatera dess bakåtlänkar"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "tar bort %s, som inte längre ritas upp av %s"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: kan inte rita upp %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "kan inte läsa %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "genererar wrappers.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "bygger om wiki.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "uppdaterar wiki.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "klar"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -616,21 +1120,14 @@ msgstr "kan inte skapa en wrapper som använder en konfigurationsfil"
 msgid "wrapper filename not specified"
 msgstr "filnamn för wrapper har inte angivits"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "misslyckades med att skriva %s: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "misslyckades med att kompilera %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "generering av %s lyckades"
@@ -639,27 +1136,106 @@ msgstr "generering av %s lyckades"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "användning: ikiwiki [flaggor] källa mål"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "genererar wrappers.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "bygger om wiki.."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "uppdaterar wiki.."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Diskussion"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr "Måste ange url till wiki med --url när --cgi används"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Fel"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "%s förbehandlingsslinga detekterades på %s, djup %i"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "kan inte läsa %s: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "diskussion"
+
+#~ msgid "rendering %s"
+#~ msgstr "ritar upp %s"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "Måste ange %s när sökinsticket används"
+
+#, fuzzy
+#~ msgid "failed to find url in html"
+#~ msgstr "googlecalendar misslyckades med att hitta url i html"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "behandlad ok på %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "Ditt lösenord har skickats till dig via e-post."
+
+#~ msgid "polygen failed"
+#~ msgstr "polygen misslyckades"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "rensar hyperestraier-sökindex"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "uppdaterar hyperestraier-sökindex"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -681,9 +1257,6 @@ msgstr "%s förbehandlingsslinga detekterades på %s, djup %i"
 #~ "REV är inte inställt, kör inte från svn post-commit-hook, kan inte skicka "
 #~ "notifieringar"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "uppdatering av %s, %s av %s"
-
 #, fuzzy
 #~ msgid "%s not found"
 #~ msgstr "mallen %s hittades inte"
diff --git a/po/underlay.setup b/po/underlay.setup
new file mode 100644 (file)
index 0000000..3e6c125
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+# Configuration file for ikiwiki that uses the po plugin to build/update
+# po and pot files for pages in the underlays.
+
+use IkiWiki::Setup::Standard {
+       # List here all languages that have translations.
+       # Listing languages without active translations
+       # will excessively bloat things.
+        po_slave_languages => {
+               #'fr' => 'Français',
+               #'es' => 'Español',
+               #'de' => 'Deutsch',
+               'da' => 'Dansk',
+        },
+       po_master_language => { 'code' => 'en', 'name' => 'English' },
+       po_translatable_pages => "*",
+       add_plugins => [qw{po}],
+
+       wikiname => "ikiwiki",
+       srcdir => "underlays",
+       destdir => "html",
+       templatedir => "templates",
+       # we don't want to pull in the normal underlays
+       underlaydirbase => "underlays/empty",
+       underlaydir => "underlays/empty",
+       discussion => 0,
+       locale => '',
+       verbose => 1,
+       syslog => 0,
+}
diff --git a/po/underlays/basewiki/ikiwiki.da.po b/po/underlays/basewiki/ikiwiki.da.po
new file mode 100644 (file)
index 0000000..74f1198
--- /dev/null
@@ -0,0 +1,74 @@
+# Danish translation of basewiki/ikiwiki page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"This wiki is powered by [ikiwiki](http://ikiwiki.info/).\n"
+"[[!if test=\"enabled(version)\"\n"
+"     then=\"(Currently running version [[!version ]].)\"\n"
+"]]\n"
+msgstr ""
+"Denne wiki er drevet af [ikiwiki](http://ikiwiki.info/).\n"
+"[[!if test=\"enabled(version)\"\n"
+"     then=\"(kører i øjeblikket version [[!version ]].)\"\n"
+"]]\n"
+
+#. type: Plain text
+msgid "Some documentation on using ikiwiki:"
+msgstr "Noget dokumentation om brug af ikiwiki:"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/formatting]]"
+msgstr "[[formatering|ikiwiki/formatting]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/wikilink]]"
+msgstr "[[ikiwiki/wikilink]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/subpage]]"
+msgstr "[[underside|ikiwiki/subpage]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/pagespec]]"
+msgstr "[[ikiwiki/pagespec]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/directive]]"
+msgstr "[[direktiv|ikiwiki/directive]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/markdown]]"
+msgstr "[[ikiwiki/markdown]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/openid]]"
+msgstr "[[ikiwiki/openid]]"
+
+#. type: Bullet: '* '
+msgid "[[ikiwiki/searching]]"
+msgstr "[[søgning|ikiwiki/searching]]"
diff --git a/po/underlays/basewiki/ikiwiki/blog.da.po b/po/underlays/basewiki/ikiwiki/blog.da.po
new file mode 100644 (file)
index 0000000..6b188fe
--- /dev/null
@@ -0,0 +1,43 @@
+# Danish translation of basewiki/ikiwiki/blog page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This page has been removed from ikiwiki's basewiki. For documentation about "
+"creating a blog with ikiwiki, see the documentation of the [[!iki ikiwiki/"
+"directive/inline desc=inline]] directive."
+msgstr ""
+"Denne side er blevet fjernet fra ikiwiki's basewiki. For dokumentation om "
+"oprettelse af en blog med ikiwiki se dokumentationen til [[!iki ikiwiki/"
+"directive/inline desc=inline]]-direktivet."
+
+#. type: Plain text
+msgid ""
+"Please update your links, as this redirection page will be removed in a "
+"future ikiwiki release."
+msgstr ""
+"Opdatér dine henvisninger, da denne omdirigeringsside bliver fjernet i en "
+"fremtidig udgave af ikiwiki."
diff --git a/po/underlays/basewiki/ikiwiki/directive.da.po b/po/underlays/basewiki/ikiwiki/directive.da.po
new file mode 100644 (file)
index 0000000..3c13491
--- /dev/null
@@ -0,0 +1,135 @@
+# Danish translation of basewiki/ikiwiki/directive page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Directives are similar to a [[ikiwiki/WikiLink]] in form, except they begin "
+"with `!` and may contain parameters. The general form is:"
+msgstr ""
+"Direktiver ligner et [[ikiwiki/WikiLink]] i form, undtagen at de begynder "
+"med `!` og kan indeholde parametre. Generelt er formen:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!directive param=\"value\" param=\"value\"]]\n"
+msgstr "\t\\[[!direktiv param=\"værdi\" param=\"værdi\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This gets expanded before the rest of the page is processed, and can be used "
+"to transform the page in various ways."
+msgstr ""
+"Dette udvides før resten af siden udarbejdes, og kan bruges til at omforme "
+"siden på forskellige måder."
+
+#. type: Plain text
+msgid ""
+"The quotes around values can be omitted if the value is a simple word.  "
+"Also, some directives may use parameters without values, for example:"
+msgstr ""
+"Citationen omkring værdier kan udelades hvis værdien er et simpelt ord. "
+"Desuden kan nogle direktiver bruge parametre uden værdier. Eksempel:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!tag foo]]\n"
+msgstr "\t\\[[!tag foo]]\n"
+
+#. type: Plain text
+msgid ""
+"A directive does not need to all be on one line, it can be wrapped to "
+"multiple lines if you like:"
+msgstr ""
+"Et direktiv behøver ikke at blive holdt på een linje, det kan bredes ud over "
+"flere linjer hvis du har lyst:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!directive foo=\"baldersnatch\"\n"
+"\tbar=\"supercalifragilisticexpialidocious\" baz=11]]\n"
+msgstr ""
+"\t\\[[!direktiv foo=\"baldersnatch\"\n"
+"\tbar=\"supercalifragilisticexpialidocious\" baz=11]]\n"
+
+#. type: Plain text
+msgid ""
+"Also, multiple lines of *quoted* text can be used for a value.  To allow "
+"quote marks inside the quoted text, delimit the block of text with triple-"
+"quotes:"
+msgstr ""
+"Flere linjer *citeret* tekst kan også bruges som værdi. For at tillade "
+"citation i den citerede tekst skal du adskille blokken med trippel-citat:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!directive text=\"\"\"\n"
+msgstr "\t\\[[!direktiv tekst=\"\"\"\n"
+
+#. type: Bullet: '     1. '
+msgid "\"foo\""
+msgstr "\"foo\""
+
+#. type: Bullet: '     2. '
+msgid "\"bar\""
+msgstr "\"bar\""
+
+#. type: Bullet: '     3. '
+msgid "\"baz\""
+msgstr "\"baz\""
+
+#. type: Plain text
+msgid ""
+"ikiwiki also has an older syntax for directives, which requires a space in "
+"directives to distinguish them from [[wikilinks|ikiwiki/wikilink]]. This "
+"syntax has several disadvantages: it requires a space after directives with "
+"no parameters (such as `\\[[pagecount ]]`), and it prohibits spaces in "
+"[[wikilinks|ikiwiki/wikilink]].  ikiwiki now provides the `!`-prefixed "
+"syntax shown above as default.  However, ikiwiki still supports wikis using "
+"the older syntax, if the `prefix_directives` option is disabled."
+msgstr ""
+"Ikiwiki har også en ældre syntaks til direktiver, som kræver et mellemrum i "
+"direktiver for at skelne dem fra [[wikilinks|ikiwiki/wikilink]].  Denne "
+"syntaks har flere ulemper: den kræver et mellemrum efter direktiver uden "
+"parametre (såsom `\\[[pagecount ]]`), og den forbyder mellemrum i "
+"[[wikilinks|ikiwiki/wikilink]]. Ikiwiki har nu den `!`-foranstillede syntaks "
+"vist ovenfor som det foretrukne alternativ. Ikiwiki understøtter dog fortsat "
+"den ældre syntaks, hvis ikke `prefix_directives`-valget er aktiveret."
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(listdirectives)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(listdirectives)\" then=\"\"\"\n"
+
+#. type: Plain text
+msgid "Here is a list of currently available directives in this wiki:"
+msgstr ""
+"Her er en oversigt over konkret tilgængelige direktiver i for denne wiki:"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!listdirectives ]]\n"
+msgstr "[[!listdirectives ]]\n"
diff --git a/po/underlays/basewiki/ikiwiki/formatting.da.po b/po/underlays/basewiki/ikiwiki/formatting.da.po
new file mode 100644 (file)
index 0000000..3a229e9
--- /dev/null
@@ -0,0 +1,298 @@
+# Danish translation of basewiki/ikiwiki/formatting page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 21:25+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta title=\"Formatting wiki pages\"]]\n"
+msgstr "[[!meta title=\"Formatering af wikisider\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Text on this wiki is, by default, written in a form very close to how you "
+"might write text for an email message. This style of text formatting is "
+"called [[MarkDown]], and it works like this:"
+msgstr ""
+"Teksten på denne wiki er, som udgangspunkt, skrevet på en måde som ligger "
+"tæt op ad hvordan du muligvis formulerer dig i email-beskeder. Denne form "
+"for tekstformatering kaldes [[MarkDown]], og det fungerer sådan her:"
+
+#. type: Plain text
+msgid "Leave blank lines between paragraphs."
+msgstr "hold afstand med blanke linjer mellem afsnit."
+
+#. type: Plain text
+msgid ""
+"You can \\**emphasise*\\* or \\*\\***strongly emphasise**\\*\\* text by "
+"placing it in single or double asterisks."
+msgstr ""
+"du kan \\**fremhæve*\\* eller \\*\\***kraftigt fremhæve**\\*\\* tekst ved at "
+"placere det med enkelte eller dobbelte asterisker (stjerner) omkring."
+
+#. type: Plain text
+msgid "To create a list, start each line with an asterisk:"
+msgstr "En liste oprettes ved at begynde hver linje med en asterisk:"
+
+#. type: Bullet: '* '
+msgid "\"* this is my list\""
+msgstr "\"* dette er min liste\""
+
+#. type: Bullet: '* '
+msgid "\"* another item\""
+msgstr "\"* et andet emne\""
+
+#. type: Plain text
+msgid ""
+"To make a numbered list, start each line with a number (any number will do) "
+"followed by a period:"
+msgstr ""
+"En nummereret liste laves ved at starte hver linje med et nummer (ethvert "
+"nummer kan bruges) efterfulgt af punktum:"
+
+#. type: Bullet: '1. '
+msgid "\"1. first line\""
+msgstr "\"1. første linje\""
+
+#. type: Bullet: '2. '
+msgid "\"2. second line\""
+msgstr "\"2. anden linje\""
+
+#. type: Bullet: '2. '
+msgid "\"2. third line\""
+msgstr "\"2. tredje linje\""
+
+#. type: Plain text
+msgid ""
+"To create a header, start a line with one or more `#` characters followed by "
+"a space and the header text. The number of `#` characters controls the size "
+"of the header:"
+msgstr ""
+"En overskrift eller en sektion er en linje med et eller flere `#`-tegn "
+"efterfulgt af et mellemrum og overskriftsteksten. Antallet af `#`-tegn "
+"styrer overskriftens størrelse:"
+
+#. type: Title #
+#, no-wrap
+msgid "# h1"
+msgstr "# h1"
+
+#. type: Title ##
+#, no-wrap
+msgid "## h2"
+msgstr "## h2"
+
+#. type: Title ###
+#, no-wrap
+msgid "### h3"
+msgstr "### h3"
+
+#. type: Title ####
+#, no-wrap
+msgid "#### h4"
+msgstr "#### h4"
+
+#. type: Title #####
+#, no-wrap
+msgid "##### h5"
+msgstr "##### h5"
+
+#. type: Title ######
+#, no-wrap
+msgid "###### h6"
+msgstr "###### h6"
+
+#. type: Plain text
+msgid ""
+"To create a horizontal rule, just write three or more dashes or stars on "
+"their own line:"
+msgstr ""
+"En vandret skillelinje oprettes ved at skrive tre eller flere bindestreger "
+"eller stjerner på en linje for sig selv."
+
+#. type: Plain text
+#, no-wrap
+msgid "To quote someone, prefix the quote with \">\":\n"
+msgstr "Citater angives ved at sætte \">\" foran hver linje:\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"> To be or not to be,\n"
+"> that is the question.\n"
+msgstr ""
+"> At være eller ikke være,\n"
+"> det er spørgsmålet.\n"
+
+#. type: Plain text
+msgid "To write a code block, indent each line with a tab or 4 spaces:"
+msgstr ""
+"En kodeblok skrives ved at indrykke hver linje med eet tabulator-tegn eller "
+"4 mellemrum:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t10 PRINT \"Hello, world!\"\n"
+"\t20 GOTO 10\n"
+msgstr ""
+"\t10 PRINT \"Hello, world!\"\n"
+"\t20 GOTO 10\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"To link to an url or email address, you can just put the\n"
+"url in angle brackets: <<http://ikiwiki.info>>, or you can use the\n"
+"form \\[link text\\]\\(url\\)\n"
+msgstr ""
+"Du kan henvise til en URL eller en email-adresse ved at putte addressen i\n"
+"vinkelklammer: <<http://ikiwiki.info>>, eller du kan bruge formen\n"
+"\\[henvisningstekst\\]\\(adresse\\)\n"
+
+#. type: Plain text
+msgid ""
+"In addition to basic html formatting using [[MarkDown]], this wiki lets you "
+"use the following additional features:"
+msgstr ""
+"Udover normal html-formatering med [[MarkDown]], kan du med denne wiki bruge "
+"følgende ekstra finesser:"
+
+#. type: Bullet: '* '
+msgid ""
+"To link to another page on the wiki, place the page's name inside double "
+"square brackets. So you would use `\\[[WikiLink]]` to link to [[WikiLink]]."
+msgstr ""
+"Henvise til en anden side på wikien ved at skrive sidenavnet med dobbelte "
+"lodrette klammer omkring. Udtrykket `\\[[WikiLink]]` henviser til "
+"[[WikiLink]]."
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(smiley) and smileys\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(smiley) and smileys\" then=\"\"\"\n"
+
+#. type: Bullet: '* '
+msgid "Insert [[smileys]] and some other useful symbols. :-)"
+msgstr "Indsætte [[smileys]] og andre anvendelige symboler. :-)"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(shortcut) and shortcuts\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(shortcut) and shortcuts\" then=\"\"\"\n"
+
+#. type: Bullet: '* '
+msgid "Use [[shortcuts]] to link to common resources."
+msgstr "Bruge [[genveje|shortcuts]] til at henvise til gængse ressourcer."
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!wikipedia War\\_of\\_1812]]\n"
+msgstr "\t\\[[!wikipedia War\\_of\\_1812]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(template) and templates\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(template) and templates\" then=\"\"\"\n"
+
+#. type: Bullet: '* '
+msgid ""
+"Create and fill out [[templates]] for repeated chunks of parameterized wiki "
+"text."
+msgstr ""
+"Oprette og udfylde [[skabeloner|templates]] for gentagne klumper af "
+"parameteriseret wikitekst."
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"* Insert various [[directives|directive]] onto a page to perform useful\n"
+"  actions.\n"
+"[[!if test=\"enabled(toc) or enabled(meta) or enabled(inline)\" then=\"\"\"\n"
+msgstr ""
+"* Indsæt diverse [[directiver|directive]] på en side for at udføre nyttige\n"
+"  handlinger.\n"
+"[[!if test=\"enabled(toc) or enabled(meta) or enabled(inline)\" then=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "  For example, you can:\n"
+msgstr "  Eksempelvis kan du:\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(toc)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(toc)\" then=\"\"\"\n"
+
+#. type: Bullet: '  * '
+msgid "Add a table of contents to a page:"
+msgstr "Tilføje en indholdsfortegnelse til en side:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toc]]\n"
+msgstr "\t\\[[!toc]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(meta)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(meta)\" then=\"\"\"\n"
+
+#. type: Bullet: '  * '
+msgid "Change the title of a page:"
+msgstr "Ændre titlen på en side:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!meta title=\"full page title\"]]\n"
+msgstr "\t\\[[!meta title=\"fuldstændige sidetitel\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(inline)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(inline)\" then=\"\"\"\n"
+
+#. type: Bullet: '  * '
+msgid "Create a blog by inlining a set of pages:"
+msgstr "Oprette en [[blog]] ved at indlejre et udvalg af sider:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"blog/*\"]]\n"
+msgstr "\t\\[[!inline pages=\"blog/*\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(listdirectives)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(listdirectives)\" then=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Full list of [[directives|directive]] enabled for this wiki:\n"
+msgstr "  Komplet oversigt over [[directiver|directive]] aktiveret for denne wiki:\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "  [[!listdirectives ]]\n"
+msgstr "  [[!listdirectives ]]\n"
diff --git a/po/underlays/basewiki/ikiwiki/markdown.da.po b/po/underlays/basewiki/ikiwiki/markdown.da.po
new file mode 100644 (file)
index 0000000..ba2eb56
--- /dev/null
@@ -0,0 +1,54 @@
+# Danish translation of basewiki/ikiwiki/markdown page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"[Markdown](http://daringfireball.net/projects/markdown/)  is a minimal "
+"markup language that resembles plain text as used in email messages. It is "
+"the markup language used by this wiki by default."
+msgstr ""
+"[Markdown](http://daringfireball.net/projects/markdown/) er et minimalt "
+"opmærkningssprog som afspejler simpel tekst som det bruges i email-beskeder. "
+"Det er standard opmærkningssprog for denne wiki."
+
+#. type: Plain text
+msgid ""
+"For documentation about the markdown syntax, see [[formatting]] and "
+"[Markdown: syntax](http://daringfireball.net/projects/markdown/syntax)."
+msgstr ""
+"Du kan læse dokumentation til markdown-syntaksen under [[formatering|"
+"formatting]] og [Markdown: syntax](http://daringfireball.net/projects/"
+"markdown/syntax)."
+
+#. type: Plain text
+msgid ""
+"Note that [[WikiLinks|WikiLink]] and [[directives|directive]] are not part "
+"of the markdown syntax, and are the only bit of markup that this wiki "
+"handles internally."
+msgstr ""
+"Bemærk at [[WikiLinks|WikiLink]] og [[direktiver|directive]] ikke er en del "
+"af markdown-syntaksen, og er de eneste stumper opmærkning som denne wiki "
+"håndterer internt."
diff --git a/po/underlays/basewiki/ikiwiki/openid.da.po b/po/underlays/basewiki/ikiwiki/openid.da.po
new file mode 100644 (file)
index 0000000..7f030ee
--- /dev/null
@@ -0,0 +1,123 @@
+# Danish translation of basewiki/ikiwiki/openid page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta title=\"OpenID\"]]\n"
+msgstr "[[!meta title=\"OpenID\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(openid)\"\n"
+"     then=\"This wiki has OpenID **enabled**.\"\n"
+"     else=\"This wiki has OpenID **disabled**.\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(openid)\"\n"
+"     then=\"Denne wiki har OpenID **aktiveret**.\"\n"
+"     else=\"Denne wiki har OpenID **deaktiveret**.\"]]\n"
+
+#. type: Plain text
+msgid ""
+"[OpenID](http://openid.net) is a decentralized authentication mechanism that "
+"allows you to have one login that you can use on a growing number of "
+"websites."
+msgstr ""
+"[OpenID](http://openid.net) er en decentral ægthedsmekanisme som giver dig "
+"mulighed for at have eet login som du kan bruge på et voksende antal "
+"websteder."
+
+#. type: Plain text
+msgid ""
+"To sign up for an OpenID, visit one of the following identity providers:"
+msgstr ""
+"Du kan registrere en OpenID ved at besøge en af de følgende "
+"identitetsudbydere:"
+
+#. type: Bullet: '* '
+msgid "[MyOpenID](https://www.myopenid.com/)"
+msgstr "[MyOpenID](https://www.myopenid.com/)"
+
+#. type: Bullet: '* '
+msgid "[GetOpenID](https://getopenid.com/)"
+msgstr "[GetOpenID](https://getopenid.com/)"
+
+#. type: Bullet: '* '
+msgid "[Videntity](http://videntity.org/)"
+msgstr "[Videntity](http://videntity.org/)"
+
+#. type: Bullet: '* '
+msgid "[LiveJournal](http://www.livejournal.com/openid/)"
+msgstr "[LiveJournal](http://www.livejournal.com/openid/)"
+
+#. type: Bullet: '* '
+msgid "[TrustBearer](https://openid.trustbearer.com/)"
+msgstr "[TrustBearer](https://openid.trustbearer.com/)"
+
+#. type: Bullet: '* '
+msgid ""
+"or any of the [many others out there](http://openiddirectory.com/openid-"
+"providers-c-1.html)"
+msgstr ""
+"eller enhver af de [mange andre derude](http://openiddirectory.com/openid-"
+"providers-c-1.html)"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"Your OpenID is the URL that you are given when you sign up.\n"
+"[[!if test=\"enabled(openid)\" then=\"\"\"\n"
+msgstr ""
+"Din OpenID er den URL som du får når du registrerer dig.\n"
+"[[!if test=\"enabled(openid)\" then=\"\"\"\n"
+
+#. type: Plain text
+msgid ""
+"To sign in to this wiki using OpenID, just enter it in the OpenID field in "
+"the signin form. You do not need to give this wiki a password or go through "
+"any registration process when using OpenID."
+msgstr ""
+"Du kan logge på denne wiki med OpenID, ved blot at angive den i OpenID-"
+"feltet på login-siden. Du behøves ikke at oplyse din adgangskode til denne "
+"wiki eller at gennemgå en registreringsproces når du bruger OpenID."
+
+#. type: Plain text
+msgid ""
+"It's also possible to make a page in the wiki usable as an OpenID url, by "
+"delegating it to an openid server. Here's an example of how to do that:"
+msgstr ""
+"Det er også muligt at lave en side i wikien brugbar som en OpenID URL, ved "
+"at delegere den til en openid server. Her er et eksempel på hvordan det kan "
+"gøres:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!meta openid=\"http://yourid.myopenid.com/\"\n"
+"\t       server=\"http://www.myopenid.com/server\"]]\n"
+msgstr ""
+"\t\\[[!meta openid=\"http://yourid.myopenid.com/\"\n"
+"\t       server=\"http://www.myopenid.com/server\"]]\n"
diff --git a/po/underlays/basewiki/ikiwiki/pagespec.da.po b/po/underlays/basewiki/ikiwiki/pagespec.da.po
new file mode 100644 (file)
index 0000000..f3bfd57
--- /dev/null
@@ -0,0 +1,253 @@
+# Danish translation of basewiki/ikiwiki/pagespec page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"To select a set of pages, such as pages that are locked, pages whose commit "
+"emails you want subscribe to, or pages to combine into a blog, the wiki uses "
+"a PageSpec. This is an expression that matches a set of pages."
+msgstr ""
+"Til at angive et udvalg af sider, eksempelvis låste sider, sider du vil "
+"abonnere på ændringer til, eller sider som skal udgøre en blog, anvender "
+"wikien et PageSpec. dette er et udtryk som passer for et bestemt udvalg af "
+"sider."
+
+#. type: Plain text
+msgid ""
+"The simplest PageSpec is a simple list of pages. For example, this matches "
+"any of the three listed pages:"
+msgstr ""
+"Det simpleste PageSpec er simpelthen en opremsning af sider med \"or\" "
+"imellem (\"or\" betyder \"eller\" på engelsk). Dette passer eksempelvis for "
+"enhver af de tre nævnte sider:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tfoo or bar or baz\n"
+msgstr "\tfoo or bar or baz\n"
+
+#. type: Plain text
+msgid ""
+"More often you will want to match any pages that have a particular thing in "
+"their name. You can do this using a glob pattern. \"`*`\" stands for any "
+"part of a page name, and \"`?`\" for any single letter of a page name. So "
+"this matches all pages about music, and any [[SubPage]]s of the SandBox, but "
+"does not match the SandBox itself:"
+msgstr ""
+"Mere hyppigt har du dog brug for at passe for sider med noget bestemt i "
+"deres navne. Dette kan du udtrykke med et \"glob-mønster\". \"`*`\" står "
+"for enhver del af et sidenavn, og \"`?`\" for ethvert enkeltbogstav i et "
+"sidenavn. Så dette passer for alle sider om musik, og alle [[UnderSider||"
+"SubPage]] til sandkassen, men ikke selve sandkasse-siden:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t*music* or SandBox/*\n"
+msgstr "\t*musik* or SandBox/*\n"
+
+#. type: Plain text
+msgid ""
+"You can also prefix an item with \"`!`\" to skip pages that match it. So to "
+"match all pages except for Discussion pages and the SandBox:"
+msgstr ""
+"Du kan også angive \"`!`\" foran et emne for at undgå sider som passer for "
+"det. Så for at passe for alle sider undtagen diskussionssider og sandkassen:"
+
+#. type: Bullet: '     * '
+msgid "and !SandBox and !*/Discussion"
+msgstr "and !SandBox and !*/Discussion"
+
+#. type: Plain text
+msgid ""
+"Some more elaborate limits can be added to what matches using these "
+"functions:"
+msgstr "Resultaterne kan begrænses mere nuanceret med disse funktioner:"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`link(page)`\" - matches only pages that link to a given page (or glob)"
+msgstr ""
+"\"`link(side)`\" - passer kun for sider som henviser til en given side "
+"(eller glob)"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`tagged(tag)`\" - matches pages that are tagged or link to the given tag "
+"(or tags matched by a glob)"
+msgstr ""
+"\"`tagged(mærkat)`\" - passer for sider mærket af med eller som henviser til "
+"den givne mærkat (eller mærkater som passer for et glob)"
+
+#. type: Bullet: '* '
+msgid "\"`backlink(page)`\" - matches only pages that a given page links to"
+msgstr ""
+"\"`backlink(side)`\" - passer kun for sider som en given side henviser til"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`creation_month(month)`\" - matches only pages created on the given month"
+msgstr ""
+"\"`creation_month(måned)`\" - passer kun for sider oprettet den givne måned"
+
+#. type: Bullet: '* '
+msgid "\"`creation_day(mday)`\" - or day of the month"
+msgstr "\"`creation_day(månedsdag)`\" - eller dag på måneden"
+
+#. type: Bullet: '* '
+msgid "\"`creation_year(year)`\" - or year"
+msgstr "\"`creation_year(år)`\" - eller år"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`created_after(page)`\" - matches only pages created after the given page "
+"was created"
+msgstr ""
+"\"`created_after(side)`\" - passer kun for sider oprettet efter den givne "
+"side blev oprettet"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`created_before(page)`\" - matches only pages created before the given "
+"page was created"
+msgstr ""
+"\"`created_before(side)`\" - passer kun for sider oprettet før den givne "
+"side blev oprettet"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`glob(someglob)`\" - matches pages that match the given glob. Just writing "
+"the glob by itself is actually a shorthand for this function."
+msgstr ""
+"\"`glob(nogetglob)`\" - passer for sider som passer for det givne glob. Blot "
+"at skrive glob'et alene er faktisk en genvej til denne funktion."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`internal(glob)`\" - like `glob()`, but matches even internal-use pages "
+"that globs do not usually match."
+msgstr ""
+"\"`internal(glob)`\" - lissom `glob()`, men passer også for internt anvendte "
+"sider som glob normalt ikke passer for."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`title(glob)`\", \"`author(glob)`\", \"`authorurl(glob)`\", \"`license"
+"(glob)`\", \"`copyright(glob)`\" - match pages that have the given metadata, "
+"matching the specified glob."
+msgstr ""
+"\"`title(glob)`\", \"`author(glob)`\", \"`authorurl(glob)`\", \"`license"
+"(glob)`\", \"`copyright(glob)`\" - passer for sider med de givne metadata, "
+"som passer for det angivne glob."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`user(username)`\" - tests whether a modification is being made by a user "
+"with the specified username. If openid is enabled, an openid can also be put "
+"here."
+msgstr ""
+"\"`user(brugernavn)`\" - tester hvorvidt en ændring foretages af en bruger "
+"med det angivne  brugernavn. Hvis openid er aktiveret, kan en openid også "
+"bruges her."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`admin()`\" - tests whether a modification is being made by one of the "
+"wiki admins."
+msgstr ""
+"\"`admin()`\" - tester hvorvidt en ændring foretages af en af wiki-"
+"administratorerne."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`ip(address)`\" - tests whether a modification is being made from the "
+"specified IP address."
+msgstr ""
+"\"`ip(adresse)`\" - tester hvorvidt en ændring foretages fra den angivne IP-"
+"adresse."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`postcomment(glob)`\" - matches only when comments are being posted to a "
+"page matching the specified glob"
+msgstr ""
+"\"`postcomment(glob)`\" - passer kun når kommentarer er blevet indsendt "
+"til en side som passer for det angivne glob"
+
+#. type: Plain text
+msgid ""
+"For example, to match all pages in a blog that link to the page about music "
+"and were written in 2005:"
+msgstr ""
+"For eksempelvis at passe for alle sider i en blog som henviser til en side "
+"om musik og som blev skrevet i 2005:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tblog/* and link(music) and creation_year(2005)\n"
+msgstr "\tblog/* and link(musik) and creation_year(2005)\n"
+
+#. type: Plain text
+msgid ""
+"Note the use of \"and\" in the above example, that means that only pages "
+"that match each of the three expressions match the whole. Use \"and\" when "
+"you want to combine expression like that; \"or\" when it's enough for a page "
+"to match one expression. Note that it doesn't make sense to say \"index and "
+"SandBox\", since no page can match both expressions."
+msgstr ""
+"Bemærk brugen af \"and\" i eksemplet ovenfor (\"and\" betyder \"og\" på "
+"engelsk), som betyder at kun sider der passer for hvert af de tre udtryk "
+"passer for det hele. Brug \"and\" når du vil kombinere udtryk på den måde; "
+"\"or\" når det er nok for en side at den passer for ét udtryk. Bemærk at det "
+"ikke giver mening at sige \"index and SandBox\", da ingen sider kan passe "
+"for begge udtryk."
+
+#. type: Plain text
+msgid ""
+"More complex expressions can also be created, by using parentheses for "
+"grouping. For example, to match pages in a blog that are tagged with either "
+"of two tags, use:"
+msgstr ""
+"Mere komplekse udtryk kan dannes ved at gruppere med paranteser. Eksempelvis "
+"passer dette for sider i en blog som er mærket af med en af to mærkater:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tblog/* and (tagged(foo) or tagged(bar))\n"
+msgstr "\tblog/* and (tagged(foo) or tagged(bar))\n"
+
+#. type: Plain text
+msgid ""
+"Note that page names in PageSpecs are matched against the absolute filenames "
+"of the pages in the wiki, so a pagespec \"foo\" used on page \"a/b\" will "
+"not match a page named \"a/foo\" or \"a/b/foo\". To match relative to the "
+"directory of the page containing the pagespec, you can use \"./\". For "
+"example, \"./foo\" on page \"a/b\" matches page \"a/foo\"."
+msgstr ""
+"Bemærk at PageSpecs for sidenavne afstemmes som de absolutte filnavne for "
+"siderne i wikien, så et pagespec \"foo\" brugt på siden \"a/b\" vil ikke "
+"passe for siderne navngivet \"a/foo\" eller \"a/b/foo\". For at afstemme "
+"relativt til samme mappe som siden der indeholder pagespec'et kan du bruge "
+"\"./\". Eksempelvis passer \"./foo\" på siden \"a/b\" for siden \"a/foo\"."
diff --git a/po/underlays/basewiki/ikiwiki/pagespec/attachment.da.po b/po/underlays/basewiki/ikiwiki/pagespec/attachment.da.po
new file mode 100644 (file)
index 0000000..6f3d286
--- /dev/null
@@ -0,0 +1,120 @@
+# Danish translation of basewiki/ikiwiki/pagespec/attachment page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(attachment)\"\n"
+"     then=\"This wiki has attachments **enabled**.\"\n"
+"     else=\"This wiki has attachments **disabled**.\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(attachment)\"\n"
+"     then=\"Denne wiki har vedhæftninger **aktiveret**.\"\n"
+"     else=\"Denne wiki har vedhæftninger **deaktiveret**.\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If attachments are enabled, the wiki admin can control what types of "
+"attachments will be accepted, via the `allowed_attachments` configuration "
+"setting."
+msgstr ""
+"Hvis vedhæftninger er aktiveret, kan wiki-administratoren styre hvilke typer "
+"vedhæftninger der vil blive accepteret gennem opsætningsindstillingen "
+"`allowed_attachments`."
+
+#. type: Plain text
+msgid ""
+"For example, to limit arbitrary files to 50 kilobytes, but allow larger mp3 "
+"files to be uploaded by joey into a specific directory, and check all "
+"attachments for viruses, something like this could be used:"
+msgstr ""
+"Som eksempel, for at begrænse vilkårlige filer til 50 kilobytes, men tillade "
+"større mp3-filer at blive lagt op af joey til en bestemt mappe, og checke "
+"alle vedhæftninger for vira, kunne noget i stil med dette bruges:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tvirusfree() and ((user(joey) and podcast/*.mp3 and mimetype(audio/mpeg) and maxsize(15mb)) or (!ispage() and maxsize(50kb)))\n"
+msgstr "\tvirusfree() and ((user(joey) and podcast/*.mp3 and mimetype(audio/mpeg) and maxsize(15mb)) or (!ispage() and maxsize(50kb)))\n"
+
+#. type: Plain text
+msgid ""
+"The regular [[ikiwiki/PageSpec]] syntax is expanded with the following "
+"additional tests:"
+msgstr ""
+"Den normale [[ikiwiki/PageSpec]]-syntaks er udvidet med følgende yderligere "
+"tests:"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`maxsize(size)`\" - tests whether the attachment is no larger than the "
+"specified size. The size defaults to being in bytes, but \"kb\", \"mb\", \"gb"
+"\" etc can be used to specify the units."
+msgstr ""
+"\"`maxsize(størrelse)`\" - tester hvorvidt vedhæftningen højst fylder den "
+"angivne størrelse. Størrelsen angives som standard i bytes, men \"kb\", \"mb"
+"\", \"gb\" osv. kan bruges til at angive enheder."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`minsize(size)`\" - tests whether the attachment is no smaller than the "
+"specified size."
+msgstr ""
+"\"`minsize(størrelse)`\" - tester hvorvidt størrelsen mindst fylder den "
+"angivne størrelse."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`ispage()`\" - tests whether the attachment will be treated by ikiwiki as "
+"a wiki page. (Ie, if it has an extension of \".mdwn\", or of any other "
+"enabled page format)."
+msgstr ""
+"\"`ispage()`\" - tester hvorvidt vedhæftningen bliver håndteret af ikiwiki "
+"som en wikiside. (altså om den har endelsen \".mdwn\", eller et hvilket som "
+"helst andet aktiveret sideformat)."
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  So, if you don't want to allow wiki pages to be uploaded as attachments,\n"
+"  use `!ispage()` ; if you only want to allow wiki pages to be uploaded\n"
+"  as attachments, use `ispage()`.\n"
+msgstr ""
+"  Derfor, hvis du ikke vil tillade wikisider at blive lagt op som vedhæftninger,\n"
+"  så brug `!ispage()` ; hvis du kun vil tillade wikisider at blive lagt op som\n"
+"  vedhæftninger, så brug `ispage()`.\n"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`mimetype(foo/bar)`\" - checks the MIME type of the attachment. You can "
+"include a glob in the type, for example `mimetype(image/*)`."
+msgstr ""
+"\"`mimetype(foo/bar)`\" - checker MIME-typen for vedhæftningen. Du kan "
+"angive et glob som type, eksampelvis `mimetype(image/*)`."
+
+#. type: Bullet: '* '
+msgid "\"`virusfree()`\" - checks the attachment with an antiviral program."
+msgstr "\"`virusfree()`\" - checker vedhæftningen med et antivirusprogram."
diff --git a/po/underlays/basewiki/ikiwiki/pagespec/po.da.po b/po/underlays/basewiki/ikiwiki/pagespec/po.da.po
new file mode 100644 (file)
index 0000000..b719d25
--- /dev/null
@@ -0,0 +1,65 @@
+# Danish translation of basewiki/ikiwiki/pagespec/po page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-20 11:33+0300\n"
+"PO-Revision-Date: 2009-07-20 11:41+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(po)\"\n"
+"     then=\"This wiki has po support **enabled**.\"\n"
+"     else=\"This wiki has po support **disabled**.\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(po)\"\n"
+"     then=\"Denne wiki har oversættelser **aktiveret**.\"\n"
+"     else=\"Denne wiki har oversættelser **deaktiveret**.\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If the [[!iki plugins/po desc=po]] plugin is enabled, the regular [[ikiwiki/"
+"PageSpec]] syntax is expanded with the following additional tests that can "
+"be used to improve user navigation in a multi-lingual wiki:"
+msgstr ""
+"Hvis udvidelsen [[!iki plugins/po desc=po]] er aktiveret er den normale "
+"[[ikiwiki/PageSpec]]-syntaks udvidet med følgende yderligere tests som kan "
+"bruges til at forbedre brugernavigation i en flersproget wiki:"
+
+#. type: Bullet: '* '
+msgid ""
+"\"`lang(LL)`\" - tests whether a page is written in the language specified "
+"as a ISO639-1 (two-letter) language code."
+msgstr ""
+"\"`lang(LL)`\" - tester hvorvidt en side er skrevet i sproget angivet som en "
+"ISO639-1 (to-bogstavs) sprogkode."
+
+#. type: Bullet: '* '
+msgid ""
+"\"`currentlang()`\" - tests whether a page is written in the same language "
+"as the current page."
+msgstr ""
+"\"`currentlang()`\" - tester hvorvidt en side er skrevet i samme sprog som "
+"den nuværende side."
+
+#. type: Plain text
+msgid ""
+"Note that every non-po page is considered to be written in "
+"`po_master_language`, as specified in `ikiwiki.setup`."
+msgstr ""
+"Bemærk at enhver ikke-po side antages at være skrevet i "
+"`po_master_language`, som angivet i `ikiwiki.setup`."
diff --git a/po/underlays/basewiki/ikiwiki/preprocessordirective.da.po b/po/underlays/basewiki/ikiwiki/preprocessordirective.da.po
new file mode 100644 (file)
index 0000000..4eee728
--- /dev/null
@@ -0,0 +1,40 @@
+# Danish translation of basewiki/ikiwiki/preprocessordirective page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=ikiwiki/directive delay=10]]\n"
+msgstr "[[!meta redir=ikiwiki/directive delay=10]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This page has moved to [[ikiwiki/directive|ikiwiki/directive]]. Please "
+"update your links, as this redirection page will be removed in a future "
+"ikiwiki release."
+msgstr ""
+"Denne side er flyttet til [[ikiwiki/directive|ikiwiki/directive]]. Opdatér "
+"dine henvisninger, da denne omdirigeringsside bliver fjernet i en fremtidig "
+"udgave af ikiwiki."
diff --git a/po/underlays/basewiki/ikiwiki/searching.da.po b/po/underlays/basewiki/ikiwiki/searching.da.po
new file mode 100644 (file)
index 0000000..3d65812
--- /dev/null
@@ -0,0 +1,90 @@
+# Danish translation of basewiki/ikiwiki/searching page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(search)\"\n"
+"then=\"This wiki has searching **enabled**.\"\n"
+"else=\"This wiki has searching **disabled**.\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(search)\"\n"
+"then=\"Denne wiki har søgning **aktiveret**.\"\n"
+"else=\"Denne wiki har søgning **deaktiveret**.\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If searching is enabled, you can enter search terms in the search field, as "
+"you'd expect. There are a few special things you can do to constuct more "
+"powerful searches."
+msgstr ""
+"Hvis søgning er aktiveret, kan du angive søgeudtryk i søgefeltet, som du "
+"ville forvente. Der er et par specielle ting du kan gøre for at konstruere "
+"mere effektive søgninger."
+
+#. type: Bullet: '* '
+msgid "To match a phrase, enclose it in double quotes."
+msgstr ""
+"Put gåseøjne omkring nogle ord for at søge efter dem som én formulering."
+
+#. type: Bullet: '* '
+msgid "`AND` can be used to search for documents containing two expressions."
+msgstr ""
+"`AND` kan bruges til at søge efter dokumenter som indeholder to udtryk."
+
+#. type: Bullet: '* '
+msgid ""
+"`OR` can be used to search for documents containing either one of two "
+"expressions."
+msgstr ""
+"`OR` kan bruges ti at søge efter dokumenter som indeholder ethvert af to "
+"udtryk."
+
+#. type: Bullet: '* '
+msgid ""
+"Parentheses can be used to build up complicated search expressions. For "
+"example, \"(foo AND bar) OR (me AND you)\""
+msgstr ""
+"Parenteser kan bruges til at opbygge komplicerede søgeformuleringer. "
+"Eksempelvis \"(foo AND bar) OR (mig AND dig)\""
+
+#. type: Bullet: '* '
+msgid ""
+"Prefix a search term with \"-\" to avoid it from appearing in the results.  "
+"For example, \"-discussion\" will omit \"discussion\"."
+msgstr ""
+"Put \"-\" foran et søgeudtryk for at undgå det blandt resultaterne. "
+"Eksempelvis vil \"-discussion\" udelade \"discussion\"."
+
+#. type: Bullet: '* '
+msgid "To search for a page with a given title, use \"title:foo\"."
+msgstr "Brug \"title:foo\" til at søge efter en side med en given titel."
+
+#. type: Bullet: '* '
+msgid "To search for pages that contain a \"bar\" link, use \"link:bar\"."
+msgstr ""
+"Brug \"link:bar\" til at søge efter sider som indeholder henvisning til \"bar"
+"\"."
diff --git a/po/underlays/basewiki/ikiwiki/subpage.da.po b/po/underlays/basewiki/ikiwiki/subpage.da.po
new file mode 100644 (file)
index 0000000..0934350
--- /dev/null
@@ -0,0 +1,56 @@
+# Danish translation of basewiki/ikiwiki/subpage page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"ikiwiki supports placing pages in a directory hierarchy. For example, this "
+"page, [[SubPage]] has some related pages placed under it, like [[SubPage/"
+"LinkingRules]]. This is a useful way to add some order to your wiki rather "
+"than just having a great big directory full of pages."
+msgstr ""
+"ikiwiki understøtter placering af sider i et mappehierarki. Eksempelvis har "
+"denne side, [[UnderSide|SubPage]], nogle relaterede sider placeret under "
+"sig, bl.a. [[HenvisningsRegler|SubPage/LinkingRules]]. dette er en praktisk "
+"måde at bringe orden i din wiki fremfor blot at have een stor mappe fuld af "
+"sider."
+
+#. type: Plain text
+msgid ""
+"To add a SubPage, just make a subdirectory and put pages in it. For example, "
+"this page is SubPage.mdwn in this wiki's source, and there is also a SubPage "
+"subdirectory, which contains SubPage/LinkingRules.mdwn. Subpages can be "
+"nested as deeply as you'd like."
+msgstr ""
+"En [[UnderSide|SubPage]] oprettes ved blot at oprette undermappen og tilføje "
+"sider til den. Denne side er eksempelvis SubPage.mdwn i kildekoden til denne "
+"wiki, og der er også en SubPage undermappe, som indeholder SubPage/"
+"LinkingRules.mdwn. Undersider kan nedarves så dybt du har lyst."
+
+#. type: Plain text
+msgid "Linking to and from a SubPage is explained in [[LinkingRules]]."
+msgstr ""
+"Henvisninger til og fra en [[UnderSide||SubPage]] er forklaret under "
+"[[HenvisningsRegler||LinkingRules]]."
diff --git a/po/underlays/basewiki/ikiwiki/subpage/linkingrules.da.po b/po/underlays/basewiki/ikiwiki/subpage/linkingrules.da.po
new file mode 100644 (file)
index 0000000..01f854b
--- /dev/null
@@ -0,0 +1,107 @@
+# Danish translation of basewiki/ikiwiki/subpage/linkingrules page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"To link to or from a [[SubPage]], you can normally use a regular "
+"[[WikiLink]] that does not contain the name of the parent directory of the "
+"[[SubPage]]. Ikiwiki descends the directory hierarchy looking for a page "
+"that matches your link."
+msgstr ""
+"For at henvise til eller fra en [[underside|SubPage]] kan du normalt bruge "
+"en almindelig normal [[WikiLink]] som ikke indeholder navnet på den "
+"overliggende mappe til [[undersiden|SubPage]]. Ikiwiki gennemgår "
+"mappehierarkiet og kigger efter en side som passer til din henvisning."
+
+#. type: Plain text
+msgid ""
+"For example, if FooBar/SubPage links to \"OtherPage\", ikiwiki will first "
+"prefer pointing the link to FooBar/SubPage/OtherPage if it exists, next to "
+"FooBar/OtherPage and finally to OtherPage in the root of the wiki."
+msgstr ""
+"Hvis eksempelvis FooBar/UnderSide henviser til \"EnAndenSide\", vil ikiwiki "
+"først foretrække at knytte henvisningen til FooBar/UnderSide/EnAndenSide "
+"hvis den eksisterer, så til FooBar/EnAndenSide og til sidst til EnAndenSide "
+"i roden af wikien."
+
+#. type: Plain text
+msgid ""
+"Note that this means that if a link on FooBar/SomePage to \"OtherPage\" "
+"currently links to OtherPage, in the root of the wiki, and FooBar/OtherPage "
+"is created, the link will _change_ to point to FooBar/OtherPage. On the "
+"other hand, a link from BazBar to \"OtherPage\" would be unchanged by this "
+"creation of a [[SubPage]] of FooBar."
+msgstr ""
+"Bemærk at dette betyder, at hvis en henvisning fra FooBar/EnSide til "
+"\"EnAndenSide\" i øjeblikket henviser til EnAndenSide i roden af wikien, og "
+"FooBar/EnAndenSide oprettes, så vil henvisningen blive _ændret_ til at pege "
+"på FooBar/EnAndenSide. Omvendt vil en henvisning fra BazBar til \"EnAndenSide"
+"\" ikke blive berørt af oprettelsen af en [[underside|SubPage]] til FooBar."
+
+#. type: Plain text
+msgid ""
+"You can also specify a link that contains a directory name, like \"FooBar/"
+"OtherPage\" to more exactly specify what page to link to. This is the only "
+"way to link to an unrelated [[SubPage]]."
+msgstr ""
+"Du kan også angive en henvisning som indeholder et mappenavn, lissom "
+"\"FooBar/EnAndenSide\", for mere nøjagtigt at angive hvilken side der "
+"henvises til. Kun på den måde kan du henvise til en anden sides [[underside|"
+"SubPage]]."
+
+#. type: Plain text
+msgid ""
+"You can use this to, for example, to link from BazBar to \"FooBar/SubPage\", "
+"or from BazBar/SubPage to \"FooBar/SubPage\"."
+msgstr ""
+"Du kan bruge dette til eksempelvis at henvise fra BazBar til \"FooBar/"
+"UnderSide\", eller fra BazBar/UnderSide til \"FooBar/UnderSide\"."
+
+#. type: Plain text
+msgid ""
+"You can also use \"/\" at the start of a link, to specify exactly which page "
+"to link to, when there are multiple pages with similar names and the link "
+"goes to the wrong page by default. For example, linking from \"FooBar/SubPage"
+"\" to \"/OtherPage\" will link to the \"OtherPage\" in the root of the wiki, "
+"even if there is a \"FooBar/OtherPage\"."
+msgstr ""
+"Du kan også bruge \"/\" i begyndelsen af en henvisning, til at angive "
+"nøjagtigt hvilken side der henvises til, når der er flere mulige sider med "
+"lignende navne og henvisningen ender forkert som standard. Eksempelvis vil "
+"en henvisning fra \"FooBar/UnderSide\" til \"/EnAndenSide\" henvise til "
+"\"EnAndenSide\" i roden af wikien, selvom der er en \"FooBar/EnAndenSide\"."
+
+#. type: Plain text
+msgid ""
+"Also, if the wiki is configured with a userdir, you can link to pages within "
+"the userdir without specifying a path to them. This is to allow for easy "
+"linking to a user's page in the userdir, to sign a comment. These links are "
+"checked for last of all."
+msgstr ""
+"Desuden kan du, hvis wikien er opsat med \"userdir\", henvise til sider "
+"under hjemmemapper uden at angive en sti til dem. Dette er for at tillade "
+"enkel henvisning til en brugers side i hjemmemappen, som signatur ved en "
+"kommentar. Sådanne henvisninger prøves allersidst."
diff --git a/po/underlays/basewiki/ikiwiki/wikilink.da.po b/po/underlays/basewiki/ikiwiki/wikilink.da.po
new file mode 100644 (file)
index 0000000..8c56584
--- /dev/null
@@ -0,0 +1,110 @@
+# Danish translation of wikilink page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"WikiLinks provide easy linking between pages of the wiki. To create a "
+"[[WikiLink]], just put the name of the page to link to in double brackets.  "
+"For example `\\[[WikiLink]]`."
+msgstr ""
+"WikiLinks gør det muligt enkelt at lave henvisninger (linke) mellem sider i\n"
+"wikien. Opret en [[WikiLink]] ved at skrive siden du vil henvise til med\n"
+"dobbelte klammer omkring. Ekempelvis `\\[[WikiLink]]`.\n"
+
+#. type: Plain text
+msgid ""
+"If you ever need to write something like `\\[[WikiLink]]` without creating a "
+"wikilink, just prefix it with a `\\`, like `\\\\[[WikiLink]]`."
+msgstr ""
+"Hvis du vil skrive noget i stil med `\\[[WikiLink]]` uden at det skal blive "
+"til en wikilink, så put en `\\` (backslash) foran, som i `\\\\[[WikiLink]]`."
+
+#. type: Plain text
+msgid ""
+"There are some special [[SubPage/LinkingRules]] that come into play when "
+"linking between [[SubPages|SubPage]]."
+msgstr ""
+"Specielle [[henvisningsregler|SubPage/LinkingRules]] træder i kraft når der "
+"henvises på tværs af [[undersider|SubPage]]."
+
+#. type: Plain text
+msgid ""
+"Also, if the file linked to by a WikiLink looks like an image, it will be "
+"displayed inline on the page."
+msgstr ""
+"Desuden, hvis filen der henvises til med en WikiLink ligner et billede, vil "
+"det blive vist indlejret i siden."
+
+#. type: Plain text
+msgid ""
+"WikiLinks are matched with page names in a case-insensitive manner, so you "
+"don't need to worry about getting the case the same, and can capitalise "
+"links at the start of a sentence, and so on."
+msgstr ""
+"WikiLinks knyttes til sidenavne uden skelen til store og små bogstaver, så "
+"du behøver ikke at bekymre dig om dette, og kan anvende stort "
+"begyndelsesbogstav i begyndelsen af en sætning o.l."
+
+#. type: Plain text
+msgid ""
+"It's also possible to write a WikiLink that uses something other than the "
+"page name as the link text. For example `\\[[foo_bar|SandBox]]` links to the "
+"SandBox page, but the link will appear like this: [[foo_bar|SandBox]]."
+msgstr ""
+"Det er også muligt at skrive en WikiLink som bruger noget andet end "
+"sidenavnet som henvisningstekst. Eksempelvis henviser `\\[[foo_bar|SandBox]]"
+"` til sandkassen, men henvisningen fremstår som her: [[foo_bar|SandBox]]."
+
+#. type: Plain text
+msgid ""
+"To link to an anchor inside a page, you can use something like `"
+"\\[[WikiLink#foo]]` ."
+msgstr ""
+"For at henvise til et anker inde på en side, kan du bruge noget i stil med `"
+"\\[[WikiLink#foo]]` ."
+
+#. type: Title ##
+#, no-wrap
+msgid "Directives and WikiLinks"
+msgstr "Direktiver og wikilinks"
+
+#. type: Plain text
+msgid ""
+"ikiwiki has two syntaxes for [[directives|directive]].  The older syntax "
+"used spaces to distinguish between directives and wikilinks; as a result, "
+"with that syntax in use, you cannot use spaces in WikiLinks, and must "
+"replace spaces with underscores.  The newer syntax, enabled with the "
+"`prefix_directives` option in an ikiwiki setup file, prefixes directives "
+"with `!`, and thus does not prevent links with spaces.  Future versions of "
+"ikiwiki will turn this option on by default."
+msgstr ""
+"ikiwiki har to syntakser til [[direktiver|directive]]. Den ældre syntaks "
+"brugte mellemrum til at skelne mellem direktiver og wikilinks; det medfører, "
+"at når den syntaks anvendes kan du ikke bruge mellemrum i WikiLinks, og må "
+"erstatte mellemrum med understregning. Den nyere syntaks, aktiveret med "
+"valget `prefix_directives` i en ikiwiki-opsætningsfil, sætter `!` foran "
+"direktiver, og forhindrer derfor ikke henvisninger med mellemrum. Fremtidige "
+"versioner af ikiwiki vil aktivere dette valg som standard."
diff --git a/po/underlays/basewiki/index.da.po b/po/underlays/basewiki/index.da.po
new file mode 100644 (file)
index 0000000..8835e9b
--- /dev/null
@@ -0,0 +1,34 @@
+# Danish translation of basewiki/index page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid "Welcome to your new wiki."
+msgstr "Velkommen til din nye wiki."
+
+#. type: Plain text
+msgid "All wikis are supposed to have a [[SandBox]], so this one does too."
+msgstr ""
+"Alle wikier forventes at have en [[SandKasse|SandBox]], så det har denne "
+"også."
+
+#. type: Plain text
+msgid "This wiki is powered by [ikiwiki](http://ikiwiki.info/)."
+msgstr "Denne wiki er drevet af [ikiwiki](http://ikiwiki.info/)."
diff --git a/po/underlays/basewiki/recentchanges.da.po b/po/underlays/basewiki/recentchanges.da.po
new file mode 100644 (file)
index 0000000..1db466a
--- /dev/null
@@ -0,0 +1,43 @@
+# Danish translation of basewiki/recentchanges page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(meta)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(meta)\" then=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta title=\"RecentChanges\"]]\n"
+msgstr "[[!meta title=\"SenesteÆndringer\"]]\n"
+
+#. type: Plain text
+msgid "Recent changes to this wiki:"
+msgstr "Seneste ændringer til denne wiki:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!inline pages=\"internal(recentchanges/change_*) and !*/Discussion\" \n"
+"template=recentchanges show=0]]\n"
+msgstr ""
+"[[!inline pages=\"internal(recentchanges/change_*) and !*/Discussion\" \n"
+"template=recentchanges show=0]]\n"
diff --git a/po/underlays/basewiki/sandbox.da.po b/po/underlays/basewiki/sandbox.da.po
new file mode 100644 (file)
index 0000000..7930e51
--- /dev/null
@@ -0,0 +1,96 @@
+# Danish translation of basewiki/sandbox page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"This is the SandBox, a page anyone can edit to learn how to use the wiki."
+msgstr ""
+"Dette er [[SandKassen|SandBox]], en side som hvem som helst kan redigere for "
+"at lære hvordan en wiki bruges."
+
+#. type: Plain text
+msgid "Here's a paragraph."
+msgstr "Her er et afsnit."
+
+#. type: Plain text
+msgid "Here's another one with *emphasised* text."
+msgstr "her er et andet afsnit med *fremhævet* tekst."
+
+#. type: Title #
+#, no-wrap
+msgid "Header"
+msgstr "Overskrift"
+
+#. type: Title ##
+#, no-wrap
+msgid "Subheader"
+msgstr "Underoverskrift"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"> This is a blockquote.\n"
+">\n"
+"> This is the first level of quoting.\n"
+">\n"
+"> > This is nested blockquote.\n"
+">\n"
+"> Back to the first level.\n"
+msgstr ""
+"> Dette er et citat-område\n"
+">\n"
+"> Dette er første niveau citering.\n"
+">\n"
+"> > Dette er et indlejret citat-område.\n"
+">\n"
+"> Tilbage til det første niveau.\n"
+
+#. type: Plain text
+msgid "Numbered list"
+msgstr "Nummereret liste"
+
+#. type: Bullet: '1. '
+msgid "First item."
+msgstr "Første emne."
+
+#. type: Bullet: '1. '
+msgid "Another."
+msgstr "Et andet."
+
+#. type: Bullet: '1. '
+msgid "And another.."
+msgstr "Og et andet.."
+
+#. type: Plain text
+msgid "Bulleted list"
+msgstr "Unummereret liste"
+
+#. type: Bullet: '* '
+msgid "*item*"
+msgstr "*emne*"
+
+#. type: Bullet: '* '
+msgid "item"
+msgstr "emne"
+
+#. type: Plain text
+msgid "[[ikiwiki/WikiLink]]"
+msgstr "[[ikiwiki/WikiLink]]"
diff --git a/po/underlays/basewiki/shortcuts.da.po b/po/underlays/basewiki/shortcuts.da.po
new file mode 100644 (file)
index 0000000..f6907d9
--- /dev/null
@@ -0,0 +1,229 @@
+# Danish translation of shortcuts page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(shortcut)\"\n"
+"     then=\"This wiki has shortcuts **enabled**.\"\n"
+"     else=\"This wiki has shortcuts **disabled**.\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(shortcut)\"\n"
+"     then=\"Denne wiki har genveje **aktiveret**.\"\n"
+"     else=\"Denne wiki har genveje **deaktiveret**.\"]]\n"
+
+#. type: Plain text
+msgid "Some examples of using shortcuts include:"
+msgstr "Nogle eksempler på brug af genveje:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!google foo]]\n"
+"\t\\[[!wikipedia War_of_1812]]\n"
+"\t\\[[!debbug 12345]]\n"
+"\tCheck the \\[[!cia ikiwiki desc=\"CIA page for %s\"]].\n"
+msgstr ""
+"\t\\[[!google foo]]\n"
+"\t\\[[!wikipedia War_of_1812]]\n"
+"\t\\[[!debbug 12345]]\n"
+
+#. type: Plain text
+msgid "This page controls what shortcut links the wiki supports."
+msgstr "Denne side styrer hvilke genveje wikien understøtter."
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=google url=\"http://www.google.com/search?q=%s\"]]"
+msgstr "[[!shortcut name=google url=\"http://www.google.com/search?q=%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=archive url=\"http://web.archive.org/*/%S\"]]"
+msgstr "[[!shortcut name=archive url=\"http://web.archive.org/*/%S\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=gmap url=\"http://maps.google.com/maps?q=%s\"]]"
+msgstr "[[!shortcut name=gmap url=\"http://maps.google.com/maps?q=%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=gmsg url=\"http://groups.google.com/groups?selm=%s\"]]"
+msgstr ""
+"[[!shortcut name=gmsg url=\"http://groups.google.com/groups?selm=%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=wikipedia url=\"http://en.wikipedia.org/wiki/%s\"]]"
+msgstr "[[!shortcut name=wikipedia url=\"http://en.wikipedia.org/wiki/%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=wikitravel url=\"http://wikitravel.org/en/%s\"]]"
+msgstr "[[!shortcut name=wikitravel url=\"http://wikitravel.org/en/%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=wiktionary url=\"http://en.wiktionary.org/wiki/%s\"]]"
+msgstr "[[!shortcut name=wiktionary url=\"http://en.wiktionary.org/wiki/%s\"]]"
+
+#. type: Bullet: '* '
+msgid ""
+"[[!shortcut name=debbug url=\"http://bugs.debian.org/%s\" desc=\"bug #%s\"]]"
+msgstr ""
+"[[!shortcut name=debbug url=\"http://bugs.debian.org/%s\" desc=\"bug #%s\"]]"
+
+#. type: Bullet: '* '
+msgid ""
+"[[!shortcut name=deblist url=\"http://lists.debian.org/debian-%s\" desc="
+"\"debian-%s@lists.debian.org\"]]"
+msgstr ""
+"[[!shortcut name=deblist url=\"http://lists.debian.org/debian-%s\" desc="
+"\"debian-%s@lists.debian.org\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=debpkg url=\"http://packages.debian.org/%s\"]]"
+msgstr "[[!shortcut name=debpkg url=\"http://packages.debian.org/%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=debpkgsid url=\"http://packages.debian.org/sid/%s\"]]"
+msgstr "[[!shortcut name=debpkgsid url=\"http://packages.debian.org/sid/%s\"]]"
+
+#. type: Bullet: '* '
+msgid "[[!shortcut name=debpts url=\"http://packages.qa.debian.org/%s\"]]"
+msgstr "[[!shortcut name=debpts url=\"http://packages.qa.debian.org/%s\"]]"
+
+#. type: Bullet: '* '
+msgid ""
+"[[!shortcut name=debmsg url=\"http://lists.debian.org/msgid-search/%s\"]]"
+msgstr ""
+"[[!shortcut name=debmsg url=\"http://lists.debian.org/msgid-search/%s\"]]"
+
+#. type: Bullet: '* '
+msgid ""
+"[[!shortcut name=debrt url=\"https://rt.debian.org/Ticket/Display.html?id=%s"
+"\"]]"
+msgstr ""
+"[[!shortcut name=debrt url=\"https://rt.debian.org/Ticket/Display.html?id=%s"
+"\"]]"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"* [[!shortcut name=debss url=\"http://snapshot.debian.net/package/%s\"]]\n"
+"  * Usage: `\\[[!debss package]]`, `\\[[!debss package#version]]`, or `\\[[!debss package/version]]`.  See http://snapshot.debian.net for details.\n"
+"* [[!shortcut name=debwiki url=\"http://wiki.debian.org/%s\"]]\n"
+"* [[!shortcut name=fdobug url=\"https://bugs.freedesktop.org/show_bug.cgi?id=%s\" desc=\"freedesktop.org bug #%s\"]]\n"
+"* [[!shortcut name=fdolist url=\"http://lists.freedesktop.org/mailman/listinfo/%s\" desc=\"%s@lists.freedesktop.org\"]]\n"
+"* [[!shortcut name=gnomebug url=\"http://bugzilla.gnome.org/show_bug.cgi?id=%s\" desc=\"GNOME bug #%s\"]]\n"
+"* [[!shortcut name=linuxbug url=\"http://bugzilla.kernel.org/show_bug.cgi?id=%s\" desc=\"Linux bug #%s\"]]\n"
+"* [[!shortcut name=mozbug url=\"https://bugzilla.mozilla.org/show_bug.cgi?id=%s\" desc=\"Mozilla bug #%s\"]]\n"
+"* [[!shortcut name=gnulist url=\"http://lists.gnu.org/mailman/listinfo/%s\" desc=\"%s@gnu.org\"]]\n"
+"* [[!shortcut name=marcmsg url=\"http://marc.info/?i=%s\"]]\n"
+"* [[!shortcut name=marclist url=\"http://marc.info/?l=%s\"]]\n"
+"* [[!shortcut name=gmane url=\"http://dir.gmane.org/gmane.%s\" desc=\"gmane.%s\"]]\n"
+"* [[!shortcut name=gmanemsg url=\"http://mid.gmane.org/%s\"]]\n"
+"* [[!shortcut name=cpan url=\"http://search.cpan.org/search?mode=dist&query=%s\"]]\n"
+"* [[!shortcut name=ctan url=\"http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=%s\"]]\n"
+"* [[!shortcut name=hoogle url=\"http://haskell.org/hoogle/?q=%s\"]]\n"
+"* [[!shortcut name=iki url=\"http://ikiwiki.info/%S/\"]]\n"
+"* [[!shortcut name=ljuser url=\"http://%s.livejournal.com/\"]]\n"
+"* [[!shortcut name=rfc url=\"http://www.ietf.org/rfc/rfc%s.txt\" desc=\"RFC %s\"]]\n"
+"* [[!shortcut name=c2 url=\"http://c2.com/cgi/wiki?%s\"]]\n"
+"* [[!shortcut name=meatballwiki url=\"http://www.usemod.com/cgi-bin/mb.pl?%s\"]]\n"
+"* [[!shortcut name=emacswiki url=\"http://www.emacswiki.org/cgi-bin/wiki/%s\"]]\n"
+"* [[!shortcut name=haskellwiki url=\"http://haskell.org/haskellwiki/%s\"]]\n"
+"* [[!shortcut name=dict url=\"http://www.dict.org/bin/Dict?Form=Dict1&Strategy=*&Database=*&Query=%s\"]]\n"
+"* [[!shortcut name=imdb url=\"http://imdb.com/find?q=%s\"]]\n"
+"* [[!shortcut name=gpg url=\"http://pgpkeys.mit.edu:11371/pks/lookup?op=vindex&exact=on&search=0x%s\"]]\n"
+"* [[!shortcut name=perldoc url=\"http://perldoc.perl.org/search.html?q=%s\"]]\n"
+"* [[!shortcut name=whois url=\"http://reports.internic.net/cgi/whois?whois_nic=%s&type=domain\"]]\n"
+"* [[!shortcut name=cve url=\"http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s\"]]\n"
+"* [[!shortcut name=cia url=\"http://cia.vc/stats/project/%s\"]]\n"
+"* [[!shortcut name=ciauser url=\"http://cia.vc/stats/user/%s\"]]\n"
+"* [[!shortcut name=flickr url=\"http://www.flickr.com/photos/%s\"]]\n"
+"* [[!shortcut name=man url=\"http://linux.die.net/man/%s\"]]\n"
+"* [[!shortcut name=ohloh url=\"http://www.ohloh.net/projects/%s\"]]\n"
+msgstr ""
+"* [[!shortcut name=debss url=\"http://snapshot.debian.net/package/%s\"]]\n"
+"  * Brug: `\\[[!debss package]]`, `\\[[!debss package#version]]`, eller `\\[[!debss package/version]]`.  Se http://snapshot.debian.net for detaljer.\n"
+"* [[!shortcut name=debwiki url=\"http://wiki.debian.org/%s\"]]\n"
+"* [[!shortcut name=fdobug url=\"https://bugs.freedesktop.org/show_bug.cgi?id=%s\" desc=\"freedesktop.org bug #%s\"]]\n"
+"* [[!shortcut name=fdolist url=\"http://lists.freedesktop.org/mailman/listinfo/%s\" desc=\"%s@lists.freedesktop.org\"]]\n"
+"* [[!shortcut name=gnomebug url=\"http://bugzilla.gnome.org/show_bug.cgi?id=%s\" desc=\"GNOME bug #%s\"]]\n"
+"* [[!shortcut name=linuxbug url=\"http://bugzilla.kernel.org/show_bug.cgi?id=%s\" desc=\"Linux bug #%s\"]]\n"
+"* [[!shortcut name=mozbug url=\"https://bugzilla.mozilla.org/show_bug.cgi?id=%s\" desc=\"Mozilla bug #%s\"]]\n"
+"* [[!shortcut name=gnulist url=\"http://lists.gnu.org/mailman/listinfo/%s\" desc=\"%s@gnu.org\"]]\n"
+"* [[!shortcut name=marcmsg url=\"http://marc.info/?i=%s\"]]\n"
+"* [[!shortcut name=marclist url=\"http://marc.info/?l=%s\"]]\n"
+"* [[!shortcut name=gmane url=\"http://dir.gmane.org/gmane.%s\" desc=\"gmane.%s\"]]\n"
+"* [[!shortcut name=gmanemsg url=\"http://mid.gmane.org/%s\"]]\n"
+"* [[!shortcut name=cpan url=\"http://search.cpan.org/search?mode=dist&query=%s\"]]\n"
+"* [[!shortcut name=ctan url=\"http://tug.ctan.org/cgi-bin/ctanPackageInformation.py?id=%s\"]]\n"
+"* [[!shortcut name=hoogle url=\"http://haskell.org/hoogle/?q=%s\"]]\n"
+"* [[!shortcut name=iki url=\"http://ikiwiki.info/%S/\"]]\n"
+"* [[!shortcut name=ljuser url=\"http://%s.livejournal.com/\"]]\n"
+"* [[!shortcut name=rfc url=\"http://www.ietf.org/rfc/rfc%s.txt\" desc=\"RFC %s\"]]\n"
+"* [[!shortcut name=c2 url=\"http://c2.com/cgi/wiki?%s\"]]\n"
+"* [[!shortcut name=meatballwiki url=\"http://www.usemod.com/cgi-bin/mb.pl?%s\"]]\n"
+"* [[!shortcut name=emacswiki url=\"http://www.emacswiki.org/cgi-bin/wiki/%s\"]]\n"
+"* [[!shortcut name=haskellwiki url=\"http://haskell.org/haskellwiki/%s\"]]\n"
+"* [[!shortcut name=dict url=\"http://www.dict.org/bin/Dict?Form=Dict1&Strategy=*&Database=*&Query=%s\"]]\n"
+"* [[!shortcut name=imdb url=\"http://imdb.com/find?q=%s\"]]\n"
+"* [[!shortcut name=gpg url=\"http://pgpkeys.mit.edu:11371/pks/lookup?op=vindex&exact=on&search=0x%s\"]]\n"
+"* [[!shortcut name=perldoc url=\"http://perldoc.perl.org/search.html?q=%s\"]]\n"
+"* [[!shortcut name=whois url=\"http://reports.internic.net/cgi/whois?whois_nic=%s&type=domain\"]]\n"
+"* [[!shortcut name=cve url=\"http://cve.mitre.org/cgi-bin/cvename.cgi?name=%s\"]]\n"
+"* [[!shortcut name=cia url=\"http://cia.vc/stats/project/%s\"]]\n"
+"* [[!shortcut name=ciauser url=\"http://cia.vc/stats/user/%s\"]]\n"
+"* [[!shortcut name=flickr url=\"http://www.flickr.com/photos/%s\"]]\n"
+"* [[!shortcut name=man url=\"http://linux.die.net/man/%s\"]]\n"
+"* [[!shortcut name=ohloh url=\"http://www.ohloh.net/projects/%s\"]]\n"
+
+#. type: Plain text
+msgid ""
+"To add a new shortcut, use the `shortcut` [[ikiwiki/directive]]. In the url, "
+"\"%s\" is replaced with the text passed to the named shortcut, after url-"
+"encoding it, and '%S' is replaced with the raw, non-encoded text. The "
+"optional `desc` parameter controls the description of the link."
+msgstr ""
+"Tilføj en ny genvej med [[direktivet|ikiwiki/directive]] `shortcut`. I URLen "
+"erstattes \"%s\" med teksten overdraget til den navngivne genvej, efter URL-"
+"omkodning af den, og '%S' erstattes med den rå, ukodede tekst. Den valgfri "
+"`desc`-parameter styrer beskrivelsen af henvisningen."
+
+#. type: Plain text
+msgid ""
+"Remember that the `name` you give the shortcut will become a new [[ikiwiki/"
+"directive]].  Avoid using a `name` that conflicts with an existing "
+"directive.  These directives also accept a `desc` parameter that will "
+"override the one provided at definition time."
+msgstr ""
+"Husk at `name`-parameteren som du tildeler genvejen bliver et nyt [[direktiv|"
+"ikiwiki/directive]]. Undgå et navn som er i strid med et eksisterende "
+"direktiv. Disse direktiver accepterer også en `desc`-parameter som vil "
+"overskygge den der blev angivet ved definitionen."
+
+#. type: Plain text
+msgid ""
+"If you come up with a shortcut that you think others might find useful, "
+"consider contributing it to the [shortcuts page on the ikiwiki ikiwiki]"
+"(http://ikiwiki.info/shortcuts/), so that future versions of ikiwiki will "
+"include your shortcut in the standard underlay."
+msgstr ""
+"Hvis du finder på en genvej som du mener andre kunne få glæde af også, kan "
+"du overveje at bidrage med den til [shortcuts-siden på ikiwiki ikiwikien]"
+"(http://ikiwiki.info/shortcuts/), så fremtidige versioner af ikiwiki "
+"inkluderer din genvej i standardunderlaget."
diff --git a/po/underlays/basewiki/templates.da.po b/po/underlays/basewiki/templates.da.po
new file mode 100644 (file)
index 0000000..22f9500
--- /dev/null
@@ -0,0 +1,244 @@
+# Danish translation of templates page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!if test=\"enabled(template)\"\n"
+"then=\"This wiki has templates **enabled**.\"\n"
+"else=\"This wiki has templates **disabled**.\"\n"
+"]]\n"
+msgstr ""
+"[[!if test=\"enabled(template)\"\n"
+"then=\"Denne wiki har skabeloner **aktiveret**.\"\n"
+"else=\"Denne wiki har skabeloner **deaktiveret**.\" ]]\n"
+
+#. type: Plain text
+msgid ""
+"Templates are files that can be filled out and inserted into pages in the "
+"wiki."
+msgstr "Skabeloner er filer som kan blive udfyldt og indsat på sider i wikien."
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!if test=\"enabled(template) and enabled(inline)\" then=\"\"\"\n"
+msgstr "[[!if test=\"enabled(template) and enabled(inline)\" then=\"\"\"\n"
+
+#. type: Plain text
+msgid ""
+"These templates are available for inclusion onto other pages in this wiki:"
+msgstr ""
+"Disse skabeloner er tilgængelige til indsættelse på andre sider i denne wiki:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"[[!inline pages=\"templates/* and !*/discussion\" feeds=no archive=yes\n"
+"sort=title template=titlepage]]\n"
+msgstr ""
+"[[!inline pages=\"templates/* and !*/discussion\" feeds=no archive=yes\n"
+"sort=title template=titlepage]]\n"
+
+#. type: Title ##
+#, no-wrap
+msgid "Using a template"
+msgstr "Brug af skabelon"
+
+#. type: Plain text
+msgid "Using a template works like this:"
+msgstr "En skabelon bruges som her:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!template id=note text=\"\"\"Here is the text to insert into my note.\"\"\"]]\n"
+msgstr "\t\\[[!template id=note text=\"\"\"Her er teksten til at sætte ind i min note.\"\"\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This fills out the [[note]] template, filling in the `text` field with the "
+"specified value, and inserts the result into the page."
+msgstr ""
+"Dette udfylder [[note]]-skabelonen, ved at erstatte `text`-feltet med den "
+"angivne værdi og indsætte resultatet på siden."
+
+#. type: Plain text
+msgid ""
+"Generally, a value can include any markup that would be allowed in the wiki "
+"page outside the template. Triple-quoting the value even allows quotes to be "
+"included in it. Combined with multi-line quoted values, this allows for "
+"large chunks of marked up text to be embedded into a template:"
+msgstr ""
+"Generelt kan en værdi indeholde enhver opmærkning som ville være tilladt på "
+"wikisiden udenfor skabelonen. Trippel-citering af værdien tillader endda at "
+"bruge citering som del af værdien. Kombineret med flerlinje-citerede værdier "
+"tillader dette indlejring af store klumper af opmærket tekst i skabelonen:"
+
+#. type: Plain text
+#, no-wrap
+msgid "        \\[[!template id=foo name=\"Sally\" color=\"green\" age=8 notes=\"\"\"\n"
+msgstr "        \\[[!template id=foo name=\"Sally\" color=\"grøn\" age=8 notes=\"\"\"\n"
+
+#. type: Bullet: '        * '
+msgid "\\[[Charley]]'s sister."
+msgstr "\\[[Charley]]'s søster."
+
+#. type: Bullet: '        * '
+msgid "\"I want to be an astronaut when I grow up.\""
+msgstr "\"Jeg vil være en astronaut når jeg bliver stor.\""
+
+#. type: Bullet: '        * '
+msgid "Really 8 and a half."
+msgstr "Egentligt 8 og et halvt."
+
+#. type: Title ##
+#, no-wrap
+msgid "Creating a template"
+msgstr "Oprettelse af skabelon"
+
+#. type: Plain text
+msgid ""
+"To create a template, simply add a template directive to a page, and the "
+"page will provide a link that can be used to create the template. The "
+"template is a regular wiki page, located in the `templates/` subdirectory "
+"inside the source directory of the wiki."
+msgstr ""
+"Opret en skabelon ved simpelthen at tilføje skabelon-direktivet til en side, "
+"så vil siden vise en henvisning som kan bruges til at oprette skabelonen. "
+"Skabelonen er en normal wikiside, placeret i `templates/` undermappen indeni "
+"wikiens kildemappe."
+
+#. type: Plain text
+msgid ""
+"The template uses the syntax used by the [[!cpan HTML::Template]] perl "
+"module, which allows for some fairly complex things to be done. Consult its "
+"documentation for the full syntax, but all you really need to know are a few "
+"things:"
+msgstr ""
+"Skabelonen bruger samme syntax som perl-modulet [[!cpan HTML::Template]] som "
+"giver mulighed for at lave ret komplekse ting. Læs dokumentationen for den "
+"fulde syntaks, men alt hvad du reelt behøver at vide er nogle få ting:"
+
+#. type: Bullet: '* '
+msgid ""
+"Each parameter you pass to the template directive will generate a template "
+"variable. There are also some pre-defined variables like PAGE and BASENAME."
+msgstr ""
+"Ethvert parameter du angiver til skabelondirektivet vil danne en "
+"skabelonvariabel. Der er også nogle foruddefinerede variable som PAGE og "
+"BASENAME."
+
+#. type: Bullet: '* '
+msgid ""
+"To insert the value of a variable, use `<TMPL_VAR variable>`. Wiki markup in "
+"the value will first be converted to html."
+msgstr ""
+"Brug `<TMPL_VAR variabel>` til at indsætte værdien af en variabel. Wiki-"
+"opmærkning i værdien bliver først konverteret til html."
+
+#. type: Bullet: '* '
+msgid ""
+"To insert the raw value of a variable, with wiki markup not yet converted to "
+"html, use `<TMPL_VAR raw_variable>`."
+msgstr ""
+"Brug `<TMPL_VAR raw_variabel>` til at indsætte den rå værdi af en variabel, "
+"med wiki-opmærkning endnu ikke konverteret til html."
+
+#. type: Bullet: '* '
+msgid ""
+"To make a block of text conditional on a variable being set use `<TMPL_IF "
+"NAME=\"variable\">text</TMPL_IF>`."
+msgstr ""
+"Gør en tekstblok betinget af at en variabel er i brug med `<TMPL_IF NAME="
+"\"variabel\">tekst</TMPL_IF>`."
+
+#. type: Bullet: '* '
+msgid ""
+"To use one block of text if a variable is set and a second if it's not, use "
+"`<TMPL_IF NAME=\"variable\">text<TMPL_ELSE>other text</TMPL_IF>`"
+msgstr ""
+"Brug een tekstblok hvis en variabel er i brug, og en anden hvis ikke, med "
+"`<TMPL_IF NAME=\"variabel\">tekst<TMPL_ELSE>anden tekst</TMPL_IF>`"
+
+#. type: Plain text
+msgid "Here's a sample template:"
+msgstr ""
+"Her er et eksempel på en skabelon (det anbefales at bruge engelske "
+"variabelnavne for at undgå problemer med æøå og andre specialtegn):"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"        <span class=\"infobox\">\n"
+"        Name: \\[[<TMPL_VAR raw_name>]]<br />\n"
+"        Age: <TMPL_VAR age><br />\n"
+"        <TMPL_IF NAME=\"color\">\n"
+"        Favorite color: <TMPL_VAR color><br />\n"
+"        <TMPL_ELSE>\n"
+"        No favorite color.<br />\n"
+"        </TMPL_IF>\n"
+"        <TMPL_IF NAME=\"notes\">\n"
+"        <hr />\n"
+"        <TMPL_VAR notes>\n"
+"        </TMPL_IF>\n"
+"        </span>\n"
+msgstr ""
+"        <span class=\"infobox\">\n"
+"        Navn: \\[[<TMPL_VAR raw_name>]]<br />\n"
+"        Alder: <TMPL_VAR age><br />\n"
+"        <TMPL_IF NAME=\"color\">\n"
+"        Favoritfarve: <TMPL_VAR color><br />\n"
+"        <TMPL_ELSE>\n"
+"        Ingen favoritfarve.<br />\n"
+"        </TMPL_IF>\n"
+"        <TMPL_IF NAME=\"notes\">\n"
+"        <hr />\n"
+"        <TMPL_VAR notes>\n"
+"        </TMPL_IF>\n"
+"        </span>\n"
+
+#. type: Plain text
+msgid ""
+"The filled out template will be formatted the same as the rest of the page "
+"that contains it, so you can include WikiLinks and all other forms of wiki "
+"markup in the template. Note though that such WikiLinks will not show up as "
+"backlinks to the page that uses the template."
+msgstr ""
+"Den udfyldte skabelon vil blive formateret som resten af siden den er "
+"inkluderet i, så du kan medtage WikiLinks og alle andre former for wiki- "
+"opmærkning i skabelonen. Bemærk dog at sådanne WikiLinks ikke vil dukke op "
+"som krydshenvisninger (backlinks) til den side som anvender skabelonen."
+
+#. type: Plain text
+msgid ""
+"Note the use of \"raw_name\" inside the [[ikiwiki/WikiLink]] generator. This "
+"ensures that if the name contains something that might be mistaken for wiki "
+"markup, it's not converted to html before being processed as a [[ikiwiki/"
+"WikiLink]]."
+msgstr ""
+"Bemærk brugen af \"raw_name\" indeni [[ikiwiki/WikiLink]]-generatoren. Dette "
+"sikrer at hvor navnet indeholder noget som måske kan fejltolkes som wiki-"
+"opmærkning, bliver det ikke konverteret til html før det er blevet behandlet "
+"som en [[ikiwiki/WikiLink]]."
diff --git a/po/underlays/basewiki/templates/note.da.po b/po/underlays/basewiki/templates/note.da.po
new file mode 100644 (file)
index 0000000..f748dbe
--- /dev/null
@@ -0,0 +1,47 @@
+# Danish translation of basewiki/templates/note page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"<div class=\"notebox\">\n"
+"<TMPL_VAR text>\n"
+"</div>\n"
+"<TMPL_UNLESS NAME=\"text\">\n"
+"Use this template to insert a note into a page. The note will be styled to\n"
+"float to the right of other text on the page. This template has one\n"
+"parameter:\n"
+"<ul>\n"
+"<li>`text` - the text to display in the note\n"
+"</ul>\n"
+"</TMPL_UNLESS>\n"
+msgstr ""
+"<div class=\"notebox\">\n"
+"<TMPL_VAR text>\n"
+"</div>\n"
+"<TMPL_UNLESS NAME=\"text\">\n"
+"Brug denne skabelon til at indsætte en note på en side. Noten vil blive\n"
+"udsmykket til at flyde til højre for den øvrige tekst på siden. Denne\n"
+"skabelon har et parameter:\n"
+"<ul>\n"
+"<li>`text` - teksten som vises i noten\n"
+"</ul>\n"
+"</TMPL_UNLESS>\n"
diff --git a/po/underlays/basewiki/templates/popup.da.po b/po/underlays/basewiki/templates/popup.da.po
new file mode 100644 (file)
index 0000000..f766015
--- /dev/null
@@ -0,0 +1,56 @@
+# Danish translation of basewiki/templates/popup page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"<TMPL_UNLESS NAME=\"mouseover\">\n"
+"Use this template to create a popup window that is displayed when the mouse\n"
+"is over part of the page. This template has two parameters:\n"
+"<ul>\n"
+"<li>`mouseover` - This is the text or other content that triggers the\n"
+"popup.\n"
+"<li>`popup` - This should be the content of the popup window. It can be\n"
+"anything, even images or a whole little wiki page, but should not be too\n"
+"large for good usability.\n"
+"</ul>\n"
+"Note that browsers that do not support the CSS will display the popup\n"
+"inline in the page, inside square brackets.\n"
+"</TMPL_UNLESS>\n"
+"<span class=\"popup\"><TMPL_VAR mouseover>\n"
+"<span class=\"paren\">[</span><span class=\"balloon\"><TMPL_VAR popup></span><span class=\"paren\">]</span>\n"
+"</span>\n"
+msgstr ""
+"<TMPL_UNLESS NAME=\"mouseover\">\n"
+"Brug denne skabelon til at lave et popup-vindue som vises når musemarkøren er\n"
+"henover en del af siden. Denne skabelon har to parametre:\n"
+"<ul>\n"
+"<li>`mouseover` - Dette er teksten eller andet indhold som udløser popup'en.\n"
+"<li>`popup` - Her angives indeholdet af popup-vinduet. Det kan være hvad som\n"
+"helst, endda billeder eller hele små wikisider, men bør ikke være for stort af\n"
+"hensyn til brugervenligheden.\n"
+"</ul>\n"
+"Bemærk at browsere som ikke understøtter CSS-koden vil vise popup'en indlejret\n"
+"på siden, indenfor lodrette klammer.\n"
+"</TMPL_UNLESS>\n"
+"<span class=\"popup\"><TMPL_VAR mouseover>\n"
+"<span class=\"paren\">[</span><span class=\"balloon\"><TMPL_VAR popup></span><span class=\"paren\">]</span>\n"
+"</span>\n"
diff --git a/po/underlays/directives/ikiwiki/directive/aggregate.da.po b/po/underlays/directives/ikiwiki/directive/aggregate.da.po
new file mode 100644 (file)
index 0000000..e3ff8f3
--- /dev/null
@@ -0,0 +1,149 @@
+# Danish translation of directives/ikiwiki/directive/aggregrate page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `aggregate` directive is supplied by the [[!iki plugins/aggregate "
+"desc=aggregate]] plugin.  This plugin requires extra setup, specifically, a "
+"cron job. See the plugin's documentation for details."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows content from other feeds to be aggregated into the "
+"wiki.  Aggregate a feed as follows:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!aggregate name=\"example blog\" dir=\"example\"\n"
+"\tfeedurl=\"http://example.com/index.rss\"\n"
+"\turl=\"http://example.com/\" updateinterval=\"15\"]]\n"
+msgstr ""
+"\t\\[[!aggregate name=\"eksempel blog\" dir=\"eksempel\"\n"
+"\tfeedurl=\"http://eksempel.dk/index.rss\"\n"
+"\turl=\"http://eksempel.dk/\" updateinterval=\"15\"]]\n"
+
+#. type: Plain text
+msgid ""
+"That example aggregates posts from the specified RSS feed, updating no more "
+"frequently than once every 15 minutes (though possibly less frequently, if "
+"the cron job runs less frequently than that), and puts a page per post under "
+"the example/ directory in the wiki."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You can then use ikiwiki's [[inline]] directive to create a blog of one or "
+"more aggregated feeds. For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"internal(example/*)\"]]\n"
+msgstr "\t\\[[!inline pages=\"internal(eksempel/*)\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Note the use of `internal()` in the [[ikiwiki/PageSpec]] to match aggregated "
+"pages. By default, aggregated pages are internal pages, which prevents them "
+"from showing up directly in the wiki, and so this special [[PageSpec]] is "
+"needed to match them."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+msgid ""
+"Here are descriptions of all the supported parameters to the `aggregate` "
+"directive:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`name` - A name for the feed. Each feed must have a unique name.  Required."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`url` - The url to the web page for the feed that's being aggregated.  "
+"Required."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`dir` - The directory in the wiki where pages should be saved. Optional, if "
+"not specified, the directory is based on the name of the feed."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feedurl` - The url to the feed. Optional, if it's not specified ikiwiki "
+"will look for feeds on the `url`. RSS and atom feeds are supported."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`updateinterval` - How often to check for new posts, in minutes. Default is "
+"15 minutes."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`expireage` - Expire old items from this feed if they are older than a "
+"specified number of days. Default is to never expire on age."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`expirecount` - Expire old items from this feed if there are more than the "
+"specified number total. Oldest items will be expired first. Default is to "
+"never expire on count."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`tag` - A tag to tag each post from the feed with. A good tag to use is the "
+"name of the feed. Can be repeated multiple times. The [[tag]] plugin must be "
+"enabled for this to work."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`template` - Template to use for creating the aggregated pages. Defaults to "
+"aggregatepost."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Note that even if you are using subversion or another revision control "
+"system, pages created by aggregation will *not* be checked into revision "
+"control."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/brokenlinks.da.po b/po/underlays/directives/ikiwiki/directive/brokenlinks.da.po
new file mode 100644 (file)
index 0000000..8d04886
--- /dev/null
@@ -0,0 +1,53 @@
+# Danish translation of directives/ikiwiki/directive/brokenlinks page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `brokenlinks` directive is supplied by the [[!iki plugins/brokenlinks "
+"desc=brokenlinks]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive generates a list of broken links on pages in the wiki. This "
+"is a useful way to find pages that still need to be written, or links that "
+"are written wrong."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The optional parameter \"pages\" can be a [[ikiwiki/PageSpec]] specifying "
+"the pages to search for broken links, default is search them all."
+msgstr ""
+
+#. type: Plain text
+msgid "Example:"
+msgstr "Eksempel:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!brokenlinks pages=\"* and !recentchanges\"]]\n"
+msgstr "\t\\[[!brokenlinks pages=\"* and !recentchanges\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/calendar.da.po b/po/underlays/directives/ikiwiki/directive/calendar.da.po
new file mode 100644 (file)
index 0000000..401c813
--- /dev/null
@@ -0,0 +1,125 @@
+# Danish translation of directives/ikiwiki/directive/calendar page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `calendar` directive is supplied by the [[!iki plugins/calendar "
+"desc=calendar]] plugin.  This plugin requires extra setup.  See the plugin "
+"documentation for details."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive displays a calendar, similar to the typical calendars shown "
+"on some blogs."
+msgstr ""
+
+#. type: Title #
+#, no-wrap
+msgid "examples"
+msgstr "exempler"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!calendar ]]\n"
+msgstr "\t\\[[!calendar ]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!calendar type=\"month\" pages=\"blog/* and !*/Discussion\"]]\n"
+msgstr "\t\\[[!calendar type=\"month\" pages=\"blog/* and !*/Discussion\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!calendar type=\"year\" year=\"2005\" pages=\"blog/* and !*/Discussion\"]]\n"
+msgstr "\t\\[[!calendar type=\"year\" year=\"2005\" pages=\"blog/* and !*/Discussion\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The calendar is essentially a fancy front end to archives of previous pages, "
+"usually used for blogs. It can produce a calendar for a given month, or a "
+"list of months for a given year."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The month format calendar simply links to any page posted on each day of the "
+"month. The year format calendar links to archive pages, with names like "
+"`archives/2007` (for all of 2007)  and `archives/2007/01` (for January, "
+"2007). For this to work, you'll need to create these archive pages. They "
+"typically use [[inline]] to display or list pages created in the given time "
+"frame."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Bullet: '* '
+msgid ""
+"`type` - Used to specify the type of calendar wanted. Can be one of \"month"
+"\" or \"year\". The default is a month view calendar."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`pages` - Specifies the [[ikiwiki/PageSpec]] of pages to link to from the "
+"month calendar. Defaults to \"*\"."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`archivebase` - Configures the base of the archives hierarchy. The default "
+"is \"archives\". Note that this default can also be overridden for the whole "
+"wiki by setting `archivebase` in ikiwiki's setup file."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`year` - The year for which the calendar is requested. Defaults to the "
+"current year."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`month` - The numeric month for which the calendar is requested, in the "
+"range 1..12. Used only for the month view calendar, and defaults to the "
+"current month."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`week_start_day` - A number, in the range 0..6, which represents the day of "
+"the week that the month calendar starts with. 0 is Sunday, 1 is Monday, and "
+"so on. Defaults to 0, which is Sunday."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`months_per_row` - In the annual calendar, number of months to place in each "
+"row. Defaults to 3."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/color.da.po b/po/underlays/directives/ikiwiki/directive/color.da.po
new file mode 100644 (file)
index 0000000..59ba665
--- /dev/null
@@ -0,0 +1,80 @@
+# Danish translation of directives/ikiwiki/directive/color page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `color` directive is supplied by the [[!iki plugins/color desc=color]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive can be used to color a piece of text on a page.  It can be "
+"used to set the foreground and/or background color of the text."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You can use a color name (e.g. `white`) or HTML code (e.g. `#ffffff`)  to "
+"define colors."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "examples"
+msgstr "eksempler"
+
+#. type: Plain text
+msgid ""
+"Here the foreground color is defined as a word, while the background color "
+"is defined as a HTML color code:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!color foreground=white background=#ff0000 text=\"White text on red background\"]]\n"
+msgstr "\t\\[[!color foreground=white background=#ff0000 text=\"Hvid tekst på rød baggrund\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The background color is missing, so the text is displayed on default "
+"background:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!color foreground=white text=\"White text on default color background\"]]\n"
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The foreground is missing, so the text has the default foreground color:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!color background=#ff0000 text=\"Default color text on red background\"]]\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/comment.da.po b/po/underlays/directives/ikiwiki/directive/comment.da.po
new file mode 100644 (file)
index 0000000..20cf299
--- /dev/null
@@ -0,0 +1,116 @@
+# Danish translation of directives/ikiwiki/directive/comment page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `comment` directive is supplied by the [[!iki plugins/comments "
+"desc=comments]] plugin, and is used to add a comment to a page. Typically, "
+"the directive is the only thing on a comment page, and is filled out by the "
+"comment plugin when a user posts a comment."
+msgstr ""
+
+#. type: Plain text
+msgid "Example:"
+msgstr "Eksempel:"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!comment format=mdwn\n"
+"\tusername=\"foo\"\n"
+"\tsubject=\"Bar\"\n"
+"\tdate=\"2009-06-02T19:05:01Z\"\n"
+"\tcontent=\"\"\"\n"
+msgstr ""
+"\t\\[[!comment format=mdwn\n"
+"\tusername=\"foo\"\n"
+"\tsubject=\"Bar\"\n"
+"\tdate=\"2009-06-02T19:05:01Z\"\n"
+"\tcontent=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tBlah blah.\n"
+"\t\"\"\"\n"
+msgstr ""
+"\tBlah blah.\n"
+"\t\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t]]\n"
+msgstr "\t]]\n"
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+msgid ""
+"The only required parameter is `content`, the others just add or override "
+"metadata of the comment."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`content` - Text to display for the comment.  Note that [[directives|ikiwiki/"
+"directive]] may not be allowed, depending on the configuration of the "
+"comment plugin."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`format` - Specifies the markup used for the content."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`subject` - Subject for the comment."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`date` - Date the comment was posted. Can be entered in nearly any format, "
+"since it's parsed by [[!cpan TimeDate]]"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`username` - Used to record the username (or OpenID)  of a logged in "
+"commenter."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`ip` - Can be used to record the IP address of a commenter, if they posted "
+"anonymously."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`claimedauthor` - Records the name that the user entered, if anonmous "
+"commenters are allowed to enter their (unverified)  name."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/copy.da.po b/po/underlays/directives/ikiwiki/directive/copy.da.po
new file mode 100644 (file)
index 0000000..539e809
--- /dev/null
@@ -0,0 +1,30 @@
+# Danish translation of directives/ikiwiki/directive/copy page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+msgstr "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/cut.da.po b/po/underlays/directives/ikiwiki/directive/cut.da.po
new file mode 100644 (file)
index 0000000..90ca7ed
--- /dev/null
@@ -0,0 +1,30 @@
+# Danish translation of directives/ikiwiki/directive/cut page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+msgstr "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/cutpaste.da.po b/po/underlays/directives/ikiwiki/directive/cutpaste.da.po
new file mode 100644 (file)
index 0000000..7eabf12
--- /dev/null
@@ -0,0 +1,134 @@
+# Danish translation of directives/ikiwiki/directive/cutpaste page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `copy`, `cut` and `paste` directives are supplied by the [[!iki plugins/"
+"cutpaste desc=cutpaste]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"With these directives you can store and recall pieces of text in a page:"
+msgstr ""
+
+#. type: Bullet: ' * '
+msgid ""
+"`\\[[!cut id=name text=\"text\"]]` memorizes the text allowing to recall it "
+"using the given ID.  The text being cut is not included in the output."
+msgstr ""
+
+#. type: Bullet: ' * '
+msgid ""
+"`\\[[!copy id=name text=\"text\"]]` memorizes the text allowing to recall it "
+"using the given ID.  The text being cut *is* included in the output."
+msgstr ""
+
+#. type: Bullet: ' * '
+msgid "`\\[[!paste id=name]]` is replaced by the previously memorized text."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The text being cut, copied and pasted can freely include wiki markup, "
+"including more calls to cut, copy and paste."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You do not need to memorize the text before using it: a cut directive can "
+"follow the paste directive that uses its text.  In fact, this is quite "
+"useful to postpone big blocks of text like long annotations and have a more "
+"natural flow.  For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!toggleable id=\"cut\" text=\"[[!paste id=cutlongdesc]]\"]]\n"
+"\t\\[[!toggleable id=\"copy\" text=\"[[!paste id=copylongdesc]]\"]]\n"
+"\t\\[[!toggleable id=\"paste\" text=\"[[!paste id=pastelongdesc]]\"]]\n"
+msgstr ""
+"\t\\[[!toggleable id=\"cut\" text=\"[[!paste id=cutlongdesc]]\"]]\n"
+"\t\\[[!toggleable id=\"copy\" text=\"[[!paste id=copylongdesc]]\"]]\n"
+"\t\\[[!toggleable id=\"paste\" text=\"[[!paste id=pastelongdesc]]\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t[...some time later...]\n"
+msgstr "\t[...noget tid senere...]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!cut id=cutlongdesc text=\"\"\"\n"
+msgstr "\t\\[[!cut id=cutlongdesc text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t   blah blah blah\n"
+msgstr "\t   blah blah blah\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!cut id=copylongdesc text=\"\"\"\n"
+msgstr "\t\\[[!cut id=copylongdesc text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!cut id=pastelongdesc text=\"\"\"\n"
+msgstr "\t\\[[!cut id=pastelongdesc text=\"\"\"\n"
+
+#. type: Plain text
+msgid ""
+"This can potentially be used to create loops, but ikiwiki is clever and "
+"breaks them."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Since you can paste without using double quotes, copy and paste can be used "
+"to nest directives that require multiline parameters inside each other:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toggleable id=foo text=\"\"\"\n"
+msgstr "\t\\[[!toggleable id=foo text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t  [[!toggleable id=bar text=\"[[!paste id=baz]]\"]]\n"
+msgstr "\t  [[!toggleable id=bar text=\"[[!paste id=baz]]\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!cut id=baz text=\"\"\"\n"
+msgstr "\t\\[[!cut id=baz text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tmultiline parameter!\n"
+msgstr "\tflere linjer lang parameter!\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/edittemplate.da.po b/po/underlays/directives/ikiwiki/directive/edittemplate.da.po
new file mode 100644 (file)
index 0000000..41ca61b
--- /dev/null
@@ -0,0 +1,90 @@
+# Danish translation of directives/ikiwiki/directive/edittemplate page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `edittemplate` directive is supplied by the [[!iki plugins/edittemplate "
+"desc=edittemplate]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows registering template pages, that provide default "
+"content for new pages created using the web frontend. To register a "
+"template, insert a [[ikiwiki/directive/template]] directive on some other "
+"page."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!edittemplate template=\"bugtemplate\" match=\"bugs/*\"]]\n"
+msgstr "\t\\[[!edittemplate template=\"bugtemplate\" match=\"bugs/*\"]]\n"
+
+#. type: Plain text
+msgid ""
+"In the above example, the page named \"bugtemplate\" is registered as a "
+"template to be used when any page named \"bugs/*\" is created. To avoid the "
+"directive displaying a note about the template being registered, add "
+"\"silent=yes\"."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Often the template page contains a simple skeleton for a particular type of "
+"page. For the bug report pages in the above example, it might look something "
+"like:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tPackage: \n"
+"\tVersion: \n"
+"\tReproducible: y/n\n"
+"\tDetails:\n"
+msgstr ""
+"\tPackage: \n"
+"\tVersion: \n"
+"\tReproducible: y/n\n"
+"\tDetails:\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"The template page can also contain [[!cpan HTML::Template]] directives,\n"
+"similar to other ikiwiki [[templates]]. Currently only one variable is\n"
+"set: `<TMPL_VAR name>` is replaced with the name of the page being\n"
+"created.\n"
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"It's generally not a good idea to put the `edittemplate` directive in the "
+"template page itself, since the directive would then be included as part of "
+"the template on new pages, which would then in turn be registered as "
+"templates. If multiple pages are registered as templates for a new page, an "
+"arbitrary one is chosen, so that could get confusing."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/format.da.po b/po/underlays/directives/ikiwiki/directive/format.da.po
new file mode 100644 (file)
index 0000000..20a7e7a
--- /dev/null
@@ -0,0 +1,84 @@
+# Danish translation of directives/ikiwiki/directive/format page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `format` directive is supplied by the [[!iki plugins/format "
+"desc=format]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The directive allows formatting a chunk of text using any available page "
+"format. It takes two parameters. First is the type of format to use, ie the "
+"extension that would be used for a standalone file of this type.  Second is "
+"the text to format."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"For example, this will embed an otl outline inside a page using mdwn or some "
+"other format:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!format otl \"\"\"\n"
+msgstr "\t\\[[!format otl \"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tfoo\n"
+"\t\t1\n"
+"\t\t2\n"
+"\tbar\n"
+"\t\t3\n"
+"\t\t4\n"
+msgstr ""
+"\tfoo\n"
+"\t\t1\n"
+"\t\t2\n"
+"\tbar\n"
+"\t\t3\n"
+"\t\t4\n"
+
+#. type: Plain text
+msgid ""
+"Note that if the highlight plugin is enabled, this directive can also be "
+"used to display syntax highlighted code. Many languages and formats are "
+"supported. For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[format perl \"\"\"\n"
+msgstr "\t\\[[format perl \"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\tprint \"hello, world\\n\";\n"
+msgstr "\tprint \"hej, verden\\n\";\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/fortune.da.po b/po/underlays/directives/ikiwiki/directive/fortune.da.po
new file mode 100644 (file)
index 0000000..d0b33ce
--- /dev/null
@@ -0,0 +1,42 @@
+# Danish translation of directives/ikiwiki/directive/fortune page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `fortune` directive is supplied by the [[!iki plugins/fortune "
+"desc=fortune]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This just uses the `fortune` program to insert a fortune cookie into the "
+"page.  Usage:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!fortune ]]\n"
+msgstr "\t\\[[!fortune ]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/graph.da.po b/po/underlays/directives/ikiwiki/directive/graph.da.po
new file mode 100644 (file)
index 0000000..2ca6e26
--- /dev/null
@@ -0,0 +1,76 @@
+# Danish translation of directives/ikiwiki/directive/graph page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `graph` directive is supplied by the [[!iki plugins/graphviz "
+"desc=graphviz]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows embedding [graphviz](http://www.graphviz.org/) graphs "
+"in a page.  Example usage:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!graph src=\"a -> b -> c; a -> c;\"]]\n"
+msgstr "\t\\[[!graph src=\"a -> b -> c; a -> c;\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Note that graphs will only show up in previews if your browser has [[!"
+"wikipedia data: URI]] support, or if the same graph already exists on that "
+"page."
+msgstr ""
+
+#. type: Plain text
+msgid "The `graph` directive supports the following parameters:"
+msgstr ""
+
+#. type: Bullet: '- '
+msgid "`src` - The graphviz source to render."
+msgstr ""
+
+#. type: Bullet: '- '
+msgid ""
+"`type` - The type of graph to render: `graph` or `digraph`.  Defaults to "
+"`digraph`."
+msgstr ""
+
+#. type: Bullet: '- '
+msgid ""
+"`prog` - The graphviz program to render with: `dot`, `neato`, `fdp`, "
+"`twopi`, or `circo`.  Defaults to `dot`."
+msgstr ""
+
+#. type: Bullet: '- '
+msgid ""
+"`height`, `width` - Limit the size of the graph to a given height and width, "
+"in inches. You must specify both to limit the size; otherwise, graphviz will "
+"choose a size, without any limit."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/haiku.da.po b/po/underlays/directives/ikiwiki/directive/haiku.da.po
new file mode 100644 (file)
index 0000000..db8d7e2
--- /dev/null
@@ -0,0 +1,55 @@
+# Danish translation of directives/ikiwiki/directive/haiku page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `haiku` directive is supplied by the [[!iki plugins/haiku desc=haiku]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows inserting a randomly generated haiku into a wiki "
+"page.  Just type:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!haiku hint=\"argument\"]]\n"
+msgstr "\t\\[[!haiku hint=\"argument\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!haiku hint=\"argument test\"]]\n"
+msgstr "[[!haiku hint=\"argument test\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The hint parameter can be omitted, it only provides the generator a hint of "
+"what to write the haiku about. If no hint is given, it might base it on the "
+"page name. Since the vocabulary it knows is very small, many hints won't "
+"affect the result at all."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/if.da.po b/po/underlays/directives/ikiwiki/directive/if.da.po
new file mode 100644 (file)
index 0000000..9f66ca8
--- /dev/null
@@ -0,0 +1,128 @@
+# Danish translation of if page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `if` directive is supplied by the [[!iki plugins/conditional "
+"desc=conditional]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"With this directive, you can make text be conditionally displayed on a "
+"page.  For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!if test=\"enabled(smiley)\"\n"
+"\t      then=\"The smiley plugin is enabled :-)\"\n"
+"\t      else=\"No smiley plugin here..\"]]\n"
+msgstr ""
+"[[!if test=\"enabled(smiley)\"\n"
+"     then=\"Smiley-udvidelsen er aktiveret :-)\"\n"
+"     else=\"Ingen smiley-udvidelse her...\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If the specified `test` succeeds, the `then` text will be displayed, "
+"otherwise the `else` text will be displayed. The `else` part is optional."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The `then` and `else` values can include any markup that would be allowed in "
+"the wiki page outside the template. Triple-quoting the values even allows "
+"quotes to be included."
+msgstr ""
+"Værdierne `then` og `else` kan indeholde enhver opmærkning som ville være "
+"tilladt på wikisiden udenfor skabelonen. Trippel-citering af værdien "
+"tillader endda at bruge citering som del af værdien."
+
+#. type: Plain text
+msgid ""
+"The `test` is a [[ikiwiki/PageSpec]]; if it matches any page in the wiki "
+"then it succeeds. So you can do things like testing for the existence of a "
+"page or pages, testing to see if any pages were created in a given month, "
+"and so on."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If you want the [[ikiwiki/PageSpec]] to only match against the page that "
+"contains the conditional, rather than matching against all pages in the "
+"wiki, set the \"all\" parameter to \"no\"."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"In an `if` directive, the regular [[ikiwiki/PageSpec]] syntax is expanded "
+"with the following additional tests:"
+msgstr ""
+"I et `if`-direktiv udvides den normale [[ikiwiki/PageSpec]]-syntaks med "
+"følgende yderligere tests:"
+
+#. type: Bullet: '* '
+msgid "enabled(plugin)"
+msgstr "enabled(udvielse)"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Tests whether the specified plugin is enabled.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "sourcepage(glob)"
+msgstr "sourcepage(glob)"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Tests whether the glob matches the name of the page that contains the\n"
+"  conditional.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "destpage(glob)"
+msgstr "destpage(glob)"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Tests whether the glob matches the name of the page that is being built.\n"
+"  That might be different than the name of the page that contains the\n"
+"  conditional, if it's being inlined into another page.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "included()"
+msgstr "included()"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Tests whether the page is being included onto another page.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/img.da.po b/po/underlays/directives/ikiwiki/directive/img.da.po
new file mode 100644 (file)
index 0000000..f6a9509
--- /dev/null
@@ -0,0 +1,98 @@
+# Danish translation of directives/ikiwiki/directive/img page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `img` directive is supplied by the [[!iki plugins/img desc=img]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This is an image handling directive.  While ikiwiki supports inlining full-"
+"size images by making a [[ikiwiki/WikiLink]] that points to the image, using "
+"this directive you can easily scale down an image for inclusion onto a page, "
+"providing a link to a full-size version."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!img image1.jpg size=\"200x200\" alt=\"clouds\"]]\n"
+msgstr "\t\\[[!img image1.jpg size=\"200x200\" alt=\"skyer\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The image file will be searched for using the same rules as used to find the "
+"file pointed to by a [[ikiwiki/WikiLink]]."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The `size` parameter is optional, defaulting to full size. Note that the "
+"original image's aspect ratio is always preserved, even if this means making "
+"the image smaller than the specified size. You can also specify only the "
+"width or the height, and the other value will be calculated based on it: "
+"\"200x\", \"x200\""
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You can also pass `alt`, `title`, `class`, `align` and `id` parameters.  "
+"These are passed through unchanged to the html img tag. If you include a "
+"`caption` parameter, the caption will be displayed centered beneath the "
+"image."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The `link` parameter is used to control whether the scaled down image links "
+"to the full size version. By default it does; set \"link=somepage\" to link "
+"to another page instead, or \"link=no\" to disable the link, or "
+"\"link=http://url\" to link to a given url."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You can also set default values that will be applied to all later images on "
+"the page, unless overridden. Useful when including many images on a page."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!img defaults size=200x200 alt=\"wedding photo\"]]\n"
+"\t\\[[!img photo1.jpg]]\n"
+"\t\\[[!img photo2.jpg]]\n"
+"\t\\[[!img photo3.jpg size=200x600]]\n"
+msgstr ""
+"\t\\[[!img defaults size=200x200 alt=\"bryllupsfoto\"]]\n"
+"\t\\[[!img photo1.jpg]]\n"
+"\t\\[[!img photo2.jpg]]\n"
+"\t\\[[!img photo3.jpg size=200x600]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/inline.da.po b/po/underlays/directives/ikiwiki/directive/inline.da.po
new file mode 100644 (file)
index 0000000..5641508
--- /dev/null
@@ -0,0 +1,285 @@
+# Danish translation of directives/ikiwiki/directive/inline page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `inline` directive is supplied by the [[!iki plugins/inline "
+"desc=inline]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This is a directive that allows including one wiki page inside another.  The "
+"most common use of inlining is generating blogs and RSS or Atom feeds."
+msgstr ""
+
+#. type: Plain text
+msgid "Example:"
+msgstr "Eksempel:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"blog/* and !*/Discussion\" show=\"10\" rootpage=\"blog\"]]\n"
+msgstr "\t\\[[!inline pages=\"blog/* and !*/Discussion\" show=\"10\" rootpage=\"blog\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Any pages that match the specified [[PageSpec]] (in the example, any "
+"[[SubPage]] of \"blog\") will be part of the blog, and the newest 10 of them "
+"will appear in the page. Note that if files that are not pages match the "
+"[[PageSpec]], they will be included in the feed using RSS enclosures, which "
+"is useful for podcasting."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The optional `rootpage` parameter tells the wiki that new posts to this blog "
+"should default to being [[SubPages|SubPage]] of \"blog\", and enables a form "
+"at the top of the blog that can be used to add new items."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If you want your blog to have an archive page listing every post ever made "
+"to it, you can accomplish that like this:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"blog/* and !*/Discussion\" archive=\"yes\"]]\n"
+msgstr "\t\\[[!inline pages=\"blog/* and !*/Discussion\" archive=\"yes\"]]\n"
+
+#. type: Plain text
+msgid ""
+"You can even create an automatically generated list of all the pages on the "
+"wiki, with the most recently added at the top, like this:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"* and !*/Discussion\" archive=\"yes\"]]\n"
+msgstr "\t\\[[!inline pages=\"* and !*/Discussion\" archive=\"yes\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If you want to be able to add pages to a given blog feed by tagging them, "
+"you can do that too. To tag a page, just make it link to a page or pages "
+"that represent its tags. Then use the special `link()` [[PageSpec]] to match "
+"all pages that have a given tag:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"link(life)\"]]\n"
+msgstr "\t\\[[!inline pages=\"link(livet)\"]]\n"
+
+#. type: Plain text
+msgid "Or include some tags and exclude others:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!inline pages=\"link(debian) and !link(social)\"]]\n"
+msgstr "\t\\[[!inline pages=\"link(debian) and !link(venner)\"]]\n"
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+msgid ""
+"There are many parameters you can use with the `inline` directive. These are "
+"the commonly used ones:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`pages` - A [[PageSpec]] of the pages to inline."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`show` - Specify the maximum number of matching pages to inline.  Default is "
+"10, unless archiving, when the default is to show all.  Set to 0 to show all "
+"matching pages."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`archive` - If set to \"yes\", only list page titles and some metadata, not "
+"full contents."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`description` - Sets the description of the rss feed if one is generated.  "
+"Defaults to the name of the wiki."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`skip` - Specify a number of pages to skip displaying. Can be useful to "
+"produce a feed that only shows archived pages."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`postform` - Set to \"yes\" to enable a form to post new pages to a blog."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`postformtext` - Set to specify text that is displayed in a postform."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`rootpage` - Enable the postform, and allows controling where newly posted "
+"pages should go, by specifiying the page that they should be a [[SubPage]] "
+"of."
+msgstr ""
+
+#. type: Plain text
+msgid "Here are some less often needed parameters:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`actions` - If set to \"yes\" add links to the bottom of the inlined pages "
+"for editing and discussion (if they would be shown at the top of the page "
+"itself)."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`rss` - controls generation of an rss feed. If the wiki is configured to "
+"generate rss feeds by default, set to \"no\" to disable. If the wiki is "
+"configured to `allowrss`, set to \"yes\" to enable."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`atom` - controls generation of an atom feed. If the wiki is configured to "
+"generate atom feeds by default, set to \"no\" to disable. If the wiki is "
+"configured to `allowatom`, set to \"yes\" to enable."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feeds` - controls generation of all types of feeds. Set to \"no\" to "
+"disable generating any feeds."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`emptyfeeds` - Set to \"no\" to disable generation of empty feeds.  Has no "
+"effect if `rootpage` or `postform` is set."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`template` - Specifies the template to fill out to display each inlined "
+"page. By default the `inlinepage` template is used, while the `archivepage` "
+"template is used for archives. Set this parameter to use some other, custom "
+"template, such as the `titlepage` template that only shows post titles or "
+"the `microblog` template, optimised for microblogging. Note that you should "
+"still set `archive=yes` if your custom template does not include the page "
+"content."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`raw` - Rather than the default behavior of creating a blog, if raw is set "
+"to \"yes\", the page will be included raw, without additional markup around "
+"it, as if it were a literal part of the source of the inlining page."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`sort` - Controls how inlined pages are sorted. The default, \"age\" is to "
+"sort newest created pages first. Setting it to \"title\" will sort pages by "
+"title, and \"mtime\" sorts most recently modified pages first. If [[!cpan "
+"Sort::Naturally]] is installed, `sort` can be set to \"title_natural\" to "
+"sort by title with numbers treated as such (\"1 2 9 10 20\" instead of \"1 "
+"10 2 20 9\")."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`reverse` - If set to \"yes\", causes the sort order to be reversed."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feedshow` - Specify the maximum number of matching pages to include in the "
+"rss/atom feeds. The default is the same as the `show` value above."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feedonly` - Only generate the feed, do not display the pages inline on the "
+"page."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`quick` - Build archives in quick mode, without reading page contents for "
+"metadata. By default, this also turns off generation of any feeds."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`timeformat` - Use this to specify how to display the time or date for pages "
+"in the blog. The format string is passed to the strftime(3) function."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feedpages` - A [[PageSpec]] of inlined pages to include in the rss/atom "
+"feeds. The default is the same as the `pages` value above, and only pages "
+"matched by that value are included, but some of those can be excluded by "
+"specifying a tighter [[PageSpec]] here."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`guid` - If a URI is given here (perhaps a UUID prefixed with `urn:uuid:`), "
+"the Atom feed will have this as its `<id>`. The default is to use the URL of "
+"the page containing the `inline` directive."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`feedfile` - Can be used to change the name of the file generated for the "
+"feed. This is particularly useful if a page contains multiple feeds.  For "
+"example, set \"feedfile=feed\" to cause it to generate `page/feed.atom` and/"
+"or `page/feed.rss`. This option is not supported if the wiki is configured "
+"not to use `usedirs`."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
+
+#. type: Plain text
+msgid ""
+"A related directive is the [[ikiwiki/directive/edittemplate]] directive, "
+"which allows default text for a new page to be specified."
+msgstr ""
diff --git a/po/underlays/directives/ikiwiki/directive/linkmap.da.po b/po/underlays/directives/ikiwiki/directive/linkmap.da.po
new file mode 100644 (file)
index 0000000..4c6b024
--- /dev/null
@@ -0,0 +1,70 @@
+# Danish translation of directives/ikiwiki/directive/linkmap page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `linkmap` directive is supplied by the [[!iki plugins/linkmap "
+"desc=linkmap]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive uses [graphviz](http://www.graphviz.org/) to generate a graph "
+"showing the links between a set of pages in the wiki. Example usage:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!linkmap pages=\"* and !blog/* and !*/Discussion\"]]\n"
+msgstr "\t\\[[!linkmap pages=\"* and !blog/* and !*/Discussion\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Only links between mapped pages will be shown; links pointing to or from "
+"unmapped pages will be omitted. If the pages to include are not specified, "
+"the links between all pages (and other files) in the wiki are mapped. For "
+"best results, only a small set of pages should be mapped, since otherwise "
+"the map can become very large, unwieldy, and complicated. Also, the map is "
+"rebuilt whenever one of the mapped pages is changed, which can make the wiki "
+"a bit slow."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Here are descriptions of all the supported parameters to the `linkmap` "
+"directive:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`pages` - A [[ikiwiki/PageSpec]] of the pages to map."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`height`, `width` - Limit the size of the map to a given height and width, "
+"in inches. Both must be specified for the limiting to take effect, otherwise "
+"the map's size is not limited."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/listdirectives.da.po b/po/underlays/directives/ikiwiki/directive/listdirectives.da.po
new file mode 100644 (file)
index 0000000..c0f08b4
--- /dev/null
@@ -0,0 +1,63 @@
+# Danish translation of directives/ikiwiki/directive/listdirectives page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `listdirectives` directive is supplied by the [[!iki plugins/"
+"listdirectives desc=listdirectives]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive generates a list of available [[directives|ikiwiki/"
+"directive]]."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!listdirectives]]\n"
+msgstr "\t\\[[!listdirectives]]\n"
+
+#. type: Plain text
+msgid ""
+"There is one optional keyword argument, `generated`.  Normally the "
+"`listdirectives` directive will list all built in directives and directives "
+"directly registered by plugins.  With this keyword, `listdirectives` will "
+"also list directives generated later.  For example, all [[shortcuts]] are "
+"directives generated in turn by the `shortcut` directive.  They will only be "
+"listed if the `generated` argument is supplied."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "    \\[[!listdirectives generated]]\n"
+msgstr "    \\[[!listdirectives generated]]\n"
+
+#. type: Plain text
+msgid ""
+"This extended list is often quite long, and often contains many undocumented "
+"directives."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/map.da.po b/po/underlays/directives/ikiwiki/directive/map.da.po
new file mode 100644 (file)
index 0000000..00caaeb
--- /dev/null
@@ -0,0 +1,64 @@
+# Danish translation of directives/ikiwiki/directive/map page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `map` directive is supplied by the [[!iki plugins/map desc=map]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive generates a hierarchical page map for the wiki. Example usage:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!map pages=\"* and !blog/* and !*/Discussion\"]]\n"
+msgstr "\t\\[[!map pages=\"* and !blog/* and !*/Discussion\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If the pages to include are not specified, all pages (and other files) in "
+"the wiki are mapped."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"By default, the names of pages are shown in the map. The `show` parameter "
+"can be used to show the titles or descriptions of pages instead (as set by "
+"the [[meta]] directive). For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!map pages=\"* and !blog/* and !*/Discussion\" show=title]]\n"
+msgstr "\t\\[[!map pages=\"* and !blog/* and !*/Discussion\" show=title]]\n"
+
+#. type: Plain text
+msgid ""
+"Hint: To limit the map to displaying pages less than a certain level deep, "
+"use a [[ikiwiki/PageSpec]] like this: `pages=\"* and !*/*/*\"`"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/meta.da.po b/po/underlays/directives/ikiwiki/directive/meta.da.po
new file mode 100644 (file)
index 0000000..08fdc9c
--- /dev/null
@@ -0,0 +1,363 @@
+# Danish translation of directives/ikiwiki/directive/meta page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `meta` directive is supplied by the [[!iki plugins/meta desc=meta]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows inserting arbitrary metadata into the source of a "
+"page.  Enter the metadata as follows:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!meta field=\"value\"]]\n"
+"\t\\[[!meta field=\"value\" param=\"value\" param=\"value\"]]\n"
+msgstr ""
+"\t\\[[!meta felt=\"værdi\"]]\n"
+"\t\\[[!meta felt=\"værdi\" param=\"værdi\" param=\"værdi\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The first form sets a given field to a given value, while the second form "
+"also specifies some additional sub-parameters."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The field values are treated as HTML entity-escaped text, so you can include "
+"a quote in the text by writing `&quot;` and so on."
+msgstr ""
+
+#. type: Plain text
+msgid "Supported fields:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "title"
+msgstr "title"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Overrides the title of the page, which is generally the same as the\n"
+"  page name.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Note that if the title is overridden, a \"title_overridden\" variable will\n"
+"  be set to a true value in the template; this can be used to format things\n"
+"  differently in this case.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "license"
+msgstr "license"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a license for the page, for example, \"GPL\". Can contain\n"
+"  WikiLinks and arbitrary markup.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "copyright"
+msgstr "copyright"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies the copyright of the page, for example, \"Copyright 2007 by\n"
+"  Joey Hess\". Can contain WikiLinks and arbitrary markup.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "author"
+msgstr "author"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Specifies the author of a page.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "authorurl"
+msgstr "authorurl"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Specifies an url for the author of a page.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "description"
+msgstr "description"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a \"description\" of the page. You could use this to provide\n"
+"  a summary, for example, to be picked up by the [[map]] directive.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "permalink"
+msgstr "permalink"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a permanent link to the page, if different than the page\n"
+"  generated by ikiwiki.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "date"
+msgstr "date"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies the creation date of the page. The date can be entered in\n"
+"  nearly any format, since it's parsed by [[!cpan TimeDate]].\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "stylesheet"
+msgstr "stylesheet"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Adds a stylesheet to a page. The stylesheet is treated as a wiki link to\n"
+"  a `.css` file in the wiki, so it cannot be used to add links to external\n"
+"  stylesheets. Example:\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!meta stylesheet=somestyle rel=\"alternate stylesheet\"\n"
+"\ttitle=\"somestyle\"]]\n"
+msgstr ""
+"\t\\[[!meta stylesheet=somestyle rel=\"alternate stylesheet\"\n"
+"\ttitle=\"etstilark\"]]\n"
+
+#. type: Bullet: '* '
+msgid "openid"
+msgstr "openid"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Adds html &lt;link&gt; tags to perform OpenID delegation to an external\n"
+"  OpenID server. This lets you use an ikiwiki page as your OpenID.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  By default this will delegate for both `openid` and `openid2`. To only\n"
+"  delegate for one, add a parameter such as `delegate=openid`.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  An optional `xrds-location`\n"
+"  parameter lets you specify the location of any [eXtensible Resource\n"
+"  DescriptorS](http://www.windley.com/archives/2007/05/using_xrds.shtml).\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "  Example:\n"
+msgstr "  Eksempel:\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\\\[[!meta openid=\"http://joeyh.myopenid.com/\"\n"
+"\tserver=\"http://www.myopenid.com/server\"\n"
+"\txrds-location=\"http://www.myopenid.com/xrds?username=joeyh.myopenid.com\"\"]]\n"
+msgstr ""
+"\t\\\\[[!meta openid=\"http://joeyh.myopenid.com/\"\n"
+"\tserver=\"http://www.myopenid.com/server\"\n"
+"\txrds-location=\"http://www.myopenid.com/xrds?username=joeyh.myopenid.com\"\"]]\n"
+
+#. type: Bullet: '* '
+msgid "link"
+msgstr "link"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a link to another page. This can be used as a way to make the\n"
+"  wiki treat one page as linking to another without displaying a user-visible\n"
+"  [[ikiwiki/WikiLink]]:\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "       \\[[!meta link=otherpage]]\n"
+msgstr "       \\[[!meta link=enandenside]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "  It can also be used to insert a html &lt;link&gt; tag. For example:\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "       \\[[!meta link=\"http://joeyh.myopenid.com/\" rel=\"openid.delegate\"]]\n"
+msgstr "       \\[[!meta link=\"http://joeyh.myopenid.com/\" rel=\"openid.delegate\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  However, this latter syntax won't be allowed if the \n"
+"  [[!iki plugins/htmlscrubber desc=htmlscrubber]] plugin is enabled, since it can be used to\n"
+"  insert unsafe content.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "redir"
+msgstr "redir"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Causes the page to redirect to another page in the wiki.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "  \t\\[[!meta redir=otherpage]]\n"
+msgstr "  \t\\[[!meta redir=otherpage]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Optionally, a delay (in seconds) can be specified. The default is to\n"
+"  redirect without delay.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "  It can also be used to redirect to an external url. For example:\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "  \t\\[[!meta redir=\"http://example.com/\"]]\n"
+msgstr "  \t\\[[!meta redir=\"http://eksempel.dk/\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  For both cases, an anchor to jump to inside the destination page may also be\n"
+"  specified using the common `#ANCHOR` syntax.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "robots"
+msgstr "robots"
+
+#. type: Plain text
+#, no-wrap
+msgid "  Causes the robots meta tag to be written:\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "        \\[[!meta robots=\"index, nofollow\"]]\n"
+msgstr "        \\[[!meta robots=\"index, nofollow\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Valid values for the attribute are: \"index\", \"noindex\", \"follow\", and\n"
+"  \"nofollow\". Multiple comma-separated values are allowed, but obviously only\n"
+"  some combinations make sense. If there is no robots meta tag, \"index,\n"
+"  follow\" is used as the default.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "  The value is escaped, but its contents are not otherwise checked.\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "guid"
+msgstr "guid"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a globally unique ID for a page. This guid should be a URI\n"
+"  (in particular, it can be `urn:uuid:` followed by a UUID, as per\n"
+"  [[!rfc 4122]]), and it will be used to identify the page's entry in RSS\n"
+"  and Atom feeds. If not given, the default is to use the page's URL as its\n"
+"  guid.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  This is mostly useful when a page has moved, to keep the guids for\n"
+"  pages unchanged and avoid_flooding_aggregators\n"
+"  (see [[!iki tips/howto_avoid_flooding_aggregators]]).\n"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "updated"
+msgstr "updated"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Specifies a fake modification time for a page, to be output into RSS and\n"
+"  Atom feeds. This is useful to avoid flooding aggregators that sort by\n"
+"  modification time, like Planet: for instance, when editing an old blog post\n"
+"  to add tags, you could set `updated` to be one second later than the original\n"
+"  value. The date/time can be given in any format that\n"
+"  [[!cpan TimeDate]] can understand, just like the `date` field.\n"
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If the field is not one of the above predefined fields, the metadata will be "
+"written to the generated html page as a &lt;meta&gt; header. However, this "
+"won't be allowed if the [[!iki plugins/htmlscrubber desc=htmlscrubber]] "
+"plugin is enabled, since it can be used to insert unsafe content."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/more.da.po b/po/underlays/directives/ikiwiki/directive/more.da.po
new file mode 100644 (file)
index 0000000..a7855d6
--- /dev/null
@@ -0,0 +1,59 @@
+# Danish translation of directives/ikiwiki/directive/more page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `more` directive is supplied by the [[!iki plugins/more desc=more]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive provides a way to have a \"more\" link on a post in a blog, "
+"that leads to the full version of the page. Use it like this:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!more linktext=\"click for more\" text=\"\"\"\n"
+msgstr "\t\\[[!more linktext=\"klik for mere\" text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tThis is the rest of my post. Not intended for people catching up on\n"
+"\ttheir blogs at 30,000 feet. Because I like to make things\n"
+"\tdifficult.\n"
+msgstr ""
+
+#. type: Plain text
+msgid "If the `linktext` parameter is omitted it defaults to just \"more\"."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Note that you can accomplish something similar using a [[toggle]] instead."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/orphans.da.po b/po/underlays/directives/ikiwiki/directive/orphans.da.po
new file mode 100644 (file)
index 0000000..3e71434
--- /dev/null
@@ -0,0 +1,55 @@
+# Danish translation of directives/ikiwiki/directive/orphans page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `orphans` directive is supplied by the [[!iki plugins/orphans "
+"desc=orphans]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive generates a list of possibly orphaned pages -- pages that no "
+"other page links to. Example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!orphans pages=\"* and !blog/*\"]]\n"
+msgstr "\t\\[[!orphans pages=\"* and !blog/*\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The optional parameter \"pages\" can be a [[ikiwiki/PageSpec]] specifying "
+"the pages to check for orphans, default is search them all."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Note that it takes backlinks into account, but does not count inlining a "
+"page as linking to it, so will generally count many blog-type pages as "
+"orphans."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/pagecount.da.po b/po/underlays/directives/ikiwiki/directive/pagecount.da.po
new file mode 100644 (file)
index 0000000..c404a77
--- /dev/null
@@ -0,0 +1,46 @@
+# Danish translation of directives/ikiwiki/directive/pagecount page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `pagecount` directive is supplied by the [[!iki plugins/pagecount "
+"desc=pagecount]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "This directive counts pages currently in the wiki. Example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!pagecount pages=\"*\"]]\n"
+msgstr "\t\\[[!pagecount pages=\"*\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The optional parameter \"pages\" can be a [[ikiwiki/PageSpec]] specifying "
+"the pages to count, default is to count them all."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/pagestats.da.po b/po/underlays/directives/ikiwiki/directive/pagestats.da.po
new file mode 100644 (file)
index 0000000..76474b2
--- /dev/null
@@ -0,0 +1,56 @@
+# Danish translation of directives/ikiwiki/directive/pagestats page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `pagestats` directive is supplied by the [[!iki plugins/pagestats "
+"desc=pagestats]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive can generate stats about how pages link to each other. It can "
+"produce either a tag cloud, or a table counting the number of links to each "
+"page."
+msgstr ""
+
+#. type: Plain text
+msgid "Here's how to use it to create a [[tag]] cloud:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!pagestats pages=\"tags/*\"]]\n"
+msgstr "\t\\[[!pagestats pages=\"tags/*\"]]\n"
+
+#. type: Plain text
+msgid "And here's how to create a table of all the pages on the wiki:"
+msgstr "Og sådan her dannes en tabel over alle sider i wikien:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!pagestats style=\"table\"]]\n"
+msgstr "\t\\[[!pagestats style=\"table\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/pagetemplate.da.po b/po/underlays/directives/ikiwiki/directive/pagetemplate.da.po
new file mode 100644 (file)
index 0000000..0db0835
--- /dev/null
@@ -0,0 +1,52 @@
+# Danish translation of directives/ikiwiki/directive/pagetemplate page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `pagetemplate` directive is supplied by the [[!iki plugins/pagetemplate "
+"desc=pagetemplate]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows a page to be created using a different wikitemplates.  "
+"The page text is inserted into the template, so the template controls the "
+"overall look and feel of the wiki page. This is in contrast to the [[ikiwiki/"
+"directive/template]] directive, which allows inserting templates _into_ the "
+"body of a page."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive can only reference templates that are already installed by "
+"the system administrator, typically into the `/usr/share/ikiwiki/templates` "
+"directory. Example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!pagetemplate template=\"my_fancy.tmpl\"]]\n"
+msgstr "\t\\[[!pagetemplate template=\"min_smarte.tmpl\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/paste.da.po b/po/underlays/directives/ikiwiki/directive/paste.da.po
new file mode 100644 (file)
index 0000000..6a3f147
--- /dev/null
@@ -0,0 +1,30 @@
+# Danish translation of directives/ikiwiki/directive/paste page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+msgstr "[[!meta redir=/ikiwiki/directive/cutpaste]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/ping.da.po b/po/underlays/directives/ikiwiki/directive/ping.da.po
new file mode 100644 (file)
index 0000000..991b1f6
--- /dev/null
@@ -0,0 +1,61 @@
+# Danish translation of directives/ikiwiki/directive/ping page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `ping` directive is supplied by the [[!iki plugins/pinger desc=pinger]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows ikiwiki to be configured to hit a URL each time it "
+"updates the wiki. One way to use this is in conjunction with the [[!iki "
+"plugins/pingee desc=pingee]] plugin to set up a loosely coupled mirror "
+"network, or a branched version of a wiki. By pinging the mirror or branch "
+"each time the main wiki changes, it can be kept up-to-date."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"        \\[[!ping from=\"http://mywiki.com/\"\n"
+"        to=\"http://otherwiki.com/ikiwiki.cgi?do=ping\"]]\n"
+msgstr ""
+"        \\[[!ping from=\"http://mywiki.com/\"\n"
+"        to=\"http://otherwiki.com/ikiwiki.cgi?do=ping\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The \"from\" parameter must be identical to the url of the wiki that is "
+"doing the pinging. This is used to prevent ping loops."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The \"to\" parameter is the url to ping. The example shows how to ping "
+"another ikiwiki instance."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/poll.da.po b/po/underlays/directives/ikiwiki/directive/poll.da.po
new file mode 100644 (file)
index 0000000..6838749
--- /dev/null
@@ -0,0 +1,76 @@
+# Danish translation of directives/ikiwiki/directive/poll page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `poll` directive is supplied by the [[!iki plugins/poll desc=poll]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows you to create online polls in the wiki. Here's an "
+"example use:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!poll 0 \"red\" 0 \"green\" 0 \"blue\"]]\n"
+msgstr "\t\\[[!poll 0 \"rød\" 0 \"grøn\" 0 \"blå\"]]\n"
+
+#. type: Plain text
+msgid ""
+"The numbers indicate how many users voted for that choice. When a user votes "
+"for a choice in the poll, the page is modified and the number incremented."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"While some basic precautions are taken to prevent users from accidentially "
+"voting twice, this sort of poll should not be counted on to be very "
+"accurate; all the usual concerns about web based polling apply. Unless the "
+"page that the poll is in is locked, users can even edit the page and change "
+"the numbers!"
+msgstr ""
+
+#. type: Plain text
+msgid "Parameters:"
+msgstr "Parametre:"
+
+#. type: Bullet: '* '
+msgid ""
+"`open` - Whether voting is still open. Set to \"no\" to close the poll to "
+"voting."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`total` - Show total number of votes at bottom of poll. Default is \"yes\"."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`percent` - Whether to display percents. Default is \"yes\"."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/polygen.da.po b/po/underlays/directives/ikiwiki/directive/polygen.da.po
new file mode 100644 (file)
index 0000000..81c2a4c
--- /dev/null
@@ -0,0 +1,48 @@
+# Danish translation of directives/ikiwiki/directive/polygen page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `polygen` directive is supplied by the [[!iki plugins/polygen "
+"desc=polygen]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows inserting text generated by polygen into a wiki page.  "
+"For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!polygen grammar=\"genius\"]]\n"
+msgstr "\t\\[[!polygen grammar=\"genius\"]]\n"
+
+#. type: Plain text
+msgid ""
+"It's also possible to specify a starting nonterminal for the grammar by "
+"including `symbol=\"text\"` in the directive."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/postsparkline.da.po b/po/underlays/directives/ikiwiki/directive/postsparkline.da.po
new file mode 100644 (file)
index 0000000..4725964
--- /dev/null
@@ -0,0 +1,127 @@
+# Danish translation of directives/ikiwiki/directive/postsparkline page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `postsparkline` directive is supplied by the [[!iki plugins/"
+"postsparkline desc=postsparkline]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive uses the [[!iki plugins/sparkline desc=sparkline]] plugin to "
+"create a [[sparkline]] of statistics about a set of pages, such as posts to "
+"a blog."
+msgstr ""
+
+#. type: Title #
+#, no-wrap
+msgid "examples"
+msgstr "eksempler"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tPost interval: \n"
+"\t\\[[!postsparkline pages=\"blog/* and !*/Discussion\" max=100\n"
+"\tformula=interval style=bar barwidth=2 barspacing=1 height=13]]\n"
+msgstr ""
+"\tBidragsinterval: \n"
+"\t\\[[!postsparkline pages=\"blog/* and !*/Discussion\" max=100\n"
+"\tformula=interval style=bar barwidth=2 barspacing=1 height=13]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tPosts per month this year: \n"
+"\t\\[[!postsparkline pages=\"blog/* and !*/Discussion\" max=12\n"
+"\tformula=permonth style=bar barwidth=2 barspacing=1 height=13]]\n"
+msgstr ""
+"\tBidrag per måned dette år: \n"
+"\t\\[[!postsparkline pages=\"blog/* and !*/Discussion\" max=12\n"
+"\tformula=permonth style=bar barwidth=2 barspacing=1 height=13]]\n"
+
+#. type: Title #
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+msgid ""
+"All options aside fron the `pages`, `max`, `formula`, `time`, and `color` "
+"options are the same as in [[sparkline]] directive."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"You don't need to specify any data points (though you can if you want to).  "
+"Instead, data points are automatically generated based on the creation times "
+"of pages matched by the specified `pages` [[ikiwiki/PageSpec]]. A maximum of "
+"`max` data points will be generated."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The `formula` parameter controls the formula used to generate data points.  "
+"Available forumlae:"
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`interval` - The height of each point represents how long it has been since "
+"the previous post."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`perday` - Each point represents a day; the height represents how many posts "
+"were made that day."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`permonth` - Each point represents a month; the height represents how many "
+"posts were made that month."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`peryear` - Each point represents a day; the height represents how many "
+"posts were made that year."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The `time` parameter has a default value of \"ctime\", since forumae use the "
+"creation times of pages by default. If you instead want them to use the "
+"modification times of pages, set it to \"mtime\"."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"To change the color used to draw the sparkline, use the `color` parameter.  "
+"For example, \"color=red\"."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/progress.da.po b/po/underlays/directives/ikiwiki/directive/progress.da.po
new file mode 100644 (file)
index 0000000..9ef1a74
--- /dev/null
@@ -0,0 +1,58 @@
+# Danish translation of directives/ikiwiki/directive/progress page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `progress` directive is supplied by the [[!iki plugins/progress "
+"desc=progress]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "This directive generates a progress bar."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"There are two possible parameter sets.  The first is a single parameter "
+"\"percent\" which holds a percentage figure of how complete the progress bar "
+"is."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The second possible set of parameters is a pair of [[ikiwiki/PageSpec]]s, "
+"`totalpages` and `donepages`. The directive counts the number of pages in "
+"each pagespec and shows the percentage of the total pages that are done."
+msgstr ""
+
+#. type: Plain text
+msgid "For example, to show what percentage of pages have discussion pages:"
+msgstr "Eksempelvis at vise procentdel af sider med diskussionssider:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!progress totalpages=\"* and !*/Discussion\" donepages=\"*/Discussion\"]]\n"
+msgstr "\t\\[[!progress totalpages=\"* and !*/Discussion\" donepages=\"*/Discussion\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/shortcut.da.po b/po/underlays/directives/ikiwiki/directive/shortcut.da.po
new file mode 100644 (file)
index 0000000..2a45de0
--- /dev/null
@@ -0,0 +1,43 @@
+# Danish translation of directives/ikiwiki/directive/shortcut page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-19 23:45+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `shortcut` directive is supplied by the [[!iki plugins/shortcut "
+"desc=shortcut]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows external links to commonly linked to sites to be made "
+"more easily using shortcuts."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The available shortcuts are defined on the [[shortcuts]] page in the wiki. "
+"The `shortcut` directive can only be used on that page."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/sparkline.da.po b/po/underlays/directives/ikiwiki/directive/sparkline.da.po
new file mode 100644 (file)
index 0000000..655b174
--- /dev/null
@@ -0,0 +1,144 @@
+# Danish translation of directives/ikiwiki/directive/sparkline page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `sparkline` directive is supplied by the [[!iki plugins/sparkline "
+"desc=sparkline]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows for embedding sparklines into wiki pages. A sparkline "
+"is a small word-size graphic chart, that is designed to be displayes "
+"alongside text."
+msgstr ""
+
+#. type: Title #
+#, no-wrap
+msgid "examples"
+msgstr "eksempler"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!sparkline 1 3 5 -3 10 0 width=40 height=16\n"
+"\tfeaturepoint=\"4,-3,red,3\" featurepoint=\"5,10,green,3\"]]\n"
+msgstr ""
+"\t\\[[!sparkline 1 3 5 -3 10 0 width=40 height=16\n"
+"\tfeaturepoint=\"4,-3,red,3\" featurepoint=\"5,10,green,3\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This creates a simple line graph, graphing several points.  It will be drawn "
+"40 pixels wide and 16 pixels high. The high point in the line has a green "
+"marker, and the low point has a red marker."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!sparkline 1 -1(red) 1 -1(red) 1 1 1 -1(red) -1(red) style=bar barwidth=2\n"
+"\tbarspacing=1 height=13]]\n"
+msgstr ""
+"\t\\[[!sparkline 1 -1(red) 1 -1(red) 1 1 1 -1(red) -1(red) style=bar barwidth=2\n"
+"\tbarspacing=1 height=13]]\n"
+
+#. type: Plain text
+msgid ""
+"This more complex example generates a bar graph.  The bars are 2 pixels "
+"wide, and separated by one pixel, and the graph is 13 pixels tall. Width is "
+"determined automatically for bar graphs. The points with negative values are "
+"colored red, instead of the default black."
+msgstr ""
+
+#. type: Title #
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Plain text
+msgid ""
+"The form for the data points is \"x,y\", or just \"y\" if the x values don't "
+"matter. Bar graphs can also add \"(color)\" to specify a color for that bar."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The following named parameters are recognised. Most of these are the same as "
+"those used by the underlying sparkline library, which is documented in more "
+"detail in [its wiki](http://sparkline.wikispaces.com/usage)."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`style` - Either \"line\" (the default) or \"bar\"."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`width` - Width of the graph in pixels. Only needed for line graphs."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`height` - Height of the graph in pixels. Defaults to 16."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`barwidth` - Width of bars in a bar graph. Default is 1 pixel."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`barspacing` - Spacing between bars in a bar graph, in pixels. Default is 1 "
+"pixel."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`ymin`, `ymax` - Minimum and maximum values for the Y axis. This is normally "
+"calculated automatically, but can be explicitly specified to get the same "
+"values for multiple related graphs."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`featurepoint` - Adds a circular marker to a line graph, with optional text. "
+"This can be used to label significant points."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  The value is a comma-delimited list of parameters specifying the feature\n"
+"  point: X value, Y value, color name, circle diameter, text (optional),\n"
+"  and text location (optional). Example: `featurepoint=\"3,5,blue,3\"`\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"  Available values for the text location are: \"top\", \"right\", \"bottom\", and\n"
+"  \"left\".\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/table.da.po b/po/underlays/directives/ikiwiki/directive/table.da.po
new file mode 100644 (file)
index 0000000..174ce11
--- /dev/null
@@ -0,0 +1,121 @@
+# Danish translation of directives/ikiwiki/directive/table page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `table` directive is supplied by the [[!iki plugins/table desc=table]] "
+"plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive can build HTML tables from data in CSV (comma-separated "
+"values)  or DSV (delimiter-separated values) format."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "examples"
+msgstr "eksempler"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!table data=\"\"\"\n"
+msgstr "\t\\[[!table data=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tCustomer|Amount\n"
+"\tFulanito|134,34\n"
+"\tMenganito|234,56\n"
+"\tMenganito|234,56\n"
+msgstr ""
+"\tKunde|Mængde\n"
+"\tFulanito|134,34\n"
+"\tMenganito|234,56\n"
+"\tMenganito|234,56\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!table class=\"book_record\" format=csv file=\"data/books/record1\"]]\n"
+msgstr "\t\\[[!table class=\"book_record\" format=csv file=\"data/books/record1\"]]\n"
+
+#. type: Plain text
+msgid "In this second example the `record1` page should be similar to:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\"Title\",\"Perl Best Practices\"\n"
+"\t\"Author\",\"Damian Conway\"\n"
+"\t\"Publisher\",\"O’Reilly\"\n"
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"To make a cell span multiple columns, follow it with one or more empty "
+"cells. For example:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tleft||right|\n"
+"\ta|b|c|d\n"
+"\tthis cell spans 4 columns|||\n"
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "usage"
+msgstr "brug"
+
+#. type: Bullet: '* '
+msgid "`data` - Values for the table."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid "`file` - A file in the wiki containing the data."
+msgstr ""
+
+#. type: Bullet: '* '
+msgid ""
+"`format` - The format of the data, either \"csv\", \"dsv\", or \"auto\" (the "
+"default)."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"* `delimiter` - The character used to separate fields. By default,\n"
+"   DSV format uses a pipe (`|`), and CSV uses a comma (`,`).\n"
+"* `class` - A CSS class for the table html element.\n"
+"* `header` - By default, or if set to \"row\", the first data line is used\n"
+"  as the table header. Set it to \"no\" to make a table without a header, or\n"
+"  \"column\" to make the first column be the header.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/tag.da.po b/po/underlays/directives/ikiwiki/directive/tag.da.po
new file mode 100644 (file)
index 0000000..1bff796
--- /dev/null
@@ -0,0 +1,94 @@
+# Danish translation of directives/ikiwiki/directive/tag page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `tag` and `taglink` directives are supplied by the [[!iki plugins/tag "
+"desc=tag]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "These directives allow tagging pages. List tags as follows:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!tag tech life linux]]\n"
+msgstr "\t\\[[!tag teknik livet linux]]\n"
+
+#. type: Plain text
+msgid ""
+"The tags work the same as if you had put a (hidden) [[ikiwiki/WikiLink]] on "
+"the page for each tag, so you can use a [[ikiwiki/PageSpec]] match all pages "
+"that are tagged with a given tag, for example. The tags will also show up on "
+"blog entries and at the bottom of the tagged pages, as well as in RSS and "
+"Atom feeds."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If you want a visible [[ikiwiki/WikiLink]] along with the tag, use taglink "
+"instead:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!taglink foo]]\n"
+"\t\\[[!taglink tagged_as_foo|foo]]\n"
+msgstr ""
+"\t\\[[!taglink foo]]\n"
+"\t\\[[!taglink mærket_af_som_foo|foo]]\n"
+
+#. type: Plain text
+msgid ""
+"Note that if the wiki is configured to use a tagbase, then the tags will be "
+"located under a base directory, such as \"tags/\". This is a useful way to "
+"avoid having to write the full path to tags, if you want to keep them "
+"grouped together out of the way."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Bear in mind that specifying a tagbase means you will need to incorporate it "
+"into the `link()` [[ikiwiki/PageSpec]] you use: e.g., if your tagbase is "
+"`tag`, you would match pages tagged \"foo\" with `link(tag/foo)`."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If you want to override the tagbase for a particular tag, you can use "
+"something like this:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!tag ./foo]]\n"
+"\t\\[[!taglink /foo]]\n"
+msgstr ""
+"\t\\[[!tag ./foo]]\n"
+"\t\\[[!taglink /foo]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/taglink.da.po b/po/underlays/directives/ikiwiki/directive/taglink.da.po
new file mode 100644 (file)
index 0000000..1bed76a
--- /dev/null
@@ -0,0 +1,30 @@
+# Danish translation of directives/ikiwiki/directive/tagline page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=/ikiwiki/directive/tag]]\n"
+msgstr "[[!meta redir=/ikiwiki/directive/tag]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/template.da.po b/po/underlays/directives/ikiwiki/directive/template.da.po
new file mode 100644 (file)
index 0000000..92e3177
--- /dev/null
@@ -0,0 +1,62 @@
+# Danish translation of directives/ikiwiki/directive/template page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `template` directive is supplied by the [[!iki plugins/template "
+"desc=template]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"[[Templates]] are files that can be filled out and inserted into pages in "
+"the wiki, by using the template directive. The directive has an `id` "
+"parameter that identifies the template to use. The remaining parameters are "
+"used to fill out the template."
+msgstr ""
+
+#. type: Plain text
+msgid "Example:"
+msgstr "Eksempel:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!template id=note text=\"\"\"Here is the text to insert into my note.\"\"\"]]\n"
+msgstr "\t\\[[!template id=note text=\"\"\"Her er teksten til at sætte ind i min note.\"\"\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This fills out the `note` template, filling in the `text` field with the "
+"specified value, and inserts the result into the page."
+msgstr ""
+"Dette udfylder `note`-skabelonen, med `text`-feltet udfyldt med den angivne "
+"værdi, og indsætter resultatet på siden."
+
+#. type: Plain text
+msgid ""
+"For a list of available templates, and details about how to create more, see "
+"the [[templates]] page."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/testpagespec.da.po b/po/underlays/directives/ikiwiki/directive/testpagespec.da.po
new file mode 100644 (file)
index 0000000..f7ea475
--- /dev/null
@@ -0,0 +1,75 @@
+# Danish translation of directives/ikiwiki/directive/testpagespec page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `testpagespec` directive is supplied by the [[!iki plugins/testpagespec "
+"desc=testpagespec]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"This directive allows testing a [[ikiwiki/PageSpec]] to see if it matches a "
+"page, and to see the part that matches, or causes the match to fail."
+msgstr ""
+
+#. type: Plain text
+msgid "Example uses:"
+msgstr "Eksempelbrug:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!testpagespec pagespec=\"foopage and barpage\" match=\"foopage\"]]\n"
+msgstr "\t\\[[!testpagespec pagespec=\"foopage and barpage\" match=\"foopage\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This will print out something like \"no match: barpage does not match foopage"
+"\", highlighting which part of the [[ikiwiki/PageSpec]] is causing the match "
+"to fail."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!testpagespec pagespec=\"foopage or !bar*\" match=\"barpage\"]]\n"
+msgstr "\t\\[[!testpagespec pagespec=\"foopage or !bar*\" match=\"barpage\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This will print out something like \"no match: bar* matches barpage\", since "
+"the part of the [[ikiwiki/PageSpec]] that fails is this negated match."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!testpagespec pagespec=\"foopage or barpage\" match=\"barpage\"]]\n"
+msgstr "\t\\[[!testpagespec pagespec=\"foopage or barpage\" match=\"barpage\"]]\n"
+
+#. type: Plain text
+msgid ""
+"This will print out something like \"match: barpage matches barpage\", "
+"indicating the part of the [[ikiwiki/PageSpec]] that caused it to match."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/teximg.da.po b/po/underlays/directives/ikiwiki/directive/teximg.da.po
new file mode 100644 (file)
index 0000000..179c502
--- /dev/null
@@ -0,0 +1,76 @@
+# Danish translation of directives/ikiwiki/directive/teximg page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `teximg` directive is supplied by the [[!iki plugins/teximg "
+"desc=teximg]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "This directive renders LaTeX formulas into images."
+msgstr ""
+
+#. type: Title ##
+#, no-wrap
+msgid "examples"
+msgstr "eksempler"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!teximg code=\"\\frac{1}{2}\"]]\n"
+"\t\\[[!teximg code=\"E = - \\frac{Z^2 \\cdot  \\mu \\cdot e^4}{32\\pi^2 \\epsilon_0^2 \\hbar^2 n^2}\" ]]\n"
+msgstr ""
+
+#. type: Plain text
+msgid "To scale the image, use height=x:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\t\\[[!teximg code=\"\\frac{1}{2}\" height=\"17\"]]\n"
+"\t\\[[!teximg code=\"\\frac{1}{2}\" height=\"8\"]]\n"
+msgstr ""
+"\t\\[[!teximg code=\"\\frac{1}{2}\" height=\"17\"]]\n"
+"\t\\[[!teximg code=\"\\frac{1}{2}\" height=\"8\"]]\n"
+
+#. type: Plain text
+msgid ""
+"If no height is chosen the default height 12 is used. Valid heights are: 8, "
+"9, 10, 11, 12, 14, 17, 20. If another height is entered, the closest "
+"available height is used."
+msgstr ""
+
+#. type: Plain text
+msgid "To add an alt text to the image, use alt=\"text\":"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!teximg code=\"\\frac{1}{2}\" alt=\"1/2\"]]\n"
+msgstr "\t\\[[!teximg code=\"\\frac{1}{2}\" alt=\"1/2\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/toc.da.po b/po/underlays/directives/ikiwiki/directive/toc.da.po
new file mode 100644 (file)
index 0000000..5dcd5b5
--- /dev/null
@@ -0,0 +1,65 @@
+# Danish translation of directives/ikiwiki/directive/toc page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `toc` directive is supplied by the [[!iki plugins/toc desc=toc]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "Add a table of contents to a page:"
+msgstr "Tilføje en indholdsfortegnelse til en side:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toc ]]\n"
+msgstr "\t\\[[!toc ]]\n"
+
+#. type: Plain text
+msgid ""
+"The table of contents will be automatically generated based on the headers "
+"of the page. By default only the largest headers present on the page will be "
+"shown; to control how many levels of headers are shown, use the `levels` "
+"parameter:"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toc levels=2]]\n"
+msgstr "\t\\[[!toc levels=2]]\n"
+
+#. type: Plain text
+msgid ""
+"The toc directive will take the level of the first header as the topmost "
+"level, even if there are higher levels seen later in the file."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The table of contents will be created as an ordered list. If you want an "
+"unordered list instead, you can change the list-style in your local style "
+"sheet."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/toggle.da.po b/po/underlays/directives/ikiwiki/directive/toggle.da.po
new file mode 100644 (file)
index 0000000..7b1ba9b
--- /dev/null
@@ -0,0 +1,95 @@
+# Danish translation of directives/ikiwiki/directive/toggle page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `toggle` and `toggleable` directives are supplied by the [[!iki plugins/"
+"toggle desc=toggle]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"With these directives you can create links on pages that, when clicked, "
+"toggle display of other parts of the page."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"It uses javascript to accomplish this; browsers without javascript will "
+"always see the full page content."
+msgstr ""
+
+#. type: Plain text
+msgid "Example use:"
+msgstr "Eksempler på brug:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toggle id=\"ipsum\" text=\"show\"]]\n"
+msgstr "\t\\[[!toggle id=\"ipsum\" text=\"vis\"]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!toggleable id=\"ipsum\" text=\"\"\"\n"
+msgstr "\t\\[[!toggleable id=\"ipsum\" text=\"\"\"\n"
+
+#. type: Plain text
+#, no-wrap
+msgid ""
+"\tLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\n"
+"\teiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim\n"
+"\tad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n"
+"\taliquip ex ea commodo consequat.\n"
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "\t[[!toggle id=\"ipsum\" text=\"hide\"]]\n"
+msgstr "\t[[!toggle id=\"ipsum\" text=\"skjul\"]]\n"
+
+#. type: Plain text
+msgid ""
+"Note that you can include wiki markup in the toggleable text, including even "
+"additional toggles, as shown in the above example."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Also, the toggle and the togglable definitions do not need to be next to "
+"each other, but can be located anywhere on the page. There can also be "
+"mutiple toggles that all toggle a single togglable."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"The id has a default value of \"default\", so can be omitted in simple cases."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"If you'd like a toggleable to be displayed by default, and toggle to hidden, "
+"then pass a parameter \"open=yes\" when setting up the toggleable."
+msgstr ""
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/toggleable.da.po b/po/underlays/directives/ikiwiki/directive/toggleable.da.po
new file mode 100644 (file)
index 0000000..c8a95f2
--- /dev/null
@@ -0,0 +1,30 @@
+# Danish translation of directives/ikiwiki/directive/toggleable page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta redir=/ikiwiki/directive/toggle]]\n"
+msgstr "[[!meta redir=/ikiwiki/directive/toggle]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/directives/ikiwiki/directive/version.da.po b/po/underlays/directives/ikiwiki/directive/version.da.po
new file mode 100644 (file)
index 0000000..9c6bd97
--- /dev/null
@@ -0,0 +1,50 @@
+# Danish translation of directives/ikiwiki/directive/version page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-19 23:45+0200\n"
+"PO-Revision-Date: 2009-07-23 00:06+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"The `version` directive is supplied by the [[!iki plugins/version "
+"desc=version]] plugin."
+msgstr ""
+
+#. type: Plain text
+msgid "This directive allows inserting the version of ikiwiki onto a page."
+msgstr ""
+
+#. type: Plain text
+msgid ""
+"Whenever ikiwiki is upgraded to a new version, the page will be rebuilt, "
+"updating the version number."
+msgstr ""
+
+#. type: Plain text
+msgid "Use is simple:"
+msgstr "Brug er simpelt:"
+
+#. type: Plain text
+#, no-wrap
+msgid "\t\\[[!version ]]\n"
+msgstr "\t\\[[!version ]]\n"
+
+#. type: Plain text
+#, no-wrap
+msgid "[[!meta robots=\"noindex, follow\"]]\n"
+msgstr "[[!meta robots=\"noindex, follow\"]]\n"
diff --git a/po/underlays/smiley/smileys.da.po b/po/underlays/smiley/smileys.da.po
new file mode 100644 (file)
index 0000000..2f53ef8
--- /dev/null
@@ -0,0 +1,214 @@
+# Danish translation of smiley/smileys page for ikiwiki.
+# Copyright (C) 2008-2009 Jonas Smedegaard <dr@jones.dk>
+# This file is distributed under the same license as the ikiwiki package.
+# Jonas Smedegaard <dr@jones.dk>, 2008.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ikiwiki 3.15\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-07-22 11:17+0300\n"
+"PO-Revision-Date: 2009-07-22 21:28+0200\n"
+"Last-Translator: Jonas Smedegaard <dr@jones.dk>\n"
+"Language-Team: None\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Danish\n"
+"X-Poedit-Country: DENMARK\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. type: Plain text
+msgid ""
+"This page is used to control what smileys are supported by the wiki.  Just "
+"write the text of a smiley to display it."
+msgstr ""
+"Denne side bruges til at styre hvilke smileys denne wiki understøtter. Skriv "
+"blot smiley-teksten for at vise den."
+
+#. type: Bullet: '* '
+msgid "\\\\:)\t[[smileys/smile.png]]"
+msgstr "\\\\:)\t[[smileys/smile.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-)\t[[smileys/smile.png]]"
+msgstr "\\\\:-)\t[[smileys/smile.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:D\t[[smileys/biggrin.png]]"
+msgstr "\\\\:D\t[[smileys/biggrin.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-D\t[[smileys/biggrin.png]]"
+msgstr "\\\\:-D\t[[smileys/biggrin.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\B)\t[[smileys/smile2.png]]"
+msgstr "\\\\B)\t[[smileys/smile2.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\B-)\t[[smileys/smile2.png]]"
+msgstr "\\\\B-)\t[[smileys/smile2.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:))\t[[smileys/smile3.png]]"
+msgstr "\\\\:))\t[[smileys/smile3.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-))\t[[smileys/smile3.png]]"
+msgstr "\\\\:-))\t[[smileys/smile3.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\;)\t[[smileys/smile4.png]]"
+msgstr "\\\\;)\t[[smileys/smile4.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\;-)\t[[smileys/smile4.png]]"
+msgstr "\\\\;-)\t[[smileys/smile4.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:\\\t[[smileys/ohwell.png]]"
+msgstr "\\\\:\\\t[[smileys/ohwell.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-\\\t[[smileys/ohwell.png]]"
+msgstr "\\\\:-\\\t[[smileys/ohwell.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:/\t[[smileys/ohwell.png]]"
+msgstr "\\\\:/\t[[smileys/ohwell.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-/\t[[smileys/ohwell.png]]"
+msgstr "\\\\:-/\t[[smileys/ohwell.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:|\t[[smileys/neutral.png]]"
+msgstr "\\\\:|\t[[smileys/neutral.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-|\t[[smileys/neutral.png]]"
+msgstr "\\\\:-|\t[[smileys/neutral.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\>:>\t[[smileys/devil.png]]"
+msgstr "\\\\>:>\t[[smileys/devil.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\X-(\t[[smileys/angry.png]]"
+msgstr "\\\\X-(\t[[smileys/angry.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\<:(\t[[smileys/frown.png]]"
+msgstr "\\\\<:(\t[[smileys/frown.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:(\t[[smileys/sad.png]]"
+msgstr "\\\\:(\t[[smileys/sad.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-(\t[[smileys/sad.png]]"
+msgstr "\\\\:-(\t[[smileys/sad.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-?\t[[smileys/tongue.png]]"
+msgstr "\\\\:-?\t[[smileys/tongue.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:-P\t[[smileys/tongue.png]]"
+msgstr "\\\\:-P\t[[smileys/tongue.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\:o\t[[smileys/redface.png]]"
+msgstr "\\\\:o\t[[smileys/redface.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\|)\t[[smileys/tired.png]]"
+msgstr "\\\\|)\t[[smileys/tired.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\|-)\t[[smileys/tired.png]]"
+msgstr "\\\\|-)\t[[smileys/tired.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{OK}\t[[smileys/thumbs-up.png]]"
+msgstr "\\\\{OK}\t[[smileys/thumbs-up.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{X}\t[[smileys/icon-error.png]]"
+msgstr "\\\\{X}\t[[smileys/icon-error.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{i}\t[[smileys/icon-info.png]]"
+msgstr "\\\\{i}\t[[smileys/icon-info.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\(./)\t[[smileys/checkmark.png]]"
+msgstr "\\\\(./)\t[[smileys/checkmark.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\(!)\t[[smileys/idea.png]]"
+msgstr "\\\\(!)\t[[smileys/idea.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\[!]\t[[smileys/attention.png]]"
+msgstr "\\\\[!]\t[[smileys/attention.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\/!\\\t[[smileys/alert.png]]"
+msgstr "\\\\/!\\\t[[smileys/alert.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\(?)\t[[smileys/question.png]]"
+msgstr "\\\\(?)\t[[smileys/question.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{x}\t[[smileys/star_on.png]]"
+msgstr "\\\\{x}\t[[smileys/star_on.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{*}\t[[smileys/star_on.png]]"
+msgstr "\\\\{*}\t[[smileys/star_on.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{o}\t[[smileys/star_off.png]]"
+msgstr "\\\\{o}\t[[smileys/star_off.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{1}\t[[smileys/prio1.png]]"
+msgstr "\\\\{1}\t[[smileys/prio1.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{2}\t[[smileys/prio2.png]]"
+msgstr "\\\\{2}\t[[smileys/prio2.png]]"
+
+#. type: Bullet: '* '
+msgid "\\\\{3}\t[[smileys/prio3.png]]"
+msgstr "\\\\{3}\t[[smileys/prio3.png]]"
+
+#. type: Plain text
+msgid "For example: {x} B) {x}"
+msgstr "Eksempel: {x} B) {x}"
+
+#. type: Plain text
+msgid ""
+"To change the supported smileys, just edit the lists on this page.  Note "
+"that the format is important; each list item should start with the text that "
+"is turned into the smiley, escaped so that users can see what produces it, "
+"followed by a [[ikiwiki/WikiLink]] to the image to display."
+msgstr ""
+"Redigér listen på denne side for at ændre understøttede smileys.  Bemærk at "
+"formatet er vigtigt: hvert listeemne skal begynde med teksten der skal "
+"omdannes til en smiley, omskrevet så brugere kan se hvordan det dannes, "
+"efterfulgt af en [[ikiwiki/WikiLink]] til billedet der skal vises."
+
+#. type: Plain text
+msgid ""
+"/!\\ Bear in mind that the link to the image needs to be written in a way "
+"that will work if it's copied to other pages on the wiki. So be sure to "
+"include the smileys directory in the path to the file."
+msgstr ""
+"/!\\ Tænk på at det er nødvendigt at skrive henvisningen til billedet på en "
+"måde så det virker hvis det kopieres til andre sider på wikien. Sørg derfor "
+"for at medtage smileys direkte i stien til filen."
index 51e85bd41dd25c9d153413ec8d51da8253e358f8..b500ed581ea4af3b092d73fdd5d3205f9412854e 100644 (file)
--- a/po/vi.po
+++ b/po/vi.po
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: ikiwiki\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-03 14:52-0500\n"
+"POT-Creation-Date: 2009-08-15 14:07-0400\n"
 "PO-Revision-Date: 2007-01-13 15:31+1030\n"
 "Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
 "Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
@@ -16,260 +16,495 @@ msgstr ""
 "Plural-Forms: nplurals=1; plural=0;\n"
 "X-Generator: LocFactoryEditor 1.6fc1\n"
 
-#: ../IkiWiki/CGI.pm:125
+#: ../IkiWiki/CGI.pm:113
 msgid "You need to log in first."
 msgstr "Trước tiên bạn cần phải đăng nhập."
 
-#: ../IkiWiki/CGI.pm:155
+#: ../IkiWiki/CGI.pm:146
+msgid ""
+"probable misconfiguration: sslcookie is set, but you are attempting to login "
+"via http, not https"
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:149
 msgid "login failed, perhaps you need to turn on cookies?"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:184
+#: ../IkiWiki/CGI.pm:168 ../IkiWiki/CGI.pm:299
+msgid "Your login session has expired."
+msgstr ""
+
+#: ../IkiWiki/CGI.pm:189
 msgid "Login"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:185
+#: ../IkiWiki/CGI.pm:190
 #, fuzzy
 msgid "Preferences"
 msgstr "Tùy thích đã được lưu."
 
-#: ../IkiWiki/CGI.pm:186
+#: ../IkiWiki/CGI.pm:191
 msgid "Admin"
 msgstr ""
 
-#: ../IkiWiki/CGI.pm:235
+#: ../IkiWiki/CGI.pm:231
 msgid "Preferences saved."
 msgstr "Tùy thích đã được lưu."
 
-#: ../IkiWiki/CGI.pm:291
-#, perl-format
-msgid "%s is not an editable page"
-msgstr ""
-
-#: ../IkiWiki/CGI.pm:382 ../IkiWiki/Plugin/brokenlinks.pm:24
-#: ../IkiWiki/Plugin/inline.pm:241 ../IkiWiki/Plugin/opendiscussion.pm:17
-#: ../IkiWiki/Plugin/orphans.pm:28 ../IkiWiki/Render.pm:95
-#: ../IkiWiki/Render.pm:175
-msgid "discussion"
-msgstr "thảo luận"
+#: ../IkiWiki/CGI.pm:262
+msgid "You are banned."
+msgstr "Bạn bị cấm ra."
 
-#: ../IkiWiki/CGI.pm:429
-#, perl-format
-msgid "creating %s"
-msgstr "đang tạo %s"
+#: ../IkiWiki/CGI.pm:390 ../IkiWiki/CGI.pm:391 ../IkiWiki.pm:1260
+msgid "Error"
+msgstr "Lỗi"
 
-#: ../IkiWiki/CGI.pm:447 ../IkiWiki/CGI.pm:466 ../IkiWiki/CGI.pm:476
-#: ../IkiWiki/CGI.pm:510 ../IkiWiki/CGI.pm:554
-#, perl-format
-msgid "editing %s"
-msgstr "đang sửa %s"
+#: ../IkiWiki/Plugin/aggregate.pm:84
+msgid "Aggregation triggered via web."
+msgstr ""
 
-#: ../IkiWiki/CGI.pm:643
-msgid "You are banned."
-msgstr "Bạn bị cấm ra."
+#: ../IkiWiki/Plugin/aggregate.pm:93
+msgid "Nothing to do right now, all feeds are up-to-date!"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:72
+#: ../IkiWiki/Plugin/aggregate.pm:220
 #, fuzzy, perl-format
 msgid "missing %s parameter"
 msgstr "mẫu thiếu tham số id"
 
-#: ../IkiWiki/Plugin/aggregate.pm:100
+#: ../IkiWiki/Plugin/aggregate.pm:255
 msgid "new feed"
 msgstr "nguồn tin mới"
 
-#: ../IkiWiki/Plugin/aggregate.pm:114
+#: ../IkiWiki/Plugin/aggregate.pm:269
 msgid "posts"
 msgstr "bài"
 
-#: ../IkiWiki/Plugin/aggregate.pm:116
+#: ../IkiWiki/Plugin/aggregate.pm:271
 msgid "new"
 msgstr "mới"
 
-#: ../IkiWiki/Plugin/aggregate.pm:232
+#: ../IkiWiki/Plugin/aggregate.pm:441
 #, perl-format
 msgid "expiring %s (%s days old)"
 msgstr "đang mãn hạn %s (cũ %s ngày)"
 
-#: ../IkiWiki/Plugin/aggregate.pm:239
+#: ../IkiWiki/Plugin/aggregate.pm:448
 #, perl-format
 msgid "expiring %s"
 msgstr "đang mãn hạn %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:265
+#: ../IkiWiki/Plugin/aggregate.pm:475
 #, perl-format
-msgid "processed ok at %s"
-msgstr "đã xử lý được ở %s"
+msgid "last checked %s"
+msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:270
+#: ../IkiWiki/Plugin/aggregate.pm:479
 #, perl-format
 msgid "checking feed %s ..."
 msgstr "đang kiểm tra nguồn tin %s ..."
 
-#: ../IkiWiki/Plugin/aggregate.pm:275
+#: ../IkiWiki/Plugin/aggregate.pm:484
 #, perl-format
 msgid "could not find feed at %s"
 msgstr "không tìm thấy nguồn tin ở %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:290
+#: ../IkiWiki/Plugin/aggregate.pm:503
 #, fuzzy
 msgid "feed not found"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/aggregate.pm:301
+#: ../IkiWiki/Plugin/aggregate.pm:514
 #, perl-format
 msgid "(invalid UTF-8 stripped from feed)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:307
+#: ../IkiWiki/Plugin/aggregate.pm:522
 #, perl-format
 msgid "(feed entities escaped)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/aggregate.pm:313
+#: ../IkiWiki/Plugin/aggregate.pm:530
 msgid "feed crashed XML::Feed!"
 msgstr "nguồn tin đã gây ra XML::Feed sụp đổ."
 
-#: ../IkiWiki/Plugin/aggregate.pm:387
+#: ../IkiWiki/Plugin/aggregate.pm:616
 #, perl-format
 msgid "creating new page %s"
 msgstr "đang tạo trang mới %s"
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:40
+#: ../IkiWiki/Plugin/amazon_s3.pm:31
+msgid "deleting bucket.."
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:38 ../ikiwiki.in:210
+msgid "done"
+msgstr "xong"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:97
+#, perl-format
+msgid "Must specify %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:136
+#, fuzzy
+msgid "Failed to create S3 bucket: "
+msgstr "Lỗi gửi thư"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:221
+#, fuzzy
+msgid "Failed to save file to S3: "
+msgstr "Lỗi gửi thư"
+
+#: ../IkiWiki/Plugin/amazon_s3.pm:243
+#, fuzzy
+msgid "Failed to delete file from S3: "
+msgstr "lỗi ghi %s: %s"
+
+#: ../IkiWiki/Plugin/attachment.pm:49
+#, perl-format
+msgid "there is already a page named %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:65
+msgid "prohibited by allowed_attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:140
+msgid "bad attachment filename"
+msgstr ""
+
+#: ../IkiWiki/Plugin/attachment.pm:182
+msgid "attachment upload"
+msgstr ""
+
+#: ../IkiWiki/Plugin/autoindex.pm:105
+msgid "automatic index generation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/blogspam.pm:108
+msgid ""
+"Sorry, but that looks like spam to <a href=\"http://blogspam.net/"
+"\">blogspam</a>: "
+msgstr ""
+
+#: ../IkiWiki/Plugin/brokenlinks.pm:42
 #, perl-format
 msgid "%s from %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/brokenlinks.pm:47
+#: ../IkiWiki/Plugin/brokenlinks.pm:50
 msgid "There are no broken links!"
 msgstr "Không có liên kết bị ngắt nào."
 
-#: ../IkiWiki/Plugin/conditional.pm:18
+#: ../IkiWiki/Plugin/comments.pm:124 ../IkiWiki/Plugin/format.pm:38
+#, perl-format
+msgid "unsupported page format %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:129
+msgid "comment must have content"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:185
+msgid "Anonymous"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:340 ../IkiWiki/Plugin/editpage.pm:97
+msgid "bad page name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:345
+#, fuzzy, perl-format
+msgid "commenting on %s"
+msgstr "đang tạo %s"
+
+#: ../IkiWiki/Plugin/comments.pm:363
+#, perl-format
+msgid "page '%s' doesn't exist, so you can't comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:370
+#, perl-format
+msgid "comments on page '%s' are closed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:464
+msgid "comment stored for moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:466
+msgid "Your comment will be posted after moderator review"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:479
+msgid "Added a comment"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:483
+#, perl-format
+msgid "Added a comment: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:525 ../IkiWiki/Plugin/websetup.pm:236
+msgid "you are not logged in as an admin"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:576
+msgid "Comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:615
+msgid "comment moderation"
+msgstr ""
+
+#: ../IkiWiki/Plugin/comments.pm:766
+msgid "Comments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/conditional.pm:27 ../IkiWiki/Plugin/cutpaste.pm:30
+#: ../IkiWiki/Plugin/cutpaste.pm:45 ../IkiWiki/Plugin/cutpaste.pm:61
+#: ../IkiWiki/Plugin/testpagespec.pm:26
 #, perl-format
 msgid "%s parameter is required"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:41
+#: ../IkiWiki/Plugin/cutpaste.pm:66
+msgid "no text was copied in this page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/cutpaste.pm:69
+#, perl-format
+msgid "no text was copied in this page with id %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:40
+#, fuzzy, perl-format
+msgid "removing old preview %s"
+msgstr "đang gỡ bỏ trang cũ %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:113
+#, perl-format
+msgid "%s is not an editable page"
+msgstr ""
+
+#: ../IkiWiki/Plugin/editpage.pm:292
+#, perl-format
+msgid "creating %s"
+msgstr "đang tạo %s"
+
+#: ../IkiWiki/Plugin/editpage.pm:310 ../IkiWiki/Plugin/editpage.pm:329
+#: ../IkiWiki/Plugin/editpage.pm:339 ../IkiWiki/Plugin/editpage.pm:383
+#: ../IkiWiki/Plugin/editpage.pm:422
+#, perl-format
+msgid "editing %s"
+msgstr "đang sửa %s"
+
+#: ../IkiWiki/Plugin/edittemplate.pm:51
 #, fuzzy
 msgid "template not specified"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:44
+#: ../IkiWiki/Plugin/edittemplate.pm:54
 #, fuzzy
 msgid "match not specified"
 msgstr "chưa xác định tên tập tin bộ bao bọc"
 
-#: ../IkiWiki/Plugin/edittemplate.pm:49
+#: ../IkiWiki/Plugin/edittemplate.pm:62
 #, perl-format
 msgid "edittemplate %s registered for %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/edittemplate.pm:111
+#: ../IkiWiki/Plugin/edittemplate.pm:133
 #, fuzzy
 msgid "failed to process"
 msgstr "mẫu không xử lý được:"
 
-#: ../IkiWiki/Plugin/fortune.pm:18
+#: ../IkiWiki/Plugin/format.pm:20
+msgid "must specify format and text"
+msgstr ""
+
+#: ../IkiWiki/Plugin/fortune.pm:27
 msgid "fortune failed"
 msgstr "fortune bị lỗi"
 
-#: ../IkiWiki/Plugin/googlecalendar.pm:22
+#: ../IkiWiki/Plugin/getsource.pm:62 ../IkiWiki/Plugin/goto.pm:55
+#, fuzzy
+msgid "missing page"
+msgstr "mẫu thiếu tham số id"
+
+#: ../IkiWiki/Plugin/getsource.pm:64 ../IkiWiki/Plugin/goto.pm:57
+#, perl-format
+msgid "The page %s does not exist."
+msgstr ""
+
+#: ../IkiWiki/Plugin/getsource.pm:73
 #, fuzzy
-msgid "failed to find url in html"
-msgstr "googlecalendar không tìm thấy địa chỉ URL trong mã HTML"
+msgid "not a page"
+msgstr "không thể đọc %s: %s"
+
+#: ../IkiWiki/Plugin/getsource.pm:75
+#, perl-format
+msgid "%s is an attachment, not a page."
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:626 ../IkiWiki/Plugin/git.pm:644
+#: ../IkiWiki/Receive.pm:129
+#, perl-format
+msgid "you are not allowed to change %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:666
+#, perl-format
+msgid "you cannot act on a file with mode %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/git.pm:670
+msgid "you are not allowed to change file modes"
+msgstr ""
 
-#: ../IkiWiki/Plugin/graphviz.pm:58
+#: ../IkiWiki/Plugin/google.pm:27 ../IkiWiki/Plugin/po.pm:129
+#: ../IkiWiki/Plugin/search.pm:36
+#, fuzzy, perl-format
+msgid "Must specify %s when using the %s plugin"
+msgstr "Cần phải xác định %s khi dùng bổ sung tìm kiếm"
+
+#: ../IkiWiki/Plugin/google.pm:31
+msgid "Failed to parse url, cannot determine domain name"
+msgstr ""
+
+#: ../IkiWiki/Plugin/graphviz.pm:67
 #, fuzzy
 msgid "failed to run graphviz"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/graphviz.pm:85
+#: ../IkiWiki/Plugin/graphviz.pm:94
 msgid "prog not a valid graphviz program"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:53
+#: ../IkiWiki/Plugin/highlight.pm:47
+#, perl-format
+msgid "tohighlight contains unknown file type '%s'"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:58
+#, perl-format
+msgid "Source code: %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/highlight.pm:123
+msgid ""
+"warning: highlight perl module not available; falling back to pass through"
+msgstr ""
+
+#: ../IkiWiki/Plugin/img.pm:63
+#, fuzzy
+msgid "Image::Magick is not installed"
+msgstr "chưa cài đặt polygen"
+
+#: ../IkiWiki/Plugin/img.pm:72
 #, perl-format
-msgid "bad size \"%s\""
+msgid "wrong size format \"%s\" (should be WxH)"
 msgstr ""
 
-#: ../IkiWiki/Plugin/img.pm:63 ../IkiWiki/Plugin/img.pm:67
-#: ../IkiWiki/Plugin/img.pm:84
+#: ../IkiWiki/Plugin/img.pm:83 ../IkiWiki/Plugin/img.pm:87
+#: ../IkiWiki/Plugin/img.pm:104
 #, fuzzy, perl-format
 msgid "failed to read %s: %s"
 msgstr "lỗi ghi %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:70
+#: ../IkiWiki/Plugin/img.pm:90
 #, fuzzy, perl-format
 msgid "failed to resize: %s"
 msgstr "lỗi ghi %s: %s"
 
-#: ../IkiWiki/Plugin/img.pm:101
+#: ../IkiWiki/Plugin/img.pm:119
 #, fuzzy, perl-format
 msgid "failed to determine size of image %s"
 msgstr "lỗi ghi %s: %s"
 
-#: ../IkiWiki/Plugin/inline.pm:42
+#: ../IkiWiki/Plugin/inline.pm:92
 msgid "Must specify url to wiki with --url when using --rss or --atom"
 msgstr ""
 "Cần phải xác định địa chỉ URL tới wiki với « --url » khi dùng « --rss » hay « --"
 "atom »"
 
-#: ../IkiWiki/Plugin/inline.pm:135
+#: ../IkiWiki/Plugin/inline.pm:138
+#, fuzzy
+msgid "page editing not allowed"
+msgstr "không tìm thấy mẫu %s"
+
+#: ../IkiWiki/Plugin/inline.pm:155
+#, fuzzy
+msgid "missing pages parameter"
+msgstr "mẫu thiếu tham số id"
+
+#: ../IkiWiki/Plugin/inline.pm:191
+#, perl-format
+msgid "the %s and %s parameters cannot be used together"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:212
+msgid "Sort::Naturally needed for title_natural sort"
+msgstr ""
+
+#: ../IkiWiki/Plugin/inline.pm:223
 #, perl-format
 msgid "unknown sort type %s"
 msgstr "kiểu sắp xếp không rõ %s"
 
-#: ../IkiWiki/Plugin/inline.pm:200
+#: ../IkiWiki/Plugin/inline.pm:327
 msgid "Add a new post titled:"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:216
+#: ../IkiWiki/Plugin/inline.pm:347
 #, perl-format
 msgid "nonexistant template %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/inline.pm:249 ../IkiWiki/Render.pm:99
-msgid "Discussion"
-msgstr "Thảo luận"
-
-#: ../IkiWiki/Plugin/inline.pm:463
+#: ../IkiWiki/Plugin/inline.pm:612
 msgid "RPC::XML::Client not found, not pinging"
 msgstr "Không tìm thấy RPC::XML::Client nên không gửi gói tin ping"
 
-#: ../IkiWiki/Plugin/linkmap.pm:98
+#: ../IkiWiki/Plugin/linkmap.pm:106
 #, fuzzy
 msgid "failed to run dot"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/lockedit.pm:29
-#, perl-format
-msgid "%s is locked by %s and cannot be edited"
+#: ../IkiWiki/Plugin/lockedit.pm:47
+#, fuzzy, perl-format
+msgid "%s is locked and cannot be edited"
 msgstr "%s bị %s khoá nên không thể sửa được"
 
-#: ../IkiWiki/Plugin/mdwn.pm:37
+#: ../IkiWiki/Plugin/mdwn.pm:44
+msgid "multimarkdown is enabled, but Text::MultiMarkdown is not installed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/mdwn.pm:67
 #, perl-format
 msgid "failed to load Markdown.pm perl module (%s) or /usr/bin/markdown (%s)"
 msgstr "lỗi nạp mô-đun perl Markdown.pm (%s) hay « /usr/bin/markdown » (%s)"
 
-#: ../IkiWiki/Plugin/meta.pm:119
+#: ../IkiWiki/Plugin/meta.pm:158
 #, fuzzy
 msgid "stylesheet not found"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/meta.pm:143
+#: ../IkiWiki/Plugin/meta.pm:196
 #, fuzzy
 msgid "redir page not found"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/meta.pm:156
+#: ../IkiWiki/Plugin/meta.pm:210
 #, fuzzy
 msgid "redir cycle is not allowed"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirrors"
 msgstr "Nhân bản"
 
-#: ../IkiWiki/Plugin/mirrorlist.pm:23
+#: ../IkiWiki/Plugin/mirrorlist.pm:42
 msgid "Mirror"
 msgstr "Nhân bản"
 
@@ -277,59 +512,200 @@ msgstr "Nhân bản"
 msgid "more"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:45
+#: ../IkiWiki/Plugin/norcs.pm:65
+msgid "getctime not implemented"
+msgstr "chưa thực hiện getctime"
+
+#: ../IkiWiki/Plugin/openid.pm:61
 msgid "Log in with"
 msgstr ""
 
-#: ../IkiWiki/Plugin/openid.pm:48
+#: ../IkiWiki/Plugin/openid.pm:64
 msgid "Get an OpenID"
 msgstr "Lấy OpenID"
 
-#: ../IkiWiki/Plugin/orphans.pm:42
-msgid "All pages are linked to by other pages."
+#: ../IkiWiki/Plugin/orphans.pm:45
+#, fuzzy
+msgid "All pages have other pages linking to them."
 msgstr "Mọi trang được liên kết với trang khác."
 
-#: ../IkiWiki/Plugin/pagetemplate.pm:21
+#: ../IkiWiki/Plugin/pagetemplate.pm:30
 msgid "bad or missing template"
 msgstr ""
 
-#: ../IkiWiki/Plugin/passwordauth.pm:162
+#: ../IkiWiki/Plugin/passwordauth.pm:248
 msgid "Account creation successful. Now you can Login."
 msgstr "Tài khoản đã được tạo. Lúc bây giờ bạn có thể đăng nhập."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:165
+#: ../IkiWiki/Plugin/passwordauth.pm:251
 msgid "Error creating account."
 msgstr "Gặp lỗi khi tạo tài khoản."
 
-#: ../IkiWiki/Plugin/passwordauth.pm:186
+#: ../IkiWiki/Plugin/passwordauth.pm:258
+msgid "No email address, so cannot email password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:292
 msgid "Failed to send mail"
 msgstr "Lỗi gửi thư"
 
-#: ../IkiWiki/Plugin/passwordauth.pm:188
-msgid "Your password has been emailed to you."
-msgstr "Mật khẩu đã được gửi đính kèm thư cho bạn."
+#: ../IkiWiki/Plugin/passwordauth.pm:294
+msgid "You have been mailed password reset instructions."
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:329
+msgid "incorrect password reset url"
+msgstr ""
+
+#: ../IkiWiki/Plugin/passwordauth.pm:332
+msgid "password reset denied"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pingee.pm:30
+msgid "Ping received."
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:53
+msgid "requires 'from' and 'to' parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:58
+#, fuzzy, perl-format
+msgid "Will ping %s"
+msgstr "đang sửa %s"
+
+#: ../IkiWiki/Plugin/pinger.pm:61
+#, perl-format
+msgid "Ignoring ping directive for wiki %s (this wiki is %s)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/pinger.pm:77
+#, fuzzy
+msgid "LWP not found, not pinging"
+msgstr "Không tìm thấy RPC::XML::Client nên không gửi gói tin ping"
+
+#: ../IkiWiki/Plugin/po.pm:15
+msgid "warning: Old po4a detected! Recommend upgrade to 0.35."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:136
+#, perl-format
+msgid "%s is not a valid language code"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:148
+#, perl-format
+msgid ""
+"%s is not a valid value for po_link_to, falling back to po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:153
+msgid ""
+"po_link_to=negotiated requires usedirs to be enabled, falling back to "
+"po_link_to=default"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:383
+#, perl-format
+msgid "rebuilding all pages to fix meta titles"
+msgstr ""
 
-#: ../IkiWiki/Plugin/poll.pm:64
+#: ../IkiWiki/Plugin/po.pm:387 ../IkiWiki/Render.pm:426
+#, fuzzy, perl-format
+msgid "building %s"
+msgstr "đang sửa %s"
+
+#: ../IkiWiki/Plugin/po.pm:424
+msgid "updated PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:448
+msgid ""
+"Can not remove a translation. If the master page is removed, however, its "
+"translations will be removed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:468
+msgid ""
+"Can not rename a translation. If the master page is renamed, however, its "
+"translations will be renamed as well."
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:829
+#, perl-format
+msgid "POT file (%s) does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:843
+#, fuzzy, perl-format
+msgid "failed to copy underlay PO file to %s"
+msgstr "lỗi biên dịch %s"
+
+#: ../IkiWiki/Plugin/po.pm:852
+#, fuzzy, perl-format
+msgid "failed to update %s"
+msgstr "lỗi biên dịch %s"
+
+#: ../IkiWiki/Plugin/po.pm:858
+#, fuzzy, perl-format
+msgid "failed to copy the POT file to %s"
+msgstr "lỗi biên dịch %s"
+
+#: ../IkiWiki/Plugin/po.pm:894
+msgid "N/A"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:907
+#, fuzzy, perl-format
+msgid "failed to translate %s"
+msgstr "lỗi ghi %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:983
+msgid "removed obsolete PO files"
+msgstr ""
+
+#: ../IkiWiki/Plugin/po.pm:1046 ../IkiWiki/Plugin/po.pm:1060
+#: ../IkiWiki/Plugin/po.pm:1100
+#, fuzzy, perl-format
+msgid "failed to write %s"
+msgstr "lỗi ghi %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1058
+#, fuzzy
+msgid "failed to translate"
+msgstr "linkmap không chạy dot được"
+
+#: ../IkiWiki/Plugin/po.pm:1063
+#, fuzzy, perl-format
+msgid "failed to read %s"
+msgstr "lỗi ghi %s: %s"
+
+#: ../IkiWiki/Plugin/po.pm:1112
+msgid "invalid gettext data, go back to previous page to continue edit"
+msgstr ""
+
+#: ../IkiWiki/Plugin/poll.pm:69
 msgid "vote"
 msgstr "bỏ phiếu"
 
-#: ../IkiWiki/Plugin/poll.pm:72
+#: ../IkiWiki/Plugin/poll.pm:77
 msgid "Total votes:"
 msgstr "Tổng số phiếu :"
 
-#: ../IkiWiki/Plugin/polygen.pm:32
+#: ../IkiWiki/Plugin/polygen.pm:41
 msgid "polygen not installed"
 msgstr "chưa cài đặt polygen"
 
-#: ../IkiWiki/Plugin/polygen.pm:51
-msgid "polygen failed"
-msgstr "lỗi polygen"
+#: ../IkiWiki/Plugin/polygen.pm:60
+#, fuzzy
+msgid "command failed"
+msgstr "fortune bị lỗi"
 
-#: ../IkiWiki/Plugin/postsparkline.pm:32
+#: ../IkiWiki/Plugin/postsparkline.pm:41
 msgid "missing formula"
 msgstr ""
 
-#: ../IkiWiki/Plugin/postsparkline.pm:39
+#: ../IkiWiki/Plugin/postsparkline.pm:48
 msgid "unknown formula"
 msgstr ""
 
@@ -385,46 +761,126 @@ msgstr ""
 msgid "%A night"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:78
+#: ../IkiWiki/Plugin/prettydate.pm:101
 msgid "at teatime on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:82
+#: ../IkiWiki/Plugin/prettydate.pm:105
 msgid "at midnight"
 msgstr ""
 
-#: ../IkiWiki/Plugin/prettydate.pm:85
+#: ../IkiWiki/Plugin/prettydate.pm:108
 msgid "at noon on %A"
 msgstr ""
 
-#: ../IkiWiki/Plugin/recentchanges.pm:74
+#: ../IkiWiki/Plugin/progress.pm:34
+#, perl-format
+msgid "illegal percent value %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/progress.pm:59
+msgid "need either `percent` or `totalpages` and `donepages` parameters"
+msgstr ""
+
+#: ../IkiWiki/Plugin/recentchangesdiff.pm:37
+msgid "(Diff truncated)"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:31 ../IkiWiki/Plugin/rename.pm:36
+#, perl-format
+msgid "%s does not exist"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:38
+#, fuzzy, perl-format
+msgid "%s is not in the srcdir, so it cannot be deleted"
+msgstr "%s bị %s khoá nên không thể sửa được"
+
+#: ../IkiWiki/Plugin/remove.pm:41 ../IkiWiki/Plugin/rename.pm:45
+#, perl-format
+msgid "%s is not a file"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:134
+#, perl-format
+msgid "confirm removal of %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:171
+msgid "Please select the attachments to remove."
+msgstr ""
+
+#: ../IkiWiki/Plugin/remove.pm:211
+msgid "removed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:42
+#, perl-format
+msgid "%s is not in the srcdir, so it cannot be renamed"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:62
 #, fuzzy
-msgid "missing page"
-msgstr "mẫu thiếu tham số id"
+msgid "no change to the file name was specified"
+msgstr "chưa xác định tên tập tin bộ bao bọc"
 
-#: ../IkiWiki/Plugin/recentchanges.pm:76
+#: ../IkiWiki/Plugin/rename.pm:68
 #, perl-format
-msgid "The page %s does not exist."
+msgid "illegal name"
 msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:34
+#: ../IkiWiki/Plugin/rename.pm:73
 #, perl-format
-msgid "Must specify %s when using the search plugin"
-msgstr "Cần phải xác định %s khi dùng bổ sung tìm kiếm"
+msgid "%s already exists"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:58
-msgid "cleaning hyperestraier search index"
-msgstr "đang làm sạch chỉ mục tìm kiếm hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:79
+#, perl-format
+msgid "%s already exists on disk"
+msgstr ""
 
-#: ../IkiWiki/Plugin/search.pm:64
-msgid "updating hyperestraier search index"
-msgstr "đang cập nhật chỉ mục tìm kiếm hyperestraier"
+#: ../IkiWiki/Plugin/rename.pm:122
+#, fuzzy, perl-format
+msgid "rename %s"
+msgstr "đang vẽ %s"
+
+#: ../IkiWiki/Plugin/rename.pm:161
+msgid "Also rename SubPages and attachments"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:247
+msgid "Only one attachment can be renamed at a time."
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:250
+msgid "Please select the attachment to rename."
+msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:18
-msgid "shortcut plugin will not work without a shortcuts.mdwn"
+#: ../IkiWiki/Plugin/rename.pm:347
+#, perl-format
+msgid "rename %s to %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/rename.pm:571
+#, fuzzy, perl-format
+msgid "update for rename of %s to %s"
+msgstr "cập nhật %2$s của %1$s bởi %3$s"
+
+#: ../IkiWiki/Plugin/search.pm:182
+#, perl-format
+msgid "need Digest::SHA1 to index %s"
 msgstr ""
 
-#: ../IkiWiki/Plugin/shortcut.pm:27
+#: ../IkiWiki/Plugin/search.pm:217
+msgid "search"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:31
+#, perl-format
+msgid "shortcut plugin will not work without %s"
+msgstr ""
+
+#: ../IkiWiki/Plugin/shortcut.pm:44
 #, fuzzy
 msgid "missing name or url parameter"
 msgstr "lối tắt thiếu tên hay tham số url"
@@ -432,177 +888,225 @@ msgstr "lối tắt thiếu tên hay tham số url"
 #. translators: This is used to display what shortcuts are defined.
 #. translators: First parameter is the name of the shortcut, the second
 #. translators: is an URL.
-#: ../IkiWiki/Plugin/shortcut.pm:36
+#: ../IkiWiki/Plugin/shortcut.pm:54
 #, fuzzy, perl-format
 msgid "shortcut %s points to <i>%s</i>"
 msgstr "lối tắt %s chỉ tới %s"
 
-#: ../IkiWiki/Plugin/smiley.pm:23
+#: ../IkiWiki/Plugin/smiley.pm:43
 #, fuzzy
 msgid "failed to parse any smileys"
 msgstr "lỗi phân tách hình cười nào nên tắt bổ sung"
 
-#: ../IkiWiki/Plugin/sparkline.pm:63
+#: ../IkiWiki/Plugin/sparkline.pm:72
 #, fuzzy
 msgid "parse error"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/sparkline.pm:69
-msgid "bad featurepoint diameter"
+#: ../IkiWiki/Plugin/sparkline.pm:78
+msgid "invalid featurepoint diameter"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:79
-msgid "bad featurepoint location"
+#: ../IkiWiki/Plugin/sparkline.pm:88
+msgid "invalid featurepoint location"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:90
+#: ../IkiWiki/Plugin/sparkline.pm:99
 msgid "missing values"
 msgstr ""
 
-#: ../IkiWiki/Plugin/sparkline.pm:95
+#: ../IkiWiki/Plugin/sparkline.pm:104
 #, fuzzy
-msgid "bad height value"
+msgid "invalid height value"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/sparkline.pm:102
+#: ../IkiWiki/Plugin/sparkline.pm:111
 #, fuzzy
 msgid "missing width parameter"
 msgstr "mẫu thiếu tham số id"
 
-#: ../IkiWiki/Plugin/sparkline.pm:106
+#: ../IkiWiki/Plugin/sparkline.pm:115
 #, fuzzy
-msgid "bad width value"
+msgid "invalid width value"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/sparkline.pm:144
+#: ../IkiWiki/Plugin/sparkline.pm:153
 #, fuzzy
 msgid "failed to run php"
 msgstr "linkmap không chạy dot được"
 
-#: ../IkiWiki/Plugin/table.pm:22
+#: ../IkiWiki/Plugin/table.pm:31
 msgid "cannot find file"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:64
+#: ../IkiWiki/Plugin/table.pm:87
 msgid "unknown data format"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:72
+#: ../IkiWiki/Plugin/table.pm:95
 msgid "empty data"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:92
+#: ../IkiWiki/Plugin/table.pm:114
 msgid "Direct data download"
 msgstr ""
 
-#: ../IkiWiki/Plugin/table.pm:126
+#: ../IkiWiki/Plugin/table.pm:148
 #, fuzzy, perl-format
 msgid "parse fail at line %d: %s"
 msgstr "lỗi ghi %s: %s"
 
-#: ../IkiWiki/Plugin/template.pm:19
+#: ../IkiWiki/Plugin/template.pm:29
 #, fuzzy
 msgid "missing id parameter"
 msgstr "mẫu thiếu tham số id"
 
-#: ../IkiWiki/Plugin/template.pm:26
+#: ../IkiWiki/Plugin/template.pm:36
 #, perl-format
 msgid "template %s not found"
 msgstr "không tìm thấy mẫu %s"
 
-#: ../IkiWiki/Plugin/template.pm:45
+#: ../IkiWiki/Plugin/template.pm:55
 #, fuzzy
 msgid "failed to process:"
 msgstr "mẫu không xử lý được:"
 
-#: ../IkiWiki/Plugin/teximg.pm:30
+#: ../IkiWiki/Plugin/teximg.pm:70
 msgid "missing tex code"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:37
+#: ../IkiWiki/Plugin/teximg.pm:77
 msgid "code includes disallowed latex commands"
 msgstr ""
 
-#: ../IkiWiki/Plugin/teximg.pm:96
+#: ../IkiWiki/Plugin/teximg.pm:128
 #, fuzzy
 msgid "failed to generate image from code"
 msgstr "lỗi ghi %s: %s"
 
-#: ../IkiWiki/Plugin/toggle.pm:88
-msgid "(not toggleable in preview mode)"
+#: ../IkiWiki/Plugin/websetup.pm:89
+msgid "plugin"
 msgstr ""
 
-#: ../IkiWiki/Rcs/Stub.pm:62
-msgid "getctime not implemented"
-msgstr "chưa thực hiện getctime"
+#: ../IkiWiki/Plugin/websetup.pm:108
+#, perl-format
+msgid "enable %s?"
+msgstr ""
 
-#: ../IkiWiki/Render.pm:273 ../IkiWiki/Render.pm:294
+#: ../IkiWiki/Plugin/websetup.pm:240
+msgid "setup file for this wiki is not known"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:256
+msgid "main"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:257
+msgid "plugins"
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:395
+msgid ""
+"The configuration changes shown below require a wiki rebuild to take effect."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:399
+msgid ""
+"For the configuration changes shown below to fully take effect, you may need "
+"to rebuild the wiki."
+msgstr ""
+
+#: ../IkiWiki/Plugin/websetup.pm:436
+#, perl-format
+msgid "Error: %s exited nonzero (%s). Discarding setup changes."
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:35
+#, perl-format
+msgid "cannot determine id of untrusted committer %s"
+msgstr ""
+
+#: ../IkiWiki/Receive.pm:85
+#, fuzzy, perl-format
+msgid "bad file name %s"
+msgstr "đang bỏ qua tên tập tin sai %s"
+
+#: ../IkiWiki/Render.pm:264
+#, perl-format
+msgid ""
+"symlink found in srcdir path (%s) -- set allow_symlinks_before_srcdir to "
+"allow this"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:287 ../IkiWiki/Render.pm:312
 #, perl-format
 msgid "skipping bad filename %s"
 msgstr "đang bỏ qua tên tập tin sai %s"
 
-#: ../IkiWiki/Render.pm:343
+#: ../IkiWiki/Render.pm:294
+#, perl-format
+msgid "%s has multiple possible source pages"
+msgstr ""
+
+#: ../IkiWiki/Render.pm:380
 #, perl-format
 msgid "removing old page %s"
 msgstr "đang gỡ bỏ trang cũ %s"
 
-#: ../IkiWiki/Render.pm:384
+#: ../IkiWiki/Render.pm:421
 #, perl-format
 msgid "scanning %s"
 msgstr "đang quét %s"
 
-#: ../IkiWiki/Render.pm:389
-#, perl-format
-msgid "rendering %s"
-msgstr "đang vẽ %s"
-
-#: ../IkiWiki/Render.pm:410
-#, perl-format
-msgid "rendering %s, which links to %s"
+#: ../IkiWiki/Render.pm:447
+#, fuzzy, perl-format
+msgid "building %s, which links to %s"
 msgstr "đang vẽ %s mà liên kết tới %s"
 
-#: ../IkiWiki/Render.pm:431
-#, perl-format
-msgid "rendering %s, which depends on %s"
+#: ../IkiWiki/Render.pm:468
+#, fuzzy, perl-format
+msgid "building %s, which depends on %s"
 msgstr "đang vẽ %s mà phụ thuộc vào %s"
 
-#: ../IkiWiki/Render.pm:470
-#, perl-format
-msgid "rendering %s, to update its backlinks"
+#: ../IkiWiki/Render.pm:507
+#, fuzzy, perl-format
+msgid "building %s, to update its backlinks"
 msgstr "đang vẽ %s để cập nhật các liên kết ngược của nó"
 
-#: ../IkiWiki/Render.pm:482
-#, perl-format
-msgid "removing %s, no longer rendered by %s"
+#: ../IkiWiki/Render.pm:519
+#, fuzzy, perl-format
+msgid "removing %s, no longer built by %s"
 msgstr "đang gỡ bỏ %s, không còn được vẽ lại bởi %s"
 
-#: ../IkiWiki/Render.pm:508
-#, perl-format
-msgid "ikiwiki: cannot render %s"
+#: ../IkiWiki/Render.pm:543
+#, fuzzy, perl-format
+msgid "ikiwiki: cannot build %s"
 msgstr "ikiwiki: không thể vẽ %s"
 
 #. translators: The first parameter is a filename, and the second
 #. translators: is a (probably not translated) error message.
-#: ../IkiWiki/Setup.pm:15
+#: ../IkiWiki/Setup.pm:19
 #, perl-format
 msgid "cannot read %s: %s"
 msgstr "không thể đọc %s: %s"
 
-#: ../IkiWiki/Setup/Standard.pm:32
-msgid "generating wrappers.."
-msgstr "đang tạo ra các bộ bao bọc.."
+#: ../IkiWiki/Setup/Automator.pm:34
+msgid "you must enter a wikiname (that contains alphanumerics)"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:72
-msgid "rebuilding wiki.."
-msgstr "đang xây dựng lại wiki.."
+#: ../IkiWiki/Setup/Automator.pm:71
+#, perl-format
+msgid "unsupported revision control system %s"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:75
-msgid "refreshing wiki.."
-msgstr "đang làm tươi wiki.."
+#: ../IkiWiki/Setup/Automator.pm:97
+msgid "failed to set up the repository with ikiwiki-makerepo"
+msgstr ""
 
-#: ../IkiWiki/Setup/Standard.pm:84
-msgid "done"
-msgstr "xong"
+#: ../IkiWiki/Setup/Automator.pm:115
+#, perl-format
+msgid "** Disabling plugin %s, since it is failing with this message:"
+msgstr ""
 
 #: ../IkiWiki/Wrapper.pm:16
 #, perl-format
@@ -617,21 +1121,14 @@ msgstr "không thể tạo bộ bao bọc sử dụng tập tin thiết lập"
 msgid "wrapper filename not specified"
 msgstr "chưa xác định tên tập tin bộ bao bọc"
 
-#. translators: The first parameter is a filename, and the second is
-#. translators: a (probably not translated) error message.
-#: ../IkiWiki/Wrapper.pm:48
-#, perl-format
-msgid "failed to write %s: %s"
-msgstr "lỗi ghi %s: %s"
-
 #. translators: The parameter is a C filename.
-#: ../IkiWiki/Wrapper.pm:99
+#: ../IkiWiki/Wrapper.pm:152
 #, perl-format
 msgid "failed to compile %s"
 msgstr "lỗi biên dịch %s"
 
 #. translators: The parameter is a filename.
-#: ../IkiWiki/Wrapper.pm:119
+#: ../IkiWiki/Wrapper.pm:172
 #, perl-format
 msgid "successfully generated %s"
 msgstr "%s đã được tạo ra"
@@ -640,27 +1137,106 @@ msgstr "%s đã được tạo ra"
 msgid "usage: ikiwiki [options] source dest"
 msgstr "cách sử dụng: ikiwiki [tùy chọn] nguồn đích"
 
-#: ../ikiwiki.in:81
+#: ../ikiwiki.in:14
+msgid "       ikiwiki --setup configfile"
+msgstr ""
+
+#: ../ikiwiki.in:91
 msgid "usage: --set var=value"
 msgstr ""
 
-#: ../IkiWiki.pm:127
+#: ../ikiwiki.in:140
+msgid "generating wrappers.."
+msgstr "đang tạo ra các bộ bao bọc.."
+
+#: ../ikiwiki.in:199
+msgid "rebuilding wiki.."
+msgstr "đang xây dựng lại wiki.."
+
+#: ../ikiwiki.in:202
+msgid "refreshing wiki.."
+msgstr "đang làm tươi wiki.."
+
+#: ../IkiWiki.pm:225
+msgid "Discussion"
+msgstr "Thảo luận"
+
+#: ../IkiWiki.pm:494
 msgid "Must specify url to wiki with --url when using --cgi"
 msgstr "Cần phải xác định địa chỉ URL tới wiki với « --url » khi dùng « --cgi »"
 
-#: ../IkiWiki.pm:196 ../IkiWiki.pm:197
-msgid "Error"
-msgstr "Lỗi"
+#: ../IkiWiki.pm:540
+msgid "cannot use multiple rcs plugins"
+msgstr ""
 
-#. translators: The first parameter is a
-#. translators: preprocessor directive name,
-#. translators: the second a page name, the
-#. translators: third a number.
-#: ../IkiWiki.pm:750
+#: ../IkiWiki.pm:569
 #, perl-format
-msgid "%s preprocessing loop detected on %s at depth %i"
+msgid "failed to load external plugin needed for %s plugin: %s"
+msgstr ""
+
+#: ../IkiWiki.pm:1243
+#, fuzzy, perl-format
+msgid "preprocessing loop detected on %s at depth %i"
 msgstr "vòng lặp tiền xử lý %s được phát hiện trên %s ở độ sâu %i"
 
+#: ../IkiWiki.pm:1783
+msgid "yes"
+msgstr ""
+
+#: ../IkiWiki.pm:1915
+#, fuzzy, perl-format
+msgid "cannot match pages: %s"
+msgstr "không thể đọc %s: %s"
+
+#: ../auto.setup:16
+msgid "What will the wiki be named?"
+msgstr ""
+
+#: ../auto.setup:16
+msgid "wiki"
+msgstr ""
+
+#: ../auto.setup:18
+msgid "What revision control system to use?"
+msgstr ""
+
+#: ../auto.setup:20
+msgid "Which user (wiki account or openid) will be admin?"
+msgstr ""
+
+#: ../auto.setup:23
+msgid "What is the domain name of the web server?"
+msgstr ""
+
+#~ msgid "discussion"
+#~ msgstr "thảo luận"
+
+#~ msgid "rendering %s"
+#~ msgstr "đang vẽ %s"
+
+#, fuzzy
+#~ msgid "Must specify %s when using the google search plugin"
+#~ msgstr "Cần phải xác định %s khi dùng bổ sung tìm kiếm"
+
+#, fuzzy
+#~ msgid "failed to find url in html"
+#~ msgstr "googlecalendar không tìm thấy địa chỉ URL trong mã HTML"
+
+#~ msgid "processed ok at %s"
+#~ msgstr "đã xử lý được ở %s"
+
+#~ msgid "Your password has been emailed to you."
+#~ msgstr "Mật khẩu đã được gửi đính kèm thư cho bạn."
+
+#~ msgid "polygen failed"
+#~ msgstr "lỗi polygen"
+
+#~ msgid "cleaning hyperestraier search index"
+#~ msgstr "đang làm sạch chỉ mục tìm kiếm hyperestraier"
+
+#~ msgid "updating hyperestraier search index"
+#~ msgstr "đang cập nhật chỉ mục tìm kiếm hyperestraier"
+
 #, fuzzy
 #~ msgid ""
 #~ "REV is not set, not running from mtn post-commit hook, cannot send "
@@ -679,9 +1255,6 @@ msgstr "vòng lặp tiền xử lý %s được phát hiện trên %s ở độ
 #~ msgstr ""
 #~ "Chưa đặt REV, không chạy từ móc sau gài vào nên không thể gửi thông báo"
 
-#~ msgid "update of %s's %s by %s"
-#~ msgstr "cập nhật %2$s của %1$s bởi %3$s"
-
 #, fuzzy
 #~ msgid "%s not found"
 #~ msgstr "không tìm thấy mẫu %s"
diff --git a/t/404.t b/t/404.t
new file mode 100755 (executable)
index 0000000..0bb3c60
--- /dev/null
+++ b/t/404.t
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 17;
+
+BEGIN { use_ok("IkiWiki::Plugin::404"); }
+
+sub cgi_page_from_404 {
+       return IkiWiki::Plugin::404::cgi_page_from_404(shift, shift, shift);
+}
+
+$IkiWiki::config{htmlext} = 'html';
+
+is(cgi_page_from_404('/', 'http://example.com', 1), 'index');
+is(cgi_page_from_404('/index.html', 'http://example.com', 0), 'index');
+is(cgi_page_from_404('/', 'http://example.com/', 1), 'index');
+is(cgi_page_from_404('/index.html', 'http://example.com/', 0), 'index');
+
+is(cgi_page_from_404('/~user/foo/bar', 'http://example.com/~user', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar/index.html', 'http://example.com/~user', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar/', 'http://example.com/~user', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar.html', 'http://example.com/~user', 0),
+   'foo/bar');
+
+is(cgi_page_from_404('/~user/foo/bar', 'http://example.com/~user/', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar/index.html', 'http://example.com/~user/', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar/', 'http://example.com/~user/', 1),
+   'foo/bar');
+is(cgi_page_from_404('/~user/foo/bar.html', 'http://example.com/~user/', 0),
+   'foo/bar');
+
+is(cgi_page_from_404('/~user/foo', 'https://example.com/~user', 1),
+   'foo');
+is(cgi_page_from_404('/~user/foo/index.html', 'https://example.com/~user', 1),
+   'foo');
+is(cgi_page_from_404('/~user/foo/', 'https://example.com/~user', 1),
+   'foo');
+is(cgi_page_from_404('/~user/foo.html', 'https://example.com/~user', 0),
+   'foo');
index baee285e24409fc699edec0609e3243e825d8092..d74f64e362f6e0822ec953e2eda2ce95c05764ea 100755 (executable)
@@ -3,10 +3,27 @@ use warnings;
 use strict;
 use Test::More 'no_plan';
 
-ok(! system("mkdir t/tmp"));
-ok(! system("make -q ikiwiki.out"));
-ok(! system("make extra_install DESTDIR=`pwd`/t/tmp/install PREFIX=/usr >/dev/null"));
-ok(! system("LANG= perl -T -I. ./ikiwiki.out -plugin smiley -plugin brokenlinks -rebuild -underlaydir=t/tmp/install/usr/share/ikiwiki/basewiki -templatedir=templates t/basewiki_brokenlinks t/tmp/out"));
-ok(`grep 'no broken links' t/tmp/out/index.html`);
-ok(-e "t/tmp/out/style.css");
-ok(! system("rm -rf t/tmp t/basewiki_brokenlinks/.ikiwiki"));
+ok(! system("rm -rf t/tmp; mkdir t/tmp"));
+ok(! system("make -s ikiwiki.out"));
+ok(! system("make underlay_install DESTDIR=`pwd`/t/tmp/install PREFIX=/usr >/dev/null"));
+
+foreach my $plugin ("", "listdirectives") {
+       ok(! system("perl -I. ./ikiwiki.out -rebuild -plugin brokenlinks ".
+                       # always enabled because pages link to it conditionally,
+                       # which brokenlinks cannot handle properly
+                       "-plugin smiley ".
+                       ($plugin ? "-plugin $plugin " : "").
+                       "-underlaydir=t/tmp/install/usr/share/ikiwiki/basewiki ".
+                       "-set underlaydirbase=t/tmp/install/usr/share/ikiwiki ".
+                       "-templatedir=templates t/basewiki_brokenlinks t/tmp/out"));
+       my $result=`grep 'no broken links' t/tmp/out/index.html`;
+       ok(length($result));
+       if (! length $result) {
+               print STDERR "\n\nbroken links found".($plugin ? " (with $plugin)" : "")."\n";
+               system("grep '<li>' t/tmp/out/index.html >&2");
+               print STDERR "\n\n";
+       }
+       ok(-e "t/tmp/out/style.css"); # linked to..
+       ok(! system("rm -rf t/tmp/out t/basewiki_brokenlinks/.ikiwiki"));
+}
+ok(! system("rm -rf t/tmp"));
index 0a6b2c39ef3538de2bf3189683fde1f191553c31..41768f7820a093676460395bf7831e0e78050560 100644 (file)
@@ -1 +1 @@
-[[brokenlinks ]]
+[[!brokenlinks ]]
index f064814fe15cbdf5d6ee9a41a5f22df766ab8ab8..2ca44a65e084ce1395855ae177f4fa8632ba3e5c 100755 (executable)
@@ -12,13 +12,14 @@ BEGIN {
                }
        }
 }
-use Test::More tests => 11;
+use Test::More tests => 16;
 
 BEGIN { use_ok("IkiWiki"); }
 
 %config=IkiWiki::defaultconfig();
 $config{rcs} = "bzr";
 $config{srcdir} = "$dir/repo";
+IkiWiki::loadplugins();
 IkiWiki::checkconfig();
 
 system "bzr init $config{srcdir}";
@@ -34,7 +35,7 @@ my @changes;
 
 is($#changes, 0);
 is($changes[0]{message}[0]{"line"}, "Added the first page");
-is($changes[0]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test1");
 is($changes[0]{user}, "Joe User");
        
 # Manual commit
@@ -44,19 +45,41 @@ my $message = "Added the second page";
 
 my $test2 = readfile("t/test2.mdwn");
 writefile('test2.mdwn', $config{srcdir}, $test2);
-system "bzr add $config{srcdir}/test2.mdwn";
-system "bzr commit --author \"$user\" -m \"$message\" $config{srcdir}";
+system "bzr add --quiet $config{srcdir}/test2.mdwn";
+system "bzr commit --quiet --author \"$user\" -m \"$message\" $config{srcdir}";
        
 @changes = IkiWiki::rcs_recentchanges(3);
 
 is($#changes, 1);
 is($changes[0]{message}[0]{"line"}, $message);
 is($changes[0]{user}, $username);
-is($changes[0]{pages}[0]{"page"}, "test2.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test2");
 
-is($changes[1]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[1]{pages}[0]{"page"}, "test1");
 
 my $ctime = IkiWiki::rcs_getctime("test2.mdwn");
 ok($ctime >= time() - 20);
 
+writefile('test3.mdwn', $config{srcdir}, $test1);
+IkiWiki::rcs_add("test3.mdwn");
+IkiWiki::rcs_rename("test3.mdwn", "test4.mdwn");
+IkiWiki::rcs_commit_staged("Added the 4th page", "moo", "Joe User");
+
+@changes = IkiWiki::rcs_recentchanges(4);
+
+is($#changes, 2);
+is($changes[0]{pages}[0]{"page"}, "test4");
+
+ok(mkdir($config{srcdir}."/newdir"));
+IkiWiki::rcs_rename("test4.mdwn", "newdir/test5.mdwn");
+IkiWiki::rcs_commit_staged("Added the 5th page", "moo", "Joe User");
+
+@changes = IkiWiki::rcs_recentchanges(4);
+
+is($#changes, 3);
+is($changes[0]{pages}[0]{"page"}, "newdir/test5");
+
+IkiWiki::rcs_remove("newdir/test5.mdwn");
+IkiWiki::rcs_commit_staged("Remove the 5th page", "moo", "Joe User");
+
 system "rm -rf $dir";
diff --git a/t/beautify_urlpath.t b/t/beautify_urlpath.t
new file mode 100755 (executable)
index 0000000..94b923d
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 8;
+
+BEGIN { use_ok("IkiWiki"); }
+
+$IkiWiki::config{usedirs} = 1;
+$IkiWiki::config{htmlext} = "HTML";
+is(IkiWiki::beautify_urlpath("foo/bar"), "./foo/bar");
+is(IkiWiki::beautify_urlpath("../badger"), "../badger");
+is(IkiWiki::beautify_urlpath("./bleh"), "./bleh");
+is(IkiWiki::beautify_urlpath("foo/index.HTML"), "./foo/");
+is(IkiWiki::beautify_urlpath("index.HTML"), "./");
+is(IkiWiki::beautify_urlpath("../index.HTML"), "../");
+$IkiWiki::config{usedirs} = 0;
+is(IkiWiki::beautify_urlpath("foo/index.HTML"), "./foo/index.HTML");
diff --git a/t/git.t b/t/git.t
index f4e27c473c5279f6e5a389e000d74f66a5edf2be..f1c24b3598e1709d9d58a9f962df4fef1f12a3f1 100755 (executable)
--- a/t/git.t
+++ b/t/git.t
@@ -3,38 +3,36 @@ use warnings;
 use strict;
 
 my $dir;
-my $gitrepo;
 BEGIN {
        $dir="/tmp/ikiwiki-test-git.$$";
-       $gitrepo="$dir/repo";
        my $git=`which git`;
        chomp $git;
-       if (! -x $git || ! mkdir($dir) || ! mkdir($gitrepo)) {
+       if (! -x $git || ! mkdir($dir)) {
                eval q{
-                       use Test::More skip_all => "git not available or could not make test dirs"
+                       use Test::More skip_all => "git not available or could not make test dir"
                }
        }
 }
-use Test::More tests => 11;
+use Test::More tests => 18;
 
 BEGIN { use_ok("IkiWiki"); }
 
 %config=IkiWiki::defaultconfig();
 $config{rcs} = "git";
 $config{srcdir} = "$dir/src";
+IkiWiki::loadplugins();
 IkiWiki::checkconfig();
 
-system "cd $gitrepo && git init >/dev/null 2>&1";
-system "cd $gitrepo && echo dummy > dummy; git add . >/dev/null 2>&1";
-system "cd $gitrepo && git commit -m Initial >/dev/null 2>&1";
-system "git clone -l -s $gitrepo $config{srcdir} >/dev/null 2>&1";
+ok (mkdir($config{srcdir}));
+is (system("./ikiwiki-makerepo git $config{srcdir} $dir/repo"), 0);
 
 my @changes;
 @changes = IkiWiki::rcs_recentchanges(3);
 
 is($#changes, 0); # counts for dummy commit during repo creation
-is($changes[0]{message}[0]{"line"}, "Initial");
-is($changes[0]{pages}[0]{"page"}, "dummy");
+# ikiwiki-makerepo's first commit is setting up the .gitignore
+is($changes[0]{message}[0]{"line"}, "initial commit");
+is($changes[0]{pages}[0]{"page"}, ".gitignore");
 
 # Web commit
 my $test1 = readfile("t/test1.mdwn");
@@ -46,7 +44,7 @@ IkiWiki::rcs_commit("test1.mdwn", "Added the first page", "moo");
 
 is($#changes, 1);
 is($changes[0]{message}[0]{"line"}, "Added the first page");
-is($changes[0]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test1");
        
 # Manual commit
 my $message = "Added the second page";
@@ -61,8 +59,32 @@ system "cd $config{srcdir}; git push origin >/dev/null 2>&1";
 
 is($#changes, 2);
 is($changes[0]{message}[0]{"line"}, $message);
-is($changes[0]{pages}[0]{"page"}, "test2.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test2");
 
-is($changes[1]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[1]{pages}[0]{"page"}, "test1");
+
+# Renaming
+
+writefile('test3.mdwn', $config{srcdir}, $test1);
+IkiWiki::rcs_add("test3.mdwn");
+IkiWiki::rcs_rename("test3.mdwn", "test4.mdwn");
+IkiWiki::rcs_commit_staged("Added the 4th page", "moo", "Joe User");
+
+@changes = IkiWiki::rcs_recentchanges(4);
+
+is($#changes, 3);
+is($changes[0]{pages}[0]{"page"}, "test4");
+
+ok(mkdir($config{srcdir}."/newdir"));
+IkiWiki::rcs_rename("test4.mdwn", "newdir/test5.mdwn");
+IkiWiki::rcs_commit_staged("Added the 5th page", "moo", "Joe User");
+
+@changes = IkiWiki::rcs_recentchanges(4);
+
+is($#changes, 3);
+is($changes[0]{pages}[0]{"page"}, "newdir/test5");
+
+IkiWiki::rcs_remove("newdir/test5.mdwn");
+IkiWiki::rcs_commit_staged("Remove the 5th page", "moo", "Joe User");
 
 system "rm -rf $dir";
index 66e90d8e3bc91d8323283be6c10d313fa603beef..3faf44154203aaa88a0bef7e1ad152311497747b 100755 (executable)
--- a/t/html.t
+++ b/t/html.t
@@ -6,7 +6,7 @@ use Test::More;
 my @pages;
 
 BEGIN {
-       @pages=qw(index todo features news plugins/map security);
+       @pages=qw(index features news plugins/map security);
        if (! -x "/usr/bin/validate") {
                plan skip_all => "/usr/bin/validate html validator not present";
        }
diff --git a/t/htmlbalance.t b/t/htmlbalance.t
new file mode 100755 (executable)
index 0000000..e5a5db0
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+BEGIN {
+       eval q{
+               use HTML::TreeBuilder;
+       };
+       if ($@) {
+               eval q{use Test::More skip_all => "HTML::TreeBuilder not available"};
+       }
+       else {
+               eval q{use Test::More tests => 7};
+       }
+       use_ok("IkiWiki::Plugin::htmlbalance");
+}
+
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "<br></br>"), "<br />");
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "<div><p b=\"c\">hello world</div>"), "<div><p b=\"c\">hello world</p></div>");
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "<a></a></a>"), "<a></a>");
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "<b>foo <a</b>"), "<b>foo </b>");
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "<b> foo <a</a></b>"), "<b> foo </b>");
+is(IkiWiki::Plugin::htmlbalance::sanitize(content => "a>"), "a&gt;");
index e79609902a5856f4a58cc47dec9477df074a0030..2f23524a7cc987cf82329a2035370840d36ee3ef 100755 (executable)
--- a/t/index.t
+++ b/t/index.t
@@ -32,9 +32,9 @@ $renderedfiles{"bar.png"}=["bar.png"];
 $links{"Foo"}=["bar.png"];
 $links{"bar"}=["Foo", "new-page"];
 $links{"bar.png"}=[];
-$depends{"Foo"}="";
-$depends{"bar"}="foo*";
-$depends{"bar.png"}="";
+$depends{"Foo"}={};
+$depends{"bar"}={"foo*" => 1};
+$depends{"bar.png"}={};
 $pagestate{"bar"}{meta}{title}="a page about bar";
 $pagestate{"bar"}{meta}{moo}="mooooo";
 # only loaded plugins save state, so this should not be saved out
@@ -80,9 +80,9 @@ is_deeply(\%links, {
        "bar.png" => [],
 }, "%links loaded correctly");
 is_deeply(\%depends, {
-       Foo => "",
-       bar => "foo*",
-       "bar.png" => "",
+       Foo => {},
+       bar => {"foo*" => 1},
+       "bar.png" => {},
 }, "%depends loaded correctly");
 is_deeply(\%pagestate, {
        bar => {
diff --git a/t/linkpage.t b/t/linkpage.t
new file mode 100755 (executable)
index 0000000..8085de1
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 7;
+
+BEGIN { use_ok("IkiWiki"); }
+
+is(linkpage("foo bar"), "foo_bar");
+is(linkpage("foo bar baz"), "foo_bar_baz");
+is(linkpage("foo bar/baz"), "foo_bar/baz");
+is(linkpage("foo bar&baz"), "foo_bar__38__baz");
+is(linkpage("foo bar & baz"), "foo_bar___38___baz");
+is(linkpage("foo bar_baz"), "foo_bar_baz");
index da4e2beaa78fc3e46284f8e8b309cbf1d74b9de4..954b17526bd31c987fa21a0c77fa64e98b4d3139 100755 (executable)
@@ -19,6 +19,7 @@ BEGIN { use_ok("IkiWiki"); }
 %config=IkiWiki::defaultconfig();
 $config{rcs} = "mercurial";
 $config{srcdir} = "$dir/repo";
+IkiWiki::loadplugins();
 IkiWiki::checkconfig();
 
 system "hg init $config{srcdir}";
@@ -34,7 +35,7 @@ my @changes;
 
 is($#changes, 0);
 is($changes[0]{message}[0]{"line"}, "Added the first page");
-is($changes[0]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test1");
 is($changes[0]{user}, "Joe User");
        
 # Manual commit
@@ -52,9 +53,9 @@ system "hg commit -R $config{srcdir} -u \"$user\" -m \"$message\" -d \"0 0\"";
 is($#changes, 1);
 is($changes[0]{message}[0]{"line"}, $message);
 is($changes[0]{user}, $username);
-is($changes[0]{pages}[0]{"page"}, "test2.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test2");
 
-is($changes[1]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[1]{pages}[0]{"page"}, "test1");
 
 my $ctime = IkiWiki::rcs_getctime("test2.mdwn");
 is($ctime, 0);
diff --git a/t/openiduser.t b/t/openiduser.t
new file mode 100755 (executable)
index 0000000..52d8794
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+BEGIN {
+       eval q{
+               use Net::OpenID::VerifiedIdentity;
+       };
+       if ($@) {
+               eval q{use Test::More skip_all => "Net::OpenID::VerifiedIdentity not available"};
+       }
+       else {
+               eval q{use Test::More tests => 9};
+       }
+       use_ok("IkiWiki::Plugin::openid");
+}
+
+# Some typical examples:
+
+# This test, when run by Test::Harness using perl -w, exposes a warning in
+# Net::OpenID::VerifiedIdentity. Normally that warning is not displayed, as
+# that module does not use warnings. To avoid cluttering the test output,
+# disable the -w switch temporarily.
+$^W=0;
+is(IkiWiki::openiduser('http://josephturian.blogspot.com'), 'josephturian [blogspot.com]');
+$^W=1;
+
+is(IkiWiki::openiduser('http://yam655.livejournal.com/'), 'yam655 [livejournal.com]');
+is(IkiWiki::openiduser('http://id.mayfirst.org/jamie/'), 'jamie [id.mayfirst.org]');
+
+# and some less typical ones taken from the ikiwiki commit history
+
+is(IkiWiki::openiduser('http://thm.id.fedoraproject.org/'), 'thm [id.fedoraproject.org]');
+is(IkiWiki::openiduser('http://dtrt.org/'), 'dtrt.org');
+is(IkiWiki::openiduser('http://alcopop.org/me/openid/'), 'openid [alcopop.org/me]');
+is(IkiWiki::openiduser('http://id.launchpad.net/882/bielawski1'), 'bielawski1 [id.launchpad.net/882]');
+is(IkiWiki::openiduser('http://technorati.com/people/technorati/drajt'), 'drajt [technorati.com/people/technorati]');
index 96e6a87f11e87b4e8e945ccc077dc40a2e826ef9..540d10f4c0bcc4a4a020674a0574e89ce42b3214 100755 (executable)
@@ -1,14 +1,35 @@
 #!/usr/bin/perl
 use warnings;
 use strict;
-use Test::More tests => 5;
+use Test::More tests => 19;
 
 BEGIN { use_ok("IkiWiki"); }
 
-# Used internally.
-$IkiWiki::hooks{htmlize}{mdwn}=1;
-
+# define mdwn as an extension
+$IkiWiki::hooks{htmlize}{mdwn}={};
+is(pagetype("foo.mdwn"), "mdwn");
 is(pagename("foo.mdwn"), "foo");
+is(pagetype("foo/bar.mdwn"), "mdwn");
 is(pagename("foo/bar.mdwn"), "foo/bar");
+
+# bare files get the full filename as page name, undef type
+is(pagetype("foo.png"), undef);
 is(pagename("foo.png"), "foo.png");
+is(pagetype("foo/bar.png"), undef);
+is(pagename("foo/bar.png"), "foo/bar.png");
+is(pagetype("foo"), undef);
 is(pagename("foo"), "foo");
+
+# keepextension preserves the extension in the page name
+$IkiWiki::hooks{htmlize}{txt}={keepextension => 1};
+is(pagename("foo.txt"), "foo.txt");
+is(pagetype("foo.txt"), "txt");
+is(pagename("foo/bar.txt"), "foo/bar.txt");
+is(pagetype("foo/bar.txt"), "txt");
+
+# noextension makes extensionless files be treated as first-class pages
+$IkiWiki::hooks{htmlize}{Makefile}={noextension =>1};
+is(pagetype("Makefile"), "Makefile");
+is(pagename("Makefile"), "Makefile");
+is(pagetype("foo/Makefile"), "Makefile");
+is(pagename("foo/Makefile"), "foo/Makefile");
index 9d55737470fd122b42aeb2d64c53d378e7501e95..64408f4898cb8b0671ba24fb7f2f8433e87dacae 100755 (executable)
@@ -6,6 +6,8 @@ use Test::More tests => 54;
 BEGIN { use_ok("IkiWiki"); }
 
 ok(pagespec_match("foo", "*"));
+ok(!pagespec_match("foo", ""));
+ok(pagespec_match("foo", "!bar"));
 ok(pagespec_match("page", "?ag?"));
 ok(! pagespec_match("page", "?a?g?"));
 ok(pagespec_match("foo.png", "*.*"));
@@ -18,6 +20,15 @@ ok(! pagespec_match("foo", "* and !foo"));
 ok(! pagespec_match("foo", "foo and !foo"));
 ok(! pagespec_match("foo.png", "* and !*.*"));
 ok(pagespec_match("foo", "(bar or ((meep and foo) or (baz or foo) or beep))"));
+ok(pagespec_match("foo", "(
+       bar
+       or (
+               (meep and foo)
+               or
+               (baz or foo)
+               or beep
+       )
+)"), "multiline complex pagespec");
 ok(! pagespec_match("a/foo", "foo", location => "a/b"), "nonrelative fail");
 ok(! pagespec_match("foo", "./*", location => "a/b"), "relative fail");
 ok(pagespec_match("a/foo", "./*", location => "a/b"), "relative");
@@ -26,6 +37,8 @@ ok(pagespec_match("a/foo", "./*", "a/b"), "relative oldstyle call");
 ok(pagespec_match("foo", "./*", location => "a"), "relative toplevel");
 ok(pagespec_match("foo/bar", "*", location => "baz"), "absolute");
 ok(! pagespec_match("foo", "foo and bar"), "foo and bar");
+ok(pagespec_match("{f}oo", "{*}*"), "curly match");
+ok(! pagespec_match("foo", "{*}*"), "curly !match");
 
 # The link and backlink stuff needs this.
 $config{userdir}="";
@@ -38,6 +51,7 @@ $links{"bugs/bar"}=[qw{done}];
 $links{"done"}=[];
 $links{"examples/softwaresite/bugs/fails_to_frobnicate"}=[qw{done}];
 $links{"examples/softwaresite/bugs/done"}=[];
+$links{"ook"}=[qw{/blog/tags/foo}];
 
 ok(pagespec_match("foo", "link(bar)"), "link");
 ok(pagespec_match("foo", "link(ba?)"), "glob link");
@@ -53,6 +67,8 @@ ok(pagespec_match("bar", "backlink(foo)"), "backlink");
 ok(! pagespec_match("quux", "backlink(foo)"), "failed backlink");
 ok(! pagespec_match("bar", ""), "empty pagespec should match nothing");
 ok(! pagespec_match("bar", "           "), "blank pagespec should match nothing");
+ok(pagespec_match("ook", "link(blog/tags/foo)"), "link internal absolute success");
+ok(pagespec_match("ook", "link(/blog/tags/foo)"), "link explicit absolute success");
 
 $IkiWiki::pagectime{foo}=1154532692; # Wed Aug  2 11:26 EDT 2006
 $IkiWiki::pagectime{bar}=1154532695; # after
@@ -72,12 +88,3 @@ ok(! pagespec_match("foo", "no_such_function(foo)"), "foo");
 my $ret=pagespec_match("foo", "(invalid");
 ok(! $ret, "syntax error");
 ok($ret =~ /syntax error/, "error message");
-
-# old style globlists
-ok(pagespec_match("foo", "foo bar"), "simple list");
-ok(pagespec_match("bar", "foo bar"), "simple list 2");
-ok(pagespec_match("foo", "f?? !foz"));
-ok(! pagespec_match("foo", "f?? !foo"));
-ok(! pagespec_match("foo", "* !foo"));
-ok(! pagespec_match("foo", "foo !foo"));
-ok(! pagespec_match("foo.png", "* !*.*"));
diff --git a/t/pagespec_merge.t b/t/pagespec_merge.t
deleted file mode 100755 (executable)
index cbb0621..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/perl
-use warnings;
-use strict;
-use Test::More tests => 25;
-
-BEGIN { use_ok("IkiWiki"); }
-
-sub same {
-       my $a=shift;
-       my $b=shift;
-       my $match=shift;
-       
-       my $imatch=(pagespec_match($match, $a) ||
-                   pagespec_match($match, $b));
-       my $cmatch=pagespec_match($match, IkiWiki::pagespec_merge($a, $b));
-       
-       return $imatch == $cmatch;
-}
-
-ok(same("foo", "bar", "foo"), "basic match 1");
-ok(same("foo", "bar", "bar"), "basic match 2");
-ok(same("foo", "bar", "foobar"), "basic failed match");
-ok(same("foo", "!bar", "foo"), "basic match with inversion");
-ok(same("foo", "!bar", "bar"), "basic failed match with inversion");
-ok(same("!foo", "bar", "foo"), "basic failed match with inversion 2");
-ok(same("!foo", "bar", "bar"), "basic match with inversion 2");
-ok(same("!foo", "!bar", "foo"), "double inversion failed match");
-ok(same("!foo", "!bar", "bar"), "double inversion failed match 2");
-ok(same("*", "!bar", "foo"), "glob+inversion match");
-ok(same("*", "!bar", "bar"), "matching glob and matching inversion");
-ok(same("* !foo", "!bar", "bar"), "matching glob and matching inversion");
-ok(same("* !foo", "!bar", "foo"), "matching glob with matching inversion and non-matching inversion");
-ok(same("* !foo", "!foo", "foo"), "matching glob with matching inversion and matching inversion");
-ok(same("b??", "!b??", "bar"), "matching glob and matching inverted glob");
-ok(same("f?? !f??", "!bar", "bar"), "matching glob and matching inverted glob");
-ok(same("b??", "!b?z", "bar"), "matching glob and non-matching inverted glob");
-ok(same("f?? !f?z", "!bar", "bar"), "matching glob and non-matching inverted glob");
-ok(same("!foo bar baz", "!bar", "bar"), "matching list and matching inversion");
-ok(pagespec_match("foo/Discussion",
-       IkiWiki::pagespec_merge("* !*/Discussion", "*/Discussion")), "should match");
-ok(same("* !*/Discussion", "*/Discussion", "foo/Discussion"), "Discussion merge 1");
-ok(same("*/Discussion", "* !*/Discussion", "foo/Discussion"), "Discussion merge 2");
-ok(same("*/Discussion !*/bar", "*/bar !*/Discussion", "foo/Discussion"), "bidirectional merge 1");
-ok(same("*/Discussion !*/bar", "*/bar !*/Discussion", "foo/bar"), "bidirectional merge 2");
index 37adba144f33b26d31bbfc84ad313c998d8ecf8e..d9aa620633d6b64e393a366c19a510b3e851542f 100755 (executable)
@@ -5,9 +5,9 @@ use Test::More tests => 7;
 
 BEGIN { use_ok("IkiWiki"); }
 
-is(IkiWiki::pagetitle("foo_bar"), "foo bar");
-is(IkiWiki::pagetitle("foo_bar_baz"), "foo bar baz");
-is(IkiWiki::pagetitle("foo_bar__33__baz"), "foo bar&#33;baz");
-is(IkiWiki::pagetitle("foo_bar__1234__baz"), "foo bar&#1234;baz");
-is(IkiWiki::pagetitle("foo_bar___33___baz"), "foo bar &#33; baz");
-is(IkiWiki::pagetitle("foo_bar___95___baz"), "foo bar &#95; baz");
+is(pagetitle("foo_bar"), "foo bar");
+is(pagetitle("foo_bar_baz"), "foo bar baz");
+is(pagetitle("foo_bar__33__baz"), "foo bar&#33;baz");
+is(pagetitle("foo_bar__1234__baz"), "foo bar&#1234;baz");
+is(pagetitle("foo_bar___33___baz"), "foo bar &#33; baz");
+is(pagetitle("foo_bar___95___baz"), "foo bar &#95; baz");
diff --git a/t/pagetype.mdwn b/t/pagetype.mdwn
deleted file mode 100755 (executable)
index 76cacd8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/perl
-use warnings;
-use strict;
-use Test::More tests => 5;
-
-BEGIN { use_ok("IkiWiki"); }
-
-# Used internally.
-$IkiWiki::hooks{htmlize}{mdwn}=1;
-
-is(pagetype("foo.mdwn"), "mdwn");
-is(pagetype("foo/bar.mdwn"), "mdwn");
-is(pagename("foo.png"), undef);
-is(pagename("foo"), undef);
diff --git a/t/parentlinks.t b/t/parentlinks.t
new file mode 100755 (executable)
index 0000000..593937a
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+# -*- cperl-indent-level: 8; -*-
+# Testcases for the Ikiwiki parentlinks plugin.
+
+use warnings;
+use strict;
+use Test::More 'no_plan';
+
+my %expected;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# Init
+%config=IkiWiki::defaultconfig();
+$config{srcdir}=$config{destdir}="/dev/null";
+$config{underlaydir}="underlays/basewiki";
+$config{templatedir}="t/parentlinks/templates";
+IkiWiki::loadplugins();
+IkiWiki::checkconfig();
+
+# Test data
+$expected{'parentlinks'} =
+  {
+   "" => [],
+   "ikiwiki" => [],
+   "ikiwiki/pagespec" =>
+     [ {depth => 0, height => 2, },
+       {depth => 1, height => 1, },
+     ],
+   "ikiwiki/pagespec/attachment" =>
+     [ {depth => 0, height => 3, depth_0 => 1, height_3 => 1},
+       {depth => 1, height => 2, },
+       {depth => 2, height => 1, },
+     ],
+  };
+
+# Test function
+sub test_loop($$) {
+       my $loop=shift;
+       my $expected=shift;
+       my $template;
+       my %params;
+
+       ok($template=template('parentlinks.tmpl'), "template created");
+       ok($params{template}=$template, "params populated");
+
+       while ((my $page, my $exp) = each %{$expected}) {
+               my @path=(split("/", $page));
+               my $pagedepth=@path;
+               my $msgprefix="$page $loop";
+
+               # manually run the plugin hook
+               $params{page}=$page;
+               $template->clear_params();
+               IkiWiki::Plugin::parentlinks::pagetemplate(%params);
+               my $res=$template->param($loop);
+
+               is(scalar(@$res), $pagedepth, "$msgprefix: path length");
+               # logic & arithmetic validation tests
+               for (my $i=0; $i<$pagedepth; $i++) {
+                       my $r=$res->[$i];
+                       is($r->{height}, $pagedepth - $r->{depth},
+                          "$msgprefix\[$i\]: height = pagedepth - depth");
+                       ok($r->{depth} ge 0, "$msgprefix\[$i\]: depth>=0");
+                       ok($r->{height} ge 0, "$msgprefix\[$i\]: height>=0");
+               }
+               # comparison tests, iff the test-suite has been written
+               if (scalar(@$exp) eq $pagedepth) {
+                       for (my $i=0; $i<$pagedepth; $i++) {
+                               my $e=$exp->[$i];
+                               my $r=$res->[$i];
+                               map { is($r->{$_}, $e->{$_}, "$msgprefix\[$i\]: $_"); } keys %$e;
+                       }
+               }
+               # else {
+               #       diag("Testsuite is incomplete for ($page,$loop); cannot run comparison tests.");
+               # }
+       }
+}
+
+# Main
+test_loop('parentlinks', $expected{'parentlinks'});
diff --git a/t/parentlinks/templates/parentlinks.tmpl b/t/parentlinks/templates/parentlinks.tmpl
new file mode 100644 (file)
index 0000000..3ca3b00
--- /dev/null
@@ -0,0 +1,4 @@
+<!-- This template file only has to "use" the loops tested by parentlinks.t -->
+
+<TMPL_LOOP NAME="PARENTLINKS">
+</TMPL_LOOP>
diff --git a/t/permalink.t b/t/permalink.t
new file mode 100755 (executable)
index 0000000..b49b983
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More 'no_plan';
+
+ok(! system("mkdir t/tmp"));
+ok(! system("make -s ikiwiki.out"));
+ok(! system("perl -I. ./ikiwiki.out -plugin inline -url=http://example.com -cgiurl=http://example.com/ikiwiki.cgi -rss -atom -underlaydir=underlays/basewiki -templatedir=templates t/tinyblog t/tmp/out"));
+# This guid should never, ever change, for any reason whatsoever!
+my $guid="http://example.com/post/";
+ok(length `grep '<guid>$guid</guid>' t/tmp/out/index.rss`);
+ok(length `grep '<id>$guid</id>' t/tmp/out/index.atom`);
+ok(! system("rm -rf t/tmp t/tinyblog/.ikiwiki"));
diff --git a/t/po.t b/t/po.t
new file mode 100755 (executable)
index 0000000..b6885a3
--- /dev/null
+++ b/t/po.t
@@ -0,0 +1,177 @@
+#!/usr/bin/perl
+# -*- cperl-indent-level: 8; -*-
+use warnings;
+use strict;
+use File::Temp qw{tempdir};
+
+BEGIN {
+       unless (eval { require Locale::Po4a::Chooser }) {
+               eval q{
+                       use Test::More skip_all => "Locale::Po4a::Chooser::new is not available"
+               }
+       }
+       unless (eval { require Locale::Po4a::Po }) {
+               eval q{
+                       use Test::More skip_all => "Locale::Po4a::Po::new is not available"
+               }
+       }
+}
+
+use Test::More tests => 65;
+
+BEGIN { use_ok("IkiWiki"); }
+
+my $msgprefix;
+
+my $dir = tempdir("ikiwiki-test-po.XXXXXXXXXX",
+                 DIR => File::Spec->tmpdir,
+                 CLEANUP => 1);
+
+### Init
+%config=IkiWiki::defaultconfig();
+$config{srcdir} = "$dir/src";
+$config{destdir} = "$dir/dst";
+$config{discussion} = 0;
+$config{po_master_language} = { code => 'en',
+                               name => 'English'
+                             };
+$config{po_slave_languages} = {
+                              es => 'Castellano',
+                              fr => "Français"
+                             };
+$config{po_translatable_pages}='index or test1 or test2 or translatable';
+$config{po_link_to}='negotiated';
+IkiWiki::loadplugins();
+IkiWiki::checkconfig();
+ok(IkiWiki::loadplugin('po'), "po plugin loaded");
+
+### seed %pagesources and %pagecase
+$pagesources{'index'}='index.mdwn';
+$pagesources{'index.fr'}='index.fr.po';
+$pagesources{'index.es'}='index.es.po';
+$pagesources{'test1'}='test1.mdwn';
+$pagesources{'test1.fr'}='test1.fr.po';
+$pagesources{'test2'}='test2.mdwn';
+$pagesources{'test2.es'}='test2.es.po';
+$pagesources{'test2.fr'}='test2.fr.po';
+$pagesources{'test3'}='test3.mdwn';
+$pagesources{'test3.es'}='test3.es.mdwn';
+$pagesources{'translatable'}='translatable.mdwn';
+$pagesources{'translatable.fr'}='translatable.fr.po';
+$pagesources{'translatable.es'}='translatable.es.po';
+$pagesources{'nontranslatable'}='nontranslatable.mdwn';
+foreach my $page (keys %pagesources) {
+    $IkiWiki::pagecase{lc $page}=$page;
+}
+
+### populate srcdir
+writefile('index.mdwn', $config{srcdir}, '[[translatable]] [[nontranslatable]]');
+writefile('test1.mdwn', $config{srcdir}, 'test1 content');
+writefile('test2.mdwn', $config{srcdir}, 'test2 content');
+writefile('test3.mdwn', $config{srcdir}, 'test3 content');
+writefile('translatable.mdwn', $config{srcdir}, '[[nontranslatable]]');
+writefile('nontranslatable.mdwn', $config{srcdir}, '[[/]] [[translatable]]');
+
+### istranslatable/istranslation
+# we run these tests twice because memoization attempts made them
+# succeed once every two tries...
+foreach (1, 2) {
+ok(IkiWiki::Plugin::po::istranslatable('index'), "index is translatable");
+ok(IkiWiki::Plugin::po::istranslatable('/index'), "/index is translatable");
+ok(! IkiWiki::Plugin::po::istranslatable('index.fr'), "index.fr is not translatable");
+ok(! IkiWiki::Plugin::po::istranslatable('index.es'), "index.es is not translatable");
+ok(! IkiWiki::Plugin::po::istranslatable('/index.fr'), "/index.fr is not translatable");
+ok(! IkiWiki::Plugin::po::istranslation('index'), "index is not a translation");
+ok(IkiWiki::Plugin::po::istranslation('index.fr'), "index.fr is a translation");
+ok(IkiWiki::Plugin::po::istranslation('index.es'), "index.es is a translation");
+ok(IkiWiki::Plugin::po::istranslation('/index.fr'), "/index.fr is a translation");
+ok(IkiWiki::Plugin::po::istranslatable('test2'), "test2 is translatable");
+ok(! IkiWiki::Plugin::po::istranslation('test2'), "test2 is not a translation");
+ok(! IkiWiki::Plugin::po::istranslatable('test3'), "test3 is not translatable");
+ok(! IkiWiki::Plugin::po::istranslation('test3'), "test3 is not a translation");
+}
+
+### links
+require IkiWiki::Render;
+
+sub refresh_n_scan(@) {
+       my @masterfiles_rel=@_;
+       foreach my $masterfile_rel (@masterfiles_rel) {
+               my $masterfile=srcfile($masterfile_rel);
+               IkiWiki::scan($masterfile_rel);
+               next unless IkiWiki::Plugin::po::istranslatable(pagename($masterfile_rel));
+               my @pofiles=IkiWiki::Plugin::po::pofiles($masterfile);
+               IkiWiki::Plugin::po::refreshpot($masterfile);
+               IkiWiki::Plugin::po::refreshpofiles($masterfile, @pofiles);
+               map IkiWiki::scan(IkiWiki::abs2rel($_, $config{srcdir})), @pofiles;
+       }
+}
+
+$config{po_link_to}='negotiated';
+$msgprefix="links (po_link_to=negotiated)";
+refresh_n_scan('index.mdwn', 'translatable.mdwn', 'nontranslatable.mdwn');
+is_deeply(\@{$links{'index'}}, ['translatable', 'nontranslatable'], "$msgprefix index");
+is_deeply(\@{$links{'index.es'}}, ['translatable.es', 'nontranslatable'], "$msgprefix index.es");
+is_deeply(\@{$links{'index.fr'}}, ['translatable.fr', 'nontranslatable'], "$msgprefix index.fr");
+is_deeply(\@{$links{'translatable'}}, ['nontranslatable'], "$msgprefix translatable");
+is_deeply(\@{$links{'translatable.es'}}, ['nontranslatable'], "$msgprefix translatable.es");
+is_deeply(\@{$links{'translatable.fr'}}, ['nontranslatable'], "$msgprefix translatable.fr");
+is_deeply(\@{$links{'nontranslatable'}}, ['/', 'translatable', 'translatable.fr', 'translatable.es'], "$msgprefix nontranslatable");
+
+$config{po_link_to}='current';
+$msgprefix="links (po_link_to=current)";
+refresh_n_scan('index.mdwn', 'translatable.mdwn', 'nontranslatable.mdwn');
+is_deeply(\@{$links{'index'}}, ['translatable', 'nontranslatable'], "$msgprefix index");
+is_deeply(\@{$links{'index.es'}}, [ map bestlink('index.es', $_), ('translatable.es', 'nontranslatable')], "$msgprefix index.es");
+is_deeply(\@{$links{'index.fr'}}, [ map bestlink('index.fr', $_), ('translatable.fr', 'nontranslatable')], "$msgprefix index.fr");
+is_deeply(\@{$links{'translatable'}}, [bestlink('translatable', 'nontranslatable')], "$msgprefix translatable");
+is_deeply(\@{$links{'translatable.es'}}, ['nontranslatable'], "$msgprefix translatable.es");
+is_deeply(\@{$links{'translatable.fr'}}, ['nontranslatable'], "$msgprefix translatable.fr");
+is_deeply(\@{$links{'nontranslatable'}}, ['/', 'translatable', 'translatable.fr', 'translatable.es'], "$msgprefix nontranslatable");
+
+### targetpage
+$config{usedirs}=0;
+$msgprefix="targetpage (usedirs=0)";
+is(targetpage('test1', 'html'), 'test1.en.html', "$msgprefix test1");
+is(targetpage('test1.fr', 'html'), 'test1.fr.html', "$msgprefix test1.fr");
+$config{usedirs}=1;
+$msgprefix="targetpage (usedirs=1)";
+is(targetpage('index', 'html'), 'index.en.html', "$msgprefix index");
+is(targetpage('index.fr', 'html'), 'index.fr.html', "$msgprefix index.fr");
+is(targetpage('test1', 'html'), 'test1/index.en.html', "$msgprefix test1");
+is(targetpage('test1.fr', 'html'), 'test1/index.fr.html', "$msgprefix test1.fr");
+is(targetpage('test3', 'html'), 'test3/index.html', "$msgprefix test3 (non-translatable page)");
+is(targetpage('test3.es', 'html'), 'test3.es/index.html', "$msgprefix test3.es (non-translatable page)");
+
+### urlto -> index
+$config{po_link_to}='current';
+$msgprefix="urlto (po_link_to=current)";
+is(urlto('', 'index'), './index.en.html', "$msgprefix index -> ''");
+is(urlto('', 'nontranslatable'), '../index.en.html', "$msgprefix nontranslatable -> ''");
+is(urlto('', 'translatable.fr'), '../index.fr.html', "$msgprefix translatable.fr -> ''");
+$config{po_link_to}='negotiated';
+$msgprefix="urlto (po_link_to=negotiated)";
+is(urlto('', 'index'), './', "$msgprefix index -> ''");
+is(urlto('', 'nontranslatable'), '../', "$msgprefix nontranslatable -> ''");
+is(urlto('', 'translatable.fr'), '../', "$msgprefix translatable.fr -> ''");
+
+### bestlink
+$config{po_link_to}='current';
+$msgprefix="bestlink (po_link_to=current)";
+is(bestlink('test1.fr', 'test2'), 'test2.fr', "$msgprefix test1.fr -> test2");
+is(bestlink('test1.fr', 'test2.es'), 'test2.es', "$msgprefix test1.fr -> test2.es");
+$config{po_link_to}='negotiated';
+$msgprefix="bestlink (po_link_to=negotiated)";
+is(bestlink('test1.fr', 'test2'), 'test2.fr', "$msgprefix test1.fr -> test2");
+is(bestlink('test1.fr', 'test2.es'), 'test2.es', "$msgprefix test1.fr -> test2.es");
+
+### beautify_urlpath
+$config{po_link_to}='default';
+$msgprefix="beautify_urlpath (po_link_to=default)";
+is(IkiWiki::beautify_urlpath('test1/index.en.html'), './test1/index.en.html', "$msgprefix test1/index.en.html");
+is(IkiWiki::beautify_urlpath('test1/index.fr.html'), './test1/index.fr.html', "$msgprefix test1/index.fr.html");
+$config{po_link_to}='negotiated';
+$msgprefix="beautify_urlpath (po_link_to=negotiated)";
+is(IkiWiki::beautify_urlpath('test1/index.html'), './test1/', "$msgprefix test1/index.html");
+is(IkiWiki::beautify_urlpath('test1/index.en.html'), './test1/', "$msgprefix test1/index.en.html");
+is(IkiWiki::beautify_urlpath('test1/index.fr.html'), './test1/', "$msgprefix test1/index.fr.html");
index 7699f56baaa77737115fabe033e73e06383966e8..e5026ed64b575ba8ed2215e468bb322d4086f020 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 use warnings;
 use strict;
-use Test::More tests => 19;
+use Test::More tests => 21;
 
 BEGIN { use_ok("IkiWiki"); }
 
@@ -51,6 +51,11 @@ is(IkiWiki::preprocess("foo", "foo", '[[foo a="""'.$multiline.'""" b="foo"]]', 0
        "foo(a => $multiline, b => foo)");
 is(IkiWiki::preprocess("foo", "foo", '[[foo a="""'."\n".$multiline."\n".'""" b="foo"]]', 0, 0),
        "foo(a => $multiline, b => foo)", "leading/trailing newline stripped");
+my $long='[[foo a="""'.("a" x 100000).'';
+is(IkiWiki::preprocess("foo", "foo", $long, 0, 0), $long,
+       "unterminated triple-quoted string inside unterminated directive(should not warn about over-recursion)");
+is(IkiWiki::preprocess("foo", "foo", $long."]]", 0, 0), $long."]]",
+       "unterminated triple-quoted string is not treated as a bare word");
 
 TODO: {
        local $TODO = "nested strings not yet implemented";
diff --git a/t/renamepage.t b/t/renamepage.t
new file mode 100755 (executable)
index 0000000..a706cbb
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 21;
+use Encode;
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("IkiWiki::Plugin::link"); }
+
+%config=IkiWiki::defaultconfig();
+$config{srcdir}=$config{destdir}="/dev/null";
+IkiWiki::checkconfig();
+
+# tests of the link plugin's renamepage function
+sub try {
+       my ($page, $oldpage, $newpage, $content)=@_;
+
+       %IkiWiki::pagecase=();
+       %links=();
+       $IkiWiki::config{userdir}="foouserdir";
+       foreach my $page ($page, $oldpage, $newpage) {
+               $IkiWiki::pagecase{lc $page}=$page;
+               $links{$page}=[];
+       }
+
+       IkiWiki::Plugin::link::renamepage(
+                       page => $page, 
+                       oldpage => $oldpage,
+                       newpage => $newpage,
+                       content => $content,
+       );
+}
+is(try("z", "foo" => "bar", "[[xxx]]"), "[[xxx]]"); # unrelated link
+is(try("z", "foo" => "bar", "[[bar]]"), "[[bar]]"); # link already to new page
+is(try("z", "foo" => "bar", "[[foo]]"), "[[bar]]"); # basic conversion to new page name
+is(try("z", "foo" => "bar", "[[/foo]]"), "[[/bar]]"); # absolute link
+is(try("z", "foo" => "bar", "[[Foo]]"), "[[Bar]]"); # preserve case
+is(try("z", "x/foo" => "x/bar", "[[x/Foo]]"), "[[x/Bar]]"); # preserve case of subpage
+is(try("z", "foo" => "bar", "[[/Foo]]"), "[[/Bar]]"); # preserve case w/absolute
+is(try("z", "foo" => "bar", "[[foo]] [[xxx]]"), "[[bar]] [[xxx]]"); # 2 links, 1 converted
+is(try("z", "foo" => "bar", "[[xxx|foo]]"), "[[xxx|bar]]"); # conversion w/text
+is(try("z", "foo" => "bar", "[[foo#anchor]]"), "[[bar#anchor]]"); # with anchor
+is(try("z", "foo" => "bar", "[[xxx|foo#anchor]]"), "[[xxx|bar#anchor]]"); # with anchor
+is(try("z", "foo" => "bar", "[[!moo ]]"), "[[!moo ]]"); # preprocessor directive unchanged
+is(try("bugs", "bugs/foo" => "wishlist/bar", "[[foo]]"), "[[wishlist/bar]]"); # subpage link
+is(try("z", "foo_bar" => "bar", "[[foo_bar]]"), "[[bar]]"); # old link with underscore
+is(try("z", "foo" => "bar_foo", "[[foo]]"), "[[bar_foo]]"); # new link with underscore
+is(try("z", "foo_bar" => "bar_foo", "[[foo_bar]]"), "[[bar_foo]]"); # both with underscore
+is(try("z", "foo" => "bar__".ord("(")."__", "[[foo]]"), "[[bar(]]"); # new link with escaped chars
+is(try("z", "foo__".ord("(")."__" => "bar(", "[[foo(]]"), "[[bar(]]"); # old link with escaped chars
+is(try("z", "foo__".ord("(")."__" => "bar__".ord(")")."__", "[[foo(]]"), "[[bar)]]"); # both with escaped chars
diff --git a/t/svn.t b/t/svn.t
index eba8c65ef1d025b224ed7d8952fb71ae48754857..5223b4409416911276974a57a823224cc4912df6 100755 (executable)
--- a/t/svn.t
+++ b/t/svn.t
@@ -23,6 +23,7 @@ $config{rcs} = "svn";
 $config{srcdir} = "$dir/src";
 $config{svnrepo} = "$dir/repo";
 $config{svnpath} = "trunk";
+IkiWiki::loadplugins();
 IkiWiki::checkconfig();
 
 my $svnrepo = "$dir/repo";
@@ -42,7 +43,7 @@ my @changes;
 
 is($#changes, 0);
 is($changes[0]{message}[0]{"line"}, "Added the first page");
-is($changes[0]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test1");
        
 # Manual commit
 my $message = "Added the second page";
@@ -55,8 +56,8 @@ system "svn commit $config{srcdir}/test2.mdwn -m \"$message\" >/dev/null";
 @changes = IkiWiki::rcs_recentchanges(3);
 is($#changes, 1);
 is($changes[0]{message}[0]{"line"}, $message);
-is($changes[0]{pages}[0]{"page"}, "test2.mdwn");
-is($changes[1]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test2");
+is($changes[1]{pages}[0]{"page"}, "test1");
 
 # extra slashes in the path shouldn't break things
 $config{svnpath} = "/trunk//";
@@ -64,7 +65,7 @@ IkiWiki::checkconfig();
 @changes = IkiWiki::rcs_recentchanges(3);
 is($#changes, 1);
 is($changes[0]{message}[0]{"line"}, $message);
-is($changes[0]{pages}[0]{"page"}, "test2.mdwn");
-is($changes[1]{pages}[0]{"page"}, "test1.mdwn");
+is($changes[0]{pages}[0]{"page"}, "test2");
+is($changes[1]{pages}[0]{"page"}, "test1");
 
 system "rm -rf $dir";
index 01346a33842d256ea6fd6f1d7b390f686ebbd8c7..a3760a2b2aa956b48bc1764dbff141335b0247ff 100755 (executable)
@@ -6,12 +6,13 @@ use Test::More;
 my @progs="ikiwiki.in";
 my @libs="IkiWiki.pm";
 # monotone, external, amazon_s3 skipped since they need perl modules
-push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v IkiWiki/Rcs/monotone.pm | grep -v IkiWiki/Plugin/external.pm | grep -v IkiWiki/Plugin/amazon_s3.pm`;
+push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm | grep -v monotone.pm | grep -v external.pm | grep -v amazon_s3.pm | grep -v po.pm`;
+push @libs, 'IkiWiki/Plugin/skeleton.pm.example';
 
 plan(tests => (@progs + @libs));
 
 foreach my $file (@progs) {
-        ok(system("perl -T -c $file >/dev/null 2>&1") eq 0, $file);
+        ok(system("perl -c $file >/dev/null 2>&1") eq 0, $file);
 }
 foreach my $file (@libs) {
         ok(system("perl -c $file >/dev/null 2>&1") eq 0, $file);
diff --git a/t/tinyblog/index.mdwn b/t/tinyblog/index.mdwn
new file mode 100644 (file)
index 0000000..72ba784
--- /dev/null
@@ -0,0 +1 @@
+[[!inline pages="post" rss=yes]]
diff --git a/t/tinyblog/post.mdwn b/t/tinyblog/post.mdwn
new file mode 100644 (file)
index 0000000..9eaeec7
--- /dev/null
@@ -0,0 +1 @@
+only post
index cc56db70c089caccb850b6760960627a3cd1c27a..5df33423e97052c4bad1ada8607fc8f44a505d4f 100755 (executable)
@@ -5,9 +5,9 @@ use Test::More tests => 7;
 
 BEGIN { use_ok("IkiWiki"); }
 
-is(IkiWiki::titlepage("foo bar"), "foo_bar");
-is(IkiWiki::titlepage("foo bar baz"), "foo_bar_baz");
-is(IkiWiki::titlepage("foo bar/baz"), "foo_bar/baz");
-is(IkiWiki::titlepage("foo bar&baz"), "foo_bar__38__baz");
-is(IkiWiki::titlepage("foo bar & baz"), "foo_bar___38___baz");
-is(IkiWiki::titlepage("foo bar_baz"), "foo_bar__95__baz");
+is(titlepage("foo bar"), "foo_bar");
+is(titlepage("foo bar baz"), "foo_bar_baz");
+is(titlepage("foo bar/baz"), "foo_bar/baz");
+is(titlepage("foo bar&baz"), "foo_bar__38__baz");
+is(titlepage("foo bar & baz"), "foo_bar___38___baz");
+is(titlepage("foo bar_baz"), "foo_bar__95__baz");
diff --git a/t/yesno.t b/t/yesno.t
new file mode 100755 (executable)
index 0000000..60a8c07
--- /dev/null
+++ b/t/yesno.t
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 10;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# note: yesno always accepts English even if localized.
+# So no need to bother setting locale to C.
+
+ok(IkiWiki::yesno("yes") == 1);
+ok(IkiWiki::yesno("Yes") == 1);
+ok(IkiWiki::yesno("YES") == 1);
+
+ok(IkiWiki::yesno("no") == 0);
+ok(IkiWiki::yesno("No") == 0);
+ok(IkiWiki::yesno("NO") == 0);
+
+ok(IkiWiki::yesno("1") == 1);
+ok(IkiWiki::yesno("0") == 0);
+ok(IkiWiki::yesno("mooooooooooo") == 0);
index 6bc789dfb29cfe241055ac51c4c392df6a6a50a4..28800e7632150329df26bc5e324b16a33a70d1ef 100644 (file)
@@ -1,7 +1,19 @@
 <p>
+<TMPL_IF NAME="PERMALINK">
+<a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a><br />
+<TMPL_ELSE>
 <a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a><br />
+</TMPL_IF>
 <i>
 Posted <TMPL_VAR CTIME>
+<TMPL_IF NAME="AUTHOR">
+by <span class="author">
+<TMPL_IF NAME="AUTHORURL">
+<a href="<TMPL_VAR AUTHORURL>"><TMPL_VAR AUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR AUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF>
 </i>
-
 </p>
index 1b1d686dddebb0d830e1c32e2c203cf5c03469ff..768695a2ca0d434e376cdf1b1de7325376b5aa49 100644 (file)
@@ -1,27 +1,27 @@
 <entry>
        <title><TMPL_VAR TITLE></title>
-       <id><TMPL_VAR URL></id>
+       <TMPL_IF NAME="GUID">
+         <id><TMPL_VAR GUID></id>
+       <TMPL_ELSE>
+         <id><TMPL_VAR URL></id>
+       </TMPL_IF>
        <link href="<TMPL_VAR PERMALINK>"/>
        <TMPL_IF NAME="AUTHOR">
         <author><name><TMPL_VAR AUTHOR ESCAPE=HTML></name></author>
        </TMPL_IF>
        <TMPL_IF NAME="COPYRIGHT">
-        <rights type="xhtml" xml:lang="en">
-         <div xmlns="http://www.w3.org/1999/xhtml">
+        <rights type="html" xml:lang="en">
           <TMPL_IF NAME="LICENSE">
-           <TMPL_VAR LICENSE>
-           <TMPL_VAR COPYRIGHT>
+           <TMPL_VAR LICENSE ESCAPE=HTML>
+           <TMPL_VAR COPYRIGHT ESCAPE=HTML>
           <TMPL_ELSE>
-           <TMPL_VAR COPYRIGHT>
+           <TMPL_VAR COPYRIGHT ESCAPE=HTML>
           </TMPL_IF>
-         </div>
         </rights>
        <TMPL_ELSE>
         <TMPL_IF NAME="LICENSE">
-         <rights type="xhtml" xml:lang="en">
-          <div xmlns="http://www.w3.org/1999/xhtml">
-           <TMPL_VAR LICENSE>
-          </div>
+         <rights type="html" xml:lang="en">
+           <TMPL_VAR LICENSE ESCAPE=HTML>
          </rights>
         </TMPL_IF>
        </TMPL_IF>
        <TMPL_IF NAME="ENCLOSURE">
         <link rel="enclosure" type="<TMPL_VAR TYPE>" href="<TMPL_VAR ENCLOSURE>" length="<TMPL_VAR LENGTH>" />
        <TMPL_ELSE>
-        <content type="xhtml" xml:lang="en">
-         <div xmlns="http://www.w3.org/1999/xhtml">
-         <TMPL_VAR CONTENT>
-         </div>
+        <content type="html" xml:lang="en">
+         <TMPL_VAR CONTENT ESCAPE=HTML>
         </content>
        </TMPL_IF>
+       <TMPL_IF NAME="COMMENTSURL">
+       <link rel="comments" href="<TMPL_VAR NAME="COMMENTSURL">" type="text/html" />
+       </TMPL_IF>
+       <TMPL_IF NAME="ATOMCOMMENTSURL">
+       <link rel="comments" href="<TMPL_VAR NAME="ATOMCOMMENTSURL">" type="application/atom+xml" />
+       </TMPL_IF>
 </entry>
index acc4737c1303b3aed5c20aaaead1072f2f805bf8..dcb89ab5cfac9ed6f26ca1e15a20caf58e6f9491 100644 (file)
@@ -3,7 +3,7 @@
 <feed xmlns="http://www.w3.org/2005/Atom">
 <title><TMPL_VAR TITLE></title>
 <link href="<TMPL_VAR PAGEURL>"/>
-<link href="<TMPL_VAR FEEDURL>" rel="self"/>
+<link href="<TMPL_VAR FEEDURL>" rel="self" type="application/atom+xml"/>
 <author>
 <TMPL_IF NAME="AUTHOR">
  <name><TMPL_VAR AUTHOR></name>
 </TMPL_IF>
 </author>
 <TMPL_IF NAME="COPYRIGHT">
- <rights type="xhtml" xml:lang="en">
-  <div xmlns="http://www.w3.org/1999/xhtml">
+ <rights type="html" xml:lang="en">
    <TMPL_IF NAME="LICENSE">
     <TMPL_VAR LICENSE>
-    <TMPL_VAR COPYRIGHT>
+    <TMPL_VAR COPYRIGHT ESCAPE=HTML>
    <TMPL_ELSE>
-    <TMPL_VAR COPYRIGHT>
+    <TMPL_VAR COPYRIGHT ESCAPE=HTML>
    </TMPL_IF>
-  </div>
  </rights>
 <TMPL_ELSE>
  <TMPL_IF NAME="LICENSE">
-  <rights type="xhtml" xml:lang="en">
-   <div xmlns="http://www.w3.org/1999/xhtml">
-    <TMPL_VAR LICENSE>
-   </div>
+  <rights type="html">
+    <TMPL_VAR LICENSE ESCAPE=HTML>
   </rights>
  </TMPL_IF>
 </TMPL_IF>
-<id><TMPL_VAR PAGEURL></id>
+<TMPL_IF NAME="GUID">
+  <id><TMPL_VAR GUID></id>
+<TMPL_ELSE>
+  <id><TMPL_VAR PAGEURL></id>
+</TMPL_IF>
 <subtitle type="html"><TMPL_VAR FEEDDESC ESCAPE=HTML></subtitle>
 <generator uri="http://ikiwiki.info/" version="<TMPL_VAR VERSION>">ikiwiki</generator>
 <updated><TMPL_VAR FEEDDATE></updated>
diff --git a/templates/autoindex.tmpl b/templates/autoindex.tmpl
new file mode 100644 (file)
index 0000000..d5ec3b8
--- /dev/null
@@ -0,0 +1 @@
+[[!map pages="<TMPL_VAR PAGE>/* and ! <TMPL_VAR PAGE>/*/*"]]
index 4a99cf5ff47a457774e686d1cbd0c320c142d363..0e61a80f4efc2d1fc173d031b827006bfce69cef 100644 (file)
@@ -3,7 +3,10 @@
 [[!meta authorurl="""<TMPL_VAR AUTHORURL>"""]]
 </TMPL_IF>
 [[!meta title="""change to<TMPL_LOOP NAME="PAGES"> <TMPL_VAR PAGE></TMPL_LOOP> on <TMPL_VAR WIKINAME>"""]]
-<div class="metadata">
+<TMPL_IF PERMALINK>
+[[!meta permalink="<TMPL_VAR PERMALINK>"]]
+</TMPL_IF>
+<div id="change-<TMPL_VAR REV>" class="metadata">
 <span class="desc"><br />Changed pages:</span>
 <span class="pagelinks">
 <TMPL_LOOP NAME="PAGES">
@@ -16,7 +19,7 @@
 <span class="desc"><br />Changed by:</span>
 <span class="committer">
 <TMPL_IF NAME="AUTHORURL">
-<a href="<TMPL_VAR AUTHORURL>"><TMPL_VAR USER></a>
+<a href="<TMPL_VAR AUTHORURL>" rel="nofollow"><TMPL_VAR USER></a>
 <TMPL_ELSE>
 <TMPL_VAR USER>
 </TMPL_IF>
 <span class="desc"><br />Commit type:</span>
 <span class="committype"><TMPL_VAR COMMITTYPE></span>
 <span class="desc"><br />Date:</span>
-<span class="changedate"><TMPL_VAR COMMITDATE></span>
+<span class="changedate"><TMPL_VAR COMMITDATE>
 </div>
 <div class=changelog>
 <TMPL_LOOP NAME="MESSAGE">
 <TMPL_IF NAME="LINE">
-<TMPL_VAR NAME="LINE" ESCAPE="HTML"><br />
+<TMPL_VAR NAME="LINE"><br />
 </TMPL_IF>
 </TMPL_LOOP>
 </div>
 <TMPL_IF NAME="DIFF">
 <div class=diff>
 <pre>
-<TMPL_VAR NAME="DIFF" ESCAPE="HTML">
+<TMPL_VAR NAME="DIFF">
 </pre>
 </div>
 </TMPL_IF>
diff --git a/templates/comment.tmpl b/templates/comment.tmpl
new file mode 100644 (file)
index 0000000..fb76ea0
--- /dev/null
@@ -0,0 +1,59 @@
+<div class="comment" id="<TMPL_VAR NAME=COMMENTID>">
+
+<div class="comment-subject">
+<TMPL_IF PERMALINK>
+<a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a>
+<TMPL_ELSE>
+<TMPL_VAR TITLE>
+</TMPL_IF>
+</div>
+
+<div class="inlinecontent">
+<TMPL_VAR CONTENT>
+</div>
+
+<div class="comment-header">
+Comment by
+
+<TMPL_IF NAME="COMMENTUSER">
+<TMPL_IF NAME="COMMENTOPENID">
+<span class="author" title="OpenID">
+<a href="<TMPL_VAR NAME=COMMENTOPENID>"><TMPL_VAR NAME=COMMENTAUTHOR></a>
+</span>
+<TMPL_ELSE>
+<span class="author" title="Signed in">
+<TMPL_IF NAME="COMMENTAUTHORURL">
+<a href="<TMPL_VAR NAME=COMMENTAUTHORURL>"><TMPL_VAR NAME=COMMENTAUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR NAME=COMMENTAUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF>
+<TMPL_ELSE><!-- !COMMENTUSER -->
+<TMPL_IF NAME=COMMENTIP>
+<span class="author" title="Unauthenticated, from <TMPL_VAR NAME=COMMENTIP>">
+<TMPL_ELSE><!-- !COMMENTIP -->
+<span class="author" title="Unauthenticated, from unknown IP address">
+</TMPL_IF>
+<TMPL_IF NAME="AUTHORURL">
+<a href="<TMPL_VAR NAME=AUTHORURL>"><TMPL_VAR NAME=AUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR NAME=AUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF><!-- !COMMENTUSER -->
+
+&mdash; <TMPL_VAR CTIME>
+</div>
+
+<TMPL_IF NAME="HAVE_ACTIONS">
+<div class="actions">
+<ul>
+<TMPL_IF NAME="REMOVEURL">
+<li><a href="<TMPL_VAR REMOVEURL>" rel="nofollow">Remove comment</a></li>
+</TMPL_IF>
+</ul>
+</div><!--.actions-->
+</TMPL_IF>
+
+</div><!--.comment-->
diff --git a/templates/commentmoderation.tmpl b/templates/commentmoderation.tmpl
new file mode 100644 (file)
index 0000000..e91d314
--- /dev/null
@@ -0,0 +1,29 @@
+<TMPL_IF NAME="COMMENTS">
+<br />
+<form action="<TMPL_VAR CGIURL>" method="post">
+<input type="hidden" name="do" value="commentmoderation" />
+<input type="hidden" name="sid" value="<TMPL_VAR SID>" />
+<input type="submit" value="Submit" />
+<input type="checkbox" name="rejectalldefer" value="1" />Reject
+all comments marked <em>Defer</em>
+<br />  
+<TMPL_LOOP NAME="COMMENTS">
+<div>
+<div>
+<TMPL_VAR VIEW>
+</div>
+<input type="radio" value="Defer" name="<TMPL_VAR ID>" checked />Defer
+<input type="radio" value="Accept" name="<TMPL_VAR ID>" />Accept
+<input type="radio" value="Reject" name="<TMPL_VAR ID>" />Reject
+</div>
+<br />
+</TMPL_LOOP>
+<input type="submit" value="Submit" />
+<input type="checkbox" name="rejectalldefer" value="1" />Reject
+all comments marked <em>Defer</em>
+</form>
+<TMPL_ELSE>
+<p>
+No comments need moderation at this time.
+</p>
+</TMPL_IF>
diff --git a/templates/editcomment.tmpl b/templates/editcomment.tmpl
new file mode 100644 (file)
index 0000000..545edb5
--- /dev/null
@@ -0,0 +1,32 @@
+<div class="editcomment">
+<TMPL_VAR MESSAGE>
+<TMPL_VAR FORM-START>
+<TMPL_VAR FIELD-DO>
+<TMPL_VAR FIELD-SID>
+<TMPL_VAR FIELD-PAGE>
+<TMPL_UNLESS NAME=USERNAME>
+<TMPL_IF NAME=ALLOWAUTHOR>
+Name: <TMPL_VAR NAME=FIELD-AUTHOR> (optional, or
+<a href="<TMPL_VAR SIGNINURL>">Signin</a>)<br />
+Website: <TMPL_VAR NAME=FIELD-URL> (optional)<br />
+<TMPL_ELSE>
+(You might want to <a href="<TMPL_VAR SIGNINURL>">Signin</a> first?)<br />
+</TMPL_IF>
+</TMPL_UNLESS>
+Subject: <TMPL_VAR FIELD-SUBJECT><br />
+<TMPL_VAR FIELD-EDITCONTENT><br />
+<TMPL_VAR FORM-SUBMIT> <TMPL_VAR FIELD-TYPE> <TMPL_VAR HELPONFORMATTINGLINK><br />
+<TMPL_VAR NAME="FORM-END">
+<TMPL_VAR WMD_PREVIEW>
+
+<TMPL_IF NAME="PAGE_PREVIEW">
+<hr />
+<div class="header">
+<span>Comment preview:</span>
+</div><!-- .header -->
+<div id="preview">
+<TMPL_VAR PAGE_PREVIEW>
+</div><!-- #preview -->
+</TMPL_IF>
+
+</div><!-- .editcomment -->
diff --git a/templates/editconflict.tmpl b/templates/editconflict.tmpl
new file mode 100644 (file)
index 0000000..1252033
--- /dev/null
@@ -0,0 +1,7 @@
+<p class="error">
+<b>Your changes conflict with other changes made to the page.</b>
+</p>
+<p>
+Conflict markers have been inserted into the page content. Reconcile the
+conflict and commit again to save your changes.
+</p>
diff --git a/templates/editcreationconflict.tmpl b/templates/editcreationconflict.tmpl
new file mode 100644 (file)
index 0000000..c99102f
--- /dev/null
@@ -0,0 +1,9 @@
+<p class="error">
+<b>While you were creating this page, someone else independently created a page
+with the same name.</b>
+</p>
+<p>
+The edit box below contains the page's current content, followed by the
+content you entered previously, to allow you to merge the two
+together before saving.
+</p>
diff --git a/templates/editfailedsave.tmpl b/templates/editfailedsave.tmpl
new file mode 100644 (file)
index 0000000..5184f7d
--- /dev/null
@@ -0,0 +1,10 @@
+<p class="error">
+<b>Failed to save your changes.</b>
+</p>
+<p>
+Your changes were not able to be saved to disk. The system gave the error:
+<blockquote>
+<TMPL_VAR ERROR_MESSAGE>
+</blockquote>
+Your changes are preserved below, and you can try again to save them.
+</p>
index 7f6c2a97a4521ac747a793862390c0065aec057a..b1cf015a2b2aa67adbc3b568d68102632a0a832f 100644 (file)
@@ -1,46 +1,6 @@
 <br />
 <TMPL_VAR JAVASCRIPT>
-<TMPL_IF NAME="PAGE_CONFLICT">
-<p>
-<b>Your changes conflict with other changes made to the page.</b>
-</p>
-<p>
-Conflict markers have been inserted into the page content. Reconcile the
-conflict and commit again to save your changes.
-</p>
-</TMPL_IF>
-<TMPL_IF NAME="FAILED_SAVE">
-<p>
-<b>Failed to save your changes.</b>
-</p>
-<p>
-Your changes were not able to be saved to disk. The system gave the error:
-<blockquote>
-<TMPL_VAR ERROR_MESSAGE>
-</blockquote>
-Your changes are preserved below, and you can try again to save them.
-</p>
-</TMPL_IF>
-<TMPL_IF NAME="PAGE_GONE">
-<p>
-<b>The page you were editing has disappeared.</b>
-</p>
-<p>
-Perhaps someone else has deleted it or moved it. If you want to recreate
-this page with your text, click "Save Page" again.
-</p>
-</TMPL_IF>
-<TMPL_IF NAME="CREATION_CONFLICT">
-<p>
-<b>While you were creating this page, someone else independently created a page
-with the same name.</b>
-</p>
-<p>
-The edit box below contains the page's current content, followed by the 
-content you entered previously, to allow you to merge the two
-together before saving.
-</p>
-</TMPL_IF>
+<TMPL_VAR MESSAGE>
 <TMPL_VAR FORM-START>
 <TMPL_VAR FIELD-DO>
 <TMPL_VAR FIELD-SID>
@@ -62,8 +22,8 @@ Optional comment about this change:<br />
 </TMPL_IF>
 <TMPL_VAR FORM-SUBMIT>
 <TMPL_VAR HELPONFORMATTINGLINK>
-<a class="toggle" href="#attachments">Attachments</a>
 <TMPL_IF NAME="FIELD-ATTACHMENT">
+<a class="toggle" href="#attachments">Attachments</a>
 <div class="<TMPL_VAR ATTACHMENTS-CLASS>" id="attachments">
 <table>
 <tr><td colspan="5"><TMPL_VAR FIELD-ATTACHMENT><TMPL_VAR FIELD-UPLOAD></td></tr>
@@ -71,12 +31,13 @@ Optional comment about this change:<br />
 <tr><td><TMPL_VAR FIELD-SELECT><TMPL_VAR LINK></td><td><TMPL_VAR SIZE></td><td><TMPL_VAR MTIME></td></tr>
 </TMPL_LOOP>
 <TMPL_IF NAME="ATTACHMENT_LIST">
-<tr><td colspan="2"><TMPL_VAR FIELD-LINK><TMPL_VAR FIELD-DELETE><TMPL_VAR FIELD-RENAME></td></tr>
+<tr><td colspan="2"><TMPL_VAR FIELD-LINK><TMPL_VAR FIELD-RENAME><TMPL_VAR FIELD-REMOVE></td></tr>
 </TMPL_IF>
 </table>
 </div>
 </TMPL_IF>
 <TMPL_VAR FORM-END>
+<TMPL_VAR WMD_PREVIEW>
 
 <TMPL_IF NAME="PAGE_PREVIEW">
 <hr />
diff --git a/templates/editpagegone.tmpl b/templates/editpagegone.tmpl
new file mode 100644 (file)
index 0000000..2eed03a
--- /dev/null
@@ -0,0 +1,7 @@
+<p class="error">
+<b>The page you were editing has disappeared.</b>
+</p>
+<p>
+Perhaps someone else has deleted it or moved it. If you want to recreate
+this page with your text, click "Save Page" again.
+</p>
diff --git a/templates/estseek.conf b/templates/estseek.conf
deleted file mode 100644 (file)
index 2abf413..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-indexname: <TMPL_VAR INDEX>
-tmplfile: <TMPL_VAR TMPLFILE>
-topfile: /dev/null
-logfile:
-logformat: 
-replace: ^file://<TMPL_VAR DESTDIR>{{!}}<TMPL_VAR URL>
-showreal: false
-perpage: 10,20,30,40,50,100
-attrselect: false
-showscore: false
-extattr: date|Date
-snipwwidth: 480
-sniphwidth: 96
-snipawidth: 96
-condgstep: 2
-dotfidf: true
-scancheck: false
-smplphrase: true
-phraseform: 2
-candetail: true
-smlrvnum: 0
-smlrtune: 16 1024 4096
-clipview: 2
-relkeynum: 0
-spcache:
-wildmax: 256
-qxpndcmd:
-helpfile: /usr/share/hyperestraier/estseek.help
-deftitle: 
-attrwidth: 80
-dispproxy: 
diff --git a/templates/googleform.tmpl b/templates/googleform.tmpl
new file mode 100644 (file)
index 0000000..e2d4a1f
--- /dev/null
@@ -0,0 +1,6 @@
+<form method="get" action="http://www.google.com/search" id="searchform">
+ <div>
+  <input name="sitesearch" value="<TMPL_VAR SITEFQDN>" type="hidden" />
+  <input name="q" value="" id="searchbox" size="16" maxlength="255" type="text" />
+ </div>
+</form>
index 71d57b00830fcdf821d87535f195e8add7d4e173..3c0b933159b168fe94119a51258b0d0f49baec06 100644 (file)
@@ -1,10 +1,13 @@
 <div class="inlinepage">
+
+<div class="inlineheader">
+
 <TMPL_IF NAME="AUTHOR">
 <span class="author">
 <TMPL_IF NAME="AUTHORURL">
-<a href="<TMPL_VAR NAME=AUTHORURL>"><TMPL_VAR NAME=AUTHOR></a>
+<a href="<TMPL_VAR AUTHORURL>"><TMPL_VAR AUTHOR></a>
 <TMPL_ELSE>
-<TMPL_VAR NAME=AUTHOR>
+<TMPL_VAR AUTHOR>
 </TMPL_IF>
 </span>
 </TMPL_IF>
 <a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a>
 </TMPL_IF>
 </span>
+
+</div><!--.inlineheader-->
+
+<div class="inlinecontent">
 <TMPL_VAR CONTENT>
+</div><!--.inlinecontent-->
+
+<div class="inlinefooter">
 
 <span class="pagedate">
 Posted <TMPL_VAR CTIME>
@@ -25,7 +35,7 @@ Posted <TMPL_VAR CTIME>
 <span class="tags">
 Tags:
 <TMPL_LOOP NAME="TAGS">
-<TMPL_VAR NAME=LINK>
+<TMPL_VAR LINK>
 </TMPL_LOOP>
 </span>
 </TMPL_IF>
@@ -48,11 +58,17 @@ License: <TMPL_VAR LICENSE>
 <TMPL_IF NAME="EDITURL">
 <li><a href="<TMPL_VAR EDITURL>" rel="nofollow">Edit</a></li>
 </TMPL_IF>
+<TMPL_IF NAME="COMMENTSLINK">
+<li><TMPL_VAR COMMENTSLINK></li>
+<TMPL_ELSE>
 <TMPL_IF NAME="DISCUSSIONLINK">
 <li><TMPL_VAR DISCUSSIONLINK></li>
 </TMPL_IF>
+</TMPL_IF>
 </ul>
-</div>
+</div><!--.actions-->
 </TMPL_IF>
 
-</div>
+</div><!--.inlinefooter-->
+
+</div><!--.inlinepage-->
diff --git a/templates/microblog.tmpl b/templates/microblog.tmpl
new file mode 100644 (file)
index 0000000..2e84441
--- /dev/null
@@ -0,0 +1,22 @@
+<div class="microblog">
+
+<div class="inlinecontent">
+<TMPL_VAR CONTENT>
+</div>
+
+<div class="microblog-header">
+
+<TMPL_IF NAME="AUTHOR">
+<span class="author">
+<TMPL_IF NAME="AUTHORURL">
+<a href="<TMPL_VAR AUTHORURL>"><TMPL_VAR AUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR AUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF>
+
+&mdash; <TMPL_VAR CTIME>
+
+</div> <!--.microblog-header-->
+</div> <!--.microblog-->
index 7f65217d124b0423d523814d2964d18e0d24952f..0de56edebc61dda8ee05eb190b6c8dbee1069b5d 100644 (file)
 </head>
 <body>
 
+<div class="pageheader">
 <div class="header">
 <span>
 <TMPL_VAR INDEXLINK>/ <TMPL_VAR TITLE>
 </span>
 </div>
+</div> <!-- .pageheader -->
 
 <div id="content">
 <TMPL_VAR PAGEBODY>
index 166f3c5604c2fc91bade3963600ae84917fd8b97..e71ba316db79a3492db66ddb2299d9f905c807c8 100644 (file)
 <link rel="alternate" type="application/x-wiki" title="Edit this page" href="<TMPL_VAR EDITURL>" />
 </TMPL_IF>
 <TMPL_IF NAME="FEEDLINKS"><TMPL_VAR FEEDLINKS></TMPL_IF>
+<TMPL_IF NAME="RELVCS"><TMPL_VAR RELVCS></TMPL_IF>
 <TMPL_IF NAME="META"><TMPL_VAR META></TMPL_IF>
 </head>
 <body>
 
+<div class="pageheader">
 <div class="header">
 <span>
+<span class="parentlinks">
 <TMPL_LOOP NAME="PARENTLINKS">
-<a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>/ 
+<a href="<TMPL_VAR URL>"><TMPL_VAR PAGE></a>/ 
 </TMPL_LOOP>
+</span>
+<span class="title">
 <TMPL_VAR TITLE>
+<TMPL_IF NAME="ISTRANSLATION">
+&nbsp;(<TMPL_VAR NAME="PERCENTTRANSLATED">%)
+</TMPL_IF>
 </span>
+</span><!--.header-->
 <TMPL_IF NAME="SEARCHFORM">
 <TMPL_VAR SEARCHFORM>
 </TMPL_IF>
 <TMPL_IF NAME="HISTORYURL">
 <li><a href="<TMPL_VAR HISTORYURL>">History</a></li>
 </TMPL_IF>
+<TMPL_IF NAME="GETSOURCEURL">
+<li><a href="<TMPL_VAR GETSOURCEURL>">Source</a></li>
+</TMPL_IF>
 <TMPL_IF NAME="PREFSURL">
 <li><a href="<TMPL_VAR PREFSURL>">Preferences</a></li>
 </TMPL_IF>
+<TMPL_IF NAME="COMMENTSLINK">
+<li><TMPL_VAR COMMENTSLINK><br /></li>
+<TMPL_ELSE>
 <TMPL_IF NAME="DISCUSSIONLINK">
 <li><TMPL_VAR DISCUSSIONLINK><br /></li>
 </TMPL_IF>
+</TMPL_IF>
 </ul>
 </div>
 </TMPL_IF>
 
+<TMPL_IF NAME="OTHERLANGUAGES">
+<div id="otherlanguages">
+<ul>
+<TMPL_LOOP NAME="OTHERLANGUAGES">
+<li>
+<a href="<TMPL_VAR NAME="URL">"><TMPL_VAR NAME="LANGUAGE"></a>
+<TMPL_IF NAME="MASTER">
+(master)
+<TMPL_ELSE>
+&nbsp;(<TMPL_VAR NAME="PERCENT">%)
+</TMPL_IF>
+</li>
+</TMPL_LOOP>
+</ul>
+</div> <!-- #otherlanguages -->
+</TMPL_IF>
+
+</div> <!-- .pageheader -->
+
 <TMPL_IF SIDEBAR>
 <div id="sidebar">
 <TMPL_VAR SIDEBAR>
 <TMPL_VAR CONTENT>
 </div>
 
-<div id="footer">
+<TMPL_IF COMMENTS>
+<div id="comments">
+<TMPL_VAR COMMENTS>
+<TMPL_IF ADDCOMMENTURL>
+<div class="addcomment">
+<a href="<TMPL_VAR ADDCOMMENTURL>">Add a comment</a>
+</div>
+<TMPL_ELSE>
+<div class="addcomment">Comments on this page are closed.</div>
+</TMPL_IF>
+</div>
+</TMPL_IF>
+
+<div id="footer" class="pagefooter">
 <div id="pageinfo">
 
 <TMPL_IF NAME="TAGS">
 <div class="tags">
 Tags:
 <TMPL_LOOP NAME="TAGS">
-<TMPL_VAR NAME=LINK>
+<TMPL_VAR LINK>
 </TMPL_LOOP>
 </div>
 </TMPL_IF>
@@ -77,18 +125,18 @@ Tags:
 <div id="backlinks">
 Links:
 <TMPL_LOOP NAME="BACKLINKS">
-<a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>
+<a href="<TMPL_VAR URL>"><TMPL_VAR PAGE></a>
 </TMPL_LOOP>
 <TMPL_IF NAME="MORE_BACKLINKS">
 <span class="popup">...
 <span class="balloon">
 <TMPL_LOOP NAME="MORE_BACKLINKS">
-<a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>
+<a href="<TMPL_VAR URL>"><TMPL_VAR PAGE></a>
 </TMPL_LOOP>
 </span>
 </span>
 </TMPL_IF>
-</div>
+</div><!-- #backlinks -->
 </TMPL_IF>
 
 <TMPL_IF COPYRIGHT>
@@ -106,14 +154,14 @@ License: <TMPL_VAR LICENSE>
 </TMPL_IF>
 
 <div class="pagedate">
-Last edited <TMPL_VAR NAME=MTIME>
-<!-- Created <TMPL_VAR NAME=CTIME> -->
+Last edited <TMPL_VAR MTIME>
+<!-- Created <TMPL_VAR CTIME> -->
 </div>
 
-</div>
+</div><!-- #pageinfo -->
 <TMPL_IF EXTRAFOOTER><TMPL_VAR EXTRAFOOTER></TMPL_IF>
-<!-- from <TMPL_VAR NAME=WIKINAME> -->
-</div>
+<!-- from <TMPL_VAR WIKINAME> -->
+</div><!-- .pagefooter #footer -->
 
 </body>
 </html>
diff --git a/templates/pocreatepage.tmpl b/templates/pocreatepage.tmpl
new file mode 100644 (file)
index 0000000..96c8fdd
--- /dev/null
@@ -0,0 +1,3 @@
+<p>
+<b>WARNING</b> this page must be written in <TMPL_VAR NAME="LANG">.
+</p>
\ No newline at end of file
diff --git a/templates/renamesummary.tmpl b/templates/renamesummary.tmpl
new file mode 100644 (file)
index 0000000..60f81b3
--- /dev/null
@@ -0,0 +1,26 @@
+<TMPL_IF ERROR>
+<p>
+<b>Failed to rename <TMPL_VAR SRC> to <TMPL_VAR DEST>: </b>
+<TMPL_VAR ERROR>
+</p>
+<TMPL_ELSE>
+<p>
+<b>Successfully renamed <TMPL_VAR SRC> to <TMPL_VAR DEST>.</b>
+</p>
+<p>
+<TMPL_IF FIXEDLINKS>
+The following pages have been automatically modified to update their links to <TMPL_VAR DEST>:
+<ul>
+<TMPL_LOOP NAME=FIXEDLINKS><li><TMPL_VAR PAGE></li></TMPL_LOOP>
+</ul>
+</TMPL_IF>
+<TMPL_IF BROKENLINKS_CHECKED>
+<TMPL_IF BROKENLINKS>
+The following pages still link to <TMPL_VAR SRC>:
+<ul>
+<TMPL_LOOP NAME=BROKENLINKS><li><TMPL_VAR PAGE></li></TMPL_LOOP>
+</ul>
+</TMPL_IF>
+</TMPL_IF>
+</p>
+</TMPL_IF>
index f22e5e3fb99c3cba669bccc860618559aad4de5a..a61b92b6127505e3f61b068d046e3f706a956d9a 100644 (file)
@@ -5,7 +5,11 @@
        <TMPL_ELSE>
        <title><TMPL_VAR TITLE></title>
        </TMPL_IF>
-       <guid><TMPL_VAR URL></guid>
+       <TMPL_IF NAME="GUID">
+         <guid isPermaLink="no"><TMPL_VAR GUID></guid>
+       <TMPL_ELSE>
+         <guid><TMPL_VAR URL></guid>
+       </TMPL_IF>
        <link><TMPL_VAR PERMALINK></link>
        <TMPL_IF NAME="CATEGORIES">
        <TMPL_LOOP NAME="CATEGORIES">
@@ -17,6 +21,9 @@
        <TMPL_IF NAME="ENCLOSURE">
        <enclosure url="<TMPL_VAR ENCLOSURE>" type="<TMPL_VAR TYPE>" length="<TMPL_VAR LENGTH>" />
        <TMPL_ELSE>
-       <description><![CDATA[<TMPL_VAR CONTENT>]]></description>
+       <description><TMPL_VAR CONTENT ESCAPE=HTML></description>
+       </TMPL_IF>
+       <TMPL_IF NAME="COMMENTSURL">
+       <comments><TMPL_VAR NAME="COMMENTSURL"></comments>
        </TMPL_IF>
 </item>
index d49cf22d33340cb7c2603149179bf2bad6e78001..afae2ebf5d711b60fb87dbb9020cdcd98de4f98c 100644 (file)
@@ -1,5 +1,5 @@
 <form method="get" action="<TMPL_VAR SEARCHACTION>" id="searchform">
 <div>
-<input type="text" name="P" value="" size="16" />
+<input type="text" id="searchbox" name="P" value="" size="16" />
 </div>
 </form>
index 0d6eb6398cb40d26ad7bb7673cab6f9307b0086c..782b12cab0cee051ed41eda88bfdaf2e3b1e8187 100644 (file)
@@ -1,5 +1,5 @@
 $setmap{prefix,title,S}
-$setmap{prefix,link,LINK}
+$setmap{prefix,link,XLINK}
 $set{thousand,$.}$set{decimal,.}$setmap{BN,,Any Country,uk,England,fr,France}
 ${
 $def{PREV,
index f5cd5bc53e69de301886902e25428cd2ab2c9b94..8a11e693ebfe08602a003f01bda55ff8dec316bf 100644 (file)
@@ -1 +1,7 @@
-<p><a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a></p>
+<p>
+<TMPL_IF NAME="PERMALINK">
+<a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a>
+<TMPL_ELSE>
+<a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a>
+</TMPL_IF>
+</p>
diff --git a/underlays/basewiki/blog.mdwn b/underlays/basewiki/blog.mdwn
deleted file mode 100644 (file)
index d9faeb8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/blog delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/blog|ikiwiki/blog]]. Please update your
-links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/basewiki/helponformatting.mdwn b/underlays/basewiki/helponformatting.mdwn
deleted file mode 100644 (file)
index 9e79876..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/formatting delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/formatting|ikiwiki/formatting]]. Please
-update your links, as this redirection page will be removed in a future
-ikiwiki release.
diff --git a/underlays/basewiki/ikiwiki/blog.mdwn b/underlays/basewiki/ikiwiki/blog.mdwn
deleted file mode 120000 (symlink)
index 7735e98..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../doc/ikiwiki/blog.mdwn
\ No newline at end of file
diff --git a/underlays/basewiki/ikiwiki/directive.mdwn b/underlays/basewiki/ikiwiki/directive.mdwn
new file mode 120000 (symlink)
index 0000000..ba130b7
--- /dev/null
@@ -0,0 +1 @@
+../../../doc/ikiwiki/directive.mdwn
\ No newline at end of file
diff --git a/underlays/basewiki/ikiwiki/pagespec/po.mdwn b/underlays/basewiki/ikiwiki/pagespec/po.mdwn
new file mode 120000 (symlink)
index 0000000..255c3de
--- /dev/null
@@ -0,0 +1 @@
+../../../../doc/ikiwiki/pagespec/po.mdwn
\ No newline at end of file
diff --git a/underlays/basewiki/ikiwiki/preprocessordirective.mdwn b/underlays/basewiki/ikiwiki/preprocessordirective.mdwn
deleted file mode 120000 (symlink)
index 3ccd8c8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../doc/ikiwiki/preprocessordirective.mdwn
\ No newline at end of file
diff --git a/underlays/basewiki/ikiwiki/subpage b/underlays/basewiki/ikiwiki/subpage
deleted file mode 120000 (symlink)
index dc18335..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../doc/ikiwiki/subpage
\ No newline at end of file
diff --git a/underlays/basewiki/ikiwiki/subpage/linkingrules.mdwn b/underlays/basewiki/ikiwiki/subpage/linkingrules.mdwn
new file mode 120000 (symlink)
index 0000000..6694188
--- /dev/null
@@ -0,0 +1 @@
+../../../../doc/ikiwiki/subpage/linkingrules.mdwn
\ No newline at end of file
diff --git a/underlays/basewiki/markdown.mdwn b/underlays/basewiki/markdown.mdwn
deleted file mode 100644 (file)
index cefd2f5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/markdown delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/markdown|ikiwiki/markdown]]. Please update
-your links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/basewiki/openid.mdwn b/underlays/basewiki/openid.mdwn
deleted file mode 100644 (file)
index 5a462c9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/openid delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/openid|ikiwiki/openid]]. Please update your
-links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/basewiki/pagespec.mdwn b/underlays/basewiki/pagespec.mdwn
deleted file mode 100644 (file)
index c3caf59..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/pagespec delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/pagespec|ikiwiki/pagespec]]. Please update
-your links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/basewiki/preprocessordirective.mdwn b/underlays/basewiki/preprocessordirective.mdwn
deleted file mode 100644 (file)
index 842ebfb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-[[!meta redir=ikiwiki/preprocessordirective delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to
-[[ikiwiki/preprocessordirective|ikiwiki/preprocessordirective]]. Please
-update your links, as this redirection page will be removed in a future
-ikiwiki release.
diff --git a/underlays/basewiki/subpage.mdwn b/underlays/basewiki/subpage.mdwn
deleted file mode 100644 (file)
index 64598b5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/subpage delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/subpage|ikiwiki/subpage]]. Please update your
-links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/basewiki/wikilink.mdwn b/underlays/basewiki/wikilink.mdwn
deleted file mode 100644 (file)
index b5a1a8e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[[!meta redir=ikiwiki/wikilink delay=10]]
-[[!meta robots="noindex, follow"]]
-
-This page has moved to [[ikiwiki/wikilink|ikiwiki/wikilink]]. Please update
-your links, as this redirection page will be removed in a future ikiwiki
-release.
diff --git a/underlays/javascript/ikiwiki.js b/underlays/javascript/ikiwiki.js
new file mode 100644 (file)
index 0000000..1252f24
--- /dev/null
@@ -0,0 +1,52 @@
+// ikiwiki's javascript utility function library
+
+var hooks;
+
+// Run onload as soon as the DOM is ready, if possible.
+// gecko, opera 9
+if (document.addEventListener) {
+       document.addEventListener("DOMContentLoaded", run_hooks_onload, false);
+}
+// other browsers
+window.onload = run_hooks_onload;
+
+function run_hooks_onload() {
+       // avoid firing twice
+       if (arguments.callee.done)
+               return;
+       arguments.callee.done = true;
+
+       run_hooks("onload");
+}
+
+function run_hooks(name) {
+       if (typeof(hooks) != "undefined") {
+               for (var i = 0; i < hooks.length; i++) {
+                       if (hooks[i].name == name) {
+                               hooks[i].call();
+                       }
+               }
+       }
+}
+
+function hook(name, call) {
+       if (typeof(hooks) == "undefined")
+               hooks = new Array;
+       hooks.push({name: name, call: call});
+}
+
+function getElementsByClass(cls, node, tag) {
+        if (document.getElementsByClass)
+                return document.getElementsByClass(cls, node, tag);
+        if (! node) node = document;
+        if (! tag) tag = '*';
+        var ret = new Array();
+        var pattern = new RegExp("(^|\\s)"+cls+"(\\s|$)");
+        var els = node.getElementsByTagName(tag);
+        for (i = 0; i < els.length; i++) {
+                if ( pattern.test(els[i].className) ) {
+                        ret.push(els[i]);
+                }
+        }
+        return ret;
+}
diff --git a/underlays/javascript/relativedate.js b/underlays/javascript/relativedate.js
new file mode 100644 (file)
index 0000000..5142332
--- /dev/null
@@ -0,0 +1,76 @@
+// Causes html elements in the 'relativedate' class to be displayed
+// as relative dates. The date is parsed from the title attribute, or from
+// the element content.
+
+var dateElements;
+
+hook("onload", getDates);
+
+function getDates() {
+       dateElements = getElementsByClass('relativedate');
+       for (var i = 0; i < dateElements.length; i++) {
+               var elt = dateElements[i];
+               var title = elt.attributes.title;
+               var d = new Date(title ? title.value : elt.innerHTML);
+               if (! isNaN(d)) {
+                       dateElements[i].date=d;
+                       elt.title=elt.innerHTML;
+               }
+       }
+
+       showDates();
+}
+
+function showDates() {
+       for (var i = 0; i < dateElements.length; i++) {
+               var elt = dateElements[i];
+               var d = elt.date;
+               if (! isNaN(d)) {
+                       elt.innerHTML=relativeDate(d);
+               }
+       }
+       setTimeout(showDates,30000); // keep updating every 30s
+}
+
+var timeUnits = new Array;
+timeUnits['minute'] = 60;
+timeUnits['hour'] = timeUnits['minute'] * 60;
+timeUnits['day'] = timeUnits['hour'] * 24;
+timeUnits['month'] = timeUnits['day'] * 30;
+timeUnits['year'] = timeUnits['day'] * 364;
+var timeUnitOrder = ['year', 'month', 'day', 'hour', 'minute'];
+
+function relativeDate(date) {
+       var now = new Date();
+       var offset = date.getTime() - now.getTime();
+       var seconds = Math.round(Math.abs(offset) / 1000);
+
+       // hack to avoid reading just in the future if there is a minor
+       // amount of clock slip
+       if (offset >= 0 && seconds < 30 * timeUnits['minute']) {
+               return "just now";
+       }
+
+       var ret = "";
+       var shown = 0;
+       for (i = 0; i < timeUnitOrder.length; i++) {
+               var unit = timeUnitOrder[i];
+               if (seconds >= timeUnits[unit]) {
+                       var num = Math.floor(seconds / timeUnits[unit]);
+                       seconds -= num * timeUnits[unit];
+                       if (ret)
+                               ret += "and ";
+                       ret += num + " " + unit + (num > 1 ? "s" : "") + " ";
+
+                       if (++shown == 2)
+                               break;
+               }
+               else if (shown)
+                       break;
+       }
+
+       if (! ret)
+               ret = "less than a minute "
+
+       return ret + (offset < 0 ? "ago" : "from now");
+}
diff --git a/underlays/javascript/toggle.js b/underlays/javascript/toggle.js
new file mode 100644 (file)
index 0000000..d190b73
--- /dev/null
@@ -0,0 +1,29 @@
+// Uses CSS to hide toggleables, to avoid any flashing on page load. The
+// CSS is only emitted after it tests that it's going to be able
+// to show the toggleables.
+if (document.getElementById && document.getElementsByTagName && document.createTextNode) {
+       document.write('<style type="text/css">div.toggleable { display: none; }</style>');
+       hook("onload", inittoggle);
+}
+
+function inittoggle() {
+       var as = getElementsByClass('toggle');
+       for (var i = 0; i < as.length; i++) {
+               var id = as[i].href.match(/#(\w.+)/)[1];
+               if (document.getElementById(id).className == "toggleable")
+                       document.getElementById(id).style.display="none";
+               as[i].onclick = function() {
+                       toggle(this);
+                       return false;
+               }
+       }
+}
+
+function toggle(s) {
+       var id = s.href.match(/#(\w.+)/)[1];
+       style = document.getElementById(id).style;
+       if (style.display == "none")
+               style.display = "block";
+       else
+               style.display = "none";
+}