/* * Project Name : Visual Python * Description : GUI-based Python code generator * File Name : com_util.js * Author : Black Logic * Note : Common utility function * License : GPLv3 (GNU General Public License v3.0) * Date : 2021. 08. 14 * Change Date : */ //============================================================================ // Common utility function //============================================================================ define([ 'vp_base/js/com/com_String' ], function (com_String) { 'use strict' //======================================================================== // Define variable //======================================================================== let isAPIListRunCode = true; //======================================================================== // Internal call function //======================================================================== /** * check duplicate variable name * @param {string} varName */ var _checkVariableNameDuplicate = function(varName) { // TODO: varName duplicate check return true; } //======================================================================== // External call function //======================================================================== /** * Generate uuid * @returns {String} uuid */ var getUUID = function() { return 'u' + ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); } /** * append css on global * @param {String} url style url */ var loadCss = function(url) { var link = document.createElement('link'); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = require.toUrl(url); document.getElementsByTagName('head')[0].appendChild(link); } /** * VisualPython container selector (jquery selector) * @returns vp top container selector */ var getVPContainer = function() { return '#vp_wrapper'; } /** * wrap selector * @param {String} selector selector * @returns wraped selecotr */ var wrapSelector = function(selector = '') { var sbSelector = new com_String(); var cnt = arguments.length; // no more selector if (cnt < 2) { sbSelector.appendFormat('{0} {1}', getVPContainer(), selector); } else { sbSelector.appendFormat('{0}', getVPContainer()); for (var idx = 0; idx < cnt; idx++) { sbSelector.appendFormat(' {0}', arguments[idx]); } } return sbSelector.toString(); } /** * add variable and trigger event * @param {string} varName variable name * @param {string} varType variable type * @returns if return 0 when success, -1 when variable name duplicate */ var addVariable = function(varName, varType) { // varName check duplicate if (_checkVariableNameDuplicate) { return -1; } else { events.trigger('add-variable.vp-wrapper', {'varName': varName, 'varType': varType}); return 0; } } /** * format simple string */ var formatString = function() { var cnt = arguments.length; if (cnt < 2) return arguments[0]; var str = arguments[0]; for (var idx = 1; idx < cnt; idx++) str = str.replace('{' + (idx - 1) + '}', arguments[idx]); return str; } /** * Convert to string format if not numeric * @param {*} code * @returns */ var convertToStr = function(code, isText=null, useRegex=false) { let prefix = ''; if (useRegex) { prefix = 'r'; } if (isText != null) { if (isText) { code = `${prefix}'${code}'`; } } else { if (!$.isNumeric(code)) { if (code.includes("'")) { code = `${prefix}"${code}"`; } else { code = `${prefix}'${code}'`; } } } return code; } /** * Remove head's script(css, js) * @param {string} scriptName */ var removeHeadScript = function(scriptName) { for (let i = 0; i < document.querySelector('head').children.length; i++){ if (document.querySelector('head') && document.querySelector('head').children[i].outerHTML.includes(scriptName)) { document.querySelector('head').removeChild(document.querySelector('head').children[i]); } } } /** * Modal * @param {Object} config { title, message, buttons(list), final(function), defaultIdx(int) } */ var renderModal = function(config={title:'', message:'', buttons:['Ok']}) { require(['vp_base/js/com/component/Modal'], function(Modal) { let modal = new Modal(config); modal.open(); }); } /** * InfoModal * @param {string} titleStr */ var renderInfoModal = function(titleStr) { require(['vp_base/js/com/component/InfoModal'], function(InfoModal) { new InfoModal(titleStr); }); } /** * AlertModal * @param {string} titleStr */ var renderAlertModal = function(titleStr, detail='') { require(['vp_base/js/com/component/AlertModal'], function(AlertModal) { new AlertModal(titleStr, detail=detail); }); } /** * Show success message on the top right of the screen * @param {string} titleStr */ var renderSuccessMessage = function(titleStr) { require(['vp_base/js/com/component/SuccessMessage'], function(SuccessMessage) { new SuccessMessage(titleStr); }); } /** * Template for error box * @param {*} titleStr * @param {*} contentStr * @returns */ var templateForErrorBox = function(titleStr, contentStr='', detailStr='') { let errorContent = new com_String(); errorContent.appendFormatLine('
', 'vp-data-error-box', (detailStr && detailStr.length > 0)?('title="'+detailStr+"'"):''); errorContent.appendLine(''); errorContent.appendFormatLine('', 'vp-data-error-box-title', titleStr); if (contentStr && contentStr != '') { errorContent.appendFormatLine('
{0}
', contentStr.split('\\n').join('
')); } errorContent.appendLine('
'); return errorContent.toString(); } /** * setIsAPIListRunCode */ var setIsAPIListRunCode = function(isAPIListRunCode_param) { isAPIListRunCode = isAPIListRunCode_param; } /** * getIsAPIListRunCode */ var getIsAPIListRunCode = function() { return isAPIListRunCode; } /** * Convert string(include html text) to safe string to display * @param {String} text * @returns */ var safeString = function(text) { return String(text).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } var optionToLabel = function(label) { label = label.replaceAll('_', ' '); label = label.charAt(0).toUpperCase() + label.slice(1); return label; } /** * Pack the code with ignoring the warnings * @param {*} code */ var ignoreWarning = function(code) { var convertedCode = new com_String(); convertedCode.appendLine('import warnings'); convertedCode.appendLine('from IPython.display import display'); convertedCode.appendLine('with warnings.catch_warnings():'); convertedCode.appendLine(" warnings.simplefilter('ignore')"); let codeLines = code.split('\n'); codeLines.forEach((line, idx) => { if (idx > 0) { convertedCode.appendLine(); } if (codeLines.length == idx + 1) { // last line convertedCode.appendFormat(" display({0})", line); } else { convertedCode.appendFormat(" {0}", line); } }); return convertedCode.toString(); } //============================================================================ // Cross-browser RegEx Split //============================================================================ // This code has been MODIFIED from the code licensed below to not replace the // default browser split. The license is reproduced here. // see http://blog.stevenlevithan.com/archives/cross-browser-split for more info: /*! * Cross-Browser Split 1.1.1 * Copyright 2007-2012 Steven Levithan * Available under the MIT License * ECMAScript compliant, uniform cross-browser split method */ /** * Splits a string into an array of strings using a regex or string * separator. Matches of the separator are not included in the result array. * However, if `separator` is a regex that contains capturing groups, * backreferences are spliced into the result each time `separator` is * matched. Fixes browser bugs compared to the native * `String.prototype.split` and can be used reliably cross-browser. * @param {String} str String to split. * @param {RegExp} separator Regex to use for separating * the string. * @param {Number} [limit] Maximum number of items to include in the result * array. * @returns {Array} Array of substrings. * @example * * // Basic use * regex_split('a b c d', ' '); * // -> ['a', 'b', 'c', 'd'] * * // With limit * regex_split('a b c d', ' ', 2); * // -> ['a', 'b'] * * // Backreferences in result array * regex_split('..word1 word2..', /([a-z]+)(\d+)/i); * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] */ var regex_split = function (str, separator, limit) { var output = [], flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 (separator.sticky ? "y" : ""), // Firefox 3+ lastLastIndex = 0, separator2, match, lastIndex, lastLength; // Make `global` and avoid `lastIndex` issues by working with a copy separator = new RegExp(separator.source, flags + "g"); var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined"; if (!compliantExecNpcg) { // Doesn't need flags gy, but they don't hurt separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); } /* Values for `limit`, per the spec: * If undefined: 4294967295 // Math.pow(2, 32) - 1 * If 0, Infinity, or NaN: 0 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; * If negative number: 4294967296 - Math.floor(Math.abs(limit)) * If other: Type-convert, then use the above rules */ limit = typeof(limit) === "undefined" ? -1 >>> 0 : // Math.pow(2, 32) - 1 limit >>> 0; // ToUint32(limit) for (match = separator.exec(str); match; match = separator.exec(str)) { // `separator.lastIndex` is not reliable cross-browser lastIndex = match.index + match[0].length; if (lastIndex > lastLastIndex) { output.push(str.slice(lastLastIndex, match.index)); // Fix browsers whose `exec` methods don't consistently return `undefined` for // nonparticipating capturing groups if (!compliantExecNpcg && match.length > 1) { match[0].replace(separator2, function () { for (var i = 1; i < arguments.length - 2; i++) { if (typeof(arguments[i]) === "undefined") { match[i] = undefined; } } }); } if (match.length > 1 && match.index < str.length) { Array.prototype.push.apply(output, match.slice(1)); } lastLength = match[0].length; lastLastIndex = lastIndex; if (output.length >= limit) { break; } } if (separator.lastIndex === match.index) { separator.lastIndex++; // Avoid an infinite loop } } if (lastLastIndex === str.length) { if (lastLength || !separator.test("")) { output.push(""); } } else { output.push(str.slice(lastLastIndex)); } return output.length > limit ? output.slice(0, limit) : output; }; //============================================================================ // End contributed Cross-browser RegEx Split //============================================================================ return { getUUID: getUUID, loadCss: loadCss, getVPContainer: getVPContainer, wrapSelector: wrapSelector, addVariable: addVariable, formatString: formatString, convertToStr: convertToStr, optionToLabel: optionToLabel, removeHeadScript: removeHeadScript, renderModal: renderModal, renderInfoModal: renderInfoModal, renderAlertModal: renderAlertModal, renderSuccessMessage: renderSuccessMessage, templateForErrorBox: templateForErrorBox, setIsAPIListRunCode: setIsAPIListRunCode, getIsAPIListRunCode: getIsAPIListRunCode, safeString: safeString, ignoreWarning: ignoreWarning, regex_split: regex_split } }); /* function, define */ /* End of file */