pogpen 0.2.0

renders parameter inputs and a markdown file to an easy-to-use operations game plan
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Playbook</title>
    <script id="content-template" type="text/x-handlebars-template">
        {{{content}}}
    </script>
    <script>
        window.playbook = {
            parameters: 
{{{parameters}}}
        };

        (function () {
            var inputTypeMappings = {text: 'text', secret: 'password', number: 'number'};
            // generate fields for each playbook item
            window.playbook.parameterFields = Object
                .keys(window.playbook.parameters)
                .map(function (paramId) {
                    var param = window.playbook.parameters[paramId];

                    var formatSelector = param.format.toLowerCase();

                    var label = document.createElement('label');
                    var labelText = document.createElement('span');
                    var field;

                    labelText.appendChild(document.createTextNode(param.name || paramId));

                    label.className = 'parameter-label';
                    label.appendChild(labelText);

                    if(formatSelector === 'choice') {
                        // always select the first item
                        param.value = param.values[0];

                        field = document.createElement('select');
                        field.addEventListener('input', function (el) {
                            param.value = el.target.value;
                            if (window.playbook.render) {
                                window.playbook.render();
                            }
                        });

                        param.values.forEach(function (val) {
                            var option = document.createElement('option');
                            option.appendChild(document.createTextNode(val));
                            option.value = val;
                            if (val === param.value) {
                                option.setAttribute('selected', 'selected');
                            }
                            field.appendChild(option);
                        });
                    } else {
                        field = document.createElement('input');

                        if(formatSelector === 'boolean') {
                            field.setAttribute('type', 'checkbox');
                            if(param.value) {
                                field.setAttribute('checked', 'checked');
                            }
                            field.addEventListener('change', function (el) {
                                param.value = !!el.target.checked;
                                if (window.playbook.render) {
                                    window.playbook.render();
                                }
                            });
                        } else {
                            field.setAttribute('type', inputTypeMappings[formatSelector] || 'text');
                            field.value = param.value;
                            field.addEventListener('input', function (el) {
                                param.value = el.target.value;
                                if (window.playbook.render) {
                                    window.playbook.render();
                                }
                            });
                        }
                    }

                    if (field) {
                        label.appendChild(field);
                    }

                    return label;
                });
        })();
    </script>
    <link href="https://fonts.googleapis.com/css?family=Roboto|Roboto+Condensed|Roboto+Mono" rel="stylesheet">
    <style>
        html, body {
            margin: 0;
            padding: 0;
            min-height: 100%;
            background: #efefff;
        }
        * {
            box-sizing: border-box;
            font-family: 'Roboto', sans-serif;
        }
        code, kbd, pre {
            font-family: 'Roboto Mono', monospace;
        }
        div.parameters-config {
            width: 30vw;
            height: 100%;
            background: #fff;
            position: fixed;
            overflow-y: scroll;
        }
        div.parameters-config label {
            display: block;
            min-height: 48px;
        }
        div.parameters-config label input:not([type=checkbox]), div.parameters-config label select {
            display: block;
            width: 100%;
            font-family: 'Roboto Mono', monospace;
            padding: 0.5ex 1em;
            border: 1px solid #233;
            border-radius: 4px;
            margin-bottom: 1em;
        }
        section.playbook-content {
            margin-left: 30vw;
            min-height: 100%;
            overflow-x: hidden;
        }
        div.parameters-config, section.playbook-content {
            padding: 2ex 2em;
        }
        h1, h2, h3, h4, h5, h6 {
            margin: 0;
            margin-bottom: 0.5ex;
            padding: 0;
            padding-bottom: 0.5ex;
            font-family: 'Roboto Condensed', serif;
            font-weight: normal;
            letter-spacing: -0.5px;
            border-bottom: 1px solid #ddd;
        }
        code {
            color: #a22;
        }
        pre {
            width: 100%;
            overflow-x: auto;
            border-radius: 4px;
            padding: 1ex 1em;
            background-color: #233;
        }
        pre>code {
            color: #eee;
            border: none;
            background: transparent;
            padding: none;
        }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js"></script>
    <script>
        Handlebars.registerHelper('parameterVal', function (id) {
            var parameter = window.playbook.parameters[id];

            if (!parameter) {
                return '<<!MISSING PARAMETER DEFINITION FOR "' + id + '">>';
            }

            return parameter.value === undefined ? '' : parameter.value;
        });

        Handlebars.registerHelper('parameterName', function (id) {
            var parameter = window.playbook.parameters[id];

            if (!parameter) {
                return '<<!MISSING PARAMETER DEFINITION FOR "' + id + '">>';
            }

            return parameter.name || id;
 
        });
    </script>
</head>
<body>
    <div class="parameters-config">
        <h3>Parameters</h3>
        <div id="parameters-list"></div>
    </div>
    <section id="playbook-content" class="playbook-content">
    </section>
    <script>
        window.playbook.parameterFields.forEach(function (parameterField) {
            document
                .getElementById('parameters-list')
                .appendChild(parameterField);
        });

        window.playbookTemplate = Handlebars.compile(document.getElementById("content-template").innerHTML);

        window.playbook.render = function () {
            var target = document.getElementById("playbook-content");
            target.innerHTML = window.playbookTemplate(window.playbook);
        }

        window.playbook.render();
    </script>
</body>
</html>