summaryrefslogtreecommitdiff
path: root/lib/VNWeb/Docs
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2019-09-23 11:01:17 +0200
committerYorhel <git@yorhel.nl>2019-09-23 11:01:17 +0200
commit9ccafba60b8de37b0c2a202d22df5c3e25b78026 (patch)
treeae150b0c25282a646e1d71868022ad4a5789e60a /lib/VNWeb/Docs
parent4542d952f782ee193dbf279cd8186cba0e9d87a4 (diff)
v2rw: Convert doc pages + add framework for item fetching & display & revisions
This bumps the minimum Perl version to 5.26 in order to make use of lexical subroutines - a feature I've been wanting for a while. This should be the last version bump, 5.26 is the highest version in Ubuntu LTS at the moment. Not that I use Ubuntu, but it's used by the Docker container and it's a sensible reference. I merged the 'maintabs' and 'hiddenmsg' features into the primary framework_ function; It fits quite well there, removes a little bit of boilerplate from the DB entry page code and reduces the reliance on common "dbSomethingGet()" methods. I was hoping I'd be able to reduce the boilerplate required for defining revisions, but I don't think that's going to happen. What I did do was reimplement the diffing to handle item and text diffs separately, with sensible defaults for the old split/join/diff options. Diffing is now performed on the raw structured data rather than on formatted HTML, which, combined with the db_entry() functions, ought to be less brittle.
Diffstat (limited to 'lib/VNWeb/Docs')
-rw-r--r--lib/VNWeb/Docs/Lib.pm90
-rw-r--r--lib/VNWeb/Docs/Page.pm67
2 files changed, 157 insertions, 0 deletions
diff --git a/lib/VNWeb/Docs/Lib.pm b/lib/VNWeb/Docs/Lib.pm
new file mode 100644
index 00000000..eed1afc0
--- /dev/null
+++ b/lib/VNWeb/Docs/Lib.pm
@@ -0,0 +1,90 @@
+package VNWeb::Docs::Lib;
+
+use VNWeb::Prelude;
+use Text::MultiMarkdown 'markdown';
+
+our @EXPORT = qw/md2html/;
+
+
+# Lets you call TUWF::XML functions and returns a string, doesn't affect any existing TUWF::XML outputs.
+# Nice idea for a TUWF::XML feature.
+sub lexicalxml(&) {
+ my $f = shift;
+ my $buf = '';
+ local $TUWF::XML::OBJ = TUWF::XML->new(write => sub { $buf .= shift });
+ $f->();
+ $buf
+}
+
+
+sub _moderators {
+ my $l = tuwf->dbAlli('SELECT id, username, perm FROM users WHERE (perm & ', \(auth->allPerms &~ auth->defaultPerms), ') > 0 ORDER BY id LIMIT 100');
+ my @modperms = grep 0 == (auth->listPerms->{$_} & auth->defaultPerms), keys auth->listPerms->%*;
+
+ lexicalxml {
+ dl_ sub {
+ for my $u (@$l) {
+ dt_ sub { a_ href => "/u$u->{id}", $u->{username} };
+ dd_ auth->allPerms == ($u->{perm} & auth->allPerms) ? 'admin'
+ : join ', ', sort grep $u->{perm} & auth->listPerms->{$_}, @modperms;
+ }
+ }
+ }
+}
+
+
+sub _skincontrib {
+ my %users;
+ push $users{ tuwf->{skins}{$_}[1] }->@*, [ $_, tuwf->{skins}{$_}[0] ]
+ for sort { tuwf->{skins}{$a}[0] cmp tuwf->{skins}{$b}[0] } keys tuwf->{skins}->%*;
+
+ my $u = tuwf->dbAlli('SELECT id, username FROM users WHERE id IN', [keys %users]);
+
+ lexicalxml {
+ dl_ sub {
+ for my $u (@$u) {
+ dt_ sub { a_ href => "/u$u->{id}", $u->{username} };
+ dd_ sub {
+ join_ ', ', sub { a_ href => "?skin=$_->[0]", $_->[1] }, $users{$u->{id}}->@*
+ }
+ }
+ }
+ }
+}
+
+
+sub md2html {
+ my $content = shift;
+
+ $content =~ s{^:MODERATORS:$}{_moderators}me;
+ $content =~ s{^:SKINCONTRIB:$}{_skincontrib}me;
+
+ my $html = markdown $content, {
+ strip_metadata => 1,
+ img_ids => 0,
+ disable_footnotes => 1,
+ disable_bibliography => 1,
+ };
+
+ # Number sections and turn them into links
+ my($sec, $subsec) = (0,0);
+ $html =~ s{<h([1-2])[^>]+>(.*?)</h\1>}{
+ if($1 == 1) {
+ $sec++;
+ $subsec = 0;
+ qq{<h3><a href="#$sec" name="$sec">$sec. $2</a></h3>}
+ } elsif($1 == 2) {
+ $subsec++;
+ qq|<h4><a href="#$sec.$subsec" name="$sec.$subsec">$sec.$subsec. $2</a></h4>\n|
+ }
+ }ge;
+
+ # Text::MultiMarkdown doesn't handle fenced code blocks properly. The
+ # following solution breaks inline code blocks, but I don't use those anyway.
+ $html =~ s/<code>/<pre>/g;
+ $html =~ s#</code>#</pre>#g;
+
+ $html
+}
+
+1;
diff --git a/lib/VNWeb/Docs/Page.pm b/lib/VNWeb/Docs/Page.pm
new file mode 100644
index 00000000..15d501a2
--- /dev/null
+++ b/lib/VNWeb/Docs/Page.pm
@@ -0,0 +1,67 @@
+package VNWeb::Docs::Page;
+
+use VNWeb::Prelude;
+use VNWeb::Docs::Lib;
+
+
+sub _index_ {
+ ul_ class => 'index', sub {
+ li_ sub { b_ 'Guidelines' };
+ li_ sub { a_ href => '/d5', 'Editing Guidelines' };
+ li_ sub { a_ href => '/d2', 'Visual Novels' };
+ li_ sub { a_ href => '/d15', 'Special Games' };
+ li_ sub { a_ href => '/d3', 'Releases' };
+ li_ sub { a_ href => '/d4', 'Producers' };
+ li_ sub { a_ href => '/d16', 'Staff' };
+ li_ sub { a_ href => '/d12', 'Characters' };
+ li_ sub { a_ href => '/d10', 'Tags & Traits' };
+ li_ sub { a_ href => '/d13', 'Capturing Screenshots' };
+ li_ sub { b_ 'About VNDB' };
+ li_ sub { a_ href => '/d9', 'Discussion Board' };
+ li_ sub { a_ href => '/d6', 'FAQ' };
+ li_ sub { a_ href => '/d7', 'About Us' };
+ li_ sub { a_ href => '/d17', 'Privacy Policy & Licensing' };
+ li_ sub { a_ href => '/d11', 'Database API' };
+ li_ sub { a_ href => '/d14', 'Database Dumps' };
+ li_ sub { a_ href => '/d18', 'Database Querying' };
+ li_ sub { a_ href => '/d8', 'Development' };
+ }
+}
+
+
+sub _rev_ {
+ my $d = shift;
+ revision_ d => $d, sub {},
+ [ title => 'Title' ],
+ [ content => 'Contents' ];
+}
+
+
+# A little in-memory cache of the rendered HTML for the latest revision of each
+# doc page. md2html() performance is "acceptable" for regular page loads but
+# can still feel a little sluggish.
+my %cache; # chid => html
+
+
+TUWF::get qr{/$RE{drev}} => sub {
+ my $d = db_entry d => tuwf->capture('id'), tuwf->capture('rev');
+ return tuwf->resNotFound if !$d;
+
+ my $html = $cache{$d->{chid}} || md2html $d->{content};
+ $cache{$d->{chid}} ||= $html if $d->{chrev} == $d->{maxrev};
+
+ framework_ title => $d->{title}, type => 'd', dbobj => $d, hiddenmsg => 1,
+ sub {
+ _rev_ $d if tuwf->capture('rev');
+ div_ class => 'mainbox', sub {
+ h1_ $d->{title};
+ div_ class => 'docs', sub {
+ _index_;
+ lit_ $html;
+ clearfloat_;
+ };
+ };
+ };
+};
+
+1;