Kwiki-0.39/0000755000076500007650000000000010573352515012501 5ustar ingyingy00000000000000Kwiki-0.39/Changes0000644000076500007650000000523510573345674014011 0ustar ingyingy00000000000000--- version: 0.39 date: Tue Mar 6 12:13:40 PST 2007 changes: - Adding documentation for Kwiki 2 - Explain that people should use Kwiki from SVN rather than CPAN for now --- version: 0.38 date: Mon Apr 4 07:44:29 PDT 2005 changes: - Tweak for Kwiki-HomePagePreference - Allow the hub to be hooked. - Socialtext changes - Allow ; in addition to & in query strings - Get rid of -M operators - Make redirects RFC compliant - Refactored themes - empty links cause double page loads - Refactors to get rid of hub connections - eliminate use_class - COmment support - Kwid Formatter for Spork - Also prints command usage from plugins. - copyright 2005 - tweak space on usage() - eliminate cleanup undef warning when doing 'kwiki -update' --- version: 0.37 date: Tue Jan 11 07:45:24 PST 2005 changes: - Remove load_class calls per Spoon 0.21 - Move archive commit hook into super class - Split Kwiki::COmmand into Spoon::Command - Make kwiki -compress work again :\ - Change -subwiki to -new_view - List all plugins commented out in plugins file - Support PagePrivacy - Support multiple config*.* - Make toolbar, widgets, and status prereqs of theme --- version: 0.36 date: Sat Dec 18 00:52:03 PST 2004 changes: - Make dependent on new Spoon which cures memory cycles - Add more of Dave Rolsky's tests --- version: 0.35 date: Sat Dec 18 00:38:39 PST 2004 changes: - Make compatible with Kwiki-0.34 --- version: 0.35 date: Fri Dec 17 02:46:43 PST 2004 changes: - Fixed archive commit hook - Don't fail tests if no HTTP::BrowserDetect --- version: 0.34 date: Wed Dec 15 13:55:58 PST 2004 - Kwiki is now memory cycle free, which makes it much more suitable for use under mod_perl (Dave Rolsky) - Added Pane superclass for Toolbar Widgets and Status - Added BrowserDetect module - Removed Htaccess module - Added Kwiki::WebFile base class - Use new Spoon::Hook for archive - Make path configurable for templates, css, and javascript - Add -subwiki and -update_all actions to installer. - Add -quiet/-q options to installer - Add BEGIN/END comments to templates automatically - Make installer smarter - Plugins can specify prerequisites - Add ip address to page metadata --- version: 0.33 date: Sun Aug 8 23:12:30 PDT 2004 changes: - Archive API supports svk - Full unicode support --- version: 0.32 date: Tue Jul 20 03:01:51 PDT 2004 changes: - Make kwiki -update take a directory parameter - kwiki -update checks that wiki directory is valid - Added status pane --- version: 0.31 date: Tue Jun 22 09:39:29 PDT 2004 changes: - Installer was clobbering some files - Allow installer to take a directory argument --- version: 0.30 date: Sun Jun 20 13:48:35 PDT 2004 changes: - Initial release. Kwiki-0.39/inc/0000755000076500007650000000000010573352515013252 5ustar ingyingy00000000000000Kwiki-0.39/inc/Module/0000755000076500007650000000000010573352515014477 5ustar ingyingy00000000000000Kwiki-0.39/inc/Module/Install/0000755000076500007650000000000010573352515016105 5ustar ingyingy00000000000000Kwiki-0.39/inc/Module/Install/Base.pm0000644000076500007650000000147710224251521017312 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Base.pm - /Users/ingy/lib/Module/Install/Base.pm" package Module::Install::Base; #line 28 sub new { my ($class, %args) = @_; foreach my $method (qw(call load)) { *{"$class\::$method"} = sub { +shift->_top->$method(@_); } unless defined &{"$class\::$method"}; } bless(\%args, $class); } #line 46 sub AUTOLOAD { my $self = shift; goto &{$self->_top->autoload}; } #line 57 sub _top { $_[0]->{_top} } #line 68 sub admin { my $self = shift; $self->_top->{admin} or Module::Install::Base::FakeAdmin->new; } sub is_admin { my $self = shift; $self->admin->VERSION; } sub DESTROY {} package Module::Install::Base::FakeAdmin; my $Fake; sub new { $Fake ||= bless(\@_, $_[0]) } sub AUTOLOAD {} sub DESTROY {} 1; __END__ #line 112 Kwiki-0.39/inc/Module/Install/Can.pm0000644000076500007650000000163210224251521017132 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Can.pm - /Users/ingy/lib/Module/Install/Can.pm" package Module::Install::Can; use Module::Install::Base; @ISA = qw(Module::Install::Base); $VERSION = '0.01'; use strict; use Config (); use File::Spec (); use ExtUtils::MakeMaker (); # check if we can run some command sub can_run { my ($self, $cmd) = @_; my $_cmd = $cmd; return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd)); for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') { my $abs = File::Spec->catfile($dir, $_[1]); return $abs if (-x $abs or $abs = MM->maybe_command($abs)); } return; } sub can_cc { my $self = shift; my @chunks = split(/ /, $Config::Config{cc}) or return; # $Config{cc} may contain args; try to find out the program part while (@chunks) { return $self->can_run("@chunks") || (pop(@chunks), next); } return; } 1; Kwiki-0.39/inc/Module/Install/Fetch.pm0000644000076500007650000000460210224251521017462 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Fetch.pm - /Users/ingy/lib/Module/Install/Fetch.pm" package Module::Install::Fetch; use Module::Install::Base; @ISA = qw(Module::Install::Base); $VERSION = '0.01'; sub get_file { my ($self, %args) = @_; my ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; if ($scheme eq 'http' and !eval { require LWP::Simple; 1 }) { $args{url} = $args{ftp_url} or (warn("LWP support unavailable!\n"), return); ($scheme, $host, $path, $file) = $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return; } $|++; print "Fetching '$file' from $host... "; unless (eval { require Socket; Socket::inet_aton($host) }) { warn "'$host' resolve failed!\n"; return; } return unless $scheme eq 'ftp' or $scheme eq 'http'; require Cwd; my $dir = Cwd::getcwd(); chdir $args{local_dir} or return if exists $args{local_dir}; if (eval { require LWP::Simple; 1 }) { LWP::Simple::mirror($args{url}, $file); } elsif (eval { require Net::FTP; 1 }) { eval { # use Net::FTP to get past firewall my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600); $ftp->login("anonymous", 'anonymous@example.com'); $ftp->cwd($path); $ftp->binary; $ftp->get($file) or (warn("$!\n"), return); $ftp->quit; } } elsif (my $ftp = $self->can_run('ftp')) { eval { # no Net::FTP, fallback to ftp.exe require FileHandle; my $fh = FileHandle->new; local $SIG{CHLD} = 'IGNORE'; unless ($fh->open("|$ftp -n")) { warn "Couldn't open ftp: $!\n"; chdir $dir; return; } my @dialog = split(/\n/, << "."); open $host user anonymous anonymous\@example.com cd $path binary get $file $file quit . foreach (@dialog) { $fh->print("$_\n") } $fh->close; } } else { warn "No working 'ftp' program available!\n"; chdir $dir; return; } unless (-f $file) { warn "Fetching failed: $@\n"; chdir $dir; return; } return if exists $args{size} and -s $file != $args{size}; system($args{run}) if exists $args{run}; unlink($file) if $args{remove}; print(((!exists $args{check_for} or -e $args{check_for}) ? "done!" : "failed! ($!)"), "\n"); chdir $dir; return !$?; } 1; Kwiki-0.39/inc/Module/Install/Makefile.pm0000644000076500007650000000721310224251521020147 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Makefile.pm - /Users/ingy/lib/Module/Install/Makefile.pm" package Module::Install::Makefile; use Module::Install::Base; @ISA = qw(Module::Install::Base); $VERSION = '0.01'; use strict 'vars'; use vars '$VERSION'; use ExtUtils::MakeMaker (); sub Makefile { $_[0] } sub prompt { shift; goto &ExtUtils::MakeMaker::prompt; } sub makemaker_args { my $self = shift; my $args = ($self->{makemaker_args} ||= {}); %$args = ( %$args, @_ ) if @_; $args; } sub clean_files { my $self = shift; my $clean = $self->makemaker_args->{clean} ||= {}; %$clean = ( %$clean, FILES => join(" ", grep length, $clean->{FILES}, @_), ); } sub libs { my $self = shift; my $libs = ref $_[0] ? shift : [shift]; $self->makemaker_args( LIBS => $libs ); } sub inc { my $self = shift; $self->makemaker_args( INC => shift ); } sub write { my $self = shift; die "&Makefile->write() takes no arguments\n" if @_; my $args = $self->makemaker_args; $args->{DISTNAME} = $self->name; $args->{NAME} = $self->module_name || $self->name || $self->determine_NAME($args); $args->{VERSION} = $self->version || $self->determine_VERSION($args); $args->{NAME} =~ s/-/::/g; if ($] >= 5.005) { $args->{ABSTRACT} = $self->abstract; $args->{AUTHOR} = $self->author; } if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) { $args->{NO_META} = 1; } if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 ) { $args->{SIGN} = 1 if $self->sign; } delete $args->{SIGN} unless $self->is_admin; # merge both kinds of requires into prereq_pm my $prereq = ($args->{PREREQ_PM} ||= {}); %$prereq = ( %$prereq, map { @$_ } map { @$_ } grep $_, ($self->build_requires, $self->requires) ); # merge both kinds of requires into prereq_pm my $dir = ($args->{DIR} ||= []); if ($self->bundles) { push @$dir, map "$_->[1]", @{$self->bundles}; delete $prereq->{$_->[0]} for @{$self->bundles}; } if (my $perl_version = $self->perl_version) { eval "use $perl_version; 1" or die "ERROR: perl: Version $] is installed, ". "but we need version >= $perl_version"; } my %args = map {($_ => $args->{$_})} grep {defined($args->{$_})} keys %$args; if ($self->admin->preop) { $args{dist} = $self->admin->preop; } ExtUtils::MakeMaker::WriteMakefile(%args); $self->fix_up_makefile(); } sub fix_up_makefile { my $self = shift; my $top_class = ref($self->_top) || ''; my $top_version = $self->_top->VERSION || ''; my $preamble = $self->preamble ? "# Preamble by $top_class $top_version\n" . $self->preamble : ''; my $postamble = "# Postamble by $top_class $top_version\n" . ($self->postamble || ''); open MAKEFILE, '< Makefile' or die $!; my $makefile = do { local $/; }; close MAKEFILE; $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; $makefile =~ s/^(FULLPERL = .*)/$1 -Iinc/m; $makefile =~ s/^(PERL = .*)/$1 -Iinc/m; open MAKEFILE, '> Makefile' or die $!; print MAKEFILE "$preamble$makefile$postamble"; close MAKEFILE; } sub preamble { my ($self, $text) = @_; $self->{preamble} = $text . $self->{preamble} if defined $text; $self->{preamble}; } sub postamble { my ($self, $text) = @_; $self->{postamble} ||= $self->admin->postamble; $self->{postamble} .= $text if defined $text; $self->{postamble} } 1; __END__ #line 273 Kwiki-0.39/inc/Module/Install/Metadata.pm0000644000076500007650000001150610224251521020152 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Metadata.pm - /Users/ingy/lib/Module/Install/Metadata.pm" package Module::Install::Metadata; use Module::Install::Base; @ISA = qw(Module::Install::Base); $VERSION = '0.04'; use strict 'vars'; use vars qw($VERSION); sub Meta { shift } my @scalar_keys = qw( name module_name version abstract author license distribution_type sign perl_version ); my @tuple_keys = qw(build_requires requires recommends bundles); foreach my $key (@scalar_keys) { *$key = sub { my $self = shift; return $self->{'values'}{$key} unless @_; $self->{'values'}{$key} = shift; return $self; }; } foreach my $key (@tuple_keys) { *$key = sub { my $self = shift; return $self->{'values'}{$key} unless @_; my @rv; while (@_) { my $module = shift or last; my $version = shift || 0; if ($module eq 'perl') { $version =~ s{^(\d+)\.(\d+)\.(\d+)} {$1 + $2/1_000 + $3/1_000_000}e; $self->perl_version($version); next; } my $rv = [$module, $version]; push @{$self->{'values'}{$key}}, $rv; push @rv, $rv; } return @rv; }; } sub features { my $self = shift; while (my ($name, $mods) = splice(@_, 0, 2)) { my $count = 0; push @{$self->{'values'}{'features'}}, ($name => [ map { (++$count % 2 and ref($_) and ($count += $#$_)) ? @$_ : $_ } @$mods ] ); } return @{$self->{'values'}{'features'}}; } sub no_index { my $self = shift; my $type = shift; push @{$self->{'values'}{'no_index'}{$type}}, @_ if $type; return $self->{'values'}{'no_index'}; } sub _dump { my $self = shift; my $package = ref($self->_top); my $version = $self->_top->VERSION; my %values = %{$self->{'values'}}; delete $values{sign}; if (my $perl_version = delete $values{perl_version}) { # Always canonical to three-dot version $perl_version =~ s{^(\d+)\.(\d\d\d)(\d*)}{join('.', $1, int($2), int($3))}e if $perl_version >= 5.006; $values{requires} = [ [perl => $perl_version], @{$values{requires}||[]}, ]; } warn "No license specified, setting license = 'unknown'\n" unless $values{license}; $values{license} ||= 'unknown'; $values{distribution_type} ||= 'module'; $values{name} ||= do { my $name = $values{module_name}; $name =~ s/::/-/g; $name; } if $values{module_name}; if ($values{name} =~ /::/) { my $name = $values{name}; $name =~ s/::/-/g; die "Error in name(): '$values{name}' should be '$name'!\n"; } my $dump = ''; foreach my $key (@scalar_keys) { $dump .= "$key: $values{$key}\n" if exists $values{$key}; } foreach my $key (@tuple_keys) { next unless exists $values{$key}; $dump .= "$key:\n"; foreach (@{$values{$key}}) { $dump .= " $_->[0]: $_->[1]\n"; } } if (my $no_index = $values{no_index}) { push @{$no_index->{'directory'}}, 'inc'; require YAML; local $YAML::UseHeader = 0; $dump .= YAML::Dump({ no_index => $no_index}); } else { $dump .= << "META"; no_index: directory: - inc META } $dump .= "generated_by: $package version $version\n"; return $dump; } sub read { my $self = shift; $self->include_deps( 'YAML', 0 ); require YAML; my $data = YAML::LoadFile( 'META.yml' ); # Call methods explicitly in case user has already set some values. while ( my ($key, $value) = each %$data ) { next unless $self->can( $key ); if (ref $value eq 'HASH') { while (my ($module, $version) = each %$value) { $self->$key( $module => $version ); } } else { $self->$key( $value ); } } return $self; } sub write { my $self = shift; return $self unless $self->is_admin; META_NOT_OURS: { local *FH; if (open FH, "META.yml") { while () { last META_NOT_OURS if /^generated_by: Module::Install\b/; } return $self if -s FH; } } warn "Writing META.yml\n"; open META, "> META.yml" or warn "Cannot write to META.yml: $!"; print META $self->_dump; close META; return $self; } sub version_from { my ($self, $version_from) = @_; require ExtUtils::MM_Unix; $self->version(ExtUtils::MM_Unix->parse_version($version_from)); } sub abstract_from { my ($self, $abstract_from) = @_; require ExtUtils::MM_Unix; $self->abstract( bless( { DISTNAME => $self->name }, 'ExtUtils::MM_Unix') ->parse_abstract($abstract_from) ); } 1; Kwiki-0.39/inc/Module/Install/Scripts.pm0000644000076500007650000000243710224251521020064 0ustar ingyingy00000000000000#line 1 "inc/Module/Install/Scripts.pm - /Users/ingy/lib/Module/Install/Scripts.pm" package Module::Install::Scripts; use Module::Install::Base; @ISA = qw(Module::Install::Base); $VERSION = '0.02'; use strict; use File::Basename (); sub prompt_script { my ($self, $script_file) = @_; my ($prompt, $abstract, $default); foreach my $line ( $self->_read_script($script_file) ) { last unless $line =~ /^#/; $prompt = $1 if $line =~ /^#\s*prompt:\s+(.*)/; $default = $1 if $line =~ /^#\s*default:\s+(.*)/; $abstract = $1 if $line =~ /^#\s*abstract:\s+(.*)/; } unless (defined $prompt) { my $script_name = File::Basename::basename($script_file); $prompt = "Do you want to install '$script_name'"; $prompt .= " ($abstract)" if defined $abstract; $prompt .= '?'; } return unless $self->prompt($prompt, ($default || 'n')) =~ /^[Yy]/; $self->install_script($script_file); } sub install_script { my $self = shift; my $args = $self->makemaker_args; my $exe_files = $args->{EXE_FILES} ||= []; push @$exe_files, @_; } sub _read_script { my ($self, $script_file) = @_; local *SCRIPT; open SCRIPT, $script_file or die "Can't open '$script_file' for input: $!\n"; return [% IF button == edit_preview_button_text %] [% preview_content %]
[% END %]


Kwiki-0.39/lib/Kwiki/Files.pm0000644000076500007650000002400310207375666015732 0ustar ingyingy00000000000000package Kwiki::Files; use Kwiki::Base -Base; use mixin 'Kwiki::Installer'; const class_id => 'files'; const class_title => 'Kwiki Files'; __DATA__ =head1 NAME Kwiki::Files - Kwiki Miscellaneous Files Module =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __index.cgi__ #!/usr/bin/perl use lib 'lib'; use Kwiki; Kwiki->new->debug->process('config*.*', -plugins => 'plugins'); __README__ A Kwiki Welcome =============== Welcome to Kwiki. Obviously you have installed a kwiki. Good job. If it's not working properly, check the Installation Notes below. Remember that the primary source of Kwiki help is: http://www.kwiki.org Cheers, Brian Ingerson (That Kwiki Guy) Kwiki Installation Notes ======================== If you are running an Apache web server, you'll want to add a section like this to your httpd.conf file: Alias /kwiki/ <%PWD%>/ /> Order allow,deny Allow from all AllowOverride All Options ExecCGI AddHandler cgi-script .cgi DirectoryIndex index.cgi Make all your overrides in: config.yaml plugins Don't touch the other files unless you know what you are doing. Kwiki Plugin Installation Notes =============================== 1) Download and install plugins from CPAN 2) Add the new module names to the 'plugins' config file 3) Type 'kwiki -update' __palm90.png__ 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 nAXCdgAAAABJRU5ErkJggg== Kwiki-0.39/lib/Kwiki/Formatter.pm0000644000076500007650000003623310217217121016621 0ustar ingyingy00000000000000package Kwiki::Formatter; use Spoon::Formatter -Base; use mixin 'Kwiki::Installer'; const config_class => 'Kwiki::Config'; const class_id => 'formatter'; const class_title => 'Kwiki Formatter'; const top_class => 'Kwiki::Formatter::Top'; const class_prefix => 'Kwiki::Formatter::'; const all_blocks => [qw(comment wafl_block hr heading ul ol pre table p)]; const all_phrases => [qw( asis wafl_phrase forced titlehyper titlewiki titlemailto hyper wiki mailto ndash mdash strong em u tt del )]; const css_file => 'formatter.css'; sub init { $self->hub->css->add_file($self->css_file); } sub formatter_classes { qw( Spoon::Formatter::WaflPhrase Spoon::Formatter::WaflBlock Line Heading Paragraph Preformatted Comment Ulist Olist Item Table TableRow TableCell Strong Emphasize Underline Delete Inline MDash NDash Asis ForcedLink HyperLink TitledHyperLink TitledMailLink MailLink TitledWikiLink WikiLink ); } ################################################################################ # Blocks ################################################################################ package Kwiki::Formatter::Top; use base 'Spoon::Formatter::Container'; const formatter_id => 'top'; ################################################################################ package Kwiki::Formatter::Comment; use base 'Spoon::Formatter::Unit'; const formatter_id => 'comment'; const html_start => "\n"; sub match { return unless $self->text =~ /^((?:#[\ \t].*\n)+)/m; $self->set_match; } sub text_filter { my $comment = shift; $comment =~ s/^# //gm; $comment =~ s/-/-/g; return $comment; } ################################################################################ package Kwiki::Formatter::Line; use base 'Spoon::Formatter::Unit'; const formatter_id => 'hr'; const pattern_block => qr/^----+\s*\n/m; const html => "
\n"; ################################################################################ package Kwiki::Formatter::Heading; use base 'Spoon::Formatter::Block'; const formatter_id => 'heading'; field 'level'; sub html_start { 'level . '>' } sub html_end { 'level . ">\n" } sub match { return unless $self->text =~ /^(={1,6})\s+(.*?)(\s+=+)?\s*\n+/m; $self->level(length($1)); $self->set_match($2); } ################################################################################ package Kwiki::Formatter::Paragraph; use base 'Spoon::Formatter::Block'; const formatter_id => 'p'; const pattern_block => qr/((?:^(?!(?:[\=\*\0]+ |[\#\|\s]|\.\w+\s*\n|-{4,}\s*\n)).*\S.*\n)+(^\s*\n)*)/m; const html_start => "

\n"; const html_end => "

\n"; ################################################################################ package Kwiki::Formatter::List; use base 'Spoon::Formatter::Container'; const contains_blocks => [qw(li)]; field 'level'; field 'start_level'; field 'tag_stack' => []; sub match { my $bullet = $self->bullet; return unless $self->text =~ /((?:^($bullet).*\n)(?:^\2(?!$bullet).*\n)*)/m; $self->set_match; ($bullet = $2) =~ s/\s//g; $self->level(length($bullet)); return 1; } sub html_start { my $next = $self->next_unit; my $tag_stack = $self->tag_stack; $next->tag_stack($tag_stack) if ref($next) and $next->isa('Kwiki::Formatter::List'); my $level = defined $self->start_level ? $self->start_level : $self->level; push @$tag_stack, ($self->html_end_tag) x $level; return ($self->html_start_tag x $level) . "\n"; } sub html_end { my $level = $self->level; my $tag_stack = $self->tag_stack; my $next = $self->next_unit; my $newline = "\n"; if (ref($next) and $next->isa('Kwiki::Formatter::List')) { my $next_level = $next->level; if ($level < $next_level) { $next->start_level($next_level - $level); $level = 0; } else { $next->start_level(0); $level = $level - $next_level; $newline = ''; } if ($self->level - $level == $next->level and $self->formatter_id ne $next->formatter_id ) { $level++; $next->start_level($next->start_level + 1); } } return join('', reverse splice(@$tag_stack, 0 - $level, $level)) . $newline; } ################################################################################ package Kwiki::Formatter::Ulist; use base 'Kwiki::Formatter::List'; const formatter_id => 'ul'; const html_start_tag => '
    '; const html_end_tag => '
'; const bullet => '\*+\ +'; ################################################################################ package Kwiki::Formatter::Olist; use base 'Kwiki::Formatter::List'; const formatter_id => 'ol'; const html_start_tag => '
    '; const html_end_tag => '
'; const bullet => '0+\ +'; ################################################################################ package Kwiki::Formatter::Item; use base 'Spoon::Formatter::Block'; const formatter_id => 'li'; const html_start => "
  • "; const html_end => "
  • \n"; const bullet => '[0\*]+\ +'; sub match { my $bullet = $self->bullet; return unless $self->text =~ /^$bullet(.*)\n/m; $self->set_match; } ################################################################################ package Kwiki::Formatter::Preformatted; use base 'Spoon::Formatter::Unit'; const formatter_id => 'pre'; const html_start => qq{
    };
    const html_end => "
    \n"; sub match { return unless $self->text =~ /((?:^ +\S.*?\n|^ *\n)+)/m; my $text = $1; $self->set_match; return unless $text =~ /\S/; return 1; } sub text_filter { my $text = shift; $text =~ s/(?<=\n)\s*$//mg; my $indent; for ($text =~ /^( +)/gm) { $indent = length() if not defined $indent or length() < $indent; } $text =~ s/^ {$indent}//gm; $text; } ################################################################################ # XXX Support colspan package Kwiki::Formatter::Table; use base 'Spoon::Formatter::Container'; const formatter_id => 'table'; const contains_blocks => [qw(tr)]; const pattern_block => qr/((^\|.*?\|\n)+)/sm; const html_start => qq{\n}; const html_end => "
    \n"; ################################################################################ package Kwiki::Formatter::TableRow; use base 'Spoon::Formatter::Container'; const formatter_id => 'tr'; const contains_blocks => [qw(td)]; const pattern_block => qr/(^\|.*?\|\n)/sm; const html_start => "\n"; const html_end => "\n"; ################################################################################ package Kwiki::Formatter::TableCell; use base 'Spoon::Formatter::Unit'; const formatter_id => 'td'; field contains_blocks => []; field contains_phrases => []; const table_blocks => [qw(wafl_block hr heading ul ol pre p)]; sub table_phrases { $self->hub->formatter->all_phrases } const html_start => ""; const html_end => "\n"; sub match { return unless $self->text =~ /(\|(\s*.*?\s*)\|)(.*)/sm; $self->start_offset($-[1]); $self->end_offset($3 eq "\n" ? $+[3] : $+[2]); my $text = $2; $text =~ s/^[ \t]*\n?(.*?)[ \t]*$/$1/; $self->text($text); if ($text =~ /\n/) { $self->contains_blocks($self->table_blocks); } else { $self->contains_phrases($self->table_phrases); } return 1; } ################################################################################ # Phrase Classes ################################################################################ package Kwiki::Formatter::Strong; use base 'Spoon::Formatter::Phrase'; use Kwiki ':char_classes'; const formatter_id => 'strong'; const pattern_start => qr/(^|(?<=[^$ALPHANUM]))\*(?=\S)/; const pattern_end => qr/\*(?=[^$ALPHANUM]|\z)/; const html_start => ""; const html_end => ""; ################################################################################ package Kwiki::Formatter::Emphasize; use base 'Spoon::Formatter::Phrase'; use Kwiki ':char_classes'; const formatter_id => 'em'; const pattern_start => qr/(^|(?<=[^$ALPHANUM]))\/(?=\S[^\/]*\/(?=\W|\z))/; const pattern_end => qr/\/(?=[^$ALPHANUM]|\z)/; const html_start => ""; const html_end => ""; ################################################################################ package Kwiki::Formatter::Underline; use base 'Spoon::Formatter::Phrase'; use Kwiki ':char_classes'; const formatter_id => 'u'; const pattern_start => qr/(^|(?<=[^$ALPHANUM]))_(?=\S)/; const pattern_end => qr/_(?=[^$ALPHANUM]|\z)/; const html_start => ""; const html_end => ""; ################################################################################ package Kwiki::Formatter::Inline; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'tt'; const pattern_start => qr/(^|(?<=[^$ALPHANUM]))\[\=/; const pattern_end => qr/\](?=[^$ALPHANUM]|\z)/; const html_start => ""; const html_end => ""; ################################################################################ package Kwiki::Formatter::Delete; use base 'Spoon::Formatter::Phrase'; use Kwiki ':char_classes'; const formatter_id => 'del'; const pattern_start => qr/(^|(?<=[^$ALPHANUM]))-(?=[^\-\s])/; const pattern_end => qr/-(?=[^$ALPHANUM]|\z)/; const html_start => ''; const html_end => ''; ################################################################################ # Empty Phrases (search & replace) ################################################################################ package Kwiki::Formatter::MDash; use base 'Spoon::Formatter::Unit'; const formatter_id => 'mdash'; const pattern_start => qr/\-{3}(?=[^-])/; const html => '—'; ################################################################################ package Kwiki::Formatter::NDash; use base 'Spoon::Formatter::Unit'; const formatter_id => 'ndash'; const pattern_start => qr/\-{2}(?=[^-])/; const html => '–'; ################################################################################ # Much Ado about Linking ################################################################################ package Kwiki::Formatter::ForcedLink; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'forced'; const pattern_start => qr/\[([$WORD]+)\]/; sub html { $self->matched =~ $self->pattern_start; my $target = $1; my $script = $self->hub->config->script_name; my $text = $self->escape_html( $target ); my $page = $self->hub->pages->new_from_name($target); return $target unless $page; my $class = $page->exists ? '' : ' class="empty"'; return qq($target); } ################################################################################ package Kwiki::Formatter::HyperLink; use base 'Spoon::Formatter::Unit'; const formatter_id => 'hyper'; our $pattern = qr{\w+:(?://|\?)\S+?(?=[),.:;]?\s|$)}; const pattern_start => qr/$pattern|!$pattern/; sub html { my $text = $self->escape_html($self->matched); return $text if $text =~ s/^!//; return qq() if $text =~ /(?:jpe?g|gif|png)$/i; return qq($text); } ################################################################################ package Kwiki::Formatter::TitledHyperLink; use base 'Spoon::Formatter::Unit'; const formatter_id => 'titlehyper'; const pattern_start => qr{\[(?:\s*([^\]]+)\s+)?(\w+:(?://|\?)[^\]\s]+)(?:\s+([^\]]+)\s*)?\]}; sub html { my $text = $self->escape_html($self->matched); my ($title1, $target, $title2) = ($text =~ $self->pattern_start); $title1 = '' unless defined $title1; $title2 = '' unless defined $title2; $target =~ s{^\w+:(?!//)}{}; my $title = $title1 . ' ' . $title2; $title =~ s/^\s*(.*?)\s*$/$1/; $title = $target unless $title =~ /\S/; return qq($title); } ################################################################################ package Kwiki::Formatter::WikiLink; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'wiki'; our $pattern = qr/[$UPPER](?=[$WORD]*[$UPPER])(?=[$WORD]*[$LOWER])[$WORD]+/; const pattern_start => qr/$pattern|!$pattern/; sub html { my $page_name = $self->escape_html($self->matched); return $page_name if $page_name =~ s/^!//; my $page = $self->hub->pages->new_from_name($page_name); return $page_name unless $page; return $page->kwiki_link; } ################################################################################ package Kwiki::Formatter::TitledWikiLink; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'titlewiki'; const pattern_start => qr/\[([^\]]*)\s+([$UPPER](?=[$WORD]*[$UPPER])(?=[$WORD]*[$LOWER])[$WORD]+)\]/; sub html { my $text = $self->escape_html($self->matched); my ($label, $page_name) = ($text =~ $self->pattern_start); my $page = $self->hub->pages->new_from_name($page_name); return $label unless $page; return $page->kwiki_link($label); } ################################################################################ package Kwiki::Formatter::MailLink; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'mailto'; our $pattern = qr/[$ALPHANUM][$WORD\+\-\.]*@[$WORD][$WORD\-\.]+/; const pattern_start => qr/$pattern|!$pattern/; sub html { my $text = $self->escape_html( $self->matched ); return $text if $text =~ s/^!//; my $dot = ($text =~ s/(\.+)$//) ? $1 : ''; return qq($text$dot); } ################################################################################ package Kwiki::Formatter::TitledMailLink; use base 'Spoon::Formatter::Unit'; use Kwiki ':char_classes'; const formatter_id => 'titlemailto'; const pattern_start => qr/\[([^\]]+)\s+([$ALPHANUM][$WORD\+\-\.]*@[$WORD][$WORD\-\.]+)\]/; sub html { my $text = $self->escape_html($self->matched); my ($title, $addr) = ($text =~ $self->pattern_start); my $dot = ($addr =~ s/(\.+)$//) ? $1 : ''; return qq($title$dot); } ################################################################################ package Kwiki::Formatter::Asis; use base 'Spoon::Formatter::Unit'; const formatter_id => 'asis'; const pattern_start => qr/\{\{/; const pattern_end => qr/\}\}/; package Kwiki::Formatter; __DATA__ =head1 NAME Kwiki::Formatter - Kwiki Formatter Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __css/formatter.css__ pre.formatter_pre { font-family: monospace; background-color: #eee; padding: 2px; padding-left: 10px; margin-left: 20px; margin-right: 20px; } table.formatter_table { border-collapse: collapse; margin-bottom: .2em; } table.formatter_table td { border: 1px; border-style: solid; padding: .2em; vertical-align: top; } span.wafl_error { color: #f00; text-decoration: underline; Kwiki-0.39/lib/Kwiki/Hub.pm0000644000076500007650000000073610207375666015415 0ustar ingyingy00000000000000package Kwiki::Hub; use Spoon::Hub -Base; sub action { $self->cgi->action || 'display'; } __DATA__ =head1 NAME Kwiki::Hub - Kwiki Hub Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Icons.pm0000644000076500007650000000274510217217121015732 0ustar ingyingy00000000000000package Kwiki::Icons; use Kwiki::Plugin -Base; use mixin 'Kwiki::Installer'; const class_id => 'icons'; const css_file => 'icons.css'; const config_file => 'icons.yaml'; sub class_title { $self->usage; } sub register { my $registry = shift; $registry->add(preload => 'icons'); $registry->add(preference => $self->use_icons); } sub init { super; if ($self->preferences->can('use_icons') and $self->preferences->use_icons->value) { $self->template->add_path($self->icons_path); } } sub use_icons { my $p = $self->new_preference('use_icons'); $p->query('Use icons in toolbar?'); $p->type('boolean'); $p->edit('correct_template_path'); $p->default(1); return $p; } sub correct_template_path { my $pref = shift; if ($pref->new_value) { $self->template->add_path($self->icons_path); } else { $self->template->remove_path($self->icons_path); } } sub icons_path { $self->usage; } sub usage { die "Don't use Kwiki::Icons directly. Use a subclass of it."; } __DATA__ =head1 NAME Kwiki::Icons - Kwiki Icons Plugin Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __config/icons.yaml__ icons_on_by_default: 1 Kwiki-0.39/lib/Kwiki/Installer.pm0000644000076500007650000000202310207375665016622 0ustar ingyingy00000000000000package Kwiki::Installer; use Spoon::Installer -Base; sub set_file_content { # Can't use super here because of mixin squashes things down into one # namespace. May need to make mixins more flexible. my $content = Spoon::Installer::set_file_content($self, @_); my $path = shift; $content = $self->warn_config($content) if $self->file_is_config($path); return $content; } sub file_is_config { my $path = shift; $path =~ /config\/\w+\.yaml$/; } sub warn_config { < =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Javascript.pm0000644000076500007650000000107610207375666017003 0ustar ingyingy00000000000000package Kwiki::Javascript; use Kwiki::WebFile -Base; const class_id => 'javascript'; const default_path_method => 'javascript_path'; conf javascript_path => [ 'javascript' ]; __DATA__ =head1 NAME Kwiki::Javascript - Kwiki Javascript Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Pages.pm0000644000076500007650000001605210216371563015724 0ustar ingyingy00000000000000package Kwiki::Pages; use Kwiki::Base -Base; use mixin 'Kwiki::Installer'; const inline_classes => [qw(Kwiki::Page Kwiki::PageMeta)]; const class_id => 'pages'; const class_title => 'Kwiki Pages'; const page_class => 'Kwiki::Page'; const meta_class => 'Kwiki::PageMeta'; field current => -init => '$self->new_page($self->current_id)'; sub all { grep { $_->is_readable } map { $self->new_page($_->filename) } io($self->current->database_directory)->all_files; } sub all_ids_newest_first { my $path = $self->current->database_directory; # XXX Unix speed hack should be worked around for win32 map {chomp; $_} `ls -1t $path`; } sub recent_by_count { my ($count) = @_; my @page_ids = $self->all_ids_newest_first; splice(@page_ids, $count) if @page_ids > $count; map { $self->new_page($_) } @page_ids; } sub all_since { my ($minutes) = @_; my @pages_since; for my $page_id ($self->all_ids_newest_first) { my $page = $self->new_page($page_id); last if $page->age_in_minutes > $minutes; next unless $page->is_readable; push @pages_since, $page; } return @pages_since; } sub current_id { my $page_name = $self->hub->cgi->page_name || $self->hub->config->main_page; $self->name_to_id($page_name); } sub name_to_id { my $id = $self->uri_escape(shift); } sub name_to_title { (shift); } sub id_to_uri { (shift); } sub id_to_title { $self->uri_unescape(shift); } sub new_page { my $page_id = shift; return if length $page_id > 255; my $page = $self->page_class->new(id => $page_id); $page->metadata($self->new_metadata($page_id)); return $page; } sub new_from_name { my $page_name = shift; my $id = $self->name_to_id($page_name); my $page = $self->new_page($id); return unless $page; $page->title($self->name_to_title($page_name)); return $page; } sub new_metadata { my $page_id = shift or die; $self->meta_class->new(id => $page_id); } package Kwiki::Page; use Kwiki::ContentObject qw(-base !io); use Kwiki ':char_classes'; field class_id => 'page'; field title => -init => '$self->hub->pages->id_to_title($self->id)'; field uri => -init => '$self->hub->pages->id_to_uri($self->id)'; sub all { return ( page_uri => $self->uri, page_title => $self->title, ); } sub database_directory { $self->hub->config->database_directory; } sub content { return $self->{content} = shift if @_; return $self->{content} if defined $self->{content}; $self->load_content; return $self->{content}; } sub metadata { return $self->{metadata} = shift if @_; $self->{metadata} ||= $self->meta_class->new(id => $self->id); return $self->{metadata} if $self->{metadata}->loaded; $self->load_metadata; return $self->{metadata}; } sub update { $self->metadata->update($self); return $self; } sub kwiki_link { my ($label) = @_; my $page_uri = $self->uri; $label = $self->title unless defined $label; return $label unless $self->is_readable; my $script = $self->hub->config->script_name; my $class = $self->active ? '' : ' class="empty"'; qq($label); } sub edit_by_link { my $user_name = $self->metadata->edit_by || 'UnknownUser'; $user_name = $self->hub->config->user_default_name if $user_name =~ /[^$ALPHANUM]/; my $page = $self->hub->pages->new_page($user_name); $page->kwiki_link; } sub edit_time { my $edit_time = $self->metadata->edit_unixtime || $self->modified_time; return $self->hub->have_plugin('time_zone') ? $self->hub->time_zone->format($edit_time) : $self->format_time($edit_time); } sub format_time { my $unix_time = shift; my $formatted = scalar gmtime $unix_time; $formatted .= ' GMT' unless $formatted =~ /GMT$/; return $formatted; } #XXX This is a bad idea. io is the IO::All constructor. Making it into a # method is problematic sub io { Kwiki::io($self->file_path)->file; } sub modified_time { $self->io->mtime || 0; } sub age { $self->age_in_minutes; } sub age_in_minutes { $self->age_in_seconds / 60; } sub age_in_seconds { return $self->{age_in_seconds} = shift if @_; return $self->{age_in_seconds} if defined $self->{age_in_seconds}; my $path = $self->database_directory; my $page_id = $self->id; return $self->{age_in_seconds} = (time - $self->modified_time); } sub to_html { my $content = @_ ? shift : $self->content; $self->hub->formatter->text_to_html($content); } sub history { $self->hub->archive->history($self); } sub revision_number { $self->hub->archive->revision_number($self); } sub revision_numbers { $self->hub->archive->revision_numbers($self, @_); } package Kwiki::PageMeta; use Spoon::MetadataObject -base; use Kwiki::Plugin -base; const class_id => 'page_metadata'; field loaded => 0; field edit_by => ''; field edit_time => ''; field edit_unixtime => ''; field edit_address => ''; sub sort_order { qw(edit_by edit_time edit_unixtime edit_address) } sub file_path { join '/', $self->plugin_directory, $self->id; } sub load { $self->loaded(1); my $file_path = $self->file_path; return unless -f $file_path; my $hash = $self->parse_yaml_file($file_path); $self->from_hash($hash); } sub update { my $page = shift; $self->edit_by($self->hub->users->current->name); my $unixtime = time; $self->edit_time(scalar gmtime($unixtime)); $self->edit_unixtime($unixtime); $self->edit_address($self->get_edit_address); return $self; } sub get_edit_address { $ENV{HTTP_X_FORWARDED_FOR} || $ENV{REMOTE_ADDR} || ''; } sub store { my $file_path = $self->file_path; my $hash = $self->to_hash; $self->print_yaml_file($file_path, $hash); } package Kwiki::Pages; __DATA__ =head1 NAME Kwiki::Pages - Kwiki Pages Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __!database/HomePage__ === Welcome to Your New Kwiki! You have successfully installed a new Kwiki. Now you should /edit this page/ and start adding NewPages. For help on Kwiki syntax and other Kwiki issues, visit http://www.kwiki.org/?KwikiHelpIndex. If this installation looks more mundane than you had expected after visiting Kwiki sites like http://www.kwiki.org, you need to install some *Kwiki plugins*. Some of the basic plugins you might want are: * Kwiki::!RecentChanges * Kwiki::Search * Kwiki::!UserPreferences * Kwiki::!UserName * Kwiki::Archive::Rcs * Kwiki::Revisions These plugin modules are available on [CPAN http://search.cpan.org/search?query=kwiki&mode=dist]. Visit http://www.kwiki.org/?KwikiPluginInstallation to learn more about installing plugins. --[http://www.kwiki.org/?BrianIngerson Brian Ingerson] Kwiki-0.39/lib/Kwiki/Pane.pm0000644000076500007650000000464510207375665015564 0ustar ingyingy00000000000000package Kwiki::Pane; use Kwiki::Plugin -Base; use mixin 'Kwiki::Installer'; sub order { () } sub pane_unit { $self->class_id } sub register { my $registry = shift; $registry->add(preload => $self->class_id); } sub html { return $self->{html} if defined $self->{html}; my @all = $self->pages->current->all; my $pane_info = $self->pane_info; my $params_method = $self->class_id . '_params'; my @units = grep { defined $_ and do { my $button = $_; $button =~ s///gs; $button =~ /\S/; } } map { $self->show($_) ? $self->template->process( $_->{template}, @all, $_->{params_class} ? do { my $class_id = $_->{params_class}; $self->hub->$class_id->$params_method } : () ) : undef } map { $pane_info->{$_}; } $self->ordered_unit_ids; $self->{html} = $self->template->process($self->pane_template, units => \ @units, ); } sub pane_info { my $units = $self->hub->registry->lookup->{$self->pane_unit} or return {}; my $info; for my $unit_id (keys %$units) { my $array = $units->{$unit_id}; $info->{$unit_id} = {@{$array}[1..$#{$array}]}; } return $info; } sub ordered_unit_ids { my $lookup = $self->hub->registry->lookup; my @unit_ids = map { @{$lookup->{add_order}{$_->{id}}{$self->pane_unit} || []}; } @{$lookup->plugins}; my @ordered_unit_ids; for my $unit_id ($self->order) { for (my $i = 0; $i < @unit_ids; $i++) { if ($unit_id eq $unit_ids[$i]) { push @ordered_unit_ids, splice @unit_ids, $i, 1; last; } } } (@ordered_unit_ids, @unit_ids); } sub show { my $unit = shift; my $action = $self->hub->action; my $show = $unit->{show_for}; if (defined $show) { for (ref($show) ? (@$show) : ($show)) { return 1 if $_ eq $action; } return 0; } my $omit = $unit->{omit_for}; if (defined $omit) { for (ref($omit) ? (@$omit) : ($omit)) { return 0 if $_ eq $action; } return 1; } my $pref = $unit->{show_if_preference}; if (defined $pref) { return $self->preferences->$pref->value; } return 1; } Kwiki-0.39/lib/Kwiki/Plugin.pm0000644000076500007650000000436210216602103016107 0ustar ingyingy00000000000000package Kwiki::Plugin; use Spoon::Plugin -Base; stub 'class_id'; const cgi_class => ''; const config_file => ''; const css_file => ''; const javascript_file => ''; const screen_template => 'theme_screen.html'; const class_title_prefix => 'Kwiki'; const config_class => 'Kwiki::Config'; field cgi => -init => '$self->hub->cgi'; field config => -init => '$self->hub->config'; field users => -init => '$self->hub->users'; field pages => -init => '$self->hub->pages'; field template => -init => '$self->hub->template'; field preferences => -init => '$self->users->current->preferences'; sub new { return $self if ref $self; super; } sub init { $self->init_cgi; $self->config->add_file($self->config_file); $self->hub->css->add_file($self->css_file); $self->hub->javascript->add_file($self->javascript_file); } sub init_cgi { my $class = $self->cgi_class or return; eval qq{require $class} unless $class->can('new'); my $package = ref($self); field -package => $package, 'cgi'; my $object = $class->new; $object->init; $self->cgi($object); } sub render_screen { $self->template_process($self->screen_template, content_pane => $self->class_id . '_content.html', @_, ); } sub template_process { $self->hub->css->add_file($self->css_file) if $self->css_file; my $template = shift; $self->template->process($template, self => $self, $self->pages->current->all, $self->cgi->all, @_, ); } sub redirect { $self->hub->headers->redirect($self->redirect_url(@_)); return ''; } sub redirect_url { my $target = shift; return $target if $target =~ /^(https?:|\/)/i or $target =~ /\?/; CGI::url(-full => 1) . '?' . $target; } sub new_preference { $self->hub->preferences->new_preference(scalar(caller), @_); } __DATA__ =head1 NAME Kwiki::Plugin - Kwiki Plugin Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Preferences.pm0000644000076500007650000000717310216371656017135 0ustar ingyingy00000000000000package Kwiki::Preferences; use Kwiki::Base -Base; field class_id => 'preferences'; const preference_class => 'Kwiki::Preference'; field objects_by_class => {}; sub load { my $values = shift; my $prefs = $self->hub->registry->lookup->preference; for (sort keys %$prefs) { my $array = $prefs->{$_}; my $class_id = $array->[0]; my $hash = {@{$array}[1..$#{$array}]} or next; next unless $hash->{object}; my $object = $hash->{object}->clone; $object->value($values->{$_}); push @{$self->objects_by_class->{$class_id}}, $object; field($_); $self->$_($object); } return $self; } sub new_preferences { my $values = shift; my $new = bless {}, ref $self; $new->load($values); return $new; } sub new_preference { $self->preference_class->new(@_); } #------------------------------------------------------------------------------# package Kwiki::Preference; use Kwiki::Base '-base'; field 'id'; field 'name'; field 'description'; field 'query'; field 'type'; field 'choices'; field 'default'; field 'handler'; field 'owner_id'; field 'size' => 20; field 'edit'; field 'new_value'; field 'error'; sub new() { my $class = shift; my $owner = shift; my $self = bless {}, $class; my $id = shift || ''; $self->id($id); my $name = $id; $name =~ s/_/ /g; $name =~ s/\b(.)/\u$1/g; $self->name($name); $self->query("$name?"); $self->type('boolean'); $self->default(0); $self->handler("${id}_handler"); $self->owner_id($owner->class_id); return $self; } sub value { return $self->{value} = shift if @_; return defined $self->{value} ? $self->{value} : $self->default; } sub value_label { my $choices = $self->choices or return ''; return ${{@$choices}}{$self->value} || ''; } sub form_element { my $type = $self->type; return $self->$type; } sub input { my $name = $self->owner_id . '__' . $self->id; my $value = $self->value; my $size = $self->size; return < END } sub boolean { my $name = $self->owner_id . '__' . $self->id; my $value = $self->value; my $checked = $value ? 'checked="checked"' : ''; return < END } sub radio { my $i = 1; my @choices = @{$self->choices}; my @values = grep {$i++ % 2} @choices; my $value = $self->value; join "\n", '
    ', CGI::radio_group( -name => $self->owner_id . '__' . $self->id, -values => \@values, -default => $value, -labels => { @choices }, -override => 1, -linebreak=>'true', ), '
    '; } sub pulldown { my $i = 1; my @choices = @{$self->choices}; my @values = grep {$i++ % 2} @choices; my $value = $self->value; CGI::popup_menu( -name => $self->owner_id . '__' . $self->id, -values => \@values, -default => $value, -labels => { @choices }, -override => 1, ); } __DATA__ =head1 NAME Kwiki::Preferences - Kwiki Preferences Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Registry.pm0000644000076500007650000000344210207375665016503 0ustar ingyingy00000000000000package Kwiki::Registry; use Spoon::Registry '-Base'; sub add { my ($key, $value) = @_; return super unless $key eq 'preference' and @_ == 2; super($key, $value->id, object => $value); } sub not_a_plugin { my $class_name = shift; die <validate_prerequisite or return; return 1; } sub validate_prerequisite { for my $hashlet (@{$self->lookup->{plugins}}) { my $class_id = $hashlet->{id}; my $prereqs = $self->lookup->{add_order}{$class_id}{prerequisite} or next; for my $prereq (@$prereqs) { $self->missing_prerequisite($class_id, $prereq) unless defined $self->lookup->{classes}{$prereq}; } } return 1; } sub missing_prerequisite { my ($class_id, $prereq) = @_; my $class_name = $self->lookup->{classes}{$class_id}; die "Missing prerequisite plugin '$prereq' for $class_name\n"; } __DATA__ =head1 NAME Kwiki::Registry - Kwiki Registry Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Status.pm0000644000076500007650000000112410207375666016152 0ustar ingyingy00000000000000package Kwiki::Status; use Kwiki::Pane -Base; const class_id => 'status'; const pane_template => 'status_pane.html'; __DATA__ =head1 NAME Kwiki::Status - Kwiki Status Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __template/tt2/status_pane.html__
    [% units.join("
    ") %]
    Kwiki-0.39/lib/Kwiki/Template/0000755000076500007650000000000010573352515016100 5ustar ingyingy00000000000000Kwiki-0.39/lib/Kwiki/Template/TT2.pm0000644000076500007650000000102410207375666017052 0ustar ingyingy00000000000000package Kwiki::Template::TT2; use Spoon::Template::TT2 -Base; use Spoon::Base 'conf'; conf template_path => [ './template/tt2' ]; __DATA__ =head1 NAME Kwiki::Template::TT2 - Kwiki Template Toolkit Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Template.pm0000644000076500007650000000067510207375666016454 0ustar ingyingy00000000000000package Kwiki::Template; use Spoon::Template -Base; __DATA__ =head1 NAME Kwiki::Template - Kwiki Template Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Theme/0000755000076500007650000000000010573352515015367 5ustar ingyingy00000000000000Kwiki-0.39/lib/Kwiki/Theme/Basic.pm0000644000076500007650000000305310207375665016754 0ustar ingyingy00000000000000package Kwiki::Theme::Basic; use Kwiki::Theme -Base; const theme_id => 'basic'; const class_title => 'Basic Theme'; __DATA__ =head1 NAME Kwiki::Theme::Basic - Kwiki Basic Theme =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __theme/basic/template/tt2/theme_screen.html__ [%- INCLUDE theme_html_doctype.html %] [% INCLUDE theme_html_begin.html %]

    [% INCLUDE theme_content_pane.html %]
    [% INCLUDE theme_html_end.html -%] __theme/basic/css/kwiki.css__ #logo_pane { text-align: center; } #logo_pane img { width: 90px; } #group { width: 100%; } #group_1 { vertical-align: top; } #group_2 { vertical-align: top; width: 125px; } body { background:#fff; } h1, h2, h3, h4, h5, h6 { margin: 0px; padding: 0px; font-weight: bold; } .error, .empty { color: #f00; } div.navigation a:visited { color: #00f; } Kwiki-0.39/lib/Kwiki/Theme.pm0000644000076500007650000001071710207375666015741 0ustar ingyingy00000000000000package Kwiki::Theme; use Kwiki::Plugin -Base; use mixin 'Kwiki::Installer'; const class_id => 'theme'; sub register { my $register = shift; $register->add(preload => 'theme', priority => 1, ); $register->add(prerequisite => 'toolbar'); $register->add(prerequisite => 'widgets'); $register->add(prerequisite => 'status'); } const default_template_path => "theme/%s/template/tt2"; const default_css_path => "theme/%s/css"; const default_javascript_path => "theme/%s/javascript"; const default_css_file => 'kwiki.css'; const default_javascript_file => ''; sub init { super; my $theme_id = $self->theme_id; my $template_path = sprintf $self->default_template_path, $theme_id; $self->template->add_path($template_path) if -e $template_path; my $css_path = sprintf $self->default_css_path, $theme_id; $self->hub->css->add_path($css_path) if -e $css_path; $self->hub->css->add_file (ref $self->default_css_file ? @{$self->default_css_file} : $self->default_css_file); my $javascript_path = sprintf $self->default_javascript_path, $theme_id; $self->hub->javascript->add_path($javascript_path) if -e $javascript_path; $self->hub->javascript->add_file (ref $self->default_javascript_file ? @{$self->default_javascript_file} : $self->default_javascript_file); $self->hub->cookie; } sub resolve_install_path { sprintf shift, $self->theme_id; } __DATA__ =head1 NAME Kwiki::Theme - Kwiki Theme Plugin =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __css/icons.css__ div.toolbar img { margin: 0; padding: 0; border: 0; vertical-align: middle; } __template/tt2/kwiki_doctype.html__ __template/tt2/kwiki_begin.html__ [% IF hub.action == 'display' || hub.action == 'edit' || hub.action == 'revisions' %] [% hub.cgi.page_name %] - [% END %] [% IF hub.action != 'display' %] [% self.class_title %] - [% END %] [% site_title %] [%# FOR link = hub.links.all -%] [%# END %] [% FOR css_file = hub.css.files -%] [% IF css_file -%] [% END -%] [% END -%] [% FOR javascript_file = hub.javascript.files -%] [% IF javascript_file -%] [% END -%] [% END -%] __template/tt2/kwiki_end.html__ __theme/%s/template/tt2/theme_screen.html__ [%- INCLUDE kwiki_screen.html -%] __theme/%s/template/tt2/theme_html_doctype.html__ [%- INCLUDE kwiki_doctype.html %] __theme/%s/template/tt2/theme_html_begin.html__ [%- INCLUDE kwiki_begin.html %] __theme/%s/template/tt2/theme_html_end.html__ [% INCLUDE kwiki_end.html -%] __theme/%s/template/tt2/theme_logo_pane.html__
    Kwiki Logo
    __theme/%s/template/tt2/theme_title_pane.html__

    [% screen_title || self.class_title %]

    __theme/%s/template/tt2/theme_toolbar_pane.html__
    [% hub.toolbar.html %] [% INCLUDE theme_login_pane.html %]
    __theme/%s/template/tt2/theme_login_pane.html__ [% IF hub.have_plugin('user_name') %] [% INCLUDE user_name_title.html %] [% END %] __theme/%s/template/tt2/theme_status_pane.html__
    [% hub.status.html %]
    __theme/%s/template/tt2/theme_widgets_pane.html__
    [% hub.widgets.html %]
    __theme/%s/template/tt2/theme_content_pane.html__
    [% INCLUDE $content_pane %]
    __theme/%s/template/tt2/theme_toolbar2_pane.html__
    [% hub.toolbar.html %]
    Kwiki-0.39/lib/Kwiki/Toolbar.pm0000644000076500007650000000166410207375666016302 0ustar ingyingy00000000000000package Kwiki::Toolbar; use Kwiki::Pane -Base; const class_id => 'toolbar'; const pane_template => 'toolbar_pane.html'; const css_file => 'toolbar.css'; const config_file => 'toolbar.yaml'; sub order { @{$self->config->toolbar_order}; } __DATA__ =head1 NAME Kwiki::Toolbar - Kwiki Toolbar Plugin =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __template/tt2/toolbar_pane.html__
    [% units.join('   ') %]
    __config/toolbar.yaml__ toolbar_order: - search_box - home_button - recent_changes_button - user_preferences_button - new_page_button - edit_button - revisions_button - revisions_controls __css/toolbar.css__ div.toolbar { } Kwiki-0.39/lib/Kwiki/Users.pm0000644000076500007650000000344310216371741015764 0ustar ingyingy00000000000000package Kwiki::Users; use Kwiki::Base -Base; use mixin 'Kwiki::Installer'; const class_id => 'users'; const class_title => 'Kwiki Users'; const user_class => 'Kwiki::User'; sub init { $self->hub->config->add_file('user.yaml'); } sub all { ($self->current); } sub all_ids { ($self->current->id); } sub current { return $self->{current} = shift if @_; return $self->{current} if defined $self->{current}; my $user_id = $ENV{REMOTE_USER} || ''; $self->{current} = $self->new_user($user_id); } sub new_user { $self->user_class->new(id => shift); } package Kwiki::User; use base 'Kwiki::Base'; field 'id'; field 'name' => ''; sub new { $self = super; $self->set_user_name; return $self; } sub set_user_name { return unless $self->is_in_cgi; my $name = ''; $name = $self->preferences->user_name->value if $self->preferences->can('user_name'); $name ||= $self->hub->config->user_default_name; $self->name($name); } sub preferences { return $self->{preferences} = shift if @_; return $self->{preferences} if defined $self->{preferences}; my $preferences = $self->hub->preferences; $self->{preferences} = $preferences->new_preferences($self->preference_values); } sub preference_values { $self->hub->cookie->jar->{preferences} || {}; } package Kwiki::Users; __DATA__ =head1 NAME Kwiki::Users - Kwiki Users Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __config/user.yaml__ user_default_name: AnonymousGnome Kwiki-0.39/lib/Kwiki/WebFile.pm0000644000076500007650000000215410207375665016207 0ustar ingyingy00000000000000package Kwiki::WebFile; use Kwiki::Base -Base; use Spoon::Base 'conf'; our @EXPORT = qw(conf); field path => []; field files => []; const default_path_method => 'default_path'; sub init { my $method = $self->default_path_method; $self->add_path(@{$self->$method}); } sub add_file { my $file = shift or return; my $file_path = ''; for (@{$self->path}) { $file_path = "$_/$file", last if -f "$_/$file"; } my $files = $self->files; @$files = grep { not /\/$file$/ } @$files; push @$files, $file_path; } sub files_which_exist { grep {io->file($_)->exists} @{$self->files}; } sub add_path { unshift @{$self->path}, @_; } sub clear_files { $self->files([]); } __DATA__ =head1 NAME Kwiki::WebFile - Super Class for CSS & Javascript =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/lib/Kwiki/Widgets.pm0000644000076500007650000000117010207375665016275 0ustar ingyingy00000000000000package Kwiki::Widgets; use Kwiki::Pane -Base; const class_id => 'widgets'; const pane_template => 'widgets_pane.html'; const pane_unit => 'widget'; __DATA__ =head1 NAME Kwiki::Widgets - Kwiki Widgets Base Class =head1 SYNOPSIS =head1 DESCRIPTION =head1 AUTHOR Brian Ingerson =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut __template/tt2/widgets_pane.html__
    [% units.join("
    ") %]
    Kwiki-0.39/lib/Kwiki.pm0000644000076500007650000001532010573352337014666 0ustar ingyingy00000000000000package Kwiki; use Spoon 0.22 -Base; our $VERSION = '0.39'; const config_class => 'Kwiki::Config'; sub process { my $hub = $self->load_hub(@_); $hub->registry->load; $hub->add_hooks; $hub->pre_process; my $html = $hub->process; if (defined $html) { $hub->headers->print; $self->utf8_encode($html); # With mod_perl < 1.27 and Perl >= 5.8.0, STDOUT does not get # tied to Apache.pm properly. exists $ENV{MOD_PERL} ? Apache->request->print($html) : print $html; } close STDOUT unless $self->using_debug; $hub->post_process; return $self; } __DATA__ =head1 NAME Kwiki - The Kwiki Wiki Building Framework =head1 KWIKI 2.0 STOP. Don't install this CPAN module! Read this section to find out why... Kwiki-0.38 and the large collection of Kwiki CPAN modules has been relatively stable on CPAN for the last couple years. Being stable also means being undeveloped. In December 2006, the Kwiki community started actively developing Kwiki again. We call the revitalized project Kwiki 2.0. This is not a version number (at least not yet), but a code name for the effort. Some goals of Kwiki 2.0 are: * Make Kwiki easier to install and maintain * Make Kwiki fast * Make Kwiki plugins easier to develop * Make Kwiki more fun We've made a lot of headway on these goals and other goals too. Kwiki is *really* simple to install now. _All_ the Perl dependencies come with Kwiki, and are /preinstalled/. This means you just need Perl 5.8.3 and a web server. Well actually we give you a web server too! NOTE: /Preinstalled/ means that the modules are all linked into a lib tree that is separate from your installed Perl modules. This is good for several reasons: 1) Installing modules takes a lot of time. 2) Kwiki is guaranteed to have module versions that work. 3) Kwiki doesn't change anything about your system's Perl lib. 4) You can delete all the modules by just deleting the Kwiki checkout. 5) Upgrading Kwiki is simple as 'svn update'! 6) You can install Kwiki without root permissions. Also Kwiki is now smoking fast if you use Kwiki::FastCGI. There are also some new caching modules that make Kwiki even faster still. The important part is this: all the new stuff is not yet on CPAN. If you want to install Kwiki, get it from our subversion repository (highly recommended) or tarball downloads. You will be amazed at how simple and fast it is to install the new Kwiki which comes with nearly 500 Perl modules. The longest part is simply checking out the repository. See L for details. Eventually all this work will make it back to CPAN, but likely not for a while. Here's a list of references for more information: * http://www.kwiki.org - Main Kwiki Site * http://www.kwiki.org/?KwikiNews - Kwiki News * http://svn.kwiki.org/kwiki/trunk/ - Kwiki SVN Repository * http://trac.kwiki.org/trac/timeline - Kwiki Project Management * #kwiki on irc.freenode.net - Kwiki IRC Channel * http://www.kwiki.org/downloads/ - Kwiki downloads * http://doolittle.kwiki.org/ - Kwiki Documentation Wiki Finally, there are generally a good amount of helpful people on IRC. Please drop by sometime! Cheers, Ingy Here's the old Kwiki.pm doc. It might be a little out of date... =head1 SYNOPSIS > kwiki -new cgi-bin/my-kwiki Kwiki software installed! Point your browser at this location. =head1 NOTE If you are impatient (don't worry, that's a good thing!) read L to get the details on how to install and configure a new Kwiki wiki in record time. =head1 DESCRIPTION A Wiki is a website that allows its users to add pages, and edit any existing pages. It is one of the most popular forms of web collaboration. If you are new to wiki, visit http://c2.com/cgi/wiki?WelcomeVisitors which is possibly the oldest wiki, and has lots of information about how wikis work. Kwiki is a Perl wiki implementation based on the Spoon application architecture and using the Spiffy object orientation model. The major goals of Kwiki are that it be easy to install, maintain and extend. All the features of a Kwiki wiki come from plugin modules. The base installation comes with the bare minimum plugins to make a working Kwiki. To make a really nice Kwiki installation you need to install additional plugins. Which plugins you pick is entirely up to you. Another goal of Kwiki is that every installation will be unique. When there are hundreds of plugins available, this will hopefully be the case. =head1 CGI::Kwiki Kwiki is the successor of the popular CGI::Kwiki software. It is a complete refactoring of that code. The new code has a lovely plugin API and is much cleaner and extendable on all fronts. There is currently no automated way to upgrade a CGI::Kwiki installation to Kwiki. It's actually quite easy to do by hand. Instructions on how to do it are here: http://www.kwiki.org/?KwikiMigrationByHand =head1 DOCUMENTATION All of the future Kwiki module documentation is being written at the http://doc.kwiki.org/ wiki. Check there for the latest doc, and help improve it. Each successive release of Kwiki will include the latest doc from that site. =head1 CREDITS I am currently employed by Socialtext, Inc. They make high quality social software for enterprise deployment. Socialtext has a bold new vision of building their products over Open Source software and returning the generic source code to the community. This results in a win/win effect for both entities. You get this shiny new wiki framework, and Socialtext can take advantage of your plugins and bug fixes. The Kwiki project would not be where it is now without their support. I thank them. Of particular note, Dave Rolsky and Chris Dent are two current Socialtext employees that have made significant contributions to Kwiki. --- Iain Truskett was probably the most active Kwiki community hacker before his untimely death in December 2003. The underlying foundation of Kwiki has been named "Spoon" in his honor. Rest in peace Spoon. --- Ian (what's with all these Iai?ns??) Langworth has become a new Kwiki warrior. He helped a lot with the maiden release. Expect a lot of plugins to come from him! Thanks Ian. --- Finally, big props to all the folks on http://www.kwiki.org and irc://irc.freenode.net/#kwiki. Thanks for all the support! =head1 SEE ALSO Kwiki::Command =head1 AUTHOR Ingy döt Net =head1 COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. Copyright (c) 2007. Ingy döt Net. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html =cut Kwiki-0.39/Makefile.PL0000644000076500007650000000043310573352451014452 0ustar ingyingy00000000000000use inc::Module::Install; name('Kwiki'); author('Ingy döt Net '); abstract('Kwiki Wiki Framework'); license('perl'); version_from('lib/Kwiki.pm'); requires(qw( perl 5.6.1 Spoon 0.22 Storable 0 )); install_script('kwiki'); check_nmake(); &WriteAll(); Kwiki-0.39/MANIFEST0000644000076500007650000000214210224251517013622 0ustar ingyingy00000000000000Changes inc/Module/Install.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Scripts.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm kwiki lib/Kwiki.pm lib/Kwiki/Archive.pm lib/Kwiki/Base.pm lib/Kwiki/BrowserDetect.pm lib/Kwiki/CGI.pm lib/Kwiki/Command.pm lib/Kwiki/Config.pm lib/Kwiki/ContentObject.pm lib/Kwiki/Cookie.pm lib/Kwiki/CSS.pm lib/Kwiki/Display.pm lib/Kwiki/Edit.pm lib/Kwiki/Files.pm lib/Kwiki/Formatter.pm lib/Kwiki/Hub.pm lib/Kwiki/Icons.pm lib/Kwiki/Installer.pm lib/Kwiki/Javascript.pm lib/Kwiki/Pages.pm lib/Kwiki/Pane.pm lib/Kwiki/Plugin.pm lib/Kwiki/Preferences.pm lib/Kwiki/Registry.pm lib/Kwiki/Status.pm lib/Kwiki/Template.pm lib/Kwiki/Template/TT2.pm lib/Kwiki/Theme.pm lib/Kwiki/Theme/Basic.pm lib/Kwiki/Toolbar.pm lib/Kwiki/Users.pm lib/Kwiki/WebFile.pm lib/Kwiki/Widgets.pm Makefile.PL MANIFEST This list of files META.yml README t/compile.t t/cycle.t t/Formatter.pm t/formatter1.t t/formatter2.t t/formatter3.t t/formatter4.t t/formatter_cycle.t t/TestChunks.pm Kwiki-0.39/META.yml0000644000076500007650000000040710573346101013745 0ustar ingyingy00000000000000name: Kwiki version: 0.38 abstract: Kwiki Wiki Framework author: Ingy döt Net license: perl distribution_type: module requires: perl: 5.6.1 Spoon: 0.22 Storable: 0 no_index: directory: - inc generated_by: Module::Install version 0.36 Kwiki-0.39/README0000644000076500007650000001462410573352366013374 0ustar ingyingy00000000000000NAME Kwiki - The Kwiki Wiki Building Framework KWIKI 2.0 STOP. Don't install this CPAN module! Read this section to find out why... Kwiki-0.38 and the large collection of Kwiki CPAN modules has been relatively stable on CPAN for the last couple years. Being stable also means being undeveloped. In December 2006, the Kwiki community started actively developing Kwiki again. We call the revitalized project Kwiki 2.0. This is not a version number (at least not yet), but a code name for the effort. Some goals of Kwiki 2.0 are: * Make Kwiki easier to install and maintain * Make Kwiki fast * Make Kwiki plugins easier to develop * Make Kwiki more fun We've made a lot of headway on these goals and other goals too. Kwiki is *really* simple to install now. _All_ the Perl dependencies come with Kwiki, and are /preinstalled/. This means you just need Perl 5.8.3 and a web server. Well actually we give you a web server too! NOTE: /Preinstalled/ means that the modules are all linked into a lib tree that is separate from your installed Perl modules. This is good for several reasons: 1) Installing modules takes a lot of time. 2) Kwiki is guaranteed to have module versions that work. 3) Kwiki doesn't change anything about your system's Perl lib. 4) You can delete all the modules by just deleting the Kwiki checkout. 5) Upgrading Kwiki is simple as 'svn update'! 6) You can install Kwiki without root permissions. Also Kwiki is now smoking fast if you use Kwiki::FastCGI. There are also some new caching modules that make Kwiki even faster still. The important part is this: all the new stuff is not yet on CPAN. If you want to install Kwiki, get it from our subversion repository (highly recommended) or tarball downloads. You will be amazed at how simple and fast it is to install the new Kwiki which comes with nearly 500 Perl modules. The longest part is simply checking out the repository. See for details. Eventually all this work will make it back to CPAN, but likely not for a while. Here's a list of references for more information: * http://www.kwiki.org - Main Kwiki Site * http://www.kwiki.org/?KwikiNews - Kwiki News * http://svn.kwiki.org/kwiki/trunk/ - Kwiki SVN Repository * http://trac.kwiki.org/trac/timeline - Kwiki Project Management * #kwiki on irc.freenode.net - Kwiki IRC Channel * http://www.kwiki.org/downloads/ - Kwiki downloads * http://doolittle.kwiki.org/ - Kwiki Documentation Wiki Finally, there are generally a good amount of helpful people on IRC. Please drop by sometime! Cheers, Ingy Here's the old Kwiki.pm doc. It might be a little out of date... SYNOPSIS > kwiki -new cgi-bin/my-kwiki Kwiki software installed! Point your browser at this location. NOTE If you are impatient (don't worry, that's a good thing!) read Kwiki::Command to get the details on how to install and configure a new Kwiki wiki in record time. DESCRIPTION A Wiki is a website that allows its users to add pages, and edit any existing pages. It is one of the most popular forms of web collaboration. If you are new to wiki, visit http://c2.com/cgi/wiki?WelcomeVisitors which is possibly the oldest wiki, and has lots of information about how wikis work. Kwiki is a Perl wiki implementation based on the Spoon application architecture and using the Spiffy object orientation model. The major goals of Kwiki are that it be easy to install, maintain and extend. All the features of a Kwiki wiki come from plugin modules. The base installation comes with the bare minimum plugins to make a working Kwiki. To make a really nice Kwiki installation you need to install additional plugins. Which plugins you pick is entirely up to you. Another goal of Kwiki is that every installation will be unique. When there are hundreds of plugins available, this will hopefully be the case. CGI::Kwiki Kwiki is the successor of the popular CGI::Kwiki software. It is a complete refactoring of that code. The new code has a lovely plugin API and is much cleaner and extendable on all fronts. There is currently no automated way to upgrade a CGI::Kwiki installation to Kwiki. It's actually quite easy to do by hand. Instructions on how to do it are here: http://www.kwiki.org/?KwikiMigrationByHand DOCUMENTATION All of the future Kwiki module documentation is being written at the http://doc.kwiki.org/ wiki. Check there for the latest doc, and help improve it. Each successive release of Kwiki will include the latest doc from that site. CREDITS I am currently employed by Socialtext, Inc. They make high quality social software for enterprise deployment. Socialtext has a bold new vision of building their products over Open Source software and returning the generic source code to the community. This results in a win/win effect for both entities. You get this shiny new wiki framework, and Socialtext can take advantage of your plugins and bug fixes. The Kwiki project would not be where it is now without their support. I thank them. Of particular note, Dave Rolsky and Chris Dent are two current Socialtext employees that have made significant contributions to Kwiki. --- Iain Truskett was probably the most active Kwiki community hacker before his untimely death in December 2003. The underlying foundation of Kwiki has been named "Spoon" in his honor. Rest in peace Spoon. --- Ian (what's with all these Iai?ns??) Langworth has become a new Kwiki warrior. He helped a lot with the maiden release. Expect a lot of plugins to come from him! Thanks Ian. --- Finally, big props to all the folks on http://www.kwiki.org and irc://irc.freenode.net/#kwiki. Thanks for all the support! SEE ALSO Kwiki::Command AUTHOR Ingy döt Net COPYRIGHT Copyright (c) 2004. Brian Ingerson. All rights reserved. Copyright (c) 2007. Ingy döt Net. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html Kwiki-0.39/t/0000755000076500007650000000000010573352515012744 5ustar ingyingy00000000000000Kwiki-0.39/t/compile.t0000644000076500007650000000054610207375665014573 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use Test::More 'no_plan'; use IO::All; for (io('lib')->All_Files) { my $name = $_->name; $name =~ s/^lib\/(.*\.pm)$/$1/ or next; if ($name eq 'Kwiki/BrowserDetect.pm') { eval "require HTTP::BrowserDetect;1" or next; } eval "require '$name'; 1"; is( $@, '', "Compile $name" ); } Kwiki-0.39/t/cycle.t0000644000076500007650000000366510207375665014247 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use Test::More; BEGIN { eval "use Test::Memory::Cycle"; if ($@) { plan skip_all => 'These tests require Test::Memory::Cycle'; } else { plan tests => 35; } } use Kwiki; { my $kwiki = Kwiki->new; my $hub = $kwiki->load_hub; memory_cycle_ok($kwiki, 'check for cycles in Kwiki object'); memory_cycle_ok($hub, 'check for cycles in Kwiki::Hub object'); } { my $kwiki = Kwiki->new; { my $hub = $kwiki->load_hub; } ok($kwiki->hub, 'Hub does not get destroyed until main goes out of scope'); } { my %classes = (cgi_class => 'Kwiki::CGI', headers_class => 'Spoon::Headers', cookie_class => 'Kwiki::Cookie', css_class => 'Kwiki::CSS', files_class => 'Kwiki::Files', formatter_class => 'Kwiki::Formatter', javascript_class => 'Kwiki::Javascript', pages_class => 'Kwiki::Pages', preferences_class => 'Kwiki::Preferences', template_class => 'Kwiki::Template::TT2', users_class => 'Kwiki::Users', archive_class => 'Kwiki::Archive', display_class => 'Kwiki::Display', edit_class => 'Kwiki::Edit', # XXX Figure out why this fails... # icons_class => 'Kwiki::Icons', pane_class => 'Kwiki::Pane', pages_class => 'Kwiki::Pages', theme_class => 'Kwiki::Theme::Basic', ); my $kwiki = Kwiki->new; my $hub = $kwiki->load_hub(\%classes); foreach my $key (sort keys %classes) { (my $id = $key) =~ s/_class$//; my $object = $hub->$id; memory_cycle_ok($hub, 'check for cycles in Kwiki::Hub object'); memory_cycle_ok($object, "check for cycles in $classes{$key} object"); } } Kwiki-0.39/t/Formatter.pm0000644000076500007650000000006510207375665015253 0ustar ingyingy00000000000000package My::Formatter; use Kwiki::Formatter '-Base'; Kwiki-0.39/t/formatter1.t0000644000076500007650000001173510207375665015231 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use TestChunks; use Kwiki; my $hub = Kwiki->new->debug->load_hub( { css_class => 'Kwiki::CSS', formatter_class => 'Kwiki::Formatter', database_directory => '.', } ); my $formatter = $hub->formatter; for my $test ((test_chunks(qw(%%% <<<)))) { my $wiki_text = $test->chunk('%%%'); my $expect_html = $test->chunk('<<<'); my $got_html = $formatter->text_to_html($wiki_text); $got_html =~ s{^
    \n(.*)
    \n\z}{$1}s; is($got_html, $expect_html); } __END__ %%% visit SomePage or [forcedlink] (not [=code]) if you can, but avoid the negated !NotALink wherever possible, also, [a titled link TitledLink]. <<<

    visit SomePage or forcedlink (not code) if you can, but avoid the negated NotALink wherever possible, also, a titled link.

    %%% Take a look at http://www.domain.com/dir/the%20page.html?this=isthe&query=string ! But don't check !http://www.negated.com/ <<<

    Take a look at http://www.domain.com/dir/the%20page.html?this=isthe&query=string ! But don't check http://www.negated.com/

    %%% This is a [named link http://www.kwiki.org/] okay? <<<

    This is a named link okay?

    %%% I wrote a letter to theman+theextra@the-machine.gov. I think it was last Tuesday. <<<

    I wrote a letter to theman+theextra@the-machine.gov. I think it was last Tuesday.

    %%% You should write to [Ingy ingy@spif-tastical-code.org] and tell him his code is Spiffy! Don't write to !refunds@irs.gov. test <<<

    You should write to Ingy and tell him his code is Spiffy! Don't write to refunds@irs.gov. test

    %%% Check out my awesome image http://www.kwiki.org/awesome-image.jpg because it's inline! <<<

    Check out my awesome image because it's inline!

    %%% = Level One Header === Level Three Header ===== Level Five Header ======= Level Seven Header == Trailing Equals = == Trailing Equals Without Space= ==No Initial Space <<<

    Level One Header

    Level Three Header

    Level Five Header
    ======= Level Seven Header

    Trailing Equals

    Trailing Equals Without Space=

    ==No Initial Space

    %%% This is *strong* <<<

    This is strong

    %%% == A *Header* <<<

    A Header

    %%% More *strong* <<<

    More strong

    %%% Use *==* for h2s. <<<

    Use == for h2s.

    %%% This is *strong stuff* man <<<

    This is strong stuff man

    %%% Paragraph one. <<<

    Paragraph one.

    %%% Paragraph one. Paragraph two. <<<

    Paragraph one.

    Paragraph two.

    %%% *this* /that/ _the other_ <<<

    this that the other

    %%% this -- that --- the other <<<

    this – that — the other

    %%% a -- b --- -blat- c ----- -- d e --- *I paused--- -then deleted- oops* <<<

    a – b — blat c


    – d

    e —

    I paused— then deleted oops

    %%% This is *strong* This is not <<<

    This is strong

    This is not

    %%% with *two* lines <&> stuff. <<<

    with two lines <&amp;> stuff.

    %%% This is a *paragraph* of /text/, with two lines <&> stuff. <<<

    This is a paragraph of text, with two lines <&amp;> stuff.

    %%% == Simple Header sub foo { ... } ----- Another Paragraph. * One 00 Foo 00 Bar /empha/ 00 LinkInALink bar * Two *strong* === Conclusion ====== We can /clearly/ see that the /WaflWay/ is /the *best* way/ to be. xxx /*-[= pedantic ]-*/ _xxx_ <<<

    Simple Header

    sub foo {
        ...
    }
    

    Another Paragraph.

    bar
    
    • Two strong

    Conclusion

    We can clearly see that the WaflWay is the best way to be.

    xxx pedantic xxx

    %%% Okay, so there's this bug. I'll talk about a path to /etc/modules.autoload and then write some [=inline stuff]. Here's the second paragraph. === /usr/local <<<

    Okay, so there's this bug. I'll talk about a path to /etc/modules.autoload and then write some inline stuff.

    Here's the second paragraph.

    /usr/local

    Kwiki-0.39/t/formatter2.t0000644000076500007650000000226310207375665015226 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use TestChunks; use Kwiki; my $hub = Kwiki->new->debug->load_hub( { css_class => 'Kwiki::CSS', formatter_class => 'Kwiki::Formatter', } ); my $formatter = $hub->formatter; for my $test ((test_chunks(qw(%%% <<<)))[1]) { my $wiki_text = $test->chunk('%%%'); my $expect_html = $test->chunk('<<<'); my $got_html = $formatter->text_to_html($wiki_text); $got_html =~ s{^
    \n(.*)
    \n\z}{$1}s; is($got_html, $expect_html); } __END__ %%% Crack Sabbath. | | x | y | | a | 1 | 3 | | b | 3 | 5 | | c | 4 | *be bold* | It's Christmas Time. | http://www.kwiki.org | it */rocks/* | <<<

    Crack Sabbath.

    x y
    a 1 3
    b 3 5
    c 4 be bold

    It's Christmas Time.

    http://www.kwiki.org it rocks
    %%% | == A Heading | <<<

    A Heading

    Kwiki-0.39/t/formatter3.t0000644000076500007650000000155410207375665015231 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use TestChunks; use Kwiki; my $hub = Kwiki->new->debug->load_hub( { css_class => 'Kwiki::CSS', formatter_class => 'Kwiki::Formatter', } ); my $formatter = $hub->formatter; for my $test ((test_chunks(qw(%%% <<<)))) { my $wiki_text = $test->chunk('%%%'); my $expect_html = $test->chunk('<<<'); my $got_html = $formatter->text_to_html($wiki_text); $got_html =~ s{^
    \n(.*)
    \n\z}{$1}s; is($got_html, $expect_html); } __END__ %%% * one * two <<<
    • one
    • two
    %%% one & <<<
    one &
    <two>
    
    %%% This is how you {{*bold /text/*}} for future reference. <<<

    This is how you *bold /text/* for future reference.

    %%% *** one * two <<<
        • one
    • two
    Kwiki-0.39/t/formatter4.t0000644000076500007650000000133310207375665015225 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use TestChunks; use Kwiki; no warnings 'once'; my $hub = Kwiki->new->debug->load_hub( { css_class => 'Kwiki::CSS', formatter_class => 'Kwiki::Formatter', } ); my $formatter = $hub->formatter; my $x = 0; for my $test ( test_chunks( '%%%', '<<<' ) ) { my $wiki_text = $test->chunk('%%%'); my $expect_html = $test->chunk('<<<'); my $got_html = $formatter->text_to_html($wiki_text); $got_html =~ s{^
    \n(.*)
    \n\z}{$1}s; is( $got_html, $expect_html ); } __END__ %%% | foo | bar | | baz | quux | <<<
    foo bar
    baz quux
    Kwiki-0.39/t/formatter_cycle.t0000644000076500007650000000216710220107373016306 0ustar ingyingy00000000000000use lib 't', 'lib'; use strict; use warnings; use Test::More; BEGIN { eval "use Test::Memory::Cycle"; if ($@) { plan skip_all => 'These tests require Test::Memory::Cycle'; } else { plan tests => 2; } } use Kwiki; { my $kwiki = Kwiki->new; my $hub = $kwiki->load_hub({formatter_class => 'Kwiki::Formatter'}); my $formatter = $hub->formatter; $formatter->text_to_html(text()); memory_cycle_ok($formatter, 'check for cycles in the formatter after parsing something'); } { my $kwiki = Kwiki->new; my $hub = $kwiki->load_hub({formatter_class => 'Kwiki::Formatter'}); my $formatter_top = $hub->formatter->top_class->new(text => text()); $formatter_top->to_html; memory_cycle_ok($formatter_top, 'check for cycles in the formatter top class after parsing something'); } sub text { <<'EOF'; ---- = ABC == Foo * 1 * 2 0 1 0 2 0 3 Plain text .pre Pre formatter .pre | 1 | -2- | 3 | | _a_ | /b/ | *c* | | sub foo { my $autarch; } | | * foo | http://www.urth.org/ [http://www.urth.org/ Urth] {{ *asis* }} --- EOF } Kwiki-0.39/t/TestChunks.pm0000644000076500007650000000117710207375665015410 0ustar ingyingy00000000000000package TestChunks; use strict; use Test::More 'no_plan'; use Spiffy '-base'; our @EXPORT = qw(test_chunks ok is); field chunks => {}; sub test_chunks { my $start = $_[0]; my $test_data = join '', ; my @test_data = ($test_data =~ /^(\Q$start\E.*?(?=\Q$start\E|\z))/msg); my @tests = (); my $split = join '|', @_; for my $data (@test_data) { my $test = TestChunks->new; my @hash = split /^($split)\n/m, $data; shift @hash; %{$test->chunks} = @hash; push @tests, $test; } return @tests; } sub chunk { my $self = shift; $self->chunks->{(shift)}; }