diff --git a/HISTORY.md b/HISTORY.md index 8e634bb..1e1ac09 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,7 +2,7 @@ https://github.com/josdejong/jsoneditor -## not yet published, version 6.2.0 +## 2019-07-28, version 6.2.0 - Implemented new mode `preview`, capable of working with large JSON documents up to 500 MiB. diff --git a/dist/jsoneditor-minimalist.js b/dist/jsoneditor-minimalist.js index 23b9ee7..f4f2d3f 100644 --- a/dist/jsoneditor-minimalist.js +++ b/dist/jsoneditor-minimalist.js @@ -24,8 +24,8 @@ * Copyright (c) 2011-2019 Jos de Jong, http://jsoneditoronline.org * * @author Jos de Jong, - * @version 6.1.0 - * @date 2019-06-22 + * @version 6.2.0 + * @date 2019-07-28 */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') @@ -120,7 +120,7 @@ return /******/ (function(modules) { // webpackBootstrap /******/ /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 13); +/******/ return __webpack_require__(__webpack_require__.s = 16); /******/ }) /************************************************************************/ /******/ ([ @@ -130,444 +130,13 @@ return /******/ (function(modules) { // webpackBootstrap "use strict"; -__webpack_require__(6); +__webpack_require__(10); +var naturalSort = __webpack_require__(11); +var jsonlint = __webpack_require__(23); +var jsonMap = __webpack_require__(24); +var translate = __webpack_require__(1).translate; -var _locales = ['en', 'pt-BR', 'zh-CN', 'tr']; -var _defs = { - en: { - array: 'Array', - auto: 'Auto', - appendText: 'Append', - appendTitle: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Select the type of the field to be appended', - appendTitleAuto: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', - ascending: 'Ascending', - ascendingTitle: 'Sort the childs of this ${type} in ascending order', - actionsMenu: 'Click to open the actions menu (Ctrl+M)', - collapseAll: 'Collapse all fields', - descending: 'Descending', - descendingTitle: 'Sort the childs of this ${type} in descending order', - drag: 'Drag to move this field (Alt+Shift+Arrows)', - duplicateKey: 'duplicate key', - duplicateText: 'Duplicate', - duplicateTitle: 'Duplicate selected fields (Ctrl+D)', - duplicateField: 'Duplicate this field (Ctrl+D)', - duplicateFieldError: 'Duplicate field name', - cannotParseFieldError: 'Cannot parse field into JSON', - cannotParseValueError: 'Cannot parse value into JSON', - empty: 'empty', - expandAll: 'Expand all fields', - expandTitle: 'Click to expand/collapse this field (Ctrl+E). \n' + - 'Ctrl+Click to expand/collapse including all childs.', - insert: 'Insert', - insertTitle: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', - insertSub: 'Select the type of the field to be inserted', - object: 'Object', - ok: 'Ok', - redo: 'Redo (Ctrl+Shift+Z)', - removeText: 'Remove', - removeTitle: 'Remove selected fields (Ctrl+Del)', - removeField: 'Remove this field (Ctrl+Del)', - selectNode: 'Select a node...', - showAll: 'show all', - showMore: 'show more', - showMoreStatus: 'displaying ${visibleChilds} of ${totalChilds} items.', - sort: 'Sort', - sortTitle: 'Sort the childs of this ${type}', - sortTitleShort: 'Sort contents', - sortFieldLabel: 'Field:', - sortDirectionLabel: 'Direction:', - sortFieldTitle: 'Select the nested field by which to sort the array or object', - sortAscending: 'Ascending', - sortAscendingTitle: 'Sort the selected field in ascending order', - sortDescending: 'Descending', - sortDescendingTitle: 'Sort the selected field in descending order', - string: 'String', - transform: 'Transform', - transformTitle: 'Filter, sort, or transform the childs of this ${type}', - transformTitleShort: 'Filter, sort, or transform contents', - extract: 'Extract', - extractTitle: 'Extract this ${type}', - transformQueryTitle: 'Enter a JMESPath query', - transformWizardLabel: 'Wizard', - transformWizardFilter: 'Filter', - transformWizardSortBy: 'Sort by', - transformWizardSelectFields: 'Select fields', - transformQueryLabel: 'Query', - transformPreviewLabel: 'Preview', - type: 'Type', - typeTitle: 'Change the type of this field', - openUrl: 'Ctrl+Click or Ctrl+Enter to open url in new window', - undo: 'Undo last action (Ctrl+Z)', - validationCannotMove: 'Cannot move a field into a child of itself', - autoType: 'Field type "auto". ' + - 'The field type is automatically determined from the value ' + - 'and can be a string, number, boolean, or null.', - objectType: 'Field type "object". ' + - 'An object contains an unordered set of key/value pairs.', - arrayType: 'Field type "array". ' + - 'An array contains an ordered collection of values.', - stringType: 'Field type "string". ' + - 'Field type is not determined from the value, ' + - 'but always returned as string.', - modeCodeText: 'Code', - modeCodeTitle: 'Switch to code highlighter', - modeFormText: 'Form', - modeFormTitle: 'Switch to form editor', - modeTextText: 'Text', - modeTextTitle: 'Switch to plain text editor', - modeTreeText: 'Tree', - modeTreeTitle: 'Switch to tree editor', - modeViewText: 'View', - modeViewTitle: 'Switch to tree view', - examples: 'Examples', - default: 'Default', - }, - 'zh-CN': { - array: '数组', - auto: '自动', - appendText: '追加', - appendTitle: '在此字段后追加一个类型为“auto”的新字段 (Ctrl+Shift+Ins)', - appendSubmenuTitle: '选择要追加的字段类型', - appendTitleAuto: '追加类型为“auto”的新字段 (Ctrl+Shift+Ins)', - ascending: '升序', - ascendingTitle: '升序排列${type}的子节点', - actionsMenu: '点击打开动作菜单(Ctrl+M)', - collapseAll: '缩进所有字段', - descending: '降序', - descendingTitle: '降序排列${type}的子节点', - drag: '拖拽移动该节点(Alt+Shift+Arrows)', - duplicateKey: '重复键', - duplicateText: '复制', - duplicateTitle: '复制选中字段(Ctrl+D)', - duplicateField: '复制该字段(Ctrl+D)', - duplicateFieldError: '重复的字段名称', - cannotParseFieldError: '无法将字段解析为JSON', - cannotParseValueError: '无法将值解析为JSON', - empty: '清空', - expandAll: '展开所有字段', - expandTitle: '点击 展开/收缩 该字段(Ctrl+E). \n' + - 'Ctrl+Click 展开/收缩 包含所有子节点.', - insert: '插入', - insertTitle: '在此字段前插入类型为“auto”的新字段 (Ctrl+Ins)', - insertSub: '选择要插入的字段类型', - object: '对象', - ok: 'Ok', - redo: '重做 (Ctrl+Shift+Z)', - removeText: '移除', - removeTitle: '移除选中字段 (Ctrl+Del)', - removeField: '移除该字段 (Ctrl+Del)', - selectNode: '选择一个节点...', - showAll: '展示全部', - showMore: '展示更多', - showMoreStatus: '显示${totalChilds}的${visibleChilds}项目.', - sort: '排序', - sortTitle: '排序${type}的子节点', - sortTitleShort: '内容排序', - sortFieldLabel: '字段:', - sortDirectionLabel: '方向:', - sortFieldTitle: '选择用于对数组或对象排序的嵌套字段', - sortAscending: '升序排序', - sortAscendingTitle: '按照该字段升序排序', - sortDescending: '降序排序', - sortDescendingTitle: '按照该字段降序排序', - string: '字符串', - transform: '变换', - transformTitle: '筛选,排序,或者转换${type}的子节点', - transformTitleShort: '筛选,排序,或者转换内容', - transformQueryTitle: '输入JMESPath查询', - transformWizardLabel: '向导', - transformWizardFilter: '筛选', - transformWizardSortBy: '排序', - transformWizardSelectFields: '选择字段', - transformQueryLabel: '查询', - transformPreviewLabel: '预览', - type: '类型', - typeTitle: '更改字段类型', - openUrl: 'Ctrl+Click 或者 Ctrl+Enter 在新窗口打开链接', - undo: '撤销上次动作 (Ctrl+Z)', - validationCannotMove: '无法将字段移入其子节点', - autoType: '字段类型 "auto". ' + - '字段类型由值自动确定 ' + - '可以为 string,number,boolean,或者 null.', - objectType: '字段类型 "object". ' + - '对象包含一组无序的键/值对.', - arrayType: '字段类型 "array". ' + - '数组包含值的有序集合.', - stringType: '字段类型 "string". ' + - '字段类型由值自动确定,' + - '但始终作为字符串返回.', - modeCodeText: '代码', - modeCodeTitle: '切换至代码高亮', - modeFormText: '表单', - modeFormTitle: '切换至表单编辑', - modeTextText: '文本', - modeTextTitle: '切换至文本编辑', - modeTreeText: '树', - modeTreeTitle: '切换至树编辑', - modeViewText: '视图', - modeViewTitle: '切换至树视图', - examples: '例子', - default: '缺省', - }, - 'pt-BR': { - array: 'Lista', - auto: 'Automatico', - appendText: 'Adicionar', - appendTitle: 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Selecione o tipo do campo a ser adicionado', - appendTitleAuto: 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)', - ascending: 'Ascendente', - ascendingTitle: 'Organizar filhor do tipo ${type} em crescente', - actionsMenu: 'Clique para abrir o menu de ações (Ctrl+M)', - collapseAll: 'Fechar todos campos', - descending: 'Descendente', - descendingTitle: 'Organizar o filhos do tipo ${type} em decrescente', - duplicateKey: 'chave duplicada', - drag: 'Arraste para mover este campo (Alt+Shift+Arrows)', - duplicateText: 'Duplicar', - duplicateTitle: 'Duplicar campos selecionados (Ctrl+D)', - duplicateField: 'Duplicar este campo (Ctrl+D)', - duplicateFieldError: 'Nome do campo duplicado', - cannotParseFieldError: 'Não é possível analisar o campo no JSON', - cannotParseValueError: 'Não é possível analisar o valor em JSON', - empty: 'vazio', - expandAll: 'Expandir todos campos', - expandTitle: 'Clique para expandir/encolher este campo (Ctrl+E). \n' + - 'Ctrl+Click para expandir/encolher incluindo todos os filhos.', - insert: 'Inserir', - insertTitle: 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)', - insertSub: 'Selecionar o tipo de campo a ser inserido', - object: 'Objeto', - ok: 'Ok', - redo: 'Refazer (Ctrl+Shift+Z)', - removeText: 'Remover', - removeTitle: 'Remover campos selecionados (Ctrl+Del)', - removeField: 'Remover este campo (Ctrl+Del)', - // TODO: correctly translate - selectNode: 'Select a node...', - // TODO: correctly translate - showAll: 'mostre tudo', - // TODO: correctly translate - showMore: 'mostre mais', - // TODO: correctly translate - showMoreStatus: 'exibindo ${visibleChilds} de ${totalChilds} itens.', - sort: 'Organizar', - sortTitle: 'Organizar os filhos deste ${type}', - // TODO: correctly translate - sortTitleShort: 'Organizar os filhos', - // TODO: correctly translate - sortFieldLabel: 'Field:', - // TODO: correctly translate - sortDirectionLabel: 'Direction:', - // TODO: correctly translate - sortFieldTitle: 'Select the nested field by which to sort the array or object', - // TODO: correctly translate - sortAscending: 'Ascending', - // TODO: correctly translate - sortAscendingTitle: 'Sort the selected field in ascending order', - // TODO: correctly translate - sortDescending: 'Descending', - // TODO: correctly translate - sortDescendingTitle: 'Sort the selected field in descending order', - string: 'Texto', - // TODO: correctly translate - transform: 'Transform', - // TODO: correctly translate - transformTitle: 'Filter, sort, or transform the childs of this ${type}', - // TODO: correctly translate - transformTitleShort: 'Filter, sort, or transform contents', - // TODO: correctly translate - transformQueryTitle: 'Enter a JMESPath query', - // TODO: correctly translate - transformWizardLabel: 'Wizard', - // TODO: correctly translate - transformWizardFilter: 'Filter', - // TODO: correctly translate - transformWizardSortBy: 'Sort by', - // TODO: correctly translate - transformWizardSelectFields: 'Select fields', - // TODO: correctly translate - transformQueryLabel: 'Query', - // TODO: correctly translate - transformPreviewLabel: 'Preview', - type: 'Tipo', - typeTitle: 'Mudar o tipo deste campo', - openUrl: 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela', - undo: 'Desfazer último ação (Ctrl+Z)', - validationCannotMove: 'Não pode mover um campo como filho dele mesmo', - autoType: 'Campo do tipo "auto". ' + - 'O tipo do campo é determinao automaticamente a partir do seu valor ' + - 'e pode ser texto, número, verdade/falso ou nulo.', - objectType: 'Campo do tipo "objeto". ' + - 'Um objeto contém uma lista de pares com chave e valor.', - arrayType: 'Campo do tipo "lista". ' + - 'Uma lista contem uma coleção de valores ordenados.', - stringType: 'Campo do tipo "string". ' + - 'Campo do tipo nao é determinado através do seu valor, ' + - 'mas sempre retornara um texto.', - examples: 'Exemplos', - default: 'Revelia', - }, - tr: { - array: 'Dizin', - auto: 'Otomatik', - appendText: 'Ekle', - appendTitle: 'Bu alanın altına \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', - appendSubmenuTitle: 'Eklenecek alanın tipini seç', - appendTitleAuto: '\'Otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', - ascending: 'Artan', - ascendingTitle: '${type}\'ın alt tiplerini artan düzende sırala', - actionsMenu: 'Aksiyon menüsünü açmak için tıklayın (Ctrl+M)', - collapseAll: 'Tüm alanları kapat', - descending: 'Azalan', - descendingTitle: '${type}\'ın alt tiplerini azalan düzende sırala', - drag: 'Bu alanı taşımak için sürükleyin (Alt+Shift+Arrows)', - duplicateKey: 'Var olan anahtar', - duplicateText: 'Aşağıya kopyala', - duplicateTitle: 'Seçili alanlardan bir daha oluştur (Ctrl+D)', - duplicateField: 'Bu alandan bir daha oluştur (Ctrl+D)', - duplicateFieldError: 'Duplicate field name', - cannotParseFieldError: 'Alan JSON\'a ayrıştırılamıyor', - cannotParseValueError: 'JSON\'a değer ayrıştırılamıyor', - empty: 'boş', - expandAll: 'Tüm alanları aç', - expandTitle: 'Bu alanı açmak/kapatmak için tıkla (Ctrl+E). \n' + - 'Alt alanlarda dahil tüm alanları açmak için Ctrl+Click ', - insert: 'Ekle', - insertTitle: 'Bu alanın üstüne \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Ins)', - insertSub: 'Araya eklenecek alanın tipini seç', - object: 'Nesne', - ok: 'Tamam', - redo: 'Yeniden yap (Ctrl+Shift+Z)', - removeText: 'Kaldır', - removeTitle: 'Seçilen alanları kaldır (Ctrl+Del)', - removeField: 'Bu alanı kaldır (Ctrl+Del)', - selectNode: 'Bir nesne seç...', - showAll: 'tümünü göster', - showMore: 'daha fazla göster', - showMoreStatus: '${totalChilds} alanın ${visibleChilds} alt alanları gösteriliyor', - sort: 'Sırala', - sortTitle: '${type}\'ın alt alanlarını sırala', - sortTitleShort: 'İçerikleri sırala', - sortFieldLabel: 'Alan:', - sortDirectionLabel: 'Yön:', - sortFieldTitle: 'Diziyi veya nesneyi sıralamak için iç içe geçmiş alanı seçin', - sortAscending: 'Artan', - sortAscendingTitle: 'Seçili alanı artan düzende sırala', - sortDescending: 'Azalan', - sortDescendingTitle: 'Seçili alanı azalan düzende sırala', - string: 'Karakter Dizisi', - transform: 'Dönüştür', - transformTitle: '${type}\'ın alt alanlarını filtrele, sırala veya dönüştür', - transformTitleShort: 'İçerikleri filterele, sırala veya dönüştür', - transformQueryTitle: 'JMESPath sorgusu gir', - transformWizardLabel: 'Sihirbaz', - transformWizardFilter: 'Filtre', - transformWizardSortBy: 'Sırala', - transformWizardSelectFields: 'Alanları seç', - transformQueryLabel: 'Sorgu', - transformPreviewLabel: 'Önizleme', - type: 'Tip', - typeTitle: 'Bu alanın tipini değiştir', - openUrl: 'URL\'i yeni bir pencerede açmak için Ctrl+Click veya Ctrl+Enter', - undo: 'Son değişikliği geri al (Ctrl+Z)', - validationCannotMove: 'Alt alan olarak taşınamıyor', - autoType: 'Alan tipi "otomatik". ' + - 'Alan türü otomatik olarak değerden belirlenir' + - 've bir dize, sayı, boolean veya null olabilir.', - objectType: 'Alan tipi "nesne". ' + - 'Bir nesne, sıralanmamış bir anahtar / değer çifti kümesi içerir.', - arrayType: 'Alan tipi "dizi". ' + - 'Bir dizi, düzenli değerler koleksiyonu içerir.', - stringType: 'Alan tipi "karakter dizisi". ' + - 'Alan türü değerden belirlenmez,' + - 'ancak her zaman karakter dizisi olarak döndürülür.', - modeCodeText: 'Kod', - modeCodeTitle: 'Kod vurgulayıcıya geç', - modeFormText: 'Form', - modeFormTitle: 'Form düzenleyiciye geç', - modeTextText: 'Metin', - modeTextTitle: 'Düz metin düzenleyiciye geç', - modeTreeText: 'Ağaç', - modeTreeTitle: 'Ağaç düzenleyiciye geç', - modeViewText: 'Görünüm', - modeViewTitle: 'Ağaç görünümüne geç', - examples: 'Örnekler', - default: 'Varsayılan', - } -}; - -var _defaultLang = 'en'; -var _lang; -var userLang = typeof navigator !== 'undefined' ? - navigator.language || navigator.userLanguage : - undefined; -_lang = _locales.find(function (l) { - return l === userLang; -}); -if (!_lang) { - _lang = _defaultLang; -} - -module.exports = { - // supported locales - _locales: _locales, - _defs: _defs, - _lang: _lang, - setLanguage: function (lang) { - if (!lang) { - return; - } - var langFound = _locales.find(function (l) { - return l === lang; - }); - if (langFound) { - _lang = langFound; - } else { - console.error('Language not found'); - } - }, - setLanguages: function (languages) { - if (!languages) { - return; - } - for (var key in languages) { - var langFound = _locales.find(function (l) { - return l === key; - }); - if (!langFound) { - _locales.push(key); - } - _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]); - } - }, - translate: function (key, data, lang) { - if (!lang) { - lang = _lang; - } - var text = _defs[lang][key]; - if (data) { - for (key in data) { - text = text.replace('${' + key + '}', data[key]); - } - } - return text || key; - } -}; - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -__webpack_require__(6); -var naturalSort = __webpack_require__(7); -var jsonlint = __webpack_require__(20); -var jsonMap = __webpack_require__(21); -var translate = __webpack_require__(0).translate; +var MAX_ITEMS_FIELDS_COLLECTION = 10000; /** * Parse JSON using the parser built-in in the browser. @@ -589,14 +158,16 @@ exports.parse = function parse(jsonString) { }; /** - * Sanitize a JSON-like string containing. For example changes JavaScript + * Repair a JSON-like string containing. For example changes JavaScript * notation into JSON notation. * This function for example changes a string like "{a: 2, 'b': {c: 'd'}" * into '{"a": 2, "b": {"c": "d"}' * @param {string} jsString * @returns {string} json */ -exports.sanitize = function (jsString) { +exports.repair = function (jsString) { + // TODO: refactor this function, it's too large and complicated now + // escape all single and double quotes inside strings var chars = []; var i = 0; @@ -677,41 +248,49 @@ exports.sanitize = function (jsString) { } } - // parse single or double quoted string + /** + * parse single or double quoted string. Returns the parsed string + * @param {string} endQuote + * @return {string} + */ function parseString(endQuote) { - chars.push('"'); + var string = ''; + + string += '"'; i++; var c = curr(); while (i < jsString.length && c !== endQuote) { if (c === '"' && prev() !== '\\') { // unescaped double quote, escape it - chars.push('\\"'); + string += '\\"'; } else if (controlChars.hasOwnProperty(c)) { // replace unescaped control characters with escaped ones - chars.push(controlChars[c]) + string += controlChars[c] } else if (c === '\\') { // remove the escape character when followed by a single quote ', not needed i++; c = curr(); if (c !== '\'') { - chars.push('\\'); + string += '\\'; } - chars.push(c); + string += c; } else { // regular character - chars.push(c); + string += c; } i++; c = curr(); } if (c === endQuote) { - chars.push('"'); + string += '"'; i++; } + + return string; } // parse an unquoted key @@ -728,13 +307,69 @@ exports.sanitize = function (jsString) { } if (specialValues.indexOf(key) === -1) { - chars.push('"' + key + '"'); + return '"' + key + '"'; } else { - chars.push(key); + return key; } } + function parseMongoDataType () { + var c = curr(); + var value; + var dataType = ''; + while (/[a-zA-Z_$]/.test(c)) { + dataType += c + i++; + c = curr(); + } + + if (dataType.length > 0 && c === '(') { + // This is an MongoDB data type like {"_id": ObjectId("123")} + i++; + c = curr(); + if (c === '"') { + // a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z") + value = parseString(c); + c = curr(); + } + else { + // a data type containing a value, like 'NumberLong(2)' + value = ''; + while(c !== ')' && c !== '') { + value += c; + i++; + c = curr(); + } + } + + if (c === ')') { + // skip the closing bracket at the end + i++; + + // return the value (strip the data type object) + return value; + } + else { + // huh? that's unexpected. don't touch it + return dataType + '(' + value + c; + } + } + else { + // hm, no Mongo data type after all + return dataType; + } + } + + function isSpecialWhiteSpace (c) { + return ( + c === '\u00A0' || + (c >= '\u2000' && c <= '\u200A') || + c === '\u202F' || + c === '\u205F' || + c === '\u3000') + } + while(i < jsString.length) { var c = curr(); @@ -744,25 +379,25 @@ exports.sanitize = function (jsString) { else if (c === '/' && next() === '/') { skipComment(); } - else if (c === '\u00A0' || (c >= '\u2000' && c <= '\u200A') || c === '\u202F' || c === '\u205F' || c === '\u3000') { + else if (isSpecialWhiteSpace(c)) { // special white spaces (like non breaking space) chars.push(' '); i++ } else if (c === quote) { - parseString(quote); + chars.push(parseString(c)); } else if (c === quoteDbl) { - parseString(quoteDbl); + chars.push(parseString(quoteDbl)); } else if (c === graveAccent) { - parseString(acuteAccent); + chars.push(parseString(acuteAccent)); } else if (c === quoteLeft) { - parseString(quoteRight); + chars.push(parseString(quoteRight)); } else if (c === quoteDblLeft) { - parseString(quoteDblRight); + chars.push(parseString(quoteDblRight)); } else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) { // skip trailing commas @@ -770,11 +405,16 @@ exports.sanitize = function (jsString) { } else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { // an unquoted object key (like a in '{a:2}') - parseKey(); + chars.push(parseKey()); } else { - chars.push(c); - i++; + if (/[a-zA-Z_$]/.test(c)) { + chars.push(parseMongoDataType()); + } + else { + chars.push(c); + i++; + } } } @@ -1776,9 +1416,11 @@ exports.getChildPaths = function (json, includeObjects) { } if (Array.isArray(json)) { - json.forEach(function (item) { + var max = Math.min(json.length, MAX_ITEMS_FIELDS_COLLECTION); + for (var i = 0; i < max; i++) { + var item = json[i]; getObjectChildPaths(item, pathsMap, '', includeObjects); - }); + } } else { pathsMap[''] = true; @@ -1859,6 +1501,51 @@ exports.parseString = function(str) { } }; +/** + * Return a human readable document size + * For example formatSize(7570718) outputs '7.2 MiB' + * @param {number} size + * @return {string} Returns a human readable size + */ +exports.formatSize = function (size) { + if (size < 900) { + return size.toFixed() + ' B'; + } + + var KiB = size / 1024; + if (KiB < 900) { + return KiB.toFixed(1) + ' KiB'; + } + + var MiB = KiB / 1024; + if (MiB < 900) { + return MiB.toFixed(1) + ' MiB'; + } + + var GiB = MiB / 1024; + if (GiB < 900) { + return GiB.toFixed(1) + ' GiB'; + } + + var TiB = GiB / 1024; + return TiB.toFixed(1) + ' TiB'; +} + +/** + * Limit text to a maximum number of characters + * @param {string} text + * @param {number} maxCharacterCount + * @return {string} Returns the limited text, + * ending with '...' if the max was exceeded + */ +exports.limitCharacters = function (text, maxCharacterCount) { + if (text.length <= maxCharacterCount) { + return text; + } + + return text.slice(0, maxCharacterCount) + '...'; +} + /** * Test whether a value is an Object * @param {*} value @@ -1880,15 +1567,463 @@ exports.contains = function (array, item) { /***/ }), -/* 2 */ +/* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var createAbsoluteAnchor = __webpack_require__(8).createAbsoluteAnchor; -var util = __webpack_require__(1); -var translate = __webpack_require__(0).translate; +__webpack_require__(10); + +var _locales = ['en', 'pt-BR', 'zh-CN', 'tr']; +var _defs = { + en: { + array: 'Array', + auto: 'Auto', + appendText: 'Append', + appendTitle: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', + appendSubmenuTitle: 'Select the type of the field to be appended', + appendTitleAuto: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + ascending: 'Ascending', + ascendingTitle: 'Sort the childs of this ${type} in ascending order', + actionsMenu: 'Click to open the actions menu (Ctrl+M)', + collapseAll: 'Collapse all fields', + descending: 'Descending', + descendingTitle: 'Sort the childs of this ${type} in descending order', + drag: 'Drag to move this field (Alt+Shift+Arrows)', + duplicateKey: 'duplicate key', + duplicateText: 'Duplicate', + duplicateTitle: 'Duplicate selected fields (Ctrl+D)', + duplicateField: 'Duplicate this field (Ctrl+D)', + duplicateFieldError: 'Duplicate field name', + cannotParseFieldError: 'Cannot parse field into JSON', + cannotParseValueError: 'Cannot parse value into JSON', + empty: 'empty', + expandAll: 'Expand all fields', + expandTitle: 'Click to expand/collapse this field (Ctrl+E). \n' + + 'Ctrl+Click to expand/collapse including all childs.', + insert: 'Insert', + insertTitle: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', + insertSub: 'Select the type of the field to be inserted', + object: 'Object', + ok: 'Ok', + redo: 'Redo (Ctrl+Shift+Z)', + removeText: 'Remove', + removeTitle: 'Remove selected fields (Ctrl+Del)', + removeField: 'Remove this field (Ctrl+Del)', + selectNode: 'Select a node...', + showAll: 'show all', + showMore: 'show more', + showMoreStatus: 'displaying ${visibleChilds} of ${totalChilds} items.', + sort: 'Sort', + sortTitle: 'Sort the childs of this ${type}', + sortTitleShort: 'Sort contents', + sortFieldLabel: 'Field:', + sortDirectionLabel: 'Direction:', + sortFieldTitle: 'Select the nested field by which to sort the array or object', + sortAscending: 'Ascending', + sortAscendingTitle: 'Sort the selected field in ascending order', + sortDescending: 'Descending', + sortDescendingTitle: 'Sort the selected field in descending order', + string: 'String', + transform: 'Transform', + transformTitle: 'Filter, sort, or transform the childs of this ${type}', + transformTitleShort: 'Filter, sort, or transform contents', + extract: 'Extract', + extractTitle: 'Extract this ${type}', + transformQueryTitle: 'Enter a JMESPath query', + transformWizardLabel: 'Wizard', + transformWizardFilter: 'Filter', + transformWizardSortBy: 'Sort by', + transformWizardSelectFields: 'Select fields', + transformQueryLabel: 'Query', + transformPreviewLabel: 'Preview', + type: 'Type', + typeTitle: 'Change the type of this field', + openUrl: 'Ctrl+Click or Ctrl+Enter to open url in new window', + undo: 'Undo last action (Ctrl+Z)', + validationCannotMove: 'Cannot move a field into a child of itself', + autoType: 'Field type "auto". ' + + 'The field type is automatically determined from the value ' + + 'and can be a string, number, boolean, or null.', + objectType: 'Field type "object". ' + + 'An object contains an unordered set of key/value pairs.', + arrayType: 'Field type "array". ' + + 'An array contains an ordered collection of values.', + stringType: 'Field type "string". ' + + 'Field type is not determined from the value, ' + + 'but always returned as string.', + modeCodeText: 'Code', + modeCodeTitle: 'Switch to code highlighter', + modeFormText: 'Form', + modeFormTitle: 'Switch to form editor', + modeTextText: 'Text', + modeTextTitle: 'Switch to plain text editor', + modeTreeText: 'Tree', + modeTreeTitle: 'Switch to tree editor', + modeViewText: 'View', + modeViewTitle: 'Switch to tree view', + modePreviewText: 'Preview', + modePreviewTitle: 'Switch to preview mode', + examples: 'Examples', + default: 'Default', + }, + 'zh-CN': { + array: '数组', + auto: '自动', + appendText: '追加', + appendTitle: '在此字段后追加一个类型为“auto”的新字段 (Ctrl+Shift+Ins)', + appendSubmenuTitle: '选择要追加的字段类型', + appendTitleAuto: '追加类型为“auto”的新字段 (Ctrl+Shift+Ins)', + ascending: '升序', + ascendingTitle: '升序排列${type}的子节点', + actionsMenu: '点击打开动作菜单(Ctrl+M)', + collapseAll: '缩进所有字段', + descending: '降序', + descendingTitle: '降序排列${type}的子节点', + drag: '拖拽移动该节点(Alt+Shift+Arrows)', + duplicateKey: '重复键', + duplicateText: '复制', + duplicateTitle: '复制选中字段(Ctrl+D)', + duplicateField: '复制该字段(Ctrl+D)', + duplicateFieldError: '重复的字段名称', + cannotParseFieldError: '无法将字段解析为JSON', + cannotParseValueError: '无法将值解析为JSON', + empty: '清空', + expandAll: '展开所有字段', + expandTitle: '点击 展开/收缩 该字段(Ctrl+E). \n' + + 'Ctrl+Click 展开/收缩 包含所有子节点.', + insert: '插入', + insertTitle: '在此字段前插入类型为“auto”的新字段 (Ctrl+Ins)', + insertSub: '选择要插入的字段类型', + object: '对象', + ok: 'Ok', + redo: '重做 (Ctrl+Shift+Z)', + removeText: '移除', + removeTitle: '移除选中字段 (Ctrl+Del)', + removeField: '移除该字段 (Ctrl+Del)', + selectNode: '选择一个节点...', + showAll: '展示全部', + showMore: '展示更多', + showMoreStatus: '显示${totalChilds}的${visibleChilds}项目.', + sort: '排序', + sortTitle: '排序${type}的子节点', + sortTitleShort: '内容排序', + sortFieldLabel: '字段:', + sortDirectionLabel: '方向:', + sortFieldTitle: '选择用于对数组或对象排序的嵌套字段', + sortAscending: '升序排序', + sortAscendingTitle: '按照该字段升序排序', + sortDescending: '降序排序', + sortDescendingTitle: '按照该字段降序排序', + string: '字符串', + transform: '变换', + transformTitle: '筛选,排序,或者转换${type}的子节点', + transformTitleShort: '筛选,排序,或者转换内容', + transformQueryTitle: '输入JMESPath查询', + transformWizardLabel: '向导', + transformWizardFilter: '筛选', + transformWizardSortBy: '排序', + transformWizardSelectFields: '选择字段', + transformQueryLabel: '查询', + transformPreviewLabel: '预览', + type: '类型', + typeTitle: '更改字段类型', + openUrl: 'Ctrl+Click 或者 Ctrl+Enter 在新窗口打开链接', + undo: '撤销上次动作 (Ctrl+Z)', + validationCannotMove: '无法将字段移入其子节点', + autoType: '字段类型 "auto". ' + + '字段类型由值自动确定 ' + + '可以为 string,number,boolean,或者 null.', + objectType: '字段类型 "object". ' + + '对象包含一组无序的键/值对.', + arrayType: '字段类型 "array". ' + + '数组包含值的有序集合.', + stringType: '字段类型 "string". ' + + '字段类型由值自动确定,' + + '但始终作为字符串返回.', + modeCodeText: '代码', + modeCodeTitle: '切换至代码高亮', + modeFormText: '表单', + modeFormTitle: '切换至表单编辑', + modeTextText: '文本', + modeTextTitle: '切换至文本编辑', + modeTreeText: '树', + modeTreeTitle: '切换至树编辑', + modeViewText: '视图', + modeViewTitle: '切换至树视图', + examples: '例子', + default: '缺省', + }, + 'pt-BR': { + array: 'Lista', + auto: 'Automatico', + appendText: 'Adicionar', + appendTitle: 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)', + appendSubmenuTitle: 'Selecione o tipo do campo a ser adicionado', + appendTitleAuto: 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)', + ascending: 'Ascendente', + ascendingTitle: 'Organizar filhor do tipo ${type} em crescente', + actionsMenu: 'Clique para abrir o menu de ações (Ctrl+M)', + collapseAll: 'Fechar todos campos', + descending: 'Descendente', + descendingTitle: 'Organizar o filhos do tipo ${type} em decrescente', + duplicateKey: 'chave duplicada', + drag: 'Arraste para mover este campo (Alt+Shift+Arrows)', + duplicateText: 'Duplicar', + duplicateTitle: 'Duplicar campos selecionados (Ctrl+D)', + duplicateField: 'Duplicar este campo (Ctrl+D)', + duplicateFieldError: 'Nome do campo duplicado', + cannotParseFieldError: 'Não é possível analisar o campo no JSON', + cannotParseValueError: 'Não é possível analisar o valor em JSON', + empty: 'vazio', + expandAll: 'Expandir todos campos', + expandTitle: 'Clique para expandir/encolher este campo (Ctrl+E). \n' + + 'Ctrl+Click para expandir/encolher incluindo todos os filhos.', + insert: 'Inserir', + insertTitle: 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)', + insertSub: 'Selecionar o tipo de campo a ser inserido', + object: 'Objeto', + ok: 'Ok', + redo: 'Refazer (Ctrl+Shift+Z)', + removeText: 'Remover', + removeTitle: 'Remover campos selecionados (Ctrl+Del)', + removeField: 'Remover este campo (Ctrl+Del)', + // TODO: correctly translate + selectNode: 'Select a node...', + // TODO: correctly translate + showAll: 'mostre tudo', + // TODO: correctly translate + showMore: 'mostre mais', + // TODO: correctly translate + showMoreStatus: 'exibindo ${visibleChilds} de ${totalChilds} itens.', + sort: 'Organizar', + sortTitle: 'Organizar os filhos deste ${type}', + // TODO: correctly translate + sortTitleShort: 'Organizar os filhos', + // TODO: correctly translate + sortFieldLabel: 'Field:', + // TODO: correctly translate + sortDirectionLabel: 'Direction:', + // TODO: correctly translate + sortFieldTitle: 'Select the nested field by which to sort the array or object', + // TODO: correctly translate + sortAscending: 'Ascending', + // TODO: correctly translate + sortAscendingTitle: 'Sort the selected field in ascending order', + // TODO: correctly translate + sortDescending: 'Descending', + // TODO: correctly translate + sortDescendingTitle: 'Sort the selected field in descending order', + string: 'Texto', + // TODO: correctly translate + transform: 'Transform', + // TODO: correctly translate + transformTitle: 'Filter, sort, or transform the childs of this ${type}', + // TODO: correctly translate + transformTitleShort: 'Filter, sort, or transform contents', + // TODO: correctly translate + transformQueryTitle: 'Enter a JMESPath query', + // TODO: correctly translate + transformWizardLabel: 'Wizard', + // TODO: correctly translate + transformWizardFilter: 'Filter', + // TODO: correctly translate + transformWizardSortBy: 'Sort by', + // TODO: correctly translate + transformWizardSelectFields: 'Select fields', + // TODO: correctly translate + transformQueryLabel: 'Query', + // TODO: correctly translate + transformPreviewLabel: 'Preview', + type: 'Tipo', + typeTitle: 'Mudar o tipo deste campo', + openUrl: 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela', + undo: 'Desfazer último ação (Ctrl+Z)', + validationCannotMove: 'Não pode mover um campo como filho dele mesmo', + autoType: 'Campo do tipo "auto". ' + + 'O tipo do campo é determinao automaticamente a partir do seu valor ' + + 'e pode ser texto, número, verdade/falso ou nulo.', + objectType: 'Campo do tipo "objeto". ' + + 'Um objeto contém uma lista de pares com chave e valor.', + arrayType: 'Campo do tipo "lista". ' + + 'Uma lista contem uma coleção de valores ordenados.', + stringType: 'Campo do tipo "string". ' + + 'Campo do tipo nao é determinado através do seu valor, ' + + 'mas sempre retornara um texto.', + examples: 'Exemplos', + default: 'Revelia', + }, + tr: { + array: 'Dizin', + auto: 'Otomatik', + appendText: 'Ekle', + appendTitle: 'Bu alanın altına \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', + appendSubmenuTitle: 'Eklenecek alanın tipini seç', + appendTitleAuto: '\'Otomatik\' tipinde yeni bir alan ekle (Ctrl+Shift+Ins)', + ascending: 'Artan', + ascendingTitle: '${type}\'ın alt tiplerini artan düzende sırala', + actionsMenu: 'Aksiyon menüsünü açmak için tıklayın (Ctrl+M)', + collapseAll: 'Tüm alanları kapat', + descending: 'Azalan', + descendingTitle: '${type}\'ın alt tiplerini azalan düzende sırala', + drag: 'Bu alanı taşımak için sürükleyin (Alt+Shift+Arrows)', + duplicateKey: 'Var olan anahtar', + duplicateText: 'Aşağıya kopyala', + duplicateTitle: 'Seçili alanlardan bir daha oluştur (Ctrl+D)', + duplicateField: 'Bu alandan bir daha oluştur (Ctrl+D)', + duplicateFieldError: 'Duplicate field name', + cannotParseFieldError: 'Alan JSON\'a ayrıştırılamıyor', + cannotParseValueError: 'JSON\'a değer ayrıştırılamıyor', + empty: 'boş', + expandAll: 'Tüm alanları aç', + expandTitle: 'Bu alanı açmak/kapatmak için tıkla (Ctrl+E). \n' + + 'Alt alanlarda dahil tüm alanları açmak için Ctrl+Click ', + insert: 'Ekle', + insertTitle: 'Bu alanın üstüne \'otomatik\' tipinde yeni bir alan ekle (Ctrl+Ins)', + insertSub: 'Araya eklenecek alanın tipini seç', + object: 'Nesne', + ok: 'Tamam', + redo: 'Yeniden yap (Ctrl+Shift+Z)', + removeText: 'Kaldır', + removeTitle: 'Seçilen alanları kaldır (Ctrl+Del)', + removeField: 'Bu alanı kaldır (Ctrl+Del)', + selectNode: 'Bir nesne seç...', + showAll: 'tümünü göster', + showMore: 'daha fazla göster', + showMoreStatus: '${totalChilds} alanın ${visibleChilds} alt alanları gösteriliyor', + sort: 'Sırala', + sortTitle: '${type}\'ın alt alanlarını sırala', + sortTitleShort: 'İçerikleri sırala', + sortFieldLabel: 'Alan:', + sortDirectionLabel: 'Yön:', + sortFieldTitle: 'Diziyi veya nesneyi sıralamak için iç içe geçmiş alanı seçin', + sortAscending: 'Artan', + sortAscendingTitle: 'Seçili alanı artan düzende sırala', + sortDescending: 'Azalan', + sortDescendingTitle: 'Seçili alanı azalan düzende sırala', + string: 'Karakter Dizisi', + transform: 'Dönüştür', + transformTitle: '${type}\'ın alt alanlarını filtrele, sırala veya dönüştür', + transformTitleShort: 'İçerikleri filterele, sırala veya dönüştür', + transformQueryTitle: 'JMESPath sorgusu gir', + transformWizardLabel: 'Sihirbaz', + transformWizardFilter: 'Filtre', + transformWizardSortBy: 'Sırala', + transformWizardSelectFields: 'Alanları seç', + transformQueryLabel: 'Sorgu', + transformPreviewLabel: 'Önizleme', + type: 'Tip', + typeTitle: 'Bu alanın tipini değiştir', + openUrl: 'URL\'i yeni bir pencerede açmak için Ctrl+Click veya Ctrl+Enter', + undo: 'Son değişikliği geri al (Ctrl+Z)', + validationCannotMove: 'Alt alan olarak taşınamıyor', + autoType: 'Alan tipi "otomatik". ' + + 'Alan türü otomatik olarak değerden belirlenir' + + 've bir dize, sayı, boolean veya null olabilir.', + objectType: 'Alan tipi "nesne". ' + + 'Bir nesne, sıralanmamış bir anahtar / değer çifti kümesi içerir.', + arrayType: 'Alan tipi "dizi". ' + + 'Bir dizi, düzenli değerler koleksiyonu içerir.', + stringType: 'Alan tipi "karakter dizisi". ' + + 'Alan türü değerden belirlenmez,' + + 'ancak her zaman karakter dizisi olarak döndürülür.', + modeCodeText: 'Kod', + modeCodeTitle: 'Kod vurgulayıcıya geç', + modeFormText: 'Form', + modeFormTitle: 'Form düzenleyiciye geç', + modeTextText: 'Metin', + modeTextTitle: 'Düz metin düzenleyiciye geç', + modeTreeText: 'Ağaç', + modeTreeTitle: 'Ağaç düzenleyiciye geç', + modeViewText: 'Görünüm', + modeViewTitle: 'Ağaç görünümüne geç', + examples: 'Örnekler', + default: 'Varsayılan', + } +}; + +var _defaultLang = 'en'; +var _lang; +var userLang = typeof navigator !== 'undefined' ? + navigator.language || navigator.userLanguage : + undefined; +_lang = _locales.find(function (l) { + return l === userLang; +}); +if (!_lang) { + _lang = _defaultLang; +} + +module.exports = { + // supported locales + _locales: _locales, + _defs: _defs, + _lang: _lang, + setLanguage: function (lang) { + if (!lang) { + return; + } + var langFound = _locales.find(function (l) { + return l === lang; + }); + if (langFound) { + _lang = langFound; + } else { + console.error('Language not found'); + } + }, + setLanguages: function (languages) { + if (!languages) { + return; + } + for (var key in languages) { + var langFound = _locales.find(function (l) { + return l === key; + }); + if (!langFound) { + _locales.push(key); + } + _defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]); + } + }, + translate: function (key, data, lang) { + if (!lang) { + lang = _lang; + } + var text = _defs[lang][key]; + if (data) { + for (key in data) { + text = text.replace('${' + key + '}', data[key]); + } + } + return text || key; + } +}; + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + +exports.DEFAULT_MODAL_ANCHOR = document.body; +exports.SIZE_LARGE = 10 * 1024 * 1024; // 10 MB + +exports.MAX_PREVIEW_CHARACTERS = 20000; + +exports.PREVIEW_HISTORY_LIMIT = 2 * 1024 * 1024 * 1024; // 2 GB + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var createAbsoluteAnchor = __webpack_require__(12).createAbsoluteAnchor; +var util = __webpack_require__(0); +var translate = __webpack_require__(1).translate; /** * A context menu @@ -2325,7 +2460,7 @@ module.exports = ContextMenu; /***/ }), -/* 3 */ +/* 4 */ /***/ (function(module, exports, __webpack_require__) { (function(exports) { @@ -3997,255 +4132,13 @@ module.exports = ContextMenu; })( false ? undefined : exports); -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -var ace -if (window.ace) { - // use the already loaded instance of Ace - ace = window.ace -} -else { - try { - // load brace - ace = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'brace'"); e.code = 'MODULE_NOT_FOUND'; throw e; }())); - - // load required Ace plugins - __webpack_require__(14); - __webpack_require__(16); - } - catch (err) { - // failed to load brace (can be minimalist bundle). - // No worries, the editor will fall back to plain text if needed. - } -} - -module.exports = ace; - - /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { -var VanillaPicker; - -if (window.Picker) { - // use the already loaded instance of VanillaPicker - VanillaPicker = window.Picker; -} -else { - try { - // load color picker - VanillaPicker = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module 'vanilla-picker'"); e.code = 'MODULE_NOT_FOUND'; throw e; }())); - } - catch (err) { - // probably running the minimalist bundle - } -} - -module.exports = VanillaPicker; - - -/***/ }), -/* 6 */ -/***/ (function(module, exports) { - - -if (typeof Element !== 'undefined') { - // Polyfill for array remove - (function () { - function polyfill (item) { - if (item.hasOwnProperty('remove')) { - return; - } - Object.defineProperty(item, 'remove', { - configurable: true, - enumerable: true, - writable: true, - value: function remove() { - if (this.parentNode != null) - this.parentNode.removeChild(this); - } - }); - } - - if (typeof Element !== 'undefined') { polyfill(Element.prototype); } - if (typeof CharacterData !== 'undefined') { polyfill(CharacterData.prototype); } - if (typeof DocumentType !== 'undefined') { polyfill(DocumentType.prototype); } - })(); -} - - -// Polyfill for startsWith -if (!String.prototype.startsWith) { - String.prototype.startsWith = function (searchString, position) { - position = position || 0; - return this.substr(position, searchString.length) === searchString; - }; -} - -// Polyfill for Array.find -if (!Array.prototype.find) { - Array.prototype.find = function(callback) { - for (var i = 0; i < this.length; i++) { - var element = this[i]; - if ( callback.call(this, element, i, this) ) { - return element; - } - } - } -} - -// Polyfill for String.trim -if (!String.prototype.trim) { - String.prototype.trim = function () { - return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); - }; -} - - -/***/ }), -/* 7 */ -/***/ (function(module, exports) { - -/* - * Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license - * Author: Jim Palmer (based on chunking idea from Dave Koelle) - */ -/*jshint unused:false */ -module.exports = function naturalSort (a, b) { - "use strict"; - var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, - sre = /(^[ ]*|[ ]*$)/g, - dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, - hre = /^0x[0-9a-f]+$/i, - ore = /^0/, - i = function(s) { return naturalSort.insensitive && ('' + s).toLowerCase() || '' + s; }, - // convert all to strings strip whitespace - x = i(a).replace(sre, '') || '', - y = i(b).replace(sre, '') || '', - // chunk/tokenize - xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), - yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), - // numeric, hex or date detection - xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && x.match(dre) && Date.parse(x)), - yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, - oFxNcL, oFyNcL; - // first try and sort Hex codes or Dates - if (yD) { - if ( xD < yD ) { return -1; } - else if ( xD > yD ) { return 1; } - } - // natural sorting through split numeric strings and default strings - for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) { - // find floats not starting with '0', string or 0 if not defined (Clint Priest) - oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0; - oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0; - // handle numeric vs string comparison - number < string - (Kyle Adams) - if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? 1 : -1; } - // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2' - else if (typeof oFxNcL !== typeof oFyNcL) { - oFxNcL += ''; - oFyNcL += ''; - } - if (oFxNcL < oFyNcL) { return -1; } - if (oFxNcL > oFyNcL) { return 1; } - } - return 0; -}; - - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - -var util = __webpack_require__(1); - -/** - * Create an anchor element absolutely positioned in the `parent` - * element. - * @param {HTMLElement} anchor - * @param {HTMLElement} parent - * @param [onDestroy(function(anchor)] Callback when the anchor is destroyed - * @returns {HTMLElement} - */ -exports.createAbsoluteAnchor = function (anchor, parent, onDestroy) { - var root = getRootNode(anchor); - var eventListeners = {}; - - var anchorRect = anchor.getBoundingClientRect(); - var frameRect = parent.getBoundingClientRect(); - - var absoluteAnchor = document.createElement('div'); - absoluteAnchor.className = 'jsoneditor-anchor'; - absoluteAnchor.style.position = 'absolute'; - absoluteAnchor.style.left = (anchorRect.left - frameRect.left) + 'px'; - absoluteAnchor.style.top = (anchorRect.top - frameRect.top) + 'px'; - absoluteAnchor.style.width = (anchorRect.width - 2) + 'px'; - absoluteAnchor.style.height = (anchorRect.height - 2) + 'px'; - absoluteAnchor.style.boxSizing = 'border-box'; - parent.appendChild(absoluteAnchor); - - function destroy () { - // remove temporary absolutely positioned anchor - if (absoluteAnchor && absoluteAnchor.parentNode) { - absoluteAnchor.parentNode.removeChild(absoluteAnchor); - - // remove all event listeners - // all event listeners are supposed to be attached to document. - for (var name in eventListeners) { - if (eventListeners.hasOwnProperty(name)) { - var fn = eventListeners[name]; - if (fn) { - util.removeEventListener(root, name, fn); - } - delete eventListeners[name]; - } - } - - if (typeof onDestroy === 'function') { - onDestroy(anchor); - } - } - } - - // create and attach event listeners - var destroyIfOutside = function (event) { - var target = event.target; - if ((target !== absoluteAnchor) && !util.isChildOf(target, absoluteAnchor)) { - destroy(); - } - } - - eventListeners.mousedown = util.addEventListener(root, 'mousedown', destroyIfOutside); - eventListeners.mousewheel = util.addEventListener(root, 'mousewheel', destroyIfOutside); - // eventListeners.scroll = util.addEventListener(root, 'scroll', destroyIfOutside); - - absoluteAnchor.destroy = destroy; - - return absoluteAnchor -} - -/** - * Node.getRootNode shim - * @param {HTMLElement} node node to check - * @return {HTMLElement} node's rootNode or `window` if there is ShadowDOM is not supported. - */ -function getRootNode(node){ - return (typeof node.getRootNode === 'function') - ? node.getRootNode() - : window; -} - - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -var picoModal = __webpack_require__(10); -var translate = __webpack_require__(0).translate; -var util = __webpack_require__(1); +var picoModal = __webpack_require__(13); +var translate = __webpack_require__(1).translate; +var util = __webpack_require__(0); /** * Show advanced sorting modal @@ -4374,8 +4267,681 @@ function showSortModal (container, json, onSort, options) { module.exports = showSortModal; +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +var jmespath = __webpack_require__(4); +var picoModal = __webpack_require__(13); +var Selectr = __webpack_require__(30); +var translate = __webpack_require__(1).translate; +var stringifyPartial = __webpack_require__(31).stringifyPartial; +var util = __webpack_require__(0); +var MAX_PREVIEW_CHARACTERS = __webpack_require__(2).MAX_PREVIEW_CHARACTERS +var debounce = util.debounce; + +/** + * Show advanced filter and transform modal using JMESPath + * @param {HTMLElement} container The container where to center + * the modal and create an overlay + * @param {JSON} json The json data to be transformed + * @param {function} onTransform Callback invoked with the created + * query as callback + */ +function showTransformModal (container, json, onTransform) { + var value = json; + + var content = '