@discoveryjs/discovery
Advanced tools
Comparing version 1.0.0-beta.77 to 1.0.0-beta.78
{ | ||
"name": "@discoveryjs/discovery", | ||
"version": "1.0.0-beta.77", | ||
"version": "1.0.0-beta.78", | ||
"description": "Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards", | ||
@@ -37,3 +37,3 @@ "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)", | ||
"hitext": "^1.0.0-beta.1", | ||
"jora": "1.0.0-beta.7", | ||
"jora": "1.0.0-beta.8", | ||
"marked": "^4.3.0" | ||
@@ -40,0 +40,0 @@ }, |
@@ -8,3 +8,2 @@ /* eslint-env browser */ | ||
import { createElement } from '../core/utils/dom.js'; | ||
import { escapeHtml } from '../core/utils/html.js'; | ||
import Progressbar from '../core/utils/progressbar.js'; | ||
@@ -109,2 +108,3 @@ import * as navButtons from '../nav/buttons.js'; | ||
'badge:"Error"', | ||
{ view: 'text', when: 'stage', data: '`[${stage}] `' }, | ||
'text:errorText' | ||
@@ -117,4 +117,5 @@ ] | ||
], { | ||
errorText: escapeHtml(error.message || String(error)), | ||
errorStack: error.stack ? escapeHtml(error.stack).replace(/^Error:\s*(\S+Error:)/, '$1') : '' | ||
stage: progressbar?.lastStage, | ||
errorText: error.message || String(error), | ||
errorStack: (error.stack || '').replace(/^Error:\s*(\S+Error:)/, '$1') | ||
}, { | ||
@@ -121,0 +122,0 @@ actions: this.action.actionMap |
@@ -1,1 +0,1 @@ | ||
export const version = "1.0.0-beta.77"; | ||
export const version = "1.0.0-beta.78"; |
@@ -1,50 +0,57 @@ | ||
export { default as alerts } from './alerts.js'; | ||
export { default as autoLink } from './auto-link.js'; | ||
export { default as badges } from './badges.js'; | ||
export { default as block } from './block.js'; | ||
export { default as button } from './button.js'; | ||
export { default as checkboxList } from './checkbox-list.js'; | ||
export { default as checkbox } from './checkbox.js'; | ||
export { default as column } from './column.js'; | ||
export { default as columns } from './columns.js'; | ||
export { default as contentFilter } from './content-filter.js'; | ||
export { default as button } from './controls/button.js'; | ||
export { default as checkboxList } from './controls/checkbox-list.js'; | ||
export { default as checkbox } from './controls/checkbox.js'; | ||
export { default as contentFilter } from './controls/content-filter.js'; | ||
export { default as dropdown } from './controls/dropdown.js'; | ||
export { default as input } from './controls/input.js'; | ||
export { default as menu } from './controls/menu.js'; | ||
export { default as menuItem } from './controls/menu-item.js'; | ||
export { default as navButton } from './controls/nav-button.js'; | ||
export { default as progressbar } from './controls/progress.js'; | ||
export { default as select } from './controls/select.js'; | ||
export { default as tabs } from './controls/tabs.js'; | ||
export { default as tab } from './controls/tab.js'; | ||
export { default as toggle } from './controls/toggle.js'; | ||
export { default as toggleGroup } from './controls/toggle-group.js'; | ||
export { default as editors } from './editor/editors.js'; | ||
export { default as block } from './layout/block.js'; | ||
export { default as column } from './layout/column.js'; | ||
export { default as columns } from './layout/columns.js'; | ||
export { default as expand } from './layout/expand.js'; | ||
export { default as hstack } from './layout/hstack.js'; | ||
export { default as listItem } from './layout/list-item.js'; | ||
export { default as lists } from './layout/lists.js'; | ||
export { default as pageHeader } from './layout/page-header.js'; | ||
export { default as popup } from './layout/popup.js'; | ||
export { default as section } from './layout/section.js'; | ||
export { default as tocSection } from './layout/toc-section.js'; | ||
export { default as alerts } from './text/alerts.js'; | ||
export { default as autoLink } from './text/auto-link.js'; | ||
export { default as badges } from './text/badges.js'; | ||
export { default as headers } from './text/headers.js'; | ||
export { default as html } from './text/html.js'; | ||
export { default as image } from './text/image.js'; | ||
export { default as imagePreview } from './text/image-preview.js'; | ||
export { default as indicator } from './text/indicator.js'; | ||
export { default as link } from './text/link.js'; | ||
export { default as markdown } from './text/markdown.js'; | ||
export { default as source } from './text/source.js'; | ||
export { default as text } from './text/text.js'; | ||
export { default as textMatch } from './text/text-match.js'; | ||
export { default as textNumeric } from './text/text-numeric.js'; | ||
export { default as context } from './context.js'; | ||
export { default as dropdown } from './dropdown.js'; | ||
export { default as editors } from './editors.js'; | ||
export { default as expand } from './expand.js'; | ||
export { default as headers } from './headers.js'; | ||
export { default as hstack } from './hstack.js'; | ||
export { default as html } from './html.js'; | ||
export { default as image } from './image.js'; | ||
export { default as imagePreview } from './image-preview.js'; | ||
export { default as indicator } from './indicator.js'; | ||
export { default as input } from './input.js'; | ||
export { default as link } from './link.js'; | ||
export { default as listItem } from './list-item.js'; | ||
export { default as lists } from './lists.js'; | ||
export { default as markdown } from './markdown.js'; | ||
export { default as menu } from './menu.js'; | ||
export { default as menuItem } from './menu-item.js'; | ||
export { default as navButton } from './nav-button.js'; | ||
export { default as pageHeader } from './page-header.js'; | ||
export { default as popup } from './popup.js'; | ||
export { default as progressbar } from './progress.js'; | ||
export { default as section } from './section.js'; | ||
export { default as select } from './select.js'; | ||
export { default as signature } from './signature.js'; | ||
export { default as source } from './source.js'; | ||
export { default as struct } from './struct.js'; | ||
export { default as switch } from './switch.js'; | ||
export { default as table } from './table.js'; | ||
export { default as tableRow } from './table-row.js'; | ||
export { default as tableCell } from './table-cell.js'; | ||
export { default as tabs } from './tabs.js'; | ||
export { default as tab } from './tab.js'; | ||
export { default as text } from './text.js'; | ||
export { default as textMatch } from './text-match.js'; | ||
export { default as textNumeric } from './text-numeric.js'; | ||
export { default as tocSection } from './toc-section.js'; | ||
export { default as toggle } from './toggle.js'; | ||
export { default as toggleGroup } from './toggle-group.js'; | ||
export { default as tree } from './tree.js'; | ||
export { default as treeItem } from './tree-leaf.js'; | ||
export { default as signature } from './signature/index.js'; | ||
export { default as struct } from './struct/index.js'; | ||
export { default as table } from './table/table.js'; | ||
export { default as tableRow } from './table/table-row.js'; | ||
export { default as tableCell } from './table/table-cell.js'; | ||
export { default as tree } from './tree/tree.js'; | ||
export { default as treeItem } from './tree/tree-leaf.js'; |
/* eslint-env browser */ | ||
import { escapeHtml, numDelim } from '../../core/utils/html.js'; | ||
import { jsonStringifyInfo } from '../../core/utils/json.js'; | ||
import copyText from '../../core/utils/copy-text.js'; | ||
import { numDelim } from '../../core/utils/html.js'; | ||
import { createClickHandler } from './click-handler.js'; | ||
import { createValueActionsPopup } from './popup-value-actions.js'; | ||
import value2html from './value-to-html.js'; | ||
@@ -17,2 +17,3 @@ import renderAnnotations from './render-annotations.js'; | ||
} from './el-proto.js'; | ||
import { createSignaturePopup } from './poup-signature.js'; | ||
@@ -65,10 +66,2 @@ const hasOwnProperty = Object.prototype.hasOwnProperty; | ||
function formatSize(size) { | ||
if (!size) { | ||
return ''; | ||
} | ||
return ', ' + numDelim(size) + ' bytes'; | ||
} | ||
function renderValueSize(el, entries, unit) { | ||
@@ -82,3 +75,4 @@ if (entries.length > 1) { | ||
function renderSorting(el, entries, sort) { | ||
let sorted = entries.length <= 1 || entries.every(([key], idx) => idx === 0 || key > entries[idx - 1][0]); | ||
const sorted = entries.length < 2 || | ||
entries.every(([key], idx) => idx === 0 || key > entries[idx - 1][0]); | ||
@@ -94,7 +88,7 @@ if (sorted) { | ||
const objectKeyEl = objectKeyProtoEl.cloneNode(true); | ||
const x = name.length > maxLength | ||
const fittedToMaxLength = name.length > maxLength | ||
? name.slice(0, maxLength) + '…' | ||
: name; | ||
appendText(objectKeyEl.firstElementChild, x); | ||
appendText(objectKeyEl.firstElementChild, fittedToMaxLength); | ||
container.appendChild(objectKeyEl); | ||
@@ -300,3 +294,3 @@ } | ||
} | ||
}, 0); | ||
}); | ||
} | ||
@@ -312,210 +306,14 @@ } | ||
const valueActionsPopup = new host.view.Popup({ | ||
className: 'view-struct-actions-popup', | ||
render: (popupEl, triggerEl) => { | ||
const el = triggerEl.parentNode; | ||
const data = elementData.get(el); | ||
let actions = []; | ||
const valueActionsPopup = createValueActionsPopup(host, elementData, buildPathForElement); | ||
const signaturePopup = createSignaturePopup(host, elementData, buildPathForElement); | ||
const clickHandler = createClickHandler( | ||
expandValue, | ||
collapseValue, | ||
scheduleApplyAnnotations, | ||
renderTable, | ||
structViewRoots, | ||
valueActionsPopup, | ||
signaturePopup | ||
); | ||
if (typeof data === 'string') { | ||
actions = [ | ||
{ | ||
text: 'Copy as quoted string', | ||
action: () => copyText(JSON.stringify(data)) | ||
}, | ||
{ | ||
text: 'Copy as unquoted string', | ||
action: () => copyText(JSON.stringify(data).slice(1, -1)) | ||
}, | ||
{ | ||
text: 'Copy a value (unescaped)', | ||
action: () => copyText(data) | ||
} | ||
]; | ||
} else { | ||
const path = host.pathToQuery(buildPathForElement(el)); | ||
const maxAllowedSize = 1024 * 1024 * 1024; | ||
let jsonFormattedStringifyError = false; | ||
let jsonCompactStringifyError = false; | ||
let compactSize = 0; | ||
let formattedSize = 0; | ||
try { | ||
const { minLength, circular } = jsonStringifyInfo(data); | ||
compactSize = minLength; | ||
if (circular.length) { | ||
jsonCompactStringifyError = 'Converting circular structure to JSON'; | ||
} else if (compactSize > maxAllowedSize) { | ||
jsonCompactStringifyError = 'Resulting JSON is over 1 Gb'; | ||
} else { | ||
formattedSize = jsonStringifyInfo(data, null, 4).minLength; | ||
if (formattedSize > maxAllowedSize) { | ||
jsonFormattedStringifyError = 'Resulting JSON is over 1 Gb'; | ||
} | ||
} | ||
} catch (e) { | ||
jsonCompactStringifyError = /Maximum call stack size|too much recursion/i.test(e.message) | ||
? 'Too much nested structure' | ||
: e.message; | ||
} | ||
if (jsonCompactStringifyError) { | ||
jsonCompactStringifyError = 'Can\'t be copied: ' + jsonCompactStringifyError; | ||
if (!jsonFormattedStringifyError) { | ||
jsonFormattedStringifyError = jsonCompactStringifyError; | ||
} | ||
} | ||
if (path) { | ||
actions.push({ | ||
text: 'Copy path:', | ||
notes: escapeHtml(path), | ||
action: () => copyText(path) | ||
}); | ||
} | ||
actions.push({ | ||
text: 'Copy as JSON', | ||
notes: `(formatted${formatSize(formattedSize)})`, | ||
error: jsonFormattedStringifyError, | ||
disabled: Boolean(jsonFormattedStringifyError), | ||
action: () => copyText(JSON.stringify(data, null, 4)) | ||
}); | ||
actions.push({ | ||
text: 'Copy as JSON', | ||
notes: `(compact${jsonCompactStringifyError ? '' : formatSize(compactSize)})`, | ||
error: jsonCompactStringifyError, | ||
disabled: Boolean(jsonCompactStringifyError), | ||
action: () => copyText(JSON.stringify(data)) | ||
}); | ||
} | ||
host.view.render(popupEl, { | ||
view: 'menu', | ||
onClick(item) { | ||
valueActionsPopup.hide(); | ||
item.action(); | ||
}, | ||
item: [ | ||
'html:text', | ||
{ | ||
view: 'block', | ||
when: 'notes', | ||
className: 'notes', | ||
content: 'html:notes' | ||
}, | ||
{ | ||
view: 'block', | ||
when: 'error', | ||
className: 'error', | ||
content: 'text:error' | ||
} | ||
] | ||
}, actions); | ||
} | ||
}); | ||
const signaturePopup = new host.view.Popup({ | ||
hoverPin: 'popup-hover', | ||
hoverTriggers: '.view-struct .show-signature', | ||
render: function(popupEl, triggerEl) { | ||
const el = triggerEl.parentNode; | ||
const data = elementData.get(el); | ||
host.view.render(popupEl, { | ||
view: 'signature', | ||
expanded: 2, | ||
path: buildPathForElement(el) | ||
}, data); | ||
} | ||
}); | ||
const clickHandler = ({ target }) => { | ||
let action = 'expand'; | ||
let cursor = target.closest(` | ||
.view-struct.struct-expand, | ||
.view-struct .struct-expand-value, | ||
.view-struct .struct-action-button | ||
`); | ||
if (!cursor) { | ||
return; | ||
} | ||
if (cursor.dataset.action) { | ||
action = cursor.dataset.action; | ||
} | ||
switch (action) { | ||
case 'expand': | ||
if (cursor.classList.contains('struct-expand')) { | ||
// expand root element | ||
cursor = cursor.lastChild; | ||
} | ||
// expand value | ||
expandValue(cursor, 0); | ||
scheduleApplyAnnotations(); | ||
cursor.parentNode.classList.add('struct-expanded-value'); | ||
if (structViewRoots.has(cursor.parentNode)) { | ||
cursor.parentNode.classList.remove('struct-expand'); | ||
} | ||
break; | ||
case 'collapse': | ||
cursor = cursor.parentNode; | ||
collapseValue(cursor); | ||
scheduleApplyAnnotations(); | ||
cursor.parentNode.classList.remove('struct-expanded-value'); | ||
cursor.classList.remove('view-as-table'); | ||
if (structViewRoots.has(cursor.parentNode)) { | ||
cursor.parentNode.classList.add('struct-expand'); | ||
} | ||
break; | ||
case 'show-signature': | ||
signaturePopup.show(cursor); | ||
break; | ||
case 'value-actions': | ||
valueActionsPopup.show(cursor); | ||
break; | ||
case 'toggle-sort-keys': | ||
expandValue(cursor.parentNode, 0, cursor.parentNode.classList.toggle('sort-keys')); | ||
scheduleApplyAnnotations(); | ||
break; | ||
case 'toggle-string-mode': | ||
cursor = cursor.parentNode; | ||
const stringTextNode = cursor.querySelector('.string-text').firstChild; | ||
stringTextNode.nodeValue = cursor.classList.toggle('string-value-as-text') | ||
? JSON.parse(`"${stringTextNode.nodeValue}"`) | ||
: JSON.stringify(stringTextNode.nodeValue).slice(1, -1); | ||
break; | ||
case 'toggle-view-as-table': | ||
cursor = cursor.parentNode; | ||
const asTable = cursor.classList.toggle('view-as-table'); | ||
if (asTable) { | ||
renderTable(cursor); | ||
} else { | ||
const tableEl = cursor.querySelector(':scope > .view-table'); | ||
if (tableEl) { | ||
tableEl.remove(); | ||
} | ||
} | ||
break; | ||
} | ||
}; | ||
// single event handler for all `struct` view instances | ||
@@ -522,0 +320,0 @@ host.addHostElEventListener('click', clickHandler, false); |
@@ -18,5 +18,7 @@ import ObjectMarker from '../core/object-marker.js'; | ||
addQueryHelpers(helpers) { | ||
joraSetup = jora.setup(queryCustomMethods = { | ||
...queryCustomMethods, | ||
...helpers | ||
joraSetup = jora.setup({ | ||
methods: queryCustomMethods = { | ||
...queryCustomMethods, | ||
...helpers | ||
} | ||
}); | ||
@@ -39,3 +41,3 @@ }, | ||
}; | ||
let joraSetup = jora.setup(queryCustomMethods); | ||
let joraSetup = jora.setup({ methods: queryCustomMethods }); | ||
@@ -42,0 +44,0 @@ return Object.assign(host => Object.assign(host, { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1328182
19632
+ Addedjora@1.0.0-beta.8(transitive)
- Removedjora@1.0.0-beta.7(transitive)
Updatedjora@1.0.0-beta.8