/** * Copyright JS Foundation and other contributors, http://js.foundation * * 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. **/ RED.utils = (function() { window._marked = window.marked; window.marked = function(txt) { console.warn("Use of 'marked()' is deprecated. Use RED.utils.renderMarkdown() instead"); return renderMarkdown(txt); } _marked.setOptions({ renderer: new _marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, smartLists: true, smartypants: false }); function renderMarkdown(txt) { var rendered = _marked(txt); var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true}) return cleaned; } function formatString(str) { return str.replace(/\r?\n/g,"↵").replace(/\t/g,"→"); } function sanitize(m) { return m.replace(/&/g,"&").replace(//g,">"); } function buildMessageSummaryValue(value) { var result; if (Array.isArray(value)) { result = $('').text('array['+value.length+']'); } else if (value === null) { result = $('null'); } else if (typeof value === 'object') { if (value.hasOwnProperty('type') && value.type === 'undefined') { result = $('undefined'); } else if (value.hasOwnProperty('type') && value.type === 'Buffer' && value.hasOwnProperty('data')) { result = $('').text('buffer['+value.length+']'); } else if (value.hasOwnProperty('type') && value.type === 'array' && value.hasOwnProperty('data')) { result = $('').text('array['+value.length+']'); } else if (value.hasOwnProperty('type') && value.type === 'set' && value.hasOwnProperty('data')) { result = $('').text('set['+value.length+']'); } else if (value.hasOwnProperty('type') && value.type === 'map' && value.hasOwnProperty('data')) { result = $('').text('map'); } else if (value.hasOwnProperty('type') && value.type === 'function') { result = $('').text('function'); } else if (value.hasOwnProperty('type') && (value.type === 'number' || value.type === 'bigint')) { result = $('').text(value.data); } else { result = $('object'); } } else if (typeof value === 'string') { var subvalue; if (value.length > 30) { subvalue = sanitize(value.substring(0,30))+"…"; } else { subvalue = sanitize(value); } result = $('').html('"'+formatString(subvalue)+'"'); } else if (typeof value === 'number') { result = $('').text(""+value); } else { result = $('').text(""+value); } return result; } function makeExpandable(el,onbuild,ontoggle,expand) { el.addClass("red-ui-debug-msg-expandable"); el.prop('toggle',function() { return function(state) { var parent = el.parent(); if (parent.hasClass('collapsed')) { if (state) { if (onbuild && !parent.hasClass('built')) { onbuild(); parent.addClass('built'); } parent.removeClass('collapsed'); return true; } } else { if (!state) { parent.addClass('collapsed'); return true; } } return false; } }); el.on("click", function(e) { var parent = $(this).parent(); var currentState = !parent.hasClass('collapsed'); if ($(this).prop('toggle')(!currentState)) { if (ontoggle) { ontoggle(!currentState); } } // if (parent.hasClass('collapsed')) { // if (onbuild && !parent.hasClass('built')) { // onbuild(); // parent.addClass('built'); // } // if (ontoggle) { // ontoggle(true); // } // parent.removeClass('collapsed'); // } else { // parent.addClass('collapsed'); // if (ontoggle) { // ontoggle(false); // } // } e.preventDefault(); }); if (expand) { el.trigger("click"); } } var pinnedPaths = {}; var formattedPaths = {}; function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey,extraTools) { if (!pinnedPaths.hasOwnProperty(sourceId)) { pinnedPaths[sourceId] = {} } var tools = $('').appendTo(obj); var copyTools = $('').appendTo(tools); if (!!key) { var copyPath = $('').appendTo(copyTools).on("click", function(e) { e.preventDefault(); e.stopPropagation(); RED.clipboard.copyText(key,copyPath,"clipboard.copyMessagePath"); }) RED.popover.tooltip(copyPath,RED._("node-red:debug.sidebar.copyPath")); } var copyPayload = $('').appendTo(copyTools).on("click", function(e) { e.preventDefault(); e.stopPropagation(); RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue"); }) RED.popover.tooltip(copyPayload,RED._("node-red:debug.sidebar.copyPayload")); if (strippedKey !== undefined && strippedKey !== '') { var isPinned = pinnedPaths[sourceId].hasOwnProperty(strippedKey); var pinPath = $('').appendTo(tools).on("click", function(e) { e.preventDefault(); e.stopPropagation(); if (pinnedPaths[sourceId].hasOwnProperty(strippedKey)) { delete pinnedPaths[sourceId][strippedKey]; $(this).removeClass("selected"); obj.removeClass("red-ui-debug-msg-row-pinned"); } else { var rootedPath = "$"+(strippedKey[0] === '['?"":".")+strippedKey; pinnedPaths[sourceId][strippedKey] = normalisePropertyExpression(rootedPath); $(this).addClass("selected"); obj.addClass("red-ui-debug-msg-row-pinned"); } }).toggleClass("selected",isPinned); obj.toggleClass("red-ui-debug-msg-row-pinned",isPinned); RED.popover.tooltip(pinPath,RED._("node-red:debug.sidebar.pinPath")); } if (extraTools) { var t = extraTools; if (typeof t === 'function') { t = t(key,msg); } if (t) { t.addClass("red-ui-debug-msg-tools-other"); t.appendTo(tools); } } } function checkExpanded(strippedKey,expandPaths,minRange,maxRange) { if (expandPaths && expandPaths.length > 0) { if (strippedKey === '' && minRange === undefined) { return true; } for (var i=0;i'); element.collapse = function() { element.find(".red-ui-debug-msg-expandable").parent().addClass("collapsed"); } header = $('').appendTo(element); if (sourceId) { addMessageControls(header,sourceId,path,obj,rootPath,strippedKey,tools); } if (!key) { element.addClass("red-ui-debug-msg-top-level"); if (sourceId) { var pinned = pinnedPaths[sourceId]; expandPaths = []; if (pinned) { for (var pinnedPath in pinned) { if (pinned.hasOwnProperty(pinnedPath)) { try { var res = getMessageProperty({$:obj},pinned[pinnedPath]); if (res !== undefined) { expandPaths.push(pinnedPath); } } catch(err) { } } } expandPaths.sort(); } element.clearPinned = function() { element.find(".red-ui-debug-msg-row-pinned").removeClass("red-ui-debug-msg-row-pinned"); pinnedPaths[sourceId] = {}; } } } else { if (!hideKey) { $('').text(key).appendTo(header); $(': ').appendTo(header); } } entryObj = $('').appendTo(header); var isArray = Array.isArray(obj); var isArrayObject = false; if (obj && typeof obj === 'object' && obj.hasOwnProperty('type') && obj.hasOwnProperty('data') && ((obj.__enc__ && obj.type === 'set') || (obj.__enc__ && obj.type === 'array') || obj.type === 'Buffer')) { isArray = true; isArrayObject = true; } if (obj === null || obj === undefined) { $(''+obj+'').appendTo(entryObj); } else if (obj.__enc__ && obj.type === 'undefined') { $('undefined').appendTo(entryObj); } else if (obj.__enc__ && (obj.type === 'number' || obj.type === 'bigint')) { e = $('').text(obj.data).appendTo(entryObj); } else if (typeHint === "function" || (obj.__enc__ && obj.type === 'function')) { e = $('').text("function").appendTo(entryObj); } else if (typeHint === "internal" || (obj.__enc__ && obj.type === 'internal')) { e = $('').text("[internal]").appendTo(entryObj); } else if (typeof obj === 'string') { if (/[\t\n\r]/.test(obj)) { element.addClass('collapsed'); $(' ').prependTo(header); makeExpandable(header, function() { $('').text(typeHint||'string').appendTo(header); var row = $('').appendTo(element); $('
').text(obj).appendTo(row);
                },function(state) {if (ontoggle) { ontoggle(path,state);}}, checkExpanded(strippedKey,expandPaths));
            }
            e = $('').html('"'+formatString(sanitize(obj))+'"').appendTo(entryObj);
            if (/^#[0-9a-f]{6}$/i.test(obj)) {
                $('').css('backgroundColor',obj).appendTo(e);
            }

        } else if (typeof obj === 'number') {
            e = $('').appendTo(entryObj);

            if (Number.isInteger(obj) && (obj >= 0)) { // if it's a +ve integer
                e.addClass("red-ui-debug-msg-type-number-toggle");
                e.on("click", function(evt) {
                    evt.preventDefault();
                    formatNumber($(this), obj, sourceId, path, true);
                });
            }
            formatNumber(e,obj,sourceId,path,false,typeHint==='hex'?'hex':undefined);

        } else if (isArray) {
            element.addClass('collapsed');

            var originalLength = obj.length;
            if (typeHint) {
                var m = /\[(\d+)\]/.exec(typeHint);
                if (m) {
                    originalLength = parseInt(m[1]);
                }
            }
            var data = obj;
            var type = 'array';
            if (isArrayObject) {
                data = obj.data;
                if (originalLength === undefined) {
                    originalLength = data.length;
                }
                if (data.__enc__) {
                    data = data.data;
                }
                type = obj.type.toLowerCase();
            } else if (/buffer/.test(typeHint)) {
                type = 'buffer';
            }
            var fullLength = data.length;

            if (originalLength > 0) {
                $(' ').prependTo(header);
                var arrayRows = $('
').appendTo(element); element.addClass('red-ui-debug-msg-buffer-raw'); } if (key) { headerHead = $('').text(typeHint||(type+'['+originalLength+']')).appendTo(entryObj); } else { headerHead = $('').appendTo(entryObj); $('[ ').appendTo(headerHead); var arrayLength = Math.min(originalLength,10); for (i=0;i, ').appendTo(headerHead); } } if (originalLength > arrayLength) { $('').appendTo(headerHead); } if (arrayLength === 0) { $('empty').appendTo(headerHead); } $(' ]').appendTo(headerHead); } if (originalLength > 0) { makeExpandable(header,function() { if (!key) { headerHead = $('').text(typeHint||(type+'['+originalLength+']')).appendTo(header); } if (type === 'buffer') { var stringRow = $('
').appendTo(element); var sr = $('').appendTo(stringRow); var stringEncoding = ""; try { stringEncoding = String.fromCharCode.apply(null, new Uint16Array(data)) } catch(err) { console.log(err); } $('
').text(stringEncoding).appendTo(sr);
                        var bufferOpts = $('').appendTo(headerHead);
                        var switchFormat = $('').text('raw').appendTo(bufferOpts).on("click", function(e) {
                            e.preventDefault();
                            e.stopPropagation();
                            formatBuffer(element,$(this),sourceId,path,true);
                        });
                        formatBuffer(element,switchFormat,sourceId,path,false);

                    }
                    var row;
                    if (fullLength <= 10) {
                        for (i=0;i