diff --git a/.changeset/brave-zebras-sing.md b/.changeset/brave-zebras-sing.md new file mode 100644 index 0000000..68bb203 --- /dev/null +++ b/.changeset/brave-zebras-sing.md @@ -0,0 +1,5 @@ +--- +"@hydrofoil/roadshow": patch +--- + +Ability to select multi-viewer to render multiple properties diff --git a/.changeset/nice-books-fetch.md b/.changeset/nice-books-fetch.md new file mode 100644 index 0000000..a46e206 --- /dev/null +++ b/.changeset/nice-books-fetch.md @@ -0,0 +1,5 @@ +--- +"@hydrofoil/roadshow": minor +--- + +Redesign the state and rendering process diff --git a/.gitignore b/.gitignore index 191b54c..d090c50 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ dist/ *.js *.d.ts *.map +coverage/ diff --git a/apps/storybook/lib/ns.ts b/apps/storybook/lib/ns.ts new file mode 100644 index 0000000..aac87b8 --- /dev/null +++ b/apps/storybook/lib/ns.ts @@ -0,0 +1,5 @@ +import namespace from '@rdf-esm/namespace' + +export const hex = namespace('https://w3id.org/hydra/extension#') +export const ex = namespace('https://example.com/') +export const wbo = namespace('https://wikibus.org/ontology#') diff --git a/apps/storybook/package.json b/apps/storybook/package.json index 36a6dc0..380f0bc 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -13,6 +13,7 @@ "@rdf-esm/dataset": "^0.5.1", "@rdf-esm/formats-common": "^0.5", "@rdf-esm/namespace": "^0.5", + "@rdf-esm/term-map": "^0.5.1", "@rdf-esm/term-set": "^0.5", "@rdfine/hydra": "^0.7.1", "@rdfine/schema": "^0.6.5", diff --git a/apps/storybook/resources/hydra-collection.ttl b/apps/storybook/resources/hydra-collection.ttl index 29793ab..7fc2c77 100644 --- a/apps/storybook/resources/hydra-collection.ttl +++ b/apps/storybook/resources/hydra-collection.ttl @@ -4,34 +4,37 @@ PREFIX rdfs: @prefix schema: . <> a hydra:Collection ; - hydra:member - [ - a schema:Person ; - schema:familyName "Doe" ; - schema:givenName "John" ; - schema:telephone "123456789" ; - schema:image [ - a schema:ImageObject ; - schema:contentUrl ; - schema:caption "John's profile image" ; - ] - ], [ - a schema:Person ; - schema:familyName "Doe" ; - schema:givenName "Jane" ; - schema:telephone "555666777" ; - schema:image - [ - a schema:ImageObject ; - schema:contentUrl ; - schema:caption "Jane's profile image" ; - ] - ] ; - hydra:manages - [ - hydra:property rdf:type ; - hydra:object schema:Person ; - ] ; + hydra:title "Addressbook"@en, "Książka adresowa"@pl ; + hydra:member + [ + a schema:Person ; + schema:familyName "Doe" ; + schema:givenName "John" ; + schema:telephone "123456789" ; + schema:image + [ + a schema:ImageObject ; + schema:contentUrl ; + schema:caption "John's profile image" ; + ] + ], + [ + a schema:Person ; + schema:familyName "Doe" ; + schema:givenName "Jane" ; + schema:telephone "555666777" ; + schema:image + [ + a schema:ImageObject ; + schema:contentUrl ; + schema:caption "Jane's profile image" ; + ] + ] ; + hydra:manages + [ + hydra:property rdf:type ; + hydra:object schema:Person ; + ] ; hydra:view [ a hydra:PartialCollectionView ; diff --git a/apps/storybook/shapes/hydra-PartialCollectionView.ttl b/apps/storybook/shapes/hydra-PartialCollectionView.ttl new file mode 100644 index 0000000..f5a1be2 --- /dev/null +++ b/apps/storybook/shapes/hydra-PartialCollectionView.ttl @@ -0,0 +1,25 @@ +PREFIX dash: +PREFIX hydra: +PREFIX sh: + +<> + a sh:NodeShape ; + sh:targetClass hydra:PartialCollectionView ; + sh:property + [ + sh:path hydra:first ; + sh:order 0 ; + ], + [ + sh:path hydra:previous ; + sh:order 1 ; + ], + [ + sh:path hydra:next ; + sh:order 2 ; + ], + [ + sh:path hydra:last ; + sh:order 3 ; + ] +. diff --git a/apps/storybook/shapes/hydra-collection.ttl b/apps/storybook/shapes/hydra-collection.ttl index 9e06c82..3836659 100644 --- a/apps/storybook/shapes/hydra-collection.ttl +++ b/apps/storybook/shapes/hydra-collection.ttl @@ -1,12 +1,24 @@ PREFIX dash: PREFIX hydra: PREFIX sh: +PREFIX hex: +prefix ex: <> sh:targetClass hydra:Collection ; sh:property + [ + sh:path hydra:title ; + sh:order 0 ; + dash:viewer ex:LocalLabelViewer ; + ], [ sh:path hydra:member ; - dash:viewer dash:HydraMemberViewer ; + dash:viewer hex:MembersViewer ; + sh:order 1 ; + ], + [ + sh:path hydra:view ; + sh:order 2 ; ] ; . diff --git a/apps/storybook/stories/HydraCollection.stories.ts b/apps/storybook/stories/HydraCollection.stories.ts index 83fbe96..94301ce 100644 --- a/apps/storybook/stories/HydraCollection.stories.ts +++ b/apps/storybook/stories/HydraCollection.stories.ts @@ -1,168 +1,19 @@ import { html } from 'lit' -import { MultiRenderer, Renderer, ViewerMatchInit } from '@hydrofoil/roadshow' +import { MultiRenderer, Renderer, ViewerMatcher } from '@hydrofoil/roadshow' import '@hydrofoil/roadshow/roadshow-view' -import { findNodes } from 'clownface-shacl-path' -import { hydra, sh, rdf, schema, dash, rdfs } from '@tpluscode/rdf-ns-builders' -import { fromPointer } from '@rdfine/shacl/lib/NodeShape' -import { NamedNode } from 'rdf-js' +import { hydra, rdf, schema } from '@tpluscode/rdf-ns-builders/strict' import type { MultiPointer } from 'clownface' -import type { Literal } from '@rdfjs/types' import { template } from '../lib/template' import addressBook, { QuadArrayFactory } from '../resources/hydra-collection.ttl' import hydraCollectionShape from '../shapes/hydra-collection.ttl' +import hydraPartialCollectionViewShape from '../shapes/hydra-PartialCollectionView.ttl' import schemaPerson from '../shapes/schema-person.ttl' import { runFactory } from '../resources/runFactory' - -const collectionViewer: ViewerMatchInit = { - viewer: dash.HydraCollectionViewer, - match({ resource }) { - return resource.has(rdf.type, hydra.Collection).terms.length ? 50 : 0 - }, -} - -const pagerViewer: ViewerMatchInit = { - viewer: dash.HydraPartialCollectionViewViewer, - match({ resource }) { - return resource.has(rdf.type, hydra.PartialCollectionView).terms.length ? 50 : 0 - }, -} - -const localizedLabelViewer: ViewerMatchInit = { - viewer: dash.LocalLabelViewer, - matchMulti({ state }) { - return state.path?.term?.equals(rdfs.label) ? 1 : 0 - }, -} - -const localizedLabel: MultiRenderer = { - viewer: dash.LocalLabelViewer, - render(resources: MultiPointer) { - const arr = resources.toArray() - const label = arr.find(r => r.term.language === this.params.language) || arr.find(r => r.term.language === 'en') - - return label ? html`${this.show({ property: rdfs.label, resource: label, viewer: dash.LiteralViewer })}` : '' - }, -} - -const tableView: Renderer = { - viewer: dash.HydraCollectionViewer, - render(collection, shape) { - const memberTypes = collection - .out(hydra.manages) - .has(hydra.property, rdf.type) - .out(hydra.object) - - const memberShape = this.shapes.shapes - .find(shape => shape.pointer.has(sh.targetClass, memberTypes).terms.length) - const memberPropertyShape = shape?.property.find(({ pointer }) => hydra.member.equals(pointer.out(sh.path).term)) - const viewPropertyShape = shape?.property.find(({ pointer }) => hydra.view.equals(pointer.out(sh.path).term)) - - return html` - - - ${memberShape?.property.filter(p => !p.hidden).map(prop => html``)} - - - - ${collection.out(hydra.member).map(resource => html`${this.show({ - resource, - shape: memberShape, - property: memberPropertyShape || hydra.member, - })}`)} - -
${prop.name}
- - ${collection.out(hydra.view).map(view => this.show({ - resource: view, - property: viewPropertyShape || hydra.view, - }))}` - }, -} - -const pagerView: Renderer = { - viewer: dash.HydraPartialCollectionViewViewer, - render(resource) { - const link = (property: NamedNode) => { - const page = resource.out(property).toArray()[0] - return !page - ? '' - : this.show({ - resource: page, - property, - viewer: dash.URIViewer, - }) - } - - return html`
- ${link(hydra.first)} - ${link(hydra.previous)} - ${link(hydra.next)} - ${link(hydra.last)} -
` - }, -} - -const tableRowView: Renderer = { - viewer: dash.HydraMemberViewer, - render(member, memberShape) { - return html` - ${memberShape?.property.filter(({ hidden }) => !hidden).map(property => html` - ${findNodes(member, property.pointer.out(sh.path)).map(resource => html` - ${this.show({ resource, shape: memberShape, property })} - `)} - `)} - ` - }, -} - -const galleryView: Renderer = { - viewer: dash.HydraCollectionViewer, - render(collection) { - const memberTypes = collection - .out(hydra.manages) - .has(hydra.property, rdf.type) - .out(hydra.object) - - const memberShape = this.shapes.shapes - .find(shape => shape.pointer.has(sh.targetClass, memberTypes).terms.length) - - return html`
- ${collection.out(hydra.member).map(resource => this.show({ - resource, - shape: memberShape, - property: hydra.member, - viewer: dash.HydraMemberViewer, - }))} -
` - }, -} - -const galleryMemberView: Renderer = { - viewer: dash.HydraMemberViewer, - render(member) { - const images = member.out(schema.image).toArray() - - return html`${images.map(image => html`
- ${this.show({ resource: image, property: schema.image })} -
`)}` - }, -} - -const imageViewer: ViewerMatchInit = { - viewer: dash.SchemaImageViewer, - match({ resource }) { - return resource.has(rdf.type, schema.ImageObject).terms.length ? 50 : 0 - }, -} - -const imageView: Renderer = { - viewer: dash.SchemaImageViewer, - render(image) { - return html`
- ${image.out(schema.caption).value || ''} -
` - }, -} +import { tableView } from '../viewers/hydra-MembersViewer/table' +import { galleryView } from '../viewers/hydra-MembersViewer/gallery' +import { localizedLabel } from '../viewers/ex-LocalLabelViewer' +import * as pagerViewer from '../viewers/hydra-PartialCollectionViewer' +import * as imageViewer from '../viewers/schema-ImageViewer' export default { title: 'Hydra Collection', @@ -170,38 +21,42 @@ export default { interface ViewStoryParams { resource: QuadArrayFactory - viewers: ViewerMatchInit[] - renderers: Array - language?: string + viewers: ViewerMatcher[] + renderers: Array | MultiRenderer> } -const Template = template(({ resource, viewers, renderers, ...params }) => { - const shapes = [ - hydraCollectionShape, - schemaPerson, - ].map(runFactory).map(p => fromPointer(p)) +async function selectShape(arg: MultiPointer) { + if (arg.has(rdf.type, hydra.Collection).terms.length) { + return [runFactory(hydraCollectionShape)] + } + if (arg.has(rdf.type, schema.Person).terms.length) { + return [runFactory(schemaPerson)] + } + if (arg.has(rdf.type, hydra.PartialCollectionView).terms.length) { + return [runFactory(hydraPartialCollectionViewShape)] + } + + return [] +} - return html` +const Template = template(({ resource, viewers, renderers }) => html` - ` -}) + `) export const AddressBookTable = Template.bind({}) AddressBookTable.args = { resource: addressBook, - viewers: [collectionViewer, pagerViewer, localizedLabelViewer], - renderers: [tableView, tableRowView, pagerView, localizedLabel], - language: '', + viewers: [pagerViewer.matcher], + renderers: [tableView, pagerViewer.renderer, localizedLabel], } export const ProfileGallery = Template.bind({}) ProfileGallery.args = { resource: addressBook, - viewers: [collectionViewer, imageViewer], - renderers: [galleryView, galleryMemberView, imageView], + viewers: [imageViewer.matcher, pagerViewer.matcher], + renderers: [galleryView, imageViewer.renderer, pagerViewer.renderer, localizedLabel], } diff --git a/apps/storybook/stories/Lazy.stories.ts b/apps/storybook/stories/Lazy.stories.ts index df1f445..6260210 100644 --- a/apps/storybook/stories/Lazy.stories.ts +++ b/apps/storybook/stories/Lazy.stories.ts @@ -1,61 +1,27 @@ import { html } from 'lit' -import { Renderer, ViewerMatchInit } from '@hydrofoil/roadshow' -import { findNodes } from 'clownface-shacl-path' -import { hydra, sh, rdf, dash } from '@tpluscode/rdf-ns-builders' +import { MultiRenderer, Renderer, ViewerMatcher } from '@hydrofoil/roadshow' +import { hydra, rdf } from '@tpluscode/rdf-ns-builders/strict' import { namedNode } from '@rdf-esm/data-model' import { ResourceLoader } from '@hydrofoil/roadshow/ResourcesController' -import clownface from 'clownface' -import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import clownface, { MultiPointer } from 'clownface' import { template } from '../lib/template' import hydraCollectionShape from '../shapes/hydra-collection.ttl' import wikibusBrochure from '../shapes/wikibus-Brochure.ttl' import { runFactory } from '../resources/runFactory' import brochures from '../resources/wikibus-brochures.trig' - -const collectionViewer: ViewerMatchInit = { - viewer: dash.HydraCollectionViewer, - match({ resource }) { - return resource.has(rdf.type, hydra.Collection).terms.length ? 50 : 0 - }, -} - -const tableView: Renderer = { - viewer: dash.HydraCollectionViewer, - render(collection) { - const memberTypes = collection - .out(hydra.manages) - .has(hydra.property, rdf.type) - .out(hydra.object) - - const memberShape = this.shapes.shapes - .find(shape => shape.pointer.has(sh.targetClass, memberTypes).terms.length) - - return html` - - - ${memberShape?.property.map(prop => html``)} - - - - ${collection.out(hydra.member).map(member => html` - ${memberShape?.property.filter(({ hidden }) => !hidden).map(property => html` - `)} - `)} - -
${prop.name}
- ${findNodes(member, property.pointer.out(sh.path).toArray()[0]).map(resource => html`${this.show({ resource, property })}`)} -
` - }, -} +import { wbo } from '../lib/ns' +import { tableView } from '../viewers/hydra-MembersViewer/table' +import { localizedLabel } from '../viewers/ex-LocalLabelViewer' +import * as pagerViewer from '../viewers/hydra-PartialCollectionViewer' export default { - title: 'Lazy loading', + title: 'Lazy loading resources', } interface ViewStoryParams { resource: string - viewers: ViewerMatchInit[] - renderers: Renderer[] + viewers: ViewerMatcher[] + renderers: Array | MultiRenderer> } const { dataset } = runFactory(brochures) @@ -68,25 +34,29 @@ const load: ResourceLoader = async (id) => { return clownface({ dataset, graph: id }).namedNode(id) } -const Template = template(({ resource, viewers, renderers }) => { - const shapes = [ - hydraCollectionShape, - wikibusBrochure, - ].map(runFactory).map(p => fromPointer(p)) +async function selectShape(arg: MultiPointer) { + if (arg.has(rdf.type, hydra.Collection).terms.length) { + return [runFactory(hydraCollectionShape)] + } + if (arg.has(rdf.type, wbo.Brochure).terms.length) { + return [runFactory(wikibusBrochure)] + } + + return [] +} - return html` +const Template = template(({ resource, viewers = [], renderers }) => html` - ` -}) + `) export const AddressBookTable = Template.bind({}) AddressBookTable.args = { resource: 'https://sources.wikibus.org/brochures', - viewers: [collectionViewer], - renderers: [tableView], + renderers: [tableView, localizedLabel, pagerViewer.renderer], + viewers: [pagerViewer.matcher], } diff --git a/apps/storybook/stories/LazyShapes.stories.ts b/apps/storybook/stories/LazyShapes.stories.ts index 40b93ce..0700544 100644 --- a/apps/storybook/stories/LazyShapes.stories.ts +++ b/apps/storybook/stories/LazyShapes.stories.ts @@ -1,130 +1,76 @@ import { html } from 'lit' -import { Renderer, ViewerMatchInit } from '@hydrofoil/roadshow' -import { findNodes } from 'clownface-shacl-path' -import { hydra, sh, rdf, dash } from '@tpluscode/rdf-ns-builders' +import { MultiRenderer, Renderer, ViewerMatcher } from '@hydrofoil/roadshow' +import { hydra, rdf } from '@tpluscode/rdf-ns-builders' import { ShapesLoader } from '@hydrofoil/roadshow/ShapesController' -import TermSet from '@rdf-esm/term-set' -import { namedNode } from '@rdf-esm/data-model' import type { GraphPointer } from 'clownface' import { ResourceLoader } from '@hydrofoil/roadshow/ResourcesController' -import clownface from 'clownface' -import { renderLoadingSlot } from '@hydrofoil/roadshow/lib/fallbackSlots' -import type { NodeShape } from '@rdfine/shacl' -import { ResourceViewState } from '@hydrofoil/roadshow/lib/state' +import TermMap from '@rdf-esm/term-map' +import type { Term } from '@rdfjs/types' import { template } from '../lib/template' import hydraCollectionShape from '../shapes/hydra-collection.ttl' import wikibusBrochure from '../shapes/wikibus-Brochure.ttl' import { runFactory } from '../resources/runFactory' import brochures from '../resources/wikibus-brochures.trig' - -const collectionViewer: ViewerMatchInit = { - viewer: dash.HydraCollectionViewer, - match({ resource }) { - return resource.has(rdf.type, hydra.Collection).terms.length ? 50 : 0 - }, -} - -declare module '@hydrofoil/roadshow' { - interface LocalState { - memberShape?: NodeShape - memberShapeLoading?: boolean - applicableMemberShapes?: NodeShape[] - } -} - -const tableView: Renderer = { - viewer: dash.HydraCollectionViewer, - render(collection) { - const { memberShape } = this.state.locals - if (!memberShape) { - const memberTypes = collection - .out(hydra.manages) - .has(hydra.property, rdf.type) - .out(hydra.object); - - (async () => { - if (this.state.locals.memberShapeLoading) return - - this.state.locals.memberShapeLoading = true - this.state.locals.applicableMemberShapes = await this.shapes.findApplicableShape({ class: memberTypes }); - [this.state.locals.memberShape] = this.state.locals.applicableMemberShapes - - this.state.locals.memberShapeLoading = false - this.requestUpdate() - })() - - return renderLoadingSlot() - } - - return html` - - - ${memberShape.property.map(prop => html``)} - - - - ${collection.out(hydra.member).map(member => html` - ${memberShape.property.filter(({ hidden }) => !hidden).map(property => html` - `)} - `)} - -
${prop.name}
- ${findNodes(member, property.pointer.out(sh.path).toArray()[0]).map(resource => html`${this.show({ resource, property })}`)} -
` - }, -} +import { ex, wbo } from '../lib/ns' +import { tableView } from '../viewers/hydra-MembersViewer/table' +import { localizedLabel } from '../viewers/ex-LocalLabelViewer' +import * as pagerViewer from '../viewers/hydra-PartialCollectionViewer' export default { - title: 'Loading shapes on demand', + title: 'Lazy loading shapes', } interface ViewStoryParams { resource: GraphPointer - viewers: ViewerMatchInit[] - renderers: Renderer[] + viewers: ViewerMatcher[] + renderers: Array | MultiRenderer> } -const load: ShapesLoader = async (applicableTo) => { - await new Promise((resolve) => { - setTimeout(resolve, Math.random() * 100 + 1000) - }) +const resourceCache = new TermMap() - if ('resource' in applicableTo) { - const { resource } = applicableTo +async function fakeCachedRequest(id: Term, representation: T) { + if (!resourceCache.has(id)) { + await new Promise((resolve) => { + setTimeout(resolve, Math.random() * 100 + 1000) + }) + } + + resourceCache.set(id, representation) + + return representation +} - if (resource.has(rdf.type, hydra.Collection).terms.length) { - return [runFactory(hydraCollectionShape)] - } - } else if ('_context' in applicableTo.class) { - if (new TermSet(applicableTo.class.terms).has(namedNode('https://wikibus.org/ontology#Brochure'))) { - return [runFactory(wikibusBrochure)] - } +const load: ShapesLoader = async (resource) => { + if (resource.has(rdf.type, hydra.Collection).terms.length) { + return [await fakeCachedRequest(ex.CollectionShape, runFactory(hydraCollectionShape))] + } if (resource.has(rdf.type, wbo.Brochure).terms.length) { + return [await fakeCachedRequest(ex.BrochureShape, runFactory(wikibusBrochure))] } return [] } -const { dataset } = runFactory(brochures) const loadResource: ResourceLoader = async (id) => { - await new Promise((resolve) => { - setTimeout(resolve, Math.random() * 100 + 1000) - }) + const graph = await fakeCachedRequest(id, runFactory(brochures)) - return clownface({ dataset, graph: id }).namedNode(id) + return graph.namedNode(id) } -const Template = template(({ resource, viewers, renderers }) => html` - -`) +const Template = template(({ resource, viewers = [], renderers }) => { + resourceCache.clear() + return html` + + ` +}) export const AddressBookTable = Template.bind({}) AddressBookTable.args = { resource: runFactory(brochures).namedNode('https://sources.wikibus.org/brochures'), - viewers: [collectionViewer], - renderers: [tableView], + renderers: [tableView, localizedLabel, pagerViewer.renderer], + viewers: [pagerViewer.matcher], } diff --git a/apps/storybook/viewers/ex-LocalLabelViewer.ts b/apps/storybook/viewers/ex-LocalLabelViewer.ts new file mode 100644 index 0000000..ed27908 --- /dev/null +++ b/apps/storybook/viewers/ex-LocalLabelViewer.ts @@ -0,0 +1,24 @@ +import { MultiPointer } from 'clownface' +import { MultiRenderer } from '@hydrofoil/roadshow/index' +import { isLiteral } from '@hydrofoil/roadshow/lib/clownface' +import { ViewersController } from '@hydrofoil/roadshow/ViewersController' +import { dash, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { ex } from '../lib/ns' + +ViewersController.viewerMeta + .node(ex.LocalLabelViewer) + .addOut(rdf.type, dash.MultiViewer) + +export const localizedLabel: MultiRenderer = { + viewer: ex.LocalLabelViewer, + render(resources: MultiPointer) { + const arr = resources.toArray().filter(isLiteral) + const label = arr.find(r => r.term.language === this.params.language) || arr.find(r => r.term.language === 'en') + + if (!label) { + return '' + } + + return this.object(label) + }, +} diff --git a/apps/storybook/viewers/hydra-MembersViewer/gallery.ts b/apps/storybook/viewers/hydra-MembersViewer/gallery.ts new file mode 100644 index 0000000..cff34dc --- /dev/null +++ b/apps/storybook/viewers/hydra-MembersViewer/gallery.ts @@ -0,0 +1,21 @@ +import { MultiRenderer } from '@hydrofoil/roadshow/index' +import { html } from 'lit' +import { schema } from '@tpluscode/rdf-ns-builders/strict' +import { FocusNodeViewContext } from '@hydrofoil/roadshow/lib/ViewContext/index' +import { PropertyState } from '@hydrofoil/roadshow/lib/state' +import { hex } from '../../lib/ns' + +function renderImage(this: FocusNodeViewContext, property: PropertyState) { + return this.show({ property }) +} + +function resource(this: FocusNodeViewContext) { + return html`${this.state.properties.filter(({ path }) => schema.image.equals(path.term)).map(renderImage.bind(this))}` +} + +export const galleryView: MultiRenderer = { + viewer: hex.MembersViewer, + render(members) { + return html`${members.map(member => this.object(member, { resource }))}` + }, +} diff --git a/apps/storybook/viewers/hydra-MembersViewer/table.ts b/apps/storybook/viewers/hydra-MembersViewer/table.ts new file mode 100644 index 0000000..c2e4534 --- /dev/null +++ b/apps/storybook/viewers/hydra-MembersViewer/table.ts @@ -0,0 +1,48 @@ +import { PropertyShape } from '@rdfine/shacl' +import { html } from 'lit' +import { GraphPointer } from 'clownface' +import { FocusNodeViewContext, PropertyViewContext } from '@hydrofoil/roadshow/lib/ViewContext/index' +import { MultiRenderer } from '@hydrofoil/roadshow/index' +import { ViewersController } from '@hydrofoil/roadshow/ViewersController' +import { dash, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { hex } from '../../lib/ns' + +ViewersController.viewerMeta + .node(hex.MembersViewer) + .addOut(rdf.type, dash.MultiViewer) + +function renderCell(this: FocusNodeViewContext, property: PropertyShape) { + return html`${this.show({ property })}` +} + +function renderResource(this: FocusNodeViewContext) { + const propertyShapes = this.state.shape?.property.filter(p => !p.hidden) || [] + + return html`${propertyShapes.map(renderCell.bind(this))}` +} + +function renderRow(this: PropertyViewContext, member: GraphPointer) { + return html`${this.object(member, { + resource: renderResource, + })}` +} + +export const tableView: MultiRenderer = { + viewer: hex.MembersViewer, + render(members) { + this.controller.shapes.loadShapes(this.state, members) + + const propertyShapes = this.state.shape?.property.filter(p => !p.hidden) || [] + + return html` + + + ${propertyShapes.map(prop => html``)} + + + + ${members.map(renderRow.bind(this))} + +
${prop.name}
` + }, +} diff --git a/apps/storybook/viewers/hydra-PartialCollectionViewer.ts b/apps/storybook/viewers/hydra-PartialCollectionViewer.ts new file mode 100644 index 0000000..6c2c11c --- /dev/null +++ b/apps/storybook/viewers/hydra-PartialCollectionViewer.ts @@ -0,0 +1,34 @@ +import { Renderer, ViewerMatcher } from '@hydrofoil/roadshow/index' +import { hydra, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { NamedNode } from 'rdf-js' +import { html } from 'lit' +import { FocusNodeViewContext } from '@hydrofoil/roadshow/lib/ViewContext' +import { hex } from '../lib/ns' + +export const matcher: ViewerMatcher = { + viewer: hex.PartialCollectionViewViewer, + match({ resource }) { + return resource.has(rdf.type, hydra.PartialCollectionView).terms.length ? 50 : 0 + }, +} + +export const renderer: Renderer = { + viewer: hex.PartialCollectionViewViewer, + render() { + const link = (predicate: NamedNode) => { + const property = this.state.properties.find(({ path }) => predicate.equals(path.term)) + if (property) { + return this.show({ property }) + } + + return '' + } + + return html`
+ ${link(hydra.first)} + ${link(hydra.previous)} + ${link(hydra.next)} + ${link(hydra.last)} +
` + }, +} diff --git a/apps/storybook/viewers/schema-ImageViewer.ts b/apps/storybook/viewers/schema-ImageViewer.ts new file mode 100644 index 0000000..d0ecedd --- /dev/null +++ b/apps/storybook/viewers/schema-ImageViewer.ts @@ -0,0 +1,20 @@ +import { Renderer, ViewerMatcher } from '@hydrofoil/roadshow/index' +import { rdf, schema } from '@tpluscode/rdf-ns-builders/strict' +import { html } from 'lit' +import { ex } from '../lib/ns' + +export const matcher: ViewerMatcher = { + viewer: ex.SchemaImageViewer, + match({ resource }) { + return resource.has(rdf.type, schema.ImageObject).terms.length ? 50 : 0 + }, +} + +export const renderer: Renderer = { + viewer: ex.SchemaImageViewer, + render(image) { + return html`
+ ${image.out(schema.caption).value || ''} +
` + }, +} diff --git a/package.json b/package.json index e7bd480..7de53f2 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Rendering app layouts using SHACL and lit-html", "scripts": { "lint": "eslint . --ext .ts --quiet --ignore-path .gitignore --ignore-path .eslintignore", + "test": "wtr", "postinstall": "husky install", "release": "changeset publish" }, @@ -14,6 +15,7 @@ "@tpluscode/eslint-config": "^0.1.1", "@typescript-eslint/eslint-plugin": "^4.15.1", "@typescript-eslint/parser": "^4.15.1", + "@web/test-runner": "^0.13.15", "eslint": "^7.12.0", "eslint-config-standard": "^15.0.0", "eslint-plugin-babel": "^5.3.1", diff --git a/packages/roadshow/RenderersController.ts b/packages/roadshow/RenderersController.ts index ca6267c..1184bf8 100644 --- a/packages/roadshow/RenderersController.ts +++ b/packages/roadshow/RenderersController.ts @@ -1,14 +1,14 @@ import { ReactiveController } from 'lit' -import { NamedNode } from '@rdfjs/types' +import { NamedNode, Term } from '@rdfjs/types' import TermMap from '@rdf-esm/term-map' -import type { GraphPointer } from 'clownface' -import { Renderer } from './index' +import { roadshow } from '@hydrofoil/vocabularies/builders' +import { Renderer, RenderFunc } from './index' import * as defaultRenderers from './renderers' +import { FocusNodeState, ObjectState, PropertyState } from './lib/state' export class RenderersController implements ReactiveController { - static readonly defaultRenderers: Array = Object.values(defaultRenderers) - - private renderers: Map = new Map() + static readonly defaultRenderers: Array> = Object.values(defaultRenderers) + private renderers: Map = new Map() constructor() { this.renderers = new TermMap() @@ -25,15 +25,26 @@ export class RenderersController implements ReactiveController { } } - get(viewer: NamedNode | undefined): Renderer['render'] { - return (viewer && (this.renderers.get(viewer)?.render || this.__renderWarning(viewer))) || this.__renderRaw - } + get(state: ObjectState | FocusNodeState | PropertyState | { viewer: NamedNode }): RenderFunc { + const renderer = this.renderers.get(roadshow.RendererNotFoundViewer)! + let { viewer } = state + if ('loading' in state) { + if (state.loading.size) { + viewer = roadshow.LoadingViewer + } + if (state.loadingFailed.size) { + viewer = roadshow.LoadingFailedViewer + } + } + + if (viewer) { + return (this.renderers.get(viewer) || renderer).render + } - private __renderWarning(viewer: NamedNode) { - return (): string => `No renderer found for ${viewer?.value}` + return renderer.render } - private __renderRaw(obj: GraphPointer): string { - return `No viewer found for ${obj.value}` + has(viewer: NamedNode): boolean { + return this.renderers.has(viewer) } } diff --git a/packages/roadshow/ResourcesController.ts b/packages/roadshow/ResourcesController.ts index 8246350..31c2a3c 100644 --- a/packages/roadshow/ResourcesController.ts +++ b/packages/roadshow/ResourcesController.ts @@ -1,51 +1,50 @@ -import { ReactiveController } from 'lit' import { NamedNode, Term } from '@rdfjs/types' import type { GraphPointer } from 'clownface' import TermMap from '@rdf-esm/term-map' import { RoadshowView } from './index' +import { FocusNodeState } from './lib/state' + +const LOADER_KEY = 'representation' export interface ResourceLoader { (term: NamedNode): Promise } -export class ResourcesController implements ReactiveController { +export class ResourcesController { private resources: Map - private _load?: ResourceLoader constructor(private host: RoadshowView) { this.resources = new TermMap() } - async hostConnected(): Promise { - this._load = this.host.resourceLoader - - let resource: GraphPointer - if (this.host.resource) { - resource = this.host.resource - this.resources.set(resource.term, resource) - } else if (this.host.resourceId) { - await this.load(this.host.resourceId) - } else { - return - } - - this.host.requestUpdate() - } - - async load(term: NamedNode) { - if (!this._load) { + async load(term: NamedNode): Promise | null | undefined> { + if (!this.host.resourceLoader) { throw new Error('Resource loader not set') } - const resource = await this._load(term) + const resource = await this.host.resourceLoader(term) if (resource) { this.resources.set(term, resource) } - return resource + return resource as any } - get(term: NamedNode): GraphPointer | undefined { - return this.resources.get(term) as any + async loadToState(state: FocusNodeState): Promise { + if (state.term.termType !== 'NamedNode' || typeof state.pointer !== 'undefined') { + return + } + + state.loading.add(LOADER_KEY) + await this.host.requestUpdate() + + const loaded = await this.load(state.term) + state.loading.delete(LOADER_KEY) + if (loaded) { + state.pointer = loaded + } else { + state.loadingFailed.add(LOADER_KEY) + } + await this.host.requestUpdate() } } diff --git a/packages/roadshow/RoadshowController.ts b/packages/roadshow/RoadshowController.ts index a0516a8..8d5eab7 100644 --- a/packages/roadshow/RoadshowController.ts +++ b/packages/roadshow/RoadshowController.ts @@ -1,103 +1,58 @@ import { ReactiveController } from 'lit' -import type { GraphPointer } from 'clownface' -import { NamedNode } from '@rdfjs/types' -import { dash } from '@tpluscode/rdf-ns-builders/strict' -import type { BlankNode } from 'rdf-js' -import { Renderer, RoadshowView } from './index' +import { dash, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { RoadshowView } from './index' +import { create, FocusNodeState } from './lib/state' import { RenderersController } from './RenderersController' -import { ViewersController, ViewerScore } from './ViewersController' +import { ViewersController } from './ViewersController' import { ShapesController } from './ShapesController' import { ResourcesController } from './ResourcesController' -import { ResourceViewState } from './lib/state' -import type { ViewContext } from './lib/ViewContext' -import RootContext from './lib/ViewContext/RootContext' -import * as fallback from './lib/fallbackSlots' -import { isResource } from './lib/clownface' export class RoadshowController implements ReactiveController { - private __render: Renderer['render'] | undefined - - rootContext: ViewContext | null = null + state: FocusNodeState + public shapes: ShapesController; constructor( public host: RoadshowView, public resources = new ResourcesController(host), public renderers = new RenderersController(), public viewers = new ViewersController(host), - public shapes = new ShapesController(host), + shapes?: ShapesController, ) { - this.host.addController(renderers) - this.host.addController(viewers) - this.host.addController(shapes) - this.host.addController(resources) this.host.addController(this) + + this.shapes = shapes || new ShapesController(host, resources) + this.state = create({ + term: rdf.nil, + }) } - // eslint-disable-next-line @typescript-eslint/no-empty-function hostConnected(): void { + this.refreshRenderers() } - async prepareViewState(): Promise { - const { resourceId } = this.host - let resource: GraphPointer | undefined | null - if (this.host.resource) { - resource = this.host.resource - } else if (resourceId) { - const loaded = await this.resources.load?.(resourceId) - if (isResource(loaded)) { - resource = loaded - } - } - - if (!resource) { - this.rootContext = null - return this.host.requestUpdate() - } - - let applicableViewers: ViewerScore[] = [] - let viewer: GraphPointer | undefined - const applicableShapes = await this.shapes.findApplicableShape({ resource }) - const [shape] = applicableShapes - - if (shape) { - applicableViewers = this.viewers.findApplicableViewers({ object: resource }) - applicableViewers = [...applicableViewers, { pointer: this.viewers.get(dash.DetailsViewer), score: null }] - const [dashViewer] = shape.pointer.out(dash.viewer).toArray() - if (dashViewer) { - applicableViewers.unshift({ - pointer: dashViewer as any, - score: null, - }) - } - viewer = applicableViewers[0]?.pointer - this.__render = this.renderers.get(viewer.term) + async initState(): Promise { + if (this.host.resourceId && !this.host.resource) { + this.state = create({ + term: this.host.resourceId, + }) + await this.resources.loadToState(this.state) + } else if (this.host.resource) { + const shape = await this.shapes.loadDashShape(this.host.resource) + this.state = create({ + shape, + term: this.host.resource.term, + }) + this.state.pointer = this.host.resource + await this.host.requestUpdate() + } else { + return } - this.rootContext = new RootContext(this, { - pointer: resource, - applicableShapes, - shape, - properties: {}, - applicableViewers, - viewer, - locals: {}, - }) - - return this.host.requestUpdate() - } - - render(): unknown { - if (!this.rootContext?.state.pointer) { - return fallback.renderLoadingSlot() - } - if (!this.rootContext?.state.shape) { - return fallback.renderNoShapeSlot() - } - if (!this.__render) { - return fallback.renderNoRendererSlot() - } + await this.shapes.loadShapes(this.state, this.state.pointer!) - return this.__render.call(this.rootContext, this.rootContext.state.pointer, this.rootContext.state.shape) + await this.host.requestUpdate() + this.state.viewer = dash.DetailsViewer + await this.host.requestUpdate() } refreshRenderers(): void { diff --git a/packages/roadshow/ShapesController.ts b/packages/roadshow/ShapesController.ts index 2771caa..0e41f81 100644 --- a/packages/roadshow/ShapesController.ts +++ b/packages/roadshow/ShapesController.ts @@ -1,54 +1,76 @@ import { ReactiveController } from 'lit' -import { NodeShape } from '@rdfine/shacl' import type { GraphPointer, MultiPointer } from 'clownface' -import { NamedNode, Term } from '@rdfjs/types' import { fromPointer } from '@rdfine/shacl/lib/NodeShape' -import { RoadshowView } from './index' -import { suitableShape } from './lib/shape' +import { BlankNode, NamedNode } from '@rdfjs/types' +import { dash, sh } from '@tpluscode/rdf-ns-builders/strict' +import type { RoadshowView } from './index' +import { createPropertyState, FocusNodeState, PropertyState } from './lib/state' +import { isResource } from './lib/clownface' +import { ResourcesController } from './ResourcesController' -interface FindShapeForResource { - resource: GraphPointer -} - -interface FindShapeForClass { - class: MultiPointer | NamedNode -} - -type FindShape = FindShapeForResource | FindShapeForClass +const LOADER_KEY = 'shapes' export interface ShapesLoader { - (arg: FindShape): Promise> -} - -function isUriResource(arg: FindShape): arg is (FindShapeForResource | FindShapeForClass) { - return 'class' in arg || ('resource' in arg && arg.resource.term.termType === 'NamedNode') + (arg: MultiPointer): Promise>> } export class ShapesController implements ReactiveController { - shapes: NodeShape[] = [] - private _load?: ShapesLoader - - constructor(private host: RoadshowView) { + constructor(private host: RoadshowView, private resources: ResourcesController) { + host.addController(this) } hostConnected(): void { - this.shapes = this.host.shapes - this._load = this.host.shapesLoader + // } - async findApplicableShape(applicableTo: FindShape): Promise { - if (this._load && isUriResource(applicableTo)) { - const pointers = await this._load(applicableTo) + async loadShapes(state: FocusNodeState | PropertyState, focusNode: MultiPointer): Promise { + const { shapesLoader } = this.host + if (!shapesLoader || state.shapesLoaded) { + return + } - if (pointers.length) { - return pointers.map((ptr: any) => fromPointer(ptr)) - } + state.shapesLoaded = true + state.loading.add(LOADER_KEY) + + const loadShapes = () => shapesLoader(focusNode) + if (!state.shape) { + await this.host.requestUpdate() + + const shapePointers = await loadShapes() + + state.applicableShapes = shapePointers.map(ptr => fromPointer(ptr)); + [state.shape] = state.applicableShapes + } else { + const shapePointers = await loadShapes() + state.applicableShapes = [ + state.shape, + ...shapePointers.map(ptr => fromPointer(ptr)).filter(found => !found.equals(state.shape)), + ] + } + if ('properties' in state) { + state.properties = state.shape?.property.reduce(createPropertyState, []) || [] } - if ('resource' in applicableTo) { - return this.shapes.filter(suitableShape(applicableTo.resource)) + state.loading.delete(LOADER_KEY) + await this.host.requestUpdate() + } + + async loadDashShape(resource: GraphPointer) { + const [dashShape] = resource.out(dash.shape).toArray().filter(isResource) + + if (dashShape) { + if (dashShape.out(sh.property).terms.length) { + return fromPointer(dashShape) + } + + if (dashShape.term.termType === 'NamedNode') { + const loaded = await this.resources.load(dashShape.term) + if (loaded) { + return fromPointer(loaded) + } + } } - return [] + return undefined } } diff --git a/packages/roadshow/ViewersController.ts b/packages/roadshow/ViewersController.ts index 0b5c7dd..4a40b88 100644 --- a/packages/roadshow/ViewersController.ts +++ b/packages/roadshow/ViewersController.ts @@ -1,18 +1,13 @@ import { ReactiveController } from 'lit' -import type { GraphPointer, MultiPointer } from 'clownface' +import clownface, { AnyPointer, GraphPointer } from 'clownface' import TermMap from '@rdf-esm/term-map' import { NamedNode, Term } from '@rdfjs/types' -import clownface, { AnyPointer } from 'clownface' -import { dataset } from '@rdf-esm/dataset' -import { RoadshowView, Viewer, ViewerMatchInit } from './index' +import * as $rdf from '@rdf-esm/dataset' +import Dash from '@zazuko/rdf-vocabularies/datasets/dash' +import { dash, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { RoadshowView, Viewer, ViewerMatcher } from './index' import * as defaultViewers from './viewers' -import { isGraphPointer } from './lib/clownface' -import { PropertyViewState } from './lib/state' - -export interface ViewerScore { - pointer: GraphPointer - score: number | null -} +import { ViewerScore } from './lib/state' function suitableViewers(resource: GraphPointer) { return (matched: ViewerScore[], { pointer, match }: Viewer): ViewerScore[] => { @@ -28,55 +23,29 @@ function suitableViewers(resource: GraphPointer) { } } -function suitableMultiViewers(resources: MultiPointer, state: PropertyViewState) { - return (matched: ViewerScore[], { pointer, matchMulti }: Viewer): ViewerScore[] => { - const score = matchMulti?.({ resources, state }) || 0 - if (score === 0) { - return matched - } - - return [...matched, { - pointer, - score, - }] - } -} - function byScore(left: ViewerScore, right: ViewerScore) { return (right.score || -1) - (left.score || -1) } -interface FindSingleViewers { - object: GraphPointer - state?: never -} - -interface FindMultiViewers { - object: MultiPointer - state: PropertyViewState -} - -type FindApplicableViewers = FindSingleViewers | FindMultiViewers - export class ViewersController implements ReactiveController { - static readonly defaultViewers: Array = Object.values(defaultViewers) - static readonly viewerMeta: AnyPointer = clownface({ dataset: dataset() }) + static readonly defaultViewers: Array = Object.values(defaultViewers) + static readonly viewerMeta: AnyPointer = clownface({ dataset: $rdf.dataset(Dash($rdf)) }) viewers: Map constructor(private host: RoadshowView) { this.viewers = new TermMap() + host.addController(this) } hostConnected(): void { const mapInit = [ ...ViewersController.defaultViewers, ...this.host.viewers, - ].map<[NamedNode, Viewer]>(({ viewer, match, matchMulti }) => { + ].map<[NamedNode, Viewer]>(({ viewer, match }) => { const impl = { pointer: ViewersController.viewerMeta.node(viewer), match, - matchMulti, } return [viewer, impl] }) @@ -84,15 +53,9 @@ export class ViewersController implements ReactiveController { this.viewers = new TermMap(mapInit) } - findApplicableViewers({ object, state }: FindApplicableViewers): ViewerScore[] { - if (isGraphPointer(object)) { - return [...this.viewers.values()] - .reduce(suitableViewers(object), []) - .sort(byScore) - } - + findApplicableViewers(object: GraphPointer): ViewerScore[] { return [...this.viewers.values()] - .reduce(suitableMultiViewers(object, state!), []) + .reduce(suitableViewers(object), []) .sort(byScore) } @@ -103,4 +66,8 @@ export class ViewersController implements ReactiveController { return ViewersController.viewerMeta.node(viewer) } + + isMultiViewer(viewer: Term): boolean { + return ViewersController.viewerMeta.node(viewer).has(rdf.type, dash.MultiViewer).terms.length > 0 + } } diff --git a/packages/roadshow/index.ts b/packages/roadshow/index.ts index 2018956..8f55d0f 100644 --- a/packages/roadshow/index.ts +++ b/packages/roadshow/index.ts @@ -1,58 +1,37 @@ import type { ReactiveControllerHost, TemplateResult } from 'lit' import type { GraphPointer, MultiPointer } from 'clownface' import type { BlankNode, NamedNode, Term } from '@rdfjs/types' -import type { NodeShape, PropertyShape } from '@rdfine/shacl' import type { ShapesLoader } from './ShapesController' import type { ResourceLoader } from './ResourcesController' -import type { PropertyViewState, ViewState } from './lib/state' -import type { ViewContext } from './lib/ViewContext' +import type { PropertyViewContext, ViewContext } from './lib/ViewContext' export { html, css } from 'lit' -export type { LocalState } from './lib/state' -export interface Show { - resource: MultiPointer - shape?: NodeShape - property: PropertyShape | NamedNode - viewer?: Term +export interface RenderFunc> { + (this: S, resource: MultiPointer): TemplateResult | string } -export interface InitRenderer { - viewer?: Term - shape?: NodeShape - property: PropertyShape | NamedNode +export interface Renderer = ViewContext> { + viewer: Term + render: RenderFunc } -export interface Renderer { - viewer: NamedNode - render(this: ViewContext, resource: GraphPointer, shape?: NodeShape): TemplateResult | string -} +export type MultiRenderer = Renderer -export interface MultiRenderer { - viewer: NamedNode - render(this: ViewContext, resources: MultiPointer): TemplateResult | string -} - -export interface ViewerMatch { +export interface ViewerMatchFunc { (arg: { resource: GraphPointer }): number | null } -export interface MultiViewerMatch { - (arg: { resources: MultiPointer; state: PropertyViewState }): number | null -} - -export interface ViewerMatchInit { +export interface ViewerMatcher { viewer: NamedNode - match?: ViewerMatch - matchMulti?: MultiViewerMatch + match: ViewerMatchFunc } export interface RoadshowView extends ReactiveControllerHost { resource: GraphPointer | undefined resourceId: NamedNode | undefined - shapes: NodeShape[] renderers: Renderer[] - viewers: ViewerMatchInit[] + viewers: ViewerMatcher[] resourceLoader?: ResourceLoader shapesLoader?: ShapesLoader params: any @@ -60,6 +39,5 @@ export interface RoadshowView extends ReactiveControllerHost { export interface Viewer { pointer: GraphPointer - match?: ViewerMatch - matchMulti?: MultiViewerMatch + match: ViewerMatchFunc } diff --git a/packages/roadshow/lib/ViewContext/LiteralViewContext.ts b/packages/roadshow/lib/ViewContext/LiteralViewContext.ts deleted file mode 100644 index 0c04d60..0000000 --- a/packages/roadshow/lib/ViewContext/LiteralViewContext.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { GraphPointer } from 'clownface' -import { Literal } from '@rdfjs/types' -import ViewContextBase from './ViewContextBase' -import { LiteralViewState } from '../state' - -export default class LiteralViewContext extends ViewContextBase { - initState(pointer: GraphPointer): LiteralViewState { - return { - pointer, - applicableViewers: [], - locals: {}, - } - } - - show() { - throw new Error('Literal view cannot have children') - } -} diff --git a/packages/roadshow/lib/ViewContext/PropertyViewContext.ts b/packages/roadshow/lib/ViewContext/PropertyViewContext.ts deleted file mode 100644 index 55d7f0c..0000000 --- a/packages/roadshow/lib/ViewContext/PropertyViewContext.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { MultiPointer } from 'clownface' -import { GraphPointer } from 'clownface' -import { findNodes } from 'clownface-shacl-path' -import ViewContextBase from './ViewContextBase' -import { ResourceViewState, PropertyViewState } from '../state' -import { InitRenderer, Show } from '../../index' -import { isGraphPointer } from '../clownface' - -export default class PropertyViewContext extends ViewContextBase { - initState(): PropertyViewState { - return { - pointer: null as never, - applicableViewers: [], - objects: {}, - locals: {}, - } - } - - show({ resource, viewer, property, shape }: Show): unknown { - if (!('termType' in property)) { - this.state.shape = property - } - - if (!isGraphPointer(resource)) { - return this.parent.show({ resource, viewer, property, shape }) - } - - let objectState = this.state.objects[resource.term.value] - - if (objectState?.render) { - return objectState.render() - } - - if (!objectState) { - const childContext = this.create(this, resource) - objectState = childContext.state - this.state.objects[resource.term.value] = objectState - } - - if (!objectState.render) { - const childContext = this.create(this, resource, objectState) - objectState = childContext.state - - childContext.initRenderer({ - viewer: this.state.shape?.viewer?.id || viewer, - property, - shape, - }) - } - - return objectState.render!() - } - - initRenderer({ viewer, shape, property }: InitRenderer): void { - const resource = findNodes(this.parent.state.pointer, this.state.path!) - - if (!isGraphPointer(resource)) { - if (!this.state.render) { - this.state.applicableViewers = this.viewers.findApplicableViewers({ object: resource, state: this.state }) - this.state.viewer = this.state.applicableViewers[0]?.pointer - - if (this.state.viewer) { - this.state.render = () => { - const render: any = this.renderers.get(this.state.viewer?.term) - return render.call(this, resource) - } - } - } - } - } - - findApplicableViewers(object: GraphPointer) { - return this.viewers.findApplicableViewers({ object, state: this.state }) - } -} diff --git a/packages/roadshow/lib/ViewContext/ResourceViewContext.ts b/packages/roadshow/lib/ViewContext/ResourceViewContext.ts deleted file mode 100644 index c8a63db..0000000 --- a/packages/roadshow/lib/ViewContext/ResourceViewContext.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { GraphPointer, MultiPointer } from 'clownface' -import { NamedNode } from 'rdf-js' -import { roadshow } from '@hydrofoil/vocabularies/builders/strict' -import { PropertyShape } from '@rdfine/shacl' -import { sh } from '@tpluscode/rdf-ns-builders/strict' -import ViewContextBase from './ViewContextBase' -import { ResourceViewState, PropertyViewState } from '../state' -import { InitRenderer, Show } from '../../index' -import { isGraphPointer, TRUE } from '../clownface' -import PropertyViewContext from './PropertyViewContext' -import { renderLoadingSlot } from '../fallbackSlots' - -export default class ResourceViewContext extends ViewContextBase { - initState(pointer: GraphPointer): ResourceViewState { - return { - pointer, - properties: {}, - applicableShapes: [], - applicableViewers: [], - locals: {}, - } - } - - show({ property, resource, viewer, shape }: Show): unknown { - if (isGraphPointer(resource)) { - return this.parent.show({ property, resource, viewer, shape }) - } - - let propertyKey: string | undefined - let propertyShape: PropertyShape | undefined - let path: MultiPointer | undefined - if ('termType' in property) { - propertyKey = property.value; - [path] = resource.node(property).toArray() - } else { - path = property.pointer.out(sh.path) - propertyKey = path?.value - propertyShape = property - } - if (!propertyKey) { - throw new Error('Missing property path term') - } - - let propertyState = this.state.properties[propertyKey] - if (!propertyState) { - const context = new PropertyViewContext(this, resource, propertyState || { path }) - propertyState = context.state - this.state.properties[propertyKey] = propertyState - context.initRenderer({ - viewer: propertyShape?.viewer?.id || viewer, - shape, - property, - }) - } - - return propertyState!.render!() - } - - initRenderer(overrides: InitRenderer) { - const resource = this.state.pointer - let propertyShape: PropertyShape | undefined - if ('id' in overrides.property) { - propertyShape = overrides.property - } - - if (!(propertyShape?.pointer.out(roadshow.dereference).term?.equals(TRUE) && resource.term.termType === 'NamedNode')) { - super.initRenderer(overrides) - return - } - - const objectState = this.state - const previouslyLoaded = this.resources.get(resource.term) - if (previouslyLoaded) { - objectState.pointer = previouslyLoaded - super.initRenderer(overrides) - return - } - - objectState.render = renderLoadingSlot - this.resources.load?.(resource.term).then((loaded) => { - if (loaded) { - delete objectState.render - this.requestUpdate() - } - }) - } -} diff --git a/packages/roadshow/lib/ViewContext/RootContext.ts b/packages/roadshow/lib/ViewContext/RootContext.ts deleted file mode 100644 index e2520c1..0000000 --- a/packages/roadshow/lib/ViewContext/RootContext.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { PropertyShape } from '@rdfine/shacl' -import { sh } from '@tpluscode/rdf-ns-builders/strict' -import type { GraphPointer, MultiPointer } from 'clownface' -import { Show } from '../../index' -import { ResourceViewState } from '../state' -import type { RoadshowController } from '../../RoadshowController' -import { ShapesController } from '../../ShapesController' -import { ViewersController } from '../../ViewersController' -import { RenderersController } from '../../RenderersController' -import { ResourcesController } from '../../ResourcesController' -import { ViewContext } from './index' -import PropertyViewContext from './PropertyViewContext' -import factory, { Factory } from './factory' -import LiteralViewContext from './LiteralViewContext' -import ResourceViewContext from './ResourceViewContext' - -export default class implements ViewContext { - shapes: ShapesController - viewers: ViewersController - renderers: RenderersController - resources: ResourcesController - - readonly locals = {} - requestUpdate: OmitThisParameter<() => void>; - readonly create: Factory - - constructor(private controller: RoadshowController, public state: ResourceViewState) { - this.shapes = controller.shapes - this.viewers = controller.viewers - this.renderers = controller.renderers - this.resources = controller.resources - this.requestUpdate = controller.host.requestUpdate.bind(controller.host) - this.locals = {} - this.create = factory({ - LiteralViewContext, - ResourceViewContext, - }) - } - - get depth(): number { - return 0 - } - - get params() { - return this.controller.host.params - } - - show({ resource, property, shape, viewer }: Show): unknown { - let propertyKey: string | undefined - let propertyShape: PropertyShape | undefined - let path: MultiPointer | undefined - if ('termType' in property) { - propertyKey = property.value; - [path] = resource.node(property).toArray() - } else { - path = property.pointer.out(sh.path) - propertyKey = path?.value - propertyShape = property - } - if (!propertyKey) { - throw new Error('Missing property path term') - } - - let propertyState = this.state.properties[propertyKey] - const context = new PropertyViewContext(this, resource, propertyState || { path }) - if (!propertyState) { - propertyState = context.state - this.state.properties[propertyKey] = propertyState - context.initRenderer({ - viewer: propertyShape?.viewer?.id || viewer, - shape, - property, - }) - - if (!propertyState.render) { - return context.show({ resource, property, shape, viewer }) - } - } - - return propertyState.render?.() || context.show({ resource, property, shape, viewer }) - } - - findApplicableViewers(object: GraphPointer) { - return this.viewers.findApplicableViewers({ object }) - } - - initRenderer() { - throw new Error('Unsupported') - } -} diff --git a/packages/roadshow/lib/ViewContext/ViewContextBase.ts b/packages/roadshow/lib/ViewContext/ViewContextBase.ts deleted file mode 100644 index b269b82..0000000 --- a/packages/roadshow/lib/ViewContext/ViewContextBase.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { GraphPointer, MultiPointer } from 'clownface' -import type { InitRenderer, Show } from '../../index' -import type { ShapesController } from '../../ShapesController' -import type { ViewersController } from '../../ViewersController' -import type { RenderersController } from '../../RenderersController' -import type { ResourcesController } from '../../ResourcesController' -import type { CoreState } from '../state' -import type { ViewContext } from './index' - -export default abstract class ViewContextBase implements ViewContext { - shapes: ShapesController - viewers: ViewersController - renderers: RenderersController - resources: ResourcesController - state: T - - constructor(public parent: ViewContext, pointer: R, state: Partial = {}) { - this.shapes = parent.shapes - this.viewers = parent.viewers - this.renderers = parent.renderers - this.resources = parent.resources - this.state = { ...this.initState(pointer), ...state } - } - - show(params: Show): unknown { - return this.parent.show(params) - } - - abstract initState(pointer: R): T - - get depth(): number { - return this.parent.depth + 1 - } - - get params(): unknown { - return this.parent.params - } - - requestUpdate(): void { - this.parent.requestUpdate() - } - - initRenderer({ viewer, shape }: InitRenderer): void { - const objectState = this.state - - objectState.applicableViewers = this.viewers.findApplicableViewers({ object: objectState.pointer }) - if (viewer) { - objectState.applicableViewers.unshift({ - pointer: this.viewers.get(viewer), score: null, - }) - } - - objectState.viewer = objectState.applicableViewers[0]?.pointer - const renderer = this.renderers.get(objectState.viewer.term) - objectState.render = () => renderer.call(this as any, objectState.pointer, shape) - } - - findApplicableViewers(object: GraphPointer) { - return this.parent.findApplicableViewers(object) - } - - create(parent: ViewContext, pointer: GraphPointer, state?: any): ViewContext { - return this.parent.create(parent, pointer, state) - } -} diff --git a/packages/roadshow/lib/ViewContext/factory.ts b/packages/roadshow/lib/ViewContext/factory.ts deleted file mode 100644 index a04cc14..0000000 --- a/packages/roadshow/lib/ViewContext/factory.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { GraphPointer } from 'clownface' -import { isLiteral, isResource } from '../clownface' -import { ViewContext } from './index' -import { LiteralViewState, ResourceViewState } from '../state' - -interface ViewStateConstructor { - new(parent: ViewContext, pointer: GraphPointer, state?: any): ViewContext -} - -interface FactoryInit { - LiteralViewContext: ViewStateConstructor - ResourceViewContext: ViewStateConstructor -} - -export interface Factory { - (parent: ViewContext, pointer: GraphPointer, state?: any): ViewContext -} - -export default function factory({ LiteralViewContext, ResourceViewContext }: FactoryInit): Factory { - return function create(parent: ViewContext, pointer: GraphPointer, state?: any): ViewContext { - if (isLiteral(pointer)) { - return new LiteralViewContext(parent, pointer, state) - } - - if (isResource(pointer)) { - return new ResourceViewContext(parent, pointer, state) - } - - throw new Error(`Cannot create view context for ${pointer.term.termType}`) - } -} diff --git a/packages/roadshow/lib/ViewContext/index.ts b/packages/roadshow/lib/ViewContext/index.ts index 388296c..bd921c9 100644 --- a/packages/roadshow/lib/ViewContext/index.ts +++ b/packages/roadshow/lib/ViewContext/index.ts @@ -1,22 +1,38 @@ -import { GraphPointer } from 'clownface' -import type { ShapesController } from '../../ShapesController' -import type { ViewersController, ViewerScore } from '../../ViewersController' -import type { RenderersController } from '../../RenderersController' -import type { ResourcesController } from '../../ResourcesController' -import type { InitRenderer, LocalState, Show } from '../../index' +/* eslint-disable @typescript-eslint/no-empty-interface */ +import type { GraphPointer, MultiPointer } from 'clownface' +import { TemplateResult } from 'lit' +import { PropertyShape } from '@rdfine/shacl' +import { NamedNode } from '@rdfjs/types' +import type { RoadshowController } from '../../RoadshowController' +import type { FocusNodeState, ObjectState, PropertyState } from '../state' -export interface ViewContext { +export interface Params extends Record { + language: string +} + +export interface ViewContext { depth: number - parent?: ViewContext - state: S & { locals: LocalState } - params: T - shapes: ShapesController - viewers: ViewersController - renderers: RenderersController - resources: ResourcesController - initRenderer(overrides: InitRenderer): void + node: MultiPointer + state: S + params: Params + controller: RoadshowController +} + +export interface Show { + property: PropertyState | PropertyShape | NamedNode +} + +export interface FocusNodeViewContext extends ViewContext { show(params: Show): unknown - requestUpdate(): void - findApplicableViewers(ptr: GraphPointer): ViewerScore[] - create(parent: ViewContext, pointer: GraphPointer, state?: any): ViewContext +} + +export interface PropertyViewContext extends ViewContext { + object(object: GraphPointer, render?: { + literal?(this: ViewContext, content: TemplateResult | string): TemplateResult | string + resource?(this: FocusNodeViewContext): TemplateResult | string + }): TemplateResult | string +} + +export interface ObjectViewContext extends ViewContext { + } diff --git a/packages/roadshow/lib/fallbackSlots.ts b/packages/roadshow/lib/fallbackSlots.ts deleted file mode 100644 index bfe8dcc..0000000 --- a/packages/roadshow/lib/fallbackSlots.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { html } from 'lit' - -export function renderNoShapeSlot() { - return html`No applicable shape found...` -} - -export function renderLoadingSlot() { - return html`Loading...` -} - -export function renderNoRendererSlot() { - return html`No renderer!` -} diff --git a/packages/roadshow/lib/rdfine.ts b/packages/roadshow/lib/rdfine.ts new file mode 100644 index 0000000..f01d6f1 --- /dev/null +++ b/packages/roadshow/lib/rdfine.ts @@ -0,0 +1,6 @@ +import RdfResource from '@tpluscode/rdfine' +import { NodeShapeBundle, PropertyShapeBundle } from '@rdfine/shacl/bundles' +import { NodeShapeMixinEx, PropertyShapeMixinEx } from '@rdfine/dash/extensions/sh' + +RdfResource.factory.addMixin(...NodeShapeBundle, ...PropertyShapeBundle) +RdfResource.factory.addMixin(NodeShapeMixinEx, PropertyShapeMixinEx) diff --git a/packages/roadshow/lib/render.ts b/packages/roadshow/lib/render.ts new file mode 100644 index 0000000..5caf51d --- /dev/null +++ b/packages/roadshow/lib/render.ts @@ -0,0 +1,212 @@ +import clownface, { GraphPointer, MultiPointer } from 'clownface' +import { html, TemplateResult } from 'lit' +import { findNodes } from 'clownface-shacl-path' +import { BlankNode, Literal, NamedNode, Term } from '@rdfjs/types' +import { roadshow } from '@hydrofoil/vocabularies/builders' +import { rdfs, sh } from '@tpluscode/rdf-ns-builders/strict' +import { dataset } from '@rdf-esm/dataset' +import { create, FocusNodeState, ObjectState, PropertyState } from './state' +import { + FocusNodeViewContext, + ObjectViewContext, + Params, + PropertyViewContext, + Show, + ViewContext, +} from './ViewContext/index' +import type { RoadshowController } from '../RoadshowController' +import { isLiteral, isResource, TRUE } from './clownface' + +interface Render { + state: FocusNodeState + focusNode?: MultiPointer + controller: RoadshowController + params: Params +} + +function findViewers(state: PropertyState, object: GraphPointer, { viewers, renderers }: RoadshowController) { + let applicableViewers = viewers.findApplicableViewers(object) + if (state.viewer && !viewers.isMultiViewer(state.viewer)) { + applicableViewers = [ + { pointer: viewers.get(state.viewer), score: null }, + ...applicableViewers.filter(match => !match.pointer.term.equals(state.viewer)), + ] + } + + const viewer = applicableViewers.find(vr => renderers.has(vr.pointer.term))?.pointer.term || roadshow.RendererNotFoundViewer + + return { applicableViewers, viewer } +} + +function objectState(state: PropertyState, object: GraphPointer, controller: RoadshowController): T extends Literal ? ObjectState : FocusNodeState { + const objectState = state.objects.get(object.term) + if (!objectState) { + const { applicableViewers, viewer } = findViewers(state, object, controller) + + if (isResource(object)) { + const newState: FocusNodeState = { + ...create({ ...state, term: object.term, pointer: object }), + applicableViewers, + viewer, + } + if (TRUE.equals(state.propertyShape?.pointer.out(roadshow.dereference).term)) { + delete newState.pointer + controller.resources.loadToState(newState) + } + state.objects.set(object.term, newState) + return newState as any + } + + const newState: ObjectState = { + applicableViewers, + viewer, + } + + state.objects.set(object.term, newState) + return newState as any + } + + return objectState as any +} + +function createChildContext(parent: ViewContext, state: any, pointer: GraphPointer) : T extends Literal ? ObjectViewContext : FocusNodeViewContext { + if (isResource(pointer)) { + const childState = objectState(state, pointer, parent.controller) + + return { + depth: parent.depth + 1, + params: parent.params, + controller: parent.controller, + node: pointer, + show: showProperty, + state: childState, + } as any + } + + const childState = objectState(state, pointer as any, parent.controller) + return { + depth: parent.depth + 1, + controller: parent.controller, + params: parent.params, + state: childState, + node: pointer, + } as any +} + +function renderMultiRenderObject(this: PropertyViewContext, ...args: Parameters) { + const [object, render] = args + + if (isResource(object) && render?.resource) { + return render.resource.call(createChildContext(this, this.state, object)) + } + + if (isLiteral(object)) { + const childContext = createChildContext(this, this.state, object) + const renderer = this.controller.renderers.get(childContext.state) + const result = renderer.call(childContext, object) + if (render?.literal) { + return render.literal.call(childContext, result) + } + + return result + } + + return '' +} + +function renderPropertyObjectsIndividually(parent: FocusNodeViewContext, property: PropertyState) { + return (object: GraphPointer) => { + const context = createChildContext(parent, property, object) + if (!context.state.viewer) { + return 'No viewer found' + } + + const renderer = parent.controller.renderers.get(context.state) + + if ('properties' in context.state) { + parent.controller.shapes.loadShapes(context.state, object) + } + + if ('pointer' in context.state) { + return renderer.call(context, context.state.pointer || object) + } + + return renderer.call(context, object) + } +} + +function propertyStateTo(show: Show) { + return (property: PropertyState) => { + if ('id' in show.property) { + return property.propertyShape.equals(show.property) + } + + if ('termType' in show.property) { + return property.propertyShape.pointer.has(sh.path, show.property).term + } + + return property === show.property + } +} + +function showProperty(this: FocusNodeViewContext, show: Show) { + const property = this.state.properties.find(propertyStateTo(show)) + + if (!property) { + const details = clownface({ dataset: dataset() }) + .blankNode() + .addOut(rdfs.label, 'Property not found in state') + return this.controller.renderers.get({ viewer: roadshow.ErrorRenderer }).call(this, details) + } + + const objects = findNodes(this.node, property.path) + if (property.viewer && this.controller.viewers.isMultiViewer(property.viewer)) { + this.controller.shapes.loadShapes(property, objects) + + const renderer = this.controller.renderers.get(property) + + const context: PropertyViewContext = { + depth: this.depth, + controller: this.controller, + params: this.params, + state: property, + node: objects, + object: renderMultiRenderObject, + } + return renderer.call(context, objects) + } + + return html`${objects.map(renderPropertyObjectsIndividually(this, property))}` +} + +function renderState({ state, focusNode, controller, params }: Required): TemplateResult | string { + const renderer = controller.renderers.get(state) + + const context: FocusNodeViewContext = { + depth: 0, + state, + params, + controller, + node: focusNode, + show: showProperty, + } + + return renderer.call(context, focusNode) +} + +export function render({ focusNode, ...rest }: Render): TemplateResult | string { + if (focusNode) { + return renderState({ focusNode, ...rest }) + } + + const pointer = clownface({ dataset: dataset() }).blankNode() + return renderState({ + ...rest, + focusNode: pointer, + state: create({ + pointer, + term: pointer.term, + viewer: roadshow.LoadingViewer, + }), + }) +} diff --git a/packages/roadshow/lib/state.ts b/packages/roadshow/lib/state.ts index ff03f6a..bbe18d4 100644 --- a/packages/roadshow/lib/state.ts +++ b/packages/roadshow/lib/state.ts @@ -1,35 +1,85 @@ /* eslint-disable no-use-before-define */ -import type { NodeShape, PropertyShape } from '@rdfine/shacl' -import type { BlankNode, Literal, NamedNode } from '@rdfjs/types' -import type { GraphPointer, MultiPointer } from 'clownface' -import type { TemplateResult } from 'lit' -import type { ViewerScore } from '../ViewersController' +import { NodeShape, PropertyShape } from '@rdfine/shacl' +import { GraphPointer } from 'clownface' +import { BlankNode, NamedNode, Term } from '@rdfjs/types' +import { dash, sh } from '@tpluscode/rdf-ns-builders/strict' +import TermMap from '@rdf-esm/term-map' +import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import { isResource, isGraphPointer } from './clownface' -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface LocalState { +export interface ViewerScore { + pointer: GraphPointer + score: number | null +} +export interface ObjectState { + applicableViewers: ViewerScore[] + viewer: Term +} +interface ShapedNodeState { + shape?: NodeShape + applicableShapes: NodeShape[] + shapesLoaded?: boolean + loading: Set + loadingFailed: Set } -export interface CoreState { - pointer: T - applicableViewers: ViewerScore[] - viewer?: GraphPointer - render?(): TemplateResult | string - locals: LocalState +export interface PropertyState extends ShapedNodeState { + propertyShape: PropertyShape + path: GraphPointer + viewer?: Term + objects: Map } -export interface PropertyViewState extends CoreState { - shape?: PropertyShape - objects: Record - path?: MultiPointer +export interface FocusNodeState extends ShapedNodeState { + term: Term + pointer?: GraphPointer + properties: PropertyState[] + applicableViewers: ViewerScore[] + viewer: Term } -export type LiteralViewState = CoreState> +export function createPropertyState(arr: PropertyState[], shape: PropertyShape): PropertyState[] { + const path = shape.pointer.out(sh.path) + if (!isGraphPointer(path)) { + // eslint-disable-next-line no-console + console.warn(`Skipping property ${shape.name || shape.id.value}. It does not have a valid sh:path`) + return arr + } + + const [shNode] = shape.pointer.out(sh.node).toArray() + const nodeShape = isResource(shNode) ? fromPointer(shNode) : undefined + + return [...arr, { + propertyShape: shape, + shape: nodeShape, + path, + objects: new TermMap(), + viewer: shape.viewer?.id, + applicableShapes: [], + loading: new Set(), + loadingFailed: new Set(), + }] +} -export interface ResourceViewState extends CoreState> { +interface Create { shape?: NodeShape - applicableShapes: NodeShape[] - properties: Partial> + viewer?: Term + term: Term + pointer?: GraphPointer } -export type ViewState = LiteralViewState | ResourceViewState +export function create({ term, pointer, shape, viewer = dash.DetailsViewer }: Create): FocusNodeState { + return { + shape, + loading: new Set(), + loadingFailed: new Set(), + applicableShapes: [], + applicableViewers: [], + shapesLoaded: false, + properties: shape?.property.reduce(createPropertyState, []) || [], + viewer, + term, + pointer, + } +} diff --git a/packages/roadshow/package.json b/packages/roadshow/package.json index 82ae74e..8cd3797 100644 --- a/packages/roadshow/package.json +++ b/packages/roadshow/package.json @@ -19,12 +19,17 @@ "@rdf-esm/namespace": "^0.5.3", "@rdf-esm/term-map": "^0.5.0", "@rdfjs/types": "*", + "@zazuko/rdf-vocabularies": "*", "clownface": "^1.2.0", "clownface-shacl-path": "^1.1", "lit": "^2.0.0-rc.2" }, "devDependencies": { - "@types/rdfjs__term-map": "*" + "@open-wc/testing": "^3.0.0-next.2", + "@rdf-esm/namespace": "^0.5.3", + "@types/rdfjs__term-map": "*", + "@types/sinon": "^10.0.2", + "sinon": "^11.1.2" }, "scripts": { "prepack": "tsc" diff --git a/packages/roadshow/renderers/Details.ts b/packages/roadshow/renderers/Details.ts index 5ba4058..37f7624 100644 --- a/packages/roadshow/renderers/Details.ts +++ b/packages/roadshow/renderers/Details.ts @@ -1,53 +1,11 @@ -import { dash, sh } from '@tpluscode/rdf-ns-builders' -import { Term } from '@rdfjs/types' -import { findNodes } from 'clownface-shacl-path' -import TermMap from '@rdf-esm/term-map' +import { dash } from '@tpluscode/rdf-ns-builders' import { html } from 'lit' -import { PropertyShape } from '@rdfine/shacl' -import type { GraphPointer } from 'clownface' import { Renderer } from '../index' +import { FocusNodeViewContext } from '../lib/ViewContext/index' -interface ResourceObject { - value: GraphPointer - viewer: GraphPointer - viewers: GraphPointer[] - render(): unknown -} - -type ResourceMap = { - shape: PropertyShape - objects: Array -} - -export const detailsView: Renderer = { +export const detailsView: Renderer = { viewer: dash.DetailsViewer, - render(resource, shape) { - const propertiesInit = shape!.property.reduce<[Term, ResourceMap][]>((entries, property) => { - if (property.hidden) { - return entries - } - - const objects = findNodes(resource, property.pointer.out(sh.path)) - .map((value) => { - const viewers = this.findApplicableViewers(value).map(v => v.pointer) - const [viewer] = viewers - const render = this.renderers.get(viewer?.term) - - return { - value, - viewer, - viewers, - render: () => render.call(this, value, shape), - } as ResourceObject - }) - - return [ - ...entries, - [property.id, { shape: property, objects }], - ] - }, []) - const properties = [...new TermMap(propertiesInit).values()] - - return html`${properties.map(property => html`${property.objects.map(object => html`${object.render()}`)}`)}` + render() { + return html`${this.state.properties.map(property => html`${this.show({ property })}`)}` }, } diff --git a/packages/roadshow/renderers/Label.ts b/packages/roadshow/renderers/Label.ts index 4694e9a..57f8a3d 100644 --- a/packages/roadshow/renderers/Label.ts +++ b/packages/roadshow/renderers/Label.ts @@ -5,8 +5,8 @@ import { Renderer } from '../index' export const Label: Renderer = { viewer: dash.LabelViewer, render(resource) { - const [label] = resource.out([rdfs.label, skos.prefLabel, schema.name], { language: '*' }).values + const [label] = resource.out([rdfs.label, skos.prefLabel, schema.name], { language: [this.params.language, '*'] }).values - return html`${label || resource.value}` + return html`${label || resource.value}` }, } diff --git a/packages/roadshow/renderers/Literal.ts b/packages/roadshow/renderers/Literal.ts index 40b2106..2fa4606 100644 --- a/packages/roadshow/renderers/Literal.ts +++ b/packages/roadshow/renderers/Literal.ts @@ -4,6 +4,6 @@ import { Renderer } from '../index' export const Literal: Renderer = { viewer: dash.LiteralViewer, render(resource) { - return resource.value + return resource.values[0] }, } diff --git a/packages/roadshow/renderers/URI.ts b/packages/roadshow/renderers/URI.ts index 2adca21..1b8b726 100644 --- a/packages/roadshow/renderers/URI.ts +++ b/packages/roadshow/renderers/URI.ts @@ -1,14 +1,12 @@ -import { dash, rdfs } from '@tpluscode/rdf-ns-builders/strict' +import { dash } from '@tpluscode/rdf-ns-builders/strict' import { html } from 'lit' import { Renderer } from '../index' export const URI: Renderer = { viewer: dash.URIViewer, render(resource) { - const label = resource.out(rdfs.label) + const [value] = resource.values - return html`${ - this.show({ resource: label, property: rdfs.label, viewer: dash.LabelViewer }) - }` + return html`${value}` }, } diff --git a/packages/roadshow/renderers/index.ts b/packages/roadshow/renderers/index.ts index 43d5e5d..67ed350 100644 --- a/packages/roadshow/renderers/index.ts +++ b/packages/roadshow/renderers/index.ts @@ -2,3 +2,6 @@ export * from './Details' export * from './Label' export * from './Literal' export * from './URI' +export * from './roadshow/Loading' +export * from './roadshow/LoadingFailed' +export * from './roadshow/RendererNotFoundViewer' diff --git a/packages/roadshow/renderers/roadshow/Loading.ts b/packages/roadshow/renderers/roadshow/Loading.ts new file mode 100644 index 0000000..bb6a5ae --- /dev/null +++ b/packages/roadshow/renderers/roadshow/Loading.ts @@ -0,0 +1,9 @@ +import { roadshow } from '@hydrofoil/vocabularies/builders' +import { Renderer } from '../../index' + +export const Loading: Renderer = { + viewer: roadshow.LoadingViewer, + render() { + return 'Loading...' + }, +} diff --git a/packages/roadshow/renderers/roadshow/LoadingFailed.ts b/packages/roadshow/renderers/roadshow/LoadingFailed.ts new file mode 100644 index 0000000..644c1f2 --- /dev/null +++ b/packages/roadshow/renderers/roadshow/LoadingFailed.ts @@ -0,0 +1,9 @@ +import { roadshow } from '@hydrofoil/vocabularies/builders' +import { Renderer } from '../../index' + +export const LoadingFailed: Renderer = { + viewer: roadshow.LoadingFailedViewer, + render() { + return 'Loading failed!' + }, +} diff --git a/packages/roadshow/renderers/roadshow/RendererNotFoundViewer.ts b/packages/roadshow/renderers/roadshow/RendererNotFoundViewer.ts new file mode 100644 index 0000000..e87ecf6 --- /dev/null +++ b/packages/roadshow/renderers/roadshow/RendererNotFoundViewer.ts @@ -0,0 +1,9 @@ +import { roadshow } from '@hydrofoil/vocabularies/builders' +import { Renderer } from '../../index' + +export const RendererNotFoundViewer: Renderer = { + viewer: roadshow.RendererNotFoundViewer, + render() { + return `Renderer not found for viewer ${this.state.viewer.value}` + }, +} diff --git a/packages/roadshow/roadshow-view.ts b/packages/roadshow/roadshow-view.ts index 509f7e1..3b97597 100644 --- a/packages/roadshow/roadshow-view.ts +++ b/packages/roadshow/roadshow-view.ts @@ -2,15 +2,14 @@ import { css, LitElement, PropertyValues } from 'lit' import { property } from 'lit/decorators.js' import type { GraphPointer } from 'clownface' import type { BlankNode, NamedNode } from '@rdfjs/types' -import type { NodeShape } from '@rdfine/shacl' -import RdfResource from '@tpluscode/rdfine' -import { NodeShapeBundle, PropertyShapeBundle } from '@rdfine/shacl/bundles' -import { NodeShapeMixinEx, PropertyShapeMixinEx } from '@rdfine/dash/extensions/sh' import { RoadshowController } from './RoadshowController' -import type { RoadshowView, Renderer, ViewerMatchInit } from './index' +import type { RoadshowView, Renderer, ViewerMatcher } from './index' import type { ResourceLoader } from './ResourcesController' import { ShapesLoader } from './ShapesController' -import { ResourceViewState } from './lib/state' +import { render } from './lib/render' +import './lib/rdfine' +import { FocusNodeState } from './lib/state' +import { Params } from './lib/ViewContext/index' export class RoadshowViewElement extends LitElement implements RoadshowView { static get styles() { @@ -22,20 +21,20 @@ export class RoadshowViewElement extends LitElement implements RoadshowView { private roadshow: RoadshowController @property({ type: Object }) - resource: GraphPointer | undefined + resource: GraphPointer | undefined @property({ type: Object }) resourceId: NamedNode | undefined @property({ type: Object }) - params: unknown = {} - - shapes: NodeShape[] = [] + params: Partial = {} @property({ type: Array }) renderers: Renderer[] = [] - viewers: ViewerMatchInit[] = [] + @property({ type: Array }) + viewers: ViewerMatcher[] = [] + resourceLoader?: ResourceLoader shapesLoader?: ShapesLoader @@ -44,13 +43,17 @@ export class RoadshowViewElement extends LitElement implements RoadshowView { this.roadshow = new RoadshowController(this) } - get state(): ResourceViewState | undefined { - return this.roadshow.rootContext?.state + get state(): FocusNodeState | null { + return this.roadshow.state } - protected updated(_changedProperties: PropertyValues): void { - if (_changedProperties.has('resource') || _changedProperties.has('resourceId')) { - this.roadshow.prepareViewState() + protected async updated(_changedProperties: PropertyValues): Promise { + if (_changedProperties.has('resourceId') && this.resourceId) { + await this.roadshow.initState() + } + + if (_changedProperties.has('resource')) { + this.roadshow.initState() } if (_changedProperties.has('renderers')) { @@ -59,7 +62,15 @@ export class RoadshowViewElement extends LitElement implements RoadshowView { } render(): unknown { - return this.roadshow.render() + return render({ + state: this.roadshow.state, + controller: this.roadshow, + focusNode: this.roadshow.state.pointer, + params: { + language: navigator.language, + ...this.params, + }, + }) } } @@ -70,6 +81,3 @@ declare global { } customElements.define('roadshow-view', RoadshowViewElement) - -RdfResource.factory.addMixin(...NodeShapeBundle, ...PropertyShapeBundle) -RdfResource.factory.addMixin(NodeShapeMixinEx, PropertyShapeMixinEx) diff --git a/packages/roadshow/test/RoadshowController.test.ts b/packages/roadshow/test/RoadshowController.test.ts new file mode 100644 index 0000000..a647c5e --- /dev/null +++ b/packages/roadshow/test/RoadshowController.test.ts @@ -0,0 +1,53 @@ +import { expect } from '@open-wc/testing' +import { dash, rdf, sh } from '@tpluscode/rdf-ns-builders/strict' +import { RoadshowController } from '../RoadshowController' +import { RoadshowView } from '../index' +import { blankNode } from './_support/clownface' +import { ex } from './_support/ns' + +describe('@hydrofoil/roadshow/RoadshowController', () => { + let view: RoadshowView + + beforeEach(() => { + const resource = blankNode() + + view = { + resource, + params: {}, + renderers: [], + viewers: [], + addController() { + // + }, + async requestUpdate() { + // + }, + } as any + }) + + describe('.prepareState', () => { + it('selects dash:shape for node state', async () => { + // given + view.resource?.addOut(dash.shape, ex.FooShape, + shape => shape.addOut(rdf.type, sh.NodeShape).addOut(sh.property)) + const controller = new RoadshowController(view) + + // when + await controller.initState() + + // then + expect(controller.state?.shape?.id).to.deep.eq(ex.FooShape) + }) + + it('sets undefined shape when it is no annotated', async () => { + // given + const controller = new RoadshowController(view) + + // when + await controller.initState() + + // then + expect(controller.state?.shape).to.be.undefined + }) + }) +}) diff --git a/packages/roadshow/test/ShapesController.test.ts b/packages/roadshow/test/ShapesController.test.ts new file mode 100644 index 0000000..d6a5341 --- /dev/null +++ b/packages/roadshow/test/ShapesController.test.ts @@ -0,0 +1,94 @@ +import sinon from 'sinon' +import { expect } from '@open-wc/testing' +import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import { ShapesController } from '../ShapesController' +import { RoadshowView } from '../index' +import { blankNode, namedNode } from './_support/clownface' +import { focusNodeState } from './_support/state' +import { ex } from './_support/ns' +import { ResourcesController } from '../ResourcesController' + +describe('@hydrofoil/roadshow/ShapesController', () => { + let host: RoadshowView + let shapesLoader: sinon.SinonStub + let resources: ResourcesController + + beforeEach(() => { + shapesLoader = sinon.stub().resolves([]) + host = { + shapesLoader, + requestUpdate: sinon.spy(), + addController: sinon.spy(), + } as any + }) + + describe('.findApplicableShapes', () => { + it('sets flag if no shape is returned', async () => { + // given + const controller = new ShapesController(host, resources) + const state = { + ...focusNodeState(), + } + + // when + await controller.loadShapes(state, blankNode()) + + // then + expect(state.shapesLoaded).to.be.true + }) + + it('does nothing if already loaded', async () => { + // given + const controller = new ShapesController(host, resources) + const state = { + ...focusNodeState(), + shapesLoaded: true, + } + + // when + await controller.loadShapes(state, blankNode()) + + // then + expect(shapesLoader).not.to.have.been.called + expect(host.requestUpdate).not.to.have.been.called + }) + + it('does not replace preselected shape', async () => { + // given + const controller = new ShapesController(host, resources) + const state = { + ...focusNodeState(), + shape: fromPointer(namedNode(ex.foo)), + } + shapesLoader.resolves([namedNode(ex.bar)]) + + // when + await controller.loadShapes(state, blankNode()) + + // then + expect(state.shape.id).to.deep.eq(ex.foo) + expect(state.applicableShapes.map(s => s.id)).to.deep.contain.ordered.members([ + ex.foo, ex.bar, + ]) + }) + + it('does not duplicate same shape is previously preselected', async () => { + // given + const controller = new ShapesController(host, resources) + const state = { + ...focusNodeState(), + shape: fromPointer(namedNode(ex.foo)), + } + shapesLoader.resolves([namedNode(ex.bar), namedNode(ex.foo)]) + + // when + await controller.loadShapes(state, blankNode()) + + // then + expect(state.applicableShapes).to.have.length(2) + expect(state.applicableShapes.map(s => s.id)).to.deep.contain.ordered.members([ + ex.foo, ex.bar, + ]) + }) + }) +}) diff --git a/packages/roadshow/test/ViewersController.test.ts b/packages/roadshow/test/ViewersController.test.ts new file mode 100644 index 0000000..7ac3c0b --- /dev/null +++ b/packages/roadshow/test/ViewersController.test.ts @@ -0,0 +1,28 @@ +import { expect } from '@open-wc/testing' +import { dash } from '@tpluscode/rdf-ns-builders/strict' +import sinon from 'sinon' +import { ViewersController } from '../ViewersController' +import { RoadshowView } from '../index' + +describe('@hydrofoil/roadshow/ViewersController', () => { + let host: RoadshowView + + beforeEach(() => { + host = { + addController: sinon.spy(), + } as any + }) + + describe('.get', () => { + it('marks multiviewer when it has that type', () => { + // given + const controller = new ViewersController(host) + + // when + const isMultiViewer = controller.isMultiViewer(dash.ValueTableViewer) + + // then + expect(isMultiViewer).to.be.true + }) + }) +}) diff --git a/packages/roadshow/test/_support/TestRenderersController.ts b/packages/roadshow/test/_support/TestRenderersController.ts new file mode 100644 index 0000000..d5c159a --- /dev/null +++ b/packages/roadshow/test/_support/TestRenderersController.ts @@ -0,0 +1,27 @@ +import TermMap from '@rdf-esm/term-map' +import { NamedNode } from '@rdfjs/types' +import { Renderer, RenderFunc } from '../../index' + +export class TestRenderersController { + private renderers: Map> + + constructor(renderers: Array<[NamedNode, RenderFunc]>) { + this.renderers = new TermMap(renderers.map(([viewer, render]) => [viewer, { viewer, render }])) + } + + get(state: { viewer: NamedNode }) { + return this.renderers.get(state.viewer)!.render + } + + has(viewer: NamedNode): boolean { + return this.renderers.has(viewer) + } + + hostConnected(): void { + // + } + + set(viewer: NamedNode, render: RenderFunc): void { + this.renderers.set(viewer, { viewer, render }) + } +} diff --git a/packages/roadshow/test/_support/clownface.ts b/packages/roadshow/test/_support/clownface.ts new file mode 100644 index 0000000..58494dc --- /dev/null +++ b/packages/roadshow/test/_support/clownface.ts @@ -0,0 +1,15 @@ +import * as RDF from '@rdf-esm/dataset' +import create from 'clownface' +import { NamedNode } from '@rdfjs/types' + +export function clownface(dataset = RDF.dataset()) { + return create({ dataset }) +} + +export function blankNode() { + return clownface().blankNode() +} + +export function namedNode(id: string | NamedNode) { + return clownface().namedNode(id) +} diff --git a/packages/roadshow/test/_support/ns.ts b/packages/roadshow/test/_support/ns.ts new file mode 100644 index 0000000..7cab655 --- /dev/null +++ b/packages/roadshow/test/_support/ns.ts @@ -0,0 +1,3 @@ +import namespace from '@rdf-esm/namespace' + +export const ex = namespace('https://example.com/') diff --git a/packages/roadshow/test/_support/state.ts b/packages/roadshow/test/_support/state.ts new file mode 100644 index 0000000..a0bafe2 --- /dev/null +++ b/packages/roadshow/test/_support/state.ts @@ -0,0 +1,14 @@ +import { FocusNodeState } from '../../lib/state' +import { ex } from './ns' + +export function focusNodeState(term = ex.foo, viewer = ex.FooViewer): FocusNodeState { + return { + properties: [], + applicableShapes: [], + applicableViewers: [], + viewer, + term, + loading: new Set(), + loadingFailed: new Set(), + } +} diff --git a/packages/roadshow/test/lib/render.test.ts b/packages/roadshow/test/lib/render.test.ts new file mode 100644 index 0000000..6b3de7f --- /dev/null +++ b/packages/roadshow/test/lib/render.test.ts @@ -0,0 +1,141 @@ +import { expect, fixture } from '@open-wc/testing' +import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import { NodeShape } from '@rdfine/shacl' +import { html } from 'lit' +import sinon from 'sinon' +import { dash, foaf, rdfs, sh } from '@tpluscode/rdf-ns-builders/strict' +import { Initializer } from '@tpluscode/rdfine/RdfResource' +import { render } from '../../lib/render' +import { blankNode, namedNode } from '../_support/clownface' +import { ex } from '../_support/ns' +import { RoadshowController } from '../../RoadshowController' +import { ShapesController } from '../../ShapesController' +import { focusNodeState } from '../_support/state' +import { create, FocusNodeState } from '../../lib/state' +import { FocusNodeViewContext, Params, PropertyViewContext } from '../../lib/ViewContext/index' +import '../../lib/rdfine' +import { TestRenderersController } from '../_support/TestRenderersController' + +describe('@hydrofoil/roadshow/lib/render', () => { + function createShape(init?: Initializer) { + return fromPointer(blankNode(), init) + } + let renderers: TestRenderersController + let loadShapes: ShapesController['loadShapes'] + let controller: RoadshowController + let params: Params + + beforeEach(() => { + renderers = new TestRenderersController([ + [dash.DetailsViewer, function render(this: FocusNodeViewContext) { + return html`${this.state.properties.map(property => html`${this.show({ property })}`)}` + }], + ]) + loadShapes = sinon.stub() + controller = { + renderers, + viewers: { + isMultiViewer: () => false, + findApplicableViewers: sinon.stub().returns([]), + get: sinon.stub().returns(blankNode()), + }, + shapes: { + loadShapes, + }, + } as any + params = { + language: 'en', + } + }) + + describe('render', () => { + it('renders using found renderer', async () => { + // given + const state = { ...focusNodeState(), shape: createShape() } + const focusNode = namedNode('/foo/bar') + renderers.set(ex.FooViewer, ({ value }) => html`
Resource ${value}
`) + + // when + const result = await fixture(render({ state, focusNode, controller, params })) + + // then + expect(result.textContent).to.eq('Resource /foo/bar') + }) + + describe('multi viewer', async () => { + it('called with all property pointers', async () => { + // given + const shape = createShape({ + property: [{ + path: rdfs.label, + viewer: ex.FooViewer, + }], + }) + sinon.stub(controller.viewers, 'isMultiViewer').returns(true) + const focusNode = namedNode('/foo/bar') + .addOut(rdfs.label, 'foo') + .addOut(rdfs.label, 'bar') + .addOut(rdfs.label, 'baz') + const state: FocusNodeState = create({ shape, term: focusNode.term, pointer: focusNode }) + renderers.set(ex.FooViewer, ptr => html`
Count: ${ptr.terms.length}
`) + + // when + const result = await fixture(render({ state, focusNode, controller, params })) + + // then + expect(result.textContent).to.eq('Count: 3') + }) + + it('calling sub-renderer for individual objects', async () => { + // given + const shape = createShape({ + property: [{ + path: foaf.knows, + viewer: ex.FriendsViewer, + node: { + types: [sh.NodeShape], + property: [{ + types: [sh.PropertyShape], + path: rdfs.label, + viewer: dash.LiteralViewer, + }, { + types: [sh.PropertyShape], + path: rdfs.comment, + viewer: dash.LiteralViewer, + }], + }, + }], + }) + sinon.stub(controller.viewers, 'isMultiViewer').returns(true) + const focusNode = namedNode('/foo/bar') + .addOut(foaf.knows, friend => friend.addOut(rdfs.label, 'Foo').addOut(rdfs.comment, 'foo comment')) + .addOut(foaf.knows, friend => friend.addOut(rdfs.label, 'Bar').addOut(rdfs.comment, 'bar comment')) + .addOut(foaf.knows, friend => friend.addOut(rdfs.label, 'Baz').addOut(rdfs.comment, 'baz comment')) + const state: FocusNodeState = create({ shape, term: focusNode.term, pointer: focusNode }) + renderers.set(ex.FriendsViewer, function render(this: PropertyViewContext, friends) { + return html` + ${friends.toArray().map(object => html` + + ${this.object(object, { + resource() { + return html`${this.state.properties.map(property => html``)}` + }, + })} + `)} +
${this.show({ property })}
` + }) + renderers.set(dash.LiteralViewer, (obj: any) => obj.value) + + // when + const result = await fixture(render({ state, focusNode, controller, params })) + + // then + const cells = [...result.querySelectorAll('td')] + .map(el => el.textContent) + expect(cells).to.contain.members([ + 'Foo', 'foo comment', 'Bar', 'bar comment', 'Baz', 'baz comment', + ]) + }) + }) + }) +}) diff --git a/packages/roadshow/test/lib/state.test.ts b/packages/roadshow/test/lib/state.test.ts new file mode 100644 index 0000000..dcd1400 --- /dev/null +++ b/packages/roadshow/test/lib/state.test.ts @@ -0,0 +1,63 @@ +import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import { expect } from '@open-wc/testing' +import { dash, rdf, rdfs, schema, sh } from '@tpluscode/rdf-ns-builders/strict' +import { blankNode } from '../_support/clownface' +import { create } from '../../lib/state' +import '../../lib/rdfine' +import { ex } from '../_support/ns' + +describe('@hydrofoil/roadshow/lib/state', () => { + describe('create', () => { + it('selects initial viewer as dash:DetailsViewer', () => { + // given + const shape = fromPointer(blankNode()) + + // when + const state = create({ shape, term: ex.foo }) + + // then + expect(state.viewer).to.deep.eq(dash.DetailsViewer) + }) + + it('builds PropertyState for every sh:property', () => { + // given + const shape = fromPointer(blankNode(), { + property: [{ + types: [sh.PropertyShape], + path: rdfs.label, + }, { + types: [sh.PropertyShape], + path: rdfs.comment, + }, { + types: [sh.PropertyShape], + path: rdf.type, + }, { + types: [sh.PropertyShape], + path: schema.owns, + }], + }) + + // when + const state = create({ shape, term: ex.foo }) + + // then + expect(state.properties).to.have.length(4) + expect(state.properties.map(p => p.path.term)).to.deep.contain.all.members([ + rdfs.label, rdfs.comment, rdf.type, schema.owns, + ]) + }) + + it('it ignores properties without sh:path', () => { + // given + const shape = fromPointer(blankNode(), { + property: [{ }, { }, { }, { }], + }) + + // when + const state = create({ shape, term: ex.foo }) + + // then + expect(state.properties).to.have.length(0) + }) + }) +}) diff --git a/packages/roadshow/test/roadshow-view.test.ts b/packages/roadshow/test/roadshow-view.test.ts new file mode 100644 index 0000000..8d1dddf --- /dev/null +++ b/packages/roadshow/test/roadshow-view.test.ts @@ -0,0 +1,114 @@ +import { aTimeout, expect, fixture } from '@open-wc/testing' +import { dash, rdfs } from '@tpluscode/rdf-ns-builders/strict' +import { html } from 'lit' +import { fromPointer } from '@rdfine/shacl/lib/NodeShape' +import sinon from 'sinon' +import { clownface } from './_support/clownface' +import { Renderer } from '../index' +import type { RoadshowViewElement } from '../roadshow-view' +import '../roadshow-view' +import { ex } from './_support/ns' +import { FocusNodeViewContext, ObjectViewContext } from '../lib/ViewContext/index' + +describe('@hydrofoil/roadshow/roadshow-view', () => { + it('rendered using details viewer by default', async () => { + // given + const graph = clownface() + const shape = fromPointer(graph.blankNode(), { + property: [{ + path: rdfs.label, + viewer: dash.LiteralViewer, + }], + }) + const resource = graph.namedNode('foo') + .addOut(rdfs.label, 'Foo Resource') + .addOut(dash.shape, shape.pointer) + const renderers = [>{ + viewer: dash.DetailsViewer, + render() { + return html`${this.state.properties.map(property => html`${this.show({ property })}`)}` + }, + }, >{ + viewer: dash.LiteralViewer, + render(obj) { + return html`${obj.value}` + }, + }] + + // when + const view = await fixture(html``) + await view.updateComplete + + // then + expect(view.renderRoot.querySelector('span')?.textContent).to.eq('Foo Resource') + }) + + it('loads shape from provider', async () => { + // given + const graph = clownface() + const shape = fromPointer(graph.blankNode(), { + property: [{ + path: rdfs.label, + viewer: dash.LiteralViewer, + }], + }) + const resource = graph.namedNode('foo') + .addOut(rdfs.label, 'Foo Resource') + const renderers = [>{ + viewer: dash.DetailsViewer, + render() { + return html`${this.state.properties.map(property => html`${this.show({ property })}`)}` + }, + }, >{ + viewer: dash.LiteralViewer, + render(obj) { + return html`${obj.value}` + }, + }] + async function loadShape() { + return [shape.pointer] + } + + // when + const view = await fixture(html``) + await view.updateComplete + + // then + expect(view.renderRoot.querySelector('span')?.textContent).to.eq('Foo Resource') + }) + + it('loads shape from provider if it is a named node without properties', async () => { + // given + const graph = clownface() + const shape = fromPointer(graph.blankNode(), { + property: [{ + path: rdfs.label, + viewer: dash.LiteralViewer, + }], + }) + const resource = graph.namedNode('foo') + .addOut(rdfs.label, 'Foo Resource') + .addOut(dash.shape, ex.FooShape) + const renderers = [>{ + viewer: dash.DetailsViewer, + render() { + return 'Foo' + }, + }] + const loadShape = sinon.stub().resolves(shape.pointer) + + // when + const view = await fixture(html``) + await view.updateComplete + await aTimeout(100) + + // then + expect(loadShape).to.have.been.calledWith(ex.FooShape) + expect(view.renderRoot.textContent).to.eq('Foo') + }) +}) diff --git a/packages/roadshow/viewers/BlankNodeViewer.ts b/packages/roadshow/viewers/BlankNodeViewer.ts index 97f39a1..7953d77 100644 --- a/packages/roadshow/viewers/BlankNodeViewer.ts +++ b/packages/roadshow/viewers/BlankNodeViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const BlankNodeViewer: ViewerMatchInit = { +export const BlankNodeViewer: ViewerMatcher = { viewer: dash.BlankNodeViewer, match({ resource }) { return resource.term.termType === 'BlankNode' ? 1 : 0 diff --git a/packages/roadshow/viewers/DetailsViewer.ts b/packages/roadshow/viewers/DetailsViewer.ts index 67216be..e7d56cf 100644 --- a/packages/roadshow/viewers/DetailsViewer.ts +++ b/packages/roadshow/viewers/DetailsViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const DetailsViewer: ViewerMatchInit = { +export const DetailsViewer: ViewerMatcher = { viewer: dash.DetailsViewer, match({ resource }) { return resource.term.termType === 'BlankNode' || resource.term.termType === 'NamedNode' ? null : 0 diff --git a/packages/roadshow/viewers/HTMLViewer.ts b/packages/roadshow/viewers/HTMLViewer.ts index 9dc9b05..3a67e7b 100644 --- a/packages/roadshow/viewers/HTMLViewer.ts +++ b/packages/roadshow/viewers/HTMLViewer.ts @@ -1,7 +1,7 @@ import { dash, rdf } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const HTMLViewer: ViewerMatchInit = { +export const HTMLViewer: ViewerMatcher = { viewer: dash.HTMLViewer, match({ resource }) { return resource.term.termType === 'Literal' && resource.term.datatype.equals(rdf.HTML) ? 50 : 0 diff --git a/packages/roadshow/viewers/HyperlinkViewer.ts b/packages/roadshow/viewers/HyperlinkViewer.ts index ed4a77d..6762cf6 100644 --- a/packages/roadshow/viewers/HyperlinkViewer.ts +++ b/packages/roadshow/viewers/HyperlinkViewer.ts @@ -1,7 +1,7 @@ import { dash, xsd } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const HyperlinkViewer: ViewerMatchInit = { +export const HyperlinkViewer: ViewerMatcher = { viewer: dash.HyperlinkViewer, match({ resource }) { if (resource.term.termType === 'Literal') { diff --git a/packages/roadshow/viewers/ImageViewer.ts b/packages/roadshow/viewers/ImageViewer.ts index 73b3d74..561d721 100644 --- a/packages/roadshow/viewers/ImageViewer.ts +++ b/packages/roadshow/viewers/ImageViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -interface ImageViewerMatchInit extends ViewerMatchInit { +interface ImageViewerMatchInit extends ViewerMatcher { extensions: string[] } diff --git a/packages/roadshow/viewers/LabelViewer.ts b/packages/roadshow/viewers/LabelViewer.ts index 5234646..5020c4f 100644 --- a/packages/roadshow/viewers/LabelViewer.ts +++ b/packages/roadshow/viewers/LabelViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const LabelViewer: ViewerMatchInit = { +export const LabelViewer: ViewerMatcher = { viewer: dash.LabelViewer, match({ resource }) { return resource.term.termType === 'NamedNode' ? 5 : 0 diff --git a/packages/roadshow/viewers/LangStringViewer.ts b/packages/roadshow/viewers/LangStringViewer.ts index bcf1f47..abdbc15 100644 --- a/packages/roadshow/viewers/LangStringViewer.ts +++ b/packages/roadshow/viewers/LangStringViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const LangStringViewer: ViewerMatchInit = { +export const LangStringViewer: ViewerMatcher = { viewer: dash.LangStringViewer, match({ resource }) { return resource.term.termType === 'Literal' && resource.term.language ? 10 : 0 diff --git a/packages/roadshow/viewers/LiteralViewer.ts b/packages/roadshow/viewers/LiteralViewer.ts index 4f9f9b2..8c32cd8 100644 --- a/packages/roadshow/viewers/LiteralViewer.ts +++ b/packages/roadshow/viewers/LiteralViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const LiteralViewer: ViewerMatchInit = { +export const LiteralViewer: ViewerMatcher = { viewer: dash.LiteralViewer, match({ resource }) { return resource.term.termType === 'Literal' ? 1 : 0 diff --git a/packages/roadshow/viewers/URIViewer.ts b/packages/roadshow/viewers/URIViewer.ts index 90fa3ce..21eb577 100644 --- a/packages/roadshow/viewers/URIViewer.ts +++ b/packages/roadshow/viewers/URIViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const URIViewer: ViewerMatchInit = { +export const URIViewer: ViewerMatcher = { viewer: dash.URIViewer, match({ resource }) { return resource.term.termType === 'NamedNode' ? 1 : 0 diff --git a/packages/roadshow/viewers/ValueTableViewer.ts b/packages/roadshow/viewers/ValueTableViewer.ts index 7516291..36b1c6c 100644 --- a/packages/roadshow/viewers/ValueTableViewer.ts +++ b/packages/roadshow/viewers/ValueTableViewer.ts @@ -1,7 +1,7 @@ import { dash } from '@tpluscode/rdf-ns-builders' -import { ViewerMatchInit } from '../index' +import { ViewerMatcher } from '../index' -export const ValueTableViewer: ViewerMatchInit = { +export const ValueTableViewer: ViewerMatcher = { viewer: dash.ValueTableViewer, match() { return null diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs new file mode 100644 index 0000000..f798d50 --- /dev/null +++ b/web-test-runner.config.mjs @@ -0,0 +1,38 @@ +import { esbuildPlugin } from '@web/dev-server-esbuild'; +import rdfjs from 'rdfjs-eds-plugin' +import { fromRollup } from '@web/dev-server-rollup' +import commonjs from '@rollup/plugin-commonjs' +import fs from 'fs' + +const nodeResolveFix = { + serve(context) { + if (context.path.includes('node_modules') && context.path.endsWith('.ts')) { + const path = `.${context.request.url}`.replace(/\.ts$/,'.js') + const body = fs.readFileSync(path) + return { body, type: 'js' }; + } + } +} + +const config = { + groups: [ + { name: 'core', files: 'packages/roadshow/test/**/*.test.ts' }, + ], + coverage: true, + nodeResolve: true, + plugins: [ + esbuildPlugin({ ts: true, js: true, target: 'auto' }), + nodeResolveFix, + rdfjs, + fromRollup(commonjs)({ + exclude: [ + '**/node_modules/@open-wc/**/*', + '**/node_modules/chai/**/*', + '**/node_modules/chai-dom/**/*', + '**/node_modules/sinon-chai/**/*', + ] + }), + ], +}; + +export default config diff --git a/yarn.lock b/yarn.lock index 6338f84..7ef1ec8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1127,6 +1127,13 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@esm-bundle/chai@^4.3.4": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@esm-bundle/chai/-/chai-4.3.4.tgz#74ed4a0794b3a9f9517ff235744ac6f4be0d34dc" + integrity sha512-6Tx35wWiNw7X0nLY9RMx8v3EL8SacCFW+eEZOE9Hc+XxmU5HFE2AFEg+GehUZpiyDGwVvPH75ckGlqC7coIPnA== + dependencies: + "@types/chai" "^4.2.12" + "@hydrofoil/vocabularies@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@hydrofoil/vocabularies/-/vocabularies-0.2.0.tgz#36ab95db69d72a709b7f7a002f0f674eb8d8cc0d" @@ -1151,7 +1158,7 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@lit/reactive-element@^1.0.0-rc.2": +"@lit/reactive-element@^1.0.0-rc.1", "@lit/reactive-element@^1.0.0-rc.2": version "1.0.0-rc.2" resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.0.0-rc.2.tgz#f24dba16ea571a08dca70f1783bd2ca5ec8de3ee" integrity sha512-cujeIl5Ei8FC7UHf4/4Q3bRJOtdTe1vpJV/JEBYCggedmQ+2P8A2oz7eE+Vxi6OJ4nc0X+KZxXnBoH4QrEbmEQ== @@ -1313,6 +1320,19 @@ "@nodelib/fs.scandir" "2.1.4" fastq "^1.6.0" +"@open-wc/chai-dom-equals@^0.12.36": + version "0.12.36" + resolved "https://registry.yarnpkg.com/@open-wc/chai-dom-equals/-/chai-dom-equals-0.12.36.tgz#ed0eb56b9e98c4d7f7280facce6215654aae9f4c" + integrity sha512-Gt1fa37h4rtWPQGETSU4n1L678NmMi9KwHM1sH+JCGcz45rs8DBPx7MUVeGZ+HxRlbEI5t9LU2RGGv6xT2OlyA== + dependencies: + "@open-wc/semantic-dom-diff" "^0.13.16" + "@types/chai" "^4.1.7" + +"@open-wc/dedupe-mixin@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@open-wc/dedupe-mixin/-/dedupe-mixin-1.3.0.tgz#0df5d438285fc3482838786ee81895318f0ff778" + integrity sha512-UfdK1MPnR6T7f3svzzYBfu3qBkkZ/KsPhcpc3JYhsUY4hbpwNF9wEQtD4Z+/mRqMTJrKg++YSxIxE0FBhY3RIw== + "@open-wc/eslint-config@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@open-wc/eslint-config/-/eslint-config-4.2.0.tgz#ab5ef8df326544d5dc05fab41e6b45505885388b" @@ -1327,6 +1347,52 @@ eslint-plugin-no-only-tests "^2.4.0" eslint-plugin-wc "^1.2.0" +"@open-wc/scoped-elements@^2.0.0-next.0": + version "2.0.0-next.4" + resolved "https://registry.yarnpkg.com/@open-wc/scoped-elements/-/scoped-elements-2.0.0-next.4.tgz#d8294358e3e8ad2ba44200ab805549fde49245f6" + integrity sha512-BMd5n5BHLi3FBhwhPbBuN7pZdi8I1CIQn10aKLZtg9aplVhN2BG1rwr0ANebXJ6fdq8m1PE1wQAaCXYCcEBTEQ== + dependencies: + "@lit/reactive-element" "^1.0.0-rc.1" + "@open-wc/dedupe-mixin" "^1.3.0" + "@webcomponents/scoped-custom-element-registry" "0.0.2" + +"@open-wc/semantic-dom-diff@^0.13.16": + version "0.13.21" + resolved "https://registry.yarnpkg.com/@open-wc/semantic-dom-diff/-/semantic-dom-diff-0.13.21.tgz#718b9ec5f9a98935fc775e577ad094ae8d8b7dea" + integrity sha512-BONpjHcGX2zFa9mfnwBCLEmlDsOHzT+j6Qt1yfK3MzFXFtAykfzFjAgaxPetu0YbBlCfXuMlfxI4vlRGCGMvFg== + +"@open-wc/semantic-dom-diff@^0.19.5-next.0": + version "0.19.5-next.1" + resolved "https://registry.yarnpkg.com/@open-wc/semantic-dom-diff/-/semantic-dom-diff-0.19.5-next.1.tgz#2f17fdee63b31f2e3b4999b8d1980550bde1af33" + integrity sha512-iGj09LszYYfsXAo8mH1mkTmluWjq4lAzayX3DCyCos8L7F4nHNgVgzEuRgvoEJ6+XnT2UT70qA3Q4wN+dEqDOg== + dependencies: + "@types/chai" "^4.2.11" + "@web/test-runner-commands" "^0.5.7" + +"@open-wc/testing-helpers@^2.0.0-next.0": + version "2.0.0-next.0" + resolved "https://registry.yarnpkg.com/@open-wc/testing-helpers/-/testing-helpers-2.0.0-next.0.tgz#ece19e1c22ff91ae5f6ff2fae199719b7a7bfce7" + integrity sha512-94TL8IK05w1JyN8xt7t+vQBQYPdPy/JSJbWJ/ytvStou085SoDN6p1xCPh1PNhjm9LALc60nWM8qb2J2YRT8QA== + dependencies: + "@open-wc/scoped-elements" "^2.0.0-next.0" + lit "^2.0.0-rc.1" + +"@open-wc/testing@^3.0.0-next.2": + version "3.0.0-next.2" + resolved "https://registry.yarnpkg.com/@open-wc/testing/-/testing-3.0.0-next.2.tgz#09348d5ec6140824e1ed49fe6916605bf7cf7ec9" + integrity sha512-tQAihXnRYjSJrbgMJd5DpAubFHkUQlEe8ywgPDPIc3wtnOAuWoCgBRqG863WmK8AjQoJYZWaPBSxojEBJz81gA== + dependencies: + "@esm-bundle/chai" "^4.3.4" + "@open-wc/chai-dom-equals" "^0.12.36" + "@open-wc/semantic-dom-diff" "^0.19.5-next.0" + "@open-wc/testing-helpers" "^2.0.0-next.0" + "@types/chai" "^4.2.11" + "@types/chai-dom" "^0.0.9" + "@types/mocha" "^5.2.7" + "@types/sinon-chai" "^3.2.3" + chai-a11y-axe "^1.3.1" + mocha "^6.2.2" + "@rdf-esm/data-model@^0.5.1", "@rdf-esm/data-model@^0.5.3", "@rdf-esm/data-model@^0.5.4": version "0.5.4" resolved "https://registry.yarnpkg.com/@rdf-esm/data-model/-/data-model-0.5.4.tgz#bd0f7aba4415240387f26ef0cd05ebb6b444f47f" @@ -1610,6 +1676,34 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^7.0.4", "@sinonjs/fake-timers@^7.1.0", "@sinonjs/fake-timers@^7.1.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" + integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@sinonjs/samsam@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.0.2.tgz#a0117d823260f282c04bff5f8704bdc2ac6910bb" + integrity sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ== + dependencies: + "@sinonjs/commons" "^1.6.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== + "@tpluscode/eslint-config@^0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@tpluscode/eslint-config/-/eslint-config-0.1.1.tgz#5562e9753d4a4e9bd6ee4785baeaf9e6c7f42bfc" @@ -1665,6 +1759,18 @@ "@types/connect" "*" "@types/node" "*" +"@types/chai-dom@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/chai-dom/-/chai-dom-0.0.9.tgz#77379354efec2568284ca355fff6a4f85f5a66f4" + integrity sha512-jj4F2NJog2/GBYsyJ8+NvhnWUBbPY4MUAKLdPJE6+568rw12GGXvj0ycUuP5nndVrnJgozmJAoMTvxvjJATXWw== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.1.7", "@types/chai@^4.2.11", "@types/chai@^4.2.12": + version "4.2.21" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.21.tgz#9f35a5643129df132cf3b5c1ec64046ea1af0650" + integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== + "@types/clownface@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/clownface/-/clownface-1.2.0.tgz#d64baf0697872b9b516d3e305bff9b483f6dad8a" @@ -1672,6 +1778,14 @@ dependencies: "@types/rdf-js" "*" +"@types/co-body@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/co-body/-/co-body-5.1.1.tgz#82fdd9832e6b535aeff85b73af5cc62480b01bc3" + integrity sha512-0/6AjTfQc5OJUchOS4OHiXNPZVuk+5XvEC2vdcizw/bwx0yb0xY7TKSf8JYvQYZ/OJDiAEjWzxnMjGPnSVlPmA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/command-line-args@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/command-line-args/-/command-line-args-5.0.0.tgz#484e704d20dbb8754a8f091eee45cdd22bcff28c" @@ -1689,6 +1803,11 @@ resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.3.tgz#0aa116701955c2faa0717fc69cd1596095e49d96" integrity sha512-P1bffQfhD3O4LW0ioENXUhZ9OIa0Zn+P7M+pWgkCKaT53wVLSq0mrKksCID/FGHpFhRSxRGhgrQmfhRuzwtKdg== +"@types/convert-source-map@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/convert-source-map/-/convert-source-map-1.5.2.tgz#318dc22d476632a4855594c16970c6dc3ed086e7" + integrity sha512-tHs++ZeXer40kCF2JpE51Hg7t4HPa18B1b1Dzy96S0eCw8QKECNMYMfwa1edK/x8yCN0r4e6ewvLcc5CsVGkdg== + "@types/cookies@*": version "0.7.6" resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.6.tgz#71212c5391a976d3bae57d4b09fac20fc6bda504" @@ -1699,6 +1818,11 @@ "@types/keygrip" "*" "@types/node" "*" +"@types/debounce@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.2.0.tgz#9ee99259f41018c640b3929e1bb32c3dcecdb192" + integrity sha512-bWG5wapaWgbss9E238T0R6bfo5Fh3OkeoSt245CM7JJwVwpw6MEBCbIxLq5z8KzsE3uJhzcIuQkyiZmzV3M/Dw== + "@types/estree@*": version "0.0.46" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" @@ -1745,7 +1869,7 @@ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69" integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA== -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.3": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== @@ -1765,6 +1889,13 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@^7.0.3": version "7.0.7" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" @@ -1818,6 +1949,16 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== +"@types/mocha@^5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + +"@types/mocha@^8.2.0": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" + integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== + "@types/node@*": version "14.14.28" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b" @@ -1915,6 +2056,21 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sinon-chai@^3.2.3": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.5.tgz#df21ae57b10757da0b26f512145c065f2ad45c48" + integrity sha512-bKQqIpew7mmIGNRlxW6Zli/QVyc3zikpGzCa797B/tRnD9OtHvZ/ts8sYXV+Ilj9u3QRaUEM8xrjgd1gwm1BpQ== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*", "@types/sinon@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.2.tgz#f360d2f189c0fd433d14aeb97b9d705d7e4cc0e4" + integrity sha512-BHn8Bpkapj8Wdfxvh2jWIUoaYB/9/XhsL0oOvBfRagJtKlSl9NWPcFOz2lRukI9szwGxFtYZCTejJSqsGDbdmw== + dependencies: + "@sinonjs/fake-timers" "^7.1.0" + "@types/trusted-types@^1.0.1": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-1.0.6.tgz#569b8a08121d3203398290d602d84d73c8dcf5da" @@ -1925,6 +2081,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== +"@types/uuid@^8.3.0": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" + integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== + "@types/vfile@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-4.0.0.tgz#c32d13cbda319bc9f4ab3cacc0263b4ba1dd1ea3" @@ -1951,6 +2112,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" + integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== + dependencies: + "@types/node" "*" + "@typescript-eslint/eslint-plugin@^4.15.1": version "4.15.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz#835f64aa0a403e5e9e64c10ceaf8d05c3f015180" @@ -2021,6 +2189,13 @@ "@typescript-eslint/types" "4.15.1" eslint-visitor-keys "^2.0.0" +"@web/browser-logs@^0.2.1", "@web/browser-logs@^0.2.2": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@web/browser-logs/-/browser-logs-0.2.4.tgz#486518a950b8fa790d97218cc5a0b4efbd20ac5a" + integrity sha512-11DAAv8ZqbO267dwBLXtvmDoJXXucG5n+i9oQQEEVgbgXKOvK/7eqGhrSDKuZ7TTTkSci9fW7ZcuKFtaKskAIA== + dependencies: + errorstacks "^2.2.0" + "@web/config-loader@^0.1.3": version "0.1.3" resolved "https://registry.yarnpkg.com/@web/config-loader/-/config-loader-0.1.3.tgz#8325ea54f75ef2ee7166783e64e66936db25bff7" @@ -2052,6 +2227,30 @@ picomatch "^2.2.2" ws "^7.4.2" +"@web/dev-server-core@^0.3.12": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@web/dev-server-core/-/dev-server-core-0.3.13.tgz#ae54e38c0e27212d44a48776c0439230e7d04bef" + integrity sha512-bGJHPeFRWATNfuL9Pp2LfqhnmqhBCc5eOO5AWQa0X+WQAwHiFo6xZNfsvsnJ1gvxXgsE4jKBAGu9lQRisvFRFA== + dependencies: + "@types/koa" "^2.11.6" + "@types/ws" "^7.4.0" + "@web/parse5-utils" "^1.2.0" + chokidar "^3.4.3" + clone "^2.1.2" + es-module-lexer "^0.4.0" + get-stream "^6.0.0" + is-stream "^2.0.0" + isbinaryfile "^4.0.6" + koa "^2.13.0" + koa-etag "^4.0.0" + koa-send "^5.0.1" + koa-static "^5.0.0" + lru-cache "^6.0.0" + mime-types "^2.1.27" + parse5 "^6.0.1" + picomatch "^2.2.2" + ws "^7.4.2" + "@web/dev-server-esbuild@^0.2.11": version "0.2.11" resolved "https://registry.yarnpkg.com/@web/dev-server-esbuild/-/dev-server-esbuild-0.2.11.tgz#391b3cffc421ed6de8def21d6136ae71a69d06bc" @@ -2074,6 +2273,17 @@ rollup "^2.35.1" whatwg-url "^8.4.0" +"@web/dev-server-rollup@^0.3.7": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.3.8.tgz#87b916cb5ba33200883904dcf0415f569b0e6e3e" + integrity sha512-IoQh/mcqssyCL3nNB4dAwcV3VMZfwAcRw2TDFnY4bKnPnkZSOSFR3R+SuyvwhvvnG14NmnNE6RA2Lf7lt7AsmA== + dependencies: + "@web/dev-server-core" "^0.3.3" + chalk "^4.1.0" + parse5 "^6.0.1" + rollup "^2.35.1" + whatwg-url "^9.0.0" + "@web/dev-server-storybook@^0.3.5": version "0.3.5" resolved "https://registry.yarnpkg.com/@web/dev-server-storybook/-/dev-server-storybook-0.3.5.tgz#881a581721329fee3f1669e395710f9e34ceb87d" @@ -2100,6 +2310,27 @@ rollup-plugin-terser "^7.0.2" storybook-addon-markdown-docs "^1.0.1" +"@web/dev-server@^0.1.17": + version "0.1.20" + resolved "https://registry.yarnpkg.com/@web/dev-server/-/dev-server-0.1.20.tgz#a2b19dc0e1bbd52eb7ddcbf5d7eca7eb9938af26" + integrity sha512-jn+X91xfTlTtidQFPp/o9HvbYCdFMGwc7gA8NBHv+PTPSIu79wxQESV2DONKFMyR0RXshMvT3mwQwlIvPEzuBg== + dependencies: + "@babel/code-frame" "^7.12.11" + "@rollup/plugin-node-resolve" "^11.0.1" + "@types/command-line-args" "^5.0.0" + "@web/config-loader" "^0.1.3" + "@web/dev-server-core" "^0.3.12" + "@web/dev-server-rollup" "^0.3.7" + camelcase "^6.2.0" + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.1" + debounce "^1.2.0" + deepmerge "^4.2.2" + ip "^1.1.5" + open "^8.0.2" + portfinder "^1.0.28" + "@web/dev-server@^0.1.8": version "0.1.8" resolved "https://registry.yarnpkg.com/@web/dev-server/-/dev-server-0.1.8.tgz#94db0637c60003c2dc1e03017377fa1640b58967" @@ -2170,6 +2401,101 @@ resolved "https://registry.yarnpkg.com/@web/storybook-prebuilt/-/storybook-prebuilt-0.1.20.tgz#6d27f3387c462c7413967116d710bc16684d65b7" integrity sha512-mhpCGhqy5IyDF561Xx9PSckU6KBG6O88AwTU+I9gOp/MvHeMf//bSF9sYZ6Md8GD7T0e9aqMkD0sbDaCUDnyeg== +"@web/test-runner-chrome@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@web/test-runner-chrome/-/test-runner-chrome-0.10.1.tgz#200de4ec9ca2131b749788db1b892dae3c23672f" + integrity sha512-6c03MdW8UfeZHZSjQZk1po/2uN8aimVXft76PttGbd3M6EM98dN5uKBwz3cbPuy49XyqzwkhktrYhlmBZAtU8w== + dependencies: + "@web/test-runner-core" "^0.10.8" + "@web/test-runner-coverage-v8" "^0.4.5" + chrome-launcher "^0.14.0" + puppeteer-core "^9.1.0" + +"@web/test-runner-commands@^0.5.6", "@web/test-runner-commands@^0.5.7": + version "0.5.8" + resolved "https://registry.yarnpkg.com/@web/test-runner-commands/-/test-runner-commands-0.5.8.tgz#919231cdf6be31972bf6bf0eba48c9dd6ec38dd9" + integrity sha512-WLiQ8WQL/4YqR5kknGaor2F41O/je1C1QiCuIcO3LxPLoJuiJQ3KoYpAQ4pI13AwlBpzPcnSnISrypa/RpTFbA== + dependencies: + "@web/test-runner-core" "^0.10.14" + mkdirp "^1.0.4" + +"@web/test-runner-core@^0.10.14", "@web/test-runner-core@^0.10.19", "@web/test-runner-core@^0.10.8", "@web/test-runner-core@^0.10.9": + version "0.10.19" + resolved "https://registry.yarnpkg.com/@web/test-runner-core/-/test-runner-core-0.10.19.tgz#7cab7f2639bced3fc1909d489d65c4a1d1957011" + integrity sha512-Aj1sO/CT2kWw8r9BqRdP0D9TGsbReRDcrMI5SuhAoZJF4m8BGvox8WiQp2Zu0IyVFkuk6ZXFzsAnOJTVSVqB1w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@types/co-body" "^5.1.0" + "@types/convert-source-map" "^1.5.1" + "@types/debounce" "^1.2.0" + "@types/istanbul-lib-coverage" "^2.0.3" + "@types/istanbul-reports" "^3.0.0" + "@types/uuid" "^8.3.0" + "@web/browser-logs" "^0.2.1" + "@web/dev-server-core" "^0.3.12" + chalk "^4.1.0" + chokidar "^3.4.3" + cli-cursor "^3.1.0" + co-body "^6.1.0" + convert-source-map "^1.7.0" + debounce "^1.2.0" + dependency-graph "^0.11.0" + globby "^11.0.1" + ip "^1.1.5" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-report "^3.0.0" + istanbul-reports "^3.0.2" + log-update "^4.0.0" + open "^8.0.2" + picomatch "^2.2.2" + source-map "^0.7.3" + uuid "^8.3.2" + +"@web/test-runner-coverage-v8@^0.4.5": + version "0.4.7" + resolved "https://registry.yarnpkg.com/@web/test-runner-coverage-v8/-/test-runner-coverage-v8-0.4.7.tgz#df19c447d2afc9537f3b414593cbc44922deaf45" + integrity sha512-S0RRG3BQrpUoCq7qihnFx7p1ozMMyDhKOchBZcFDzzar0LpWbsNcDImYZhACgHv2QLabMRzwP95Vf9Tsf99p4A== + dependencies: + "@web/test-runner-core" "^0.10.9" + istanbul-lib-coverage "^3.0.0" + picomatch "^2.2.2" + v8-to-istanbul "^8.0.0" + +"@web/test-runner-mocha@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@web/test-runner-mocha/-/test-runner-mocha-0.7.3.tgz#7e23042241f480256c1f6a2890095a16eb3554ec" + integrity sha512-EbJydgh9Peo74SR0WjAEXs9X64ec41RaSXp4yXCup7jzvzH/5mQd2kZ/ga9F8Jh3zcKknR+s59JLVivgc5Ni7A== + dependencies: + "@types/mocha" "^8.2.0" + "@web/test-runner-core" "^0.10.8" + +"@web/test-runner@^0.13.15": + version "0.13.15" + resolved "https://registry.yarnpkg.com/@web/test-runner/-/test-runner-0.13.15.tgz#b2a7a64063950971744f312f75bb9dc83f482094" + integrity sha512-LxGVk0ixqTiecUK2LzqtuCzMO1kdIi+cce1+yaOKdoA7hre+XDNkrxT0ep6OEJjdgo1HL/uynXYE8MXeC5gkuw== + dependencies: + "@web/browser-logs" "^0.2.2" + "@web/config-loader" "^0.1.3" + "@web/dev-server" "^0.1.17" + "@web/test-runner-chrome" "^0.10.0" + "@web/test-runner-commands" "^0.5.6" + "@web/test-runner-core" "^0.10.19" + "@web/test-runner-mocha" "^0.7.3" + camelcase "^6.2.0" + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.1" + convert-source-map "^1.7.0" + diff "^5.0.0" + globby "^11.0.1" + portfinder "^1.0.28" + source-map "^0.7.3" + +"@webcomponents/scoped-custom-element-registry@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@webcomponents/scoped-custom-element-registry/-/scoped-custom-element-registry-0.0.2.tgz#c863d163cb39c60063808e5ae23e06a1766fbe5f" + integrity sha512-lKCoZfKoE3FHvmmj2ytaLBB8Grxp4HaxfSzaGlIZN6xXnOILfpCO0PFJkAxanefLGJWMho4kRY5PhgxWFhmSOw== + "@webcomponents/webcomponentsjs@^2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.5.0.tgz#61b27785a6ad5bfd68fa018201fe418b118cb38d" @@ -2222,6 +2548,13 @@ acorn@^7.4.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -2257,6 +2590,11 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2509,6 +2847,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -2541,6 +2884,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.5.1: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -2597,6 +2949,11 @@ breakword@^1.0.5: dependencies: wcwidth "^1.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + browserslist@^4.14.5, browserslist@^4.16.3: version "4.16.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" @@ -2608,16 +2965,34 @@ browserslist@^4.14.5, browserslist@^4.16.3: escalade "^3.1.1" node-releases "^1.1.70" +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer@^5.2.1, buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-modules@^3.0.0, builtin-modules@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" integrity sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA== +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2729,6 +3104,13 @@ ccount@^1.0.0, ccount@^1.0.3: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== +chai-a11y-axe@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/chai-a11y-axe/-/chai-a11y-axe-1.3.1.tgz#1889d2b639612ff4e9b9e40ff528442fd0191798" + integrity sha512-O+JJ+fELEvK/5SwFe9ltIk+qYz9p+zjnw/iUC1qNrlpgEPvTxScvyvQSU7eP73ixxHkCH1oNFAqkiM+MopbCEw== + dependencies: + axe-core "^4.0.2" + chalk@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2805,6 +3187,21 @@ chokidar@^3.4.3: optionalDependencies: fsevents "~2.3.1" +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-launcher@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.14.0.tgz#de8d8a534ccaeea0f36ea8dc12dd99e3169f3320" + integrity sha512-W//HpflaW6qBGrmuskup7g+XJZN6w03ko9QSIe5CtcTal2u0up5SeReK3Ll1Why4Ey8dPkv8XSodZyHPnGbVHQ== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -2906,6 +3303,16 @@ clownface@^1, clownface@^1.2.0: "@rdfjs/data-model" "^1.1.0" "@rdfjs/namespace" "^1.0.0" +co-body@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.1.0.tgz#d87a8efc3564f9bfe3aced8ef5cd04c7a8766547" + integrity sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ== + dependencies: + inflation "^2.0.0" + qs "^6.5.2" + raw-body "^2.3.3" + type-is "^1.6.16" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3057,6 +3464,13 @@ content-type@^1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +convert-source-map@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -3184,6 +3598,20 @@ debounce@^1.2.0: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3262,7 +3690,12 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -define-properties@^1.1.3: +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -3316,6 +3749,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +dependency-graph@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + destroy@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -3333,6 +3771,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== +devtools-protocol@0.0.869402: + version "0.0.869402" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.869402.tgz#03ade701761742e43ae4de5dc188bcd80f156d8d" + integrity sha512-VvlVYY+VDJe639yHs5PHISzdWTLL3Aw8rO4cvUtwvoxFd6FHbE4OpHHcde52M6096uYYazAmd4l0o5VuFRO2WA== + didyoumean2@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/didyoumean2/-/didyoumean2-4.1.0.tgz#f813cb7c82c249443e599be077f76e88f24b85e4" @@ -3342,6 +3785,16 @@ didyoumean2@4.1.0: leven "^3.1.0" lodash.deburr "^4.1.0" +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3466,7 +3919,7 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -3492,6 +3945,11 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +errorstacks@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/errorstacks/-/errorstacks-2.3.2.tgz#cab2c7c83e199a2b2862de3fea46f68372094166" + integrity sha512-cJp8qf5t2cXmVZJjZVrcU4ODFJeQOcUyjJEtPFtWO+3N6JPM6vCe4Sfv3cwIs/qS7gnUo/fvKX/mDCVQZq+P7A== + es-abstract@^1.18.0-next.1: version "1.18.0-next.2" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" @@ -3512,11 +3970,39 @@ es-abstract@^1.18.0-next.1: string.prototype.trimend "^1.0.3" string.prototype.trimstart "^1.0.3" +es-abstract@^1.18.0-next.2: + version "1.18.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" + integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.3" + is-string "^1.0.6" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + es-module-lexer@^0.3.13, es-module-lexer@^0.3.26: version "0.3.26" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.3.26.tgz#7b507044e97d5b03b01d4392c74ffeb9c177a83b" integrity sha512-Va0Q/xqtrss45hWzP8CZJwzGSZJjDM5/MJRE3IXXnUCcVLElR9BRaE9F62BopysASyc4nM3uwhSW7FFB9nlWAA== +es-module-lexer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e" + integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA== + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3546,11 +4032,16 @@ escape-html@^1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + eslint-config-airbnb-base@^14.0.0: version "14.2.1" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e" @@ -3921,6 +4412,17 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3977,6 +4479,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -4015,6 +4524,13 @@ find-replace@^3.0.0: dependencies: array-back "^3.0.1" +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -4030,13 +4546,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -4069,6 +4578,13 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + flatted@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" @@ -4105,6 +4621,11 @@ fresh@~0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" @@ -4162,7 +4683,7 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.1, get-intrinsic@^1.0.2: +get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -4249,6 +4770,18 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.2: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" @@ -4314,6 +4847,11 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -4339,6 +4877,11 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -4349,11 +4892,23 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-symbols@^1.0.0, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -4561,7 +5116,7 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" -he@^1.2.0: +he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -4571,6 +5126,11 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-minifier-terser@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" @@ -4607,6 +5167,17 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.7.2" +http-errors@1.7.3, http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-errors@^1.6.3, http-errors@^1.7.3: version "1.8.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" @@ -4628,17 +5199,6 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4648,6 +5208,14 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + human-id@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/human-id/-/human-id-1.0.2.tgz#e654d4b2b0d8b07e45da9f6020d8af17ec0a5df3" @@ -4663,13 +5231,18 @@ husky@^5.0.9: resolved "https://registry.yarnpkg.com/husky/-/husky-5.0.9.tgz#6d38706643d66ed395bcd4ee952d02e3f15eb3a3" integrity sha512-0SjcaY21a+IRdx7p7r/X33Vc09UR2m8SbP8yfkhUX2/jAmwcz+GR7i9jXkp2pP3GfX23JhMkVP6SWwXB18uXtg== -iconv-lite@^0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -4705,6 +5278,11 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +inflation@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" + integrity sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4713,7 +5291,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4728,6 +5306,15 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + intersection-observer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.0.tgz#6c84628f67ce8698e5f9ccf857d97718745837aa" @@ -4780,6 +5367,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.3.tgz#fc9d9e364210480675653ddaea0518528d49a581" + integrity sha512-ZU538ajmYJmzysE5yU4Y7uIrPQ2j704u+hXFiIPQExpqzzUbpe5jCPdTfmz7jXRxZdvjY3KZ3ZNenoXQovX+Dg== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -4787,12 +5379,20 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.0: +is-buffer@^2.0.0, is-buffer@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -4809,6 +5409,11 @@ is-callable@^1.1.4, is-callable@^1.2.2: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== +is-callable@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -4870,6 +5475,11 @@ is-docker@^2.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== +is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -4936,6 +5546,13 @@ is-negative-zero@^2.0.1: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -4990,6 +5607,14 @@ is-regex@^1.1.1: call-bind "^1.0.2" has-symbols "^1.0.1" +is-regex@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -5010,6 +5635,13 @@ is-string@^1.0.5: resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== +is-string@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + is-subdir@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/is-subdir/-/is-subdir-1.2.0.tgz#b791cd28fab5202e91a08280d51d9d7254fd20d4" @@ -5024,6 +5656,13 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5049,13 +5688,18 @@ is-word-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== -is-wsl@^2.1.1: +is-wsl@^2.1.1, is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -5088,6 +5732,28 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + jest-changed-files@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" @@ -5121,6 +5787,14 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.13.0, js-yaml@^3.13.1, js-yaml@^3.6.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5225,6 +5899,11 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +just-extend@^4.0.2: + version "4.2.1" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" + integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== + keygrip@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" @@ -5342,6 +6021,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lighthouse-logger@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.3.0.tgz#ba6303e739307c4eee18f08249524e7dafd510db" + integrity sha512-BbqAKApLb9ywUli+0a+PcV04SyJ/N1q/8qgCNe6U97KbPCS1BTksEuHFLYdvc8DltuhfxIUBqDZsC0bBGtl3lA== + dependencies: + debug "^2.6.9" + marky "^1.2.2" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -5424,7 +6111,7 @@ lit-html@^2.0.0-rc.3: dependencies: "@types/trusted-types" "^1.0.1" -lit@^2.0.0-rc.2: +lit@^2.0.0-rc.1, lit@^2.0.0-rc.2: version "2.0.0-rc.2" resolved "https://registry.yarnpkg.com/lit/-/lit-2.0.0-rc.2.tgz#724a2d621aa098001d73bf7106f3a72b7b5948ef" integrity sha512-BOCuoJR04WaTV8UqTKk09cNcQA10Aq2LCcBOiHuF7TzWH5RNDsbCBP5QM9sLBSotGTXbDug/gFO08jq6TbyEtw== @@ -5504,6 +6191,11 @@ lodash.deburr@^4.1.0: resolved "https://registry.yarnpkg.com/lodash.deburr/-/lodash.deburr-4.1.0.tgz#ddb1bbb3ef07458c0177ba07de14422cb033ff9b" integrity sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s= +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -5529,6 +6221,13 @@ lodash@^4.17.4: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + log-symbols@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -5595,6 +6294,13 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.4" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -5627,6 +6333,11 @@ markdown-table@^1.1.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== +marky@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.2.tgz#4456765b4de307a13d263a69b0c79bf226e68323" + integrity sha512-k1dB2HNeaNyORco8ulVEhctyEGkKHb2YWAhDsxeFlW2nROIirsctBYzKwwS3Vza+sKTS1zO4Z+n9/+9WbGLIxQ== + mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" @@ -5793,7 +6504,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -5827,6 +6538,18 @@ mixme@^0.4.0: resolved "https://registry.yarnpkg.com/mixme/-/mixme-0.4.0.tgz#a1aee27f0d63cc905e1cc6ddc98abf94d414435e" integrity sha512-B4Sm1CDC5+ov5AYxSkyeT5HLtiDgNOLKwFlq34wr8E2O3zRdTvQiLzo599Jt9cir6VJrSenOlgvdooVYCQJIYw== +mkdirp-classic@^0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + +mkdirp@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" + integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== + dependencies: + minimist "^1.2.5" + mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5834,11 +6557,50 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.5" +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mocha@^6.2.2: + version "6.2.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.3.tgz#e648432181d8b99393410212664450a4c1e31912" + integrity sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.4" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -5889,6 +6651,17 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +nise@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.0.tgz#713ef3ed138252daef20ec035ab62b7a28be645c" + integrity sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@sinonjs/fake-timers" "^7.0.4" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" + path-to-regexp "^1.7.0" + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -5897,6 +6670,19 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -5955,12 +6741,17 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" + integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== + object-inspect@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -5972,6 +6763,16 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" @@ -5992,6 +6793,15 @@ object.entries@^1.1.2: es-abstract "^1.18.0-next.1" has "^1.0.3" +object.getownpropertydescriptors@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" + integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -6043,6 +6853,15 @@ open@^7.3.0: is-docker "^2.0.0" is-wsl "^2.1.1" +open@^8.0.2: + version "8.2.1" + resolved "https://registry.yarnpkg.com/open/-/open-8.2.1.tgz#82de42da0ccbf429bc12d099dad2e0975e14e8af" + integrity sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -6296,6 +7115,13 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -6317,6 +7143,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -6418,7 +7249,7 @@ prismjs@~1.17.0: optionalDependencies: clipboard "^2.0.0" -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -6435,6 +7266,11 @@ property-information@^5.0.0, property-information@^5.2.0, property-information@^ dependencies: xtend "^4.0.0" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -6458,6 +7294,31 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +puppeteer-core@^9.1.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-9.1.1.tgz#0c189c3275967d65c39270e6b146e559baca3d47" + integrity sha512-zbedbitVIGhmgz0nt7eIdLsnaoVZSlNJfBivqm2w67T8LR2bU1dvnruDZ8nQO0zn++Iet7zHbAOdnuS5+H2E7A== + dependencies: + debug "^4.1.0" + devtools-protocol "0.0.869402" + extract-zip "^2.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.1" + pkg-dir "^4.2.0" + progress "^2.0.1" + proxy-from-env "^1.1.0" + rimraf "^3.0.2" + tar-fs "^2.0.0" + unbzip2-stream "^1.3.3" + ws "^7.2.3" + +qs@^6.5.2: + version "6.10.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" + integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -6480,6 +7341,16 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +raw-body@^2.3.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" + integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== + dependencies: + bytes "3.1.0" + http-errors "1.7.3" + iconv-lite "0.4.24" + unpipe "1.0.0" + rdf-canonize@^1.0.2: version "1.2.0" resolved "https://registry.yarnpkg.com/rdf-canonize/-/rdf-canonize-1.2.0.tgz#9872b2cc6ed92a9969e834f9f042addaf0d4f7f9" @@ -6603,7 +7474,7 @@ read-yaml-file@^1.1.0: pify "^4.0.1" strip-bom "^3.0.0" -readable-stream@^3.0.2, readable-stream@^3.3.0, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.3.0, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -7099,7 +7970,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -7109,7 +7980,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^6.1.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -7182,11 +8053,32 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +sinon@^11.1.2: + version "11.1.2" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-11.1.2.tgz#9e78850c747241d5c59d1614d8f9cbe8840e8674" + integrity sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw== + dependencies: + "@sinonjs/commons" "^1.8.3" + "@sinonjs/fake-timers" "^7.1.2" + "@sinonjs/samsam" "^6.0.2" + diff "^5.0.0" + nise "^5.1.0" + supports-color "^7.2.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -7285,7 +8177,7 @@ source-map@^0.6.0, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: +source-map@^0.7.3, source-map@~0.7.2: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== @@ -7434,7 +8326,7 @@ string-to-stream@^3.0.1: dependencies: readable-stream "^3.4.0" -string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -7468,6 +8360,14 @@ string.prototype.trimend@^1.0.3: call-bind "^1.0.0" define-properties "^1.1.3" +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + string.prototype.trimstart@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" @@ -7476,6 +8376,14 @@ string.prototype.trimstart@^1.0.3: call-bind "^1.0.0" define-properties "^1.1.3" +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7567,6 +8475,11 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -7586,6 +8499,13 @@ style-to-object@^0.2.1: dependencies: inline-style-parser "0.1.1" +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -7598,7 +8518,7 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -7630,6 +8550,27 @@ table@^6.0.4: slice-ansi "^4.0.0" string-width "^4.2.0" +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -7744,6 +8685,13 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +tr46@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" + integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== + dependencies: + punycode "^2.1.1" + trim-lines@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.3.tgz#839514be82428fd9e7ec89e35081afe8f6f93115" @@ -7849,6 +8797,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" @@ -7907,6 +8860,24 @@ ua-parser-js@^0.7.23: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.24.tgz#8d3ecea46ed4f1f1d63ec25f17d8568105dc027c" integrity sha512-yo+miGzQx5gakzVK3QFfN0/L9uVhosXBBO7qmnk7c2iw1IhL212wfA3zbnI54B0obGwC/5NWub/iT9sReMx+Fw== +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +unbzip2-stream@^1.3.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + underscore@^1.9.1: version "1.12.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.0.tgz#4814940551fc80587cef7840d1ebb0f16453be97" @@ -8084,6 +9055,11 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unpipe@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -8119,11 +9095,25 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== +v8-to-istanbul@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz#4229f2a99e367f3f018fa1d5c2b8ec684667c69c" + integrity sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + validate-element-name@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/validate-element-name/-/validate-element-name-2.1.1.tgz#8ff75f7da69f73e7c510588362130508b7ac644e" @@ -8264,6 +9254,25 @@ whatwg-url@^8.4.0: tr46 "^2.0.2" webidl-conversions "^6.1.0" +whatwg-url@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-9.1.0.tgz#1b112cf237d72cd64fa7882b9c3f6234a1c3050d" + integrity sha512-CQ0UcrPHyomtlOCot1TL77WyMIm/bCwrJ2D6AOKGwEczU9EpyoqAokfqrf/MioU9kHcMsmJZcg1egXix2KYEsA== + dependencies: + tr46 "^2.1.0" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -8277,7 +9286,7 @@ which-pm@2.0.0: load-yaml-file "^0.2.0" path-exists "^4.0.0" -which@^1.2.9: +which@1.3.1, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -8291,6 +9300,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + widest-line@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" @@ -8343,6 +9359,11 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +ws@^7.2.3: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== + ws@^7.4.2: version "7.4.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd" @@ -8393,7 +9414,7 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== -yargs-parser@^13.1.2: +yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== @@ -8409,7 +9430,16 @@ yargs-parser@^18.1.2, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^13.0.0: +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.2, yargs@^13.0.0, yargs@^13.3.0: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -8442,6 +9472,14 @@ yargs@^15.1.0, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + ylru@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f"