#!/usr/bin/perl use v5.18; # needed for \h (horizontal whitespace) in regexes use strict; use warnings; use autodie; use List::Util qw(pairs); use Config::Tiny; use Path::Tiny; use Text::Hogan::Compiler; use IO::Prompter; =head1 NAME mkdocs-prep - mkdocs preprocessor expanding inline hints and mustache tokens =head1 VERSION Version 0.02 =head1 SYNOPSIS =head1 DESCRIPTION B prepares a markdown document for B processing. The document is converted using inline hint section to a mustache template and resolved using an external set of single-word tokens. A document section named "Special strings" is parsed for token definitions where each line lists a single-word token, a colon, and default string. The section is then stripped, and all occurences of default strings are replaced with tokens wrapped with double curly brackets. Template tokens are gathered from external config file F, where each line lists a token, an equals sign, and replacement string. Inline defined tokens not declared in F will be prompted for. if a value is provided it will be used, and also saved in F. If no value is provided then inline default string is used. Each token in the document, wrapped with double curly brackets {{like_this}}, is replaced (including brackets) with corresponding string. =cut my ( $infile, $outfile ) = @ARGV; @ARGV = undef; my $cfgfile = path('site.mk'); my $config = $cfgfile->exists ? Config::Tiny->read( $cfgfile, 'utf8' ) : Config::Tiny->new; my $config_has_changed; my $content = path($infile)->slurp_utf8; $content =~ s/^#+\s*Special strings\s*\n((?:\n|[^#\n][^\n]*\n)*)//m; my $section = $1 || ''; my %defaults; while ( $section =~ /^(\w+)\h*:\h*(\w\S*(?:\h+\S+)*)/mg ) { my $token = $1; my $string = $2; unless ( exists $config->{_}->{$1} ) { $_ = prompt "Which string should replace token '$token'?"; next unless $_; $config->{_}->{$1} = $_; $config_has_changed++; } $content =~ s/\Q$string\E/{{$token}}/g; }; my $compiler = Text::Hogan::Compiler->new; my $template = $compiler->compile($content); path($outfile)->spew_utf8( $template->render( $config->{_} ) ); $cfgfile->touch; $config->write( $cfgfile, 'utf8' ) if $config_has_changed; 1;