@phoenix-plugin-registry/brackets-markdown-preview
Version: 
Markdown live preview incl. detached window, code syntax highlighting, output themes, adaptive preview width, graphical checkboxes, activation on start...
179 lines (164 loc) • 8.26 kB
JavaScript
/**
 * @module      ExtLoggingUtils
 * @file        Functions and classes helping to develop and debug a brackets extension using structured 'use case oriented' log entries (hence the object type name 'LogCase').
 * @author      Loïs Bégué
 * @license     MIT license (MIT)
 * @copyright   Copyright (c) 2017 Loïs Bégué
 */
/*global define, $, brackets, window */
define(function (require, exports, module) {
    "use strict";
    /**
     * The log case object can be used to debug a particular use/test case i.e. a particular code block.
     * The log entries are collected in a case specific array (e.g. to review them at a later stage).
     * The log entries can optionaly show up directly in the console. An optional time stamp can be added to the entries.
     * @typedef LogCase
     * @type {object}
     * @property {number} ID - the ID of the log/test case (automatically incremented).
     * @property {string} description - The description of the logcase.
     * @property {string[]} logArray - The array of log entries of the logcase.
     * @property {boolean} verbose - directly writes the logs in the console when 'true'
     * @property {function} log - create, save a log entry and (optionally) write it to the console
     * @property {string} fulllog - the entire log of the log case object (each entry on a new line)
     * @property {function} start - Registers the start of the log case and writes an entry in the log
     * @property {function} end - Registers the end of the log case and writes an entry in the log
     * @property {boolean} timed - Writes a time stamp on each log entry when set to 'true'
     * @property {boolean} started - 'true' when the 'start' method has been called
     * @property {boolean} completed - 'true' when the 'end' method has been called
     * @property {object} startTime - the date object correpsonding to the start of the case
     * @property {object} endTime - the date object correpsonding to the end of the case
     */    
    // Register local extension modules
    var ExtUtils        = require("scripts/ExtUtils");
    // Module variables and constants
    var _logCaseID = 0; // 0 = first log case ID
    var logSeparator = "-----------------------------------------------------------";
    const defaultDesc = "no description available";
    /**
     * Insert an entry in the log of the case and (optionally) write it to the console.
     * May add a time stamp to the entry when the 'timed' option is set to 'true'.
     * If no text is provided, a divider/separator line will be inserted instead.
     * If 'timed' is 'true' and no time stamp is provided, the current date will be used as a time stamp.
     * @author Loïs Bégué
     * @this
     * @param {string} [sometext = logSeparator] The text of the log entry (or the default 'separator line' if no text is  provided)
     * @param {object} [timeStamp = null]        A time stamp (Date object), that should be attached to the log entry when the timed option is on.
     */
    function log(sometext = logSeparator, timeStamp = null) {
        let timeString = (true === this.timed) ? "[" + ( timeStamp ? timeStamp.toLocaleString() : (new Date()).toLocaleString()) + "]" : "";
        let textToLog = "[C" + ExtUtils.padNumber(this.ID) + "] " + timeString + sometext;
        if (true === this.verbose) {
            console.log(textToLog);
        }
        this.logArray.push(textToLog);
    }
    /**
     * Function returning a string containing all the log entries (one entry per line)
     * @author Loïs Bégué
     * @returns {string} The full log of the log case object
     * @this
     */
    function getFullLog(){
        return this.logArray.join("\n");
    }
    /**
     * Ends the log case and insert a corresponding log entry 
     * @author Loïs Bégué
     * @this
     */
    function endLogCase(){
        this.completed = true;
        this.endTime = new Date();
        let t = "[END] ";
        this.log( ExtUtils.padText(t, 80, "="), this.endTime);
    }
    /**
     * Starts the log case and insert a log entry containing the case description
     * @author Loïs Bégué
     * @this
     */
    function startLogCase(){
        this.started = true;
        this.startTime = new Date();
        let t = "[START] " + this.description + " ";
        this.log( ExtUtils.padText(t, 80, "="), this.startTime);
    }
    /**
     * Create a LogCase object and give it back to the caller
     * @author Loïs Bégué
     * @param   {string} [logCaseDescription = defaultDesc] The description of the test case  to be logged
     * @param   {boolean} [verbose = false]                 Displays the logs immediately in the console when set to 'true' Use 'fulllog' property to retrieve the log afterwards
     * @param   {boolean} [timed = false]                   Adds a time stamp to the log entries when set to 'true'
     * @returns {LogCase} a new log case object
     */
    function createLogCase(logCaseDescription = defaultDesc, verbose = false, timed = false){
        let newLogCase = {};
        newLogCase["description"]  = logCaseDescription;
        newLogCase["ID"]           = _logCaseID++;
        newLogCase["logArray"]     = [];
        newLogCase["verbose"]      = verbose;
        newLogCase["log"]          = log;
        newLogCase["fullLog"]      = getFullLog;
        newLogCase["end"]          = endLogCase;
        newLogCase["start"]        = startLogCase;
        newLogCase["started"]      = false;
        newLogCase["completed"]    = false;
        newLogCase["timed"]        = timed;
        newLogCase["startTime"]    = Date.now();
        newLogCase["endTime"]      = newLogCase["startTime"];
        return newLogCase;
    }
    /**
     * Self test function to check the module functionality (also suitable as usage example)
     * @author Loïs Bégué
     * @this
     */
    function selfTest(){
        // instanciate the selftest logcase: verbose=true, timed=false
        let selfTestLogCase = this.createLogCase("Self Test of the module 'ExtLoggingUtils'", true, false);
        selfTestLogCase.start();
        selfTestLogCase.log("Execute the first (nested) code block to be tested...");
        {
            // instanciate the first logCase
            let myLogCase1 = this.createLogCase("This is the first code to be tested", true, false);
            // start
            myLogCase1.start();
            // log
            myLogCase1.log("Before Action #1");
            // application code simulation
            console.log("...Action #1...");
            // log
            myLogCase1.log("Before Action #2");
            // application code simulation
            console.log("...Action #2...");
            // last log before closing (end of the code block has been reached safelly so far)
            myLogCase1.end();
        }
        selfTestLogCase.log("Execute the second (nested) code block to be tested...");
        {
            // instanciate the second logCase
            let myLogCase2 = this.createLogCase("This is the second code to be tested", true, false);
            // start
            myLogCase2.start();
            // log
            myLogCase2.log("Before Action #1");
            // application code simulation
            console.log("...Action #1...");
            // log
            myLogCase2.log("Before Action #2");
            // application code simulation
            console.log("...Action #2...");
            // last log before closing (end of the code block has been reached safelly so far)
            myLogCase2.end();
        }
        selfTestLogCase.end();
        // Display the full log of the "selfTest Log Case"
        console.log("SELF TEST LOG CASE : FULLLOG\n" + selfTestLogCase.fullLog());
        return selfTestLogCase.fullLog();
    }
    exports.createLogCase = createLogCase;
    exports.selfTest      = selfTest;
});
/* TODO: improve code = in particular make all objects rock strong using private members/methods 
e.g. using the following technics https://philipwalton.com/articles/implementing-private-and-protected-members-in-javascript/ or
https://stackoverflow.com/questions/34869352/how-to-declare-private-variables-and-private-methods-in-es6-class */