New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@discoveryjs/discovery

Package Overview
Dependencies
Maintainers
3
Versions
93
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@discoveryjs/discovery - npm Package Compare versions

Comparing version 1.0.0-beta.65 to 1.0.0-beta.66

src/version.js

15

package.json
{
"name": "@discoveryjs/discovery",
"version": "1.0.0-beta.65",
"version": "1.0.0-beta.66",
"description": "Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards",

@@ -21,3 +21,4 @@ "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)",

"build-gh-pages": "discovery-build -o .gh-pages --clean",
"prepublishOnly": "npm run build",
"prepublishOnly": "node scripts/bake-version && npm run build",
"postpublish": "node scripts/bake-version --rollback",
"cypress": "npx cypress open",

@@ -35,10 +36,10 @@ "cypress:server": "discovery -c ./cypress/fixtures/single-model/.discoveryrc.js -p 8124",

"hitext": "^1.0.0-beta.1",
"jora": "1.0.0-beta.6",
"marked": "^4.0.14"
"jora": "1.0.0-beta.7",
"marked": "^4.0.18"
},
"devDependencies": {
"@discoveryjs/cli": "^2.0.0-beta.14",
"@discoveryjs/cli": "^2.1.1",
"cypress": "^9.5.4",
"esbuild": "~0.14.36",
"eslint": "^8.13.0",
"esbuild": "~0.14.49",
"eslint": "^8.19.0",
"eslint-plugin-cypress": "^2.12.1"

@@ -45,0 +46,0 @@ },

@@ -22,2 +22,3 @@ <img align="right" width="128" height="128"

- [Statoscope](https://github.com/statoscope/statoscope) – a toolkit to analyze and validate webpack bundle
- [CPUpro](https://github.com/lahmatiy/cpupro) – rethinking of CPU profile analysis
- [CSS syntax reference](https://csstree.github.io/docs/syntax/) ([source](https://github.com/csstree/docs/tree/master/src/syntax))

@@ -24,0 +25,0 @@ - [CSSWG spec drafts index](https://csstree.github.io/csswg-drafts-index/) ([source](https://github.com/csstree/csswg-drafts-index))

@@ -31,4 +31,4 @@ /* eslint-env browser */

const el = container.appendChild(document.createElement('div'));
el.className = 'buildin-view-config-error';
el.innerText = errorMsg;
el.className = 'discovery-buildin-view-config-error';
el.textContent = errorMsg;

@@ -35,0 +35,0 @@ return Promise.resolve();

@@ -8,1 +8,11 @@ export function escapeHtml(str) {

}
export function numDelim(num) {
const strNum = String(num);
if (strNum.length > 3) {
return strNum.replace(/\..+$|\B(?=(\d{3})+(\D|$))/g, m => m || '<span class="num-delim"></span>');
}
return strNum;
}

@@ -11,3 +11,3 @@ /* eslint-env browser */

const configTransitions = new WeakMap();
const specialConfigProps = new Set([
const configOnlyProps = new Set([
'view',

@@ -71,7 +71,9 @@ 'when',

function createDefaultConfigErrorView(view) {
return {
name: 'config-error',
render: function(el, config) {
el.className = 'buildin-view-config-error';
function createDefaultRenderErrorView(view) {
return {
name: false,
options: STUB_OBJECT,
render(el, config) {
el.className = 'discovery-buildin-view-render-error';
el.dataset.type = config.type;
el.textContent = config.reason;

@@ -81,3 +83,2 @@

const configEl = el.appendChild(document.createElement('span'));
let expanded = false;

@@ -87,12 +88,7 @@ configEl.className = 'toggle-config';

configEl.addEventListener('click', () => {
expanded = !expanded;
el.classList.toggle('expanded', expanded);
configEl.textContent = expanded ? 'hide config...' : 'show config...';
if (expanded) {
const buffer = document.createDocumentFragment();
view.render(buffer, { view: 'struct', expanded: 1 }, config.config)
.then(() => el.appendChild(buffer));
if (el.classList.toggle('expanded')) {
configEl.textContent = 'hide config...';
view.render(el, { view: 'struct', expanded: 1 }, config.config);
} else {
configEl.textContent = 'show config...';
el.lastChild.remove();

@@ -102,6 +98,5 @@ }

}
},
options: STUB_OBJECT
}
};
};
}

@@ -127,3 +122,3 @@ function condition(type, host, config, data, context, inputData, placeholder) {

function renderDom(renderer, placeholder, config, props, data, context, inputData) {
function renderDom(host, renderer, placeholder, config, props, data, context, inputData) {
const { tag } = renderer.options;

@@ -141,3 +136,13 @@ const el = tag === false || tag === null

.then(function() {
if (el.classList) {
const info = {
config,
props,
inputData,
data,
context
};
if (el.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
viewEls.set(el, info);
if (renderer.name) {

@@ -150,2 +155,6 @@ el.classList.add(`view-${renderer.name}`);

if (typeof classNames === 'string' && classNames.startsWith('=')) {
classNames = host.queryFn(classNames.slice(1));
}
if (typeof classNames === 'function') {

@@ -167,14 +176,2 @@ classNames = classNames(data, context);

}
}
const info = {
config,
props,
inputData,
data,
context
};
if (el.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
viewEls.set(el, info);
} else {

@@ -285,4 +282,4 @@ for (let child of el.childNodes) {

renderer = this.get('config-error') || this.defaultConfigErrorRenderer;
config = { reason: errorMsg, config };
renderer = this.defaultRenderErrorRenderer;
config = { type: 'config', reason: errorMsg, config };
}

@@ -307,2 +304,3 @@

? renderDom(
this.host,
renderer,

@@ -319,9 +317,7 @@ placeholder,

.catch(e => {
renderDom(this.get('alert-danger'), placeholder, {
postRender(el) {
el.style.whiteSpace = 'pre-wrap';
el.style.fontFamily = 'monospace';
el.style.fontSize = '12px';
}
}, {}, e);
renderDom(this.host, this.defaultRenderErrorRenderer, placeholder, STUB_OBJECT, {
type: 'render',
reason: String(e),
config
});
console.error(e);

@@ -339,3 +335,3 @@ });

this.host = host;
this.defaultConfigErrorRenderer = createDefaultConfigErrorView(this);
this.defaultRenderErrorRenderer = createDefaultRenderErrorView(this);
}

@@ -407,3 +403,4 @@

return {
view: this.defaultConfigErrorRenderer.render,
view: this.defaultRenderErrorRenderer.render,
type: 'config',
reason: errorMsg,

@@ -444,3 +441,4 @@ config

for (const [key, value] of Object.entries(config)) {
if (!specialConfigProps.has(key)) {
// Config only props are not available for view's render
if (!configOnlyProps.has(key)) {
props[key] = typeof value === 'string' && value.startsWith('=')

@@ -447,0 +445,0 @@ ? this.host.query(value.slice(1), data, context)

@@ -10,4 +10,6 @@ import App from './app/index.js';

import { buttons as navButtons } from './nav/index.js';
import { version } from './version.js';
export {
version,
Widget,

@@ -14,0 +16,0 @@ App,

@@ -1,3 +0,4 @@

import { createFragment } from '../core/utils/dom.js';
import { createElement, createFragment } from '../core/utils/dom.js';
import { ContentRect } from '../core/utils/size.js';
import { version } from '../version.js';

@@ -69,2 +70,12 @@ function createNavArray(host, defaults) {

constructor(host) {
const poweredByDiscovery = createElement('div', 'powered-by-discoveryjs', [
'powered by ',
createElement('a', {
class: 'view-link',
href: 'https://github.com/discoveryjs/discovery',
target: '_blank'
}, 'Discovery.js'),
` ${version}`
]);
this.host = host;

@@ -104,3 +115,3 @@ this.popup = null;

this.popup.toggle(el, (el) => el.append(...nodes));
this.popup.toggle(el, (el) => el.append(...nodes, poweredByDiscovery));
}

@@ -107,0 +118,0 @@ },

import { createElement } from '../../core/utils/dom.js';
import { escapeHtml } from '../../core/utils/html.js';
import { contextWithoutEditorParams } from './params.js';

@@ -79,2 +80,3 @@ function count(value, one, many) {

perform(data, context) {
const queryContext = contextWithoutEditorParams(context, lastQuery.context);
let pageQuery = context.params.query;

@@ -84,6 +86,7 @@ let queryTime;

// update editor
queryEditor.setValue(pageQuery);
// perform data query
if (lastQuery.query === pageQuery && lastQuery.data === data && lastQuery.context === context) {
if (lastQuery.query === pageQuery && lastQuery.data === data && lastQuery.context === queryContext) {
results = lastQuery.results;

@@ -98,3 +101,3 @@ } else {

queryTime = Date.now();
results = host.query(pageQuery, data, context);
results = host.query(pageQuery, data, queryContext);
queryTime = Date.now() - queryTime;

@@ -127,4 +130,4 @@ } catch (error) {

data,
context: queryContext,
query: pageQuery,
context,
results

@@ -131,0 +134,0 @@ };

@@ -5,2 +5,3 @@ import debounce from '../../core/utils/debounce.js';

import { jsonStringifyAsJavaScript } from '../../core/utils/json.js';
import { contextWithoutEditorParams } from './params.js';
import renderUsage from '../../views/_usage.js';

@@ -171,2 +172,3 @@

render(data, context, reportContentEl) {
const viewContext = contextWithoutEditorParams(context, lastView.context);
const viewMode = typeof context.params.view === 'string' ? 'custom' : 'default';

@@ -190,3 +192,3 @@ let pageView = context.params.view;

if (lastView.data !== data || lastView.view !== pageView) {
if (lastView.view !== pageView || lastView.data !== data || lastView.context !== viewContext) {
reportContentEl.innerHTML = '';

@@ -196,3 +198,3 @@

view = Function('return ' + (pageView ? '0,' + pageView : 'null'))();
host.view.render(reportContentEl, view, data, context);
host.view.render(reportContentEl, view, data, viewContext);
} catch (e) {

@@ -207,3 +209,4 @@ host.view.render(reportContentEl, el => {

lastView = {
data: data,
data,
context: viewContext,
view: pageView

@@ -210,0 +213,0 @@ };

@@ -18,2 +18,24 @@ /* eslint-env browser */

function toDate(value) {
if (value && (typeof value === 'number' || typeof value === 'string')) {
const date = new Date(value);
return !isNaN(date) ? date : null;
}
return value instanceof Date ? value : null;
}
function formatDate(value) {
const date = toDate(value);
if (date) {
return date
.toISOString()
.replace(/^(\d{4})-(\d{2})-(\d{2})T([\d:]+).*/, '$3/$2/$1 $4');
}
return null;
}
export default function(host, updateParams) {

@@ -107,2 +129,3 @@ let titleInputEl;

const { title, noedit } = context.params;
const createdAt = formatDate(context.createdAt);

@@ -113,8 +136,8 @@ titleInputEl.value = title;

noeditToggleEl.classList.toggle('disabled', noedit);
dataDateTimeEl.innerText = context.createdAt && typeof context.createdAt.toLocaleString === 'function'
? 'Data collected at ' + context.createdAt.toLocaleString().replace(',', '') + ' | '
dataDateTimeEl.innerText = createdAt
? 'Data collected at ' + createdAt + ' | '
: '';
viewDateTimeEl.innerText = 'View built at ' + new Date().toLocaleString().replace(',', '');
viewDateTimeEl.innerText = 'Rendered at ' + formatDate(new Date());
}
};
}

@@ -7,4 +7,6 @@ import * as base64 from '../../core/utils/base64.js';

export const decodedSpecialParams = ['query', 'view', 'title', 'dzen', 'noedit'];
export const encodedSpecialParams = ['q', 'v', 'title', 'dzen', 'noedit'];
export function encodeParams(params) {
const specialParams = ['query', 'view', 'title', 'dzen', 'noedit'];
const { query, view, title, dzen, noedit, ...extra } = typeof params === 'string' ? { query: params } : params;

@@ -34,3 +36,3 @@ const pairs = [];

Object.keys(extra || {}).sort().forEach(name => {
if (!specialParams.includes(name)) {
if (!decodedSpecialParams.includes(name)) {
pairs.push([name, name.endsWith('-b64') && typeof extra[name] === 'string'

@@ -48,3 +50,2 @@ ? base64.encode(extra[name])

const params = Object.fromEntries(pairs);
const specialParams = ['q', 'v', 'title', 'dzen', 'noedit'];
const decodedParams = {

@@ -59,3 +60,3 @@ title: params.title || '',

Object.keys(params).forEach(name => {
if (!specialParams.includes(name)) {
if (!encodedSpecialParams.includes(name)) {
decodedParams[name] = name.endsWith('-b64') && typeof params[name] === 'string'

@@ -69,1 +70,37 @@ ? base64.decode(params[name])

}
function filterDecodedParams(params) {
return Object.fromEntries(Object.entries(params).filter(([key]) =>
!decodedSpecialParams.includes(key)
));
}
function isEqual(a, b, skipKey) {
for (const key of Object.keys(a)) {
if (key !== skipKey && a[key] !== b[key]) {
return false;
}
}
for (const key of Object.keys(b)) {
if (key !== skipKey && a[key] !== b[key]) {
return false;
}
}
return true;
}
export function contextWithoutEditorParams(newContext, currentContext = {}) {
const stableNewContext = {
...newContext,
params: filterDecodedParams(newContext.params)
};
if (!isEqual(currentContext, stableNewContext, 'params') ||
!isEqual(currentContext.params, stableNewContext.params)) {
return stableNewContext;
}
return currentContext;
}
import renderUsage from '../views/_usage.js';
const intro = `
## Working with views
A presentation in Discovery.js is setting up as a tree of views.
There are several ways to define a view, some may be more convenient in one case, others in another.
The main notation is an object, all other notations are converted to it.
The only required property is \`view\` which defines a view name, any other properties are optional:
\`\`\`discovery-view
{
view: "view-name"
}
\`\`\`
The following properties are supported by any view:
- \`when\` – control view rendering (should it be rendered or not) before an input data is transformed (\`data\` is applied)
- \`data\` – transform input data for the view and its nested views
- \`whenData\` – control view rendering after an input data is transformed
- \`className\` – add class name(s) to the root element of view if any
- \`postRender\` - a function which should be invoked after view rendering but before placing to destination place in DOM
The order of evaluation during a view render:
\`\`\`js
input data | output data (the result of "data" evaluation if any)
|
render start ---> [when] --> [data] -|-> [whenData] --> [postRender] --> [className] --> render finish
|
\`\`\`
When \`data\` property is specified, it changes flow's data according the following rules:
- a string – treated as a query which result is used as the output data
- a function like \`fn(data, context)\` – the result of the function invocation is used as the output data
- any other value used as the output data
> Note: Only \`when\` and \`data\` properties get an input data, any other functions and queries receive
a result of \`data\` property evalution. When \`data\` is not specified all the queries and functions
receive the same input data.
Properties \`when\` and \`whenData\` can take:
- a string – treated as a query
- \`true\` – treated as a empty query which mean that the data itself is examinated with no any transformation
- \`undefined\` – same when not specified, just render (ignore the property)
- a function like \`fn(data, context)\`
- any other value used as is
Regardless of how the value is obtained, it is coerce to a boolean.
Plase note, that Jora rules are used which mean that empty arrays and object with no own keys are falsy (truthy in JavaScript).
The view is only rendered if the resulting value is truthy.
## Queries for properties
In some cases, it is necessary to compute the value of a property based on the data.
To do this, you can use a string value for a property that starts with \`=\`.
This will mean that everything after the \`=\` is a query which will take output data and produce a value for the property.
Other values are passed to the view render as is, without any changes.
In the following, limit number of items rendered at once only if there are more than 12 items:
\`\`\`discovery-view
{
view: 'list',
limit: '=size() <= 12 and 10' // the same as '=size() <= 12 ? false : 10'
}
\`\`\`
> Note: In those rare cases when you need to pass to a property a string that starts with \`=\`,
you can use a query like \`="=some string"\`,<br>e.g. \`{ view: 'example', prop: '="=string="' }\`
## Shorthand notations
| Shorhand notation | Expanding into ... |
| --- | --- |
| \`'name'\` | \`{ view: 'name' }\`
| \`'name:<query>'\` | \`{ view: 'name', data: '<query>' }\`
| \`'name{ foo: size() / 2, bar: "qux" }'\` | \`{ view: 'name', foo: '=size() / 2', bar: 'qux' }\`
## List of views
If you need to specify a list of views, then you must use an array.
An array with view definitions can be passed anywhere a view is accepted as a value.
\`\`\`discovery-view
[
{
view: 'list',
item: [
'text:name',
{ view: 'badge', data: 'something.size()' }
]
},
'table{ limit: 10 }'
]
\`\`\`
`;
export default function(host) {

@@ -40,3 +139,7 @@ // const fixture = () => ({

{ when: 'no $ and #.id', content: 'alert-warning:"View \\"" + #.id + "\\" not found"' },
{ when: 'no $', content: 'text:"Select a view"' },
{ when: 'no $', content: [
'h1:"Views showcase"',
'alert:"← Select a view to get details"',
{ view: 'markdown', source: intro }
] },
{ content: [

@@ -43,0 +146,0 @@ { view: 'context', postRender: function(el, config, data, context) {

@@ -95,3 +95,3 @@ /* eslint-env browser */

{ value: 'config-json', text: 'Config (JSON)' },
{ value: 'html', text: 'HTML' }
{ value: 'html', text: 'Output (HTML)' }
],

@@ -98,0 +98,0 @@ content: {

@@ -15,2 +15,3 @@ /* eslint-env browser */

host.view.define('alert', render, { usage });
host.view.define('alert-primary', render, { usage });
host.view.define('alert-success', render, { usage });

@@ -17,0 +18,0 @@ host.view.define('alert-danger', render, { usage });

@@ -18,3 +18,14 @@ /* eslint-env browser */

const { content } = config;
let { color, textColor, darkColor, darkTextColor, text, href, prefix, postfix, hint } = data || {};
let {
color,
textColor,
darkColor,
darkTextColor,
text,
href,
external,
prefix,
postfix,
hint
} = data || {};
let render;

@@ -46,2 +57,6 @@

if (external) {
el.target = '_blank';
}
if (hint) {

@@ -48,0 +63,0 @@ el.title = hint;

@@ -12,8 +12,21 @@ export default (view, group) => ({

{
title: 'With color',
title: 'Custom colors',
beforeDemo: {
view: 'md',
source: [
'Data properties to setup a custom colors:',
'* `color` – default background color',
'* `textColor` – default text color',
'* `darkColor` – background color in dark mode',
'* `textColor` – text color in dark mode'
].join('\n')
},
demo: {
view,
data: {
text: 'Colored badge',
color: 'rgba(237, 177, 9, 0.35)',
text: 'Colored badge'
textColor: 'orange',
darkColor: '#ffff00',
darkTextColor: 'black'
}

@@ -23,25 +36,2 @@ }

{
title: 'With text color',
demo: {
view,
data: {
textColor: 'red',
text: 'Badge with colored text'
}
}
},
{
title: 'With explicit dark-mode colors',
demo: {
view,
data: {
color: 'blue',
textColor: 'white',
darkColor: 'yellow',
darkTextColor: 'black',
text: 'Badge with colored text'
}
}
},
{
title: 'As a link',

@@ -51,4 +41,5 @@ demo: {

data: {
text: 'Link to something',
href: '#',
text: 'Click me!'
external: true
}

@@ -63,4 +54,4 @@ }

prefix: 'prefix',
postfix: 'postfix',
text: 'text'
text: 'link',
postfix: 'postfix'
}

@@ -67,0 +58,0 @@ }

@@ -6,3 +6,3 @@ /* eslint-env browser */

view,
onClick: () => alert('Hello world!'),
onClick: Function('return () => alert("Hello world!")')(),
data: {

@@ -9,0 +9,0 @@ text: 'Button'

@@ -0,1 +1,3 @@

import { demoImageSrc } from './image.usage.js';
export default {

@@ -5,3 +7,3 @@ beforeDemo: ['md:"The same as `image` view but with "'],

view: 'image-preview',
src: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij4KICAgIDxyZWN0IHg9IjY1LjYiIHk9IjI0LjYiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTM5NyAtMC4zNDIgMC4zNDIgMC45Mzk3IC05Ljk0MjYgMzEuODI4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjM5LjMiIGhlaWdodD0iMzkiPjwvcmVjdD4KICAgIDxyZWN0IHg9IjcwLjYiIHk9IjUyLjciIHRyYW5zZm9ybT0ibWF0cml4KC0wLjkzOTcgMC4zNDIgLTAuMzQyIC0wLjkzOTcgMTk0Ljc4NTIgODEuMTIwNCkiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzOS4zIiBoZWlnaHQ9IjEwIj48L3JlY3Q+CiAgICA8cGF0aCBmaWxsPSIjOThCRUQ4IiBkPSJNMTExLjUsNTQuNmwtMS4xLDEuMUw5Ny4xLDE5LjFsMS41LDAuMmM4LDAuOSwxNC43LDYuMiwxNy40LDEzLjdsMCwwQzExOC44LDQwLjQsMTE3LDQ4LjgsMTExLjUsNTQuNnoiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03My41LDcyLjJjLTEuMiwwLTIuNC0wLjgtMi44LTJMNTcuMywzMy41Yy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzNi45LTEzLjRjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTMuMywzNi42YzAuMywwLjcsMC4yLDEuNi0wLjEsMi4zYy0wLjMsMC43LTAuOSwxLjMtMS43LDEuNkw3NC41LDcyQzc0LjIsNzIuMSw3My44LDcyLjIsNzMuNSw3Mi4yek02NCwzNC4zbDExLjMsMzFsMzEuMy0xMS40bC0xMS4zLTMxTDY0LDM0LjN6Ij48L3BhdGg+CiAgICA8cmVjdCB4PSIzNSIgeT0iNDYuNyIgdHJhbnNmb3JtPSJtYXRyaXgoMC45Mzk3IC0wLjM0MiAwLjM0MiAwLjkzOTcgLTE2LjIwMTEgMjAuOTg4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjMyLjgiIGhlaWdodD0iMTkuNSI+PC9yZWN0PgogICAgPHJlY3QgeD0iMzcuMyIgeT0iNTkuOCIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTM5NyAwLjM0MiAtMC4zNDIgLTAuOTM5NyAxMjUuNjc2MyAxMDMuMzk0NikiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzMi44IiBoZWlnaHQ9IjYiPjwvcmVjdD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik0zOS40LDc0LjJjLTAuNCwwLTAuOS0wLjEtMS4zLTAuM2MtMC43LTAuMy0xLjMtMC45LTEuNi0xLjdsLTYuNy0xOC4zYy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzMC44LTExLjJjMC43LTAuMywxLjYtMC4yLDIuMywwLjFjMC43LDAuMywxLjMsMC45LDEuNiwxLjdMNzMsNTljMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhMNDAuNCw3NEM0MCw3NC4xLDM5LjcsNzQuMiwzOS40LDc0LjJ6IE0zNi41LDU0LjdsNC42LDEyLjdsMjUuMi05LjJsLTQuNi0xMi43TDM2LjUsNTQuN3oiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03MCwxMTguOWMtMS4yLDAtMi40LTAuNy0yLjgtMS45bC0xNC0zNy4ybC04LjQsMy4xbC0xNy4yLDM0LjRjLTAuNywxLjUtMi41LDIuMS00LDEuM2MtMS41LTAuNy0yLjEtMi41LTEuMy00TDQwLDc5YzAuMy0wLjcsMC45LTEuMiwxLjctMS41TDU0LDczLjFjMS41LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTUsNDBjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjlDNzAuNywxMTguOCw3MC40LDExOC45LDcwLDExOC45eiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjYsODAuMWMtMS4yLDAtMi40LTAuOC0yLjgtMkw2LjMsNjUuOWMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsNC40LDEyLjJjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhDMTQuMyw4MC4xLDE0LDgwLjEsMTMuNiw4MC4xeiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjIsNzMuM2MtMS4yLDAtMi40LTAuOC0yLjgtMmMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhMMzUsNTkuMmMxLjYtMC42LDMuMywwLjIsMy44LDEuOGMwLjYsMS42LTAuMiwzLjMtMS44LDMuOGwtMjIuOCw4LjNDMTMuOSw3My4zLDEzLjYsNzMuMywxMy4yLDczLjN6Ij48L3BhdGg+Cjwvc3ZnPgo=',
src: demoImageSrc,
height: 100

@@ -8,0 +10,0 @@ },

@@ -0,5 +1,6 @@

export const demoImageSrc = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij4KICAgIDxyZWN0IHg9IjY1LjYiIHk9IjI0LjYiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTM5NyAtMC4zNDIgMC4zNDIgMC45Mzk3IC05Ljk0MjYgMzEuODI4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjM5LjMiIGhlaWdodD0iMzkiPjwvcmVjdD4KICAgIDxyZWN0IHg9IjcwLjYiIHk9IjUyLjciIHRyYW5zZm9ybT0ibWF0cml4KC0wLjkzOTcgMC4zNDIgLTAuMzQyIC0wLjkzOTcgMTk0Ljc4NTIgODEuMTIwNCkiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzOS4zIiBoZWlnaHQ9IjEwIj48L3JlY3Q+CiAgICA8cGF0aCBmaWxsPSIjOThCRUQ4IiBkPSJNMTExLjUsNTQuNmwtMS4xLDEuMUw5Ny4xLDE5LjFsMS41LDAuMmM4LDAuOSwxNC43LDYuMiwxNy40LDEzLjdsMCwwQzExOC44LDQwLjQsMTE3LDQ4LjgsMTExLjUsNTQuNnoiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03My41LDcyLjJjLTEuMiwwLTIuNC0wLjgtMi44LTJMNTcuMywzMy41Yy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzNi45LTEzLjRjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTMuMywzNi42YzAuMywwLjcsMC4yLDEuNi0wLjEsMi4zYy0wLjMsMC43LTAuOSwxLjMtMS43LDEuNkw3NC41LDcyQzc0LjIsNzIuMSw3My44LDcyLjIsNzMuNSw3Mi4yek02NCwzNC4zbDExLjMsMzFsMzEuMy0xMS40bC0xMS4zLTMxTDY0LDM0LjN6Ij48L3BhdGg+CiAgICA8cmVjdCB4PSIzNSIgeT0iNDYuNyIgdHJhbnNmb3JtPSJtYXRyaXgoMC45Mzk3IC0wLjM0MiAwLjM0MiAwLjkzOTcgLTE2LjIwMTEgMjAuOTg4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjMyLjgiIGhlaWdodD0iMTkuNSI+PC9yZWN0PgogICAgPHJlY3QgeD0iMzcuMyIgeT0iNTkuOCIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTM5NyAwLjM0MiAtMC4zNDIgLTAuOTM5NyAxMjUuNjc2MyAxMDMuMzk0NikiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzMi44IiBoZWlnaHQ9IjYiPjwvcmVjdD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik0zOS40LDc0LjJjLTAuNCwwLTAuOS0wLjEtMS4zLTAuM2MtMC43LTAuMy0xLjMtMC45LTEuNi0xLjdsLTYuNy0xOC4zYy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzMC44LTExLjJjMC43LTAuMywxLjYtMC4yLDIuMywwLjFjMC43LDAuMywxLjMsMC45LDEuNiwxLjdMNzMsNTljMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhMNDAuNCw3NEM0MCw3NC4xLDM5LjcsNzQuMiwzOS40LDc0LjJ6IE0zNi41LDU0LjdsNC42LDEyLjdsMjUuMi05LjJsLTQuNi0xMi43TDM2LjUsNTQuN3oiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03MCwxMTguOWMtMS4yLDAtMi40LTAuNy0yLjgtMS45bC0xNC0zNy4ybC04LjQsMy4xbC0xNy4yLDM0LjRjLTAuNywxLjUtMi41LDIuMS00LDEuM2MtMS41LTAuNy0yLjEtMi41LTEuMy00TDQwLDc5YzAuMy0wLjcsMC45LTEuMiwxLjctMS41TDU0LDczLjFjMS41LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTUsNDBjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjlDNzAuNywxMTguOCw3MC40LDExOC45LDcwLDExOC45eiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjYsODAuMWMtMS4yLDAtMi40LTAuOC0yLjgtMkw2LjMsNjUuOWMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsNC40LDEyLjJjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhDMTQuMyw4MC4xLDE0LDgwLjEsMTMuNiw4MC4xeiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjIsNzMuM2MtMS4yLDAtMi40LTAuOC0yLjgtMmMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhMMzUsNTkuMmMxLjYtMC42LDMuMywwLjIsMy44LDEuOGMwLjYsMS42LTAuMiwzLjMtMS44LDMuOGwtMjIuOCw4LjNDMTMuOSw3My4zLDEzLjYsNzMuMywxMy4yLDczLjN6Ij48L3BhdGg+Cjwvc3ZnPgo=';
export default {
demo: {
view: 'image',
src: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjggMTI4Ij4KICAgIDxyZWN0IHg9IjY1LjYiIHk9IjI0LjYiIHRyYW5zZm9ybT0ibWF0cml4KDAuOTM5NyAtMC4zNDIgMC4zNDIgMC45Mzk3IC05Ljk0MjYgMzEuODI4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjM5LjMiIGhlaWdodD0iMzkiPjwvcmVjdD4KICAgIDxyZWN0IHg9IjcwLjYiIHk9IjUyLjciIHRyYW5zZm9ybT0ibWF0cml4KC0wLjkzOTcgMC4zNDIgLTAuMzQyIC0wLjkzOTcgMTk0Ljc4NTIgODEuMTIwNCkiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzOS4zIiBoZWlnaHQ9IjEwIj48L3JlY3Q+CiAgICA8cGF0aCBmaWxsPSIjOThCRUQ4IiBkPSJNMTExLjUsNTQuNmwtMS4xLDEuMUw5Ny4xLDE5LjFsMS41LDAuMmM4LDAuOSwxNC43LDYuMiwxNy40LDEzLjdsMCwwQzExOC44LDQwLjQsMTE3LDQ4LjgsMTExLjUsNTQuNnoiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03My41LDcyLjJjLTEuMiwwLTIuNC0wLjgtMi44LTJMNTcuMywzMy41Yy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzNi45LTEzLjRjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTMuMywzNi42YzAuMywwLjcsMC4yLDEuNi0wLjEsMi4zYy0wLjMsMC43LTAuOSwxLjMtMS43LDEuNkw3NC41LDcyQzc0LjIsNzIuMSw3My44LDcyLjIsNzMuNSw3Mi4yek02NCwzNC4zbDExLjMsMzFsMzEuMy0xMS40bC0xMS4zLTMxTDY0LDM0LjN6Ij48L3BhdGg+CiAgICA8cmVjdCB4PSIzNSIgeT0iNDYuNyIgdHJhbnNmb3JtPSJtYXRyaXgoMC45Mzk3IC0wLjM0MiAwLjM0MiAwLjkzOTcgLTE2LjIwMTEgMjAuOTg4KSIgZmlsbD0iI0ZGRkZGRiIgd2lkdGg9IjMyLjgiIGhlaWdodD0iMTkuNSI+PC9yZWN0PgogICAgPHJlY3QgeD0iMzcuMyIgeT0iNTkuOCIgdHJhbnNmb3JtPSJtYXRyaXgoLTAuOTM5NyAwLjM0MiAtMC4zNDIgLTAuOTM5NyAxMjUuNjc2MyAxMDMuMzk0NikiIGZpbGw9IiNDN0Q3RTIiIHdpZHRoPSIzMi44IiBoZWlnaHQ9IjYiPjwvcmVjdD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik0zOS40LDc0LjJjLTAuNCwwLTAuOS0wLjEtMS4zLTAuM2MtMC43LTAuMy0xLjMtMC45LTEuNi0xLjdsLTYuNy0xOC4zYy0wLjMtMC43LTAuMi0xLjYsMC4xLTIuM2MwLjMtMC43LDAuOS0xLjMsMS43LTEuNmwzMC44LTExLjJjMC43LTAuMywxLjYtMC4yLDIuMywwLjFjMC43LDAuMywxLjMsMC45LDEuNiwxLjdMNzMsNTljMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhMNDAuNCw3NEM0MCw3NC4xLDM5LjcsNzQuMiwzOS40LDc0LjJ6IE0zNi41LDU0LjdsNC42LDEyLjdsMjUuMi05LjJsLTQuNi0xMi43TDM2LjUsNTQuN3oiPjwvcGF0aD4KICAgIDxwYXRoIGZpbGw9IiM0NTRCNTQiIGQ9Ik03MCwxMTguOWMtMS4yLDAtMi40LTAuNy0yLjgtMS45bC0xNC0zNy4ybC04LjQsMy4xbC0xNy4yLDM0LjRjLTAuNywxLjUtMi41LDIuMS00LDEuM2MtMS41LTAuNy0yLjEtMi41LTEuMy00TDQwLDc5YzAuMy0wLjcsMC45LTEuMiwxLjctMS41TDU0LDczLjFjMS41LTAuNiwzLjMsMC4yLDMuOCwxLjhsMTUsNDBjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjlDNzAuNywxMTguOCw3MC40LDExOC45LDcwLDExOC45eiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjYsODAuMWMtMS4yLDAtMi40LTAuOC0yLjgtMkw2LjMsNjUuOWMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhjMS42LTAuNiwzLjMsMC4yLDMuOCwxLjhsNC40LDEyLjJjMC42LDEuNi0wLjIsMy4zLTEuOCwzLjhDMTQuMyw4MC4xLDE0LDgwLjEsMTMuNiw4MC4xeiI+PC9wYXRoPgogICAgPHBhdGggZmlsbD0iIzQ1NEI1NCIgZD0iTTEzLjIsNzMuM2MtMS4yLDAtMi40LTAuOC0yLjgtMmMtMC42LTEuNiwwLjItMy4zLDEuOC0zLjhMMzUsNTkuMmMxLjYtMC42LDMuMywwLjIsMy44LDEuOGMwLjYsMS42LTAuMiwzLjMtMS44LDMuOGwtMjIuOCw4LjNDMTMuOSw3My4zLDEzLjYsNzMuMywxMy4yLDczLjN6Ij48L3BhdGg+Cjwvc3ZnPgo=',
src: demoImageSrc,
height: 100

@@ -6,0 +7,0 @@ },

@@ -45,2 +45,3 @@ export { default as alerts } from './alerts.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';

@@ -47,0 +48,0 @@ export { default as toggle } from './toggle.js';

@@ -26,3 +26,3 @@ export default {

title: 'Interpolation',
beforeDemo: ['md:"Interpolation can be used almost anywhere in a markdown to embed the result of a jora query into resulting HTML. Just wrap a jora query in `{{`{{}` + `}`}}`:"'],
beforeDemo: ['md:"Interpolation can be used almost anywhere in a markdown to embed the result of a jora query into resulting HTML. Just place a jora query between `{{`{{`}}` and `{{`}`+`}`}}`:"'],
demo: {

@@ -29,0 +29,0 @@ view: 'md',

@@ -151,3 +151,3 @@ /* eslint-env browser */

this.hide = this.hide.bind(this);
this.hideTimer;
this.hideTimer = null;

@@ -349,3 +349,18 @@ this.lastTriggerEl = null;

}
destroy() {
inspectorLockedInstances.delete(this);
const popupIndex = hoverTriggerInstances.indexOf(this);
if (popupIndex !== -1) {
hoverTriggerInstances.splice(popupIndex, 1);
}
this.hide();
this.el = null;
this.lastTriggerEl = null;
this.lastHoverTriggerEl = null;
}
};
};

@@ -0,5 +1,7 @@

const codeExample = 'let name = "world";\n\nconsole.log(`Hello, ${name}!`);';
export default {
demo: {
view: 'source',
data: { content: 'var hello = "world";', syntax: 'js' }
data: { content: codeExample, syntax: 'js' }
},

@@ -28,3 +30,3 @@ examples: [

data: {
content: 'const a = 1; // line number 5',
content: codeExample,
syntax: 'js',

@@ -40,3 +42,3 @@ lineNum: idx => idx + 5

data: {
content: 'const a = 1;',
content: codeExample,
syntax: 'js',

@@ -43,0 +45,0 @@ lineNum: false

@@ -30,2 +30,9 @@ import { createElement, createFragment } from '../../core/utils/dom.js';

},
get viewAsTable() {
return createElement('span', {
class: 'struct-action-button',
title: 'Toggle view as table',
'data-action': 'toggle-view-as-table'
});
},
get sortKeys() {

@@ -56,2 +63,3 @@ return createElement('span', {

valueButtons.actions,
valueButtons.viewAsTable,
createElement('span', 'value-size'),

@@ -65,2 +73,3 @@ ']'

valueButtons.actions,
valueButtons.viewAsTable,
valueButtons.sortKeys,

@@ -73,5 +82,5 @@ createElement('span', 'value-size'),

export const objectKeyProtoEl = createElement('span', 'label', [
'\xA0 \xA0 ',
'\xA0\xA0\xA0\xA0',
createElement('span', 'property'),
':\xA0'
]);
/* eslint-env browser */
import { escapeHtml } from '../../core/utils/html.js';
import { escapeHtml, numDelim } from '../../core/utils/html.js';
import { jsonStringifyInfo } from '../../core/utils/json.js';

@@ -22,6 +22,16 @@ import copyText from '../../core/utils/copy-text.js';

const defaultCollapsedItemsLimit = 4;
const maxStringLength = 150;
const maxLinearStringLength = 50;
const defaultAllowedExcessStringLength = 10;
const defaultMaxStringLength = 150;
const defaultCompactStringLength = 40;
const defaultMaxCompactPropertyLength = 35;
function isValueExpandable(value) {
function intOption(value, defaultValue) {
if (typeof value === 'number' && isFinite(value) && value >= 1) {
return parseInt(value, 10);
}
return defaultValue;
}
function isValueExpandable(value, options) {
// array

@@ -33,3 +43,3 @@ if (Array.isArray(value)) {

// string
if (typeof value === 'string' && (value.length > maxStringLength || /[\r\n\f\t]/.test(value))) {
if (typeof value === 'string' && (value.length > options.maxStringLength || /[\r\n\f\t]/.test(value))) {
return true;

@@ -64,3 +74,4 @@ }

if (entries.length > 1) {
appendText(el.lastElementChild, entries.length + ' ' + unit);
el.lastElementChild
.innerHTML = numDelim(entries.length) + ' ' + unit;
}

@@ -100,3 +111,3 @@ }

// at this point we assume that a data is a string, an array or an object,
// at this point we assume data is a string, an array or an object,
// since only such types of data expandable

@@ -110,3 +121,3 @@ if (typeof data === 'string') {

appendText(stringValueEl.firstChild, text.slice(1, -1));
appendText(stringValueEl.previousSibling, `length: ${text.length} chars`);
stringValueEl.previousSibling.innerHTML = `length: ${numDelim(text.length)} chars`;

@@ -156,3 +167,3 @@ el.innerHTML = '';

function renderValue(container, value, autoExpandLimit, options, context) {
const expandable = isValueExpandable(value);
const expandable = isValueExpandable(value, options);
const valueEl = valueProtoEl.cloneNode(true);

@@ -214,2 +225,13 @@

function renderTable(el) {
let data = elementData.get(el);
if (!Array.isArray(data)) {
data = Object.entries(data).map(([key, value]) => ({ '[key]': key, '[value]': value }));
}
host.view.render(el, 'table', data, {});
el.append(el.lastChild.previousSibling);
}
function buildPathForElement(el) {

@@ -293,20 +315,36 @@ let path = [];

const maxAllowedSize = 1024 * 1024 * 1024;
const { minLength: compactSize, circular } = jsonStringifyInfo(data);
let jsonFormattedStringifyError = false;
let jsonCompactStringifyError = false;
let compactSize = 0;
let formattedSize = 0;
if (circular.length) {
jsonCompactStringifyError = 'Can\'t be copied: Converting circular structure to JSON';
jsonFormattedStringifyError = jsonCompactStringifyError;
} else if (compactSize > maxAllowedSize) {
jsonCompactStringifyError = 'Can\'t be copied: Resulting JSON is over 1 Gb';
jsonFormattedStringifyError = jsonCompactStringifyError;
} else {
formattedSize = jsonStringifyInfo(data, null, 4).minLength;
if (formattedSize > maxAllowedSize) {
jsonFormattedStringifyError = 'Can\'t be copied: Resulting JSON is over 1 Gb';
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) {

@@ -413,2 +451,3 @@ actions.push({

cursor.parentNode.classList.remove('struct-expanded-value');
cursor.classList.remove('view-as-table');

@@ -442,2 +481,18 @@ if (structViewRoots.has(cursor.parentNode)) {

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;
}

@@ -450,4 +505,13 @@ };

host.view.define('struct', function(el, config, data) {
const { expanded, limit, limitCollapsed, annotations } = config;
const expandable = isValueExpandable(data);
const {
expanded,
limit,
limitCollapsed,
annotations,
allowedExcessStringLength,
maxStringLength,
maxCompactStringLength,
maxCompactPropertyLength
} = config;
const options = {

@@ -457,4 +521,6 @@ limitCollapsed: host.view.listLimit(limitCollapsed, defaultCollapsedItemsLimit),

annotations: host.annotations.concat(annotations || []),
maxStringLength,
maxLinearStringLength
allowedExcessStringLength: intOption(allowedExcessStringLength, defaultAllowedExcessStringLength),
maxStringLength: intOption(maxStringLength, defaultMaxStringLength),
maxCompactStringLength: intOption(maxCompactStringLength, defaultCompactStringLength),
maxCompactPropertyLength: intOption(maxCompactPropertyLength, defaultMaxCompactPropertyLength)
};

@@ -471,3 +537,3 @@

if (expandable && !expanded) {
if (!expanded && isValueExpandable(data, options)) {
el.classList.add('struct-expand');

@@ -474,0 +540,0 @@ }

@@ -43,4 +43,20 @@ export default {

}
},
{
title: 'Setup maximum length for strings',
beforeDemo: ['md:"There 3 options to define limit for a string length:\\n* `maxStringLength` (default: 150) defines max length for strings in expanded values\\n* `maxCompactStringLength` (default: 40) defines max length for strings in collapsed objects and arrays\\n* `allowedExcessStringLength` (default: 10) defines allowed excess in length before a string will be cut and \\"N more\\" label will be added"'],
demo: {
view: 'struct',
expanded: 1,
maxStringLength: 30,
maxCompactStringLength: 10,
data: {
stringInExpandedObject: 'Quite a long string value Quite a long string value',
level2: {
stringInCollapsedObject: 'Quite a long string value Quite a long string value'
}
}
}
}
]
};

@@ -1,2 +0,2 @@

import { escapeHtml } from '../../core/utils/html.js';
import { escapeHtml, numDelim } from '../../core/utils/html.js';

@@ -10,6 +10,6 @@ const urlRx = /^(?:https?:)?\/\/(?:[a-z0-9]+(?:\.[a-z0-9]+)+|\d+(?:\.\d+){3})(?:\:\d+)?(?:\/\S*?)?$/i;

function more(num) {
return token('more', `…${num} more…`);
return token('more', `…${numDelim(num)} more…`);
}
export default function value2html(value, linear, options) {
export default function value2html(value, compact, options) {
switch (typeof value) {

@@ -21,12 +21,5 @@ case 'boolean':

case 'number':
case 'bigint': {
let str = String(value);
case 'bigint':
return token('number', numDelim(value));
if (str.length > 3) {
str = str.replace(/\..+$|\B(?=(\d{3})+(\D|$))/g, m => m || '<span class="num-delim"></span>');
}
return token('number', str);
}
case 'symbol':

@@ -39,5 +32,5 @@ return token('symbol', String(value));

case 'string': {
const maxLength = linear ? options.maxLinearStringLength : options.maxStringLength;
const maxLength = compact ? options.maxCompactStringLength : options.maxStringLength;
if (value.length > maxLength + 15) {
if (value.length > maxLength + options.allowedExcessStringLength) {
return token(

@@ -54,3 +47,3 @@ 'string',

'string',
!linear && (value[0] === 'h' || value[0] === '/') && urlRx.test(value)
!compact && (value[0] === 'h' || value[0] === '/') && urlRx.test(value)
? `"<a href="${escapeHtml(value)}" target="_blank">${escapeHtml(str.slice(1, -1))}</a>"`

@@ -87,3 +80,3 @@ : escapeHtml(str)

if (linear) {
if (compact) {
for (let key in value) {

@@ -105,3 +98,8 @@ if (hasOwnProperty.call(value, key)) {

if (count < limitCollapsed) {
content.push(`${token('property', key)}: ${value2html(value[key], true, options)}`);
const property = escapeHtml(key.length > options.maxCompactPropertyLength
? key.slice(0, options.maxCompactPropertyLength) + '…'
: key
);
content.push(`${token('property', property)}: ${value2html(value[key], true, options)}`);
}

@@ -108,0 +106,0 @@

/* eslint-env browser */
const defaultDetailsRender = { view: 'struct', expanded: 1 };
const hasOwnProperty = Object.hasOwnProperty;
function defaultCellRender(el, data) {
function defaultCellRender(el, data, isDataObject) {
if (Array.isArray(data)) {

@@ -12,7 +13,7 @@ el.classList.add('complex');

if (data && typeof data === 'object') {
if (isDataObject) {
el.classList.add('complex');
for (let k in data) {
if (Object.prototype.hasOwnProperty.call(data, k)) {
if (hasOwnProperty.call(data, k)) {
el.textContent = '{…}';

@@ -28,3 +29,2 @@ return;

if (data === undefined) {
el.textContent = '';
return;

@@ -47,3 +47,3 @@ }

el.textContent = data;
el.textContent = String(data);
}

@@ -53,4 +53,12 @@

host.view.define('table-cell', function(el, config, data, context) {
let { content, details } = config;
let { content, details, colSpan, scalarAsStruct } = config;
const isDataObject =
data !== null &&
typeof data === 'object' &&
data instanceof RegExp === false;
if (typeof colSpan === 'number' && colSpan > 1) {
el.colSpan = colSpan;
}
if (typeof content === 'function') {

@@ -66,3 +74,3 @@ content = content(data, context);

if (details || (!content && (data && typeof data === 'object'))) {
if (details || (!content && isDataObject)) {
el.classList.add('details');

@@ -113,7 +121,11 @@ el.addEventListener('click', (e) => {

if (scalarAsStruct && !content && !isDataObject) {
content = 'struct';
}
if (content) {
return host.view.render(el, content, data, context);
} else {
defaultCellRender(el, data);
}
defaultCellRender(el, data, isDataObject);
}, {

@@ -120,0 +132,0 @@ tag: 'td'

@@ -100,7 +100,10 @@ /* eslint-env browser */

function isScalar(value) {
return value === null || typeof value !== 'object' || value instanceof RegExp;
}
export default function(host) {
host.view.define('table', function(el, config, data, context) {
let { cols, rowConfig, limit } = config;
let colsMap = cols && typeof cols === 'object' ? cols : {};
let scalarCol = false;
let renderRowConfig;

@@ -114,4 +117,4 @@ if (!Array.isArray(data)) {

const bodyEl = el.appendChild(createElement('tbody'));
const moreEl = el
.appendChild(createElement('tbody'))
const moreEl = el.appendChild(createElement('tbody'));
const moreButtonsEl = moreEl
.appendChild(createElement('tr'))

@@ -122,3 +125,3 @@ .appendChild(createElement('td'));

bodyEl.innerHTML = '';
moreEl.innerHTML = '';
moreButtonsEl.innerHTML = '';

@@ -131,6 +134,11 @@ for (const headerCell of headerCells) {

return host.view.renderList(bodyEl, this.composeConfig({
view: 'table-row',
cols
}, rowConfig), orderedData, context, 0, host.view.listLimit(limit, 25), moreEl);
return host.view.renderList(
bodyEl,
renderRowConfig,
orderedData,
{ ...context, isScalar, cols },
0,
host.view.listLimit(limit, 25),
moreButtonsEl
).then(() => moreEl.hidden = !moreButtonsEl.firstChild);
};

@@ -150,17 +158,24 @@

const colNames = new Set();
const colsMap = cols && typeof cols === 'object' ? cols : {};
let scalarCol = false;
cols = [];
data
.forEach(item => {
if (item && typeof item === 'object') {
for (const key in item) {
colNames.add(key);
}
} else {
scalarCol = true;
for (const value of data) {
if (isScalar(value)) {
scalarCol = true;
} else {
for (const key of Object.keys(value)) {
colNames.add(key);
}
});
}
}
Object.keys(colsMap)
.forEach(name => colsMap[name] ? colNames.add(name) : colNames.delete(name));
for (const key of Object.keys(colsMap)) {
if (colsMap[key]) {
colNames.add(key);
} else {
colNames.delete(key);
}
}

@@ -171,7 +186,9 @@ if (scalarCol) {

view: 'table-cell',
data: String
sorting: '$ ascN',
scalarAsStruct: true,
colSpan: '=$isScalar:#.isScalar;$isScalar() ? #.cols.size() : 1'
});
}
colNames.forEach(name =>
for (const name of colNames) {
cols.push(

@@ -181,4 +198,4 @@ hasOwnProperty.call(colsMap, name)

: configFromName(name)
)
);
);
}
}

@@ -232,3 +249,8 @@

moreEl.colSpan = cols.length;
moreButtonsEl.colSpan = cols.length;
renderRowConfig = this.composeConfig({
view: 'table-row',
cols: '=$isScalar:#.isScalar;$isScalar() ? [#.cols[]] : #.cols'
}, rowConfig);
return render(data);

@@ -235,0 +257,0 @@ }, {

@@ -307,15 +307,18 @@ /* eslint-env browser */

if (key === 'view' || key === 'postRender' || key === 'className') {
throw new SyntaxError('[Discovery] Widget#queryToConfig(): set a value for "' + key + '" property via query is prohibited');
if (key === 'view' || key === 'postRender') {
throw new SyntaxError('[Discovery] Widget#queryToConfig(): set a value for "' + key + '" property in shorthand notation is prohibited');
}
// when / data / whenData properties take string values as a jora query
// that's why we don't need for a special processing
if (key === 'when' || key === 'data' || key === 'whenData') {
if (entry.value.type === 'Literal') {
config[key] = typeof entry.value.value === 'string'
? JSON.stringify(entry.value.value)
: entry.value.value;
} else {
config[key] = jora.syntax.stringify(entry.value);
}
// When value is a literal there is no need to compute them using a query,
// so add such values to the config as is. However, this doesn't work for string values
// since it will be treated as a query
config[key] = entry.value.type === 'Literal' && typeof entry.value.value !== 'string'
? entry.value.value
: jora.syntax.stringify(entry.value);
} else {
// We can use literal values as is excluding strings which start with '=',
// since it's an indicator that the string is a query
config[key] = entry.value.type === 'Literal' && (typeof entry.value.value !== 'string' || entry.value.value[0] !== '=')

@@ -326,2 +329,3 @@ ? entry.value.value

}
console.log(config);

@@ -328,0 +332,0 @@ return config;

@@ -12,2 +12,23 @@ const lastQuerySuggestionsStat = new WeakMap();

function stringifyValue(value, text) {
if (typeof value !== 'string') {
return String(value);
}
value = JSON.stringify(value);
if (text[0] !== "'") {
return value;
}
// convert "string" -> 'string'
// \" -> "
// ' -> \'
// \. -> \. (any other escaped char left as is)
return `'${value.slice(1, -1).replace(
/\\.|'/g,
m => m === '\\"' ? '"' : m === '\'' ? '\\\'' : m
)}'`;
}
function isSameSuggestions(api, pos1, pos2) {

@@ -25,4 +46,5 @@ if (pos1 === pos2) {

return ranges1.every((range1, idx) => {
const range2 = ranges2[idx];
for (let i = 0; i < ranges1.length; i++) {
const range1 = ranges1[i];
const range2 = ranges2[i];

@@ -34,5 +56,5 @@ for (const key of Object.keys(range1)) {

}
}
return true;
});
return true;
}

@@ -90,3 +112,3 @@

value: entry.type === 'value'
? (typeof value === 'string' ? JSON.stringify(value) : String(value))
? stringifyValue(value, entry.text)
: value

@@ -93,0 +115,0 @@ })));

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

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

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

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

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

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc