%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /bin/
Upload File :
Create Path :
Current File : //bin/dh_mkdocs

#!/usr/bin/perl

# Copyright: 2018 Dmitry Shachnev <mitya57@debian.org>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

=head1 NAME

dh_mkdocs - helps with packaging MkDocs-generated documentation

=head1 SYNOPSIS

dh_mkdocs [S<I<debhelper options>>] [B<-X>I<item>] [B<-T>I<package> | B<--theme-package> I<package>]

=head1 DESCRIPTION

B<dh_mkdocs> is a helper program for packaging documentation generated
by MkDocs. More specifically:

=over 4

=item *

It replaces static files with symlinks to their packaged versions if possible.
For packages using non-standard themes, use the B<--theme-package> option,
for example:

    dh_mkdocs --theme-package mkdocs-bootstrap

B<dh_mkdocs> only symlinks non-empty files with identical content.

=item *

For the standard B<mkdocs> and B<readthedocs> themes, it replaces references to
the highlight.js library from CDN with references to the packaged version of
that library.

=item *

It adds the needed dependencies to B<${mkdocs:Depends}> substitution variable.
Please add this variable to the B<Depends:> field of your documentation
package.

=back

You can pass B<--with mkdocs> to L<dh(1)> to make it automatically call
B<dh_mkdocs> after B<dh_installdocs>.

=head1 OPTIONS

=over 4

=item B<-X>I<item>, B<--exclude> I<item>

Exclude files that contain I<item> anywhere in their filename from being
symlinked or edited.

This option can be specified multiple times.

=item B<-T>I<package>, B<--theme-package> I<package>

Scan the specified additional I<package> for files that can be used as
symlink targets.

This option can be specified multiple times.

=back

=cut

use strict;
use warnings;
use Debian::Debhelper::Dh_Lib;
use Digest::file qw(digest_file);
use File::Find qw(find);
use File::Spec;
use IPC::Open2 qw(open2);

my @theme_packages;
my %package_dependencies;

sub add_theme_package {
    my ($option, $value) = @_;
    push @theme_packages, $value;
}

init(options => {
    'theme-package=s' => \&add_theme_package,
    'T=s' => \&add_theme_package,
});

my $mkdocs_directory_found = 0;

foreach my $package (@{$dh{DOPACKAGES}}) {
    my $tmpdir = tmpdir($package);
    next unless -d $tmpdir;

    # in this hash, value 1 means versioned dependency, 0 means unversioned
    $package_dependencies{$package} = {};

    find({
        wanted => sub {
            return unless -d;
            return if -l;
            return if excludefile($_);
            return unless looks_like_mkdocs_directory($_);

            $mkdocs_directory_found = 1;
            fixup_highlightjs_usage($package, $_);
            if ($package ne 'mkdocs-doc') {
                symlink_static_files($package, $_);
            }
            write_substvars($package);
        },
        no_chdir => 1
    }, $tmpdir);
}

$mkdocs_directory_found or error('MkDocs directory not found');

sub looks_like_mkdocs_directory {
    my ($path) = @_;
    return 0 unless -f "$path/index.html";
    return 0 unless -f "$path/sitemap.xml";
    return 0 unless -f "$path/search/search_index.json";
    return 1;
}

sub fixup_highlightjs_usage {
    my ($package, $path) = @_;
    my $cdn_hljs = '(?:https:)?//cdnjs.cloudflare.com/ajax/libs/highlight.js/[\d.]+';
    my $pkg_hljs = 'file:///usr/share/javascript/highlight.js';

    find({
        wanted => sub {
            return unless -f;
            return unless /\.html$/s;
            my $filename = $_;

            open(my $in, '<', $_) or error("Failed to open $_ for read: $!");
            open(my $out, '>', "$_.new") or error("Failed to open $_.new for write: $!");
            while (<$in>) {
                if (m{$cdn_hljs/highlight.min.js}) {
                    $package_dependencies{$package}{'libjs-highlight.js'} = 0;
                }
                s{$cdn_hljs/highlight.min.js}{$pkg_hljs/highlight.min.js};
                s{$cdn_hljs/styles/github.min.css}{$pkg_hljs/styles/github.css};
                print $out $_ unless m{$cdn_hljs/languages/};
            }
            close($in);
            close($out);
            rename("$filename.new", $filename);
        },
        no_chdir => 1
    }, $path);
}

sub symlink_static_files {
    my ($package, $path) = @_;
    my %file_names_by_hash;
    my %package_names_by_hash;
    my @packages = (
        'fonts-lato',
        'fonts-font-awesome',
        'libjs-bootstrap4',
        'libjs-jquery',
        'libjs-lunr',
        'libjs-modernizr',
        'node-jquery',
        'mkdocs',
        'sphinx-rtd-theme-common'
    );
    push @packages, @theme_packages;

    foreach my $package_name (@packages) {
        my $stdout;
        my $pid = open2($stdout, undef, 'dpkg-query', '--listfiles', $package_name);
        waitpid($pid, 0);
        if ($? eq 0) {
            while (<$stdout>) {
                chomp;
                if (-f && -s && ! -l) {
                    my $digest = digest_file($_, 'SHA-1');
                    $file_names_by_hash{$digest} = $_;
                    $package_names_by_hash{$digest} = $package_name;
                }
            }
        }
    }

    find({
        wanted => sub {
            return unless -f;
            return if -l;
            return if excludefile($_);

            my $digest = digest_file($_, 'SHA-1');
            if (exists $file_names_by_hash{$digest}) {
                my $target_path = $file_names_by_hash{$digest};
                my ($source_path) = $_ =~ m{debian/$package(/.*)};
                my $target_relpath = File::Spec->abs2rel($target_path, dirname($source_path));
                unlink($_) or error("Failed to delete $_: $!");
                symlink($target_relpath, $_) or error("Failed to create symbolic link: $!");
                my $dependency_name = $package_names_by_hash{$digest};
                $package_dependencies{$package}{$dependency_name} = 1;
            }
        },
        no_chdir => 1
    }, $path);
}

sub write_substvars {
    my ($package) = @_;
    my $dependencies = $package_dependencies{$package};

    while (my ($dependency, $versioned) = each %{$dependencies}) {
        if ($versioned) {
            my $stdout;
            my $pid = open2($stdout, undef,
                            'dpkg-query', '--show', '--showformat=${Version}', $dependency);
            waitpid($pid, 0);
            my $version = <$stdout>;
            $dependency = "$dependency (>= $version)";
        }
        addsubstvar($package, 'mkdocs:Depends', $dependency);
    }
}

=head1 SEE ALSO

L<debhelper(7)>, L<dh(1)>.

This program is meant to be used together with debhelper.

=head1 AUTHOR

Dmitry Shachnev <mitya57@debian.org>

=cut

Zerion Mini Shell 1.0