aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IkiWiki.pm17
-rw-r--r--IkiWiki/CGI.pm6
-rw-r--r--IkiWiki/Plugin/calendar.pm270
-rw-r--r--IkiWiki/Plugin/mirrorlist.pm2
-rw-r--r--IkiWiki/Render.pm1
-rw-r--r--debian/NEWS12
-rw-r--r--debian/changelog17
-rw-r--r--debian/control2
-rw-r--r--doc/bugs/Impossible_to_resize_text_input_in_search_results.mdwn2
-rw-r--r--doc/bugs/More_mobile_friendly_default_themes.mdwn24
-rw-r--r--doc/bugs/Spam:_recent_changes_discussion.mdwn35
-rw-r--r--doc/bugs/outdated_jquery-ui.mdwn10
-rw-r--r--doc/forum/OpenID_not_working___47___where_to_define_wiki__39__s_ID__63__/comment_5_af8c6f5cdebae6e72d9d8eb9011a9dbf._comment8
-rw-r--r--doc/forum/global__95__sidebars_breaks_my_web_setup_page.mdwn8
-rw-r--r--doc/forum/global__95__sidebars_breaks_my_web_setup_page/comment_1_5af6f470cc568fa7139d43a896763767._comment9
-rw-r--r--doc/git.mdwn1
-rw-r--r--doc/ikiwiki-calendar.mdwn7
-rw-r--r--doc/ikiwiki/directive/calendar.mdwn21
-rw-r--r--doc/ikiwikiusers.mdwn3
-rw-r--r--doc/plugins/calendar.mdwn23
-rw-r--r--doc/style.css45
-rw-r--r--doc/tipjar.mdwn1
-rw-r--r--doc/tips/nearlyfreespeech/discussion.mdwn17
-rw-r--r--doc/todo/Fenced_code_blocks___40__from_GitHub_Flavored_Markdown__41__.mdwn2
-rw-r--r--doc/todo/Let_plugins_influence_what_environment_variables_a_wrapper_will_preserve.mdwn50
-rw-r--r--doc/todo/calendar_autocreate.mdwn2
-rw-r--r--doc/todo/generate_HTML5_by_default.mdwn2
-rw-r--r--doc/todo/support_multiple_perl_libraries.mdwn36
-rw-r--r--doc/users/james.mdwn1
-rw-r--r--doc/users/mjd.mdwn5
-rwxr-xr-xikiwiki-comment.in4
-rwxr-xr-xt/html.t30
-rwxr-xr-xt/img.t3
-rwxr-xr-xt/relativity.t189
-rwxr-xr-xt/wellformed.t50
-rw-r--r--templates/googleform.tmpl2
-rw-r--r--templates/page.tmpl13
-rw-r--r--templates/searchform.tmpl2
-rw-r--r--templates/searchquery.tmpl4
-rw-r--r--themes/actiontabs/style.css10
-rw-r--r--themes/blueview/style.css27
-rw-r--r--themes/monochrome/style.css1
42 files changed, 713 insertions, 261 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm
index 9e2eb0b1a..7c55764be 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -5,6 +5,7 @@ package IkiWiki;
use warnings;
use strict;
use Encode;
+use Fcntl q{:flock};
use URI::Escape q{uri_escape_utf8};
use POSIX ();
use Storable;
@@ -274,7 +275,7 @@ sub getsetup () {
html5 => {
type => "boolean",
default => 0,
- description => "generate HTML5?",
+ description => "use elements new in HTML5 like <section>?",
advanced => 0,
safe => 1,
rebuild => 1,
@@ -549,6 +550,13 @@ sub getsetup () {
safe => 0,
rebuild => 0,
},
+ responsive_layout => {
+ type => "boolean",
+ default => 1,
+ description => "theme has a responsive layout? (mobile-optimized)",
+ safe => 1,
+ rebuild => 1,
+ },
}
sub getlibdirs () {
@@ -1822,8 +1830,11 @@ sub lockwiki () {
}
open($wikilock, '>', "$config{wikistatedir}/lockfile") ||
error ("cannot write to $config{wikistatedir}/lockfile: $!");
- if (! flock($wikilock, 2)) { # LOCK_EX
- error("failed to get lock");
+ if (! flock($wikilock, LOCK_EX | LOCK_NB)) {
+ debug("failed to get lock; waiting...");
+ if (! flock($wikilock, LOCK_EX)) {
+ error("failed to get lock");
+ }
}
return 1;
}
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index f448db6ef..61af830f8 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -67,9 +67,6 @@ sub cgitemplate ($$$;@) {
if (exists $params{page}) {
$page=delete $params{page};
$params{forcebaseurl}=urlto($page);
- if (! $config{html5}) {
- $params{forcebaseurl}=urlabs($params{forcebaseurl}, $topurl);
- }
}
run_hooks(pagetemplate => sub {
shift->(
@@ -81,9 +78,6 @@ sub cgitemplate ($$$;@) {
templateactions($template, "");
my $baseurl = baseurl();
- if (! $config{html5}) {
- $baseurl = urlabs($baseurl, $topurl),
- }
$template->param(
dynamic => 1,
diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm
index 4df7070ac..23246757b 100644
--- a/IkiWiki/Plugin/calendar.pm
+++ b/IkiWiki/Plugin/calendar.pm
@@ -25,11 +25,17 @@ use Time::Local;
my $time=time;
my @now=localtime($time);
+my %changed;
sub import {
+ hook(type => "checkconfig", id => "calendar", call => \&checkconfig);
hook(type => "getsetup", id => "calendar", call => \&getsetup);
hook(type => "needsbuild", id => "calendar", call => \&needsbuild);
hook(type => "preprocess", id => "calendar", call => \&preprocess);
+ hook(type => "scan", id => "calendar", call => \&scan);
+ hook(type => "build_affected", id => "calendar", call => \&build_affected);
+
+ IkiWiki::loadplugin("transient");
}
sub getsetup () {
@@ -49,11 +55,41 @@ sub getsetup () {
archive_pagespec => {
type => "pagespec",
example => "page(posts/*) and !*/Discussion",
- description => "PageSpec of pages to include in the archives; used by ikiwiki-calendar command",
+ description => "PageSpec of pages to include in the archives, if option `calendar_autocreate` is true.",
link => 'ikiwiki/PageSpec',
safe => 1,
rebuild => 0,
},
+ calendar_autocreate => {
+ type => "boolean",
+ example => 1,
+ description => "autocreate new calendar pages?",
+ safe => 1,
+ rebuild => undef,
+ },
+ calendar_fill_gaps => {
+ type => "boolean",
+ example => 1,
+ default => 1,
+ description => "if set, when building calendar pages, also build pages of year and month when no pages were published (building empty calendars).",
+ safe => 1,
+ rebuild => 0,
+ },
+}
+
+sub checkconfig () {
+ if (! defined $config{calendar_autocreate}) {
+ $config{calendar_autocreate} = defined $config{archivebase};
+ }
+ if (! defined $config{archive_pagespec}) {
+ $config{archive_pagespec} = '*';
+ }
+ if (! defined $config{archivebase}) {
+ $config{archivebase} = 'archives';
+ }
+ if (! defined $config{calendar_fill_gaps}) {
+ $config{calendar_fill_gaps} = 1;
+ }
}
sub is_leap_year (@) {
@@ -70,6 +106,184 @@ sub month_days {
return $days_in_month;
}
+sub build_affected {
+ my %affected;
+ my ($ayear, $amonth, $valid);
+
+ foreach my $year (keys %changed) {
+ ($ayear, $valid) = nextyear($year, $config{archivebase});
+ $affected{calendarlink($ayear)} = sprintf(gettext("building calendar for %s, its previous or next year has changed"), $ayear) if ($valid);
+ ($ayear, $valid) = previousyear($year, $config{archivebase});
+ $affected{calendarlink($ayear)} = sprintf(gettext("building calendar for %s, its previous or next year has changed"), $ayear) if ($valid);
+ foreach my $month (keys $changed{$year}) {
+ ($ayear, $amonth, $valid) = nextmonth($year, $month, $config{archivebase});
+ $affected{calendarlink($ayear, sprintf("%02d", $amonth))} = sprintf(gettext("building calendar for %s/%s, its previous or next month has changed"), $amonth, $ayear) if ($valid);
+ ($ayear, $amonth, $valid) = previousmonth($year, $month, $config{archivebase});
+ $affected{calendarlink($ayear, sprintf("%02d", $amonth))} = sprintf(gettext("building calendar for %s/%s, its previous or next month has changed"), $amonth, $ayear) if ($valid);
+ }
+ }
+
+ return %affected;
+}
+
+sub autocreate {
+ my ($page, $pagefile, $year, $month) = @_;
+ my $message=sprintf(gettext("creating calendar page %s"), $page);
+ debug($message);
+
+ my $template;
+ if (defined $month) {
+ $template=template("calendarmonth.tmpl");
+ } else {
+ $template=template("calendaryear.tmpl");
+ }
+ $template->param(year => $year);
+ $template->param(month => $month) if defined $month;
+ $template->param(pagespec => $config{archive_pagespec});
+
+ my $dir = $IkiWiki::Plugin::transient::transientdir;
+
+ writefile($pagefile, $dir, $template->output);
+}
+
+sub calendarlink($;$) {
+ my ($year, $month) = @_;
+ if (defined $month) {
+ return $config{archivebase} . "/" . $year . "/" . $month;
+ } else {
+ return $config{archivebase} . "/" . $year;
+ }
+}
+
+sub gencalendarmonth{
+ my $year = shift;
+ my $month = sprintf("%02d", shift);
+
+ my $page = calendarlink($year, $month);
+ my $pagefile = newpagefile($page, $config{default_pageext});
+ add_autofile(
+ $pagefile, "calendar",
+ sub {return autocreate($page, $pagefile, $year, $month);}
+ );
+}
+
+sub gencalendaryear {
+ my $year = shift;
+ my %params = @_;
+
+ # Building year page
+ my $page = calendarlink($year);
+ my $pagefile = newpagefile($page, $config{default_pageext});
+ add_autofile(
+ $pagefile, "calendar",
+ sub {return autocreate($page, $pagefile, $year);}
+ );
+
+ if (not exists $wikistate{calendar}{minyear}) {
+ $wikistate{calendar}{minyear} = $year;
+ }
+ if (not exists $wikistate{calendar}{maxyear}) {
+ $wikistate{calendar}{maxyear} = $year;
+ }
+
+ if ($config{calendar_fill_gaps}) {
+ # Building month pages
+ foreach my $month (1 .. 12) {
+ gencalendarmonth($year, $month);
+ }
+
+ # Filling potential gaps in years (e.g. calendar goes from 2010 to 2014,
+ # and we just added year 2005. We have to add years 2006 to 2009).
+ return if $params{norecurse};
+ if ($wikistate{calendar}{minyear} > $year) {
+ foreach my $other ($year + 1 .. $wikistate{calendar}{minyear} - 1) {
+ gencalendaryear($other, norecurse => 1);
+ }
+ $wikistate{calendar}{minyear} = $year;
+ }
+ if ($wikistate{calendar}{maxyear} < $year) {
+ foreach my $other ($wikistate{calendar}{maxyear} + 1 .. $year - 1) {
+ gencalendaryear($other, norecurse => 1);
+ }
+ $wikistate{calendar}{maxyear} = $year;
+ }
+ }
+ if ($year < $wikistate{calendar}{minyear}) {
+ $wikistate{calendar}{minyear} = $year;
+ }
+ if ($year > $wikistate{calendar}{maxyear}) {
+ $wikistate{calendar}{maxyear} = $year;
+ }
+}
+
+sub previousmonth($$$) {
+ my $year = shift;
+ my $month = shift;
+ my $archivebase = shift;
+
+ if (not exists $wikistate{calendar}{minyear}) {
+ $wikistate{calendar}{minyear} = $year;
+ }
+
+ my $pmonth = $month;
+ my $pyear = $year;
+ while ((not exists $pagesources{"$archivebase/$pyear/" . sprintf("%02d", $pmonth)}) or ($pmonth == $month and $pyear == $year)) {
+ $pmonth -= 1;
+ if ($pmonth == 0) {
+ $pyear -= 1;
+ $pmonth = 12;
+ return ($pyear, $pmonth, 0) unless $pyear >= $wikistate{calendar}{minyear};
+ }
+ }
+ return ($pyear, $pmonth, 1);
+}
+
+sub nextmonth($$$) {
+ my $year = shift;
+ my $month = shift;
+ my $archivebase = shift;
+
+ if (not exists $wikistate{calendar}{maxyear}) {
+ $wikistate{calendar}{maxyear} = $year;
+ }
+
+ my $nmonth = $month;
+ my $nyear = $year;
+ while ((not exists $pagesources{"$archivebase/$nyear/" . sprintf("%02d", $nmonth)}) or ($nmonth == $month and $nyear == $year)) {
+ $nmonth += 1;
+ if ($nmonth == 13) {
+ $nyear += 1;
+ $nmonth = 1;
+ return ($nyear, $nmonth, 0) unless $nyear <= $wikistate{calendar}{maxyear};
+ }
+ }
+ return ($nyear, $nmonth, 1);
+}
+
+sub previousyear($$) {
+ my $year = shift;
+ my $archivebase = shift;
+
+ my $pyear = $year - 1;
+ while (not exists $pagesources{"$archivebase/$pyear"}) {
+ $pyear -= 1;
+ return ($pyear, 0) unless ($pyear >= $wikistate{calendar}{minyear});
+ }
+ return ($pyear, 1);
+}
+
+sub nextyear($$) {
+ my $year = shift;
+ my $archivebase = shift;
+
+ my $nyear = $year + 1;
+ while (not exists $pagesources{"$archivebase/$nyear"}) {
+ $nyear += 1;
+ return ($nyear, 0) unless ($nyear <= $wikistate{calendar}{maxyear});
+ }
+ return ($nyear, 1);
+}
+
sub format_month (@) {
my %params=@_;
@@ -92,20 +306,12 @@ sub format_month (@) {
push(@{$linkcache{"$year/$mtag/$mday"}}, $p);
}
- my $pmonth = $params{month} - 1;
- my $nmonth = $params{month} + 1;
- my $pyear = $params{year};
- my $nyear = $params{year};
-
- # Adjust for January and December
- if ($params{month} == 1) {
- $pmonth = 12;
- $pyear--;
- }
- if ($params{month} == 12) {
- $nmonth = 1;
- $nyear++;
- }
+ my $archivebase = 'archives';
+ $archivebase = $config{archivebase} if defined $config{archivebase};
+ $archivebase = $params{archivebase} if defined $params{archivebase};
+
+ my ($pyear, $pmonth, $pvalid) = previousmonth($params{year}, $params{month}, $archivebase);
+ my ($nyear, $nmonth, $nvalid) = nextmonth($params{year}, $params{month}, $archivebase);
# Add padding.
$pmonth=sprintf("%02d", $pmonth);
@@ -129,10 +335,6 @@ sub format_month (@) {
my $pmonthname=strftime_utf8("%B", localtime(timelocal(0,0,0,1,$pmonth-1,$pyear-1900)));
my $nmonthname=strftime_utf8("%B", localtime(timelocal(0,0,0,1,$nmonth-1,$nyear-1900)));
- my $archivebase = 'archives';
- $archivebase = $config{archivebase} if defined $config{archivebase};
- $archivebase = $params{archivebase} if defined $params{archivebase};
-
# Calculate URL's for monthly archives.
my ($url, $purl, $nurl)=("$monthname $params{year}",'','');
if (exists $pagesources{"$archivebase/$params{year}/$params{month}"}) {
@@ -274,7 +476,7 @@ EOF
sub format_year (@) {
my %params=@_;
-
+
my @post_months;
foreach my $p (pagespec_match_list($params{page},
"creation_year($params{year}) and ($params{pages})",
@@ -290,18 +492,18 @@ sub format_year (@) {
}
my $calendar="\n";
+
+ my $archivebase = 'archives';
+ $archivebase = $config{archivebase} if defined $config{archivebase};
+ $archivebase = $params{archivebase} if defined $params{archivebase};
- my $pyear = $params{year} - 1;
- my $nyear = $params{year} + 1;
+ my ($pyear, $pvalid) = previousyear($params{year}, $archivebase);
+ my ($nyear, $nvalid) = nextyear($params{year}, $archivebase);
my $thisyear = $now[5]+1900;
my $future_month = 0;
$future_month = $now[4]+1 if $params{year} == $thisyear;
- my $archivebase = 'archives';
- $archivebase = $config{archivebase} if defined $config{archivebase};
- $archivebase = $params{archivebase} if defined $params{archivebase};
-
# calculate URL's for previous and next years
my ($url, $purl, $nurl)=("$params{year}",'','');
if (exists $pagesources{"$archivebase/$params{year}"}) {
@@ -431,6 +633,7 @@ sub preprocess (@) {
}
$params{month} = sprintf("%02d", $params{month});
+ $changed{$params{year}}{$params{month}} = 1;
if ($params{type} eq 'month' && $params{year} == $thisyear
&& $params{month} == $thismonth) {
@@ -508,7 +711,22 @@ sub needsbuild (@) {
}
}
}
+
return $needsbuild;
}
+sub scan (@) {
+ my %params=@_;
+ my $page=$params{page};
+
+ return unless $config{calendar_autocreate};
+
+ # Check if year pages have to be generated
+ if (pagespec_match($page, $config{archive_pagespec})) {
+ my @ctime = localtime($IkiWiki::pagectime{$page});
+ gencalendaryear($ctime[5]+1900);
+ gencalendarmonth($ctime[5]+1900, $ctime[4]+1);
+ }
+}
+
1
diff --git a/IkiWiki/Plugin/mirrorlist.pm b/IkiWiki/Plugin/mirrorlist.pm
index b7e532485..5afd9ec1a 100644
--- a/IkiWiki/Plugin/mirrorlist.pm
+++ b/IkiWiki/Plugin/mirrorlist.pm
@@ -53,7 +53,7 @@ sub pagetemplate (@) {
sub mirrorlist ($) {
my $page=shift;
- return ($config{html5} ? '<nav id="mirrorlist">' : '<div>').
+ return ($config{html5} ? '<nav' : '<div').' id="mirrorlist">'.
(keys %{$config{mirrorlist}} > 1 ? gettext("Mirrors") : gettext("Mirror")).
": ".
join(", ",
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 9d6f636a2..c1a3dcbf2 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -134,6 +134,7 @@ sub genpage ($$) {
ctime => displaytime($pagectime{$page}, undef, 1),
baseurl => baseurl($page),
html5 => $config{html5},
+ responsive_layout => $config{responsive_layout},
);
run_hooks(pagetemplate => sub {
diff --git a/debian/NEWS b/debian/NEWS
index ff856e5f0..75e8b184c 100644
--- a/debian/NEWS
+++ b/debian/NEWS
@@ -1,3 +1,15 @@
+ikiwiki (3.20141201) UNRELEASED; urgency=medium
+
+ By default, this version of IkiWiki tells mobile browsers that its
+ layout is suitable for small screens. The default layout and the
+ actiontabs, blueview, goldtype and monochrome themes have been adjusted.
+
+ If you have custom CSS that does not work in a small window (a typical
+ phone is 320 to 400 CSS pixels wide), please set the new responsive_layout
+ config option to 0.
+
+ -- Simon McVittie <smcv@debian.org> Mon, 01 Dec 2014 16:04:41 +0000
+
ikiwiki (3.20110122) unstable; urgency=low
If you have custom CSS that uses "#feedlinks" or "#blogform", you will
diff --git a/debian/changelog b/debian/changelog
index 014066e32..afe3bb578 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,6 @@
ikiwiki (3.20141017) UNRELEASED; urgency=medium
+ [ Joey Hess ]
* Added ikiwiki-comment program.
* Add missing build-depends on libcgi-formbuilder-perl, needed for
t/relativity.t
@@ -7,6 +8,22 @@ ikiwiki (3.20141017) UNRELEASED; urgency=medium
* Set Debian package maintainer to Simon McVittie as I'm retiring from
Debian.
+ [ Simon McVittie ]
+ * calendar: add calendar_autocreate option, with which "ikiwiki --refresh"
+ can mostly supersede the ikiwiki-calendar command.
+ Thanks, Louis Paternault
+ * search: add more classes as a hook for CSS. Thanks, sajolida
+ * core: generate HTML5 by default, but keep avoiding new elements
+ like <section> that require specific browser support unless html5 is
+ set to 1.
+ * Tell mobile browsers to draw our pages in a device-sized viewport,
+ not an 800-1000px viewport designed to emulate a desktop/laptop browser.
+ * Add new responsive_layout option which can be set to 0 if your custom
+ CSS only works in a large viewport.
+ * style.css, actiontabs, blueview, goldtype, monochrome: adjust layout
+ below 600px ("responsive layout") so that horizontal scrolling is not
+ needed on smartphone browsers or other small viewports.
+
-- Joey Hess <joeyh@debian.org> Mon, 20 Oct 2014 12:04:49 -0400
ikiwiki (3.20141016) unstable; urgency=medium
diff --git a/debian/control b/debian/control
index 78bb68341..a5cac3c01 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,7 @@ Build-Depends: perl, debhelper (>= 9)
Build-Depends-Indep: dpkg-dev (>= 1.9.0), libxml-simple-perl,
libtext-markdown-discount-perl,
libtimedate-perl, libhtml-template-perl,
- libhtml-scrubber-perl, wdg-html-validator,
+ libhtml-scrubber-perl,
libhtml-parser-perl, liburi-perl (>= 1.36), perlmagick, po4a (>= 0.34),
libfile-chdir-perl, libyaml-libyaml-perl, librpc-xml-perl,
libcgi-pm-perl, libcgi-session-perl, ghostscript,
diff --git a/doc/bugs/Impossible_to_resize_text_input_in_search_results.mdwn b/doc/bugs/Impossible_to_resize_text_input_in_search_results.mdwn
index 0cc5aca26..68e49b938 100644
--- a/doc/bugs/Impossible_to_resize_text_input_in_search_results.mdwn
+++ b/doc/bugs/Impossible_to_resize_text_input_in_search_results.mdwn
@@ -43,3 +43,5 @@ Here is a patch:
<hr>
--
2.1.1
+
+> [[Applied|done]], thanks --[[smcv]]
diff --git a/doc/bugs/More_mobile_friendly_default_themes.mdwn b/doc/bugs/More_mobile_friendly_default_themes.mdwn
index fa25814ec..8eeae413d 100644
--- a/doc/bugs/More_mobile_friendly_default_themes.mdwn
+++ b/doc/bugs/More_mobile_friendly_default_themes.mdwn
@@ -11,6 +11,10 @@ http://source.ikiwiki.branchable.com/?p=source.git;a=blob;f=templates/page.tmpl;
> a proportion of desktop browsers, rather than being responsive to window
> size like they should have been all along. --[[smcv]]
+>> Fixed in master. It is currently on by default, but people with
+>> customized CSS that doesn't scale nicely can put
+>> `responsive_layout => 0` in the config to turn it off. --[[smcv]]
+
Further more:
* fonts need to be tweaked
@@ -21,10 +25,30 @@ Further more:
> anti-theme; enhancing the other themes would be OK though.)
> --[[smcv]]
+ >> With git master, the layout and font sizes seem appropriate on my
+ >> Galaxy Nexus (360 CSS pixels wide), and on simulated devices
+ >> 320 device pixels wide (e.g. the first couple of iPhone models)
+ >> in Chromium's developer tools. [[done]]
+ >>
+ >> Test sites:
+ >>
+ >> * <http://actiontabs.hosted.pseudorandom.co.uk/>
+ >> * <http://blueview.hosted.pseudorandom.co.uk/>
+ >> * <http://goldtype.hosted.pseudorandom.co.uk/>
+ >> * <http://monochrome.hosted.pseudorandom.co.uk/>
+ >> * <http://unthemed.hosted.pseudorandom.co.uk/>
+ >>
+ >> If stylistic changes are needed, please open another issue with a
+ >> suggested patch.
+ >> --[[smcv]]
+
* XHTML should be dropped !
> Already in the to-do list: [[todo/generate HTML5 by default]]. --[[smcv]]
+ >> Next version will always generate HTML5, unless someone overrules me.
+ >> --[[smcv]]
+
I'm practicing this on http://dabase.com/ with <http://source.dabase.branchable.com/?p=source.git;a=blob;f=templates/page.tmpl;>
> [[!format diff """
diff --git a/doc/bugs/Spam:_recent_changes_discussion.mdwn b/doc/bugs/Spam:_recent_changes_discussion.mdwn
index cdaa5b85c..f0363745b 100644
--- a/doc/bugs/Spam:_recent_changes_discussion.mdwn
+++ b/doc/bugs/Spam:_recent_changes_discussion.mdwn
@@ -5,3 +5,38 @@ see <http://www.dk0tu.de/recentchanges/discussion/>
The content is changing frequently without being checked into the git repository. Any ideas?
--[[bastla]]
+
+> Please check your web server logs for any error messages from the CGI.
+> It seems likely that the spammer is editing that page but the changes
+> are somehow not getting committed or pushed.
+>
+> I can't tell you much without knowing details of your setup.
+> For instance, are you using the suggested git repository setup
+> shown in the diagram on the [[rcs/git]] page, or something
+> different? Can you publish a (possibly censored) setup file somewhere?
+>
+> It would probably also be worthwhile to compare the git history of
+> `srcdir/.git` with the git history of the bare repository, if you
+> have one.
+>
+> To recover, you could undo the spam in the `srcdir` (as the user ID
+> that owns the wiki), commit that, and merge with the bare repository
+> if necessary.
+>
+> ----
+>
+> When I tried editing the spammed page to clear it, I got this error:
+>
+> Error: /srv/www/Kurse/AFu-Lizenz/e09.tex independently created, not overwriting with version from Kurse/AFu-Lizenz/e09.tex
+>
+> Your srcdir and destdir seem to have got out of sync. You might need
+> to rebuild the wiki.
+>
+> (I think I'd have received the same error for *any* edit right now.)
+>
+> If you're going to enable completely anonymous editing, I
+> recommend monitoring the wiki more carefully. It might be useful
+> to enable the `syslog` option so that wiki errors go to the
+> system log.
+>
+> --[[smcv]]
diff --git a/doc/bugs/outdated_jquery-ui.mdwn b/doc/bugs/outdated_jquery-ui.mdwn
new file mode 100644
index 000000000..41d3f1b21
--- /dev/null
+++ b/doc/bugs/outdated_jquery-ui.mdwn
@@ -0,0 +1,10 @@
+ < thm> joeyh: ping
+ < thm> can you update the embedded jquery-ui? (for cve
+ 2010-5312, and/or 2012-6662)
+
+I'll do this next time I spend some time on ikiwiki unless Joey or
+Amitai gets there first.
+
+It doesn't look as though we actually use the vulnerable functionality.
+
+--[[smcv]]
diff --git a/doc/forum/OpenID_not_working___47___where_to_define_wiki__39__s_ID__63__/comment_5_af8c6f5cdebae6e72d9d8eb9011a9dbf._comment b/doc/forum/OpenID_not_working___47___where_to_define_wiki__39__s_ID__63__/comment_5_af8c6f5cdebae6e72d9d8eb9011a9dbf._comment
new file mode 100644
index 000000000..2c909ab48
--- /dev/null
+++ b/doc/forum/OpenID_not_working___47___where_to_define_wiki__39__s_ID__63__/comment_5_af8c6f5cdebae6e72d9d8eb9011a9dbf._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="http://www.globalclue.com/"
+ nickname="Dion"
+ subject="comment 5"
+ date="2014-12-08T17:44:49Z"
+ content="""
+I tried just now and it does work, and it is quite surprising
+"""]]
diff --git a/doc/forum/global__95__sidebars_breaks_my_web_setup_page.mdwn b/doc/forum/global__95__sidebars_breaks_my_web_setup_page.mdwn
new file mode 100644
index 000000000..d1d350552
--- /dev/null
+++ b/doc/forum/global__95__sidebars_breaks_my_web_setup_page.mdwn
@@ -0,0 +1,8 @@
+After enabling "Show sidebar on all pages" (global_sidebars) I can no longer access the setup page via the web interface.
+
+The rest of the wiki continues to work, but only "Content-type: text/html" gets sent for this page.
+
+* Fresh ikiwiki --setup of 3.20141016-1
+* Nginx
+
+Would this be something I'm doing wrong or a bug?
diff --git a/doc/forum/global__95__sidebars_breaks_my_web_setup_page/comment_1_5af6f470cc568fa7139d43a896763767._comment b/doc/forum/global__95__sidebars_breaks_my_web_setup_page/comment_1_5af6f470cc568fa7139d43a896763767._comment
new file mode 100644
index 000000000..b75b5e850
--- /dev/null
+++ b/doc/forum/global__95__sidebars_breaks_my_web_setup_page/comment_1_5af6f470cc568fa7139d43a896763767._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://smcv.pseudorandom.co.uk/"
+ nickname="smcv"
+ subject="more info needed"
+ date="2014-11-27T12:14:56Z"
+ content="""
+That sounds like a bug. Please check your web server log for warnings
+or error messages from the CGI script.
+"""]]
diff --git a/doc/git.mdwn b/doc/git.mdwn
index ed0224723..1e67ba2e5 100644
--- a/doc/git.mdwn
+++ b/doc/git.mdwn
@@ -81,6 +81,7 @@ think about merging them. This is recommended. :-)
* [[mhameed]] `git://github.com/mhameed/ikiwiki.git`
* [[spalax]] `git://github.com/paternal/ikiwiki.git` ([[browse|https://github.com/paternal/ikiwiki]])
* [[jcflack]] `git://github.com/jcflack/ikiwiki.git`
+* [[users/mjd]] `https://github.com/mjdominus/ikiwiki.git` ([[browse|https://github.com/mjdominus/ikiwiki]])
## branches
diff --git a/doc/ikiwiki-calendar.mdwn b/doc/ikiwiki-calendar.mdwn
index d311a1859..fd3244694 100644
--- a/doc/ikiwiki-calendar.mdwn
+++ b/doc/ikiwiki-calendar.mdwn
@@ -46,6 +46,13 @@ An example crontab:
This command uses two [[templates]] to generate
the pages, `calendarmonth.tmpl` and `calendaryear.tmpl`.
+# [[plugins/calendar]] setup option
+
+Most of the goals of this command can be replaced by setting up
+`calendar_autocreate` setup option (of plugin [[plugins/calendar]]), and
+running `ikiwiki -setup you.setup`. The only thing that `ikiwiki-calendar` can
+do and that `ikiwiki` cannot is forcing page generation (using `-f` switch).
+
# AUTHOR
Joey Hess <joey@ikiwiki.info>
diff --git a/doc/ikiwiki/directive/calendar.mdwn b/doc/ikiwiki/directive/calendar.mdwn
index cb40f884e..4c2b99ccb 100644
--- a/doc/ikiwiki/directive/calendar.mdwn
+++ b/doc/ikiwiki/directive/calendar.mdwn
@@ -25,14 +25,23 @@ in the sidebar, you'll also need to create these archive pages. They
typically use this directive to display a calendar, and also use [[inline]]
to display or list pages created in the given time frame.
-The `ikiwiki-calendar` command can be used to automatically generate the
-archive pages. It also refreshes the wiki, updating the calendars to
-highlight the current day. This command is typically run at midnight from
-cron.
+## Generating archive pages
+
+If [[!iki plugins/calendar desc=option]] `calendar_autocreate` is not set, the
+[[!iki ikiwiki-calendar]] command can be used to automatically generate the archive
+pages. It also refreshes the wiki, updating the calendars to highlight the
+current day. This command is typically run at midnight from cron.
An example crontab:
- 0 0 * * * ikiwiki-calendar ~/ikiwiki.setup "posts/* and !*/Discussion"
+ 0 0 * * * ikiwiki-calendar ~/ikiwiki.setup "posts/* and !*/Discussion"
+
+
+With [[!iki plugins/calendar desc="setup option"]] `calendar_autocreate`,
+all this work is done by `ikiwiki` itself. Thus, the crontab command can be
+replaced by:
+
+ 0 0 * * * ikiwiki --setup ~/ikiwiki.setup --refresh
## usage
@@ -45,7 +54,7 @@ An example crontab:
for the whole wiki by setting `archivebase` in ikiwiki's setup file.
Calendars link to pages under here, with names like "2010/04" and
"2010". These pages can be automatically created using the
- `ikiwiki-calendar` program.
+ `calendar_autocreate` [[!iki plugins/calendar desc="setup option"]].
* `year` - The year for which the calendar is requested. Defaults to the
current year. Can also use -1 to refer to last year, and so on.
* `month` - The numeric month for which the calendar is requested, in the
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index e3a500242..a8ae0ffec 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -185,7 +185,6 @@ Personal sites and blogs
* [L'Altro Wiki](http://laltromondo.dynalias.net/~iki/) Tutorials, reviews, miscellaneus articles in English and Italian.
* gregoa's [p.r. - political rants](http://info.comodo.priv.at/pr/)
* [Michael Hammer](http://www.michael-hammer.at/)
-* [Richardson Family Wiki](http://the4richardsons.com) A wiki, blog or some such nonsense for the family home page or something or other... I will eventually move the rest of my sites to ikiwiki. The source of the site is in git.
* [The personal website of Andrew Back](http://carrierdetect.com)
* [Paul Elms](http://paul.elms.pro) Personal site and blog in russian.
* [Salient Dream](http://www.salientdream.com/) - All Things Strange.
@@ -205,4 +204,4 @@ Personal sites and blogs
* [KheOps's blog](https://w.ceops.eu/words/)
* [Stig Sandbeck Mathisen](http://fnord.no/) - Personal site and blog, with a bootstrap theme, and varnish frontend.
* Kalle Söderman: [Seen Architecture](http://img.kalleswork.net), [Stockholm Project](http://stockholm.kalleswork.net) - Mainly -image galleries using the album and osm plugins with a customized html5 theme.
-
+* [James Technotes](http://jamestechnotes.com), my [wiki](http://jamestechnotes.com) and [blog](http://jamestechnotes.com/blog).
diff --git a/doc/plugins/calendar.mdwn b/doc/plugins/calendar.mdwn
index 76e718a3b..8d18ed081 100644
--- a/doc/plugins/calendar.mdwn
+++ b/doc/plugins/calendar.mdwn
@@ -5,7 +5,28 @@ This plugin provides a [[ikiwiki/directive/calendar]] [[ikiwiki/directive]].
The directive displays a calendar, similar to the typical calendars shown on
some blogs.
-The [[ikiwiki-calendar]] command is used to keep the calendar up-to-date.
+The [[ikiwiki-calendar]] command is used to force generating year and month
+pages from templates (overriding the existing ones).
+
+## Setup options
+
+* `archivebase` - Default value for [[ikiwiki/directive/calendar]] directive
+ option of the same name.
+* `archive_pagespec` - [[ikiwiki/PageSpec]] of pages to include in the
+ archives, if option `calendar_autocreate` is on. It defaults to `*`.
+* `calendar_autocreate` - Control whether new archive pages are created as
+ needed. It defaults to being done only if option `archivebase` is set.
+* `calendar_fill_gaps` - If set (and `calendar_autocreate` is set as well),
+ build calendar pages of empty years and months (but does not build pages older
+ than the older page, and younger than the younger page of the pagespec). If
+ not, those empty calendar pages will be skipped. *Please note:*
+ * The archive pages will not be automatically updated if this option changes.
+ It is up to the user to delete relevant pages, and rebuild the wiki.
+ * When `calendar_fill_gaps` is set, and a post is deleted, making the
+ corresponding year/month empty, the corresponding page is left, and shows
+ an empty calendar. This is on purpose, not to break any external link
+ pointing to this particular page. If you do not like it, delete the
+ relevant pages, and rebuild the wiki.
## CSS
diff --git a/doc/style.css b/doc/style.css
index 4c48e5c7b..fe1eb903d 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -548,3 +548,48 @@ a.openid_large_btn:focus {
.trailsep {
display: none;
}
+
+/* mobile/small-screen-friendly layout */
+@media (max-width: 600px) {
+ .sidebar {
+ width: auto;
+ float: none;
+ margin-top: 0;
+ border: none;
+ }
+
+ /* if the mobile browser is new enough, use flex layout to shuffle
+ * the sidebar to the end */
+ .page {
+ display: -webkit-box;
+ display: -webkit-flexbox;
+ display: -webkit-flex;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-flex-direction: tb;
+ -webkit-flex-direction: column;
+ -webkit-flex-flow: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ }
+ #pageheader {
+ -webkit-box-ordinal-group: -1;
+ -webkit-order: -1;
+ -ms-box-ordinal-group: -1;
+ -ms-flex-order: -1;
+ order: -1;
+ }
+ .sidebar, #footer {
+ -webkit-box-ordinal-group: 1;
+ -webkit-order: 1;
+ -ms-box-ordinal-group: 1;
+ -ms-flex-order: 1;
+ order: 1;
+ }
+
+ .blogform, #blogform {
+ padding: 4px 4px;
+ }
+}
diff --git a/doc/tipjar.mdwn b/doc/tipjar.mdwn
index 80d8f5cb2..d23dc103c 100644
--- a/doc/tipjar.mdwn
+++ b/doc/tipjar.mdwn
@@ -18,6 +18,7 @@ Thanks to the following people for their kind contributions:
* Jon Dowland
* Amitai Schlair
* Luca Capello
+* Patrick ZAJDA
(Note that this page is locked to prevent anyone from tampering with the PayPal link.
If you prefer your donation *not* be listed here, let [[Joey]] know.)
diff --git a/doc/tips/nearlyfreespeech/discussion.mdwn b/doc/tips/nearlyfreespeech/discussion.mdwn
index b76432566..b13366caa 100644
--- a/doc/tips/nearlyfreespeech/discussion.mdwn
+++ b/doc/tips/nearlyfreespeech/discussion.mdwn
@@ -20,3 +20,20 @@ Thanks for your incredible work!
> it ikiwiki. --[[Joey]]
Thanks a lot Joey. :-)
+
+Hi
+
+I installed version 3.20141016 as described, and it works mostly. However to get [[!iki plugins/sparkline]] to work properly I had to add
+
+[[!format php """
+set_include_path(get_include_path() . PATH_SEPARATOR . '/home/private/src/sparkline-php-0.2/lib');
+require_once('/home/private/src/sparkline-php-0.2/lib/Sparkline_$style.php');
+"""]]
+
+to `sparkline.pm` around line 38. This is mostly likely because
+
+1. I didn't install sparkline into php's default path.
+1. I don't really know php.
+1. I don't have the time (right now) to sort out the proper way to do this.
+
+I also haven't sorted out how to make [[!iki ikiwiki/directive/format]] fully functional. I suspect I don't have everything installed on the host. -- [[james]]
diff --git a/doc/todo/Fenced_code_blocks___40__from_GitHub_Flavored_Markdown__41__.mdwn b/doc/todo/Fenced_code_blocks___40__from_GitHub_Flavored_Markdown__41__.mdwn
index 24552b29f..bf1ca0eb4 100644
--- a/doc/todo/Fenced_code_blocks___40__from_GitHub_Flavored_Markdown__41__.mdwn
+++ b/doc/todo/Fenced_code_blocks___40__from_GitHub_Flavored_Markdown__41__.mdwn
@@ -42,3 +42,5 @@ main = forever $
> > ```
> >
> > ... maybe a bug in Discount... --[[anarcat]]
+
+> > I strongly support this feature as well! --[[integrii]]
diff --git a/doc/todo/Let_plugins_influence_what_environment_variables_a_wrapper_will_preserve.mdwn b/doc/todo/Let_plugins_influence_what_environment_variables_a_wrapper_will_preserve.mdwn
index 48901a2c4..4f4478330 100644
--- a/doc/todo/Let_plugins_influence_what_environment_variables_a_wrapper_will_preserve.mdwn
+++ b/doc/todo/Let_plugins_influence_what_environment_variables_a_wrapper_will_preserve.mdwn
@@ -12,3 +12,53 @@ I was asked by [[Joey]] to create a page here for purposes of review. I'm still
That seemed to be ok for reviewing [[bugs/CGI wrapper doesn't store PERL5LIB environment variable]], so I hope it's ok for this one too. If another way would be preferable, please let me know.
-- [[jcflack]]
+
+> This is less about what plugins need, and more about what is safe.
+> If an environment variable is unsafe (in the sense of "can make a
+> setuid executable change its behaviour in dangerous ways") then we
+> must not pass it through, however desirable it might be.
+>
+> Because the only safe thing we can do is a whitelist, the list
+> is secondarily about what plugins need: if nothing needs a variable,
+> we don't pass it through.
+>
+> However, if a particular variable is safe, then it's always safe;
+> so if any plugin needs something, we might as well just put it in
+> the big list of things to keep. (In other words, any change to this
+> list is already security-sensitive.)
+>
+> As such, and because importing CGI into Setup pulls in a bunch
+> of extra code that is normally only imported when we are actually
+> running as a CGI, it might make more sense to have the "master list"
+> stay in Wrapper.
+>
+> What variables would `signinview` need? Can we just add them to
+> the list and skip the complexity of per-plugin configurability?
+>
+> Sorting the list makes sense to me, and so does adding the RFC 3875 set.
+>
+> [[!format txt """
+This change does seem to have exposed a thing where various plugins that
+call checksessionexpiry() (in CGI.pm) have been supplying one more argument
+than its prototype allows ... for years ...
+"""]]
+>
+> I fixed that in ikiwiki 3.20141016. Please don't add the extra ignored
+> parameter to the prototype.
+>
+> [[!format diff """
++ if ( $config{needenvkeys} ) {
+"""]]
+>
+> If this is needed at all, you should include this in the master list of
+> setup keys in IkiWiki.pm so it's documentable. Please mention setuid
+> in the description: "environment variables that are safe to pass through
+> a setuid wrapper" or something.
+>
+> I think it's `safe => 0, advanced => 1`.
+>
+> `preserve_env` or `env_keep` (or without the underscore, as you prefer)
+> might be better names for it (terminology stolen from `debuild` and `sudo`
+> respectively).
+>
+> --[[smcv]]
diff --git a/doc/todo/calendar_autocreate.mdwn b/doc/todo/calendar_autocreate.mdwn
index 371079d68..c1f9c454e 100644
--- a/doc/todo/calendar_autocreate.mdwn
+++ b/doc/todo/calendar_autocreate.mdwn
@@ -1,5 +1,7 @@
Here is a patch that makes [[ikiwiki-calendar]] almost useless.
+> [[merged|done]], thanks! --[[smcv]]
+
It adds some options, the main one being `calendar_autocreate`, which is
similar to the `tag_autocreate` option of the [[tag|plugins/tag]]: it create
archive pages when needed.
diff --git a/doc/todo/generate_HTML5_by_default.mdwn b/doc/todo/generate_HTML5_by_default.mdwn
index f8d598cc1..56041d9d3 100644
--- a/doc/todo/generate_HTML5_by_default.mdwn
+++ b/doc/todo/generate_HTML5_by_default.mdwn
@@ -59,3 +59,5 @@ At the moment my preferred option is the last, for which see my `ready/html5`
branch. I'll apply this at some point if there are no objections.
--[[smcv]]
+
+> [[merged|done]] --[[smcv]]
diff --git a/doc/todo/support_multiple_perl_libraries.mdwn b/doc/todo/support_multiple_perl_libraries.mdwn
index 2869b5033..6e3fe22a4 100644
--- a/doc/todo/support_multiple_perl_libraries.mdwn
+++ b/doc/todo/support_multiple_perl_libraries.mdwn
@@ -8,4 +8,40 @@ I think the change is a one-liner, but I put this here for discussion before att
[[DavidBremner]]
+> I would like this feature too, for the very same reasons.
+>
+> To preserve backward compatibility, I tried to implement it in the following way: if `libdir` is a string, it is (as it is right now), a directory in which plugins can be searched; if `libdir` is an array of strings, it is a list of libdirs. The ideal place to put it in would be in subroutine [checkconfig](http://source.ikiwiki.branchable.com/?p=source.git;a=blob;f=IkiWiki.pm;hb=56f8223f9594ae687099dada0c138d669a6f931f#l569). However, plugins are loaded (and option `libdir` is used) in subroutine [loadplugins](http://source.ikiwiki.branchable.com/?p=source.git;a=blob;f=IkiWiki.pm;hb=56f8223f9594ae687099dada0c138d669a6f931f#l713), which is called [just before `checkconfig`](http://source.ikiwiki.branchable.com/?p=source.git;a=blob;f=ikiwiki.in;hb=729991564ec7e1116fc023c51e73b47af8b6fce7#l143).
+>
+> A solution would be to check `libdir` (and turn it into a list if necessary) somewhere in subroutine [getconfig](http://source.ikiwiki.branchable.com/?p=source.git;a=blob;f=ikiwiki.in;hb=729991564ec7e1116fc023c51e73b47af8b6fce7#l26), but I do not know where to put it not to make it look like a bad hack…
+>
+> Any idea about the best place to preprocess `libdir`? Or any better idea to implement this?
+>
+> [[Louis|spalax]]
+
+>> Modifying `getconfig` is not a valid solution, because IkiWiki.pm is also imported by
+>> [[ikiwiki-transition]], [[ikiwiki-calendar]], the regression tests, etc.
+>>
+>> The way I would personally do it is to have a new non-exported function `getlibdirs`
+>> or something, have it do something like this:
+>>
+>> if (! ref $config{libdir}) {
+>> if (length $config{libdir}) {
+>> $config{libdir} = [$config{libdir}];
+>> } else {
+>> $config{libdir} = [];
+>> }
+>> }
+>> return @{$config{libdir}};
+>>
+>> and replace all uses of $config{libdir} with it.
+>>
+>> --[[smcv]]
+>>>
+>>> I implemented it (see branch ``paternal/libdirs``). I used [[smcv]]'s idea, but
+>>> avoiding side effects. I edited documentation as well. As usual, as neither
+>>> English nor Perl are my first languages (damn! I would be so much more
+>>> efficient in Python) feel free to improve my [[!taglink patch]].
+>>> [[!template id=gitbranch branch=spalax/paternal/libdirs browse="https://github.com/paternal/ikiwiki/tree/paternal/libdirs" author="[[Louis|spalax]]"]]
+
+
[[!taglink wishlist]]
diff --git a/doc/users/james.mdwn b/doc/users/james.mdwn
new file mode 100644
index 000000000..ee539c2b7
--- /dev/null
+++ b/doc/users/james.mdwn
@@ -0,0 +1 @@
+Runs ikiwiki on his home page at [[http://jamestechnotes.com]] and can be reached at [[james@jamestechnotes.com]]
diff --git a/doc/users/mjd.mdwn b/doc/users/mjd.mdwn
new file mode 100644
index 000000000..018314b6e
--- /dev/null
+++ b/doc/users/mjd.mdwn
@@ -0,0 +1,5 @@
+Mark Jason Dominus / `yrlnry` (on IRC) / [[Ikiwiki git repo|https://github.com/mjdominus/ikiwiki]]
+
+* [[blog|http://blog.plover.com/]]
+* [[CPAN|https://metacpan.org/author/MJD]]
+* [[math.stackexchange|http://math.stackexchange.com/users/25554/mjd]]
diff --git a/ikiwiki-comment.in b/ikiwiki-comment.in
index ef2751eca..b0cea4a4a 100755
--- a/ikiwiki-comment.in
+++ b/ikiwiki-comment.in
@@ -14,7 +14,9 @@ my $pagefile=shift || usage ();
my $dir=IkiWiki::dirname($pagefile);
$dir="." unless length $dir;
my $page=IkiWiki::basename($pagefile);
-$page=~s/\.[^.]+$//;
+if (! -d $pagefile) {
+ $page=~s/\.[^.]+$//;
+}
IkiWiki::Plugin::comments::checkconfig();
my $comment_num=1 + IkiWiki::Plugin::comments::num_comments($page, $dir);
diff --git a/t/html.t b/t/html.t
deleted file mode 100755
index 84c561fa8..000000000
--- a/t/html.t
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/perl
-use warnings;
-use strict;
-use Test::More;
-
-my @pages;
-
-BEGIN {
- @pages=qw(index features news plugins/map security);
- if (system("command -v validate >/dev/null") != 0) {
- plan skip_all => "html validator not present";
- }
- else {
- plan(tests => int @pages + 2);
- }
- use_ok("IkiWiki");
-}
-
-# Have to build the html pages first.
-# Note that just building them like this doesn't exersise all the possible
-# html that can be generated, in particular it misses some of the action
-# links at the top, etc.
-ok(system("make >/dev/null") == 0);
-
-foreach my $page (@pages) {
- print "# Validating $page\n";
- ok(system("validate html/$page.html") == 0);
-}
-
-# TODO: validate form output html
diff --git a/t/img.t b/t/img.t
index 8c10d9b74..2ea3abb24 100755
--- a/t/img.t
+++ b/t/img.t
@@ -26,7 +26,8 @@ ok(! system("rm -rf t/tmp; mkdir -p t/tmp/in"));
ok(! system("cp t/img/redsquare.png t/tmp/in/redsquare.png"));
if ($SVGS_WORK) {
- writefile("emptysquare.svg", "t/tmp/in", '<svg width="30" height="30"/>');
+ writefile("emptysquare.svg", "t/tmp/in",
+ '<svg width="30" height="30"><rect x="0" y="0" width="30" height="30" fill="blue"/></svg>');
}
# using different image sizes for different pages, so the pagenumber selection can be tested easily
diff --git a/t/relativity.t b/t/relativity.t
index 054f8f664..a1f3ad830 100755
--- a/t/relativity.t
+++ b/t/relativity.t
@@ -59,7 +59,6 @@ cgiurl: $args{cgiurl}
$w3mmodeline
cgi_wrapper: t/tmp/ikiwiki.cgi
cgi_wrappermode: 0754
-html5: $args{html5}
# make it easier to test previewing
add_plugins:
- anonok
@@ -148,7 +147,6 @@ sub test_startup {
sub test_site1_perfectly_ordinary_ikiwiki {
write_setup_file(
- html5 => 0,
url => "http://example.com/wiki/",
cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
);
@@ -157,77 +155,35 @@ sub test_site1_perfectly_ordinary_ikiwiki {
# url and cgiurl are on the same host so the cgiurl is host-relative
check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
my %bits = parse_cgi_content(run_cgi());
- is($bits{basehref}, "http://example.com/wiki/");
+ like($bits{basehref}, qr{^(?:(?:http:)?//example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
# when accessed via HTTPS, links are secure
%bits = parse_cgi_content(run_cgi(is_https => 1));
- is($bits{basehref}, "https://example.com/wiki/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
# when accessed via a different hostname, links stay on that host
%bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
- is($bits{basehref}, "http://staging.example.net/wiki/");
+ like($bits{basehref}, qr{^(?:(?:http:)?//staging\.example\.net)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
# previewing a page
%bits = parse_cgi_content(run_cgi(is_preview => 1));
- is($bits{basehref}, "http://example.com/wiki/a/b/c/");
+ like($bits{basehref}, qr{^(?:(?:http:)?//example\.com)?/wiki/a/b/c/$});
like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- # in html5, the <base> is allowed to be relative, and we take full
- # advantage of that
- write_setup_file(
- html5 => 1,
- url => "http://example.com/wiki/",
- cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
- );
- thoroughly_rebuild();
- check_cgi_mode_bits();
- # url and cgiurl are on the same host so the cgiurl is host-relative
- check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
-
- %bits = parse_cgi_content(run_cgi());
- is($bits{basehref}, "/wiki/");
- is($bits{stylehref}, "/wiki/style.css");
- is($bits{tophref}, "/wiki/");
- is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
-
- # when accessed via HTTPS, links are secure - this is easy because under
- # html5 they're independent of the URL at which the CGI was accessed
- %bits = parse_cgi_content(run_cgi(is_https => 1));
- is($bits{basehref}, "/wiki/");
- is($bits{stylehref}, "/wiki/style.css");
- is($bits{tophref}, "/wiki/");
- is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
-
- # when accessed via a different hostname, links stay on that host -
- # this is really easy in html5 because we can use relative URLs
- %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
- is($bits{basehref}, "/wiki/");
- is($bits{stylehref}, "/wiki/style.css");
- is($bits{tophref}, "/wiki/");
- is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
-
- # previewing a page
- %bits = parse_cgi_content(run_cgi(is_preview => 1));
- is($bits{basehref}, "/wiki/a/b/c/");
- is($bits{stylehref}, "/wiki/style.css");
- like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
- is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
}
sub test_site2_static_content_and_cgi_on_different_servers {
write_setup_file(
- html5 => 0,
url => "http://static.example.com/",
cgiurl => "http://cgi.example.com/ikiwiki.cgi",
);
@@ -238,14 +194,14 @@ sub test_site2_static_content_and_cgi_on_different_servers {
check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
my %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
- like($bits{basehref}, qr{^http://static.example.com/$});
+ like($bits{basehref}, qr{^(?:(?:http:)?//static.example.com)?/$});
like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
# when accessed via HTTPS, links are secure
%bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
- like($bits{basehref}, qr{^https://static.example.com/$});
+ like($bits{basehref}, qr{^(?:https:)?//static\.example\.com/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
@@ -253,7 +209,7 @@ sub test_site2_static_content_and_cgi_on_different_servers {
# when accessed via a different hostname, links to the CGI (only) should
# stay on that host?
%bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
- like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
+ like($bits{basehref}, qr{^(?:http:)?//static\.example\.com/a/b/c/$});
like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
like($bits{cgihref}, qr{^(?:(?:http:)?//(?:staging\.example\.net|cgi\.example\.com))?/ikiwiki.cgi$});
@@ -261,48 +217,10 @@ sub test_site2_static_content_and_cgi_on_different_servers {
local $TODO = "use self-referential CGI URL?";
like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
}
-
- write_setup_file(
- html5 => 1,
- url => "http://static.example.com/",
- cgiurl => "http://cgi.example.com/ikiwiki.cgi",
- );
- thoroughly_rebuild();
- check_cgi_mode_bits();
- # url and cgiurl are not on the same host so the cgiurl has to be
- # protocol-relative or absolute
- check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
-
- %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
- is($bits{basehref}, "//static.example.com/");
- is($bits{stylehref}, "//static.example.com/style.css");
- is($bits{tophref}, "//static.example.com/");
- is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
-
- # when accessed via HTTPS, links are secure - in fact they're exactly the
- # same as when accessed via HTTP
- %bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
- is($bits{basehref}, "//static.example.com/");
- is($bits{stylehref}, "//static.example.com/style.css");
- is($bits{tophref}, "//static.example.com/");
- is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
-
- # when accessed via a different hostname, links to the CGI (only) should
- # stay on that host?
- %bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
- is($bits{basehref}, "//static.example.com/a/b/c/");
- is($bits{stylehref}, "//static.example.com/style.css");
- is($bits{tophref}, "../../../");
- like($bits{cgihref}, qr{//(?:staging\.example\.net|cgi\.example\.com)/ikiwiki\.cgi});
- TODO: {
- local $TODO = "use self-referential CGI URL maybe?";
- is($bits{cgihref}, "//staging.example.net/ikiwiki.cgi");
- }
}
sub test_site3_we_specifically_want_everything_to_be_secure {
write_setup_file(
- html5 => 0,
url => "https://example.com/wiki/",
cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
);
@@ -313,7 +231,7 @@ sub test_site3_we_specifically_want_everything_to_be_secure {
# when accessed via HTTPS, links are secure
my %bits = parse_cgi_content(run_cgi(is_https => 1));
- is($bits{basehref}, "https://example.com/wiki/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
@@ -331,25 +249,22 @@ sub test_site3_we_specifically_want_everything_to_be_secure {
# when accessed via a different hostname, links stay on that host
%bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
- is($bits{basehref}, "https://staging.example.net/wiki/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//staging\.example\.net)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
# previewing a page
%bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
- is($bits{basehref}, "https://example.com/wiki/a/b/c/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/a/b/c/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- # not testing html5: 0 here because that ends up identical to site 1
}
sub test_site4_cgi_is_secure_static_content_doesnt_have_to_be {
# (NetBSD wiki)
write_setup_file(
- html5 => 0,
url => "http://example.com/wiki/",
cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
);
@@ -360,14 +275,15 @@ sub test_site4_cgi_is_secure_static_content_doesnt_have_to_be {
# when accessed via HTTPS, links are secure (to avoid mixed-content)
my %bits = parse_cgi_content(run_cgi(is_https => 1));
- is($bits{basehref}, "https://example.com/wiki/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
- # when not accessed via HTTPS, ???
+ # FIXME: when not accessed via HTTPS, should the static content be
+ # forced to https anyway? For now we accept either
%bits = parse_cgi_content(run_cgi());
- like($bits{basehref}, qr{^https?://example.com/wiki/$});
+ like($bits{basehref}, qr{^(?:(?:https?)?://example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
@@ -376,7 +292,7 @@ sub test_site4_cgi_is_secure_static_content_doesnt_have_to_be {
%bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
# because the static and dynamic stuff is on the same server, we assume that
# both are also on the staging server
- like($bits{basehref}, qr{^https://staging.example.net/wiki/$});
+ like($bits{basehref}, qr{^(?:(?:https:)?//staging\.example\.net)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:(?:(?:https:)?//staging.example.net)?/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//(?:staging\.example\.net|example\.com))?/cgi-bin/ikiwiki.cgi$});
@@ -387,63 +303,15 @@ sub test_site4_cgi_is_secure_static_content_doesnt_have_to_be {
# previewing a page
%bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
- is($bits{basehref}, "https://example.com/wiki/a/b/c/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/a/b/c/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- write_setup_file(
- html5 => 1,
- url => "http://example.com/wiki/",
- cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
- );
- thoroughly_rebuild();
- check_cgi_mode_bits();
- # url and cgiurl are on the same host but different schemes
- check_generated_content(qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
-
- # when accessed via HTTPS, links are secure (to avoid mixed-content)
- %bits = parse_cgi_content(run_cgi(is_https => 1));
- is($bits{basehref}, "/wiki/");
- is($bits{stylehref}, "/wiki/style.css");
- is($bits{tophref}, "/wiki/");
- like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- # when not accessed via HTTPS, ???
- %bits = parse_cgi_content(run_cgi());
- like($bits{basehref}, qr{^(?:https?://example.com)?/wiki/$});
- like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
- like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
- like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- # when accessed via a different hostname, links stay on that host
- %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
- # because the static and dynamic stuff is on the same server, we assume that
- # both are also on the staging server
- is($bits{basehref}, "/wiki/");
- is($bits{stylehref}, "/wiki/style.css");
- like($bits{tophref}, qr{^(?:/wiki|\.)/$});
- like($bits{cgihref}, qr{^(?:(?:https:)?//(?:example\.com|staging\.example\.net))?/cgi-bin/ikiwiki.cgi$});
- TODO: {
- local $TODO = "this should really point back to itself but currently points to example.com";
- like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
- }
-
- # previewing a page
- %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
- is($bits{basehref}, "/wiki/a/b/c/");
- is($bits{stylehref}, "/wiki/style.css");
- like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
- like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
-
- # Deliberately not testing https static content with http cgiurl,
- # because that makes remarkably little sense.
}
sub test_site5_w3mmode {
# as documented in [[w3mmode]]
write_setup_file(
- html5 => 0,
url => undef,
cgiurl => "ikiwiki.cgi",
w3mmode => 1,
@@ -459,28 +327,10 @@ sub test_site5_w3mmode {
like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
-
- write_setup_file(
- html5 => 1,
- url => undef,
- cgiurl => "ikiwiki.cgi",
- w3mmode => 1,
- );
- thoroughly_rebuild();
- check_cgi_mode_bits();
- # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
- check_generated_content(qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
-
- %bits = parse_cgi_content(run_cgi(PATH_INFO => '/ikiwiki.cgi', SCRIPT_NAME => '/cgi-bin/ikiwiki-w3m.cgi'));
- like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
- like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
- like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
- like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
}
sub test_site6_behind_reverse_proxy {
write_setup_file(
- html5 => 0,
url => "https://example.com/wiki/",
cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
reverse_proxy => 1,
@@ -495,18 +345,15 @@ sub test_site6_behind_reverse_proxy {
my %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'localhost'));
like($bits{tophref}, qr{^(?:/wiki|\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
- is($bits{basehref}, "https://example.com/wiki/");
+ like($bits{basehref}, qr{^(?:(?:https:)?//example\.com)?/wiki/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
# previewing a page
%bits = parse_cgi_content(run_cgi(is_preview => 1, HTTP_HOST => 'localhost'));
like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
- is($bits{basehref}, "https://example.com/wiki/a/b/c/");
+ like($bits{basehref}, qr{^(?:(?:https)?://example\.com)?/wiki/a/b/c/$});
like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
-
- # not testing html5: 1 because it would be the same as site 1 -
- # the reverse_proxy config option is unnecessary under html5
}
test_startup();
diff --git a/t/wellformed.t b/t/wellformed.t
new file mode 100755
index 000000000..cee0ff3be
--- /dev/null
+++ b/t/wellformed.t
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Cwd qw();
+use File::Find;
+use Test::More;
+
+plan(skip_all => "XML::Parser not available")
+ unless eval q{use XML::Parser (); 1;};
+
+use IkiWiki;
+
+ok(system("make >/dev/null") == 0);
+
+chdir("html") || die "chdir: $!";
+
+sub wanted {
+ my $file = $_;
+ return if -d $file;
+ $file =~ s{^\./}{};
+ return if $file !~ m/\.html$/;
+ if (eval {
+ XML::Parser->new()->parsefile($file);
+ 1;
+ }) {
+ pass($file);
+ }
+ elsif ($file =~ m{^(?:
+ # user-contributed, contains explicit <br>
+ plugins/contrib/gallery |
+ # use templatebody when branchable.com has been upgraded
+ templates/ |
+ # malformed content in <pre> not escaped by discount
+ tips/convert_mediawiki_to_ikiwiki
+ # user-contributed, content is anyone's guess
+ users/ |
+ )}x) {
+ TODO: {
+ local $TODO = $@;
+ fail($file);
+ }
+ }
+}
+
+find({
+ no_chdir => 1,
+ wanted => \&wanted,
+}, '.');
+
+done_testing;
diff --git a/templates/googleform.tmpl b/templates/googleform.tmpl
index b1c3078fb..155a08155 100644
--- a/templates/googleform.tmpl
+++ b/templates/googleform.tmpl
@@ -3,6 +3,6 @@
<div>
<input name="sitesearch" value="<TMPL_VAR URL>" type="hidden" />
<input name="q" value="" id="searchbox" size="16" maxlength="255" type="text"
- <TMPL_IF HTML5>placeholder="search"</TMPL_IF> />
+ placeholder="search" />
</div>
</form>
diff --git a/templates/page.tmpl b/templates/page.tmpl
index c709c4f85..9e8b330a4 100644
--- a/templates/page.tmpl
+++ b/templates/page.tmpl
@@ -1,9 +1,5 @@
-<TMPL_IF HTML5><!DOCTYPE html>
-<html>
-<TMPL_ELSE><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
-</TMPL_IF>
<head>
<TMPL_IF DYNAMIC>
<TMPL_IF FORCEBASEURL><base href="<TMPL_VAR FORCEBASEURL>" /><TMPL_ELSE>
@@ -12,6 +8,7 @@
</TMPL_IF>
<TMPL_IF HTML5><meta charset="utf-8" /><TMPL_ELSE><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></TMPL_IF>
<title><TMPL_VAR TITLE></title>
+<TMPL_IF RESPONSIVE_LAYOUT><meta name="viewport" content="width=device-width, initial-scale=1" /></TMPL_IF>
<TMPL_IF FAVICON>
<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
</TMPL_IF>
@@ -134,7 +131,7 @@
<div id="pagebody">
-<TMPL_IF HTML5><section id="content" role="main"><TMPL_ELSE><div id="content"></TMPL_IF>
+<TMPL_IF HTML5><section<TMPL_ELSE><div</TMPL_IF> id="content" role="main">
<TMPL_VAR CONTENT>
<TMPL_IF HTML5></section><TMPL_ELSE></div></TMPL_IF>
@@ -146,7 +143,7 @@
<TMPL_UNLESS DYNAMIC>
<TMPL_IF COMMENTS>
-<TMPL_IF HTML5><section id="comments" role="complementary"><TMPL_ELSE><div id="comments"></TMPL_IF>
+<TMPL_IF HTML5><section<TMPL_ELSE><div</TMPL_IF> id="comments" role="complementary">
<TMPL_VAR COMMENTS>
<TMPL_IF ADDCOMMENTURL>
<div class="addcomment">
@@ -161,7 +158,7 @@
</div>
-<TMPL_IF HTML5><footer id="footer" class="pagefooter" role="contentinfo"><TMPL_ELSE><div id="footer" class="pagefooter"></TMPL_IF>
+<TMPL_IF HTML5><footer<TMPL_ELSE><div</TMPL_IF> id="footer" class="pagefooter" role="contentinfo">
<TMPL_UNLESS DYNAMIC>
<TMPL_IF HTML5><nav id="pageinfo"><TMPL_ELSE><div id="pageinfo"></TMPL_IF>
diff --git a/templates/searchform.tmpl b/templates/searchform.tmpl
index cb65d124c..8cdf745f9 100644
--- a/templates/searchform.tmpl
+++ b/templates/searchform.tmpl
@@ -1,6 +1,6 @@
<form method="get" action="<TMPL_VAR SEARCHACTION>" id="searchform">
<div>
<input type="text" id="searchbox" name="P" value="" size="16"
-<TMPL_IF HTML5>placeholder="search"</TMPL_IF> />
+ placeholder="search" />
</div>
</form>
diff --git a/templates/searchquery.tmpl b/templates/searchquery.tmpl
index 15bc78e28..62772664d 100644
--- a/templates/searchquery.tmpl
+++ b/templates/searchquery.tmpl
@@ -33,8 +33,8 @@ $def{NEXT,$if{$ne{$last,$msize},<INPUT TYPE=submit NAME="&gt;" VALUE="Next">}}
<FORM NAME=P METHOD=GET
ACTION="$html{$env{CGIURL}}" TARGET="_top">
-<div style="text-align:center">
-<INPUT NAME=P VALUE="$html{$query}" SIZE=65>
+<div class="searchquery" style="text-align:center">
+<INPUT class="searchbox" NAME=P VALUE="$html{$query}" SIZE=65>
<INPUT TYPE=SUBMIT VALUE="Search">
$env{HELPLINK}
<hr>
diff --git a/themes/actiontabs/style.css b/themes/actiontabs/style.css
index d4afc0915..67720e285 100644
--- a/themes/actiontabs/style.css
+++ b/themes/actiontabs/style.css
@@ -147,3 +147,13 @@ div.recentchanges {
/* allow space for the action tabs */
margin-bottom: 2em;
}
+
+@media (max-width: 600px) {
+ #content, #enclosure, #comments, #footer {
+ margin: 0.5em;
+ }
+ .pageheader .actions ul li {
+ padding: .1em .2em 0 .2em;
+ font-size: 0.8em;
+ }
+}
diff --git a/themes/blueview/style.css b/themes/blueview/style.css
index af1434574..57813e2ee 100644
--- a/themes/blueview/style.css
+++ b/themes/blueview/style.css
@@ -279,3 +279,30 @@ body {
}
+/* lose the border on mobile */
+@media (max-width: 600px) {
+ body {
+ padding: 0;
+ }
+ .page {
+ border: none;
+ margin: 0;
+ }
+ #pagebody {
+ margin: auto;
+ border: none;
+ padding: 0.5em;
+ }
+ #footer {
+ padding: 0.5em;
+ }
+}
+
+/* cancel the minimum width if it would mean scrollbars */
+@media (max-width: 850px) {
+ .page {
+ width: auto;
+ min-width: 0;
+ padding: 0;
+ }
+}
diff --git a/themes/monochrome/style.css b/themes/monochrome/style.css
index bd3fdf593..e85f8abb5 100644
--- a/themes/monochrome/style.css
+++ b/themes/monochrome/style.css
@@ -10,6 +10,7 @@ body {
margin-left: auto;
margin-right: auto;
width: 48em;
+ max-width: 95%;
background: url(gradient.png) repeat-x white 0px -16px;
margin-top: 48px; /* height of gradient.png that we want to see */