App-DocKnot

 view release on metacpan or  search on metacpan

lib/App/DocKnot.pm  view on Meta::CPAN

# Parent module for DocKnot.
#
# DocKnot provides various commands for generating documentation, web pages,
# and software releases.  This parent module provides some internal helper
# functions used to load configuration and metadata.  The normal entry point
# are the various submodules, or App::DocKnot::Command via docknot.
#
# SPDX-License-Identifier: MIT

##############################################################################
# Modules and declarations
##############################################################################

package App::DocKnot v8.0.1;

use 5.024;
use autodie;
use warnings;

use File::BaseDir qw(config_files);
use File::ShareDir qw(module_file);
use Kwalify qw(validate);
use Path::Tiny qw(path);
use YAML::XS ();

##############################################################################
# Helper methods
##############################################################################

# Helper routine to return the path of a file from the application data.
# These data files are installed with App::DocKnot, but each file can be
# overridden by the user via files in $HOME/.config/docknot or
# /etc/xdg/docknot (or whatever $XDG_CONFIG_DIRS is set to).
#
# We therefore try File::BaseDir first (which handles the XDG paths) and fall
# back on using File::ShareDir to locate the data.
#
# This function must be in the App::DocKnot module so that File::ShareDir
# works properly and searches the correct module path.
#
# @path - The relative path of the file as a list of components
#
# Returns: The absolute path to the application data
#  Throws: Text exception on failure to locate the desired file
sub appdata_path {
    my ($self, @path) = @_;

    # Try XDG paths first.
    my $path = config_files('docknot', @path);

    # If that doesn't work, use the data that came with the module.
    if (!defined($path)) {
        $path = module_file('App::DocKnot', path(@path)->stringify());
    }
    return $path;
}

# Load a YAML file with schema checking.
#
# $path   - Path to the YAML file to load
# $schema - Name of the schema file against which to check it
#
# Returns: Contents of the file as a hash
#  Throws: YAML::XS exception on invalid file
#          Text exception on schema mismatch
sub load_yaml_file {
    my ($self, $path, $schema) = @_;

    # Tell YAML::XS to use real booleans.  Otherwise, Kwalify is unhappy with
    # data elements set to false.
    local $YAML::XS::Boolean = 'JSON::PP';

    # Load the metadata and check it against the schema.  YAML::XS for some
    # reason puts a newline before the system error part of an error message
    # when loading a file, so clean up the error a bit.
    my $schema_path = $self->appdata_path('schema', $schema . '.yaml');
    my ($data_ref, $schema_ref);
    eval {
        $data_ref = YAML::XS::LoadFile($path);
        $schema_ref = YAML::XS::LoadFile($schema_path);
    };
    if ($@) {
        my $error = lcfirst($@);
        chomp($error);
        $error =~ s{ \n }{ }xms;
        die "$error\n";
    }
    eval { validate($schema_ref, $data_ref) };
    if ($@) {
        my $errors = $@;
        chomp($errors);
        die "schema validation for $path failed:\n$errors\n";
    }

    # Return the verified contents.
    return $data_ref;
}

##############################################################################
# Module return value and documentation
##############################################################################

1;
__END__

=for stopwords
Allbery DocKnot docknot MERCHANTABILITY NONINFRINGEMENT sublicense
submodules Kwalify

=head1 NAME

App::DocKnot - Documentation and software release management

=head1 REQUIREMENTS

Perl 5.24 or later and the modules File::BaseDir, File::ShareDir, Kwalify,
Path::Tiny, and YAML::XS, all of which are available from CPAN.

=head1 DESCRIPTION

DocKnot is a system for documentation and software release management.  Its
functionality is provided by various submodules, often invoked via the
B<docknot> command-line program.  For more information, see L<docknot(1)>.

This module only provides helper functions to load configuration and metadata
that are used by its various submodules.

=head1 INSTANCE METHODS

=over 4

=item appdata_path(PATH[, ...])

Return the path of a file from the application data.  The file is specified as
one or more path components.

These data files are installed with App::DocKnot, but each file can be
overridden by the user via files in F<$HOME/.config/docknot> or
F</etc/xdg/docknot> (or whatever $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS are set
to).  Raises a text exception if the desired file could not be located.

=item load_yaml_file(PATH, SCHEMA)

Load a YAML file with schema checking.  PATH is the path to the file.
SCHEMA is the name of the schema, which will be loaded from the F<schema>
directory using appdata_path().  See the description of that method for the
paths that are searched.



( run in 1.780 second using v1.01-cache-2.11-cpan-140bd7fdf52 )