diff --git a/MANIFEST.in b/MANIFEST.in index e00b83e..d6f43a3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,2 @@ -recursive-include spyglass/utils/editor/static * -recursive-include spyglass/utils/editor/templates * recursive-include spyglass/ **.yaml recursive-include spyglass/ **.json diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst index bca3532..ef1df4a 100644 --- a/doc/source/getting_started.rst +++ b/doc/source/getting_started.rst @@ -72,9 +72,6 @@ Supported Features 2. Remote Data Source Plugin: Supports extracting site data from a REST endpoint. -3. YAML Editor for Intermediary YAML: Support runtime editing of missing - site parameters, see :ref:`yaml-editor-info` - Future Work ----------- 1) Schema based manifest generation instead of Jinja2 templates. It shall @@ -160,7 +157,6 @@ Options: excel spec -idir, --intermediary_dir PATH The path where intermediary file needs to be generated - -e, --edit_intermediary Flag to let user edit intermediary -m, --generate_manifests Generate manifests from the generated intermediary file -mdir, --manifest_dir PATH The path where manifest files needs to be diff --git a/doc/source/index.rst b/doc/source/index.rst index 924681c..b0ec2b9 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -33,4 +33,3 @@ fed to Shipyard for site deployment / updates. getting_started tugboat - yaml-editor diff --git a/doc/source/yaml-editor.rst b/doc/source/yaml-editor.rst deleted file mode 100644 index 7e5a246..0000000 --- a/doc/source/yaml-editor.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. - Copyright 2018 AT&T Intellectual Property. - All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); you may - not use this file except in compliance with the License. You may obtain - a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - License for the specific language governing permissions and limitations - under the License. - -.. _yaml-editor-info: - -=========== -Yaml Editor -=========== - -What is Yaml Editor? --------------------- - -Yaml Editor is a spyglass utility which lets user edit their generated -intermediary file in a browser window. It is a minimal flask app which is -invoked from the parser engine in order to let user edit fields which -could not be fetched via :ref:`tugboatinfo` plugin. - - -Yaml Editor Utility Inputs --------------------------- - - a) Yaml File: Yaml file required to be edited (This is required field) - b) Port: Port on which app shall be running - c) Host: This is only used to form URL which can be followed to open file in browser - d) String: String which is required to be updated in the file (default is '#CHANGE_ME') - -Yaml Editor Utility Usage -------------------------- - - With Spyglass (edit option is True by default): - :: - - spyglass -mg --edit_intermediary -t tugboat -x SiteDesignSpec_v0.1.xlsx -e excel_spec_upstream.yaml -d site_config.yaml -s airship-seaworthy --template_dir= - - Help: - :: - - > yaml-editor --help - Usage: yaml-editor [OPTIONS] - - Options: - -f, --file FILENAME Path with file name to the intermediary yaml file. - [required] - -h, --host TEXT Optional host parameter to run Flask on. - -p, --port INTEGER Optional port parameter to run Flask on. - -s, --string TEXT Text which is required to be changed on yaml file. - --help Show this message and exit. diff --git a/setup.py b/setup.py index 4b43c75..12326cd 100644 --- a/setup.py +++ b/setup.py @@ -30,13 +30,10 @@ setup( 'netaddr', 'pyyaml', 'jinja2', - 'flask', - 'flask-bootstrap', ], entry_points={ 'console_scripts': [ 'spyglass=spyglass.spyglass:main', - 'yaml-editor=spyglass.utils.editor.editor:main', ], 'data_extractor_plugins': ['formation=spyglass.data_extractor.plugins.formation:FormationPlugin', diff --git a/spyglass/parser/engine.py b/spyglass/parser/engine.py index f3ba441..95ab944 100644 --- a/spyglass/parser/engine.py +++ b/spyglass/parser/engine.py @@ -15,11 +15,9 @@ import copy import json import logging -import os import pkg_resources import pprint import sys -import tempfile import jsonschema import netaddr @@ -394,28 +392,11 @@ class ProcessDataSource: f.write(yaml_file) f.close() - def generate_intermediary_yaml(self, edit_intermediary=False): + def generate_intermediary_yaml(self): """ Generating intermediary yaml """ LOG.info("Start: Generate Intermediary") self._apply_design_rules() self._get_genesis_node_details() # This will validate the extracted data from different sources. self._validate_intermediary_data(self.data) - if edit_intermediary: - self.edit_intermediary_yaml() - # This will check if user edited changes are in order. - self._validate_intermediary_data(self.data) - self.intermediary_yaml = self.data - return self.intermediary_yaml - - def edit_intermediary_yaml(self): - """ Edit generated data using on browser """ - LOG.info( - "edit_intermediary_yaml: Invoking web server for yaml editing" - ) - with tempfile.NamedTemporaryFile(mode="r+") as file_obj: - yaml.safe_dump(self.data, file_obj, default_flow_style=False) - host = self._get_genesis_node_ip() - os.system("yaml-editor -f {0} -h {1}".format(file_obj.name, host)) - file_obj.seek(0) - self.data = yaml.safe_load(file_obj) + return self.data diff --git a/spyglass/spyglass.py b/spyglass/spyglass.py index 9d53a3a..7a3733e 100644 --- a/spyglass/spyglass.py +++ b/spyglass/spyglass.py @@ -64,12 +64,6 @@ LOG = logging.getLogger("spyglass") type=click.Path(exists=True), help="The path where intermediary file needs to be generated", ) -@click.option( - "--edit_intermediary/--no_edit_intermediary", - "-e/-nedit", - default=True, - help="Flag to let user edit intermediary", -) @click.option( "--generate_manifests", "-m", @@ -117,7 +111,6 @@ def main(*args, **kwargs): # Extract user provided inputs generate_intermediary = kwargs["generate_intermediary"] intermediary_dir = kwargs["intermediary_dir"] - edit_intermediary = kwargs["edit_intermediary"] generate_manifests = kwargs["generate_manifests"] manifest_dir = kwargs["manifest_dir"] intermediary = kwargs["intermediary"] @@ -208,9 +201,7 @@ def main(*args, **kwargs): ) LOG.info("Generate intermediary yaml") - intermediary_yaml = process_input_ob.generate_intermediary_yaml( - edit_intermediary - ) + intermediary_yaml = process_input_ob.generate_intermediary_yaml() else: LOG.info("Loading intermediary from user provided input") with open(intermediary, "r") as intermediary_file: diff --git a/spyglass/utils/editor/__init__.py b/spyglass/utils/editor/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/spyglass/utils/editor/editor.py b/spyglass/utils/editor/editor.py deleted file mode 100644 index 726e0e3..0000000 --- a/spyglass/utils/editor/editor.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright 2018 AT&T Intellectual Property. All other rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the 'License'); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an 'AS IS' BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import json -import logging -import os -import sys - -import click -import yaml - -from flask import Flask, request, render_template, send_from_directory -from flask_bootstrap import Bootstrap - - -app_path = os.path.dirname(os.path.abspath(__file__)) -app = Flask( - "Yaml Editor!", - template_folder=os.path.join(app_path, "templates"), - static_folder=os.path.join(app_path, "static"), -) -Bootstrap(app) -logging.getLogger("werkzeug").setLevel(logging.ERROR) -LOG = app.logger - - -@app.route("/favicon.ico") -def favicon(): - return send_from_directory(app.static_folder, "favicon.ico") - - -@app.route("/", methods=["GET", "POST"]) -def index(): - """Renders index page to edit provided yaml file.""" - LOG.info("Rendering yaml file for editing") - with open(app.config["YAML_FILE"]) as file_obj: - data = yaml.safe_load(file_obj) - return render_template( - "yaml.html", - data=json.dumps(data), - change_str=app.config["STRING_TO_CHANGE"], - ) - - -@app.route("/save", methods=["POST"]) -def save(): - """Save current progress on file.""" - LOG.info("Saving edited inputs from user to yaml file") - out = request.json.get("yaml_data") - with open(app.config["YAML_FILE"], "w") as file_obj: - yaml.safe_dump(out, file_obj, default_flow_style=False) - return "Data saved successfully!" - - -@app.route("/saveExit", methods=["POST"]) -def save_exit(): - """Save current progress on file and shuts down the server.""" - LOG.info( - "Saving edited inputs from user to yaml file and shutting" - " down server" - ) - out = request.json.get("yaml_data") - with open(app.config["YAML_FILE"], "w") as file_obj: - yaml.safe_dump(out, file_obj, default_flow_style=False) - func = request.environ.get("werkzeug.server.shutdown") - if func: - func() - return "Saved successfully, Shutting down app! You may close the tab!" - - -@app.errorhandler(404) -def page_not_found(e): - """Serves 404 error.""" - LOG.info("User tried to access unavailable page.") - return "

404: Page not Found!

" - - -def run(*args, **kwargs): - """Starts the server.""" - LOG.info("Initiating web server for yaml editing") - port = kwargs.get("port", None) - if not port: - port = 8161 - app.run(host="0.0.0.0", port=port, debug=False) - - -@click.command() -@click.option( - "--file", - "-f", - required=True, - type=click.File(), - multiple=False, - help="Path with file name to the intermediary yaml file.", -) -@click.option( - "--host", - "-h", - default="0.0.0.0", - type=click.STRING, - multiple=False, - help="Optional host parameter to run Flask on.", -) -@click.option( - "--port", - "-p", - default=8161, - type=click.INT, - multiple=False, - help="Optional port parameter to run Flask on.", -) -@click.option( - "--string", - "-s", - default="#CHANGE_ME", - type=click.STRING, - multiple=False, - help="Text which is required to be changed on yaml file.", -) -def main(*args, **kwargs): - LOG.setLevel(logging.INFO) - LOG.info("Initiating yaml-editor") - try: - yaml.safe_load(kwargs["file"]) - except yaml.YAMLError as e: - LOG.error("EXITTING - Please provide a valid yaml file.") - if hasattr(e, "problem_mark"): - mark = e.problem_mark - LOG.error( - "Error position: ({0}:{1})".format( - mark.line + 1, mark.column + 1 - ) - ) - sys.exit(2) - except Exception: - LOG.error("EXITTING - Please provide a valid yaml file.") - sys.exit(2) - LOG.info( - """ - -############################################################################## - -Please go to http://{0}:{1}/ to edit your yaml file. - -############################################################################## - - """.format( - kwargs["host"], kwargs["port"] - ) - ) - app.config["YAML_FILE"] = kwargs["file"].name - app.config["STRING_TO_CHANGE"] = kwargs["string"] - run(*args, **kwargs) - - -if __name__ == "__main__": - """Invoked when used as a script.""" - main() diff --git a/spyglass/utils/editor/static/app.js b/spyglass/utils/editor/static/app.js deleted file mode 100644 index b0e834a..0000000 --- a/spyglass/utils/editor/static/app.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2018 AT&T Intellectual Property. All other rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -// This file includes all the frond-end functionality being used for the -// yaml editor application. - - -/** - * Calls /save URL to save edit progress. - * @param {String} data Stringified JSON data. - */ -function save(data) { - $.ajax({ - type: 'POST', - url: '/save', - data: data, - success: function(res) { - setTimeout(function() { alert(res); }, 3); - }, - contentType: 'application/json;charset=UTF-8' - }); -} - -/** - * Calls /saveExit URL to save edit progress and shut down web server. - * @param {String} data Stringified JSON data. - */ -function saveAndExit(data) { - $.ajax({ - type: 'POST', - url: '/saveExit', - data: data, - success: function(res) { - setTimeout(function() { alert(res); }, 3); - }, - contentType: 'application/json;charset=UTF-8' - }); -} - -/** - * Collects and validates data from textarea. - * @returns {String} Stringified JSON data. - */ -function getSimpleData() { - var data = $("#yaml_data").val(); - try { - var index = data.indexOf(changeStr) - if (index != -1) { - var lineNum = data.substring(0, index).split('\n').length; - alert('Please change value on line '+ lineNum + '!') - return null - } - data = jsyaml.load(data) - } - catch(err) { - alert(err) - return null - } - return JSON.stringify({yaml_data : data}) -} - -/** - * Function to save edit progress. - */ -function saveSimple() { - var data = getSimpleData() - if (data) { - save(data) - } -} - -/** - * Function to save edit progress and shut down web server. - */ -function saveExitSimple() { - var data = getSimpleData() - if (data) { - saveAndExit(data) - } -} diff --git a/spyglass/utils/editor/static/favicon.ico b/spyglass/utils/editor/static/favicon.ico deleted file mode 100644 index d3dca27..0000000 Binary files a/spyglass/utils/editor/static/favicon.ico and /dev/null differ diff --git a/spyglass/utils/editor/static/jquery-linedtextarea.css b/spyglass/utils/editor/static/jquery-linedtextarea.css deleted file mode 100755 index 82ad0bd..0000000 --- a/spyglass/utils/editor/static/jquery-linedtextarea.css +++ /dev/null @@ -1,68 +0,0 @@ -/** - * jQuery Lined Textarea Plugin - * http://alan.blog-city.com/jquerylinedtextarea.htm - * - * Copyright (c) 2010 Alan Williamson - * - * Released under the MIT License: - * http://www.opensource.org/licenses/mit-license.php - * - * Usage: - * Displays a line number count column to the left of the textarea - * - * Class up your textarea with a given class, or target it directly - * with JQuery Selectors - * - * $(".lined").linedtextarea({ - * selectedLine: 10, - * selectedClass: 'lineselect' - * }); - * - */ - -.linedwrap { - border: 1px solid #c0c0c0; - padding: 3px; -} - -.linedtextarea { - padding: 0px; - margin: 0px; -} - -.linedtextarea textarea, .linedwrap .codelines .lineno { - font-size: 10pt; - font-family: monospace; - line-height: normal !important; -} - -.linedtextarea textarea { - padding-right:0.3em; - padding-top:0.3em; - border: 0; -} - -.linedwrap .lines { - margin-top: 0px; - width: 50px; - float: left; - overflow: hidden; - border-right: 1px solid #c0c0c0; - margin-right: 10px; -} - -.linedwrap .codelines { - padding-top: 5px; -} - -.linedwrap .codelines .lineno { - color:#AAAAAA; - padding-right: 0.5em; - padding-top: 0.0em; - text-align: right; - white-space: nowrap; -} - -.linedwrap .codelines .lineselect { - color: red; -} diff --git a/spyglass/utils/editor/static/jquery-linedtextarea.js b/spyglass/utils/editor/static/jquery-linedtextarea.js deleted file mode 100755 index b3699d6..0000000 --- a/spyglass/utils/editor/static/jquery-linedtextarea.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * jQuery Lined Textarea Plugin - * http://alan.blog-city.com/jquerylinedtextarea.htm - * - * Copyright (c) 2010 Alan Williamson - * - * Version: - * $Id: jquery-linedtextarea.js 464 2010-01-08 10:36:33Z alan $ - * - * Released under the MIT License: - * http://www.opensource.org/licenses/mit-license.php - * - * Usage: - * Displays a line number count column to the left of the textarea - * - * Class up your textarea with a given class, or target it directly - * with JQuery Selectors - * - * $(".lined").linedtextarea({ - * selectedLine: 10, - * selectedClass: 'lineselect' - * }); - * - * History: - * - 2010.01.08: Fixed a Google Chrome layout problem - * - 2010.01.07: Refactored code for speed/readability; Fixed horizontal sizing - * - 2010.01.06: Initial Release - * - */ -(function($) { - - $.fn.linedtextarea = function(options) { - - // Get the Options - var opts = $.extend({}, $.fn.linedtextarea.defaults, options); - - - /* - * Helper function to make sure the line numbers are always - * kept up to the current system - */ - var fillOutLines = function(codeLines, h, lineNo){ - while ( (codeLines.height() - h ) <= 0 ){ - if ( lineNo == opts.selectedLine ) - codeLines.append("
" + lineNo + "
"); - else - codeLines.append("
" + lineNo + "
"); - - lineNo++; - } - return lineNo; - }; - - - /* - * Iterate through each of the elements are to be applied to - */ - return this.each(function() { - var lineNo = 1; - var textarea = $(this); - - /* Turn off the wrapping of as we don't want to screw up the line numbers */ - textarea.attr("wrap", "off"); - textarea.css({resize:'none'}); - var originalTextAreaWidth = textarea.outerWidth(); - - /* Wrap the text area in the elements we need */ - textarea.wrap("
"); - var linedTextAreaDiv = textarea.parent().wrap("
"); - var linedWrapDiv = linedTextAreaDiv.parent(); - - linedWrapDiv.prepend("
"); - - var linesDiv = linedWrapDiv.find(".lines"); - linesDiv.height( textarea.height() + 6 ); - - - /* Draw the number bar; filling it out where necessary */ - linesDiv.append( "
" ); - var codeLinesDiv = linesDiv.find(".codelines"); - lineNo = fillOutLines( codeLinesDiv, linesDiv.height(), 1 ); - - /* Move the textarea to the selected line */ - if ( opts.selectedLine != -1 && !isNaN(opts.selectedLine) ){ - var fontSize = parseInt( textarea.height() / (lineNo-2) ); - var position = parseInt( fontSize * opts.selectedLine ) - (textarea.height()/2); - textarea[0].scrollTop = position; - } - - - /* Set the width */ - var sidebarWidth = linesDiv.outerWidth(); - var paddingHorizontal = parseInt( linedWrapDiv.css("border-left-width") ) + parseInt( linedWrapDiv.css("border-right-width") ) + parseInt( linedWrapDiv.css("padding-left") ) + parseInt( linedWrapDiv.css("padding-right") ); - var linedWrapDivNewWidth = originalTextAreaWidth - paddingHorizontal; - var textareaNewWidth = originalTextAreaWidth - sidebarWidth - paddingHorizontal - 20; - - textarea.width( textareaNewWidth ); - linedWrapDiv.width( linedWrapDivNewWidth ); - - - - /* React to the scroll event */ - textarea.scroll( function(tn){ - var domTextArea = $(this)[0]; - var scrollTop = domTextArea.scrollTop; - var clientHeight = domTextArea.clientHeight; - codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} ); - lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo ); - }); - - - /* Should the textarea get resized outside of our control */ - textarea.resize( function(tn){ - var domTextArea = $(this)[0]; - linesDiv.height( domTextArea.clientHeight + 6 ); - }); - - }); - }; - - // default options - $.fn.linedtextarea.defaults = { - selectedLine: -1, - selectedClass: 'lineselect' - }; -})(jQuery); diff --git a/spyglass/utils/editor/static/js-yaml.min.js b/spyglass/utils/editor/static/js-yaml.min.js deleted file mode 100644 index 078bf73..0000000 --- a/spyglass/utils/editor/static/js-yaml.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).jsyaml=e()}}(function(){return function o(a,s,c){function u(t,e){if(!s[t]){if(!a[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);var i=new Error("Cannot find module '"+t+"'");throw i.code="MODULE_NOT_FOUND",i}var r=s[t]={exports:{}};a[t][0].call(r.exports,function(e){return u(a[t][1][e]||e)},r,r.exports,o,a,s,c)}return s[t].exports}for(var l="function"==typeof require&&require,e=0;e=i.flowLevel;switch(H(r,n,i.indent,t,function(e){return function(e,t){var n,i;for(n=0,i=e.implicitTypes.length;n"+V(r,i.indent)+Z(L(function(e,t){var n,i,r=/(\n+)([^\n]*)/g,o=(s=e.indexOf("\n"),s=-1!==s?s:e.length,r.lastIndex=s,z(e.slice(0,s),t)),a="\n"===e[0]||" "===e[0];var s;for(;i=r.exec(e);){var c=i[1],u=i[2];n=" "===u[0],o+=c+(a||n||""===u?"":"\n")+z(u,t),a=n}return o}(r,t),e));case $:return'"'+function(e){for(var t,n,i,r="",o=0;ot&&o tag resolver accepts not "'+c+'" style');i=s.represent[c](t,c)}e.dump=i}return!0}return!1}function Q(e,t,n,i,r,o){e.tag=null,e.dump=n,J(e,n,!1)||J(e,n,!0);var a=l.call(e.dump);i&&(i=e.flowLevel<0||e.flowLevel>t);var s,c,u="[object Object]"===a||"[object Array]"===a;if(u&&(c=-1!==(s=e.duplicates.indexOf(n))),(null!==e.tag&&"?"!==e.tag||c||2!==e.indent&&0 "+e.dump)}return!0}function X(e,t){var n,i,r=[],o=[];for(function e(t,n,i){var r,o,a;if(null!==t&&"object"==typeof t)if(-1!==(o=n.indexOf(t)))-1===i.indexOf(o)&&i.push(o);else if(n.push(t),Array.isArray(t))for(o=0,a=t.length;ot)&&0!==i)_(e,"bad indentation of a sequence entry");else if(e.lineIndentt?d=1:e.lineIndent===t?d=0:e.lineIndentt?d=1:e.lineIndent===t?d=0:e.lineIndentt)&&(K(e,t,b,!0,r)&&(m?d=e.result:h=e.result),m||(D(e,l,p,f,d,h,o,a),f=d=h=null),q(e,!0,-1),s=e.input.charCodeAt(e.position)),e.lineIndent>t&&0!==s)_(e,"bad indentation of a mapping entry");else if(e.lineIndentl&&(l=e.lineIndent),j(o))p++;else{if(e.lineIndent>10),56320+(c-65536&1023)),e.position++}else _(e,"unknown escape sequence");n=i=e.position}else j(s)?(T(e,n,i,!0),R(e,q(e,!1,t)),n=i=e.position):e.position===e.lineStart&&Y(e)?_(e,"unexpected end of the document within a double quoted scalar"):(e.position++,i=e.position)}_(e,"unexpected end of the stream within a double quoted scalar")}(e,p)?m=!0:!function(e){var t,n,i;if(42!==(i=e.input.charCodeAt(e.position)))return!1;for(i=e.input.charCodeAt(++e.position),t=e.position;0!==i&&!I(i)&&!E(i);)i=e.input.charCodeAt(++e.position);return e.position===t&&_(e,"name of an alias node must contain at least one character"),n=e.input.slice(t,e.position),e.anchorMap.hasOwnProperty(n)||_(e,'unidentified alias "'+n+'"'),e.result=e.anchorMap[n],q(e,!0,-1),!0}(e)?function(e,t,n){var i,r,o,a,s,c,u,l,p=e.kind,f=e.result;if(I(l=e.input.charCodeAt(e.position))||E(l)||35===l||38===l||42===l||33===l||124===l||62===l||39===l||34===l||37===l||64===l||96===l)return!1;if((63===l||45===l)&&(I(i=e.input.charCodeAt(e.position+1))||n&&E(i)))return!1;for(e.kind="scalar",e.result="",r=o=e.position,a=!1;0!==l;){if(58===l){if(I(i=e.input.charCodeAt(e.position+1))||n&&E(i))break}else if(35===l){if(I(e.input.charCodeAt(e.position-1)))break}else{if(e.position===e.lineStart&&Y(e)||n&&E(l))break;if(j(l)){if(s=e.line,c=e.lineStart,u=e.lineIndent,q(e,!1,-1),e.lineIndent>=t){a=!0,l=e.input.charCodeAt(e.position);continue}e.position=o,e.line=s,e.lineStart=c,e.lineIndent=u;break}}a&&(T(e,r,o,!1),R(e,e.line-s),r=o=e.position,a=!1),S(l)||(o=e.position+1),l=e.input.charCodeAt(++e.position)}return T(e,r,o,!1),!!e.result||(e.kind=p,e.result=f,!1)}(e,p,x===n)&&(m=!0,null===e.tag&&(e.tag="?")):(m=!0,null===e.tag&&null===e.anchor||_(e,"alias node should not have any properties")),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):0===d&&(m=s&&B(e,f))),null!==e.tag&&"!"!==e.tag)if("?"===e.tag){for(c=0,u=e.implicitTypes.length;c tag; it should be "'+l.kind+'", not "'+e.kind+'"'),l.resolve(e.result)?(e.result=l.construct(e.result),null!==e.anchor&&(e.anchorMap[e.anchor]=e.result)):_(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")):_(e,"unknown tag !<"+e.tag+">");return null!==e.listener&&e.listener("close",e),null!==e.tag||null!==e.anchor||m}function $(e){var t,n,i,r,o=e.position,a=!1;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap={},e.anchorMap={};0!==(r=e.input.charCodeAt(e.position))&&(q(e,!0,-1),r=e.input.charCodeAt(e.position),!(0t/2-1){n=" ... ",i+=5;break}for(r="",o=this.position;ot/2-1){r=" ... ",o-=5;break}return a=this.buffer.slice(i,o),s.repeat(" ",e)+n+a+r+"\n"+s.repeat(" ",e+this.position-i+n.length)+"^"},i.prototype.toString=function(e){var t,n="";return this.name&&(n+='in "'+this.name+'" '),n+="at line "+(this.line+1)+", column "+(this.column+1),e||(t=this.getSnippet())&&(n+=":\n"+t),n},t.exports=i},{"./common":2}],7:[function(e,t,n){"use strict";var i=e("./common"),r=e("./exception"),o=e("./type");function a(e,t,i){var r=[];return e.include.forEach(function(e){i=a(e,t,i)}),e[t].forEach(function(n){i.forEach(function(e,t){e.tag===n.tag&&e.kind===n.kind&&r.push(t)}),i.push(n)}),i.filter(function(e,t){return-1===r.indexOf(t)})}function s(e){this.include=e.include||[],this.implicit=e.implicit||[],this.explicit=e.explicit||[],this.implicit.forEach(function(e){if(e.loadKind&&"scalar"!==e.loadKind)throw new r("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.")}),this.compiledImplicit=a(this,"implicit",[]),this.compiledExplicit=a(this,"explicit",[]),this.compiledTypeMap=function(){var e,t,n={scalar:{},sequence:{},mapping:{},fallback:{}};function i(e){n[e.kind][e.tag]=n.fallback[e.tag]=e}for(e=0,t=arguments.length;e>16&255),s.push(a>>8&255),s.push(255&a)),a=a<<6|o.indexOf(i.charAt(t));return 0==(n=r%4*6)?(s.push(a>>16&255),s.push(a>>8&255),s.push(255&a)):18===n?(s.push(a>>10&255),s.push(a>>2&255)):12===n&&s.push(a>>4&255),c?c.from?c.from(s):new c(s):s},predicate:function(e){return c&&c.isBuffer(e)},represent:function(e){var t,n,i="",r=0,o=e.length,a=u;for(t=0;t>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]),r=(r<<8)+e[t];return 0==(n=o%3)?(i+=a[r>>18&63],i+=a[r>>12&63],i+=a[r>>6&63],i+=a[63&r]):2===n?(i+=a[r>>10&63],i+=a[r>>4&63],i+=a[r<<2&63],i+=a[64]):1===n&&(i+=a[r>>2&63],i+=a[r<<4&63],i+=a[64],i+=a[64]),i}})},{"../type":13}],15:[function(e,t,n){"use strict";var i=e("../type");t.exports=new i("tag:yaml.org,2002:bool",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t=e.length;return 4===t&&("true"===e||"True"===e||"TRUE"===e)||5===t&&("false"===e||"False"===e||"FALSE"===e)},construct:function(e){return"true"===e||"True"===e||"TRUE"===e},predicate:function(e){return"[object Boolean]"===Object.prototype.toString.call(e)},represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"})},{"../type":13}],16:[function(e,t,n){"use strict";var i=e("../common"),r=e("../type"),o=new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");var a=/^[-+]?[0-9]+e/;t.exports=new r("tag:yaml.org,2002:float",{kind:"scalar",resolve:function(e){return null!==e&&!(!o.test(e)||"_"===e[e.length-1])},construct:function(e){var t,n,i,r;return n="-"===(t=e.replace(/_/g,"").toLowerCase())[0]?-1:1,r=[],0<="+-".indexOf(t[0])&&(t=t.slice(1)),".inf"===t?1===n?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:".nan"===t?NaN:0<=t.indexOf(":")?(t.split(":").forEach(function(e){r.unshift(parseFloat(e,10))}),t=0,i=1,r.forEach(function(e){t+=e*i,i*=60}),n*t):n*parseFloat(t,10)},predicate:function(e){return"[object Number]"===Object.prototype.toString.call(e)&&(e%1!=0||i.isNegativeZero(e))},represent:function(e,t){var n;if(isNaN(e))switch(t){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(t){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(t){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(i.isNegativeZero(e))return"-0.0";return n=e.toString(10),a.test(n)?n.replace("e",".e"):n},defaultStyle:"lowercase"})},{"../common":2,"../type":13}],17:[function(e,t,n){"use strict";var i=e("../common"),r=e("../type");t.exports=new r("tag:yaml.org,2002:int",{kind:"scalar",resolve:function(e){if(null===e)return!1;var t,n,i,r,o=e.length,a=0,s=!1;if(!o)return!1;if("-"!==(t=e[a])&&"+"!==t||(t=e[++a]),"0"===t){if(a+1===o)return!0;if("b"===(t=e[++a])){for(a++;a -{% endblock %} - -{% block scripts %} -{{super()}} - - - - -{% endblock %} - -{% block content %} - -
-
-
Edit your YAML (Update corresponding fields with {{ change_str }} text):
-
- -
-
-
- - -
-
- -{% endblock %}