#! /bin/false # Copyright (C) 2016-2018 Guido Flohr <guido.flohr@cantanea.com>, # all rights reserved. # 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 Qgoda::Schema; $Qgoda::Schema::VERSION = 'v0.9.3'; use strict; use Locale::TextDomain qw(qgoda); use Cwd; use JSON::PP; use File::Spec; use Qgoda; use constant true => $JSON::PP::true; use constant false => $JSON::PP::false; sub config { # FIXME! Fill in the variable parts. return { '$schema' => 'http://json-schema.org/draft-07/schema#', '$id' => 'http://www.qgoda.net/schema/Qgoda/v' . $Qgoda::VERSION . '/config.schema.json', title => __"Configuration", description => __"A Qgoda Configuration", type => 'object', properties => { 'case-sensitive' => { description => __"Set to true if a case-sensitive file system " . "shoud be assumed.", type => 'boolean', default => false }, 'compare-output' => { description => __"Should existing output files be read and " . "compared to the new version to avoid " . "updating timestamps (default => true)", type => 'boolean', default => true }, defaults => { description => __"Default values, see " . "http://www.qgoda.net/en/docs/defaults", type => 'array', default => [], items => { description => __"A list of objects with properties " . "'files' and 'values', default => empty", type => 'object', required => [qw(files values)], additionalProperties => false, properties => { files => { description => __"Either one single file name " . "pattern or a list of file name " . "patterns. Files that match will " . "receive the values specified.", type => 'array', items => { type => 'string' }, default => [] }, values => { description => __"Values that should be set for " . "matching files.", type => 'object', default => {} } } } }, exclude => { description => __"List of additional file name patterns that " . "should be ignored for building the site.", type => 'array', items => { type => 'string' }, default => [] }, 'exclude-watch' => { description => __"List of additional file name patterns that " . "should be ignored when changed in watch " . "mode.", type => 'array', items => { type => 'string' }, default => [] }, 'front-matter-placeholder' => { description => __"An object of valid chain names or '*' that " . "give the frontmatter placeholder string " . "for each configured processor chain.", type => 'object', default => { '*' => "[% '' %]\n" } }, generator => { description => __"Value for the generator meta tag in " . "generated pages.", type => 'string', default => __x("Qgoda v{version} (http://www.qgoda.net/)", version => $Qgoda::VERSION), }, helpers => { description => __"Key-value pairs of command identifiers and " . "the command to run in parallel, when running " . "in watch mode. Default: empty.", type => 'object', additionalProperties => false, patternProperties => { '.+' => { type => 'array', items => { type => 'string' } } }, default => {} }, index => { description => __"Basename of a file that is considered to be " . "the index document of a directory.", type => 'string', default => 'index' }, latency => { descriptions => "Number of seconds to wait until a rebuild " . "is triggered after a file system change in " . "watch mode.", type => 'number', minimum => 0, default => 0.5 }, linguas => { description => __"List of language identifiers complying to " . "RFC4647 section 2.1 but without any asterisk " . "(*) characters.", type => 'array', items => { type => 'string', pattern => "[a-zA-Z]{1,8}(-[a-zA-z0-9]{8})?" } }, location => { description => __"Template string for the output location.", type => 'string', default => '/{directory}/{basename}/{index}{suffix}' }, 'no-scm' => { description => __"List of additional file name patterns that " . "should be processed in scm mode, even when " . "not under version control", type => 'array', items => { type => 'string' }, default => [] }, paths => { description => __"Configurable paths.", type => 'object', required => [qw(plugins po site timestamp views)], additionalProperties => false, default => {}, properties => { plugins => { description => __"Directory for plug-ins.", type => 'string', default => '_plugins' }, po => { description => __"Directory for po files and other i18n " . "related files.", type => 'string', default => '_po' }, site => { description => __"Directory where to store rendered " . "files, defaults to the absolute path " . "to '_site' in the current directory.", type => 'string', default => File::Spec->catdir(Cwd::abs_path(''), '_site') }, timestamp => { description => __"Name of the timestamp file containing " . "the seconds since the epoch since " . "the last write of the site.", type => 'string', default => '_timestamp' }, views => { description => __"Directory where view templates are " . "searched.", type => 'string', default => '_views', } } }, permalink => { description => __"Template string for permalinks.", type => 'string', default => '{significant-path}' }, po => { description => __"Variables for internationalization (i18n) and " . "the translation workflow.", type => 'object', additionalProperties => false, default => {}, properties => { 'copyright-holder' => { description => __"Copyright information for the original " . "content.", type => 'string', default => __x("Set {variable} in '_config.yaml'.", variable => 'config.po.copyright-holder') }, mdextra => { description => __"List of file name patterns for " . "additional markdown files to " . "translate.", type => 'array', items => { type => 'string' }, default => [] }, msgfmt => { description => __"The 'msgfmt' command or an array of " . "the program name plus arguments.", type => 'array', items => { type => 'string' }, default => ['msgfmt'] }, 'msgid-bugs-address' => { description => __"Where to report translation problems " . "with the original strings.", type => 'string', default => __x("Set {variable} in '_config.yaml'.", variable => 'config.po.msgid-bugs-address') }, msgmerge => { description => __"The 'msgmerge' command(or an array of " . "the program name plus arguments.", type => 'array', items => { type => 'string' }, default => ['msgmerge'] }, qgoda => { description => __"The 'qgoda' command or an array of the " . "program name plus arguments.", type => 'array', items => { type => 'string' }, default => ['qgoda'], }, reload => { description => __"Whether to throw away the " . "translation before every rebuild, " . "defaults to false.", type => 'boolean', default => false }, textdomain => { description => __"An identifier for the translation " . "catalog (textdomain), defaults to " . "'messages'.", type => 'string', default => 'messages' }, tt2 => { description => __"A list of file name patterns or one " . "single pattern, where translatable " . "templates for the Template Toolkit " . "version 2 are stored, defaults to " . "'_views'.", type => 'array', items => { type => 'string' }, # Default value will be set after parsing, if still # empty. See https://github.com/epoberezkin/ajv/issues/681 default => [] }, xgettext => { description => __"The 'xgettext' command or an array of " . "the program name plus arguments.", type => 'array', items => { type => 'string' }, default => ['xgettext'] }, 'xgettext-tt2' => { description => __"The 'xgettext-tt2' command or an " . "array of the program name plus " . "arguments.", type => 'array', items => { type => 'string' }, default => ['xgettext-tt2'] } } }, processors => { description => __"The processors to use for generating " . "content.", additionalProperties => false, default => {}, required => ['chains', 'options', 'triggers'], properties => { chains => { description => __"The processor chains.", default => { html => { modules => ['TT2', 'Strip', 'HTMLFilter'] }, markdown => { modules => ['TT2', 'Strip', 'Markdown'], suffix => 'html', wrapper => 'html' }, xml => { modules => ['TT2', 'Strip'] } }, patternProperties => { '[_a-zA-z][a-zA-Z0-9]*' => { description => __"Properties of one processor " . "chain.", type => 'object', addititionalProperties => false, required => ['modules'], properties => { modules => { description => __"The module names.", type => 'array', items => { type => 'string' }, #minLength => 1 # The possible values are filled at # run-time. }, suffix => { description => __"An optional suffix " . "if different from " . "original filename.", type => 'string', #minLength => 1, }, wrapper => { description => __"An optional wrapper " . "for a second run.", type => 'string', #minLength => 1 # The possible values are filled at # run-time. } } } } }, options => { description => __"Additional options for the" . " processor plug-ins", type => 'object', default => { HTMLFilter => { TOC => { 'content-tag' => 'qgoda-content', 'toc-tag' => 'qgoda-toc', start => 2, end => 6, template => 'components/toc.html' }, AnchorTarget => {}, Generator => {}, CleanUp => {}, }, }, }, triggers => { description => __"Filename extenders that trigger a " . " particular chain if not specified" . " in front matter or defaults.", default => { htm => 'html', html => 'html', md => 'markdown', mdown => 'markdown', mdwn => 'markdown', mkd => 'markdown', mkdn => 'markdown', xml => 'xml' }, patternProperties => { '.+' => { description => __"The filename extender.", type => 'string' } } } }, }, scm => { description => __"Source code management (SCM) that is in " . "use. If present, only files that are under " . "version control and those matching 'no-scm' " . "are processed. Currently only git is " . "supported.", type => 'string', const => 'git' }, srcdir => { description => __"The source directory for all assets. Do " . "not set that variable yourself! It will be " . "overwritten at runtime with the absolute " . "path to the current directory.", type => 'string', const => Cwd::abs_path() }, taxonomies => { description => __"Key/value pairs of taxonomy names and their " . "respective weights for the computation " . "of relatedness.", type => 'object', default => { categories => 3, links => 1, tags => 2 } }, title => { description => __"The title of the site. It has no " . "particular semantics.", default => __"A new Qgoda Powered Site", }, view => { description => __"The default view template to use.", default => 'default.html', minLength => 1, } } } }; 1;