forked from github/kensanata.oddmuse
Compare commits
338 Commits
2.3.0
...
new-file-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03111c7f58 | ||
|
|
b1d39e3195 | ||
|
|
48a00a6ff6 | ||
|
|
a3ee3c60ce | ||
|
|
d69063599e | ||
|
|
0146225c4f | ||
|
|
50fca72f82 | ||
|
|
1a4e6aa527 | ||
|
|
cdf8b561a6 | ||
|
|
905d8c930e | ||
|
|
f64c6d470b | ||
|
|
0657d84769 | ||
|
|
0181d8b944 | ||
|
|
fae5f1e345 | ||
|
|
81b179acac | ||
|
|
bc810ee0ce | ||
|
|
3a4236bc45 | ||
|
|
8642ae63a2 | ||
|
|
3c5373f76b | ||
|
|
58e297b092 | ||
|
|
cd4f6dc64c | ||
|
|
5a112b64b3 | ||
|
|
a7b0c661c8 | ||
|
|
b2f9a0044b | ||
|
|
d0cdd451e4 | ||
|
|
86334d6532 | ||
|
|
733752727d | ||
|
|
6635803807 | ||
|
|
7f3488baaa | ||
|
|
dcc318f34e | ||
|
|
17edc1c523 | ||
|
|
85912f211b | ||
|
|
52d7239400 | ||
|
|
9c691e5b9b | ||
|
|
0e45ea2e99 | ||
|
|
8773242dba | ||
|
|
267cd53adb | ||
|
|
ce82a328b6 | ||
|
|
b925805800 | ||
|
|
c8c50b4e81 | ||
|
|
4a976278d5 | ||
|
|
1255fe8168 | ||
|
|
081e8243d7 | ||
|
|
a20fc60617 | ||
|
|
770de2986a | ||
|
|
0551018de1 | ||
|
|
aa77f2ce2f | ||
|
|
471994f7b1 | ||
|
|
9d2c0216f6 | ||
|
|
82d888f0ea | ||
|
|
ccaf283204 | ||
|
|
3fb5319562 | ||
|
|
76c92f027c | ||
|
|
d828454511 | ||
|
|
34c6e93780 | ||
|
|
0a6f473098 | ||
|
|
4d67f9bfd2 | ||
|
|
6e80adc293 | ||
|
|
dc3fb65317 | ||
|
|
6a652de193 | ||
|
|
4747235fe7 | ||
|
|
0ecbeeb2c4 | ||
|
|
65378d91cb | ||
|
|
cb6a6bf4a6 | ||
|
|
db67c34203 | ||
|
|
ccf8fe2314 | ||
|
|
e336086cf0 | ||
|
|
5315b3f6ad | ||
|
|
e31abd57bc | ||
|
|
5bf60bb5d8 | ||
|
|
ad672aff28 | ||
|
|
e49af47d30 | ||
|
|
ecbe6a859a | ||
|
|
413228c56c | ||
|
|
a905de7ab5 | ||
|
|
a09409f375 | ||
|
|
764c0ffcf1 | ||
|
|
5962745937 | ||
|
|
d380062ec6 | ||
|
|
cd8066233c | ||
|
|
6f04d2044f | ||
|
|
f41ded592b | ||
|
|
8a2c9eca9c | ||
|
|
d712a17f82 | ||
|
|
504190b752 | ||
|
|
56e515a791 | ||
|
|
36feb62052 | ||
|
|
239f15cdbc | ||
|
|
f39cfd3235 | ||
|
|
329699a6aa | ||
|
|
28965bdaa6 | ||
|
|
ed42d2dad5 | ||
|
|
45b21cbdb8 | ||
|
|
b540093c2c | ||
|
|
d164d47e24 | ||
|
|
a56b92ecb3 | ||
|
|
114d914754 | ||
|
|
875051ea84 | ||
|
|
003357acad | ||
|
|
e1c77c4ba6 | ||
|
|
88475c3e41 | ||
|
|
e80f05301d | ||
|
|
a624e78975 | ||
|
|
8cd869f0f9 | ||
|
|
b09b3f8f8e | ||
|
|
b9043ffd98 | ||
|
|
54d3dc400a | ||
|
|
3962068385 | ||
|
|
a0b74ac3c6 | ||
|
|
870d75ac64 | ||
|
|
42d8260ce4 | ||
|
|
bfda4abe54 | ||
|
|
4b0d411564 | ||
|
|
6790de2d6a | ||
|
|
2784628544 | ||
|
|
dd8c687b2b | ||
|
|
9f4ceb2d72 | ||
|
|
0f8a4fa1df | ||
|
|
3b16b58880 | ||
|
|
192a902932 | ||
|
|
aedf77cff8 | ||
|
|
728547f309 | ||
|
|
33f5484441 | ||
|
|
a225486709 | ||
|
|
3f7f9ec1eb | ||
|
|
174aac5570 | ||
|
|
954232f7c8 | ||
|
|
067658fd10 | ||
|
|
b2b2b0f6cc | ||
|
|
408d169729 | ||
|
|
0eddbd5806 | ||
|
|
210a28afd4 | ||
|
|
94a16bd463 | ||
|
|
4005e246f7 | ||
|
|
6b3cd0437f | ||
|
|
c961748b49 | ||
|
|
7327eb8e0c | ||
|
|
1b0d595945 | ||
|
|
b7e2a04bb4 | ||
|
|
848eb65ad0 | ||
|
|
7ae98f4ed9 | ||
|
|
dc792691d4 | ||
|
|
0a57a8e89b | ||
|
|
f75d415322 | ||
|
|
1654562236 | ||
|
|
ba0535f39d | ||
|
|
e5b069f70b | ||
|
|
d34b9f669b | ||
|
|
ae2061fcaf | ||
|
|
65475cf2e8 | ||
|
|
ce2e63be6b | ||
|
|
007ce8db86 | ||
|
|
5997c3ea02 | ||
|
|
6895428844 | ||
|
|
2bc2d1f927 | ||
|
|
873ce10ced | ||
|
|
3855c83a7e | ||
|
|
281736a082 | ||
|
|
63d8e24c2f | ||
|
|
c66f1a6f8e | ||
|
|
6418cab98c | ||
|
|
040d51bc93 | ||
|
|
41c3245a51 | ||
|
|
ffc2a0b12f | ||
|
|
90c632f4ab | ||
|
|
9e8def306a | ||
|
|
f4e551111a | ||
|
|
1ead545561 | ||
|
|
f5fc46821f | ||
|
|
ce9f8d9b74 | ||
|
|
1104ecf72f | ||
|
|
13fc4cc0a4 | ||
|
|
31f7b330c5 | ||
|
|
ad3909888b | ||
|
|
f7b99d44fd | ||
|
|
2cf943d178 | ||
|
|
b2b1c16247 | ||
|
|
f91041b677 | ||
|
|
30b0faa70e | ||
|
|
174c4f6642 | ||
|
|
9ba5b119f8 | ||
|
|
b8ce7f07df | ||
|
|
c9a9db28a6 | ||
|
|
b21dc2db01 | ||
|
|
0f61a795ee | ||
|
|
ed30eeffb0 | ||
|
|
9473e08a14 | ||
|
|
16796b7fe5 | ||
|
|
1e704ece07 | ||
|
|
1f824d5838 | ||
|
|
d8bc7bd82f | ||
|
|
a2e1a73d10 | ||
|
|
68e71cc535 | ||
|
|
548bdf7d1c | ||
|
|
a6314a2c44 | ||
|
|
85e8800435 | ||
|
|
41b5c65e22 | ||
|
|
3ad0438a78 | ||
|
|
3ab80d0e3f | ||
|
|
2312787ec1 | ||
|
|
b8b2035151 | ||
|
|
4aefc9a648 | ||
|
|
c1cb7516a8 | ||
|
|
5aba2ae56f | ||
|
|
f958de8165 | ||
|
|
f79b188e82 | ||
|
|
dc182fde16 | ||
|
|
5fbc444a53 | ||
|
|
a7f83b2ba7 | ||
|
|
5bfe0073d9 | ||
|
|
3b3e707d3b | ||
|
|
ee932dee37 | ||
|
|
772bf2745a | ||
|
|
8cbd7dabec | ||
|
|
860d2f0bce | ||
|
|
ef4aac31b4 | ||
|
|
be1789f996 | ||
|
|
b7c1045783 | ||
|
|
54913a0131 | ||
|
|
a6036d2455 | ||
|
|
12d362106e | ||
|
|
b292ab5983 | ||
|
|
090c708ce9 | ||
|
|
67dc63c433 | ||
|
|
2606b846f0 | ||
|
|
ff66da7c65 | ||
|
|
76a6b4bfad | ||
|
|
ddadb21517 | ||
|
|
e62423ec84 | ||
|
|
083fdb3371 | ||
|
|
6cfe1ab29a | ||
|
|
4e43357daa | ||
|
|
7a82dd40ff | ||
|
|
584f23b08a | ||
|
|
b21f33951f | ||
|
|
acacd5ff01 | ||
|
|
a333fbf3b1 | ||
|
|
eb7de3c722 | ||
|
|
ac7ca05707 | ||
|
|
32ce6cde2d | ||
|
|
d922b7413c | ||
|
|
54b0fbcfaf | ||
|
|
d919dd5d94 | ||
|
|
48ec41b566 | ||
|
|
0d592e12f2 | ||
|
|
ee8b8db17f | ||
|
|
252033bff8 | ||
|
|
e21333faca | ||
|
|
ff3d7a9ea2 | ||
|
|
dd34aff9ef | ||
|
|
9eee99514b | ||
|
|
5ead2bdcf2 | ||
|
|
8b5267a013 | ||
|
|
423dad59b1 | ||
|
|
f79aa04c68 | ||
|
|
7535c859b9 | ||
|
|
ac34706853 | ||
|
|
b705fcb3f1 | ||
|
|
ae13fe5235 | ||
|
|
5830fbcd71 | ||
|
|
a2123aeb76 | ||
|
|
f07bdddb5d | ||
|
|
5da39c28a8 | ||
|
|
28f08d9583 | ||
|
|
0ba55b13d6 | ||
|
|
270e1aad9e | ||
|
|
ec1b7d1a46 | ||
|
|
718e17f07f | ||
|
|
48ff67a27c | ||
|
|
39eabb6cbb | ||
|
|
28d7d0a897 | ||
|
|
3f295e7a88 | ||
|
|
d6ef6bb56c | ||
|
|
f276ae6469 | ||
|
|
f6d4d5f517 | ||
|
|
0ee7a23018 | ||
|
|
61dec7317b | ||
|
|
7a1b4c38b1 | ||
|
|
0e97e7bee5 | ||
|
|
769bc55821 | ||
|
|
bd9cdf56bf | ||
|
|
be97b89b87 | ||
|
|
a9f5fe4374 | ||
|
|
a88878dc08 | ||
|
|
dcaabca09f | ||
|
|
d680d0173b | ||
|
|
3e8cb56f37 | ||
|
|
33ec1b1743 | ||
|
|
6f4b5451fc | ||
|
|
2770defdc4 | ||
|
|
1d6f435ca8 | ||
|
|
00856c0436 | ||
|
|
e0ee3bb24d | ||
|
|
8bbbed026d | ||
|
|
c9767ce84b | ||
|
|
b984f3ecad | ||
|
|
f58f784009 | ||
|
|
b6ee8da7c6 | ||
|
|
ae59ab3746 | ||
|
|
28ab5885a0 | ||
|
|
881dbc7094 | ||
|
|
2537a97900 | ||
|
|
20de100781 | ||
|
|
e1c3445136 | ||
|
|
e8be707079 | ||
|
|
680c3b96ce | ||
|
|
ba4ce729e6 | ||
|
|
d74da11382 | ||
|
|
9d0e6cb3cb | ||
|
|
027557999d | ||
|
|
41fb4d0c4b | ||
|
|
7cf0904b2b | ||
|
|
7330f1961b | ||
|
|
6e9d50204f | ||
|
|
629157d367 | ||
|
|
23af89d21e | ||
|
|
a3cf3dbb99 | ||
|
|
a28f380125 | ||
|
|
eb8fd17e01 | ||
|
|
4784e3bc88 | ||
|
|
cff287ee24 | ||
|
|
07eeffa3e3 | ||
|
|
fe7a5e564a | ||
|
|
00aa0761d7 | ||
|
|
f09a81b3b9 | ||
|
|
c43b0695c2 | ||
|
|
e9e436c0b8 | ||
|
|
c0194c1178 | ||
|
|
c6a0cb33ac | ||
|
|
e9375974cb | ||
|
|
a226902617 | ||
|
|
213774d6ff | ||
|
|
98d96fd1d8 | ||
|
|
ddb8fb06e6 | ||
|
|
8ec456ed41 | ||
|
|
020df9098d | ||
|
|
26a5db86b0 | ||
|
|
ab3a7752ba |
18
Makefile
18
Makefile
@@ -17,24 +17,22 @@ build:
|
||||
mkdir -p build
|
||||
|
||||
build/wiki.pl: wiki.pl
|
||||
sed "s/\\\$$q->a({-href=>'http:\/\/www.oddmuse.org\/'}, 'Oddmuse')/\\\$$q->a({-href=>'http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tag\/?id=$(VERSION_NO)'}, 'wiki.pl') . ' ($(VERSION_NO)), see ' . &/" < $< > $@
|
||||
perl -lne "s/(\\\$$q->a\({-href=>'http:\/\/www.oddmuse.org\/'}, 'Oddmuse'\))/\\\$$q->a({-href=>'http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tag\/?id=$(VERSION_NO)'}, 'wiki.pl') . ' ($(VERSION_NO)), see ' . \$$1/; print" < $< > $@
|
||||
|
||||
build/%-utf8.pl: modules/translations/%-utf8.pl
|
||||
sed "s/<a href=\"http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tree\/modules\/translations\/\\(.*\\).pl\">\\(.*\\).pl<\/a>/<a href=\"http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tree\/modules\/translations\/\\1.pl?id=$(VERSION_NO)\">\\1.pl<\/a> (for $(VERSION_NO))/" < $< > $@
|
||||
|
||||
# Currently oddtrans introduces encoding errors!
|
||||
|
||||
# %-utf8.pl: wiki.pl $(MODULES)
|
||||
# perl oddtrans -l $@ $^ > $@-new && mv $@-new $@
|
||||
perl -lne "s/(AddModuleDescription\('[^']+', '[^']+')\)/\$$1, 'translations\/', '$(VERSION_NO)')/; print" < $< > $@
|
||||
|
||||
# from: http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/namespaces.pl
|
||||
# to: http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/namespaces.pl?id=2.1-11-gd4f1e27
|
||||
|
||||
build/%.pl: modules/%.pl
|
||||
sed "s/<a href=\"http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tree\/modules\/\\(.*\\).pl\">\\(.*\\).pl<\/a>/<a href=\"http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tree\/modules\/\\1.pl?id=$(VERSION_NO)\">\\1.pl<\/a> (for $(VERSION_NO))/" < $< > $@
|
||||
|
||||
|
||||
perl -lne "s/(AddModuleDescription\('[^']+', '[^']+')\)/\$$1, undef, '$(VERSION_NO)')/; print" < $< > $@
|
||||
|
||||
translations: $(TRANSLATIONS)
|
||||
for f in $^; do \
|
||||
echo updating $$f...; \
|
||||
perl oddtrans -l $$f wiki.pl $(MODULES) > $$f-new && mv $$f-new $$f; \
|
||||
done
|
||||
|
||||
# UNTESTED/OBSOLETE: these targets have not been tested in a long time
|
||||
# and are potentially obsolete.
|
||||
|
||||
315
contrib/add-link.pl
Normal file
315
contrib/add-link.pl
Normal file
@@ -0,0 +1,315 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
# Copyright (C) 2011–2015 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
use LWP::UserAgent;
|
||||
use HTML::TreeBuilder;
|
||||
use JSON::PP;
|
||||
use utf8;
|
||||
|
||||
# load Oddmuse core
|
||||
$RunCGI = 0;
|
||||
do "wiki.pl";
|
||||
|
||||
# globals depending on the name of the script
|
||||
my ($self, $name, $wiki);
|
||||
if ($0 eq '/home/alex/campaignwiki.org/add-link.pl') {
|
||||
$self = "https://campaignwiki.org/add-link";
|
||||
$name = "OSR Links to Wisdom";
|
||||
$wiki = 'LinksToWisdom';
|
||||
} elsif ($0 eq '/home/alex/campaignwiki.org/add-adventure.pl') {
|
||||
$self = "https://campaignwiki.org/add-adventure";
|
||||
$name = "OSR Links to Adventures";
|
||||
$wiki = 'Adventures';
|
||||
} else {
|
||||
ReportError('Cannot determine wiki!', '500 INTERNAL SERVER ERROR');
|
||||
}
|
||||
|
||||
# derived variables
|
||||
my $site = "https://campaignwiki.org/wiki/$wiki";
|
||||
# my $site = "http://localhost/wiki.pl";
|
||||
my $home = "$site/$HomePage";
|
||||
# http://www.emacswiki.org/pics/star.png
|
||||
my $stardata = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEUAAHkAAACzdRTapx3twwD/9qb////1YCa0AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXAQYCJAu+WhwbAAAAKnRFWHRDb21tZW50AGJ5IFJhZG9taXIgJ1RoZSBTaGVlcCcgRG9waWVybGFza2kVfTXbAAAAYElEQVQI12NgQAKMMIaYAFTAzRDKCHOEMETCnEFyjIJhYS6OggwMoqGhaS7GRgIMjC6uYc5GikA5YRcXIyWwotBgJUWw7lAXsAyDaIihMlhK1FFA0AjEEAESQgJQu4EYAPAPC2XcokgQAAAAAElFTkSuQmCC';
|
||||
|
||||
main();
|
||||
|
||||
sub toc {
|
||||
# start with the homepage
|
||||
my @values;
|
||||
my %labels;
|
||||
for my $id (GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g) {
|
||||
push @values, $id;
|
||||
for my $item (GetPageContent(FreeToNormal($id)) =~ /(\*+ [^][\n]*)$/mg) {
|
||||
my $value = $item;
|
||||
my $label = $item;
|
||||
$value =~ s/\* *//g;
|
||||
push @values, $value;
|
||||
$label =~ s/\* */ /g; # EM SPACE
|
||||
$labels{$value} = $label;
|
||||
}
|
||||
}
|
||||
return \@values, \%labels;
|
||||
}
|
||||
|
||||
sub top {
|
||||
# start with the homepage
|
||||
my %blog;
|
||||
my $n;
|
||||
for my $id (GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g) {
|
||||
for my $item (GetPageContent(FreeToNormal($id)) =~ /^\*+\s+\[(https?:\/\/[^\/\n\t ]+)/mg) {
|
||||
$n++;
|
||||
# handle blogspot domain munging
|
||||
$item =~ s/blogspot(\.[a-z]+)+/blogspot.com/;
|
||||
$blog{$item}++;
|
||||
}
|
||||
}
|
||||
print $q->p("Total links counted: $n.");
|
||||
my @list = sort { $blog{$b} <=> $blog{$a} } keys %blog;
|
||||
# my $max = scalar @list;
|
||||
# $max = 20 if $max > 20;
|
||||
# @list = @list[0 .. $max -1];
|
||||
@list = map {
|
||||
my $domain = substr($_, index($_, '://') + 3);
|
||||
my $term = quotemeta($domain);
|
||||
# handle blogspot domain munging
|
||||
$term =~ s/blogspot\\\.com/blogspot(\\.[a-z]+)+/;
|
||||
$term = QuoteHtml($term);
|
||||
$q->a({-href => $_}, $domain)
|
||||
. " (" . $q->a({-href => "$self/match/$term"}, $blog{$_}) . ")";
|
||||
} @list;
|
||||
return \@list;
|
||||
}
|
||||
|
||||
sub match {
|
||||
my $term = shift;
|
||||
# start with the homepage
|
||||
my @list;
|
||||
my $title;
|
||||
for my $id (GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g) {
|
||||
for my $line (split /\n/, GetPageContent(FreeToNormal($id))) {
|
||||
if ($line =~ /^\*+\s+([^][\n]*)$/) {
|
||||
$title = $1;
|
||||
} elsif ($line =~ /$term/o) {
|
||||
if ($line =~ /^\*+\s+\[(https?:\S+)\s+([^]]+)\]/) {
|
||||
push (@list, $q->a({-href => $1}, $2) . " (" . $title . ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return \@list;
|
||||
}
|
||||
|
||||
sub html_toc {
|
||||
my ($values, $labels) = toc();
|
||||
return $q->radio_group(-name =>'toc',
|
||||
-values => $values,
|
||||
-labels => $labels,
|
||||
-linebreak=>'true');
|
||||
}
|
||||
|
||||
sub default {
|
||||
print $q->p("Add a link to the " . $q->a({-href=>$home}, $name) . ".");
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'url'}, T('URL:')) . ' '
|
||||
. $q->textfield(-name=>'url', -id=>'url', -size=>80));
|
||||
print $q->p({-style=>'font-size: 10pt'},
|
||||
"(Drag this bookmarklet to your bookmarks bar for easy access:",
|
||||
$q->a({-href=>q{javascript:location='}
|
||||
. $q->url()
|
||||
. qq{?url='+encodeURIComponent(window.location.href)}},
|
||||
"Submit $name") . ".)");
|
||||
print html_toc();
|
||||
print $q->submit('go', 'Add!');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
sub confirm {
|
||||
my ($url, $name, $toc) = @_;
|
||||
print $q->p("Please confirm that you want to add "
|
||||
. GetUrl($url, $name)
|
||||
. " to the section “$toc”.");
|
||||
print $q->start_form(-method=>'get');
|
||||
print $q->p($q->label({-for=>'name', -style=>'display: inline-block; width: 15em'},
|
||||
T('Use a different link name:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'name', -id=>'name', -size=>50, -default=>$name)
|
||||
. $q->br()
|
||||
. $q->label({-for=>'summary', -style=>'display: inline-block; width:15em'},
|
||||
T('An optional short summary:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'summary', -id=>'summary', -size=>50)
|
||||
. $q->br()
|
||||
. $q->label({-for=>'username', -style=>'display: inline-block; width:15em'},
|
||||
T('Your name for the log file:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'username', -id=>'username', -size=>50));
|
||||
my $star = $q->img({-src=>$stardata, -class=>'smiley', -alt=>'☆'});
|
||||
print '<p>Optionally: Do you want to rate it?<br />';
|
||||
my $i = 0;
|
||||
foreach my $label ($q->span({-style=>'display: inline-block; width:3em'}, $star)
|
||||
. 'I might use this for my campaign',
|
||||
$q->span({-style=>'display: inline-block; width:3em'}, $star x 2)
|
||||
. 'I have used this in a campaign and it worked as intended',
|
||||
$q->span({-style=>'display: inline-block; width:3em'}, $star x 3)
|
||||
. 'I have used this in a campaign and it was ' . $q->em('great')) {
|
||||
$i++;
|
||||
print qq{<label><input type="radio" name="stars" value="$i" $checked/>$label</label><br />};
|
||||
}
|
||||
print '</p>';
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('toc', $toc);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
# returns unquoted html
|
||||
sub get_name {
|
||||
my $url = shift;
|
||||
my $tree = HTML::TreeBuilder->new_from_content(GetRaw($url));
|
||||
my $h = $tree->look_down('_tag', 'title');
|
||||
$h = $tree->look_down('_tag', 'h1') unless $h;
|
||||
$h = $h->as_text if $h;
|
||||
return $h;
|
||||
}
|
||||
|
||||
sub post_addition {
|
||||
my ($url, $name, $toc, $summary) = @_;
|
||||
my $id = FreeToNormal($name);
|
||||
my $display = $name;
|
||||
utf8::decode($display); # we're dealing with user input
|
||||
utf8::decode($summary); # we're dealing with user input
|
||||
print $q->p("Adding ", GetUrl($url, $display), " to “$toc”.");
|
||||
# start with the homepage
|
||||
my @pages = GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g;
|
||||
for my $id (@pages) {
|
||||
return post($id, undef, $name, $summary, $url, GetParam('stars', '')) if $id eq $toc;
|
||||
my $data = GetPageContent(FreeToNormal($id));
|
||||
while ($data =~ /(\*+ ([^][\n]*))$/mg) {
|
||||
return post($id, $1, $name, $summary, $url, GetParam('stars', '')) if $2 eq $toc;
|
||||
}
|
||||
}
|
||||
print $q->p("Whoops. I was unable to find “$toc” in the wiki. Sorry!");
|
||||
}
|
||||
|
||||
sub post {
|
||||
my ($id, $toc, $name, $summary, $url, $stars) = @_;
|
||||
my $data = GetPageContent(FreeToNormal($id));
|
||||
my $re = quotemeta($url);
|
||||
if ($data =~ /$re\s+(.*?)\]/) {
|
||||
my $display = $1;
|
||||
print $q->p($q->strong("Oops, we seem to have a problem!"));
|
||||
print $q->p(GetPageLink(NormalToFree($id)),
|
||||
" already links to the URL you submitted:",
|
||||
GetUrl($url, $display));
|
||||
return;
|
||||
}
|
||||
$stars = ' ' . (':star:' x $stars) if $stars;
|
||||
$summary = ': ' . $summary if $summary;
|
||||
if ($toc) {
|
||||
$toc =~ /^(\*+)/;
|
||||
my $depth = "*$1"; # one more!
|
||||
my $regexp = quotemeta($toc);
|
||||
$data =~ s/$regexp/$toc\n$depth \[$url $name\]$summary$stars/;
|
||||
} else {
|
||||
$data = "* [$url $name]$summary$stars\n" . $data;
|
||||
}
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my %params = (text => $data,
|
||||
title => $id,
|
||||
summary => $name,
|
||||
username => GetParam('username'),
|
||||
pwd => GetParam('pwd'));
|
||||
# spam fighting modules
|
||||
$params{$QuestionaskerSecretKey} = 1 if $QuestionaskerSecretKey;
|
||||
$params{$HoneyPotOk} = time if $HoneyPotOk;
|
||||
my $response = $ua->post($site, \%params);
|
||||
if ($response->is_error) {
|
||||
print $q->p("The submission failed!");
|
||||
print $response->content;
|
||||
} else {
|
||||
print $q->p("See for yourself: ", GetPageLink($id));
|
||||
}
|
||||
}
|
||||
|
||||
sub print_end_of_page {
|
||||
print $q->p('Questions? Send mail to Alex Schroeder <'
|
||||
. $q->a({-href=>'mailto:kensanata@gmail.com'},
|
||||
'kensanata@gmail.com') . '>');
|
||||
print $q->end_div();
|
||||
PrintFooter();
|
||||
}
|
||||
|
||||
sub main {
|
||||
$ConfigFile = "$DataDir/config"; # read the global config file
|
||||
$DataDir = "$DataDir/$wiki"; # but link to the local pages
|
||||
Init(); # read config file (no modules!)
|
||||
$ScriptName = $site; # undo setting in the config file
|
||||
$FullUrl = $site; #
|
||||
binmode(STDOUT,':utf8');
|
||||
$q->charset('utf8');
|
||||
if ($q->path_info eq '/source') {
|
||||
seek DATA, 0, 0;
|
||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n", <DATA>;
|
||||
} elsif ($q->path_info eq '/structure') {
|
||||
my ($values, $labels) = toc();
|
||||
my @indented = map {
|
||||
($labels->{$_} || $_) =~ /^( *)/;
|
||||
[$_, length($1)]
|
||||
} @$values;
|
||||
print "Content-type: application/json; charset=UTF-8\r\n\r\n";
|
||||
binmode(STDOUT,':raw'); # because of encode_json
|
||||
print JSON::PP::encode_json(\@indented);
|
||||
} elsif ($q->path_info eq '/toc') {
|
||||
my ($values, $labels) = toc();
|
||||
print "Content-type: application/json; charset=UTF-8\r\n\r\n";
|
||||
binmode(STDOUT,':raw'); # because of encode_json
|
||||
print JSON::PP::encode_json($values);
|
||||
} elsif ($q->path_info eq '/top') {
|
||||
print GetHeader('', 'Top Blogs');
|
||||
print $q->start_div({-class=>'content top'});
|
||||
print $q->ol($q->li(top()));
|
||||
print_end_of_page();
|
||||
} elsif ($q->path_info =~ '^/match/(.*)') {
|
||||
my $term = $1;
|
||||
print GetHeader('', "Entries Matching '$term'");
|
||||
print $q->start_div({-class=>'content match'});
|
||||
print $q->ol($q->li(match($term)));
|
||||
print_end_of_page();
|
||||
} else {
|
||||
push(@UserGotoBarPages, 'Help');
|
||||
$UserGotoBar = $q->a({-href=>$q->url . '/source'}, 'Source');
|
||||
print GetHeader('', 'Submit a new link');
|
||||
print $q->start_div({-class=>'content index'});
|
||||
my $url = GetParam('url');
|
||||
my $name = UnquoteHtml(GetParam('name', get_name($url)));
|
||||
my $toc = GetParam('toc');
|
||||
my $confirm = GetParam('confirm');
|
||||
my $summary = GetParam('summary');
|
||||
if (not $url or not $toc) {
|
||||
default();
|
||||
} elsif (not $confirm) {
|
||||
confirm($url, $name, $toc);
|
||||
} else {
|
||||
post_addition($url, $name, $toc, $summary);
|
||||
}
|
||||
print_end_of_page();
|
||||
}
|
||||
}
|
||||
|
||||
__DATA__
|
||||
37
contrib/campaignwiki/README
Normal file
37
contrib/campaignwiki/README
Normal file
@@ -0,0 +1,37 @@
|
||||
The files in this directory are used to run http://campaignwiki.org/
|
||||
|
||||
add-link.pl
|
||||
===========
|
||||
|
||||
This is used to add links to the Links To Wisdom wiki. This wiki is a
|
||||
bookmark site: A few pages make up a big unordered list of links in
|
||||
wiki format. add-link is a tool to help users contribute new links to
|
||||
the list.
|
||||
|
||||
http://campaignwiki.org/wiki/LinksToWisdom/HomePage
|
||||
|
||||
copy.pl
|
||||
=======
|
||||
|
||||
This is used to copy the text from a web page to a wiki page. The idea
|
||||
was to keep archive copies of cool pages somewhere. The Blog Archive
|
||||
never got used, though.
|
||||
|
||||
http://campaignwiki.org/wiki/BlogArchive/HomePage
|
||||
|
||||
monster-tag.pl
|
||||
==============
|
||||
|
||||
This is used to quickly tag many pages in the Monsters wiki. The
|
||||
Monsters wiki hasn't been used in a long time, though.
|
||||
|
||||
http://campaignwiki.org/wiki/Monsters/HomePage
|
||||
|
||||
submit.pl
|
||||
=========
|
||||
|
||||
This used to be used to add sites to the Old School RPG Planet. The
|
||||
aggregator was configured via a wiki page on the Planet wiki. It's now
|
||||
abandoned.
|
||||
|
||||
http://campaignwiki.org/wiki/Planet/HomePage
|
||||
262
contrib/campaignwiki/add-link.pl
Normal file → Executable file
262
contrib/campaignwiki/add-link.pl
Normal file → Executable file
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
# Copyright (C) 2011 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2011–2014 Alex Schroeder <alex@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
|
||||
@@ -15,8 +15,10 @@
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
use LWP::UserAgent;
|
||||
use HTML::TreeBuilder;
|
||||
use JSON::PP;
|
||||
use utf8;
|
||||
|
||||
# load Oddmuse core
|
||||
@@ -24,11 +26,14 @@ $RunCGI = 0;
|
||||
do "wiki.pl";
|
||||
|
||||
# globals
|
||||
my $self = "http://campaignwiki.org/add-link";
|
||||
my $name = "OSR Links to Wisdom";
|
||||
my $wiki = 'LinksToWisdom';
|
||||
my $site = "http://campaignwiki.org/wiki/$wiki";
|
||||
# my $site = "http://localhost/wiki.pl";
|
||||
my $home = "$site/$HomePage";
|
||||
# http://www.emacswiki.org/pics/star.png
|
||||
my $stardata = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAFVBMVEUAAHkAAACzdRTapx3twwD/9qb////1YCa0AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXAQYCJAu+WhwbAAAAKnRFWHRDb21tZW50AGJ5IFJhZG9taXIgJ1RoZSBTaGVlcCcgRG9waWVybGFza2kVfTXbAAAAYElEQVQI12NgQAKMMIaYAFTAzRDKCHOEMETCnEFyjIJhYS6OggwMoqGhaS7GRgIMjC6uYc5GikA5YRcXIyWwotBgJUWw7lAXsAyDaIihMlhK1FFA0AjEEAESQgJQu4EYAPAPC2XcokgQAAAAAElFTkSuQmCC';
|
||||
|
||||
main();
|
||||
|
||||
@@ -47,9 +52,62 @@ sub toc {
|
||||
$labels{$value} = $label;
|
||||
}
|
||||
}
|
||||
return \@values, \%labels;
|
||||
}
|
||||
|
||||
sub top {
|
||||
# start with the homepage
|
||||
my %blog;
|
||||
my $n;
|
||||
for my $id (GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g) {
|
||||
for my $item (GetPageContent(FreeToNormal($id)) =~ /^\*+\s+\[(https?:\/\/[^\/\n\t ]+)/mg) {
|
||||
$n++;
|
||||
# handle blogspot domain munging
|
||||
$item =~ s/blogspot(\.[a-z]+)+/blogspot.com/;
|
||||
$blog{$item}++;
|
||||
}
|
||||
}
|
||||
print $q->p("Total links counted: $n.");
|
||||
my @list = sort { $blog{$b} <=> $blog{$a} } keys %blog;
|
||||
# my $max = scalar @list;
|
||||
# $max = 20 if $max > 20;
|
||||
# @list = @list[0 .. $max -1];
|
||||
@list = map {
|
||||
my $domain = substr($_, index($_, '://') + 3);
|
||||
my $term = quotemeta($domain);
|
||||
# handle blogspot domain munging
|
||||
$term =~ s/blogspot\\\.com/blogspot(\\.[a-z]+)+/;
|
||||
$term = QuoteHtml($term);
|
||||
$q->a({-href => $_}, $domain)
|
||||
. " (" . $q->a({-href => "$self/match/$term"}, $blog{$_}) . ")";
|
||||
} @list;
|
||||
return \@list;
|
||||
}
|
||||
|
||||
sub match {
|
||||
my $term = shift;
|
||||
# start with the homepage
|
||||
my @list;
|
||||
my $title;
|
||||
for my $id (GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g) {
|
||||
for my $line (split /\n/, GetPageContent(FreeToNormal($id))) {
|
||||
if ($line =~ /^\*+\s+([^][\n]*)$/) {
|
||||
$title = $1;
|
||||
} elsif ($line =~ /$term/o) {
|
||||
if ($line =~ /^\*+\s+\[(https?:\S+)\s+([^]]+)\]/) {
|
||||
push (@list, $q->a({-href => $1}, $2) . " (" . $title . ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return \@list;
|
||||
}
|
||||
|
||||
sub html_toc {
|
||||
my ($values, $labels) = toc();
|
||||
return $q->radio_group(-name =>'toc',
|
||||
-values => \@values,
|
||||
-labels => \%labels,
|
||||
-values => $values,
|
||||
-labels => $labels,
|
||||
-linebreak=>'true');
|
||||
}
|
||||
|
||||
@@ -57,102 +115,108 @@ sub default {
|
||||
print $q->p("Add a link to the " . $q->a({-href=>$home}, $name) . ".");
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'url'}, T('URL:')) . ' '
|
||||
. $q->textfield(-name=>'url', -id=>'url', -size=>50));
|
||||
print toc();
|
||||
print $q->submit('go', 'Add!');
|
||||
print $q->end_form();
|
||||
print $q->p("Drag this bookmarklet to your bookmarks bar for easy access:",
|
||||
. $q->textfield(-name=>'url', -id=>'url', -size=>80));
|
||||
print $q->p({-style=>'font-size: 10pt'},
|
||||
"(Drag this bookmarklet to your bookmarks bar for easy access:",
|
||||
$q->a({-href=>q{javascript:location='}
|
||||
. $q->url()
|
||||
. qq{?url='+encodeURIComponent(window.location.href)}},
|
||||
"Submit $name") . ".");
|
||||
"Submit $name") . ".)");
|
||||
print html_toc();
|
||||
print $q->submit('go', 'Add!');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
sub check_url {
|
||||
my $toc = GetParam('toc');
|
||||
return default() unless $toc;
|
||||
my $url = shift;
|
||||
if (not GetParam('confirm', 0)) {
|
||||
my $name = get_name($url);
|
||||
print $q->p("Please confirm that you want to add "
|
||||
. GetUrl($url, $name)
|
||||
. " to the section “$toc”.");
|
||||
print $q->start_form(-method=>'get');
|
||||
print $q->p($q->label({-for=>'name', -style=>'display: inline-block; width:30ex'},
|
||||
T('Use a different link name:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:60ex',
|
||||
-name=>'name', -id=>'name', -size=>50, -default=>$name)
|
||||
. $q->br()
|
||||
. $q->label({-for=>'username', -style=>'display: inline-block; width:30ex'},
|
||||
T('Your name for the log file:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:60ex',
|
||||
-name=>'username', -id=>'username', -size=>50));
|
||||
my $star = $q->img({-src=>'http://www.emacswiki.org/pics/star.png', -class=>'smiley',
|
||||
-alt=>'star'});
|
||||
print '<p>Optionally: Do you want to rate it?<br />';
|
||||
my $i = 0;
|
||||
foreach my $label ($q->span({-style=>'display: inline-block; width:15ex'}, $star)
|
||||
. 'I might use this for my next campaign',
|
||||
$q->span({-style=>'display: inline-block; width:15ex'}, $star x 2)
|
||||
. 'I have used this in a campaign and it worked as intended',
|
||||
$q->span({-style=>'display: inline-block; width:15ex'}, $star x 3)
|
||||
. 'I have used it in many of my campaigns',
|
||||
$q->span({-style=>'display: inline-block; width:15ex'}, $star x 4)
|
||||
. 'Everybody should give it a try',
|
||||
$q->span({-style=>'display: inline-block; width:15ex'}, $star x 5)
|
||||
. 'Everybody should use it, that is how awesome it is!') {
|
||||
$i++;
|
||||
print qq{<label><input type="radio" name="stars" value="$i" $checked/>$label</label><br />};
|
||||
}
|
||||
print '</p>';
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('toc', $toc);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
} else {
|
||||
post_addition($q->param('name'), $url, $toc);
|
||||
sub confirm {
|
||||
my ($url, $name, $toc) = @_;
|
||||
print $q->p("Please confirm that you want to add "
|
||||
. GetUrl($url, $name)
|
||||
. " to the section “$toc”.");
|
||||
print $q->start_form(-method=>'get');
|
||||
print $q->p($q->label({-for=>'name', -style=>'display: inline-block; width: 15em'},
|
||||
T('Use a different link name:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'name', -id=>'name', -size=>50, -default=>$name)
|
||||
. $q->br()
|
||||
. $q->label({-for=>'summary', -style=>'display: inline-block; width:15em'},
|
||||
T('An optional short summary:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'summary', -id=>'summary', -size=>50)
|
||||
. $q->br()
|
||||
. $q->label({-for=>'username', -style=>'display: inline-block; width:15em'},
|
||||
T('Your name for the log file:')) . ' '
|
||||
. $q->textfield(-style=>'display: inline-block; width:50ex',
|
||||
-name=>'username', -id=>'username', -size=>50));
|
||||
my $star = $q->img({-src=>$stardata, -class=>'smiley', -alt=>'☆'});
|
||||
print '<p>Optionally: Do you want to rate it?<br />';
|
||||
my $i = 0;
|
||||
foreach my $label ($q->span({-style=>'display: inline-block; width:3em'}, $star)
|
||||
. 'I might use this for my campaign',
|
||||
$q->span({-style=>'display: inline-block; width:3em'}, $star x 2)
|
||||
. 'I have used this in a campaign and it worked as intended',
|
||||
$q->span({-style=>'display: inline-block; width:3em'}, $star x 3)
|
||||
. 'I have used this in a campaign and it was ' . $q->em('great')) {
|
||||
$i++;
|
||||
print qq{<label><input type="radio" name="stars" value="$i" $checked/>$label</label><br />};
|
||||
}
|
||||
print '</p>';
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('toc', $toc);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
# returns unquoted html
|
||||
sub get_name {
|
||||
my $url = shift;
|
||||
my $tree = HTML::TreeBuilder->new_from_content(GetRaw($url));
|
||||
my $h = $tree->look_down('_tag', 'h1');
|
||||
$h = $tree->look_down('_tag', 'title') unless $h;
|
||||
my $h = $tree->look_down('_tag', 'title');
|
||||
$h = $tree->look_down('_tag', 'h1') unless $h;
|
||||
$h = $h->as_text if $h;
|
||||
return $h;
|
||||
}
|
||||
|
||||
sub post_addition {
|
||||
my ($name, $url, $toc) = @_;
|
||||
my ($url, $name, $toc, $summary) = @_;
|
||||
my $id = FreeToNormal($name);
|
||||
my $display = $name;
|
||||
utf8::decode($display); # we're dealing with user input
|
||||
utf8::decode($summary); # we're dealing with user input
|
||||
print $q->p("Adding ", GetUrl($url, $display), " to “$toc”.");
|
||||
# start with the homepage
|
||||
my @pages = GetPageContent($HomePage) =~ /\* \[\[(.*?)\]\]/g;
|
||||
for my $id (@pages) {
|
||||
return post($id, undef, $name, $url, GetParam('stars', '')) if $id eq $toc;
|
||||
return post($id, undef, $name, $summary, $url, GetParam('stars', '')) if $id eq $toc;
|
||||
my $data = GetPageContent(FreeToNormal($id));
|
||||
while ($data =~ /(\*+ ([^][\n]*))$/mg) {
|
||||
return post($id, $1, $name, $url, GetParam('stars', '')) if $2 eq $toc;
|
||||
return post($id, $1, $name, $summary, $url, GetParam('stars', '')) if $2 eq $toc;
|
||||
}
|
||||
}
|
||||
print $q->p("Whoops. I was unable to find “$toc” in the wiki. Sorry!");
|
||||
}
|
||||
|
||||
sub post {
|
||||
my ($id, $toc, $name, $url, $stars) = @_;
|
||||
my ($id, $toc, $name, $summary, $url, $stars) = @_;
|
||||
my $data = GetPageContent(FreeToNormal($id));
|
||||
my $re = quotemeta($url);
|
||||
if ($data =~ /$re\s+(.*?)\]/) {
|
||||
my $display = $1;
|
||||
print $q->p($q->strong("Oops, we seem to have a problem!"));
|
||||
print $q->p(GetPageLink(NormalToFree($id)),
|
||||
" already links to the URL you submitted:",
|
||||
GetUrl($url, $display));
|
||||
return;
|
||||
}
|
||||
$stars = ' ' . (':star:' x $stars) if $stars;
|
||||
$summary = ': ' . $summary if $summary;
|
||||
if ($toc) {
|
||||
$toc =~ /^(\*+)/;
|
||||
my $depth = "*$1"; # one more!
|
||||
my $regexp = quotemeta($toc);
|
||||
$data =~ s/$regexp/$toc\n$depth \[$url $name\]$stars/;
|
||||
$data =~ s/$regexp/$toc\n$depth \[$url $name\]$summary$stars/;
|
||||
} else {
|
||||
$data = "* [$url $name]$stars\n" . $data;
|
||||
$data = "* [$url $name]$summary$stars\n" . $data;
|
||||
}
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my %params = (text => $data,
|
||||
@@ -173,30 +237,68 @@ sub post {
|
||||
}
|
||||
}
|
||||
|
||||
sub main {
|
||||
$ConfigFile = "$DataDir/config"; # read the global config file
|
||||
$DataDir = "$DataDir/$wiki"; # but link to the local pages
|
||||
Init(); # read config file (no modules!)
|
||||
$ScriptName = $site; # undo setting in the config file
|
||||
binmode(STDOUT,':utf8');
|
||||
$q->charset('utf8');
|
||||
if ($q->path_info eq '/source') {
|
||||
seek DATA, 0, 0;
|
||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n", <DATA>;
|
||||
} else {
|
||||
$UserGotoBar = $q->a({-href=>$q->url . '/source'}, 'Source');
|
||||
print GetHeader('', 'Submit a new link');
|
||||
print $q->start_div({-class=>'content index'});
|
||||
if (not GetParam('url')) {
|
||||
default();
|
||||
} else {
|
||||
check_url(GetParam('url'));
|
||||
}
|
||||
sub print_end_of_page {
|
||||
print $q->p('Questions? Send mail to Alex Schroeder <'
|
||||
. $q->a({-href=>'mailto:kensanata@gmail.com'},
|
||||
'kensanata@gmail.com') . '>');
|
||||
print $q->end_div();
|
||||
PrintFooter();
|
||||
}
|
||||
|
||||
sub main {
|
||||
$ConfigFile = "$DataDir/config"; # read the global config file
|
||||
$DataDir = "$DataDir/$wiki"; # but link to the local pages
|
||||
Init(); # read config file (no modules!)
|
||||
$ScriptName = $site; # undo setting in the config file
|
||||
$FullUrl = $site; #
|
||||
binmode(STDOUT,':utf8');
|
||||
$q->charset('utf8');
|
||||
if ($q->path_info eq '/source') {
|
||||
seek DATA, 0, 0;
|
||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n", <DATA>;
|
||||
} elsif ($q->path_info eq '/structure') {
|
||||
my ($values, $labels) = toc();
|
||||
my @indented = map {
|
||||
($labels->{$_} || $_) =~ /^( *)/;
|
||||
[$_, length($1)]
|
||||
} @$values;
|
||||
print "Content-type: application/json; charset=UTF-8\r\n\r\n";
|
||||
binmode(STDOUT,':raw'); # because of encode_json
|
||||
print JSON::PP::encode_json(\@indented);
|
||||
} elsif ($q->path_info eq '/toc') {
|
||||
my ($values, $labels) = toc();
|
||||
print "Content-type: application/json; charset=UTF-8\r\n\r\n";
|
||||
binmode(STDOUT,':raw'); # because of encode_json
|
||||
print JSON::PP::encode_json($values);
|
||||
} elsif ($q->path_info eq '/top') {
|
||||
print GetHeader('', 'Top Blogs');
|
||||
print $q->start_div({-class=>'content top'});
|
||||
print $q->ol($q->li(top()));
|
||||
print_end_of_page();
|
||||
} elsif ($q->path_info =~ '^/match/(.*)') {
|
||||
my $term = $1;
|
||||
print GetHeader('', "Entries Matching '$term'");
|
||||
print $q->start_div({-class=>'content match'});
|
||||
print $q->ol($q->li(match($term)));
|
||||
print_end_of_page();
|
||||
} else {
|
||||
push(@UserGotoBarPages, 'Help');
|
||||
$UserGotoBar = $q->a({-href=>$q->url . '/source'}, 'Source');
|
||||
print GetHeader('', 'Submit a new link');
|
||||
print $q->start_div({-class=>'content index'});
|
||||
my $url = GetParam('url');
|
||||
my $name = UnquoteHtml(GetParam('name', get_name($url)));
|
||||
my $toc = GetParam('toc');
|
||||
my $confirm = GetParam('confirm');
|
||||
my $summary = GetParam('summary');
|
||||
if (not $url or not $toc) {
|
||||
default();
|
||||
} elsif (not $confirm) {
|
||||
confirm($url, $name, $toc);
|
||||
} else {
|
||||
post_addition($url, $name, $toc, $summary);
|
||||
}
|
||||
print_end_of_page();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /usr/bin/perl
|
||||
|
||||
# Copyright (C) 2011 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2011–2014 Alex Schroeder <alex@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
|
||||
@@ -17,63 +17,62 @@
|
||||
package OddMuse;
|
||||
use LWP::UserAgent;
|
||||
use HTML::TreeBuilder;
|
||||
use utf8;
|
||||
|
||||
# load Oddmuse core
|
||||
$RunCGI = 0;
|
||||
do "wiki.pl";
|
||||
|
||||
# globals
|
||||
my $wiki = 'BlogArchive';
|
||||
my $site = "http://campaignwiki.org/wiki/$wiki";
|
||||
# my $site = "http://localhost/wiki.pl";
|
||||
my $home = "$site/HomePage";
|
||||
$default_namespace = 'NameOfYourWiki';
|
||||
|
||||
main();
|
||||
|
||||
sub default {
|
||||
print $q->p("Copy a blog article to the "
|
||||
. $q->a({-href=>$home}, $wiki) . ".");
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'url'}, T('URL:')) . ' '
|
||||
. $q->textfield(-name=>'url', -id=>'url', -size=>50));
|
||||
my ($url, $ns) = @_;
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'copy');
|
||||
print $q->p("This script helps you copy of a blog post to your Campaign Wiki.");
|
||||
print $q->p($q->label({-for=>'url', -style=>'display: inline-block; width: 20ex'}, 'Blog post URL:'),
|
||||
$q->textfield(-name=>'url', -id=>'url', -size=>50),
|
||||
$q->br(),
|
||||
$q->label({-for=>'ns', -style=>'display: inline-block; width: 20ex'}, 'Name of your wiki:'),
|
||||
$q->textfield(-name=>'ns', -id=>'ns', -size=>50, -default=>$default_namespace));
|
||||
if ($url and not $ns) {
|
||||
print $q->p($q->em('Please provide the name of your wiki. It is mandatory. Use “NameOfYourWiki” if you just want to test something.'));
|
||||
}
|
||||
print $q->submit('go', 'Go!');
|
||||
print $q->end_form();
|
||||
print $q->p("Please make sure you’re only submitting your own articles",
|
||||
"or articles with an appropriate license.");
|
||||
|
||||
print $q->p("Drag this bookmarklet to your bookmarks bar for easy access:",
|
||||
$q->a({-href=>q{javascript:location='http://campaignwiki.org/copy?url='+encodeURIComponent(window.location.href)}}, $wiki) . ".");
|
||||
$q->a({-href=>q{javascript:location='http://campaignwiki.org/copy?url='+encodeURIComponent(window.location.href)}}, 'Copy Blog Post') . ".");
|
||||
}
|
||||
|
||||
sub check_url {
|
||||
my $url = shift;
|
||||
print $q->p("Looking at ", $q->a({-href=>$url}, $url));
|
||||
my ($name, $data) = get_data($url);
|
||||
$name = GetParam('name', $name);
|
||||
if (name_exists($name) and not GetParam('confirm', 0)) {
|
||||
print $q->p("We already have a page with that name: ",
|
||||
$q->a({-href=>$duplicate}, $duplicate));
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'name'}, T('New name:')) . ' '
|
||||
. $q->textfield(-name=>'name', -id=>'name', -size=>50,
|
||||
-default=>$name));
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
} elsif (not GetParam('confirm', 0)) {
|
||||
print $q->p("Please confirm that you want to copy this article to the wiki.");
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'name'}, T('Name:')) . ' '
|
||||
. $q->textfield(-name=>'name', -id=>'name', -size=>50,
|
||||
-default=>$name));
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
} else {
|
||||
post_addition($name, $data, $url);
|
||||
}
|
||||
sub confirm_overwrite {
|
||||
my ($url, $ns, $name) = @_;
|
||||
print $q->p("We already have a page with that name: ", GetPageLink($name));
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'name'}, T('New name:')) . ' '
|
||||
. $q->textfield(-name=>'name', -id=>'name', -size=>50, -default=>$name));
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('ns', $ns);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
sub confirm_save {
|
||||
my ($url, $ns, $name) = @_;
|
||||
my $ns = GetParam('ns', $default_namespace);
|
||||
print $q->p("Please confirm that you want to copy",
|
||||
$q->a({-href=>$url}, "this article"), "to", GetPageLink($HomePage, $ns) . ".");
|
||||
print $q->start_multipart_form(-method=>'get', -class=>'submit');
|
||||
print $q->p($q->label({-for=>'name'}, T('Name:')) . ' '
|
||||
. $q->textfield(-name=>'name', -id=>'name', -size=>50, -default=>$name));
|
||||
print $q->hidden('url', $url);
|
||||
print $q->hidden('ns', $ns);
|
||||
print $q->hidden('confirm', 1);
|
||||
print $q->submit('go', 'Continue');
|
||||
print $q->end_form();
|
||||
}
|
||||
|
||||
sub get_data {
|
||||
@@ -82,24 +81,32 @@ sub get_data {
|
||||
my $h = $tree->look_down('_tag', 'h1');
|
||||
$h = $tree->look_down('_tag', 'title') unless $h;
|
||||
$h = $h->as_text if $h;
|
||||
my $b = $tree->look_down('_tag', 'body');
|
||||
if ($b = $tree->look_down('_tag', 'div',
|
||||
'class', qr/post-body/)) {
|
||||
# blogspot
|
||||
my $b;
|
||||
if ($b = $tree->look_down('_tag', 'div', 'class', qr/post-body/)) {
|
||||
# Blogspot
|
||||
$b = html($b);
|
||||
} elsif ($b = $tree->look_down('_tag', 'div', 'class', qr/content/)) {
|
||||
# Oddmuse
|
||||
$b = html($b);
|
||||
} else {
|
||||
# no idea, just get the text
|
||||
$b = $b->as_text if $b;
|
||||
# default: get it all
|
||||
$b = html($tree->look_down('_tag', 'body'));
|
||||
}
|
||||
# common illegal character for page names
|
||||
$h =~ s/:/,/g;
|
||||
return ($h, $b);
|
||||
}
|
||||
|
||||
sub html {
|
||||
my $tree = shift;
|
||||
my ($tree, $p) = @_;
|
||||
# $p indicates whether we need an empty line or not
|
||||
my $str;
|
||||
for my $element ($tree->content_list()) {
|
||||
if (not ref $element) {
|
||||
$str .= $element;
|
||||
} elsif ($element->tag() eq 'p') {
|
||||
$str .= ($p == 1 ? "\n\n" : "") . html($element);
|
||||
$p = 1;
|
||||
} elsif ($element->tag() eq 'br') {
|
||||
$str .= "\n\n";
|
||||
} elsif ($element->tag() eq 'span'
|
||||
@@ -107,6 +114,20 @@ sub html {
|
||||
$str .= "[b]" . html($element) . "[/b]";
|
||||
} elsif ($element->tag() =~ m/^(b|i|h[1-6])$/) {
|
||||
$str .= "[$1]" . html($element) . "[/$1]";
|
||||
} elsif ($element->tag() eq 'a'
|
||||
and $element->attr('href')) {
|
||||
$str .= "[url=" . $element->attr('href') . "]" . html($element) . "[/url]";
|
||||
} elsif ($element->tag() eq 'img'
|
||||
and $element->attr('src')) {
|
||||
$str .= "[img]" . $element->attr('src') . "[/img]";
|
||||
} elsif ($element->tag() eq 'pre') {
|
||||
$str .= "\n\n[code]\n" . $element->as_text() . "\n[/code]";
|
||||
$p = 1;
|
||||
} elsif ($element->tag() eq 'div'
|
||||
and ($element->attr('style') =~ /float: *(left|right)/
|
||||
or $element->attr('style') =~ /text-align: *(center)/)) {
|
||||
$str .= "\n[$1]" . html($element) . "[/$1]";
|
||||
$p = 1;
|
||||
} else {
|
||||
$str .= html($element);
|
||||
}
|
||||
@@ -123,25 +144,25 @@ sub name_exists {
|
||||
}
|
||||
|
||||
sub post_addition {
|
||||
my ($name, $data, $url) = @_;
|
||||
my ($url, $ns, $name, $data) = @_;
|
||||
my $id = FreeToNormal($name);
|
||||
print $q->p("Adding ", $q->a({-href=>$url}, $name));
|
||||
print $q->p("Copying ", $q->a({-href=>$url}, "the blog post") . "…");
|
||||
my $text = "Based on [$url $name].\n----\n" . $data;
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my %params = (text => $text,
|
||||
title => $id,
|
||||
summary => $name,
|
||||
username => GetParam('username'),
|
||||
ns => $ns,
|
||||
pwd => GetParam('pwd'));
|
||||
$params{$QuestionaskerSecretKey} = 1 if $QuestionaskerSecretKey;
|
||||
my $response = $ua->post($site, \%params);
|
||||
my $response = $ua->post($FullUrl, \%params);
|
||||
if ($response->is_error) {
|
||||
print $q->p("The submission failed!");
|
||||
print $q->pre($response->status_line . "\n"
|
||||
. $response->content);
|
||||
print $q->p("Copying failed!");
|
||||
print $q->p($q->strong($response->status_line));
|
||||
print $response->content;
|
||||
} else {
|
||||
print $q->p("See for yourself: ",
|
||||
$q->a({-href=>"$site/$id"}, $name));
|
||||
print $q->p("Your copy: ", GetPageLink($name) . ".");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,12 +173,22 @@ sub main {
|
||||
print "Content-type: text/plain; charset=UTF-8\r\n\r\n", <DATA>;
|
||||
} else {
|
||||
$UserGotoBar .= $q->a({-href=>$q->url . '/source'}, 'Source');
|
||||
print GetHeader('', 'Submit a new blog article');
|
||||
print GetHeader('', 'Copy a blog article');
|
||||
print $q->start_div({-class=>'content index'});
|
||||
if (not GetParam('url')) {
|
||||
default();
|
||||
my $url = GetParam('url');
|
||||
my $ns = GetParam('ns');
|
||||
if (not $url or not $ns) {
|
||||
default($url, $ns);
|
||||
} else {
|
||||
check_url(GetParam('url'));
|
||||
my ($name, $data) = get_data($url);
|
||||
$name = GetParam('name', $name);
|
||||
if (name_exists($name) and not GetParam('confirm', 0)) {
|
||||
confirm_overwrite($url, $ns, $name);
|
||||
} elsif (not GetParam('confirm', 0)) {
|
||||
confirm_save($url, $ns, $name);
|
||||
} else {
|
||||
post_addition($url, $ns, $name, $data);
|
||||
}
|
||||
}
|
||||
print $q->p('Questions? Send mail to Alex Schröder <'
|
||||
. $q->a({-href=>'mailto:kensanata@gmail.com'},
|
||||
|
||||
0
contrib/campaignwiki/monster-tag.pl
Normal file → Executable file
0
contrib/campaignwiki/monster-tag.pl
Normal file → Executable file
0
contrib/campaignwiki/submit.pl
Normal file → Executable file
0
contrib/campaignwiki/submit.pl
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
108
contrib/oddmuse_stats
Executable file
108
contrib/oddmuse_stats
Executable file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/perl -w
|
||||
# -*- perl -*-
|
||||
|
||||
=head1 NAME
|
||||
|
||||
oddmuse-stats - Plugin to monitor Oddmuse edits
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
Set env.parent_dirs in the config file. The directories in this list
|
||||
are searched for data directories containing rc.log files. No
|
||||
whitespace in the directory names, sorry.
|
||||
|
||||
Example:
|
||||
|
||||
[oddmuse_stats]
|
||||
user www-data
|
||||
env.parent_dirs /home/alex /home/alex/campaignwiki
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Original Author: Alex Schroeder
|
||||
|
||||
=head1 LICENSE
|
||||
|
||||
GPLv3
|
||||
|
||||
=head1 MAGIC MARKERS
|
||||
|
||||
#%# family=auto
|
||||
#%# capabilities=autoconf
|
||||
|
||||
=cut
|
||||
|
||||
use Munin::Plugin;
|
||||
use File::Basename;
|
||||
|
||||
# The wiki directories may not contain any spaces.
|
||||
# Use the config file to set the environment variable!
|
||||
my @parent_dirs = ();
|
||||
my %logfiles = ();
|
||||
my %names = ();
|
||||
my $debug = $ENV{MUNIN_DEBUG};
|
||||
|
||||
if ($ENV{'parent_dirs'}) {
|
||||
@parent_dirs = split(/ /, $ENV{'parent_dirs'});
|
||||
} else {
|
||||
die "The parent_dirs environment variable must be set.\n";
|
||||
}
|
||||
|
||||
for my $parent_dir (@parent_dirs) {
|
||||
warn "opening $parent_dir\n" if $debug;
|
||||
if (opendir(my $dh, $parent_dir)) {
|
||||
while(readdir $dh) {
|
||||
next if $_ eq '.' or $_ eq '..';
|
||||
if (-r "$parent_dir/$_/rc.log") {
|
||||
my $basename = basename($_);
|
||||
$names{clean_fieldname($basename)}
|
||||
= $basename;
|
||||
$logfiles{clean_fieldname($basename)}
|
||||
= "$parent_dir/$_/rc.log";
|
||||
} else {
|
||||
warn "discarding $_\n" if $debug;
|
||||
}
|
||||
}
|
||||
closedir $dh;
|
||||
}
|
||||
}
|
||||
|
||||
my $yesterday = time() - 86400;
|
||||
|
||||
if ($ARGV[0]) {
|
||||
if ($ARGV[0] eq 'autoconf') {
|
||||
if (keys %logfiles) {
|
||||
print "yes\n";
|
||||
exit 0;
|
||||
} else {
|
||||
print "no (no logfiles found in " . join(", ", @parent_dirs) . ")\n";
|
||||
exit 0;
|
||||
}
|
||||
} elsif ($ARGV[0] eq 'config') {
|
||||
print "graph_title Oddmuse Wikis\n";
|
||||
print "graph_category wikis\n";
|
||||
print "graph_info This graph shows how many edits the wiki had in the last 24h.\n";
|
||||
print "graph_vlabel edits/day\n";
|
||||
print "graph_order";
|
||||
for my $wiki (sort keys %logfiles) {
|
||||
print " $wiki";
|
||||
};
|
||||
print "\n";
|
||||
for my $wiki (sort keys %logfiles) {
|
||||
my $name = $names{$wiki};
|
||||
print "$wiki.label $name\n";
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
for my $wiki (sort keys %logfiles) {
|
||||
open (my $fh, '<', $logfiles{$wiki})
|
||||
or die "cannot open " . $logfiles{$wiki} . ": $!";
|
||||
my $value = 0;
|
||||
while (<$fh>) {
|
||||
my ($ts) = split(/\x1e/);
|
||||
$value++ if $ts and $ts >= $yesterday;
|
||||
}
|
||||
print "$wiki.value $value\n";
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
(add-to-list 'vc-handled-backends 'oddmuse)
|
||||
|
||||
(require 'oddmuse)
|
||||
(require 'oddmuse-curl)
|
||||
(require 'diff)
|
||||
|
||||
(defun vc-oddmuse-revision-granularity () 'file)
|
||||
@@ -39,11 +39,15 @@
|
||||
(file-name-directory file)))
|
||||
|
||||
(defun vc-oddmuse-state (file)
|
||||
"No idea."
|
||||
'up-to-date)
|
||||
"Return the current version control state of FILE.
|
||||
For a list of possible values, see `vc-state'."
|
||||
;; Avoid downloading the current version from the wiki and comparing
|
||||
;; the text: Too much traffic!
|
||||
'edited)
|
||||
|
||||
(defun vc-oddmuse-working-revision (file)
|
||||
"No idea")
|
||||
"The current revision based on `oddmuse-revisions'."
|
||||
(oddmuse-revision-get oddmuse-wiki oddmuse-page-name))
|
||||
|
||||
(defun vc-oddmuse-checkout-model (files)
|
||||
"No locking."
|
||||
@@ -60,52 +64,28 @@
|
||||
nil)
|
||||
|
||||
(defvar vc-oddmuse-log-command
|
||||
"curl --silent %w\"?action=rc;showedit=1;all=1;from=1;raw=1;match=%r\""
|
||||
(concat "curl --silent %w"
|
||||
" --form action=rc"
|
||||
" --form showedit=1"
|
||||
" --form all=1"
|
||||
" --form from=1"
|
||||
" --form raw=1"
|
||||
" --form match='%r'")
|
||||
"Command to use for publishing index pages.
|
||||
It must print the page to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
%r Regular expression, URL encoded, of the pages to limit ourselves to.
|
||||
This uses the free variable `regexp'.")
|
||||
See `oddmuse-format-command' for the formatting options.")
|
||||
|
||||
(defun vc-oddmuse-print-log (files buffer &optional shortlog
|
||||
start-revision limit)
|
||||
(defun vc-oddmuse-print-log (files buffer &optional shortlog start-revision limit)
|
||||
"Load complete recent changes for the files."
|
||||
(let* ((wiki (or oddmuse-wiki
|
||||
(completing-read "Wiki: " oddmuse-wikis nil t)))
|
||||
(wiki-data (assoc wiki oddmuse-wikis))
|
||||
(url (nth 1 wiki-data))
|
||||
(regexp (concat
|
||||
"^(" ;; Perl regular expression!
|
||||
(mapconcat 'file-name-nondirectory files "|")
|
||||
")$"))
|
||||
(command (oddmuse-format-command vc-oddmuse-log-command))
|
||||
(coding (nth 2 wiki-data))
|
||||
(coding-system-for-read coding)
|
||||
(coding-system-for-write coding)
|
||||
(max-mini-window-height 1))
|
||||
(oddmuse-run "Getting recent changes" command buffer nil))
|
||||
;; Parse current buffer as RSS 3.0 and display it correctly.
|
||||
(save-excursion
|
||||
(with-current-buffer buffer
|
||||
(let (result)
|
||||
(dolist (item (cdr (split-string (buffer-string) "\n\n")));; skip first item
|
||||
(let ((data (mapcar (lambda (line)
|
||||
(when (string-match "^\\(.*?\\): \\(.*\\)" line)
|
||||
(cons (match-string 1 line)
|
||||
(match-string 2 line))))
|
||||
(split-string item "\n"))))
|
||||
(setq result (cons data result))))
|
||||
(dolist (item (nreverse result))
|
||||
(insert "title: " (cdr (assoc "title" item)) "\n"
|
||||
"version: " (cdr (assoc "revision" item)) "\n"
|
||||
"generator: " (cdr (assoc "generator" item)) "\n"
|
||||
"timestamp: " (cdr (assoc "last-modified" item)) "\n\n"
|
||||
" " (or (cdr (assoc "description" item)) ""))
|
||||
(fill-paragraph)
|
||||
(insert "\n\n"))
|
||||
(goto-char (point-min))))))
|
||||
;; Derive `oddmuse-wiki' from the first file
|
||||
(with-oddmuse-file (car files)
|
||||
;; The wiki expects a Perl regular expression!
|
||||
(let ((regexp (concat "^(" (mapconcat 'file-name-nondirectory files "|") ")$")))
|
||||
(oddmuse-run "Getting recent changes" vc-oddmuse-log-command nil nil buffer)))
|
||||
(with-current-buffer buffer
|
||||
(oddmuse-render-rss3))
|
||||
'limit-unsupported)
|
||||
|
||||
(defun vc-oddmuse-log-outgoing ()
|
||||
(error "This is not supported."))
|
||||
@@ -114,74 +94,75 @@ It must print the page to stdout.
|
||||
(error "This is not supported."))
|
||||
|
||||
(defvar vc-oddmuse-get-revision-command
|
||||
"curl --silent %w\"?action=browse;id=%t;revision=%o;raw=1\""
|
||||
(concat "curl --silent"
|
||||
" --form action=browse"
|
||||
" --form id=%t"
|
||||
" --form revision=%v"
|
||||
" --form raw=1"
|
||||
" '%w'")
|
||||
"Command to use to get older revisions of a page.
|
||||
It must print the page to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
%t Page title as provided by `oddmuse-page-name'
|
||||
%o Revision to retrieve as provided by `oddmuse-revision'")
|
||||
%v Revision to retrieve as provided by `oddmuse-revision'")
|
||||
|
||||
(defvar vc-oddmuse-get-history-command
|
||||
"curl --silent %w\"?action=history;id=%t;raw=1\""
|
||||
"Command to use to get the history of a page.
|
||||
It must print the page to stdout.
|
||||
|
||||
%? '?' character
|
||||
%w URL of the wiki as provided by `oddmuse-wikis'
|
||||
%t Page title as provided by `oddmuse-page-name'")
|
||||
(defun oddmuse-revision-filename (rev)
|
||||
"Return filename for revision REV.
|
||||
This uses `oddmuse-directory', `wiki' and `pagename' as bound by
|
||||
`with-oddmuse-file'."
|
||||
(concat oddmuse-directory
|
||||
"/" wiki
|
||||
"/" pagename
|
||||
".~" rev "~"))
|
||||
|
||||
(defun vc-oddmuse-diff (files &optional rev1 rev2 buffer)
|
||||
"Report the differences for FILES."
|
||||
(setq buffer (or buffer (get-buffer-create "*vc-diff*")))
|
||||
(dolist (file files)
|
||||
(setq oddmuse-page-name (file-name-nondirectory file)
|
||||
oddmuse-wiki (or oddmuse-wiki
|
||||
(file-name-nondirectory
|
||||
(directory-file-name
|
||||
(file-name-directory file)))))
|
||||
(let* ((wiki-data (or (assoc oddmuse-wiki oddmuse-wikis)
|
||||
(error "Cannot find data for wiki %s" oddmuse-wiki)))
|
||||
(url (nth 1 wiki-data)))
|
||||
(unless rev1
|
||||
;; Since we don't know the most recent revision we have to fetch
|
||||
;; it from the server every time.
|
||||
(with-temp-buffer
|
||||
(let ((max-mini-window-height 1))
|
||||
(oddmuse-run "Determining latest revision"
|
||||
(oddmuse-format-command vc-oddmuse-get-history-command)
|
||||
(current-buffer) nil))
|
||||
(if (re-search-forward "^revision: \\([0-9]+\\)$" nil t)
|
||||
(setq rev1 (match-string 1))
|
||||
(error "Cannot determine the latest revision from the page history"))))
|
||||
(with-oddmuse-file file
|
||||
(setq rev1 (or rev1 (oddmuse-get-latest-revision wiki pagename)))
|
||||
(dolist (rev (list rev1 rev2))
|
||||
(when (and rev
|
||||
(not (file-readable-p (concat oddmuse-directory
|
||||
"/" oddmuse-wiki "/"
|
||||
oddmuse-page-name
|
||||
".~" rev "~"))))
|
||||
(when (and rev (not (file-readable-p (oddmuse-revision-filename rev))))
|
||||
(let* ((oddmuse-revision rev)
|
||||
(command (oddmuse-format-command vc-oddmuse-get-revision-command))
|
||||
(coding (nth 2 wiki-data))
|
||||
(filename (concat oddmuse-directory "/" oddmuse-wiki "/"
|
||||
oddmuse-page-name ".~" rev "~"))
|
||||
(coding-system-for-read coding)
|
||||
(coding-system-for-write coding))
|
||||
(command vc-oddmuse-get-revision-command)
|
||||
(filename (oddmuse-revision-filename rev)))
|
||||
(with-temp-buffer
|
||||
(let ((max-mini-window-height 1))
|
||||
(oddmuse-run (concat "Downloading revision " rev)
|
||||
command (current-buffer) nil))
|
||||
(oddmuse-run
|
||||
(concat "Downloading revision " rev)
|
||||
command wiki pagename)
|
||||
(write-file filename)))))
|
||||
(diff-no-select
|
||||
(if rev1
|
||||
(concat oddmuse-directory "/" oddmuse-wiki "/" oddmuse-page-name ".~" rev1 "~")
|
||||
file)
|
||||
(if rev2
|
||||
(concat oddmuse-directory "/" oddmuse-wiki "/" oddmuse-page-name ".~" rev2 "~")
|
||||
file)
|
||||
(if rev1 (oddmuse-revision-filename rev1) file)
|
||||
(if rev2 (oddmuse-revision-filename rev2) file)
|
||||
nil
|
||||
(vc-switches 'oddmuse 'diff)
|
||||
buffer))))
|
||||
|
||||
(defun vc-oddmuse-revert (file &optional contents-done)
|
||||
"Revert FILE back to the wiki revision.
|
||||
If optional arg CONTENTS-DONE is non-nil, then nothing needs to
|
||||
be done, as the contents of FILE have already been reverted from
|
||||
a version backup."
|
||||
(unless contents-done
|
||||
(with-oddmuse-file file
|
||||
(let ((command (oddmuse-format-command vc-oddmuse-get-revision-command)))
|
||||
(with-temp-buffer
|
||||
(oddmuse-run "Loading" command)
|
||||
(write-file file))))))
|
||||
|
||||
(defun vc-oddmuse-checkin (files rev comment)
|
||||
"Commit changes in FILES to this backend.
|
||||
REV is a historical artifact and should be ignored. COMMENT is
|
||||
used as a check-in comment."
|
||||
(dolist (file files)
|
||||
(with-oddmuse-file file
|
||||
(let* ((summary comment)
|
||||
(command (oddmuse-format-command oddmuse-post-command))
|
||||
(buf (get-buffer-create " *oddmuse-response*")))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(oddmuse-run "Posting" command wiki pagename buf t 302))))))
|
||||
|
||||
(provide 'vc-oddmuse)
|
||||
|
||||
@@ -74,6 +74,55 @@ h1 a:visited, h2 a:visited, h3 a:visited {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* for download buttons and the like */
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
font-size: 120%;
|
||||
cursor: pointer;
|
||||
padding: 0.4em 0.6em;
|
||||
text-shadow: 0px -1px 0px #ccc;
|
||||
background-color: #cfa;
|
||||
border: 1px solid #9d8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 1px 3px white inset, 0px 1px 3px black;
|
||||
}
|
||||
|
||||
.button .icon {
|
||||
color: #363;
|
||||
text-shadow: 0px -1px 1px white, 0px 1px 3px #666;
|
||||
}
|
||||
|
||||
.button a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* links */
|
||||
|
||||
a.pencil {
|
||||
padding-left: 1ex;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
visible: hidden;
|
||||
transition: visibility 0s 1s, opacity 1s linear;
|
||||
opacity: 0;
|
||||
}
|
||||
*:hover > a.pencil {
|
||||
visible: visible;
|
||||
transition: opacity .5s linear;
|
||||
opacity: 1;
|
||||
}
|
||||
@media print {
|
||||
a.pencil {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.number {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stop floating content from flowing over the footer */
|
||||
|
||||
hr {
|
||||
@@ -110,6 +159,15 @@ pre, code, tt {
|
||||
line-height: 110%;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow:hidden;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
/* styling for divs that will be invisible when printing
|
||||
when printing. */
|
||||
|
||||
@@ -235,8 +293,8 @@ div.comment h2 {
|
||||
margin-top: 5em;
|
||||
}
|
||||
/* comment pages with username, homepage, and email subscription */
|
||||
.comment span { display: block; }
|
||||
.comment span label { display: inline-block; width: 10em; }
|
||||
.comment form span { display: block; }
|
||||
.comment form span label { display: inline-block; width: 10em; }
|
||||
/* IE sucks */
|
||||
.comment input#username,
|
||||
.comment input#homepage,
|
||||
@@ -336,6 +394,10 @@ div.image span.caption {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.left { float:left; margin-right: 1em; }
|
||||
.right { float:right; margin-left: 1em; }
|
||||
.half a img { height: 50%; width: 50%; }
|
||||
|
||||
632
css/alex-2014.css
Normal file
632
css/alex-2014.css
Normal file
@@ -0,0 +1,632 @@
|
||||
/* font-face includes TTF for PDF generation */
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff') url('/fonts/NoticiaText-Regular.ttf') format('truetype');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff') url('/fonts/NoticiaText-Regular.ttf') format('truetype');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff') url('/fonts/NoticiaText-Regular.ttf') format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff') url('/fonts/NoticiaText-Bold.ttf') format('truetype');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff') url('/fonts/NoticiaText-Bold.ttf') format('truetype');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff') url('/fonts/NoticiaText-Bold.ttf') format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff') url('/fonts/NoticiaText-Italic.ttf') format('truetype');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff') url('/fonts/NoticiaText-Italic.ttf') format('truetype');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff') url('/fonts/NoticiaText-Italic.ttf') format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff') url('/fonts/NoticiaText-BoldItalic.ttf') format('truetype');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff') url('/fonts/NoticiaText-BoldItalic.ttf') format('truetype');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff') url('/fonts/NoticiaText-BoldItalic.ttf') format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Symbola';
|
||||
src: local('Symbola'), url('/fonts/Symbola.woff') format('woff') url('/fonts/Symbola.ttf') format('truetype');
|
||||
}
|
||||
|
||||
body, rss {
|
||||
font-family: "Noticia Text", Symbola, serif;
|
||||
font-style: normal;
|
||||
font-size: 14pt;
|
||||
margin: 1em 3em;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font-size: 12pt;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* hide all the crap */
|
||||
div.diff, div.diff+hr, div.refer, div.near, div.definition, div.sister,
|
||||
div.cal, div.footer, span.specialdays, span.gotobar, a.edit, a.number span,
|
||||
div.rc form, form.tiny, p.comment, p#plus1, div.g-plusone, div.content a.feed {
|
||||
display:none;
|
||||
}
|
||||
div.content a.book,
|
||||
div.content a.movie {
|
||||
text-decoration: none;
|
||||
}
|
||||
a cite {
|
||||
font-style: italic;
|
||||
}
|
||||
img[alt="RSS"] { display: none }
|
||||
a.rss { font-size: 8pt }
|
||||
}
|
||||
|
||||
/* headings: we can use larger sizes if we use a lighter color.
|
||||
we cannot inherit the font-family because header and footer use a narrow font. */
|
||||
|
||||
h1, h2, h3, title {
|
||||
font-family: inherit;
|
||||
font-weight: normal;
|
||||
}
|
||||
h1, channel title {
|
||||
font-size: 32pt;
|
||||
margin: 1em 0 0.5em 0;
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18pt;
|
||||
margin: 2em 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
margin: 1em 0 0 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* headers in the journal are smaller */
|
||||
|
||||
div.journal h1, item title {
|
||||
font-size: inherit;
|
||||
padding: 0;
|
||||
clear: both;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
div.journal h2 {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
div.journal h3 {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
font-style: italic;
|
||||
}
|
||||
div.journal hr {
|
||||
visibility: hidden;
|
||||
}
|
||||
p.more {
|
||||
margin-top: 3em;
|
||||
}
|
||||
/* Links in headings appear on journal pages. */
|
||||
|
||||
h1 a, h2 a, h3 a {
|
||||
color:inherit;
|
||||
text-decoration:none;
|
||||
font-weight: normal;
|
||||
}
|
||||
h1 a:visited, h2 a:visited, h3 a:visited {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* for download buttons and the like */
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
font-size: 120%;
|
||||
cursor: pointer;
|
||||
padding: 0.4em 0.6em;
|
||||
text-shadow: 0px -1px 0px #ccc;
|
||||
background-color: #cfa;
|
||||
border: 1px solid #9d8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 1px 3px white inset, 0px 1px 3px black;
|
||||
}
|
||||
|
||||
.button .icon {
|
||||
color: #363;
|
||||
text-shadow: 0px -1px 1px white, 0px 1px 3px #666;
|
||||
}
|
||||
|
||||
.button a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* links */
|
||||
|
||||
a.pencil {
|
||||
padding-left: 1ex;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
visibility: hidden;
|
||||
transition: visibility 0s 1s, opacity 1s linear;
|
||||
opacity: 0;
|
||||
}
|
||||
*:hover > a.pencil {
|
||||
visibility: visible;
|
||||
transition: opacity .5s linear;
|
||||
opacity: 1;
|
||||
}
|
||||
@media print {
|
||||
a.pencil {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.number {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stop floating content from flowing over the footer */
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* the distance between links in the navigation bars */
|
||||
|
||||
span.bar a {
|
||||
margin-right: 1ex;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* search box in the top bar */
|
||||
|
||||
.header form, .header p {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
label[for="searchlang"], #searchlang, .header input[type="submit"] {
|
||||
/* don't use display: none! http://stackoverflow.com/questions/5665203/getting-iphone-go-button-to-submit-form */
|
||||
visibility: hidden; position: absolute;
|
||||
}
|
||||
/* wrap on the iphone */
|
||||
@media media only screen and (max-device-width: 480px) {
|
||||
}
|
||||
|
||||
.header input {
|
||||
width: 10ex;
|
||||
}
|
||||
|
||||
/* other form fields */
|
||||
|
||||
input[type="text"] {
|
||||
padding: 0;
|
||||
font-size: 80%;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
/* code */
|
||||
|
||||
textarea, pre, code, tt {
|
||||
font-family: "Andale Mono", Monaco, "Courier New", Courier, monospace, "Symbola";
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow:hidden;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
/* styling for divs that will be invisible when printing
|
||||
when printing. */
|
||||
|
||||
div.header, div.footer, div.near, div.definition, p.comment, a.tag {
|
||||
|
||||
font-size: 14pt;
|
||||
}
|
||||
@media print {
|
||||
div.header, div.footer, div.near, div.definition, p.comment, a.tag {
|
||||
font-size: 8pt;
|
||||
}
|
||||
}
|
||||
|
||||
div.footer form.search {
|
||||
display: none;
|
||||
}
|
||||
div.rc li + li {
|
||||
margin-top: 1em;
|
||||
}
|
||||
div.rc li strong, table.history strong, strong.description {
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
div.diff {
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
font-size: 12pt;
|
||||
color: #000;
|
||||
|
||||
}
|
||||
div.old {
|
||||
background-color: #ffffaf;
|
||||
}
|
||||
div.new {
|
||||
background-color: #cfffcf;
|
||||
}
|
||||
|
||||
div.refer {
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
div.message {
|
||||
background-color:#fee;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
img.xml {
|
||||
border:none;
|
||||
padding:1px;
|
||||
}
|
||||
a.small img {
|
||||
max-width:300px;
|
||||
}
|
||||
a.large img {
|
||||
max-width:600px;
|
||||
}
|
||||
div.sister {
|
||||
margin-right:1ex;
|
||||
background-color:inherit;
|
||||
}
|
||||
div.sister p {
|
||||
margin-top:0;
|
||||
}
|
||||
div.sister hr {
|
||||
display:none;
|
||||
}
|
||||
div.sister img {
|
||||
border:none;
|
||||
}
|
||||
|
||||
div.near, div.definition {
|
||||
background-color:#efe;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
float:right;
|
||||
border:1px dotted #000;
|
||||
padding:0 1em;
|
||||
}
|
||||
div.sidebar ul {
|
||||
padding-left:1em;
|
||||
}
|
||||
|
||||
/* replacements, features */
|
||||
|
||||
ins {
|
||||
color: #b33;
|
||||
text-decoration: none;
|
||||
}
|
||||
acronym, abbr {
|
||||
letter-spacing:0.1em;
|
||||
font-variant:small-caps;
|
||||
}
|
||||
|
||||
/* Interlink prefix not shown */
|
||||
a .site, a .separator {
|
||||
display: none;
|
||||
}
|
||||
a cite { font:inherit; }
|
||||
/* browser borkage */
|
||||
textarea[name="text"] { width:97%; height:80%; }
|
||||
textarea[name="summary"] { width:97%; height:3em; }
|
||||
/* comments */
|
||||
textarea[name="aftertext"] { width:97%; height:10em; }
|
||||
div.commentshown {
|
||||
font-size: 12pt;
|
||||
padding: 2em 0;
|
||||
}
|
||||
div.commenthidden {
|
||||
display:none;
|
||||
}
|
||||
div.commentshown {
|
||||
display:block;
|
||||
}
|
||||
p.comment {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.comment {
|
||||
font-size: 14pt;
|
||||
}
|
||||
div.comment h2 {
|
||||
margin-top: 5em;
|
||||
}
|
||||
/* comment pages with username, homepage, and email subscription */
|
||||
.comment form span { display: block; }
|
||||
.comment form span label { display: inline-block; width: 10em; }
|
||||
/* IE sucks */
|
||||
.comment input#username,
|
||||
.comment input#homepage,
|
||||
.comment input#mail { width: 20em; }
|
||||
|
||||
/* cal */
|
||||
div.month { padding:0; margin:0 2ex; }
|
||||
body > div.month {
|
||||
float:right;
|
||||
background-color: inherit;
|
||||
border:solid thin;
|
||||
padding:0 1ex;
|
||||
}
|
||||
div.year > div.month {
|
||||
float:left;
|
||||
}
|
||||
div.footer {
|
||||
clear:both;
|
||||
}
|
||||
div.content div.month a.edit {
|
||||
color:inherit;
|
||||
font-weight:inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* history tables and other tables */
|
||||
table.history {
|
||||
border: none;
|
||||
}
|
||||
td.history {
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.user {
|
||||
border: none;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding: 1em;
|
||||
margin: 1em 2em;
|
||||
}
|
||||
table.user tr td, table.user tr th {
|
||||
border: none;
|
||||
padding: 0.2em 0.5em;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.arab tr th {
|
||||
font-weight:normal;
|
||||
text-align:left;
|
||||
vertical-align:top;
|
||||
}
|
||||
table.arab, table.arab tr th, table.arab tr td {
|
||||
border:none;
|
||||
}
|
||||
th.nobreak {
|
||||
white-space:nowrap;
|
||||
}
|
||||
table.full { width:99%; margin-left:1px; }
|
||||
table.j td, table.j th, table tr td.j, table tr th.j, .j { text-align:justify; }
|
||||
table.l td, table.l th, table tr td.l, table tr th.l, .l { text-align:left; }
|
||||
table.r td, table.r th, table tr td.r, table tr th.r, .r { text-align:right; }
|
||||
table.c td, table.c th, table tr td.c, table tr th.c, .c { text-align:center; }
|
||||
table.t td { vertical-align: top; }
|
||||
td.half { width:50%; }
|
||||
td.third { width:33%; }
|
||||
|
||||
form table td { padding:5px; }
|
||||
|
||||
/* lists */
|
||||
dd { padding-bottom:0.5ex; }
|
||||
dl.inside dt { float:left; }
|
||||
/* search */
|
||||
div.search span.result { font-size:larger; }
|
||||
div.search span.info { font-size:smaller; font-style:italic; }
|
||||
div.search p.result { display:none; }
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
margin: 0 0 0 1ex;
|
||||
padding: 0;
|
||||
border: 1px solid #000;
|
||||
opacity: 0.3;
|
||||
background-color:#ffe;
|
||||
}
|
||||
|
||||
/* images */
|
||||
|
||||
div.content a.feed img, div.journal a.feed img,
|
||||
div.content a img.smiley, div.journal a img.smiley, img.smiley,
|
||||
div.content a.inline img, div.journal a.inline img,
|
||||
div.content li a.image img, div.journal li a.image img {
|
||||
margin: 0; padding: 0; border: none;
|
||||
}
|
||||
div.image a img {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.image span.caption {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.left { float:left; margin-right: 1em; }
|
||||
.right { float:right; margin-left: 1em; }
|
||||
.half a img { height: 50%; width: 50%; }
|
||||
div.left .left, div.right .right {
|
||||
float:none;
|
||||
}
|
||||
.center { text-align:center; }
|
||||
table.aside {
|
||||
float:right;
|
||||
width:40%;
|
||||
margin-left: 1em;
|
||||
padding: 1ex;
|
||||
border: 1px dotted #666;
|
||||
}
|
||||
table.aside td {
|
||||
text-align:left;
|
||||
}
|
||||
div.sidebar {
|
||||
float:right; width: 250px;
|
||||
text-align: right;
|
||||
border: none;
|
||||
margin: 1ex;
|
||||
}
|
||||
|
||||
.bigsidebar {
|
||||
float:right;
|
||||
width: 500px;
|
||||
border: none;
|
||||
margin-left: 1ex;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
dl.irc dt { width:20ex; float:left; text-align:right; clear:left; }
|
||||
dl.irc dt span.time { float:left; }
|
||||
dl.irc dd { margin-left:22ex; }
|
||||
|
||||
/* portrait */
|
||||
|
||||
div.footer, div.comment, hr { clear: both; }
|
||||
.portrait { float: left; font-size: small; margin-right: 1em; }
|
||||
.portrait a { color: #999; }
|
||||
|
||||
div.left { float:left; margin:1em; padding: 0.5em; }
|
||||
div.left p { display:table-cell; }
|
||||
div.left p + p { display:table-caption; caption-side:bottom; }
|
||||
|
||||
p.table a { float:left; width:20ex; }
|
||||
p.table + p { clear:both; }
|
||||
|
||||
/* no bleeding
|
||||
@media screen {
|
||||
div.content, div.rc {
|
||||
overflow:hidden;
|
||||
}
|
||||
} */
|
||||
|
||||
/* rss */
|
||||
|
||||
channel * { display: block; }
|
||||
|
||||
channel title {
|
||||
margin-top: 30pt;
|
||||
}
|
||||
copyright {
|
||||
font-size: 14pt;
|
||||
margin-top: 1em;
|
||||
}
|
||||
channel > link:before {
|
||||
font-size: 18pt;
|
||||
display: block;
|
||||
margin: 1em;
|
||||
padding: 0.5em;
|
||||
content: "This is an RSS feed, designed to be read in a feed reader.";
|
||||
color: red;
|
||||
border: 1px solid red;
|
||||
}
|
||||
link, license {
|
||||
font-size: 11pt;
|
||||
margin-bottom: 9pt;
|
||||
}
|
||||
username:before { content: "Last edited by "; }
|
||||
username:after { content: "."; }
|
||||
generator:before { content: "Feed generated by "; }
|
||||
generator:after { content: "."; }
|
||||
channel description {
|
||||
font-weight: bold;
|
||||
}
|
||||
item description {
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
docs, language,
|
||||
pubDate, lastBuildDate, ttl, guid, category, comments,
|
||||
docs, image title, image link,
|
||||
status, version, diff, history, importance {
|
||||
display: none;
|
||||
}
|
||||
347
css/bootstrap.css
vendored
Normal file
347
css/bootstrap.css
vendored
Normal file
@@ -0,0 +1,347 @@
|
||||
/* Public Domain
|
||||
Written by Alex Schroeder and Evgkeni Sampelnikof */
|
||||
textarea { width:100%; }
|
||||
h1 a { color: inherit }
|
||||
div.journal h1 { font-size:large; }
|
||||
table { margin-bottom: 1em; }
|
||||
|
||||
div.diff { padding-left:5%; padding-right:5%; }
|
||||
div.old { background-color:#FFFFAF; }
|
||||
div.new { background-color:#CFFFCF; }
|
||||
|
||||
img.portrait { float: left; clear: left; margin: 1ex; border:#999 1px solid; }
|
||||
div.footer, div.comment, hr { clear: both; }
|
||||
div.portrait { float: left; clear: left; font-size: xx-small; margin-right: 1em; }
|
||||
div.portrait img.portrait { float: none; margin: 0; }
|
||||
div.portrait a { text-decoration: none; color: #999; }
|
||||
div.color {
|
||||
clear: both;
|
||||
padding: 1ex 2em;
|
||||
margin: 0 -1em;
|
||||
box-shadow: inset 40px 0px 20px -20px #EEEEEE,
|
||||
inset -40px 0px 20px -20px #EEEEEE;
|
||||
}
|
||||
|
||||
.left { float:left; margin-right:1em; }
|
||||
.right { float:right; margin-left:1em; }
|
||||
|
||||
div.two, div.one {
|
||||
color: #444;
|
||||
background-color: #f8f8f8;
|
||||
margin: 7px -1em;
|
||||
box-shadow: inset 40px 0px 20px -20px #EEEEEE,
|
||||
inset -40px 0px 20px -20px #EEEEEE,
|
||||
0px 8px 4px -8px #ccc,
|
||||
0px -6px 4px -8px #ccc;
|
||||
}
|
||||
|
||||
.irc .time { display: none; }
|
||||
dl.irc dt { float: left; text-align: right; width: 13ex; }
|
||||
dl.irc dd { margin-left: 15ex; display: block; }
|
||||
|
||||
div.toc {
|
||||
background-color: #FAFAFA;
|
||||
border: 1px solid #dddddd;
|
||||
font-family: sans-serif;
|
||||
font-size: 80%;
|
||||
line-height: 90%;
|
||||
margin: 3em 0 1em;
|
||||
padding: 1em 0px 0px 1em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
div.toc li {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.ell .toc li {
|
||||
display: inline;
|
||||
padding-right: 1em;
|
||||
}
|
||||
div.letter { column-count: 3; -webkit-column-count: 3; -moz-column-count: 3 }
|
||||
|
||||
.footer .edit.bar {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.specialdays {
|
||||
line-height: 1em; /* has no effect: set for div.header instead? */
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.footer .time {
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
color: #888;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.footer .legal {
|
||||
text-align: justify;
|
||||
-moz-text-align-last: center;
|
||||
text-align-last: center;
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4em;
|
||||
margin: 0 120px 0;
|
||||
padding: 1em 0 0;
|
||||
}
|
||||
.footer .legal a {
|
||||
color: #888;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.translation.bar {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 0.8em;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
/* .include.WikiLanguageMenu could share those styles,
|
||||
(altough it might be better to leave it left-aligned) */
|
||||
|
||||
.translation.bar a:nth-child(n+2) {
|
||||
border-left: 1px solid #999;
|
||||
}
|
||||
|
||||
.translation.bar a {
|
||||
padding: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.navbar .nav > li > a.brand {
|
||||
color: #C76A0D;
|
||||
padding: 5px 8px 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #C76A0D;
|
||||
}
|
||||
a:hover {
|
||||
color: #8F3E0F;
|
||||
}
|
||||
|
||||
body {
|
||||
word-wrap: break-word;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
background-color: #EEEEEE;
|
||||
color: #000;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: #ccc 1px solid;
|
||||
border-bottom: #fff 1px solid;
|
||||
}
|
||||
|
||||
.footer_wrapper {
|
||||
background: #EEEEEE;
|
||||
background: linear-gradient(to bottom, #EEEEEE, #CCCCCC);
|
||||
padding-bottom: 20px;
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.footer.container hr:first-child {
|
||||
display: none;
|
||||
}
|
||||
.footer hr {
|
||||
margin: 10px 100px 0;
|
||||
}
|
||||
.footer.container {
|
||||
padding-top: 10px;
|
||||
margin-top: 10px;
|
||||
background: radial-gradient(
|
||||
50% 8px at top,
|
||||
rgba(0, 0, 0, 0.3) 0%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
box-shadow: 0 -1px 2px -2px white;
|
||||
/* border-top: 1px #ccc solid; */
|
||||
}
|
||||
body, li {
|
||||
line-height: 2em;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
text-shadow: 1px 1px white;
|
||||
}
|
||||
.navbar-inner {
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-width: 0 1px 1px;
|
||||
}
|
||||
.navbar .nav > li > a {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
label[for="searchlang"], input#searchlang {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width:480px){
|
||||
h1 { font-size: 1.8em; }
|
||||
.navbar .nav > li > a {
|
||||
padding: 0px 2px;
|
||||
line-height: 10px;
|
||||
}
|
||||
/* hide CC logo */
|
||||
.footer .licence {
|
||||
display: none;
|
||||
}
|
||||
/* make legal foo*/
|
||||
.footer .legal {
|
||||
margin: 5px 5px 5px;
|
||||
}
|
||||
.footer .bar a {
|
||||
margin: 2px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Right-alignment. Will make it harder to achieve responsive behaviour:
|
||||
|
||||
twitter.github.com/bootstrap/components.html#navbar
|
||||
Look for "Responsive navbar" heading.
|
||||
|
||||
If this is undesirable, remove the lines with the "RA" comment;
|
||||
*/
|
||||
|
||||
.navbar .nav {
|
||||
text-align: right; /* RA */
|
||||
*text-align: left; /* RA */
|
||||
width: 100%; /* RA */
|
||||
}
|
||||
|
||||
.navbar .nav > li:first-child {
|
||||
float: left; /* RA */
|
||||
}
|
||||
|
||||
.navbar .nav > li {
|
||||
display: inline-block; /* RA */
|
||||
float: none; /* RA */
|
||||
*float: left;
|
||||
*display: inline;
|
||||
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
textarea:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="datetime"]:focus,
|
||||
input[type="datetime-local"]:focus,
|
||||
input[type="date"]:focus,
|
||||
input[type="month"]:focus,
|
||||
input[type="time"]:focus,
|
||||
input[type="week"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="email"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="search"]:focus,
|
||||
input[type="tel"]:focus,
|
||||
input[type="color"]:focus,
|
||||
.uneditable-input:focus {
|
||||
border-color: rgba(236,160,73,.8);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),
|
||||
0 0 8px rgba(236,160,73,.6);
|
||||
}
|
||||
|
||||
/* IE7/8 Flexibility */
|
||||
|
||||
.container,
|
||||
.navbar-static-top .container,
|
||||
.navbar-fixed-top .container,
|
||||
.navbar-fixed-bottom .container {
|
||||
width: auto;
|
||||
max-width: 940px;
|
||||
}
|
||||
|
||||
/* Don't widen the layout past 940 */
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.container,
|
||||
.navbar-static-top .container,
|
||||
.navbar-fixed-top .container,
|
||||
.navbar-fixed-bottom .container {
|
||||
width: 940px;
|
||||
}
|
||||
}
|
||||
|
||||
div.comment {
|
||||
background: radial-gradient(
|
||||
50% 8px at top,
|
||||
rgba(0, 0, 0, 0.3) 0%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
background-repeat: no-repeat;
|
||||
box-shadow: 0 -1px 2px -2px white;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
div.comment p:nth-child(2) {
|
||||
color: #666;
|
||||
/* line-height: 15px; */
|
||||
font-size: 0.9em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.comment p:nth-child(1) {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.comment textarea {
|
||||
width: 100%;
|
||||
*width: auto;
|
||||
resize: vertical;
|
||||
*resize: both;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* highlighting source code */
|
||||
|
||||
span.builtin { color: #483d8b; } /* DarkSlateBlue */
|
||||
span.comment { color: #b22222; } /* Firebrick */
|
||||
span.constant { color: #008b8b; } /* DarkCyan */
|
||||
span.function { color: #0000ff; } /* Blue1 */
|
||||
span.keyword { color: #7f007f; } /* Purple */
|
||||
span.string { color: #8b475d; } /* VioletRed4 */
|
||||
span.type { color: #228b22; } /* ForestGreen */
|
||||
span.warning { color: #ff0000; font-weight: bold; } /* Red1 */
|
||||
span.comment span,
|
||||
span.string span { color: inherit; }
|
||||
span.comment span.important.constant,
|
||||
span.string span.important.constant { color: #008b8b; }
|
||||
|
||||
/* old: Equivalent to Output::HTML */
|
||||
|
||||
span.linecomment { color: #b22222; } /* firebrick */
|
||||
span.blockcomment { color: #b22222; } /* firebrick */
|
||||
span.prepro { color: purple; }
|
||||
span.select { font-weight: bold; }
|
||||
span.quote { color: #8b475d; } /* VioletRed4 */
|
||||
span.category_1 { color: teal; }
|
||||
span.category_2 { color: blue; }
|
||||
span.category_3 { color: blue; }
|
||||
|
||||
code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Local Variables: */
|
||||
/* css-indent-offset: 4 */
|
||||
/* End: */
|
||||
@@ -115,6 +115,7 @@ div.toc h2 {
|
||||
|
||||
/* get rid of useless "10 results found" when using indexed search. */
|
||||
div.search p.result { display:none; }
|
||||
label[for="searchlang"], input#searchlang { display: none; }
|
||||
|
||||
form.tiny, form.tiny p {
|
||||
display:inline;
|
||||
@@ -335,7 +336,22 @@ div.month a.local {
|
||||
|
||||
/* highlighting */
|
||||
|
||||
/* Equivalent to Output::HTML */
|
||||
/* highlighting source code */
|
||||
|
||||
span.builtin { color: #483d8b; } /* DarkSlateBlue */
|
||||
span.comment { color: #b22222; } /* Firebrick */
|
||||
span.constant { color: #008b8b; } /* DarkCyan */
|
||||
span.function { color: #0000ff; } /* Blue1 */
|
||||
span.keyword { color: #7f007f; } /* Purple */
|
||||
span.string { color: #8b475d; } /* VioletRed4 */
|
||||
span.type { color: #228b22; } /* ForestGreen */
|
||||
span.warning { color: #ff0000; font-weight: bold; } /* Red1 */
|
||||
span.comment span,
|
||||
span.string span { color: inherit; }
|
||||
span.comment span.important.constant,
|
||||
span.string span.important.constant { color: #008b8b; }
|
||||
|
||||
/* old: Equivalent to Output::HTML */
|
||||
|
||||
span.linecomment { color: green; }
|
||||
span.blockcomment { color: green; }
|
||||
|
||||
384
css/light.css
Normal file
384
css/light.css
Normal file
@@ -0,0 +1,384 @@
|
||||
/* This file is in the public domain. */
|
||||
|
||||
/* Esteban is nice, but bold is not so nice, and on Windows it suffers.
|
||||
@import url(http://fonts.googleapis.com/css?family=Esteban&subset=latin,latin-ext);
|
||||
|
||||
For campaignwiki.org, we need to use the same URL in the config file when
|
||||
calling wkhtmltopdf.
|
||||
|
||||
@import url(https://fonts.googleapis.com/css?family=Noticia+Text:400,400italic,700italic,700&subset=latin,latin-ext); */
|
||||
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text'), local('NoticiaText-Regular)'), url('/fonts/NoticiaText-Regular.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold'), local('NoticiaText-Bold)'), url('/fonts/NoticiaText-Bold.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Noticia Text Italic'), local('NoticiaText-Italic)'), url('/fonts/NoticiaText-Italic.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff');
|
||||
unicode-range: U+0102-0103, U+1EA0-1EF1, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Noticia Text';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Noticia Text Bold Italic'), local('NoticiaText-BoldItalic)'), url('/fonts/NoticiaText-BoldItalic.woff') format('woff');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Symbola';
|
||||
src: local('Symbola'), url('/fonts/Symbola.woff') format('woff');
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Noticia Text", Symbola, serif;
|
||||
font-size: 14pt;
|
||||
color: #000;
|
||||
background-color: #eed;
|
||||
margin:1em 2em;
|
||||
}
|
||||
|
||||
textarea, pre, code, tt {
|
||||
font-family: "Andale Mono", Monaco, "Courier New", Courier, monospace, Symbola;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background-color: white;
|
||||
font-family: Times, serif;
|
||||
font-size:10pt;
|
||||
}
|
||||
}
|
||||
|
||||
/* iPhone */
|
||||
|
||||
@media only screen and (max-device-width: 480px) {
|
||||
img { max-width: 480px !important; }
|
||||
}
|
||||
|
||||
/* iPad */
|
||||
|
||||
@media only screen and (min-device-width: 481px) and (max-device-width: 900px) {
|
||||
body { font-size: 150%; }
|
||||
textarea,input { font-size: 100%; }
|
||||
img { max-width: 550px !important; }
|
||||
}
|
||||
|
||||
/* general */
|
||||
.browse { min-height: 3em; }
|
||||
.header form, .header p { margin: 0; }
|
||||
/* hide the buttons but don't use display:none because of
|
||||
http://stackoverflow.com/questions/5665203/getting-iphone-go-button-to-submit-form */
|
||||
.header input[type="submit"] { position: absolute; visibility: hidden; }
|
||||
.header input { width: 5em; font-size: 80%; }
|
||||
.footer { clear:both; font-size: 90%; }
|
||||
.content input { font-size: 80%; line-height: 125%; }
|
||||
|
||||
/* comments, footer */
|
||||
div.commentshown {
|
||||
padding-bottom: 1ex;
|
||||
padding-left: 2em;
|
||||
border-left: 2px solid black;
|
||||
font-size: smaller;
|
||||
}
|
||||
div.commenthidden { display:none; }
|
||||
div.commentshown { display:block; }
|
||||
/* comment pages with username, homepage, and email subscription */
|
||||
.comment span { display: block; }
|
||||
.comment span label {
|
||||
display: inline-block; width: 10em;
|
||||
}
|
||||
input#mail, input#homepage, input#username {
|
||||
display: inline-block; width: 20em;
|
||||
}
|
||||
|
||||
/* titles */
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
font-size: 150%;
|
||||
padding: 1em 0;
|
||||
}
|
||||
h1 a:link, h1 a:visited {
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
h2 {
|
||||
font-weight: bold;
|
||||
font-size: 130%;
|
||||
padding: 1em 0;
|
||||
clear: both;
|
||||
}
|
||||
@media print {
|
||||
h1 a, h2 a, h3 a, h4 a { font-style: normal; }
|
||||
}
|
||||
|
||||
/* links */
|
||||
a:link {
|
||||
color: #851;
|
||||
background-color: inherit;
|
||||
}
|
||||
a:visited {
|
||||
color: #542;
|
||||
background-color: inherit;
|
||||
}
|
||||
a:active {
|
||||
color:#a41;
|
||||
background-color: inherit;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
font-size: 150%;
|
||||
cursor: pointer;
|
||||
padding: 0.3em 0.5em;
|
||||
text-shadow: 0px -1px 0px #ccc;
|
||||
background-color: #cfa;
|
||||
border: 1px solid #9d8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 1px 3px white inset,
|
||||
0px 1px 3px black;
|
||||
}
|
||||
.button a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
.bar a { padding-right: 1em; }
|
||||
@media print {
|
||||
a, a:link, a:visited {
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
font-weight: normal;
|
||||
}
|
||||
a.edit, div.footer, form, span.gotobar, a.number span { display:none; }
|
||||
a[class="url number"]:after, a[class="inter number"]:after {
|
||||
content:"[" attr(href) "]";
|
||||
}
|
||||
a[class="local number"]:after { content:"[" attr(title) "]"; }
|
||||
img[smiley] { line-height: inherit; }
|
||||
}
|
||||
|
||||
/* edit paragraphs */
|
||||
a.pencil {
|
||||
padding-left: 1ex;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
visible: hidden;
|
||||
transition: visibility 0s 1s, opacity 1s linear;
|
||||
opacity: 0;
|
||||
}
|
||||
*:hover > a.pencil {
|
||||
visible: visible;
|
||||
transition: opacity .5s linear;
|
||||
opacity: 1;
|
||||
}
|
||||
@media print {
|
||||
a.pencil {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
table a.pencil {
|
||||
position: absolute;
|
||||
right: inherit;
|
||||
}
|
||||
|
||||
/* table of contents */
|
||||
.toc {
|
||||
font-size: smaller;
|
||||
border-left: 1em solid #886;
|
||||
}
|
||||
.toc ol {
|
||||
list-style-type: none;
|
||||
padding-left: 1em;
|
||||
}
|
||||
.toc a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* images with links, captions, etc */
|
||||
div.image { display: inline; margin: 1em; font-size: 90%; text-align: center; }
|
||||
.left { float: left; margin-right: 1em; }
|
||||
.right { float: right; margin-left: 1em; }
|
||||
div.right .right { float: none; }
|
||||
div.left .left { float: none; }
|
||||
.caption { padding: 0 1em; }
|
||||
.license { font-size: small; }
|
||||
.aside {
|
||||
font-size: small;
|
||||
width: 30%;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
.aside img.smiley { height: 1em; }
|
||||
.narrow {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
a img { border: 1px solid #333; }
|
||||
.fit img { width: 80%; text-align: center; margin: 2em 8%; }
|
||||
.half img { width: 50%; height: 50%; text-align: center; margin: 2em 8%; }
|
||||
.noborder img { border: none; }
|
||||
.twenty img { max-width: 20em; }
|
||||
img.logo {
|
||||
float: right;
|
||||
clear: right;
|
||||
border-style:none;
|
||||
margin-left: 1em;
|
||||
margin-bottom: 1ex;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
/* fancy bold underline */
|
||||
em.underline { font-weight: bold; }
|
||||
|
||||
/* editing, previewing */
|
||||
textarea { width:100%; }
|
||||
div.edit { padding-right: 1em; }
|
||||
div.diff { padding-left:5%; padding-right:5%; }
|
||||
div.old { background-color:#FFFFAF; }
|
||||
div.new { background-color:#CFFFCF; }
|
||||
/* div.message { background-color:#FEE; } */
|
||||
div.message {
|
||||
background-color: inherit;
|
||||
font-size: smaller;
|
||||
}
|
||||
table.history { border-style:none; }
|
||||
td.history { border-style:none; }
|
||||
span.result { font-size:larger; }
|
||||
span.info { font-size:smaller; font-style:italic; }
|
||||
div.rc hr { display: none; }
|
||||
div.rc li { padding-bottom: 0.5em; }
|
||||
|
||||
/* Tables */
|
||||
table.user {
|
||||
margin: 1em 0;
|
||||
padding: 0 1em;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
div.aside table.user {
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.user td, table.user th {
|
||||
border-style: none;
|
||||
padding:5px 10px;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.user th { font-weight:bold; }
|
||||
table.user td.r { text-align:right; }
|
||||
table.user td.l { text-align:left; }
|
||||
table.user td.c { text-align:center; }
|
||||
table.user td.j { text-align:justify; }
|
||||
table.user td.mark { background-color:yellow; }
|
||||
tr:empty { display: block; height: 0.5em; }
|
||||
@media print {
|
||||
table {
|
||||
font-size: 9pt;
|
||||
margin: 0;
|
||||
}
|
||||
table.user td, table.user th {
|
||||
padding: 0 1ex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calendar */
|
||||
div.month { margin:0; padding:0; font-size:x-small; float:right; }
|
||||
div.content div.month { float:none; }
|
||||
div.year div.month { float:left; font-size:medium; padding:1ex; }
|
||||
div.month pre { margin:0; padding:0 0 0 1ex; }
|
||||
div.month a { text-decoration:none; font: inherit; }
|
||||
div.month span.title a { font: inherit; }
|
||||
/* no difference between a.exact and a.collection */
|
||||
div.month a.local { font-weight: bold; }
|
||||
div.month a.local:link { color: #562; }
|
||||
div.month a.local:visited { color: #542; }
|
||||
div.month a.today { background-color: #faa; }
|
||||
div.month span.title a.local { font-weight: normal; color: #842; }
|
||||
@media print {
|
||||
div.month { display: none; }
|
||||
div.year div.month { display: block; }
|
||||
div.year div.month a { display: inline; }
|
||||
}
|
||||
@@ -197,6 +197,19 @@ hr {
|
||||
div.footer hr {
|
||||
height:4px;
|
||||
margin: 2em 0 1ex 0;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
div.content > div.comment {
|
||||
border-top: none;
|
||||
padding-top: none;
|
||||
border-left: 1ex solid #bbb;
|
||||
padding-left: 1ex;
|
||||
}
|
||||
|
||||
div.wrapper > div.comment {
|
||||
border-top: 2px solid #000;
|
||||
padding-top: 2em;
|
||||
}
|
||||
|
||||
pre {
|
||||
@@ -205,9 +218,13 @@ pre {
|
||||
margin-right: 2em;
|
||||
white-space: pre;
|
||||
overflow:hidden;
|
||||
font-size: smaller;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
div.footer hr {
|
||||
clear:both;
|
||||
}
|
||||
tt, pre, code {
|
||||
font-size: 80%;
|
||||
};
|
||||
|
||||
250
css/oddmuse-2014.css
Normal file
250
css/oddmuse-2014.css
Normal file
@@ -0,0 +1,250 @@
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Basic'), local('GentiumBasic'), url(/fonts/GenBasR.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Gentium Basic Bold'), local('GentiumBasic-Bold'), url(/fonts/GenBasB.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Basic Italic'), local('GentiumBasic-Italic'), url(/fonts/GenBasI.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Basic';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: local('Gentium Basic Bold Italic'), local('GentiumBasic-BoldItalic'), url(/fonts/GenBasBI.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Gentium Plus';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Plus'), local('GentiumPlus'), url(/fonts/GentiumPlus-R.woff) format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Gentium Plus';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: local('Gentium Plus Italic'), local('GentiumPlus-Italic'), url(/fonts/GentiumPlus-I.woff) format('woff');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Symbola';
|
||||
src: local('Symbola'), url('/fonts/Symbola.woff') format('woff') url('/fonts/Symbola.ttf') format('truetype');
|
||||
}
|
||||
|
||||
body {
|
||||
background:#fff;
|
||||
padding:2% 5%;
|
||||
margin:0;
|
||||
font-family: "Gentium Basic", "Gentium Plus", "Symbola", serif;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
div.header h1 {
|
||||
margin-top:2ex;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #d88;
|
||||
}
|
||||
|
||||
div.header h1 a:hover, h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover,
|
||||
a:hover, span.caption a.image:hover {
|
||||
background:#fee;
|
||||
}
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
clear: right;
|
||||
border-style:none;
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
img {
|
||||
padding: 0.5em;
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
a.image:hover {
|
||||
background:inherit;
|
||||
}
|
||||
|
||||
a.image:hover img {
|
||||
background:#fee;
|
||||
}
|
||||
|
||||
/* a.definition soll aussehen wie h2 */
|
||||
h2, p a.definition {
|
||||
display:block;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
/* Such Link im h1 soll nicht auffallen. */
|
||||
h1, h2, h3, h4, h1 a, h1 a:visited, p a.definition {
|
||||
color:#666;
|
||||
font-size: 30pt;
|
||||
font-weight: normal;
|
||||
margin: 4ex 0 1ex 0;
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
|
||||
h3, h4 {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
div.diff {
|
||||
padding: 1em 3em;
|
||||
}
|
||||
div.old {
|
||||
background-color:#FFFFAF;
|
||||
}
|
||||
div.new {
|
||||
background-color:#CFFFCF;
|
||||
}
|
||||
div.old p, div.new p {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
div.refer { padding-left:5%; padding-right:5%; font-size:smaller; }
|
||||
div[class="content refer"] p { margin-top:2em; }
|
||||
div.content div.refer hr { display:none; }
|
||||
div.content div.refer { padding:0; font-size:medium; }
|
||||
div.content div.refer p { margin:0; }
|
||||
div.refer a { display:block; }
|
||||
table.history { border-style:none; }
|
||||
td.history { border-style:none; }
|
||||
|
||||
table.user {
|
||||
border-style: none;
|
||||
margin-left: 3em;
|
||||
}
|
||||
table.user tr td {
|
||||
border-style: none;
|
||||
padding:0.5ex 1ex;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight:bold;
|
||||
}
|
||||
dd {
|
||||
margin-bottom:1ex;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width:100%;
|
||||
height:80%;
|
||||
font-size: 12pt;
|
||||
}
|
||||
textarea#summary { height: 3em; }
|
||||
input {
|
||||
font-size: 12pt;
|
||||
}
|
||||
div.image span.caption {
|
||||
margin: 0 1em;
|
||||
}
|
||||
li img, img.smiley, .noborder img {
|
||||
border:none;
|
||||
padding:0;
|
||||
margin:0;
|
||||
background:#fff;
|
||||
color:#000;
|
||||
}
|
||||
/* Google +1 */
|
||||
a#plus1 img {
|
||||
background-color: #fff;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.header img, div.footer img { border:0; padding:0; margin:0; }
|
||||
/* No goto bar at the bottom. */
|
||||
.footer .gotobar, .footer .edit br { display: none; }
|
||||
|
||||
.left { float:left; }
|
||||
.right { float:right; }
|
||||
div.left .left, div.right .right {
|
||||
float:none;
|
||||
}
|
||||
.center { text-align:center; }
|
||||
|
||||
span.author {
|
||||
color: #501;
|
||||
}
|
||||
span.bar a {
|
||||
padding-right:1ex;
|
||||
}
|
||||
|
||||
.rc .author {
|
||||
color: #655;
|
||||
}
|
||||
|
||||
.rc strong {
|
||||
font-weight: normal;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.rc li {
|
||||
position:relative;
|
||||
padding: 1ex 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border:none;
|
||||
color:black;
|
||||
background-color:#000;
|
||||
height:2px;
|
||||
margin-top:2ex;
|
||||
}
|
||||
|
||||
div.footer hr {
|
||||
height:4px;
|
||||
margin: 2em 0 1ex 0;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
div.content > div.comment {
|
||||
border-top: none;
|
||||
padding-top: none;
|
||||
border-left: 1ex solid #bbb;
|
||||
padding-left: 1ex;
|
||||
}
|
||||
|
||||
div.wrapper > div.comment {
|
||||
border-top: 2px solid #000;
|
||||
padding-top: 2em;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0.5em;
|
||||
margin-left: 1em;
|
||||
margin-right: 2em;
|
||||
white-space: pre;
|
||||
overflow:hidden;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
tt, pre, code {
|
||||
font-size: 80%;
|
||||
};
|
||||
1
description
Normal file
1
description
Normal file
@@ -0,0 +1 @@
|
||||
Oddmuse
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/aawrapperdiv.pl">aawrapperdiv.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/WrapperDiv_Module">WrapperDiv Module</a></p>';
|
||||
AddModuleDescription('aawrapperdiv.pl', 'WrapperDiv Module');
|
||||
|
||||
|
||||
*OldGetHeader = *GetHeader;
|
||||
|
||||
36
modules/accesskeys.pl
Normal file
36
modules/accesskeys.pl
Normal file
@@ -0,0 +1,36 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('accesskeys.pl', 'Links With AccessKeys Extension');
|
||||
|
||||
push(@MyRules, \&LinksWithAccessKeys);
|
||||
sub LinksWithAccessKeys {
|
||||
if (m/\G(\[\[$FreeLinkPattern\{(.)\}\]\])/cog) {
|
||||
my ($id, $key) = ($2, $3);
|
||||
Dirty($1);
|
||||
$id = FreeToNormal($id);
|
||||
my ($class, $resolved, $title, $exists) = ResolveId($id);
|
||||
my $text = NormalToFree($id);
|
||||
if ($resolved) { # anchors don't exist as pages, therefore do not use $exists
|
||||
print ScriptLink(UrlEncode($resolved), $text, $class, undef, $title, $key);
|
||||
} else {
|
||||
print "[[" . QuoteHtml($text) . GetEditLink($id, '?') . "]]";
|
||||
}
|
||||
return ''; # this is a dirty rule that depends the definition of other pages
|
||||
}
|
||||
return undef; # the rule didn't match
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/admin.pl">admin.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Admin_Power_Extension">Admin Power Extension</a></p>';
|
||||
AddModuleDescription('admin.pl', 'Admin Power Extension');
|
||||
|
||||
$Action{delete} = \&AdminPowerDelete;
|
||||
$Action{rename} = \&AdminPowerRename;
|
||||
@@ -62,13 +62,13 @@ sub AdminPowerRename {
|
||||
# Regenerate index on next request -- remove this before errors can occur!
|
||||
unlink($IndexFile);
|
||||
# page file
|
||||
CreatePageDir($PageDir, $new); # It might not exist yet
|
||||
CreateDir($PageDir); # It might not exist yet
|
||||
rename($fname, $newfname)
|
||||
or ReportError(Tss('Cannot rename %1 to %2', $fname, $newfname) . ": $!", '500 INTERNAL SERVER ERROR');
|
||||
# keep directory
|
||||
my $kdir = GetKeepDir($id);
|
||||
my $newkdir = GetKeepDir($new);
|
||||
CreatePageDir($KeepDir, $new); # It might not exist yet (only the parent directory!)
|
||||
CreateDir($KeepDir); # It might not exist yet (only the parent directory!)
|
||||
rename($kdir, $newkdir)
|
||||
or ReportError(Tss('Cannot rename %1 to %2', $kdir, $newkdir) . ": $!", '500 INTERNAL SERVER ERROR')
|
||||
if -d $kdir;
|
||||
@@ -76,7 +76,7 @@ sub AdminPowerRename {
|
||||
if (defined(&GetRefererFile)) {
|
||||
my $rdir = GetRefererFile($id);
|
||||
my $newrdir = GetRefererFile($new);
|
||||
CreatePageDir($RefererDir, $new); # It might not exist yet
|
||||
CreateDir($RefererDir); # It might not exist yet
|
||||
rename($rdir, $newrdir)
|
||||
or ReportError(Tss('Cannot rename %1 to %2', $rdir, $newrdir) . ": $!", '500 INTERNAL SERVER ERROR')
|
||||
if -d $rdir;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/adsense.pl">adsense.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/AdSense_Module">AdSense Module</a></p>';
|
||||
AddModuleDescription('adsense.pl', 'AdSense Module');
|
||||
|
||||
use vars qw($AdSensePageName $AdSensePlace);
|
||||
|
||||
|
||||
35
modules/advanced-uploads.pl
Normal file
35
modules/advanced-uploads.pl
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
|
||||
# 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('advanced-uploads.pl', 'Advanced File Upload Extension');
|
||||
|
||||
$HtmlHeaders .= '<script type="text/javascript" src="/js/uploader.js"></script>';
|
||||
|
||||
*AdvancedUploadsOldGetTextArea = *GetTextArea;
|
||||
*GetTextArea = *AdvancedUploadsNewGetTextArea;
|
||||
|
||||
sub AdvancedUploadsNewGetTextArea {
|
||||
my ($name, $text, $rows) = @_;
|
||||
return AdvancedUploadsOldGetTextArea(@_) . $q->br() . ($name =~ 'text|aftertext' ? GetUploadForm() : '');
|
||||
}
|
||||
|
||||
sub GetUploadForm {
|
||||
return $q->span({-class=>'upload'}, $q->label({-for=>'fileToUpload'}, T('Attach file:')),
|
||||
$q->filefield(-name=>'fileToUpload', -id=>'fileToUpload', -multiple=>'multiple', -onChange=>'fileSelected()', -size=>20),
|
||||
$q->span({-id=>'fileSize'}, ''),
|
||||
$q->button(-name=>'uploadButton', -value=>T('Upload'), -onClick=>'uploadFile()'),
|
||||
$q->span({-id=>'progressNumber'}));
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/age.pl">age.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Age_Indication_Extension">Age Indication Extension</a></p>';
|
||||
AddModuleDescription('age.pl', 'Age Indication Extension');
|
||||
|
||||
use vars qw(%AgeEffect $AgeParameter);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/aggregate.pl">aggregate.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Front_Page_Extension">Front Page Extension</a></p>';
|
||||
AddModuleDescription('aggregate.pl', 'Front Page Extension');
|
||||
|
||||
push(@MyRules, \&AggregateRule);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/all.pl">all.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/All_Action">All Action</a></p>';
|
||||
AddModuleDescription('all.pl', 'All Action');
|
||||
|
||||
$Action{all} = \&DoPrintAllPages;
|
||||
|
||||
@@ -28,7 +28,7 @@ sub DoPrintAllPages {
|
||||
print GetHeader('', T('Complete Content'))
|
||||
. $q->p(Ts('The main page is %s.', $q->a({-href=>'#' . $HomePage}, $HomePage)));
|
||||
print $q->p($q->b(Ts('(for %s)', GetParam('lang', 0)))) if GetParam('lang', 0);
|
||||
PrintAllPages(0, 0, undef, AllPagesList());
|
||||
PrintAllPages(0, 0, undef, undef, AllPagesList());
|
||||
PrintFooter();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/anchors.pl">anchors.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Local_Anchor_Extension">Local Anchor Extension</a></p>';
|
||||
AddModuleDescription('anchors.pl', 'Local Anchor Extension');
|
||||
|
||||
push(@MyRules, \&AnchorsRule);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/antispam.pl">antispam.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Antispam_Module">Antispam Module</a></p>';
|
||||
AddModuleDescription('antispam.pl', 'Antispam Module');
|
||||
|
||||
use vars qw($DoMaskEmail $CreateMailtoLinks);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/archive.pl">archive.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Archive_Extension">Archive Extension</a></p>';
|
||||
AddModuleDescription('archive.pl', 'Archive Extension');
|
||||
|
||||
*OldArchiveGetHeader = *GetHeader;
|
||||
*GetHeader = *NewArchiveGetHeader;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/askpage.pl">askpage.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Ask_Page_Extension">Ask Page Extension</a></p>';
|
||||
AddModuleDescription('askpage.pl', 'Ask Page Extension');
|
||||
|
||||
use Fcntl qw(:DEFAULT :flock);
|
||||
|
||||
@@ -39,13 +39,12 @@ sub IncrementInFile {
|
||||
*DoPost=*NewAskPageDoPost;
|
||||
sub NewAskPageDoPost {
|
||||
my $id = FreeToNormal(shift);
|
||||
if ($id eq $AskPage and not GetParam('text', undef)) {
|
||||
my $currentId = IncrementInFile("$DataDir/curquestion");
|
||||
if ($id eq $AskPage and not GetParam('text', undef)) { # comment, not a regular edit
|
||||
my $currentQuestion = IncrementInFile("$DataDir/curquestion");
|
||||
$currentQuestion =~ s/[\s\n]//g;
|
||||
return OldAskPageDoPost($QuestionPage . $currentQuestion, @_);
|
||||
} else {
|
||||
return OldAskPageDoPost($id, @_);
|
||||
return OldAskPageDoPost($QuestionPage . $currentQuestion, @_); # hack page name
|
||||
}
|
||||
OldAskPageDoPost($id, @_); # keep original functionality for regular edits
|
||||
}
|
||||
|
||||
*OldAskPageGetCommentForm=*GetCommentForm;
|
||||
@@ -53,7 +52,7 @@ sub NewAskPageDoPost {
|
||||
sub NewAskPageGetCommentForm {
|
||||
my ($id, $rev, $comment) = @_;
|
||||
$NewComment = $NewQuestion if $id eq $AskPage;
|
||||
return OldAskPageGetCommentForm(@_);
|
||||
OldAskPageGetCommentForm(@_);
|
||||
}
|
||||
|
||||
*OldAskPageJournalSort=*JournalSort;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2004, 2006, 2008 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2004, 2006, 2008, 2014 Alex Schroeder <alex@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
|
||||
@@ -17,7 +17,7 @@ use XML::Atom::Entry;
|
||||
use XML::Atom::Link;
|
||||
use XML::Atom::Person;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/atom.pl">atom.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Atom_Extension">Atom Extension</a></p>';
|
||||
AddModuleDescription('atom.pl', 'Atom Extension');
|
||||
|
||||
push(@MyInitVariables, \&AtomInit);
|
||||
|
||||
@@ -140,11 +140,11 @@ sub DoAtomSave {
|
||||
my $title = $entry->title();
|
||||
my $author = $entry->author();
|
||||
SetParam('username', $author->name) if $author; # Used in Save()
|
||||
my $id = FreeToNormal($title) if ValidIdOrDie($title);
|
||||
my $id = FreeToNormal($title);
|
||||
UserCanEditOrDie($id);
|
||||
$oldid = $id unless $oldid;
|
||||
ValidIdOrDie($oldid);
|
||||
my $summary = $entry->summary();
|
||||
ReportError(Ts('Editing not allowed for %s.', $id), '403 FORBIDDEN') unless UserCanEdit($id, 1);
|
||||
# Lock before getting old page to prevent races
|
||||
RequestLockOrError(); # fatal
|
||||
OpenPage($oldid);
|
||||
|
||||
@@ -25,7 +25,7 @@ directory of your Oddmuse Wiki.
|
||||
=cut
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/autolock.pl">autolock.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Autolock_Extension">Autolock Extension</a></p>';
|
||||
AddModuleDescription('autolock.pl', 'Autolock Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
# ie: http://search.cpan.org/CPAN/authors/id/C/CH/CHAMAS/MLDBM-2.01.tar.gz
|
||||
|
||||
use MLDBM qw( DB_File Storable );
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/backlinkage.pl">backlinkage.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Inline_Backlinks">Inline Backlinks</a></p>';
|
||||
AddModuleDescription('backlinkage.pl', 'Inline Backlinks');
|
||||
|
||||
my $debug=1; # Set Text Output Verbosity when compiling
|
||||
my $backfile = $DataDir . '/backlinks.db'; # Where data lives
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# For user doc, see:
|
||||
# http://www.oddmuse.org/cgi-bin/oddmuse/Backlinks_Extension
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/backlinks.pl">backlinks.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Backlinks_Extension">Backlinks Extension</a></p>';
|
||||
AddModuleDescription('backlinks.pl', 'Backlinks Extension');
|
||||
|
||||
*OldGetSearchLink = *GetSearchLink;
|
||||
*GetSearchLink = *NewGetSearchLink;
|
||||
|
||||
@@ -73,7 +73,7 @@ wiki is locked and migration is started.
|
||||
|
||||
=cut
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/balanced-page-directories.pl">balanced-page-directories.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Balanced_Page_Directories_Extension">Balanced Page Directories Extension</a>';
|
||||
AddModuleDescription('balanced-page-directories.pl', 'Balanced Page Directories Extension');
|
||||
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
use File::Find qw(finddepth);
|
||||
|
||||
@@ -25,7 +25,7 @@ the IP or hostname will be added to the C<BannedHosts> page for you.
|
||||
|
||||
=cut
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/ban-contributors.pl">ban-contributors.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Ban_Contributors_Extension">Ban Contributors Extension</a></p>';
|
||||
AddModuleDescription('ban-contributors.pl', 'Ban Contributors Extension');
|
||||
|
||||
push(@MyAdminCode, \&BanMenu);
|
||||
|
||||
@@ -150,7 +150,7 @@ sub NewBanContributorsWriteRcLog {
|
||||
$q->submit(T('Ban!'))),
|
||||
$q->end_form();
|
||||
};
|
||||
print $q->p(T("Consider banning the hostname or IP number as well: "),
|
||||
print $q->p(T("Consider banning the IP number as well: "),
|
||||
ScriptLink('action=ban;id=' . UrlEncode($id), T('Ban contributors')));
|
||||
};
|
||||
return OldBanContributorsWriteRcLog(@_);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# This file must load before logbannedcontent.pl such that quick
|
||||
# editors will be logged.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/ban-quick-editors.pl">ban-quick-editors.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Banning_Quick_Editors">Banning Quick Editors</a></p>';
|
||||
AddModuleDescription('ban-quick-editors.pl', 'Banning Quick Editors');
|
||||
|
||||
*BanQuickOldUserIsBanned = *UserIsBanned;
|
||||
*UserIsBanned = *BanQuickNewUserIsBanned;
|
||||
@@ -25,7 +25,7 @@ sub BanQuickNewUserIsBanned {
|
||||
if (not $rule
|
||||
and $SurgeProtection # need surge protection
|
||||
and GetParam('title')) {
|
||||
my $name = GetParam('username', GetRemoteAddress());
|
||||
my $name = GetParam('username', GetRemoteHost());
|
||||
my @entries = @{$RecentVisitors{$name}};
|
||||
# $entry[0] is $Now after AddRecentVisitor
|
||||
my $ts = $entries[1];
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/banned-regexps.pl">banned-regexps.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Banning_Regular_Expressions">Banning Regular Expressions</a></p>';
|
||||
AddModuleDescription('banned-regexps.pl', 'Banning Regular Expressions');
|
||||
|
||||
=h1 Compatibility
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/bbcode.pl">bbcode.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/bbCode_Extension">bbCode Extension</a></p>';
|
||||
AddModuleDescription('bbcode.pl', 'bbCode Extension');
|
||||
|
||||
push(@MyRules, \&bbCodeRule);
|
||||
|
||||
@@ -122,15 +122,15 @@ sub bbCodeRule {
|
||||
# smiley
|
||||
elsif (/\G(:-?[()])/cg) {
|
||||
if (substr($1,-1) eq ')') {
|
||||
# '☺' 0009786 00263a WHITE SMILING FACE, So, 0, ON, N,
|
||||
return '☺'; }
|
||||
# 😊 1F60A SMILING FACE WITH SMILING EYES
|
||||
return '😊'; }
|
||||
else {
|
||||
# '☹' 0009785 002639 WHITE FROWNING FACE, So, 0, ON, N,
|
||||
return '☹'; }}
|
||||
# 😟 1F61F WORRIED FACE
|
||||
return '😟'; }}
|
||||
elsif (/\G:(?:smile|happy):/cg) {
|
||||
return '☺'; }
|
||||
return '😊'; }
|
||||
elsif (/\G:(?:sad|frown):/cg) {
|
||||
return '☹'; }
|
||||
return '😟'; }
|
||||
# no match
|
||||
return undef;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/beautify.pl">beautify.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Source_Code_Beautification_Extension">Source Code Beautification Extension</a></p>';
|
||||
AddModuleDescription('beautify.pl', 'Source Code Beautification Extension');
|
||||
|
||||
use Beautifier::Core;
|
||||
use Output::HTML;
|
||||
|
||||
@@ -15,14 +15,18 @@
|
||||
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/big-brother.pl">big-brother.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Big_Brother_Extension">Big Brother Extension</a></p>';
|
||||
AddModuleDescription('big-brother.pl', 'Big Brother Extension');
|
||||
|
||||
use vars qw($VisitorTime);
|
||||
use vars qw($VisitorTime @BigBrotherSecretParameters);
|
||||
|
||||
my $US = "\x1f";
|
||||
|
||||
$VisitorTime = 7200; # keep visitor data arround for 2 hours.
|
||||
|
||||
# normal password parameter from wiki.pl
|
||||
# password parameters from login.pl
|
||||
@BigBrotherSecretParameters = qw(pwd pwd1 pwd2 oldpwd);
|
||||
|
||||
push(@MyAdminCode, \&BigBrotherVisitors);
|
||||
|
||||
sub BigBrotherVisitors {
|
||||
@@ -47,6 +51,13 @@ sub AddRecentVisitor {
|
||||
$ts++ while $entries{$ts};
|
||||
my $action = GetParam('action', 'browse');
|
||||
my $id = GetId(); # script/p/q -> q
|
||||
my %params = map { $_ => 1 } $q->param;
|
||||
for $bad (@BigBrotherSecretParameters) {
|
||||
delete $params{$bad};
|
||||
}
|
||||
my $url = ScriptUrl(join(';', "action=$action;id=" . UrlEncode($id),
|
||||
map { $_ . '=' . UrlEncode(GetParam($_)) }
|
||||
keys %params));
|
||||
my $url = $q->url(-path_info=>1,-query=>1);
|
||||
my $download = GetParam('action', 'browse') eq 'download'
|
||||
|| GetParam('download', 0)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/blockquote.pl">blockquote.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Comments_on_Text_Formatting_Rules">Comments on Text Formatting Rules</a></p>';
|
||||
AddModuleDescription('blockquote.pl', 'Comments on Text Formatting Rules');
|
||||
|
||||
push(@MyRules, \&BlockQuoteRule);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# is useless. This extension will not work under Windows/IIS unless cal
|
||||
# is installed.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/cal3.pl">cal3.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Cal3_Extension">Cal3 Extension</a></p>';
|
||||
AddModuleDescription('cal3.pl', 'Cal3 Extension');
|
||||
|
||||
*OldCalendarGetHeader = *GetHeader;
|
||||
*GetHeader = *NewCalendarGetHeader;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/calendar.pl">calendar.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Calendar_Extension">Calendar Extension</a></p>';
|
||||
AddModuleDescription('calendar.pl', 'Calendar Extension');
|
||||
|
||||
use vars qw($CalendarOnEveryPage $CalAsTable $CalStartMonday);
|
||||
|
||||
@@ -104,7 +104,7 @@ sub DoCollect {
|
||||
# Now save information required for saving the cache of the current page.
|
||||
local (%Page, $OpenPageName);
|
||||
print $q->start_div({-class=>'content journal collection'});
|
||||
PrintAllPages(1, 1, undef, @pages);
|
||||
PrintAllPages(1, 1, undef, undef, @pages);
|
||||
print $q->end_div();
|
||||
}
|
||||
$CollectingJournal = 0;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/canonical.pl">canonical.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Canonical_Names">Canonical Names</a></p>';
|
||||
AddModuleDescription('canonical.pl', 'Canonical Names');
|
||||
|
||||
use utf8;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/checkbox.pl">checkbox.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Checklist_Extension">Checklist Extension</a></p>';
|
||||
AddModuleDescription('checkbox.pl', 'Checklist Extension');
|
||||
|
||||
# [[ : To do]]
|
||||
# [[X: Done]]
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/clustermap.pl">clustermap.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/ClusterMap_Module">ClusterMap Module</a></p>';
|
||||
AddModuleDescription('clustermap.pl', 'ClusterMap Module');
|
||||
|
||||
use vars qw($ClusterMapPage $ClusterMapTOC $FilterUnclusteredRegExp @ClusterMapAdminPages);
|
||||
|
||||
@@ -40,8 +40,8 @@ $PrintTOCAnchor = 0;
|
||||
|
||||
%ClusterMap = ();
|
||||
|
||||
*OldDoRc = *DoRc;
|
||||
*DoRc = *ClusterMapDoRc;
|
||||
*OldPrintRcHtml = *PrintRcHtml;
|
||||
*PrintRcHtml = *ClusterMapPrintRcHtml;
|
||||
|
||||
push(@MyAdminCode, \&ClusterMapAdminRule);
|
||||
|
||||
@@ -178,7 +178,7 @@ sub CreateClusterMap {
|
||||
}
|
||||
}
|
||||
|
||||
sub ClusterMapDoRc {
|
||||
sub ClusterMapPrintRcHtml {
|
||||
my ( @options ) = @_;
|
||||
my $page = "";
|
||||
my $cluster = GetParam(rcclusteronly);
|
||||
@@ -195,7 +195,7 @@ sub ClusterMapDoRc {
|
||||
print "</ul>";
|
||||
}
|
||||
|
||||
OldDoRc(@options);
|
||||
OldPrintRcHtml(@options);
|
||||
}
|
||||
|
||||
sub PrintUnclusteredMap {
|
||||
|
||||
55
modules/comment-div-wrapper.pl
Normal file
55
modules/comment-div-wrapper.pl
Normal file
@@ -0,0 +1,55 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('comment-div-wrapper.pl', 'Comment Div Wrapper Extension');
|
||||
|
||||
my $CommentDiv = 0;
|
||||
push(@MyRules, \&CommentDivWrapper);
|
||||
$RuleOrder{\&CommentDivWrapper} = -50;
|
||||
|
||||
sub CommentDivWrapper {
|
||||
if (substr($OpenPageName, 0, length($CommentsPrefix)) eq $CommentsPrefix) {
|
||||
if (pos == 0 and not $CommentDiv) {
|
||||
$CommentDiv = 1;
|
||||
return $q->start_div({-class=>'userComment'});
|
||||
}
|
||||
}
|
||||
if ($OpenPageName =~ /$CommentsPattern/o) {
|
||||
if ($bol and m/\G(\s*\n)*----+[ \t]*\n?/cg) {
|
||||
my $html = CloseHtmlEnvironments()
|
||||
. ($CommentDiv++ > 0 ? $q->end_div() : $q->h2({-class=>'commentsHeading'}, T('Comments:'))) . $q->start_div({-class=>'userComment'})
|
||||
. AddHtmlEnvironment('p');
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
# close final div
|
||||
*OldCommentDivApplyRules = *ApplyRules;
|
||||
*ApplyRules = *NewCommentDivApplyRules;
|
||||
|
||||
sub NewCommentDivApplyRules {
|
||||
my ($blocks, $flags) = OldCommentDivApplyRules(@_);
|
||||
if ($CommentDiv) {
|
||||
print $q->end_div();
|
||||
$blocks .= $FS . $q->end_div();
|
||||
$flags .= $FS . 0;
|
||||
$CommentDiv = 0;
|
||||
}
|
||||
return ($blocks, $flags);
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/commentcount.pl">commentcount.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Comment_Count_Extension">Comment Count Extension</a></p>';
|
||||
AddModuleDescription('commentcount.pl', 'Comment Count Extension');
|
||||
|
||||
*OldCommentcountAddComment = *AddComment;
|
||||
*AddComment = *NewCommentcountAddComment;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/compilation.pl">compilation.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Compilation_Extension">Compilation Extension</a></p>';
|
||||
AddModuleDescription('compilation.pl', 'Compilation Extension');
|
||||
|
||||
$Action{compilation} = \&DoCompilation;
|
||||
|
||||
@@ -49,7 +49,7 @@ sub PrintCompilation {
|
||||
local %Page;
|
||||
local $OpenPageName='';
|
||||
print '<div class="compilation">';
|
||||
PrintAllPages(1, 1, undef, @pages);
|
||||
PrintAllPages(1, 1, undef, undef, @pages);
|
||||
print '</div>';
|
||||
}
|
||||
return @pages;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/config.pl">config.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Plans">Plans</a></p>';
|
||||
AddModuleDescription('config.pl', 'Plans');
|
||||
|
||||
$Action{config} = \&DoConfig;
|
||||
$Action{clone} = \&DoClone;
|
||||
@@ -37,7 +37,7 @@ sub DoConfig {
|
||||
$SurgeProtection $SurgeProtectionTime $SurgeProtectionViews
|
||||
$DeletedPage $RCName @RcDays $RcDefault $KeepDays
|
||||
$KeepMajor $SummaryHours $SummaryDefaultLength $ShowEdits
|
||||
$UseLookup $RecentTop $RecentLink $PageCluster
|
||||
$RecentTop $RecentLink $PageCluster
|
||||
$InterWikiMoniker $SiteDescription $RssImageUrl $RssRights
|
||||
$RssExclude $RssCacheHours $RssStyleSheet $UploadAllowed
|
||||
@UploadTypes $EmbedWiki $FooterNote $EditNote $TopLinkBar
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/context.pl">context.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Calendar_Extension">Calendar Extension</a></p>';
|
||||
AddModuleDescription('context.pl', 'Calendar Extension');
|
||||
|
||||
push (@MyInitVariables, \&ContextMenuItem);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#
|
||||
# Of course, you can customize this to store more information
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/creationdate.pl">creationdate.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/CreationDate_Module">CreationDate Module</a></p>';
|
||||
AddModuleDescription('creationdate.pl', 'CreationDate Module');
|
||||
|
||||
*CreationDateOldOpenPage = *OpenPage;
|
||||
*OpenPage = CreationDateOpenPage;
|
||||
|
||||
@@ -14,7 +14,7 @@ directory for your Oddmuse Wiki.
|
||||
=cut
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/creole.pl">creole.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Creole_Markup_Extension">Creole Markup Extension</a></p>';
|
||||
AddModuleDescription('creole.pl', 'Creole Markup Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
|
||||
@@ -242,6 +242,7 @@ sub CreoleRule {
|
||||
-class=> 'image outside'},
|
||||
$q->img({-src=> UnquoteHtml($1),
|
||||
-alt=> UnquoteHtml($3),
|
||||
-title=> UnquoteHtml($3),
|
||||
-class=> 'url outside'})));
|
||||
}
|
||||
# image link: [[link|{{pic}}]] and [[link|{{pic|text}}]]
|
||||
@@ -252,6 +253,7 @@ sub CreoleRule {
|
||||
ScriptLink(UrlEncode(FreeToNormal($2)),
|
||||
$q->img({-src=> GetDownloadLink(FreeToNormal($3), 2),
|
||||
-alt=> UnquoteHtml($text),
|
||||
-title=> UnquoteHtml($text),
|
||||
-class=> 'upload'}), 'image')), $text);
|
||||
}
|
||||
# image link: [[link|{{url}}]] and [[link|{{url|text}}]]
|
||||
@@ -262,6 +264,7 @@ sub CreoleRule {
|
||||
ScriptLink(UrlEncode(FreeToNormal($2)),
|
||||
$q->img({-src=> UnquoteHtml($3),
|
||||
-alt=> UnquoteHtml($text),
|
||||
-title=> UnquoteHtml($text),
|
||||
-class=> 'url outside'}), 'image')), $text);
|
||||
}
|
||||
# image link: [[url|{{pic}}]] and [[url|{{pic|text}}]]
|
||||
@@ -272,6 +275,7 @@ sub CreoleRule {
|
||||
$q->a({-href=> UnquoteHtml($2), -class=> 'image outside'},
|
||||
$q->img({-src=> GetDownloadLink(FreeToNormal($3), 2),
|
||||
-alt=> UnquoteHtml($text),
|
||||
-title=> UnquoteHtml($text),
|
||||
-class=> 'upload'}))), $text);
|
||||
}
|
||||
# image link: [[url|{{url}}]] and [[url|{{url|text}}]]
|
||||
@@ -281,6 +285,7 @@ sub CreoleRule {
|
||||
$q->a({-href=> UnquoteHtml($1), -class=> 'image outside'},
|
||||
$q->img({-src=> UnquoteHtml($2),
|
||||
-alt=> UnquoteHtml($4),
|
||||
-title=> UnquoteHtml($4),
|
||||
-class=> 'url outside'})));
|
||||
}
|
||||
# link: [[url]] and [[url|text]]
|
||||
@@ -456,21 +461,16 @@ sub CreoleListAndNewLineRule {
|
||||
my $is_in_list_item = InElement('li');
|
||||
|
||||
# # numbered list
|
||||
if (($bol and m/\G[ \t]*(#)[ \t]*/cg) or
|
||||
($is_in_list_item and m/\G[ \t]*\n+[ \t]*(#+)[ \t]*/cg)) {
|
||||
# * bullet list (nestable; needs space when nested to disambiguate from bold)
|
||||
if (($bol and m/\G[ \t]*([#*])[ \t]*/cg) or
|
||||
($is_in_list_item and m/\G[ \t]*\n+[ \t]*(#+)[ \t]*/cg) or
|
||||
($is_in_list_item and m/\G[ \t]*\n+[ \t]*(\*+)[ \t]+/cg)) {
|
||||
# Note: the first line of this return statement is --not-- equivalent to:
|
||||
# "return CloseHtmlEnvironmentUntil('li')", as that line does not permit
|
||||
# modules overriding the CloseHtmlEnvironments() function to "have a say."
|
||||
return ($is_in_list_item ? CloseHtmlEnvironmentUntil('li') : CloseHtmlEnvironments())
|
||||
.OpenHtmlEnvironment('ol', length($1))
|
||||
.AddHtmlEnvironment ('li');
|
||||
}
|
||||
# * bullet list (nestable; needs space when nested to disambiguate from bold)
|
||||
elsif (($bol and m/\G[ \t]*(\*)[ \t]*/cg) or
|
||||
($is_in_list_item and m/\G[ \t]*\n+[ \t]*(\*+)[ \t]+/cg)) {
|
||||
return ($is_in_list_item ? CloseHtmlEnvironmentUntil('li') : CloseHtmlEnvironments())
|
||||
.OpenHtmlEnvironment('ul', length($1))
|
||||
.AddHtmlEnvironment ('li');
|
||||
.OpenHtmlEnvironment(substr($1, 0, 1) eq '#' ? 'ol' : 'ul', length($1), '', 'ol|ul')
|
||||
.AddHtmlEnvironment('li');
|
||||
}
|
||||
# - bullet list (not nestable; always needs space)
|
||||
elsif ($CreoleDashStyleUnorderedLists and (
|
||||
|
||||
@@ -22,7 +22,7 @@ creoleaddition is simply installable; simply:
|
||||
=cut
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/creoleaddition.pl">creoleaddition.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Creole_Addition_Markup_Extension">Creole Addition Markup Extension</a></p>';
|
||||
AddModuleDescription('creoleaddition.pl', 'Creole Addition Markup Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ crossbar is easily installable; move this file into the B<wiki/modules/>
|
||||
directory for your Oddmuse Wiki.
|
||||
|
||||
=cut
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/crossbar.pl">crossbar.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Crossbar_Extension">Crossbar Extension</a></p>';
|
||||
AddModuleDescription('crossbar.pl', 'Crossbar Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
use vars qw($CrossbarPageName
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/crumbs.pl">crumbs.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/List_Parent_Pages_Extension">List Parent Pages Extension</a></p>';
|
||||
AddModuleDescription('crumbs.pl', 'List Parent Pages Extension');
|
||||
|
||||
push(@MyRules, \&CrumbsRule);
|
||||
$RuleOrder{\&CrumbsRule} = -10; # run before default rules!
|
||||
|
||||
@@ -15,7 +15,7 @@ automatically.
|
||||
|
||||
=cut
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/css-install.pl">css-install.pl</a></p>';
|
||||
AddModuleDescription('css-install.pl');
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/csv.pl">csv.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Comments_on_Long_Table_Markup_Extension">Comments on Long Table Markup Extension</a></p>';
|
||||
AddModuleDescription('csv.pl', 'Comments on Long Table Markup Extension');
|
||||
|
||||
push(@MyRules, \&CsvRule);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/dates.pl">dates.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Dates_Extension">Dates Extension</a></p>';
|
||||
AddModuleDescription('dates.pl', 'Dates Extension');
|
||||
|
||||
push(@MyAdminCode, \&DatesMenu);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('debug.pl');
|
||||
|
||||
@Debugging = (\&DebugInterLinks);
|
||||
|
||||
sub DebugInterLinks {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/delete-all.pl">delete-all.pl</a></p>';
|
||||
AddModuleDescription('delete-all.pl');
|
||||
|
||||
use vars qw($DeletedAge);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/despam.pl">despam.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Despam_Extension">Despam Extension</a></p>';
|
||||
AddModuleDescription('despam.pl', 'Despam Extension');
|
||||
|
||||
push(@MyAdminCode, \&DespamMenu);
|
||||
|
||||
|
||||
84
modules/diff.pl
Normal file
84
modules/diff.pl
Normal file
@@ -0,0 +1,84 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('diff.pl', 'Diff Action Extension');
|
||||
|
||||
push(@MyRules, \&DiffActionRule);
|
||||
$Action{pagediff} = \&DoDiffAction;
|
||||
|
||||
sub DiffActionRule {
|
||||
return PrintDiffActionChooser($3) if (m/\G(<diff( (.*))>)/cgi);
|
||||
return undef; # the rule didn't match
|
||||
}
|
||||
|
||||
sub DoDiffAction {
|
||||
print GetHeader('', T('Page diff'), '');
|
||||
my $page1 = GetParam('page1');
|
||||
my $page2 = GetParam('page2');
|
||||
my $pattern = GetParam('pattern');
|
||||
$pattern ||= '.*';
|
||||
print PrintDiffActionChooser($pattern);
|
||||
ValidIdOrDie($page1);
|
||||
ValidIdOrDie($page2);
|
||||
my $diff = DoUnifiedDiff("1\n \n" . GetPageContent($page1), "2\n \n" . GetPageContent($page2)); # add extra lines, otherwise diff between identical files will print nothing # TODO fix this, otherwise one day this will fail...
|
||||
$diff = QuoteHtml($diff);
|
||||
$diff =~ tr/\r//d; # TODO is this required? # probably not
|
||||
for (split /\n/, $diff) {
|
||||
s/(^.)//;
|
||||
my $type = $1;
|
||||
if ($type eq '+') {
|
||||
print '<span class="diffactionnew">' . $type;
|
||||
} elsif ($type eq '-') {
|
||||
print '<span class="diffactionold">' . $type;
|
||||
}
|
||||
ApplyRules($_);
|
||||
print '</span>' if $type =~ /[+-]/;
|
||||
print '<br/>';
|
||||
}
|
||||
PrintFooter();
|
||||
}
|
||||
|
||||
sub PrintDiffActionChooser {
|
||||
my $pattern = shift;
|
||||
$pattern ||= '.*';
|
||||
my @chosenPages = ();
|
||||
for (@IndexList) {
|
||||
push @chosenPages, $_ if m/$pattern/;
|
||||
}
|
||||
return GetFormStart(undef, 'get', 'pagediff')
|
||||
. GetHiddenValue('action', 'pagediff')
|
||||
. GetHiddenValue('pattern', $pattern)
|
||||
. $q->popup_menu(-name=>'page1', -values=>\@chosenPages) . ' '
|
||||
. $q->popup_menu(-name=>'page2', -values=>\@chosenPages) . ' '
|
||||
. $q->submit(-name=>'', -value=>T('Diff'))
|
||||
. $q->end_form();
|
||||
}
|
||||
|
||||
sub DoUnifiedDiff { # copied from DoDiff
|
||||
CreateDir($TempDir);
|
||||
my $oldName = "$TempDir/old";
|
||||
my $newName = "$TempDir/new";
|
||||
RequestLockDir('diff') or return '';
|
||||
WriteStringToFile($oldName, $_[0]);
|
||||
WriteStringToFile($newName, $_[1]);
|
||||
my $diff_out = `diff -U 99999 -- \Q$oldName\E \Q$newName\E | tail -n +7`; # should be +4, but we always add extra line # TODO that workaround is ugly, fix it!
|
||||
utf8::decode($diff_out); # needs decoding
|
||||
$diff_out =~ s/\n\K\\ No newline.*\n//g; # Get rid of common complaint.
|
||||
ReleaseLockDir('diff');
|
||||
# No need to unlink temp files--next diff will just overwrite.
|
||||
return $diff_out;
|
||||
}
|
||||
39
modules/div-foo.pl
Normal file
39
modules/div-foo.pl
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('div-foo.pl', 'Div Foo Extension');
|
||||
|
||||
use vars qw($DivFooPrefix);
|
||||
$DivFooPrefix = 'foo_';
|
||||
|
||||
push(@MyRules, \&DivFooRule);
|
||||
|
||||
sub DivFooRule {
|
||||
if (m/\G \< ([a-z-_][a-z-_ ]+[a-z-_]) \> \s*\n /cgx) {
|
||||
return CloseHtmlEnvironment('p') . AddHtmlEnvironment('div', 'class="' . join(' ', map {"$DivFooPrefix$_"} split /\s+/, $1) . '"');
|
||||
}
|
||||
if (m/\G \< ([a-z-_][a-z-_ ]+[a-z-_]) (\?(.*?(?=\>)))? \> /cgx) {
|
||||
my $title = $3 ? ' title="' . QuoteHtml($3) . '"' : '';
|
||||
return AddHtmlEnvironment('span', 'class="' . join(' ', map {"$DivFooPrefix$_"} split /\s+/, $1) . '"' . $title);
|
||||
}
|
||||
if (m/\G \< \/ \/ \> /cgx) {
|
||||
return CloseHtmlEnvironment('div') . (InElement('div') ? '' : AddHtmlEnvironment('p'));
|
||||
}
|
||||
if (m/\G \< \/ \> /cgx) {
|
||||
return CloseHtmlEnvironment('span');
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/dojo.pl">dojo.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Using_Dojo_Instead_Of_Wiki_Markup">Using Dojo Instead Of Wiki Markup</a></p>';
|
||||
AddModuleDescription('dojo.pl', 'Using Dojo Instead Of Wiki Markup');
|
||||
|
||||
use vars qw(@DojoPlugins $DojoTheme);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# edit a page by double-clicking on it. The user must have
|
||||
# JavaScript enabled for this to work.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/doubleclick.pl">doubleclick.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Doubleclick_Extension">Doubleclick Extension</a></p>';
|
||||
AddModuleDescription('doubleclick.pl', 'Doubleclick Extension');
|
||||
|
||||
*OldDoubleclickGetHeader = *GetHeader;
|
||||
*GetHeader = NewDoubleclickGetHeader;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/download.pl">download.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Download_Extension">Download Extension</a></p>';
|
||||
AddModuleDescription('download.pl', 'Download Extension');
|
||||
|
||||
push( @MyRules, \&DownloadSupportRule );
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
use File::Glob ':glob';
|
||||
use vars qw($DraftDir);
|
||||
|
||||
AddModuleDescription('drafts.pl');
|
||||
|
||||
$DraftDir = $DataDir."/draft"; # directory for drafts
|
||||
|
||||
push(@MyInitVariables, \&DraftInit);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/duckduckgo-search.pl">duckduckgo-search.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Use_DuckDuckGo_For_Searches">Use DuckDuckGo For Searches</a></p>';
|
||||
AddModuleDescription('duckduckgo-search.pl', 'Use DuckDuckGo For Searches');
|
||||
|
||||
use vars qw($DuckDuckGoSearchDomain);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/dynamic-comments.pl">dynamic-comments.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Dynamic_Comments_Extension">Dynamic Comments Extension</a></p>';
|
||||
AddModuleDescription('dynamic-comments.pl', 'Dynamic Comments Extension');
|
||||
|
||||
push(@MyInitVariables, \&DynamicCommentsAddScript);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# $LogoUrl = GetDynLogoUrl();
|
||||
#
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/dynlogo.pl">dynlogo.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Dynamic_Logo">Dynamic Logo</a></p>';
|
||||
AddModuleDescription('dynlogo.pl', 'Dynamic Logo');
|
||||
|
||||
use vars qw($DynLogoDirectory $DynLogoDefault %DynLogoMap);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/edit-assist.pl">edit-assist.pl</a></p>';
|
||||
AddModuleDescription('edit-assist.pl');
|
||||
|
||||
push (@MyInitVariables,
|
||||
sub {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
AddModuleDescription('edit-cluster.pl');
|
||||
|
||||
$EditCluster = 'EditCluster';
|
||||
|
||||
sub GetRc {
|
||||
@@ -88,7 +90,7 @@ sub EditClusterNewRcHeader {
|
||||
} else {
|
||||
print $q->h2((GetParam('days', $RcDefault) != 1)
|
||||
? Ts('Updates in the last %s days', GetParam('days', $RcDefault))
|
||||
: Ts('Updates in the last %s day', GetParam('days', $RcDefault)))
|
||||
: Ts('Updates in the last day'))
|
||||
}
|
||||
my $action;
|
||||
my ($idOnly, $userOnly, $hostOnly, $clusterOnly, $filterOnly, $match, $lang) =
|
||||
|
||||
75
modules/edit-paragraphs.js
Normal file
75
modules/edit-paragraphs.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright 2014 Alex Schroeder <alex@gnu.org>
|
||||
based on http://git.savannah.gnu.org/cgit/oddmuse.git/plain/plinks.js
|
||||
for more information see http://oddmuse.org/wiki/Purple_Numbers_Extension
|
||||
based on http://simon.incutio.com/archive/2004/05/30/plinks#p-13
|
||||
Copyright 2004 Simon Willison
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
function add_edit_links() {
|
||||
/* Only show edit links on ordinary pages: They either use
|
||||
* path_info or keywords in the URL, not parameters. */
|
||||
if (/=/.test(document.location.href)) {
|
||||
return;
|
||||
}
|
||||
// find all the pencil links
|
||||
var links = new Array;
|
||||
var elem = document.getElementsByTagName('a');
|
||||
for (var i = 0; i < elem.length; i++) {
|
||||
var atr = elem[i].getAttribute('class');
|
||||
if (atr != null) {
|
||||
var classes = atr.split(" ");
|
||||
for (var j = 0; j < classes.length; j++) {
|
||||
if (classes[j] == 'pencil') {
|
||||
links.push(elem[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// make them invisible
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var link = links[i];
|
||||
var func = function(thislink) {
|
||||
return function() {
|
||||
if (thislink.style.visibility == "visible") {
|
||||
thislink.style.transition = "visibility 0s 1s, opacity 1s linear";
|
||||
thislink.style.visibility = "hidden";
|
||||
thislink.style.opacity = "0";
|
||||
} else {
|
||||
thislink.style.transition = "opacity 1s linear";
|
||||
thislink.style.visibility = "visible";
|
||||
thislink.style.opacity = "1";
|
||||
};
|
||||
}
|
||||
};
|
||||
link.style.transition = "visibility 0s 1s, opacity 1s linear";
|
||||
link.style.visibility = "hidden";
|
||||
link.style.opacity = "0";
|
||||
link.parentNode.onclick = func(link);
|
||||
}
|
||||
}
|
||||
|
||||
function add_load_event(func) {
|
||||
var oldonload = window.onload;
|
||||
if (typeof window.onload != 'function') {
|
||||
window.onload = func;
|
||||
} else {
|
||||
window.onload = function() {
|
||||
oldonload();
|
||||
func();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_load_event(add_edit_links);
|
||||
213
modules/edit-paragraphs.pl
Normal file
213
modules/edit-paragraphs.pl
Normal file
@@ -0,0 +1,213 @@
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('edit-paragraph.pl', 'Edit Paragraphs Extension');
|
||||
|
||||
# edit icon
|
||||
# http://publicdomainvectors.org/en/free-clipart/Pencil-vector-icon/9221.html
|
||||
# q{<img width="30" height="30" title="" alt="edit" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAE2UlEQVRIx53WW0sbaRwG8GcmSsxhdTKT5K60FFqa4CmKh96uq62gtR563butN1KNQSgESqFemBjr2mKjMRpBt1uln2FJe9ObHsyu3d2yyH6EFoTVhr7PXrQTJslMmuwLA0mYvL95/vOebPjSJJMLJZ+t7iu9pw9AHEAQwAGAE4v/Wnasf5dNHsQK/R7A37IsEwAB/ATAY9W/VUpjh9Wi7wHw5s2b4vz588KAKyb9fDMVqniwPgB/AWA0GhX5fF68fftWBAIBHV82wf83bET/AMDJyUnx4cMHwa/t1atXRry07AW0FlhvPwA4dDgclCRJtLe3ixcvXtDYXr9+bcRXjLhcQ+JS9LeGhgbeunVLXL58WQBgIBDg8+fPy/BgMKjjD3VcrrHUOppraGjg3NycWFpaEmfOnKGiKLTC37x5I1paWnT8US2w3voBHDgcDkYiEZFIJITP56PH42E0GmVLSwsB8NKlS8xms0V4JpMRdXV1+lSrWNbS3/sBHLhcLs7OzopEIiH8fj8VReHy8jIjkQhdLhfPnTtXhudyOdHV1UVJkgSAPVQxV4uSulwuhsNhsbi4KPx+P1VV5dLSEsPhMGVZZnNzMxcWFnj27FkCYDAY5P7+vmhra9OT/gLAWe0yOADgwO12c2ZmpoBqmsbFxUWGw2HabDY2Nzdza2uLN27coCzL7Ojo0BPq6C4Ad7Ur0gCAnNvtLkrq9XoZj8cLSVtbW7mxscHx8XEC4NDQEBcWFoSqqjq6DeC7ass7ACBXWl6v18tYLFZA29vbub6+zomJCQLg8PAwt7e3RW9vL7+u22kATWYrlxl6BcDvTqeTkUhExONx4fP5CklnZ2dps9kYCoWYTCYL6PXr15lOp0V3d7eeNGWxUVii7xwOB+fm5spQPWlHR0cROjY2xlQqJXp6enQ0CUD71u5kRP+02+28c+eOiMfj9Hq91DSNiUSCMzMzpuj4+DjX1tZEb2+vjq4C8FZ4pUXoVQDv6+vrGY1GRSwWE5qmUVVVPnjwoICGQiGura0VBtLExASTyaQRfQTAV+U4wlV9E797966IxWJUVZWKonBlZYXT09OUZZltbW1MpVKV0IeSJPnN3qkZPAjgCADv3bsnYrEYPR4PGxsbubq6ytu3b1OSJLa2tjKdTnNsbMyqvCsmqGWprwD4R9/E79+/z6amJrrdbq6vr3NqaqqwImUyGY6OjhIAR0dHSwfSyjeSlrV3dXV1nJ+fFx8/fuSTJ0/Y2NjIjY0NTk1NUZIkBgIB7uzscGRkhAA4MjLCzc1N45R5KEmSr8LZzbRRURTx6dMnkuTx8TGz2SwnJycJgBcvXuTTp0957dq1osWhq6vLOJAqjl6rB6CqqoIkhfhyasnn80yn07xw4QL39/c5PDxMABwcHOTu7q7o7Ow0Thmt2tFbBmuaRiMshODJyQlfvnzJoaEhAuDAwAD39vZEKBQyLg6eGk6h5XB9fT0zmUwRTpKnp6d8/Pgx+/v7+ezZM+PWlrI4sko1lfrre+bm5mYZ/vnzZ2azWREMBnU0XbLLSFVureawjm9tbRUdV3K5nAgEAgQgAGQAuGpALRNLBlgCAKfTib6+PtjtdpyenvLw8FA6OjoSAH4G8COAfyuVzyKYafvVmNrkygPYAWCvMWnFUv8Hwmcq2TCQ4MwAAAAASUVORK5CYII=" />};
|
||||
|
||||
our $EditParagraphPencil = '✎';
|
||||
|
||||
# Allow editing of substrings
|
||||
|
||||
$Action{'edit-paragraph'} = \&DoEditParagraph;
|
||||
|
||||
sub DoEditParagraph {
|
||||
my $id = UnquoteHtml(GetParam('title', ''));
|
||||
UserCanEditOrDie($id);
|
||||
|
||||
my $old = UnquoteHtml(GetParam('paragraph', ''));
|
||||
$old =~ s/\r//g;
|
||||
return DoEdit($id) unless $old;
|
||||
|
||||
my $around = GetParam('around', undef);
|
||||
|
||||
# Find text to edit
|
||||
my $new = GetParam('text', '');
|
||||
OpenPage($id);
|
||||
if ($new) {
|
||||
my $myoldtime = GetParam('oldtime', ''); # maybe empty!
|
||||
my $text;
|
||||
if ($myoldtime and $myoldtime != $LastUpdate) {
|
||||
($text) = GetTextAtTime($myoldtime);
|
||||
} else {
|
||||
$text = $Page{text};
|
||||
}
|
||||
|
||||
my $done;
|
||||
if ($around) {
|
||||
# The tricky part is that the numbers refer to the HTML quoted text. What a pain.
|
||||
my $qold = QuoteHtml($old);
|
||||
my $qtext = QuoteHtml($text);
|
||||
|
||||
if (substr($qtext, $around - length($qold), length($qold)) eq $qold) {
|
||||
$text = UnquoteHtml(substr($qtext, 0, $around - length($qold))
|
||||
. QuoteHtml($new) . substr($qtext, $around));
|
||||
$done = 1;
|
||||
}
|
||||
} else {
|
||||
# simple case, just do it
|
||||
my $search_term = quotemeta($old);
|
||||
$done = $text =~ s/$search_term/$new/;
|
||||
}
|
||||
|
||||
if ($done) {
|
||||
SetParam('text', UnquoteHtml($text));
|
||||
return DoPost($id);
|
||||
} else {
|
||||
$text = substr($text, 0, $around)
|
||||
. "\n### around here ###\n"
|
||||
. substr($text, $around)
|
||||
if $around;
|
||||
ReportError(T('Could not identify the paragraph you were editing'),
|
||||
'500 INTERNAL SERVER ERROR',
|
||||
undef,
|
||||
$q->p(T('This is the section you edited:'))
|
||||
. $q->pre(QuoteHtml($old))
|
||||
. $q->p(T('This is the current page:'))
|
||||
. $q->pre($text));
|
||||
}
|
||||
}
|
||||
print GetHeader('', Ts('Editing %s', NormalToFree($id)));
|
||||
print $q->start_div({-class=>'content edit paragraph'});
|
||||
my $form = GetEditForm($id, undef, $old);
|
||||
my $param = GetHiddenValue('paragraph', $old);
|
||||
$param .= GetHiddenValue('action', 'edit-paragraph'); # add action
|
||||
$param .= GetHiddenValue('around', $around); # add around position
|
||||
$form =~ s!</form>!$param</form>!;
|
||||
print $form;
|
||||
print $q->end_div();
|
||||
PrintFooter($id, 'edit');
|
||||
}
|
||||
|
||||
# When PrintWikiToHTML is called for the current revision of a page we
|
||||
# initialize our data structure. The data structure simply divides the
|
||||
# page up into blocks based on what one would like to edit. By
|
||||
# default, that's just paragraph breaks and list items. When using
|
||||
# Creole, ordered list items and table rows are added.
|
||||
|
||||
my @EditParagraphs = ();
|
||||
|
||||
*EditParagraphOldPrintWikiToHTML = *PrintWikiToHTML;
|
||||
*PrintWikiToHTML = *EditParagraphNewPrintWikiToHTML;
|
||||
|
||||
sub EditParagraphNewPrintWikiToHTML {
|
||||
my ($text, $is_saving_cache, $revision, $is_locked) = @_;
|
||||
# We need to use quoted HTML because that's what the rules will applied to!
|
||||
my $quoted_text = QuoteHtml($text);
|
||||
if ($quoted_text and not $revision) {
|
||||
my ($start, $end) = (0, 0);
|
||||
# This grouping with zero-width positive look-ahead assertion makes sure that this chunk of text does not include
|
||||
# markup need for the next chunk of text.
|
||||
if (grep { $_ eq \&CreoleRule } @MyRules) {
|
||||
$regexp = "\n+(\n|(?=[*#-=|]))";
|
||||
} else {
|
||||
$regexp = "\n+(\n|(?=[*]))";
|
||||
}
|
||||
while ($quoted_text =~ /$regexp/g) {
|
||||
$end = pos($quoted_text);
|
||||
push(@EditParagraphs,
|
||||
[$start, $end, substr($quoted_text, $start, $end - $start)]);
|
||||
$start = $end;
|
||||
}
|
||||
# Only do this if we have at least two paragraphs and the end isn't just some empty lines.
|
||||
if (@EditParagraphs and $start and $start < length($quoted_text)) {
|
||||
push(@EditParagraphs, [$start, length($quoted_text), substr($quoted_text, $start)]);
|
||||
}
|
||||
}
|
||||
# warn join('', '', map { $_->[0] . "-" . $_->[1] .": " . $_->[2]; } @EditParagraphs);
|
||||
return EditParagraphOldPrintWikiToHTML(@_);
|
||||
}
|
||||
|
||||
# Whenever an important element is closed, we try to add a link.
|
||||
|
||||
*EditParagraphOldCloseHtmlEnvironments = *CloseHtmlEnvironments;
|
||||
*CloseHtmlEnvironments = *EditParagraphNewCloseHtmlEnvironments;
|
||||
|
||||
sub EditParagraphNewCloseHtmlEnvironments {
|
||||
EditParagraph();
|
||||
return EditParagraphOldCloseHtmlEnvironments(@_);
|
||||
}
|
||||
|
||||
*EditParagraphOldCloseHtmlEnvironmentUntil = *CloseHtmlEnvironmentUntil;
|
||||
*CloseHtmlEnvironmentUntil = *EditParagraphNewCloseHtmlEnvironmentUntil;
|
||||
|
||||
sub EditParagraphNewCloseHtmlEnvironmentUntil {
|
||||
my $tag = $_[0];
|
||||
if ($tag =~ /^(p|li|table|h[1-6])$/i) {
|
||||
EditParagraph();
|
||||
}
|
||||
return EditParagraphOldCloseHtmlEnvironmentUntil(@_);
|
||||
}
|
||||
|
||||
sub EditParagraph {
|
||||
my $text;
|
||||
my $pos = pos; # pos is empty for the last link
|
||||
if (@EditParagraphs) {
|
||||
if ($pos) {
|
||||
while (@EditParagraphs and $EditParagraphs[0]->[1] <= $pos) {
|
||||
$pos = $EditParagraphs[0]->[1]; # just in case we're overshooting
|
||||
$text .= $EditParagraphs[0]->[2];
|
||||
shift(@EditParagraphs);
|
||||
}
|
||||
} else {
|
||||
# the last one
|
||||
$text = $EditParagraphs[-1]->[2];
|
||||
}
|
||||
}
|
||||
if ($text) {
|
||||
|
||||
# Huge Hack Alert: We are appending to $Fragment, which is what Clean appends to. We do this so that we can handle
|
||||
# headers and other block elements. Without this fix we'd see something like this:
|
||||
# <h2>...</h2><p><a ...>✎</a></p>
|
||||
# Usually this would look as follows:
|
||||
# <h2>...</h2><p></p>
|
||||
# This is eliminated in Dirty. But it won't be eliminated if we leave the link in there. What we want is this:
|
||||
# <h2>...<a ...>✎</a></h2><p></p>
|
||||
#
|
||||
# The same issue arises for other block level elements. What happens at the end of a table? Without this fix we'd
|
||||
# see something like this:
|
||||
# <table><tr><td>...</td></tr></table><p><a ...>✎</a></p>
|
||||
# What we want, I guess, is this:
|
||||
# <table><tr><td>...<a ...>✎</a></td></tr></table></p>
|
||||
|
||||
$pos = $pos || length(QuoteHtml($Page{text})); # make sure we have an around value
|
||||
my $title = UrlEncode($OpenPageName);
|
||||
my $paragraph = UrlEncode(UnquoteHtml($text));
|
||||
my $link = ScriptLink("action=edit-paragraph;title=$title;around=$pos;paragraph=$paragraph",
|
||||
$EditParagraphPencil, 'pencil');
|
||||
|
||||
if ($Fragment =~ s!((:?</h[1-6]>|</t[dh]></tr></table>|</pre>)<p>)$!!) {
|
||||
# $Fragment .= '<!-- moved inside -->';
|
||||
$Fragment .= $link . $1;
|
||||
} elsif ($Fragment =~ s!(</p>\s*</form>)$!!) {
|
||||
# $Fragment .= '<!-- HTML fixes for <html> -->';
|
||||
# Since anything can appear in raw HTML tags, there is no one-size fits all rule.
|
||||
# I usually use the <html> tags to embed forms, and forms need to contain a <p>.
|
||||
# so that's what I'm handling.
|
||||
$Fragment .= $link . $1;
|
||||
} elsif ($pos and $Fragment =~ /<(p|tr)>$/) {
|
||||
# Do nothing: this is either an empty paragraph and will be
|
||||
# eliminated, or an empty row which will not be shown.
|
||||
# $Fragment .= '<!-- empty -->';
|
||||
} else {
|
||||
# This is the default: add the link.
|
||||
# $Fragment .= '<!-- default -->';
|
||||
$Fragment .= $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
# For user doc, see:
|
||||
# http://www.oddmuse.org/cgi-bin/oddmuse/Email_Quote_Extension
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/emailquote.pl">emailquote.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Email_Quote_Extension">Email Quote Extension</a></p>';
|
||||
AddModuleDescription('emailquote.pl', 'Email Quote Extension');
|
||||
|
||||
push(@MyRules, \&EmailQuoteRule);
|
||||
|
||||
|
||||
66
modules/emoji.pl
Normal file
66
modules/emoji.pl
Normal file
@@ -0,0 +1,66 @@
|
||||
# Copyright (C) 2014 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
AddModuleDescription('emoji.pl', 'Smilies');
|
||||
|
||||
push(@MyRules, \&EmojiRule);
|
||||
# this must come before tex.pl because of \o/ turning into ø/
|
||||
$RuleOrder{\&EmojiRule} = 150;
|
||||
|
||||
# Some relevant links
|
||||
# https://en.wikipedia.org/wiki/List_of_emoticons
|
||||
|
||||
sub EmojiRule {
|
||||
if (m/\G:-?D/cg) {
|
||||
# 😀 1F600 GRINNING FACE
|
||||
return '😀';
|
||||
} elsif (/\G:[-o]?\)/cg) {
|
||||
# 😊 1F60A SMILING FACE WITH SMILING EYES
|
||||
return '😊';
|
||||
} elsif (/\G\s+:3/cg) {
|
||||
# 😸 1F638 GRINNING CAT FACE WITH SMILING EYES
|
||||
return ' 😸';
|
||||
} elsif (/\G:-?\(/cg) {
|
||||
# 😟 1F61F WORRIED FACE
|
||||
return '😟';
|
||||
} elsif (/\G;-?\)/cg) {
|
||||
# 😉 1F609 WINKING FACE
|
||||
return '😉';
|
||||
} elsif (/\G:'\(/cg) {
|
||||
# 😢 1F622 CRYING FACE
|
||||
return '😢';
|
||||
} elsif (/\G>:-?\(/cg) {
|
||||
# 😠 1F620 ANGRY FACE
|
||||
return '😠';
|
||||
} elsif (/\G:-?[Ppb]/cg) {
|
||||
# 😝 1F61D FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES
|
||||
return '😝';
|
||||
} elsif (/\G<3/cg) {
|
||||
# ❤ 2764 HEAVY BLACK HEART
|
||||
return '❤';
|
||||
} elsif (/\G\^_*\^/cg) {
|
||||
# 😄 1F604 SMILING FACE WITH OPEN MOUTH AND SMILING EYES
|
||||
return '😄';
|
||||
} elsif (/\G\b[Oo]_[Oo]\b/cg) {
|
||||
# 😲 1F632 ASTONISHED FACE
|
||||
return '😲';
|
||||
} elsif (/\G\\o\//cg) {
|
||||
# 🙌 1F64C PERSON RAISING BOTH HANDS IN CELEBRATION
|
||||
return '🙌';
|
||||
} elsif (/\G\\m\//cg) {
|
||||
# ✊ 270A RAISED FIST
|
||||
return '✊';
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/enclosure.pl">enclosure.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Podcasting">Podcasting</a></p>';
|
||||
AddModuleDescription('enclosure.pl', 'Podcasting');
|
||||
|
||||
use vars qw(@Enclosures);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
# Additionally, lines starting with Q: and A: are rendered using
|
||||
# the css classes div.question and div.answer.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/faq.pl">faq.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/FAQ_Extension">FAQ Extension</a></p>';
|
||||
AddModuleDescription('faq.pl', 'FAQ Extension');
|
||||
|
||||
$FaqHeaderText = "Questions on this page:" unless $FaqHeaderText;
|
||||
$FaqQuestionText = "Question: " unless $FaqQuestionText;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA,
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/fckeditor.pl">fckeditor.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Using_FCKeditor_In_Addition_To_Wiki_Markup">Using FCKeditor In Addition To Wiki Markup</a></p>';
|
||||
AddModuleDescription('fckeditor.pl', 'Using FCKeditor In Addition To Wiki Markup');
|
||||
|
||||
use vars qw($FCKeditorHeight);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# For user doc, see:
|
||||
# http://www.oddmuse.org/cgi-bin/oddmuse/Field_List_Extension
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/fieldlist.pl">fieldlist.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Field_List_Extension">Field List Extension</a></p>';
|
||||
AddModuleDescription('fieldlist.pl', 'Field List Extension');
|
||||
|
||||
push(@MyRules, \&FieldListRules);
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/find.pl">find.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Find_Extension">Find Extension</a></p>';
|
||||
AddModuleDescription('find.pl', 'Find Extension');
|
||||
|
||||
$Action{find} = \&DoFind;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/fix-encoding.pl">fix-encoding.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Fix_Encoding">Fix Encoding</a></p>';
|
||||
AddModuleDescription('fix-encoding.pl', 'Fix Encoding');
|
||||
|
||||
$Action{'fix-encoding'} = \&FixEncoding;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ directory of your Oddmuse Wiki.
|
||||
=cut
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/flashbox.pl">flashbox.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Flashbox_Extension">Flashbox Extension</a></p>';
|
||||
AddModuleDescription('flashbox.pl', 'Flashbox Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/flickrgallery.pl">flickrgallery.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/FlickrGallery_Module">FlickrGallery Module</a></p>';
|
||||
AddModuleDescription('flickrgallery.pl', 'FlickrGallery Module');
|
||||
|
||||
# NOTE: This API key for Flickr is NOT to be used in any other products
|
||||
# INCLUDING derivative works. The rest of the code can be used as licensed
|
||||
|
||||
@@ -13,7 +13,7 @@ directory for your Oddmuse Wiki.
|
||||
=cut
|
||||
package OddMuse;
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/footnotes.pl">footnotes.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Footnotes_Extension">Footnotes Extension</a></p>';
|
||||
AddModuleDescription('footnotes.pl', 'Footnotes Extension');
|
||||
|
||||
# ....................{ CONFIGURATION }....................
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p>form_timeout_token.pl</p>';
|
||||
AddModuleDescription('form_timeout.pl');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
# ====================[ forms.pl ]====================
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/forms.pl">forms.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Form_Extension">Form Extension</a></p>';
|
||||
AddModuleDescription('forms.pl', 'Form Extension');
|
||||
|
||||
# ....................{ MARKUP }....................
|
||||
push(@MyRules, \&FormsRule);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/fractions.pl">fractions.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Fractions">Fractions</a></p>';
|
||||
AddModuleDescription('fractions.pl', 'Fractions');
|
||||
|
||||
push(@MyRules, \&FractionsRule);
|
||||
|
||||
|
||||
398
modules/gd_security_image.pl
Normal file
398
modules/gd_security_image.pl
Normal file
@@ -0,0 +1,398 @@
|
||||
# GdSecurityImage - a CAPTCHA module for Oddmuse using GD::SecurityImage module
|
||||
#
|
||||
# Copyright (C) 2014 Aki Goto <tyatsumi@gmail.com>
|
||||
#
|
||||
# Codes reused from MwfCaptcha.pm in mwForum - Web-based discussion forum
|
||||
# Copyright (c) 1999-2014 Markus Wichitill
|
||||
#
|
||||
# Codes reused from questionasker.pl for Oddmuse
|
||||
# Copyright (C) 2004 Brock Wilcox <awwaiid@thelackthereof.org>
|
||||
# Copyright (C) 2006, 2007 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
AddModuleDescription('gd_security_image.pl');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is a CAPTCHA module for Oddmuse using GD::SecurityImage module.
|
||||
|
||||
=head1 CONFIGURATION
|
||||
|
||||
$GdSecurityImageFont
|
||||
Mandatory.
|
||||
Set a TTF font file used for generating CAPTCHA images.
|
||||
Example: '/usr/share/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf'.
|
||||
|
||||
$GdSecurityImageRememberAnswer
|
||||
If 1, once CAPTCHA is answered, the result is cached on cookies
|
||||
and you need not to re-answer CAPTCHAs for some duration specified
|
||||
by $GdSecurityImageDuration.
|
||||
If 0, CAPTCHA is requested everytime you try to submit forms.
|
||||
Default = 1.
|
||||
|
||||
$GdSecurityImageDuration
|
||||
The duration a CAPTCHA ticket is valid in seconds.
|
||||
Default = 60 * 10 (10 minutes).
|
||||
|
||||
$GdSecurityImageRequiredList
|
||||
The page name for exceptions, if defined. Every page linked to via
|
||||
WikiWord or [[free link]] is considered to be a page which needs
|
||||
questions asked. All other pages do not require questions asked. If
|
||||
not set, then all pages need questions asked.
|
||||
|
||||
%GdSecurityImageProtectedForms
|
||||
Forms using one of the specified classes are protected.
|
||||
Default: ('comment' => 1, 'edit upload' => 1, 'edit text' => 1,).
|
||||
|
||||
$GdSecurityImageDataDir
|
||||
When using with Namespaces Extension, specify original root data directory
|
||||
to concentrate GdSecurityImage data files in it.
|
||||
Default: $DataDir.
|
||||
|
||||
$GdSecurityImageWidth
|
||||
Default: 250.
|
||||
|
||||
$GdSecurityImageHeight
|
||||
Default: 60.
|
||||
|
||||
$GdSecurityImagePtsize
|
||||
Default: 16.
|
||||
|
||||
$GdSecurityImageScramble
|
||||
Default: 1.
|
||||
|
||||
$GdSecurityImageChars
|
||||
Default: [qw(A B C D E F G H I J K L M O P R S T U V W X Y)].
|
||||
|
||||
=head1 API
|
||||
|
||||
You can use this module in other modules by using following APIs.
|
||||
|
||||
GdSecurityImageGetHtml
|
||||
returns CAPTCHA HTML form element for embedding in HTML form clause.
|
||||
|
||||
GdSecurityImageCheck
|
||||
returns whether CAPTCHA is answered correctly or not.
|
||||
|
||||
=head1 DATA STRUCTURE
|
||||
|
||||
Image data and ticket data are stored in $DataDir/gd_security_image directory.
|
||||
Old data are deleted partially whenever CAPTCHA form is accessed.
|
||||
You can delete this directory totally harmlessly, although it forces users to
|
||||
re-answer CAPTCHA.
|
||||
|
||||
=cut
|
||||
|
||||
use vars qw($GdSecurityImageFont $GdSecurityImageRememberAnswer
|
||||
$GdSecurityImageDuration $GdSecurityImageRequiredList
|
||||
%GdSecurityImageProtectedForms $GdSecurityImageDataDir
|
||||
$GdSecurityImageWidth $GdSecurityImageHeight
|
||||
$GdSecurityImagePtsize $GdSecurityImageScramble $GdSecurityImageChars
|
||||
$GdSecurityImageAA);
|
||||
use vars qw($GdSecurityImageDir $GdSecurityImageId $GdSecurityImagePngToAA);
|
||||
|
||||
use Digest::MD5;
|
||||
use File::Glob ':glob';
|
||||
|
||||
$GdSecurityImageRequiredList = '';
|
||||
|
||||
$Action{gd_security_image} = \&GdSecurityImageDoImage;
|
||||
|
||||
push(@MyInitVariables, \&GdSecurityImageInitVariables);
|
||||
|
||||
sub GdSecurityImageGetImageFile {
|
||||
my ($id) = @_;
|
||||
return "$GdSecurityImageDir/$id.png";
|
||||
}
|
||||
|
||||
sub GdSecurityImageGetTicketFile {
|
||||
my ($id) = @_;
|
||||
return "$GdSecurityImageDir/$id.ticket";
|
||||
}
|
||||
|
||||
sub GdSecurityImageGenerate {
|
||||
# Load modules
|
||||
my $gd = eval { require GD };
|
||||
eval { require Image::Magick }
|
||||
or ReportError(T('GD or Image::Magick modules not available.'), '500 INTERNAL SERVER ERROR') if !$gd;
|
||||
eval { require GD::SecurityImage }
|
||||
or ReportError(T('GD::SecurityImage module not available.'));
|
||||
|
||||
# Generate captcha image
|
||||
GD::SecurityImage->import($gd ? () : (use_magick => 1));
|
||||
my $img = GD::SecurityImage->new(
|
||||
width => $GdSecurityImageWidth,
|
||||
height => $GdSecurityImageHeight,
|
||||
font => $GdSecurityImageFont,
|
||||
ptsize => $GdSecurityImagePtsize,
|
||||
scramble => $GdSecurityImageScramble,
|
||||
rnd_data => $GdSecurityImageChars,
|
||||
bgcolor => '#000000',
|
||||
);
|
||||
$img->random();
|
||||
my $newCaptchaStr = $img->random_str();
|
||||
$img->create('ttf', int(rand(2)) ? 'default' : 'ec', '#ffffff', '#ffffff');
|
||||
$img->particle(3000);
|
||||
|
||||
### experimental ###
|
||||
#my $raw = $img->raw;
|
||||
#my $w2 = $GdSecurityImageWidth * 2 / 3;
|
||||
#my $h2 = $GdSecurityImageHeight * 2 / 3;
|
||||
#my $raw2 = GD::Image->new($w2, $h2);
|
||||
#$raw2->copyResampled($raw, 0, 0, 0, 0, $w2, $h2, $raw->getBounds);
|
||||
#my $png = $raw2->png;
|
||||
|
||||
# Store captcha image
|
||||
my ($imgData) = $img->out(force => 'png');
|
||||
my $ticketId = Digest::MD5::md5_hex(rand());
|
||||
CreateDir($GdSecurityImageDir);
|
||||
my $file = GdSecurityImageGetImageFile($ticketId);
|
||||
open my $fh, ">:raw", $file
|
||||
or ReportError(Ts('Image storing failed. (%s)', $!), '500 INTERNAL SERVER ERROR');
|
||||
print $fh $imgData;
|
||||
#print $fh $png; ### experimental ###
|
||||
close $fh;
|
||||
|
||||
# Insert captcha ticket
|
||||
my %page = ();
|
||||
$page{id} = $ticketId;
|
||||
$page{generation_time} = $Now;
|
||||
$page{string} = $newCaptchaStr;
|
||||
CreateDir($GdSecurityImageDir);
|
||||
WriteStringToFile(GdSecurityImageGetTicketFile($ticketId), EncodePage(%page));
|
||||
|
||||
return $ticketId;
|
||||
}
|
||||
|
||||
sub GdSecurityImageIsValidId {
|
||||
my ($id) = @_;
|
||||
return $id =~ /^[0-9a-f]+$/;
|
||||
}
|
||||
|
||||
sub GdSecurityImageReadImageFile {
|
||||
my $file = shift;
|
||||
utf8::encode($file); # filenames are bytes!
|
||||
if (open(IN, '<:raw', $file)) {
|
||||
local $/ = undef; # Read complete files
|
||||
my $data=<IN>;
|
||||
close IN;
|
||||
return (1, $data);
|
||||
}
|
||||
return (0, '');
|
||||
}
|
||||
|
||||
sub GdSecurityImageDoImage {
|
||||
my $id = GetParam('gd_security_image_id', '');
|
||||
|
||||
if (!GdSecurityImageIsValidId($id)) {
|
||||
ReportError(T('Bad gd_security_image_id.'), '400 BAD REQUEST');
|
||||
}
|
||||
|
||||
my ($status, $data) = GdSecurityImageReadImageFile(GdSecurityImageGetImageFile($id));
|
||||
|
||||
binmode(STDOUT, ":raw");
|
||||
print $q->header(-type=>'image/png');
|
||||
print $data;
|
||||
|
||||
unlink(GdSecurityImageGetImageFile($id));
|
||||
}
|
||||
|
||||
sub GdSecurityImageCleanup {
|
||||
my ($id) = @_;
|
||||
if (!GdSecurityImageIsValidId($id)) {
|
||||
return;
|
||||
}
|
||||
my @files = (bsd_glob("$GdSecurityImageDir/*.png"), bsd_glob("$GdSecurityImageDir/*.ticket"));
|
||||
foreach my $file (@files) {
|
||||
if ($Now - (stat $file)[9] > $GdSecurityImageDuration) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub GdSecurityImageCheck {
|
||||
if (defined($GdSecurityImageId)) {
|
||||
return $GdSecurityImageId eq '';
|
||||
}
|
||||
|
||||
my $id = GetParam('gd_security_image_id', '');
|
||||
my $answer = GetParam('gd_security_image_answer', '');
|
||||
|
||||
GdSecurityImageCleanup($id);
|
||||
|
||||
if ($answer ne '' && GdSecurityImageIsValidId($id)) {
|
||||
my ($status, $data) = ReadFile(GdSecurityImageGetTicketFile($id));
|
||||
if ($status) {
|
||||
my %page = ParseData($data);
|
||||
if ($page{generation_time} + $GdSecurityImageDuration > $Now) {
|
||||
if ($answer eq $page{string}) {
|
||||
$GdSecurityImageId = '';
|
||||
if (!$GdSecurityImageRememberAnswer) {
|
||||
SetParam('gd_security_image_id', '');
|
||||
SetParam('gd_security_image_answer', '');
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GdSecurityImageIsValidId($id)) {
|
||||
unlink(GdSecurityImageGetTicketFile($id));
|
||||
}
|
||||
|
||||
$GdSecurityImageId = GdSecurityImageGenerate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub GdSecurityImageGetHtml {
|
||||
if (GdSecurityImageCheck()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
my $form = '';
|
||||
|
||||
SetParam('gd_security_image_answer', '');
|
||||
|
||||
$form .= $q->start_div({-class=>'gd_security_image'});
|
||||
|
||||
$form .= $q->start_div();
|
||||
$form .= T('Please type the six characters from the anti-spam image');
|
||||
$form .= $q->end_div();
|
||||
|
||||
$form .= $q->start_div();
|
||||
$form .= $q->input({-type=>'hidden', -name=>'gd_security_image_id', -value=>$GdSecurityImageId});
|
||||
$form .= $q->textfield(-name=>'gd_security_image_answer', -id=>'gd_security_image_answer');
|
||||
$form .= $q->submit(-name=>'Submit', -value=>T('Submit'));
|
||||
$form .= $q->end_div();
|
||||
|
||||
$form .= $q->start_div();
|
||||
$form .= $q->img({-src=>"$FullUrl?action=gd_security_image&gd_security_image_id=$GdSecurityImageId", -alt=>T('CAPTCHA'), -width=>$GdSecurityImageWidth, -height=>$GdSecurityImageHeight});
|
||||
$form .= $q->end_div();
|
||||
|
||||
if ($GdSecurityImageAA) {
|
||||
$form .= $q->start_div({class=>'aa_captcha'});
|
||||
$form .= $q->start_pre();
|
||||
my $png_file = GdSecurityImageGetImageFile($GdSecurityImageId);
|
||||
$form .= `$GdSecurityImagePngToAA $png_file`;
|
||||
$form .= $q->end_pre();
|
||||
$form .= $q->end_div();
|
||||
}
|
||||
|
||||
$form .= $q->end_div();
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
*OldGdSecurityImageDoPost = *DoPost;
|
||||
*DoPost = *NewGdSecurityImageDoPost;
|
||||
|
||||
sub NewGdSecurityImageDoPost {
|
||||
my(@params) = @_;
|
||||
my $id = FreeToNormal(GetParam('title', undef));
|
||||
my $preview = GetParam('Preview', undef); # case matters!
|
||||
unless (UserIsEditor()
|
||||
or $preview
|
||||
or GdSecurityImageCheck()
|
||||
or GdSecurityImageException($id)) {
|
||||
print GetHeader('', T('Edit Denied'), undef, undef, '403 FORBIDDEN');
|
||||
print $q->p(T('You did not answer correctly.'));
|
||||
print GetFormStart(), GdSecurityImageGetHtml(),
|
||||
(map { $q->input({-type=>'hidden', -name=>$_, -value=>UnquoteHtml(GetParam($_))}) }
|
||||
qw(title text oldtime summary recent_edit aftertext)), $q->end_form;
|
||||
PrintFooter();
|
||||
# logging to the error log file of the server
|
||||
# warn "Q: '$QuestionaskerQuestions[$question_num][0]', A: '$answer'\n";
|
||||
return;
|
||||
}
|
||||
return (OldGdSecurityImageDoPost(@params));
|
||||
}
|
||||
|
||||
*OldGdSecurityImageGetEditForm = *GetEditForm;
|
||||
*GetEditForm = *NewGdSecurityImageGetEditForm;
|
||||
|
||||
sub NewGdSecurityImageGetEditForm {
|
||||
return GdSecurityImageAddTo(OldGdSecurityImageGetEditForm(@_));
|
||||
}
|
||||
|
||||
*OldGdSecurityImageGetCommentForm = *GetCommentForm;
|
||||
*GetCommentForm = *NewGdSecurityImageGetCommentForm;
|
||||
|
||||
sub NewGdSecurityImageGetCommentForm {
|
||||
return GdSecurityImageAddTo(OldGdSecurityImageGetCommentForm(@_));
|
||||
}
|
||||
|
||||
sub GdSecurityImageAddTo {
|
||||
my $form = shift;
|
||||
if (not $upload
|
||||
and not GdSecurityImageException(GetId())
|
||||
and not UserIsEditor()) {
|
||||
my $question = GdSecurityImageGetHtml();
|
||||
$form =~ s/(.*)<p>(.*?)<label for="username">/$1$question<p>$2<label for="username">/;
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
sub GdSecurityImageException {
|
||||
my $id = shift;
|
||||
return 0 unless $GdSecurityImageRequiredList and $id;
|
||||
my $data = GetPageContent($GdSecurityImageRequiredList);
|
||||
if ($WikiLinks) {
|
||||
while ($data =~ /$LinkPattern/g) {
|
||||
return 0 if FreeToNormal($1) eq $id;
|
||||
}
|
||||
}
|
||||
if ($FreeLinks) {
|
||||
while ($data =~ /\[\[$FreeLinkPattern\]\]/g) {
|
||||
return 0 if FreeToNormal($1) eq $id;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub GdSecurityImageInitVariables {
|
||||
ReportError(T('$GdSecurityImageFont is not set.'), '500 INTERNAL SERVER ERROR') unless defined $GdSecurityImageFont;
|
||||
$GdSecurityImageRememberAnswer = 1 unless defined $GdSecurityImageRememberAnswer;
|
||||
$GdSecurityImageDuration = 60 * 10 unless defined $GdSecurityImageDuration;
|
||||
|
||||
$GdSecurityImageRequiredList = FreeToNormal($GdSecurityImageRequiredList);
|
||||
|
||||
# Forms using one of the following classes are protected.
|
||||
%GdSecurityImageProtectedForms = ('comment' => 1,
|
||||
'edit upload' => 1,
|
||||
'edit text' => 1,)
|
||||
unless defined %GdSecurityImageProtectedForms;
|
||||
|
||||
$GdSecurityImageDataDir = $DataDir unless defined $GdSecurityImageDataDir;
|
||||
|
||||
$GdSecurityImageWidth = 240 unless defined $GdSecurityImageWidth;
|
||||
$GdSecurityImageHeight = 75 unless defined $GdSecurityImageHeight;
|
||||
$GdSecurityImagePtsize = 16.75 unless defined $GdSecurityImagePtsize;
|
||||
$GdSecurityImageScramble = 1 unless defined $GdSecurityImageScramble;
|
||||
$GdSecurityImageChars = [qw(A B C D E F G H I J K L M O P R S T U V W X Y)] unless defined $GdSecurityImageChars;
|
||||
|
||||
$GdSecurityImageAA = 0 unless defined $GdSecurityImageAA;
|
||||
|
||||
$GdSecurityImageDir = "$GdSecurityImageDataDir/gd_security_image";
|
||||
|
||||
$GdSecurityImageId = undef;
|
||||
|
||||
$GdSecurityImagePngToAA = "$ModuleDir/pngtoaa";
|
||||
|
||||
$CookieParameters{'gd_security_image_id'} = '';
|
||||
$InvisibleCookieParameters{'gd_security_image_id'} = 1;
|
||||
$CookieParameters{'gd_security_image_answer'} = '';
|
||||
$InvisibleCookieParameters{'gd_security_image_answer'} = 1;
|
||||
}
|
||||
72
modules/git-another.pl
Normal file
72
modules/git-another.pl
Normal file
@@ -0,0 +1,72 @@
|
||||
# Copyright (C) 2014 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
# Copyright (C) 2011 Alex Schroeder <alex@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 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/>.
|
||||
|
||||
package OddMuse;
|
||||
|
||||
AddModuleDescription('git-another.pl', 'Another Git Extension');
|
||||
|
||||
use Cwd;
|
||||
use Capture::Tiny ':all';
|
||||
use vars qw($GitBinary $GitMail);
|
||||
|
||||
$GitBinary = 'git';
|
||||
$GitMail = 'unknown@oddmuse.org';
|
||||
|
||||
sub GitCommit {
|
||||
my ($message, $author) = @_;
|
||||
my $oldDir = cwd;
|
||||
chdir("$DataDir/page");
|
||||
capture {
|
||||
system($GitBinary, qw(add -A));
|
||||
system($GitBinary, qw(commit -q -m), $message, "--author=$author <$GitMail>");
|
||||
};
|
||||
chdir($oldDir);
|
||||
}
|
||||
|
||||
sub GitInitRepository {
|
||||
return if -d "$DataDir/page/.git";
|
||||
capture {
|
||||
system($GitBinary, qw(init -q --), "$DataDir/page");
|
||||
};
|
||||
GitCommit('Initial import', 'Oddmuse');
|
||||
}
|
||||
|
||||
sub RenderHtmlCacheWithoutPrinting { # requires an open page
|
||||
$FootnoteNumber = 0;
|
||||
my $blocks, $flags;
|
||||
capture {
|
||||
($blocks, $flags) = ApplyRules(QuoteHtml($Page{text}), 1, 1, $Page{revision}, 'p');
|
||||
};
|
||||
if ($Page{blocks} ne $blocks and $Page{flags} ne $flags) {
|
||||
$Page{blocks} = $blocks;
|
||||
$Page{flags} = $flags;
|
||||
SavePage();
|
||||
}
|
||||
}
|
||||
|
||||
*GitOldSave = *Save;
|
||||
*Save = *GitNewSave;
|
||||
|
||||
sub GitNewSave {
|
||||
GitInitRepository();
|
||||
GitCommit('No description available', 'Oddmuse'); # commit any changes before this edit
|
||||
GitOldSave(@_);
|
||||
RenderHtmlCacheWithoutPrinting();
|
||||
my $message = $Page{summary};
|
||||
$message =~ s/^\s+$//;
|
||||
$message ||= T('No summary provided');
|
||||
my $author = $Page{username} || T('Anonymous');
|
||||
GitCommit($message, $author); # commit this edit
|
||||
}
|
||||
143
modules/git.pl
143
modules/git.pl
@@ -31,7 +31,7 @@ Set these variables in the B<config> file within your data directory.
|
||||
|
||||
=head2 $GitBinary
|
||||
|
||||
Default: C</usr/bin/git>
|
||||
Default: C<git>
|
||||
|
||||
The fully qualified name for the binary to run. Your PATH will not be searched.
|
||||
|
||||
@@ -48,31 +48,56 @@ Default: C<unknown@oddmuse.org>
|
||||
|
||||
The email address used to identify users in git.
|
||||
|
||||
=head2 $GitDebug
|
||||
|
||||
Default: 0
|
||||
|
||||
If set, we capture the output of the git command and store it in
|
||||
$GitResult. This is useful when writing tests.
|
||||
|
||||
=head2 $GitResult
|
||||
|
||||
If $GitDebug is set, this variable holds STDOUT of the git command.
|
||||
|
||||
=cut
|
||||
|
||||
use vars qw($GitBinary $GitRepo $GitMail);
|
||||
use Cwd;
|
||||
use File::Temp ();
|
||||
use vars qw($GitBinary $GitRepo $GitMail $GitPageFile $GitDebug $GitResult);
|
||||
|
||||
$GitBinary = '/usr/bin/git';
|
||||
AddModuleDescription('git.pl', 'Git Extension');
|
||||
|
||||
$GitBinary = 'git';
|
||||
$GitMail = 'unknown@oddmuse.org';
|
||||
$GitPageFile = 0;
|
||||
|
||||
push(@MyInitVariables, \&GitInitVariables);
|
||||
|
||||
sub GitRun {
|
||||
my $result = '';
|
||||
local *STDOUT;
|
||||
open(STDOUT, '>', \$result) or die "Can't open memory file: $!";
|
||||
system($GitBinary, @_) == 0
|
||||
or ReportError("git failed: $!",
|
||||
"500 INTERNAL SERVER ERROR",
|
||||
undef,
|
||||
$q->p($q->tt(join(' ', $GitBinary, map {
|
||||
if (index($_, ' ') == -1) {
|
||||
$_;
|
||||
} else {
|
||||
"'$_'";
|
||||
}
|
||||
} @_))),
|
||||
$q->pre($result));
|
||||
my $oldDir = cwd;
|
||||
my $exitStatus;
|
||||
# warn join(' ', $GitBinary, @_) . "\n";
|
||||
|
||||
chdir($GitRepo);
|
||||
if ($GitDebug) {
|
||||
# capture the output of the git comand in a temporary file
|
||||
my $fh = File::Temp->new();
|
||||
open(my $oldout, ">&STDOUT") or die "Can't dup STDOUT: $!";
|
||||
open(STDOUT, '>', $fh) or die "Can't redirect STDOUT: $!";
|
||||
# run git in the work directory
|
||||
$exitStatus = system($GitBinary, @_);
|
||||
# read the temporary file with the output
|
||||
close($fh);
|
||||
open(STDOUT, ">&", $oldout) or die "Can't dup \$oldout: $!";
|
||||
open(F, '<', $fh) or die "Can't open temp file for reading: $!";
|
||||
local $/ = undef; # Read complete files
|
||||
$GitResult = <F>;
|
||||
close(F);
|
||||
} else {
|
||||
$exitStatus = system($GitBinary, @_);
|
||||
}
|
||||
chdir($oldDir);
|
||||
return $exitStatus;
|
||||
}
|
||||
|
||||
sub GitInitVariables {
|
||||
@@ -80,39 +105,50 @@ sub GitInitVariables {
|
||||
}
|
||||
|
||||
sub GitInitRepository {
|
||||
if (not -d "$GitRepo/.git") {
|
||||
CreateDir($GitRepo);
|
||||
chdir($GitRepo); # important for all the git commands that follow!
|
||||
GitRun('init', '--quiet');
|
||||
foreach my $id (AllPagesList()) {
|
||||
OpenPage($id);
|
||||
WriteStringToFile("$GitRepo/$id", $Page{text});
|
||||
GitRun('add', $id);
|
||||
}
|
||||
GitRun('commit', '--quiet', '-m', 'initial import',
|
||||
"--author=Oddmuse <$GitMail>");
|
||||
} else {
|
||||
chdir($GitRepo); # important for all the git commands that follow!
|
||||
return if -d "$GitRepo/.git";
|
||||
my $exception = shift;
|
||||
CreateDir($GitRepo);
|
||||
GitRun(qw(init --quiet));
|
||||
# Add legacy pages: If you installed this extension for an older
|
||||
# wiki, all the existing pages need to be added. We do this for all
|
||||
# the pages except for the one we just saved. That page will get a
|
||||
# better author and log message.
|
||||
foreach my $id (AllPagesList()) {
|
||||
next if $id eq $exception;
|
||||
OpenPage($id);
|
||||
WriteStringToFile("$GitRepo/$id", $GitPageFile ? EncodePage(%Page) : $Page{text});
|
||||
GitRun(qw(add --), $id);
|
||||
}
|
||||
GitRun(qw(commit --quiet -m), 'initial import', "--author=Oddmuse <$GitMail>");
|
||||
}
|
||||
|
||||
*GitOldSave = *Save;
|
||||
*Save = *GitNewSave;
|
||||
|
||||
sub GitNewSave {
|
||||
|
||||
# Save is called within lock, with opened page. That's why we cannot
|
||||
# call GitInitRepository right away, because it opens all the legacy
|
||||
# pages to save them, too. We need to save first.
|
||||
GitOldSave(@_);
|
||||
GitInitRepository();
|
||||
my ($id) = @_;
|
||||
WriteStringToFile("$GitRepo/$id", $Page{text});
|
||||
if ($Page{revision} == 1) {
|
||||
GitRun('add', $id);
|
||||
}
|
||||
|
||||
# We also need to save all the data from the open page.
|
||||
my $message = $Page{summary};
|
||||
$message =~ s/^\s+$//;
|
||||
$message ||= T('no summary available');
|
||||
my $author = $Page{username} || T('Anonymous');
|
||||
GitRun('commit', '--quiet', '-m', $message,
|
||||
"--author=$author <$GitMail>", $id);
|
||||
my $data = $GitPageFile ? EncodePage(%Page) : $Page{text};
|
||||
my $id = shift;
|
||||
# GitInitRepository will try to add and commit all the pages already
|
||||
# in the wiki. These are assumed to be legacy pages. The page we
|
||||
# just saved, however, should not be committed as a legacy page
|
||||
# because legacy pages are committed with a default author and log
|
||||
# message!
|
||||
GitInitRepository($id);
|
||||
WriteStringToFile("$GitRepo/$id", $data);
|
||||
GitRun(qw(add --), $id);
|
||||
GitRun(qw(commit --quiet -m), $message,
|
||||
"--author=$author <$GitMail>", '--', $id);
|
||||
}
|
||||
|
||||
*GitOldDeletePage = *DeletePage;
|
||||
@@ -123,11 +159,11 @@ sub GitNewDeletePage {
|
||||
return $error if $error;
|
||||
GitInitRepository();
|
||||
my ($id) = @_;
|
||||
GitRun('rm', '--quiet', '--ignore-unmatch', $id);
|
||||
GitRun(qw(rm --quiet --ignore-unmatch --), $id);
|
||||
my $message = T('page was marked for deletion');
|
||||
my $author = T('Oddmuse');
|
||||
GitRun('commit', '--quiet', '-m', $message,
|
||||
"--author=$author <$GitMail>", $id);
|
||||
GitRun(qw(commit --quiet -m), $message,
|
||||
"--author=$author <$GitMail>", '--', $id);
|
||||
return ''; # no error
|
||||
}
|
||||
|
||||
@@ -140,8 +176,7 @@ sub DoGitCleanup {
|
||||
print GetHeader('', 'Git', '');
|
||||
print $q->start_div({-class=>'content git'});
|
||||
RequestLockOrError();
|
||||
print $q->p(T('Main lock obtained.')), '<p>',
|
||||
T('Cleaning up git repository');
|
||||
print $q->p(T('Main lock obtained.')), '<p>', T('Cleaning up git repository');
|
||||
GitCleanup();
|
||||
ReleaseLock();
|
||||
print $q->p(T('Main lock released.')), $q->end_div();
|
||||
@@ -150,7 +185,7 @@ sub DoGitCleanup {
|
||||
|
||||
sub GitCleanup {
|
||||
if (-d $GitRepo) {
|
||||
print $q->p("Git cleanup starting");
|
||||
print $q->p('Git cleanup starting');
|
||||
AllPagesList();
|
||||
# delete all the files including all the files starting with a dot
|
||||
opendir(DIR, $GitRepo) or ReportError("cannot open directory $GitRepo: $!");
|
||||
@@ -163,20 +198,20 @@ sub GitCleanup {
|
||||
}
|
||||
closedir DIR;
|
||||
# write all the files again, just to be sure
|
||||
print $q->p("Rewriting all the files, just to be sure");
|
||||
print $q->p('Rewriting all the files, just to be sure');
|
||||
foreach my $id (@IndexList) {
|
||||
OpenPage($id);
|
||||
WriteStringToFile("$GitRepo/$id", $Page{text});
|
||||
WriteStringToFile("$GitRepo/$id", $GitPageFile ? EncodePage(%Page) : $Page{text});
|
||||
}
|
||||
# run git!
|
||||
chdir($GitRepo); # important for all the git commands that follow!
|
||||
# add any new files
|
||||
print $q->p("Adding new files, if any");
|
||||
GitRun('add', '.');
|
||||
print $q->p('Adding new files, if any');
|
||||
GitRun(qw(add -A));
|
||||
# commit the new state
|
||||
print $q->p("Committing changes, if any");
|
||||
# try to protect against mysterious crashes
|
||||
print $q->pre(`$GitBinary commit --quiet -a -m 'maintenance job' --author=Oddmuse <$GitMail>` . ' ');
|
||||
print $q->p("Git done");
|
||||
print $q->p('Committing changes, if any');
|
||||
my $exitStatus = GitRun(qw(commit --quiet -m), 'maintenance job',
|
||||
"--author=Oddmuse <$GitMail>");
|
||||
print $q->p('git commit finished with ' . $exitStatus . ' exit status.');
|
||||
print $q->p('Git done');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use vars qw($GoogleCustomSearchEngine);
|
||||
|
||||
$GoogleCustomSearchEngine = 'http://www.google.com/cse?cx=004774160799092323420:6-ff2s0o6yi&q=';
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/google-custom-search.pl">google-custom-search.pl</a></p>';
|
||||
AddModuleDescription('google-custom-search.pl');
|
||||
|
||||
# disable search form
|
||||
sub GetSearchForm {}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/google-search.pl">google-search.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Use_Google_For_Searches">Use Google For Searches</a></p>';
|
||||
AddModuleDescription('google-search.pl', 'Use Google For Searches');
|
||||
|
||||
use vars qw($GoogleSearchDomain $GoogleSearchExclusive);
|
||||
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
# Copyright (C) 2006 Alex Schroeder <alex@emacswiki.org>
|
||||
# Copyright (C) 2006-2014 Alex Schroeder <alex@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 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.
|
||||
# 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.
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/gotobar.pl">gotobar.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Gotobar_Extension">Gotobar Extension</a></p>';
|
||||
AddModuleDescription('gotobar.pl', 'Gotobar Extension');
|
||||
|
||||
use vars qw($GotobarName);
|
||||
|
||||
@@ -32,18 +28,20 @@ sub GotobarInit {
|
||||
$AdminPages{$GotobarName} = 1;
|
||||
if ($IndexHash{$GotobarName}) {
|
||||
OpenPage($GotobarName);
|
||||
return if $DeletedPage && $Page{text} =~ /^\s*$DeletedPage\b/o;
|
||||
return if PageMarkedForDeletion();
|
||||
# Don't use @UserGotoBarPages because this messes up the order of
|
||||
# links for unsuspecting users.
|
||||
@UserGotoBarPages = ();
|
||||
$UserGotoBar = '';
|
||||
my $count = 0;
|
||||
while ($Page{text} =~ m/($LinkPattern|\[\[$FreeLinkPattern\]\]|\[\[$FreeLinkPattern\|([^\]]+)\]\]|\[$InterLinkPattern\s+([^\]]+?)\])/og) {
|
||||
my $page = $2||$3||$4||$6;
|
||||
my $text = $5||$7;
|
||||
while ($Page{text} =~ m/($LinkPattern|\[\[$FreeLinkPattern\]\]|\[\[$FreeLinkPattern\|([^\]]+)\]\]|\[$InterLinkPattern\s+([^\]]+?)\]|\[$FullUrlPattern[|[:space:]]([^\]]+?)\])/og) {
|
||||
my $page = $2||$3||$4||$6||$8;
|
||||
my $text = $5||$7||$9;
|
||||
$UserGotoBar .= ' ' if $UserGotoBar;
|
||||
if ($6) {
|
||||
$UserGotoBar .= GetInterLink($page, $text);
|
||||
} elsif ($8) {
|
||||
$UserGotoBar .= GetUrl($page, $text);
|
||||
} else {
|
||||
$UserGotoBar .= GetPageLink($page, $text);
|
||||
# The first local page is the homepage, the second local page
|
||||
@@ -58,4 +56,3 @@ sub GotobarInit {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/gravatar.pl">gravatar.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Gravatar">Gravatar</a></p>';
|
||||
AddModuleDescription('gravatar.pl', 'Gravatar');
|
||||
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
|
||||
@@ -26,7 +26,7 @@ push(@MyRules, \&GravatarRule);
|
||||
sub GravatarRule {
|
||||
if ($bol && m!\G$gravatar_regexp!cog) {
|
||||
my $url = $1;
|
||||
my $gravatar = "http://www.gravatar.com/avatar/$3";
|
||||
my $gravatar = "https://secure.gravatar.com/avatar/$3";
|
||||
my $name = FreeToNormal($2);
|
||||
$url = ScriptUrl($name) unless $url;
|
||||
return $q->span({-class=>"portrait gravatar"},
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/grep.pl">grep.pl</a></p>';
|
||||
AddModuleDescription('grep.pl');
|
||||
|
||||
push(@MyRules, \&GrepRule);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/header-and-footer-templates.pl">header-and-footer-templates.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Comments_on_HTML_Templates">Comments on HTML Templates</a></p>';
|
||||
AddModuleDescription('header-and-footer-templates.pl', 'Comments on HTML Templates');
|
||||
|
||||
use vars qw($HtmlTemplateDir);
|
||||
use HTML::Template;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place, Suite 330
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
$ModulesDescription .= '<p><a href="http://git.savannah.gnu.org/cgit/oddmuse.git/tree/modules/headers.pl">headers.pl</a>, see <a href="http://www.oddmuse.org/cgi-bin/oddmuse/Header_Markup_Extension">Header Markup Extension</a></p>';
|
||||
AddModuleDescription('headers.pl', 'Header Markup Extension');
|
||||
|
||||
# After toc.pl but before usemod.pl
|
||||
push(@MyRules, \&HeadersRule);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user