diff --git a/.gitignore b/.gitignore index d5f19d8..948d314 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +.idea +cypress/screenshots node_modules package-lock.json diff --git a/README.md b/README.md index 1dbc665..8093a47 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,103 @@ # Codemeta Generator This repository contains a (client-side) web application to generate CodeMeta documents (aka. `codemeta.json`). The [CodeMeta initiative](https://github.com/codemeta/codemeta) is a Free and Open Source academic collaboration creating a minimal metadata schema for research software and code. The academic community recommands on adding a codemeta.json file in the root directory of your repository. With this linked data metadata file, you can easily declare the authorship, include contextual information and link to other research outputs (publications, data, etc.). Also, the `codemeta.json` file in your source code is indexed in the Software Heritage (SWH) archive, which will improve findability in searches. ### References - [SWH guidelines](https://www.softwareheritage.org/save-and-reference-research-software/) for research software. - [SWH blog post](https://www.softwareheritage.org/2019/05/28/mining-software-metadata-for-80-m-projects-and-even-more/) about metadata indexation. - [Dan S. Katz's blog post](https://danielskatzblog.wordpress.com/2017/09/25/software-heritage-and-repository-metadata-a-software-citation-solution/) about including metadata in your repository. - FORCE11's Software Citation Implementation WG [repository](https://github.com/force11/force11-sciwg) - RDA & FORCE11's joint Software Source Code Identification WG [repository](https://github.com/force11/force11-rda-scidwg) ## Specifications ### Use case 1. create a complete codemeta.json file from scratch 2. aggregate existing information and add complementary information to a codemeta.json file ### Functionalities - helpers while completing the form, for example a reference list of spdx licenses - a validation mechanism after submission - the possibility to use all the codeMeta terms and schema.org terms - accessible from multiple platforms (web browsers or OS) - (extra) the possibility to correct the output after validation as part of the creation process This tool was initially prepared for the [FORCE19 Hackathon](https://github.com/force11/force11-rda-scidwg/tree/master/hackathon/FORCE2019). ## Code contributions. This section only applies to developers who want to contribute to the Codemeta Generator. If you only want to use it, you can use [the hosted version](https://codemeta.github.io/codemeta-generator/) instead. ### Code guidelines This application is designed to work on popular modern browsers (Firefox, Chromium/Google Chrome, Edge, Safari). Check [Caniuse](https://caniuse.com/) for availability of features for these browsers. To keep the architecture simple, we serve javascript files directly to browsers, without a compiler or transpiler; and do not use third-party dependencies for now. ### Running local changes To run Codemeta Generator, you just need an HTTP server serving the files (nginx, apache2, etc.). The simplest way is probably to use Python's HTTP server: ``` git clone https://github.com/codemeta/codemeta-generator cd codemeta-generator python3 -m http.server ``` then open [http://localhost:8000/](http://localhost:8000/) in your web browser. ### Automatic testing In addition to manual testing, we have automated tests to check for bugs quickly, using [Cypress](https://www.cypress.io/). To run them, first install Cypress: ``` sudo apt install npm # or the equivalent on your system -npm install cypress -$(npm bin)/cypress install +npx cypress@9.7.0 install ``` Then, run the tests: ``` -$(npm bin)/cypress run +npx cypress@9.7.0 run ``` ## Contributed by ![Image description](https://annex.softwareheritage.org/public/logo/software-heritage-logo-title-motto.svg) diff --git a/contexts/codemeta-2.0.jsonld b/contexts/codemeta-2.0.jsonld new file mode 100644 index 0000000..ea7283f --- /dev/null +++ b/contexts/codemeta-2.0.jsonld @@ -0,0 +1,88 @@ +{ + "@context": { + "type": "@type", + "id": "@id", + "schema":"http://schema.org/", + "codemeta": "https://codemeta.github.io/terms/", + "Organization": {"@id": "schema:Organization"}, + "Person": {"@id": "schema:Person"}, + "Review": {"@id": "schema:Review"}, + "Role": {"@id": "schema:Role"}, + "SoftwareSourceCode": {"@id": "schema:SoftwareSourceCode"}, + "SoftwareApplication": {"@id": "schema:SoftwareApplication"}, + "Text": {"@id": "schema:Text"}, + "URL": {"@id": "schema:URL"}, + "address": { "@id": "schema:address"}, + "affiliation": { "@id": "schema:affiliation"}, + "applicationCategory": { "@id": "schema:applicationCategory", "@type": "@id"}, + "applicationSubCategory": { "@id": "schema:applicationSubCategory", "@type": "@id"}, + "citation": { "@id": "schema:citation"}, + "codeRepository": { "@id": "schema:codeRepository", "@type": "@id"}, + "contributor": { "@id": "schema:contributor"}, + "copyrightHolder": { "@id": "schema:copyrightHolder"}, + "copyrightYear": { "@id": "schema:copyrightYear"}, + "dateCreated": {"@id": "schema:dateCreated", "@type": "schema:Date" }, + "dateModified": {"@id": "schema:dateModified", "@type": "schema:Date" }, + "datePublished": {"@id": "schema:datePublished", "@type": "schema:Date" }, + "description": { "@id": "schema:description"}, + "downloadUrl": { "@id": "schema:downloadUrl", "@type": "@id"}, + "email": { "@id": "schema:email"}, + "editor": { "@id": "schema:editor"}, + "encoding": { "@id": "schema:encoding"}, + "endDate": { "@id": "schema:endDate"}, + "familyName": { "@id": "schema:familyName"}, + "fileFormat": { "@id": "schema:fileFormat", "@type": "@id"}, + "fileSize": { "@id": "schema:fileSize"}, + "funder": { "@id": "schema:funder"}, + "givenName": { "@id": "schema:givenName"}, + "hasPart": { "@id": "schema:hasPart" }, + "identifier": { "@id": "schema:identifier", "@type": "@id"}, + "installUrl": { "@id": "schema:installUrl", "@type": "@id"}, + "isAccessibleForFree": { "@id": "schema:isAccessibleForFree"}, + "isPartOf": { "@id": "schema:isPartOf"}, + "keywords": { "@id": "schema:keywords"}, + "license": { "@id": "schema:license", "@type": "@id"}, + "memoryRequirements": { "@id": "schema:memoryRequirements", "@type": "@id"}, + "name": { "@id": "schema:name"}, + "operatingSystem": { "@id": "schema:operatingSystem"}, + "permissions": { "@id": "schema:permissions"}, + "position": { "@id": "schema:position"}, + "processorRequirements": { "@id": "schema:processorRequirements"}, + "producer": { "@id": "schema:producer"}, + "programmingLanguage": { "@id": "schema:programmingLanguage"}, + "provider": { "@id": "schema:provider"}, + "publisher": { "@id": "schema:publisher"}, + "relatedLink": { "@id": "schema:relatedLink", "@type": "@id"}, + "review": { "@id": "schema:review", "@type": "@id" }, + "reviewAspect": { "@id": "schema:reviewAspect" }, + "reviewBody": { "@id": "schema:reviewBody" }, + "releaseNotes": { "@id": "schema:releaseNotes"}, + "roleName": { "@id": "schema:roleName"}, + "runtimePlatform": { "@id": "schema:runtimePlatform"}, + "sameAs": { "@id": "schema:sameAs", "@type": "@id"}, + "softwareHelp": { "@id": "schema:softwareHelp"}, + "softwareRequirements": { "@id": "schema:softwareRequirements", "@type": "@id"}, + "softwareVersion": { "@id": "schema:softwareVersion"}, + "sponsor": { "@id": "schema:sponsor"}, + "startDate": { "@id": "schema:startDate"}, + "storageRequirements": { "@id": "schema:storageRequirements", "@type": "@id"}, + "supportingData": { "@id": "schema:supportingData"}, + "targetProduct": { "@id": "schema:targetProduct"}, + "url": { "@id": "schema:url", "@type": "@id"}, + "version": { "@id": "schema:version"}, + "author": { "@id": "schema:author", "@container": "@list" }, + + "softwareSuggestions": { "@id": "codemeta:softwareSuggestions", "@type": "@id"}, + "continuousIntegration": { "@id": "codemeta:continuousIntegration", "@type": "@id"}, + "buildInstructions": { "@id": "codemeta:buildInstructions", "@type": "@id"}, + "developmentStatus": { "@id": "codemeta:developmentStatus", "@type": "@id"}, + "embargoEndDate": { "@id":"codemeta:embargoEndDate", "@type": "schema:Date" }, + "funding": { "@id": "codemeta:funding" }, + "readme": { "@id":"codemeta:readme", "@type": "@id" }, + "issueTracker": { "@id":"codemeta:issueTracker", "@type": "@id" }, + "referencePublication": { "@id": "codemeta:referencePublication", "@type": "@id"}, + "maintainer": { "@id": "codemeta:maintainer" }, + "hasSourceCode": { "@id": "codemeta:hasSourceCode", "@type": "@id"}, + "isSourceCodeOf": { "@id": "codemeta:isSourceCodeOf", "@type": "@id"} + } +} diff --git a/contexts/codemeta-2.0.txt b/contexts/codemeta-2.0.txt new file mode 100644 index 0000000..1f9acfc --- /dev/null +++ b/contexts/codemeta-2.0.txt @@ -0,0 +1,2 @@ +Matthew B. Jones, Carl Boettiger, Abby Cabunoc Mayes, Arfon Smith, Peter Slaughter, Kyle Niemeyer, Yolanda Gil, Martin Fenner, Krzysztof Nowak, Mark Hahnel, Luke Coy, Alice Allen, Mercè Crosas, Ashley Sands, Neil Chue Hong, Patricia Cruse, Daniel S. Katz, Carole Goble. 2017. CodeMeta: an exchange schema for software metadata. Version 2.0. KNB Data Repository. doi:10.5063/schema/codemeta-2.0 +https://archive.softwareheritage.org/swh:1:cnt:ecba88bee7bac07a81a6f45414f4f57ce5eb2d29;origin=https://github.com/codemeta/codemeta;visit=swh:1:snp:a35573dd8a59795b7d81055234352efd8b08a603;anchor=swh:1:rev:dbc58ffa8b088ae1b09ad335852d9767c402983d;path=/codemeta.jsonld \ No newline at end of file diff --git a/cypress/integration/basics.js b/cypress/integration/basics.js index 3fbc7f6..3dafb40 100644 --- a/cypress/integration/basics.js +++ b/cypress/integration/basics.js @@ -1,243 +1,243 @@ /** * Copyright (C) 2020 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ /* * Tests the basic features of the application. */ "use strict"; describe('JSON Generation', function() { beforeEach(function() { /* Clear the session storage, as it is used to restore field data; * and we don't want a test to load data from the previous test. */ cy.window().then((win) => { win.sessionStorage.clear() }) cy.visit('./index.html'); }); it('works just from the software name', function() { cy.get('#name').type('My Test Software'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", }); }); it('works just from all main fields when using only one license', function() { cy.get('#name').type('My Test Software'); cy.get('#description').type('This is a\ngreat piece of software'); cy.get('#dateCreated').type('2019-10-02'); cy.get('#datePublished').type('2020-01-01'); cy.get('#license').type('AGPL-3.0'); cy.get("#license").type('{enter}'); cy.get('#generateCodemeta').click(); cy.get("#license").should('have.value', ''); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "license": "https://spdx.org/licenses/AGPL-3.0", "dateCreated": "2019-10-02", "datePublished": "2020-01-01", "name": "My Test Software", "description": "This is a\ngreat piece of software", }); }); it('works just from all main fields when using multiple licenses', function() { cy.get('#name').type('My Test Software'); cy.get('#description').type('This is a\ngreat piece of software'); cy.get('#dateCreated').type('2019-10-02'); cy.get('#datePublished').type('2020-01-01'); cy.get('#license').type('AGPL-3.0'); cy.get("#license").type('{enter}'); cy.get('#license').type('MIT'); cy.get("#license").type('{enter}'); cy.get('#generateCodemeta').click(); cy.get("#license").should('have.value', ''); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "license": ["https://spdx.org/licenses/AGPL-3.0", "https://spdx.org/licenses/MIT"], "dateCreated": "2019-10-02", "datePublished": "2020-01-01", "name": "My Test Software", "description": "This is a\ngreat piece of software", }); }); it('works when choosing licenses without the keyboard', function() { cy.get('#name').type('My Test Software'); cy.get('#description').type('This is a\ngreat piece of software'); cy.get('#dateCreated').type('2019-10-02'); cy.get('#datePublished').type('2020-01-01'); cy.get('#license').type('AGPL-3.0'); // no cy.get("#license").type('{enter}'); here cy.get('#generateCodemeta').click(); cy.get("#license").should('have.value', ''); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "license": "https://spdx.org/licenses/AGPL-3.0", "dateCreated": "2019-10-02", "datePublished": "2020-01-01", "name": "My Test Software", "description": "This is a\ngreat piece of software", }); }); }); describe('JSON Import', function() { it('works just from the software name', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#name').should('have.value', 'My Test Software'); }); it('works just from all main fields when using license as string', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "license": "https://spdx.org/licenses/AGPL-3.0", "dateCreated": "2019-10-02", "datePublished": "2020-01-01", "name": "My Test Software", "description": "This is a\ngreat piece of software", })) ); cy.get('#importCodemeta').click(); cy.get('#name').should('have.value', 'My Test Software'); cy.get('#description').should('have.value', 'This is a\ngreat piece of software'); cy.get('#dateCreated').should('have.value', '2019-10-02'); cy.get('#datePublished').should('have.value', '2020-01-01'); cy.get('#license').should('have.value', ''); cy.get("#selected-licenses").children().should('have.length', 1); cy.get("#selected-licenses").children().first().children().first().should('have.text', 'AGPL-3.0'); }); it('works just from all main fields when using license as array', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "license": ["https://spdx.org/licenses/AGPL-3.0", "https://spdx.org/licenses/MIT"], "dateCreated": "2019-10-02", "datePublished": "2020-01-01", "name": "My Test Software", "description": "This is a\ngreat piece of software", })) ); cy.get('#importCodemeta').click(); cy.get('#name').should('have.value', 'My Test Software'); cy.get('#description').should('have.value', 'This is a\ngreat piece of software'); cy.get('#dateCreated').should('have.value', '2019-10-02'); cy.get('#datePublished').should('have.value', '2020-01-01'); cy.get('#license').should('have.value', ''); cy.get("#selected-licenses").children().should('have.length', 2); cy.get("#selected-licenses").children().eq(0).children().first().should('have.text', 'AGPL-3.0'); cy.get("#selected-licenses").children().eq(1).children().first().should('have.text', 'MIT'); }); it('errors on invalid type', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "foo", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); // Should still be imported as much as possible cy.get('#name').should('have.value', 'My Test Software'); // But must display an error cy.get('#errorMessage').should('have.text', 'Wrong document type: must be "SoftwareSourceCode"/"SoftwareApplication", not "foo"'); }); it('allows singleton array as context', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": ["https://doi.org/10.5063/schema/codemeta-2.0"], "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#name').should('have.value', 'My Test Software'); }); it('errors on invalid context URL', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-100000", "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#errorMessage').should('have.text', '@context must be "https://doi.org/10.5063/schema/codemeta-2.0", not "https://doi.org/10.5063/schema/codemeta-100000"'); }); it('errors on invalid context URL in array', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": ["https://doi.org/10.5063/schema/codemeta-100000"], "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#errorMessage').should('have.text', '@context must be "https://doi.org/10.5063/schema/codemeta-2.0", not ["https://doi.org/10.5063/schema/codemeta-100000"]'); }); it('errors nicely when there are other contexts', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": [ "https://doi.org/10.5063/schema/codemeta-2.0", "https://schema.org/", ], "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#errorMessage').should('have.text', 'Multiple values in @context are not supported (@context should be "https://doi.org/10.5063/schema/codemeta-2.0", not ["https://doi.org/10.5063/schema/codemeta-2.0","https://schema.org/"])'); }); }); diff --git a/cypress/integration/persons.js b/cypress/integration/persons.js index a296afc..e4e0182 100644 --- a/cypress/integration/persons.js +++ b/cypress/integration/persons.js @@ -1,424 +1,424 @@ /** * Copyright (C) 2020 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ /* * Tests the author/contributor dynamic fieldsets */ "use strict"; describe('Zero author', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", }); }); it('can be imported from no list', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", })) ); cy.get('#importCodemeta').click(); cy.get('#author_nb').should('have.value', '0'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('not.exist'); }); it('can be imported from empty list', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "author": [], })) ); cy.get('#importCodemeta').click(); cy.get('#author_nb').should('have.value', '0'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('not.exist'); }); }); describe('One full author', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#author_nb').should('have.value', '0'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('not.exist'); cy.get('#author_1_givenName').should('not.exist'); cy.get('#author_add').click(); cy.get('#author_nb').should('have.value', '1'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('exist'); cy.get('#author_2').should('not.exist'); cy.get('#author_1_givenName').should('have.value', ''); cy.get('#author_1_familyName').should('have.value', ''); cy.get('#author_1_email').should('have.value', ''); cy.get('#author_1_id').should('have.value', ''); cy.get('#author_1_affiliation').should('have.value', ''); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_familyName').type('Doe'); cy.get('#author_1_email').type('jdoe@example.org'); cy.get('#author_1_id').type('http://example.org/~jdoe'); cy.get('#author_1_affiliation').type('http://example.org/'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { - "@type": "Person", - "@id": "http://example.org/~jdoe", + "type": "Person", + "id": "http://example.org/~jdoe", "givenName": "Jane", "familyName": "Doe", "email": "jdoe@example.org", "affiliation": { - "@type": "Organization", - "@id": "http://example.org/", + "type": "Organization", + "id": "http://example.org/", } } ], }); }); it('can be imported', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { "@type": "Person", "@id": "http://example.org/~jdoe", "givenName": "Jane", "familyName": "Doe", "email": "jdoe@example.org", "affiliation": { "@type": "Organization", "@id": "http://example.org/", } } ], })) ); cy.get('#importCodemeta').click(); cy.get('#author_nb').should('have.value', '1'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('exist'); cy.get('#author_2').should('not.exist'); cy.get('#author_1_givenName').should('have.value', 'Jane'); cy.get('#author_1_familyName').should('have.value', 'Doe'); cy.get('#author_1_email').should('have.value', 'jdoe@example.org'); cy.get('#author_1_id').should('have.value', 'http://example.org/~jdoe'); cy.get('#author_1_affiliation').should('have.value', 'http://example.org/'); }); }); describe('Affiliation id', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('http://example.org/'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { - "@type": "Person", + "type": "Person", "givenName": "Jane", "affiliation": { - "@type": "Organization", - "@id": "http://example.org/", + "type": "Organization", + "id": "http://example.org/", } } ], }); }); it('can be imported', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { "@type": "Person", "@id": "http://example.org/~jdoe", "givenName": "Jane", "familyName": "Doe", "email": "jdoe@example.org", "affiliation": { "@type": "Organization", "@id": "http://example.org/", } } ], })) ); cy.get('#importCodemeta').click(); cy.get('#author_nb').should('have.value', '1'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('exist'); cy.get('#author_2').should('not.exist'); cy.get('#author_1_affiliation').should('have.value', 'http://example.org/'); }); }); describe('Affiliation name', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { - "@type": "Person", + "type": "Person", "givenName": "Jane", "affiliation": { - "@type": "Organization", + "type": "Organization", "name": "Example Org", } } ], }); }); it('can be imported', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { "@type": "Person", "@id": "http://example.org/~jdoe", "givenName": "Jane", "familyName": "Doe", "email": "jdoe@example.org", "affiliation": { "@type": "Organization", "name": "Example Org", } } ], })) ); cy.get('#importCodemeta').click(); cy.get('#author_nb').should('have.value', '1'); cy.get('#author_0').should('not.exist'); cy.get('#author_1').should('exist'); cy.get('#author_2').should('not.exist'); cy.get('#author_1_affiliation').should('have.value', 'Example Org'); }); }); describe('Author order change', function() { it('is a noop with a single author', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); - cy.get('#author_1_moveToRight').click() + cy.get('#author_1_moveToRight').click(); cy.get('#author_1_givenName').should('have.value', 'Jane'); cy.get('#author_1_affiliation').should('have.value', 'Example Org'); - cy.get('#author_1_moveToLeft').click() + cy.get('#author_1_moveToLeft').click(); cy.get('#author_1_givenName').should('have.value', 'Jane'); cy.get('#author_1_affiliation').should('have.value', 'Example Org'); }); it('flips two authors', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); cy.get('#author_2_givenName').type('John'); cy.get('#author_2_familyName').type('Doe'); cy.get('#author_3_givenName').type('Alex'); - cy.get('#author_1_moveToRight').click() + cy.get('#author_1_moveToRight').click(); cy.get('#author_1_givenName').should('have.value', 'John'); cy.get('#author_1_familyName').should('have.value', 'Doe'); cy.get('#author_1_affiliation').should('have.value', ''); cy.get('#author_2_givenName').should('have.value', 'Jane'); cy.get('#author_2_familyName').should('have.value', ''); cy.get('#author_2_affiliation').should('have.value', 'Example Org'); cy.get('#author_3_givenName').should('have.value', 'Alex'); cy.get('#author_3_familyName').should('have.value', ''); cy.get('#author_3_affiliation').should('have.value', ''); }); it('updates generated Codemeta', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); cy.get('#author_2_givenName').type('John'); cy.get('#author_2_familyName').type('Doe'); cy.get('#generateCodemeta').click(); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { - "@type": "Person", + "type": "Person", "givenName": "Jane", "affiliation": { - "@type": "Organization", + "type": "Organization", "name": "Example Org", } }, { - "@type": "Person", + "type": "Person", "givenName": "John", "familyName": "Doe", }, ], }); cy.get('#author_1_moveToRight').click(); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "author": [ { - "@type": "Person", + "type": "Person", "givenName": "John", "familyName": "Doe", }, { - "@type": "Person", + "type": "Person", "givenName": "Jane", "affiliation": { - "@type": "Organization", + "type": "Organization", "name": "Example Org", } }, ], }); }); it('wraps around to the right', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); cy.get('#author_2_givenName').type('John'); cy.get('#author_2_familyName').type('Doe'); cy.get('#author_3_givenName').type('Alex'); cy.get('#author_1_moveToLeft').click() cy.get('#author_1_givenName').should('have.value', 'Alex'); cy.get('#author_1_familyName').should('have.value', ''); cy.get('#author_1_affiliation').should('have.value', ''); cy.get('#author_2_givenName').should('have.value', 'John'); cy.get('#author_2_familyName').should('have.value', 'Doe'); cy.get('#author_2_affiliation').should('have.value', ''); cy.get('#author_3_givenName').should('have.value', 'Jane'); cy.get('#author_3_familyName').should('have.value', ''); cy.get('#author_3_affiliation').should('have.value', 'Example Org'); }); it('wraps around to the left', function() { cy.get('#name').type('My Test Software'); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_add').click(); cy.get('#author_1_givenName').type('Jane'); cy.get('#author_1_affiliation').type('Example Org'); cy.get('#author_2_givenName').type('John'); cy.get('#author_2_familyName').type('Doe'); cy.get('#author_3_givenName').type('Alex'); cy.get('#author_3_moveToRight').click() cy.get('#author_1_givenName').should('have.value', 'Alex'); cy.get('#author_1_familyName').should('have.value', ''); cy.get('#author_1_affiliation').should('have.value', ''); cy.get('#author_2_givenName').should('have.value', 'John'); cy.get('#author_2_familyName').should('have.value', 'Doe'); cy.get('#author_2_affiliation').should('have.value', ''); cy.get('#author_3_givenName').should('have.value', 'Jane'); cy.get('#author_3_familyName').should('have.value', ''); cy.get('#author_3_affiliation').should('have.value', 'Example Org'); }); }) diff --git a/cypress/integration/special_fields.js b/cypress/integration/special_fields.js index 569337e..62eb48d 100644 --- a/cypress/integration/special_fields.js +++ b/cypress/integration/special_fields.js @@ -1,90 +1,90 @@ /** * Copyright (C) 2020 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ /* * Tests the author/contributor dynamic fieldsets */ "use strict"; describe('Funder id', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#funder').type('http://example.org/'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "funder": { - "@type": "Organization", - "@id": "http://example.org/", + "type": "Organization", + "id": "http://example.org/", }, }); }); it('can be imported', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "funder": { "@type": "Organization", "@id": "http://example.org/", }, })) ); cy.get('#importCodemeta').click(); cy.get('#funder').should('have.value', 'http://example.org/'); }); }); describe('Funder name', function() { it('can be exported', function() { cy.get('#name').type('My Test Software'); cy.get('#funder').type('Example Org'); cy.get('#generateCodemeta').click(); cy.get('#errorMessage').should('have.text', ''); cy.get('#codemetaText').then((elem) => JSON.parse(elem.text())) .should('deep.equal', { "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", + "type": "SoftwareSourceCode", "name": "My Test Software", "funder": { - "@type": "Organization", + "type": "Organization", "name": "Example Org", } }); }); it('can be imported', function() { cy.get('#codemetaText').then((elem) => elem.text(JSON.stringify({ "@context": "https://doi.org/10.5063/schema/codemeta-2.0", "@type": "SoftwareSourceCode", "name": "My Test Software", "funder": { "@type": "Organization", "name": "Example Org", } })) ); cy.get('#importCodemeta').click(); cy.get('#funder').should('have.value', 'Example Org'); }); }); diff --git a/index.html b/index.html index 0ae9b8b..9292617 100644 --- a/index.html +++ b/index.html @@ -1,359 +1,362 @@ CodeMeta generator

CodeMeta generator

Most fields are optional. Mandatory fields will be highlighted when generating Codemeta.

The software itself

the software title


from SPDX licence list

Discoverability and citation


such as ISBNs, GTIN codes, UUIDs etc.. http://schema.org/identifier


grant funding software development


organization funding software development

Authors and contributors can be added below
Development community / tools


Run-time environment


Current version of the software


Additional Info


see www.repostatus.org for details

Authors
Contributors

Order of contributors does not matter.

codemeta.json:


   
+ diff --git a/js/codemeta_generation.js b/js/codemeta_generation.js index 986e9a0..487aed9 100644 --- a/js/codemeta_generation.js +++ b/js/codemeta_generation.js @@ -1,258 +1,281 @@ /** * Copyright (C) 2019-2020 The Software Heritage developers * See the AUTHORS file at the top-level directory of this distribution * License: GNU Affero General Public License version 3, or any later version * See top-level LICENSE file for more information */ "use strict"; +const CODEMETA_CONTEXT_URL = 'https://doi.org/10.5063/schema/codemeta-2.0'; +const CONTEXTS = { + [CODEMETA_CONTEXT_URL]: `${window.location.origin}/contexts/codemeta-2.0.jsonld` +} + const SPDX_PREFIX = 'https://spdx.org/licenses/'; +const jsonldCustomLoader = url => { + const xhrDocumentLoader = jsonld.documentLoaders.xhr(); + if (url in CONTEXTS) { + return xhrDocumentLoader(CONTEXTS[url]); + } + return xhrDocumentLoader(url); +}; + function emptyToUndefined(v) { if (v == null || v == "") return undefined; else return v; } function getIfSet(query) { return emptyToUndefined(document.querySelector(query).value); } function setIfDefined(query, value) { if (value !== undefined) { document.querySelector(query).value = value; } } function getLicenses() { let selectedLicenses = Array.from(document.getElementById("selected-licenses").children); return selectedLicenses.map(licenseDiv => SPDX_PREFIX + licenseDiv.children[0].innerText); } // Names of codemeta properties with a matching HTML field name const directCodemetaFields = [ 'codeRepository', 'contIntegration', 'dateCreated', 'datePublished', 'dateModified', 'downloadUrl', 'issueTracker', 'name', 'version', 'identifier', 'description', 'applicationCategory', 'releaseNotes', 'funding', 'developmentStatus', 'isPartOf', 'referencePublication' ]; const splittedCodemetaFields = [ ['keywords', ','], ['programmingLanguage', ','], ['runtimePlatform', ','], ['operatingSystem', ','], ['softwareRequirements', '\n'], ['relatedLink', '\n'], ] // Names of codemeta properties with a matching HTML field name, // in a Person object const directPersonCodemetaFields = [ 'givenName', 'familyName', 'email', 'affiliation', ]; function generateShortOrg(fieldName) { var affiliation = getIfSet(fieldName); if (affiliation !== undefined) { if (isUrl(affiliation)) { return { "@type": "Organization", "@id": affiliation, }; } else { return { "@type": "Organization", "name": affiliation, }; } } else { return undefined; } } function generatePerson(idPrefix) { var doc = { "@type": "Person", - "@id": getIfSet(`#${idPrefix}_id`), + } + var id = getIfSet(`#${idPrefix}_id`); + if (id !== undefined) { + doc["@id"] = id; } directPersonCodemetaFields.forEach(function (item, index) { doc[item] = getIfSet(`#${idPrefix}_${item}`); }); doc["affiliation"] = generateShortOrg(`#${idPrefix}_affiliation`) return doc; } function generatePersons(prefix) { var persons = []; var nbPersons = getNbPersons(prefix); for (let personId = 1; personId <= nbPersons; personId++) { persons.push(generatePerson(`${prefix}_${personId}`)); } return persons; } -function generateCodemeta() { - var inputForm = document.querySelector('#inputForm'); - var codemetaText, errorHTML; - if (inputForm.checkValidity()) { - var doc = { - "@context": "https://doi.org/10.5063/schema/codemeta-2.0", - "@type": "SoftwareSourceCode", - }; - - let licenses = getLicenses(); - if (licenses.length > 0) { - doc["license"] = (licenses.length === 1) ? licenses[0] : licenses; - } +function buildDoc() { + var doc = { + "@context": CODEMETA_CONTEXT_URL, + "@type": "SoftwareSourceCode", + }; - // Generate most fields - directCodemetaFields.forEach(function (item, index) { - doc[item] = getIfSet('#' + item) - }); + let licenses = getLicenses(); + if (licenses.length > 0) { + doc["license"] = licenses; + } - doc["funder"] = generateShortOrg('#funder', doc["affiliation"]); + // Generate most fields + directCodemetaFields.forEach(function (item, index) { + doc[item] = getIfSet('#' + item) + }); - // Generate simple fields parsed simply by splitting - splittedCodemetaFields.forEach(function (item, index) { - const id = item[0]; - const separator = item[1]; - const value = getIfSet('#' + id); - if (value !== undefined) { - doc[id] = value.split(separator).map(trimSpaces); - } - }); + doc["funder"] = generateShortOrg('#funder', doc["affiliation"]); - // Generate dynamic fields - var authors = generatePersons('author'); - if (authors.length > 0) { - doc["author"] = authors; - } - var contributors = generatePersons('contributor'); - if (contributors.length > 0) { - doc["contributor"] = contributors; + // Generate simple fields parsed simply by splitting + splittedCodemetaFields.forEach(function (item, index) { + const id = item[0]; + const separator = item[1]; + const value = getIfSet('#' + id); + if (value !== undefined) { + doc[id] = value.split(separator).map(trimSpaces); } + }); - codemetaText = JSON.stringify(doc, null, 4); + // Generate dynamic fields + var authors = generatePersons('author'); + if (authors.length > 0) { + doc["author"] = authors; + } + var contributors = generatePersons('contributor'); + if (contributors.length > 0) { + doc["contributor"] = contributors; + } + return doc; +} + +async function generateCodemeta() { + var inputForm = document.querySelector('#inputForm'); + var codemetaText, errorHTML; + + if (inputForm.checkValidity()) { + var doc = buildDoc(); + const expanded = await jsonld.expand(doc, {documentLoader: jsonldCustomLoader}); + const compacted = await jsonld.compact(expanded, CODEMETA_CONTEXT_URL, {documentLoader: jsonldCustomLoader}); + codemetaText = JSON.stringify(compacted, null, 4); errorHTML = ""; } else { codemetaText = ""; errorHTML = "invalid input (see error above)"; inputForm.reportValidity(); } document.querySelector('#codemetaText').innerText = codemetaText; setError(errorHTML); // Run validator on the exported value, for extra validation. // If this finds a validation, it means there is a bug in our code (either // generation or validation), and the generation MUST NOT generate an // invalid codemeta file, regardless of user input. if (codemetaText && !validateDocument(JSON.parse(codemetaText))) { alert('Bug detected! The data you wrote is correct; but for some reason, it seems we generated an invalid codemeta.json. Please report this bug at https://github.com/codemeta/codemeta-generator/issues/new and copy-paste the generated codemeta.json file. Thanks!'); } if (codemetaText) { // For restoring the form state on page reload sessionStorage.setItem('codemetaText', codemetaText); } } // Imports a single field (name or @id) from an Organization. function importShortOrg(fieldName, doc) { if (doc !== undefined) { // Use @id if set, else use name setIfDefined(fieldName, doc["name"]); setIfDefined(fieldName, doc["@id"]); } } function importPersons(prefix, legend, docs) { if (docs === undefined) { return; } docs.forEach(function (doc, index) { var personId = addPerson(prefix, legend); setIfDefined(`#${prefix}_${personId}_id`, doc['@id']); directPersonCodemetaFields.forEach(function (item, index) { setIfDefined(`#${prefix}_${personId}_${item}`, doc[item]); }); importShortOrg(`#${prefix}_${personId}_affiliation`, doc['affiliation']) }) } function importCodemeta() { var inputForm = document.querySelector('#inputForm'); var doc = parseAndValidateCodemeta(false); resetForm(); if (doc['license'] !== undefined) { if (typeof doc['license'] === 'string') { doc['license'] = [doc['license']]; } doc['license'].forEach(l => { if (l.indexOf(SPDX_PREFIX) !== 0) { return; } let licenseId = l.substring(SPDX_PREFIX.length); insertLicenseElement(licenseId); }); } directCodemetaFields.forEach(function (item, index) { setIfDefined('#' + item, doc[item]); }); importShortOrg('#funder', doc["funder"]); // Import simple fields by joining on their separator splittedCodemetaFields.forEach(function (item, index) { const id = item[0]; const separator = item[1]; let value = doc[id]; if (value !== undefined) { if (Array.isArray(value)) { value = value.join(separator); } setIfDefined('#' + id, value); } }); importPersons('author', 'Author', doc['author']) importPersons('contributor', 'Contributor', doc['contributor']) } function loadStateFromStorage() { var codemetaText = sessionStorage.getItem('codemetaText') if (codemetaText) { document.querySelector('#codemetaText').innerText = codemetaText; importCodemeta(); } } diff --git a/js/libs/jsonld/LICENSE b/js/libs/jsonld/LICENSE new file mode 100644 index 0000000..5a8c53e --- /dev/null +++ b/js/libs/jsonld/LICENSE @@ -0,0 +1,40 @@ +You may use the jsonld.js project under the terms of the BSD License. + +You are free to use this project in commercial projects as long as the +copyright header is left intact. + +If you are a commercial entity and use this set of libraries in your +commercial software then reasonable payment to Digital Bazaar, if you can +afford it, is not required but is expected and would be appreciated. If this +library saves you time, then it's saving you money. The cost of developing +JSON-LD was on the order of several months of work and tens of +thousands of dollars. We are attempting to strike a balance between helping +the development community while not being taken advantage of by lucrative +commercial entities for our efforts. + +------------------------------------------------------------------------------- +New BSD License (3-clause) +Copyright (c) 2010, Digital Bazaar, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Digital Bazaar, Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DIGITAL BAZAAR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/js/libs/jsonld/jsonld.esm.min.js b/js/libs/jsonld/jsonld.esm.min.js new file mode 100644 index 0000000..01c6e28 --- /dev/null +++ b/js/libs/jsonld/jsonld.esm.min.js @@ -0,0 +1,72 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.jsonld=t():e.jsonld=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=174)}([function(e,t,n){"use strict";(function(t){var n=function(e){return e&&e.Math===Math&&e};e.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof t&&t)||n("object"==typeof this&&this)||function(){return this}()||Function("return this")()}).call(this,n(118))},function(e,t,n){"use strict";e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){"use strict";var r=n(69),o=Function.prototype,i=o.call,a=r&&o.bind.bind(i,i);e.exports=r?a:function(e){return function(){return i.apply(e,arguments)}}},function(e,t,n){"use strict";var r=n(0),o=n(42).f,i=n(31),a=n(27),s=n(87),c=n(126),u=n(93);e.exports=function(e,t){var n,l,d,f,p,h=e.target,v=e.global,g=e.stat;if(n=v?r:g?r[h]||s(h,{}):(r[h]||{}).prototype)for(l in t){if(f=t[l],d=e.dontCallGetSet?(p=o(n,l))&&p.value:n[l],!u(v?l:h+(g?".":"#")+l,e.forced)&&void 0!==d){if(typeof f==typeof d)continue;c(f,d)}(e.sham||d&&d.sham)&&i(f,"sham",!0),a(n,l,f,e)}}},function(e,t,n){"use strict";var r=n(121),o=r.all;e.exports=r.IS_HTMLDDA?function(e){return"function"==typeof e||e===o}:function(e){return"function"==typeof e}},function(e,t,n){"use strict";var r=n(69),o=Function.prototype.call;e.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(e,t,n){"use strict";var r=n(55),o=n(141),i=n(64),a=n(36),s=n(22).f,c=n(201),u=n(204),l=n(26),d=n(11),f=a.set,p=a.getterFor("Array Iterator");e.exports=c(Array,"Array",(function(e,t){f(this,{type:"Array Iterator",target:r(e),index:0,kind:t})}),(function(){var e=p(this),t=e.target,n=e.index++;if(!t||n>=t.length)return e.target=void 0,u(void 0,!0);switch(e.kind){case"keys":return u(n,!1);case"values":return u(t[n],!1)}return u([n,t[n]],!1)}),"values");var h=i.Arguments=i.Array;if(o("keys"),o("values"),o("entries"),!l&&d&&"values"!==h.name)try{s(h,"name",{value:"values"})}catch(e){}},function(e,t,n){"use strict";var r=n(0),o=n(85),i=n(13),a=n(88),s=n(84),c=n(122),u=r.Symbol,l=o("wks"),d=c?u.for||u:u&&u.withoutSetter||a;e.exports=function(e){return i(l,e)||(l[e]=s&&i(u,e)?u[e]:d("Symbol."+e)),l[e]}},function(e,t,n){"use strict";var r=n(0),o=n(205),i=n(206),a=n(6),s=n(31),c=n(59),u=n(7)("iterator"),l=a.values,d=function(e,t){if(e){if(e[u]!==l)try{s(e,u,l)}catch(t){e[u]=l}if(c(e,t,!0),o[t])for(var n in a)if(e[n]!==a[n])try{s(e,n,a[n])}catch(t){e[n]=a[n]}}};for(var f in o)d(r[f]&&r[f].prototype,f);d(i,"DOMTokenList")},function(e,t,n){"use strict";var r=n(39),o=String;e.exports=function(e){if("Symbol"===r(e))throw new TypeError("Cannot convert a Symbol value to a string");return o(e)}},function(e,t,n){"use strict";var r=n(15),o=String,i=TypeError;e.exports=function(e){if(r(e))return e;throw new i(o(e)+" is not an object")}},function(e,t,n){"use strict";var r=n(1);e.exports=!r((function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]}))},function(e,t,n){"use strict";n(180),n(193),n(195),n(196),n(197),n(198)},function(e,t,n){"use strict";var r=n(2),o=n(21),i=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return i(o(e),t)}},function(e,t,n){"use strict";var r=n(3),o=n(2),i=n(20),a=n(21),s=n(23),c=n(207),u=n(9),l=n(1),d=n(144),f=n(146),p=n(147),h=n(148),v=n(57),g=n(149),y=[],m=o(y.sort),x=o(y.push),b=l((function(){y.sort(void 0)})),w=l((function(){y.sort(null)})),j=f("sort"),I=!l((function(){if(v)return v<70;if(!(p&&p>3)){if(h)return!0;if(g)return g<603;var e,t,n,r,o="";for(e=65;e<76;e++){switch(t=String.fromCharCode(e),e){case 66:case 69:case 70:case 72:n=3;break;case 68:case 71:n=4;break;default:n=2}for(r=0;r<47;r++)y.push({k:t+r,v:n})}for(y.sort((function(e,t){return t.v-e.v})),r=0;ru(n)?1:-1}}(e)),n=s(o),r=0;r"boolean"==typeof e||"[object Boolean]"===Object.prototype.toString.call(e),r.isDouble=e=>r.isNumber(e)&&(-1!==String(e).indexOf(".")||Math.abs(e)>=1e21),r.isEmptyObject=e=>r.isObject(e)&&0===Object.keys(e).length,r.isNumber=e=>"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e),r.isNumeric=e=>!isNaN(parseFloat(e))&&isFinite(e),r.isObject=e=>"[object Object]"===Object.prototype.toString.call(e),r.isString=e=>"string"==typeof e||"[object String]"===Object.prototype.toString.call(e),r.isUndefined=e=>void 0===e},function(e,t,n){"use strict";var r=n(38),o=TypeError;e.exports=function(e){if(r(e))throw new o("Can't call method on "+e);return e}},function(e,t,n){"use strict";n(6),n(8),n(40),n(104),n(25),n(53),n(14);const r=n(32),o=n(16),i=n(105).IdentifierIssuer,a=n(19),s=/(?:<[^>]*?>|"[^"]*?"|[^,])+/g,c=/\s*<([^>]*?)>\s*(?:;\s*(.*))?/,u=/(.*?)=(?:(?:"([^"]*?)")|([^"]*?))\s*(?:(?:;\s*)|$)/g,l={accept:"application/ld+json, application/json"},d={};e.exports=d,d.IdentifierIssuer=i,d.REGEX_BCP47=/^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/,d.REGEX_KEYWORD=/^@[a-zA-Z]+$/,d.clone=function(e){if(e&&"object"==typeof e){let t;if(o.isArray(e)){t=[];for(let n=0;n{if(Object.keys(e).some(e=>"accept"===e.toLowerCase()))throw new RangeError('Accept header may not be specified; only "'+l.accept+'" is supported.');return Object.assign({Accept:l.accept},e)},d.parseLinkHeader=e=>{const t={},n=e.match(s);for(let e=0;e{if(!(o.isString(e)||o.isArray(e)&&e.every(e=>o.isString(e)))){if(t&&o.isObject(e))switch(Object.keys(e).length){case 0:return;case 1:if("@default"in e&&d.asArray(e["@default"]).every(e=>o.isString(e)))return}throw new a('Invalid JSON-LD syntax; "@type" value must a string, an array of strings, an empty object, or a default object.',"jsonld.SyntaxError",{code:"invalid type value",value:e})}},d.hasProperty=(e,t)=>{if(e.hasOwnProperty(t)){const n=e[t];return!o.isArray(n)||n.length>0}return!1},d.hasValue=(e,t,n)=>{if(d.hasProperty(e,t)){let i=e[t];const a=r.isList(i);if(o.isArray(i)||a){a&&(i=i["@list"]);for(let e=0;e{if("propertyIsArray"in(r=r||{})||(r.propertyIsArray=!1),"valueIsArray"in r||(r.valueIsArray=!1),"allowDuplicate"in r||(r.allowDuplicate=!0),"prependValue"in r||(r.prependValue=!1),r.valueIsArray)e[t]=n;else if(o.isArray(n)){0===n.length&&r.propertyIsArray&&!e.hasOwnProperty(t)&&(e[t]=[]),r.prependValue&&(n=n.concat(e[t]),e[t]=[]);for(let o=0;o[].concat(e[t]||[]),d.removeProperty=(e,t)=>{delete e[t]},d.removeValue=(e,t,n,r)=>{"propertyIsArray"in(r=r||{})||(r.propertyIsArray=!1);const o=d.getValues(e,t).filter(e=>!d.compareValues(e,n));0===o.length?d.removeProperty(e,t):1!==o.length||r.propertyIsArray?e[t]=o:e[t]=o[0]},d.relabelBlankNodes=(e,t)=>function e(t,n){if(o.isArray(n))for(let r=0;re===t||(!(!r.isValue(e)||!r.isValue(t)||e["@value"]!==t["@value"]||e["@type"]!==t["@type"]||e["@language"]!==t["@language"]||e["@index"]!==t["@index"])||!!(o.isObject(e)&&"@id"in e&&o.isObject(t)&&"@id"in t)&&e["@id"]===t["@id"]),d.compareShortestLeast=(e,t)=>e.length0?o(r(e),9007199254740991):0}},function(e,t,n){"use strict";var r=n(3),o=n(80);r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},function(e,t,n){"use strict";e.exports=!1},function(e,t,n){"use strict";var r=n(4),o=n(22),i=n(125),a=n(87);e.exports=function(e,t,n,s){s||(s={});var c=s.enumerable,u=void 0!==s.name?s.name:t;if(r(n)&&i(n,u,s),s.global)c?e[t]=n:a(t,n);else{try{s.unsafe?e[t]&&(c=!0):delete e[t]}catch(e){}c?e[t]=n:o.f(e,t,{value:n,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return e}},function(e,t,n){"use strict";var r=n(184);e.exports=function(e){var t=+e;return t!=t||0===t?0:r(t)}},function(e,t,n){"use strict";var r,o,i,a=n(152),s=n(11),c=n(0),u=n(4),l=n(15),d=n(13),f=n(39),p=n(44),h=n(31),v=n(27),g=n(60),y=n(35),m=n(78),x=n(45),b=n(7),w=n(88),j=n(36),I=j.enforce,O=j.get,S=c.Int8Array,E=S&&S.prototype,N=c.Uint8ClampedArray,A=N&&N.prototype,T=S&&m(S),D=E&&m(E),R=Object.prototype,k=c.TypeError,L=b("toStringTag"),C=w("TYPED_ARRAY_TAG"),_=a&&!!x&&"Opera"!==f(c.opera),P=!1,M={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},F={BigInt64Array:8,BigUint64Array:8},B=function(e){var t=m(e);if(l(t)){var n=O(t);return n&&d(n,"TypedArrayConstructor")?n.TypedArrayConstructor:B(t)}},J=function(e){if(!l(e))return!1;var t=f(e);return d(M,t)||d(F,t)};for(r in M)(i=(o=c[r])&&o.prototype)?I(i).TypedArrayConstructor=o:_=!1;for(r in F)(i=(o=c[r])&&o.prototype)&&(I(i).TypedArrayConstructor=o);if((!_||!u(T)||T===Function.prototype)&&(T=function(){throw new k("Incorrect invocation")},_))for(r in M)c[r]&&x(c[r],T);if((!_||!D||D===R)&&(D=T.prototype,_))for(r in M)c[r]&&x(c[r].prototype,D);if(_&&m(A)!==D&&x(A,D),s&&!d(D,L))for(r in P=!0,g(D,L,{configurable:!0,get:function(){return l(this)?this[C]:void 0}}),M)c[r]&&h(c[r],C,r);e.exports={NATIVE_ARRAY_BUFFER_VIEWS:_,TYPED_ARRAY_TAG:P&&C,aTypedArray:function(e){if(J(e))return e;throw new k("Target is not a typed array")},aTypedArrayConstructor:function(e){if(u(e)&&(!x||y(T,e)))return e;throw new k(p(e)+" is not a typed array constructor")},exportTypedArrayMethod:function(e,t,n,r){if(s){if(n)for(var o in M){var i=c[o];if(i&&d(i.prototype,e))try{delete i.prototype[e]}catch(n){try{i.prototype[e]=t}catch(e){}}}D[e]&&!n||v(D,e,n?t:_&&E[e]||t,r)}},exportTypedArrayStaticMethod:function(e,t,n){var r,o;if(s){if(x){if(n)for(r in M)if((o=c[r])&&d(o,e))try{delete o[e]}catch(e){}if(T[e]&&!n)return;try{return v(T,e,n?t:_&&T[e]||t)}catch(e){}}for(r in M)!(o=c[r])||o[e]&&!n||v(o,e,t)}},getTypedArrayConstructor:B,isView:function(e){if(!l(e))return!1;var t=f(e);return"DataView"===t||d(M,t)||d(F,t)},isTypedArray:J,TypedArray:T,TypedArrayPrototype:D}},function(e,t,n){"use strict";e.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},function(e,t,n){"use strict";var r=n(11),o=n(22),i=n(54);e.exports=r?function(e,t,n){return o.f(e,t,i(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){"use strict";const r=n(16),o={};e.exports=o,o.isSubject=e=>{if(r.isObject(e)&&!("@value"in e||"@set"in e||"@list"in e)){return Object.keys(e).length>1||!("@id"in e)}return!1},o.isSubjectReference=e=>r.isObject(e)&&1===Object.keys(e).length&&"@id"in e,o.isValue=e=>r.isObject(e)&&"@value"in e,o.isList=e=>r.isObject(e)&&"@list"in e,o.isGraph=e=>r.isObject(e)&&"@graph"in e&&1===Object.keys(e).filter(e=>"@id"!==e&&"@index"!==e).length,o.isSimpleGraph=e=>o.isGraph(e)&&!("@id"in e),o.isBlankNode=e=>{if(r.isObject(e)){if("@id"in e){const t=e["@id"];return!r.isString(t)||0===t.indexOf("_:")}return 0===Object.keys(e).length||!("@value"in e||"@set"in e||"@list"in e)}return!1}},function(e,t,n){"use strict";var r=n(2),o=r({}.toString),i=r("".slice);e.exports=function(e){return i(o(e),8,-1)}},function(e,t,n){"use strict";var r=n(0),o=n(4),i=function(e){return o(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?i(r[e]):r[e]&&r[e][t]}},function(e,t,n){"use strict";var r=n(2);e.exports=r({}.isPrototypeOf)},function(e,t,n){"use strict";var r,o,i,a=n(182),s=n(0),c=n(15),u=n(31),l=n(13),d=n(86),f=n(90),p=n(91),h=s.TypeError,v=s.WeakMap;if(a||d.state){var g=d.state||(d.state=new v);g.get=g.get,g.has=g.has,g.set=g.set,r=function(e,t){if(g.has(e))throw new h("Object already initialized");return t.facade=e,g.set(e,t),t},o=function(e){return g.get(e)||{}},i=function(e){return g.has(e)}}else{var y=f("state");p[y]=!0,r=function(e,t){if(l(e,y))throw new h("Object already initialized");return t.facade=e,u(e,y,t),t},o=function(e){return l(e,y)?e[y]:{}},i=function(e){return l(e,y)}}e.exports={set:r,get:o,has:i,enforce:function(e){return i(e)?o(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!c(t)||(n=o(t)).type!==e)throw new h("Incompatible receiver, "+e+" required");return n}}}},function(e,t,n){"use strict";n(25),n(6),n(8),n(82),n(81);const r=n(16),o={};e.exports=o,o.parsers={simple:{keys:["href","scheme","authority","path","query","fragment"],regex:/^(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/},full:{keys:["href","protocol","scheme","authority","auth","user","password","hostname","port","path","directory","file","query","fragment"],regex:/^(([a-zA-Z][a-zA-Z0-9+-.]*):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?(?:(((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/}},o.parse=(e,t)=>{const n={},r=o.parsers[t||"full"],i=r.regex.exec(e);let a=r.keys.length;for(;a--;)n[r.keys[a]]=void 0===i[a]?null:i[a];return("https"===n.scheme&&"443"===n.port||"http"===n.scheme&&"80"===n.port)&&(n.href=n.href.replace(":"+n.port,""),n.authority=n.authority.replace(":"+n.port,""),n.port=null),n.normalizedPath=o.removeDotSegments(n.path),n},o.prependBase=(e,t)=>{if(null===e)return t;if(o.isAbsolute(t))return t;e&&!r.isString(e)||(e=o.parse(e||""));const n=o.parse(t),i={protocol:e.protocol||""};if(null!==n.authority)i.authority=n.authority,i.path=n.path,i.query=n.query;else if(i.authority=e.authority,""===n.path)i.path=e.path,null!==n.query?i.query=n.query:i.query=e.query;else{if(0===n.path.indexOf("/"))i.path=n.path;else{let t=e.path;t=t.substr(0,t.lastIndexOf("/")+1),(t.length>0||e.authority)&&"/"!==t.substr(-1)&&(t+="/"),t+=n.path,i.path=t}i.query=n.query}""!==n.path&&(i.path=o.removeDotSegments(i.path));let a=i.protocol;return null!==i.authority&&(a+="//"+i.authority),a+=i.path,null!==i.query&&(a+="?"+i.query),null!==n.fragment&&(a+="#"+n.fragment),""===a&&(a="./"),a},o.removeBase=(e,t)=>{if(null===e)return t;e&&!r.isString(e)||(e=o.parse(e||""));let n="";if(""!==e.href?n+=(e.protocol||"")+"//"+(e.authority||""):t.indexOf("//")&&(n+="//"),0!==t.indexOf(n))return t;const i=o.parse(t.substr(n.length)),a=e.normalizedPath.split("/"),s=i.normalizedPath.split("/"),c=i.fragment||i.query?0:1;for(;a.length>0&&s.length>c&&a[0]===s[0];)a.shift(),s.shift();let u="";if(a.length>0){a.pop();for(let e=0;e{if(0===e.length)return"";const t=e.split("/"),n=[];for(;t.length>0;){const e=t.shift(),r=0===t.length;"."!==e?".."!==e?n.push(e):(n.pop(),r&&n.push("")):r&&n.push("")}return"/"===e[0]&&n.length>0&&""!==n[0]&&n.unshift(""),1===n.length&&""===n[0]?"/":n.join("/")};const i=/^([A-Za-z][A-Za-z0-9+-.]*|_):[^\s]*$/;o.isAbsolute=e=>r.isString(e)&&i.test(e),o.isRelative=e=>r.isString(e)},function(e,t,n){"use strict";e.exports=function(e){return null==e}},function(e,t,n){"use strict";var r=n(187),o=n(4),i=n(33),a=n(7)("toStringTag"),s=Object,c="Arguments"===i(function(){return arguments}());e.exports=r?i:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=s(e),a))?n:c?i(t):"Object"===(r=i(t))&&o(t.callee)?"Arguments":r}},function(e,t,n){"use strict";var r=n(73).PROPER,o=n(27),i=n(10),a=n(9),s=n(1),c=n(160),u=RegExp.prototype.toString,l=s((function(){return"/a/b"!==u.call({source:"a",flags:"b"})})),d=r&&"toString"!==u.name;(l||d)&&o(RegExp.prototype,"toString",(function(){var e=i(this);return"/"+a(e.source)+"/"+a(c(e))}),{unsafe:!0})},function(e,t,n){"use strict";var r=n(67)(n(68));function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t0){const n=t.substr(0,a),s=t.substr(a+1);if("_"===n||0===s.indexOf("//"))return t;r&&r.hasOwnProperty(n)&&w.createTermDefinition({activeCtx:e,localCtx:r,term:n,defined:o,options:i});const c=e.mappings.get(n);if(c&&c._prefix)return c["@id"]+s;if(f(t))return t}if(n.vocab&&"@vocab"in e){t=e["@vocab"]+t}else if(n.base){let n,r;"@base"in e?e["@base"]?(r=h(i.base,e["@base"]),n=h(r,t)):(r=e["@base"],n=t):(r=i.base,n=h(i.base,t)),t=n}return t}e.exports=w,w.process=async({activeCtx:e,localCtx:t,options:n,propagate:r=!0,overrideProtected:o=!1,cycles:a=new Set})=>{u(t)&&"@context"in t&&c(t["@context"])&&(t=t["@context"]);if(0===m(t).length)return e;const d=[],y=[({event:e,next:t})=>{d.push(e),t()}];n.eventHandler&&y.push(n.eventHandler);const x=n;n=i(i({},n),{},{eventHandler:y});const b=await n.contextResolver.resolve({activeCtx:e,context:t,documentLoader:n.documentLoader,base:n.base});u(b[0].document)&&"boolean"==typeof b[0].document["@propagate"]&&(r=b[0].document["@propagate"]);let I=e;r||I.previousContext||(I=I.clone(),I.previousContext=e);for(const r of b){let{document:i}=r;if(e=I,null===i){if(!o&&0!==Object.keys(e.protected).length)throw new s("Tried to nullify a context with protected terms outside of a term definition.","jsonld.SyntaxError",{code:"invalid context nullification"});I=e=w.getInitialContext(n).clone();continue}const c=r.getProcessed(e);if(c){if(x.eventHandler)for(const e of c.events)v({event:e,options:x});I=e=c.context;continue}if(u(i)&&"@context"in i&&(i=i["@context"]),!u(i))throw new s("Invalid JSON-LD syntax; @context must be an object.","jsonld.SyntaxError",{code:"invalid local context",context:i});I=I.clone();const y=new Map;if("@version"in i){if(1.1!==i["@version"])throw new s("Unsupported JSON-LD version: "+i["@version"],"jsonld.UnsupportedVersion",{code:"invalid @version value",context:i});if(e.processingMode&&"json-ld-1.0"===e.processingMode)throw new s("@version: "+i["@version"]+" not compatible with "+e.processingMode,"jsonld.ProcessingModeConflict",{code:"processing mode conflict",context:i});I.processingMode="json-ld-1.1",I["@version"]=i["@version"],y.set("@version",!0)}if(I.processingMode=I.processingMode||e.processingMode,"@base"in i){let e=i["@base"];if(null===e||f(e));else{if(!p(e))throw new s('Invalid JSON-LD syntax; the value of "@base" in a @context must be an absolute IRI, a relative IRI, or null.',"jsonld.SyntaxError",{code:"invalid base IRI",context:i});e=h(I["@base"],e)}I["@base"]=e,y.set("@base",!0)}if("@vocab"in i){const e=i["@vocab"];if(null===e)delete I["@vocab"];else{if(!l(e))throw new s('Invalid JSON-LD syntax; the value of "@vocab" in a @context must be a string or null.',"jsonld.SyntaxError",{code:"invalid vocab mapping",context:i});if(!f(e)&&w.processingMode(I,1))throw new s('Invalid JSON-LD syntax; the value of "@vocab" in a @context must be an absolute IRI.',"jsonld.SyntaxError",{code:"invalid vocab mapping",context:i});{const t=j(I,e,{vocab:!0,base:!0},void 0,void 0,n);f(t)||n.eventHandler&&v({event:{type:["JsonLdEvent"],code:"relative @vocab reference",level:"warning",message:"Relative @vocab reference found.",details:{vocab:t}},options:n}),I["@vocab"]=t}}y.set("@vocab",!0)}if("@language"in i){const e=i["@language"];if(null===e)delete I["@language"];else{if(!l(e))throw new s('Invalid JSON-LD syntax; the value of "@language" in a @context must be a string or null.',"jsonld.SyntaxError",{code:"invalid default language",context:i});e.match(g)||n.eventHandler&&v({event:{type:["JsonLdEvent"],code:"invalid @language value",level:"warning",message:"@language value must be valid BCP47.",details:{language:e}},options:n}),I["@language"]=e.toLowerCase()}y.set("@language",!0)}if("@direction"in i){const t=i["@direction"];if("json-ld-1.0"===e.processingMode)throw new s("Invalid JSON-LD syntax; @direction not compatible with "+e.processingMode,"jsonld.SyntaxError",{code:"invalid context member",context:i});if(null===t)delete I["@direction"];else{if("ltr"!==t&&"rtl"!==t)throw new s('Invalid JSON-LD syntax; the value of "@direction" in a @context must be null, "ltr", or "rtl".',"jsonld.SyntaxError",{code:"invalid base direction",context:i});I["@direction"]=t}y.set("@direction",!0)}if("@propagate"in i){const n=i["@propagate"];if("json-ld-1.0"===e.processingMode)throw new s("Invalid JSON-LD syntax; @propagate not compatible with "+e.processingMode,"jsonld.SyntaxError",{code:"invalid context entry",context:i});if("boolean"!=typeof n)throw new s("Invalid JSON-LD syntax; @propagate value must be a boolean.","jsonld.SyntaxError",{code:"invalid @propagate value",context:t});y.set("@propagate",!0)}if("@import"in i){const r=i["@import"];if("json-ld-1.0"===e.processingMode)throw new s("Invalid JSON-LD syntax; @import not compatible with "+e.processingMode,"jsonld.SyntaxError",{code:"invalid context entry",context:i});if(!l(r))throw new s("Invalid JSON-LD syntax; @import must be a string.","jsonld.SyntaxError",{code:"invalid @import value",context:t});const o=await n.contextResolver.resolve({activeCtx:e,context:r,documentLoader:n.documentLoader,base:n.base});if(1!==o.length)throw new s("Invalid JSON-LD syntax; @import must reference a single context.","jsonld.SyntaxError",{code:"invalid remote context",context:t});const a=o[0].getProcessed(e);if(a)i=a;else{const n=o[0].document;if("@import"in n)throw new s("Invalid JSON-LD syntax: imported context must not include @import.","jsonld.SyntaxError",{code:"invalid context entry",context:t});for(const e in n)i.hasOwnProperty(e)||(i[e]=n[e]);o[0].setProcessed(e,i)}y.set("@import",!0)}y.set("@protected",i["@protected"]||!1);for(const e in i)if(w.createTermDefinition({activeCtx:I,localCtx:i,term:e,defined:y,options:n,overrideProtected:o}),u(i[e])&&"@context"in i[e]){const t=i[e]["@context"];let r=!0;if(l(t)){const e=h(n.base,t);a.has(e)?r=!1:a.add(e)}if(r)try{await w.process({activeCtx:I.clone(),localCtx:i[e]["@context"],overrideProtected:!0,options:n,cycles:a})}catch(t){throw new s("Invalid JSON-LD syntax; invalid scoped context.","jsonld.SyntaxError",{code:"invalid scoped context",context:i[e]["@context"],term:e})}}r.setProcessed(e,{context:I,events:d})}return I},w.createTermDefinition=({activeCtx:e,localCtx:t,term:n,defined:r,options:o,overrideProtected:i=!1})=>{if(r.has(n)){if(r.get(n))return;throw new s("Cyclical context definition detected.","jsonld.CyclicalContext",{code:"cyclic IRI mapping",context:t,term:n})}let a;if(r.set(n,!1),t.hasOwnProperty(n)&&(a=t[n]),"@type"===n&&u(a)&&"@set"===(a["@container"]||"@set")&&w.processingMode(e,1.1)){const e=["@container","@id","@protected"],r=Object.keys(a);if(0===r.length||r.some(t=>!e.includes(t)))throw new s("Invalid JSON-LD syntax; keywords cannot be overridden.","jsonld.SyntaxError",{code:"keyword redefinition",context:t,term:n})}else{if(w.isKeyword(n))throw new s("Invalid JSON-LD syntax; keywords cannot be overridden.","jsonld.SyntaxError",{code:"keyword redefinition",context:t,term:n});if(n.match(y))return void(o.eventHandler&&v({event:{type:["JsonLdEvent"],code:"reserved term",level:"warning",message:'Terms beginning with "@" are reserved for future use and dropped.',details:{term:n}},options:o}));if(""===n)throw new s("Invalid JSON-LD syntax; a term cannot be an empty string.","jsonld.SyntaxError",{code:"invalid term definition",context:t})}const d=e.mappings.get(n);e.mappings.has(n)&&e.mappings.delete(n);let p=!1;if((l(a)||null===a)&&(p=!0,a={"@id":a}),!u(a))throw new s("Invalid JSON-LD syntax; @context term values must be strings or objects.","jsonld.SyntaxError",{code:"invalid term definition",context:t});const h={};e.mappings.set(n,h),h.reverse=!1;const g=["@container","@id","@language","@reverse","@type"];w.processingMode(e,1.1)&&g.push("@context","@direction","@index","@nest","@prefix","@protected");for(const e in a)if(!g.includes(e))throw new s("Invalid JSON-LD syntax; a term definition must not contain "+e,"jsonld.SyntaxError",{code:"invalid term definition",context:t});const m=n.indexOf(":");if(h._termHasColon=m>0,"@reverse"in a){if("@id"in a)throw new s("Invalid JSON-LD syntax; a @reverse term definition must not contain @id.","jsonld.SyntaxError",{code:"invalid reverse property",context:t});if("@nest"in a)throw new s("Invalid JSON-LD syntax; a @reverse term definition must not contain @nest.","jsonld.SyntaxError",{code:"invalid reverse property",context:t});const i=a["@reverse"];if(!l(i))throw new s("Invalid JSON-LD syntax; a @context @reverse value must be a string.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t});if(i.match(y))return o.eventHandler&&v({event:{type:["JsonLdEvent"],code:"reserved @reverse value",level:"warning",message:'@reverse values beginning with "@" are reserved for future use and dropped.',details:{reverse:i}},options:o}),void(d?e.mappings.set(n,d):e.mappings.delete(n));const c=j(e,i,{vocab:!0,base:!1},t,r,o);if(!f(c))throw new s("Invalid JSON-LD syntax; a @context @reverse value must be an absolute IRI or a blank node identifier.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t});h["@id"]=c,h.reverse=!0}else if("@id"in a){let i=a["@id"];if(i&&!l(i))throw new s("Invalid JSON-LD syntax; a @context @id value must be an array of strings or a string.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t});if(null===i)h["@id"]=null;else{if(!w.isKeyword(i)&&i.match(y))return o.eventHandler&&v({event:{type:["JsonLdEvent"],code:"reserved @id value",level:"warning",message:'@id values beginning with "@" are reserved for future use and dropped.',details:{id:i}},options:o}),void(d?e.mappings.set(n,d):e.mappings.delete(n));if(i!==n){if(i=j(e,i,{vocab:!0,base:!1},t,r,o),!f(i)&&!w.isKeyword(i))throw new s("Invalid JSON-LD syntax; a @context @id value must be an absolute IRI, a blank node identifier, or a keyword.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t});if(n.match(/(?::[^:])|\//)){if(j(e,n,{vocab:!0,base:!1},t,new Map(r).set(n,!0),o)!==i)throw new s("Invalid JSON-LD syntax; term in form of IRI must expand to definition.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t})}h["@id"]=i,h._prefix=p&&!h._termHasColon&&null!==i.match(/[:\/\?#\[\]@]$/)}}}if(!("@id"in h))if(h._termHasColon){const i=n.substr(0,m);if(t.hasOwnProperty(i)&&w.createTermDefinition({activeCtx:e,localCtx:t,term:i,defined:r,options:o}),e.mappings.has(i)){const t=n.substr(m+1);h["@id"]=e.mappings.get(i)["@id"]+t}else h["@id"]=n}else if("@type"===n)h["@id"]=n;else{if(!("@vocab"in e))throw new s("Invalid JSON-LD syntax; @context terms must define an @id.","jsonld.SyntaxError",{code:"invalid IRI mapping",context:t,term:n});h["@id"]=e["@vocab"]+n}if((!0===a["@protected"]||!0===r.get("@protected")&&!1!==a["@protected"])&&(e.protected[n]=!0,h.protected=!0),r.set(n,!0),"@type"in a){let n=a["@type"];if(!l(n))throw new s("Invalid JSON-LD syntax; an @context @type value must be a string.","jsonld.SyntaxError",{code:"invalid type mapping",context:t});if("@json"===n||"@none"===n){if(w.processingMode(e,1))throw new s(`Invalid JSON-LD syntax; an @context @type value must not be "${n}" in JSON-LD 1.0 mode.`,"jsonld.SyntaxError",{code:"invalid type mapping",context:t})}else if("@id"!==n&&"@vocab"!==n){if(n=j(e,n,{vocab:!0,base:!1},t,r,o),!f(n))throw new s("Invalid JSON-LD syntax; an @context @type value must be an absolute IRI.","jsonld.SyntaxError",{code:"invalid type mapping",context:t});if(0===n.indexOf("_:"))throw new s("Invalid JSON-LD syntax; an @context @type value must be an IRI, not a blank node identifier.","jsonld.SyntaxError",{code:"invalid type mapping",context:t})}h["@type"]=n}if("@container"in a){const n=l(a["@container"])?[a["@container"]]:a["@container"]||[],r=["@list","@set","@index","@language"];let o=!0;const i=n.includes("@set");if(w.processingMode(e,1.1)){if(r.push("@graph","@id","@type"),n.includes("@list")){if(1!==n.length)throw new s("Invalid JSON-LD syntax; @context @container with @list must have no other values","jsonld.SyntaxError",{code:"invalid container mapping",context:t})}else if(n.includes("@graph")){if(n.some(e=>"@graph"!==e&&"@id"!==e&&"@index"!==e&&"@set"!==e))throw new s("Invalid JSON-LD syntax; @context @container with @graph must have no other values other than @id, @index, and @set","jsonld.SyntaxError",{code:"invalid container mapping",context:t})}else o&=n.length<=(i?2:1);if(n.includes("@type")&&(h["@type"]=h["@type"]||"@id",!["@id","@vocab"].includes(h["@type"])))throw new s("Invalid JSON-LD syntax; container: @type requires @type to be @id or @vocab.","jsonld.SyntaxError",{code:"invalid type mapping",context:t})}else o&=!c(a["@container"]),o&=n.length<=1;if(o&=n.every(e=>r.includes(e)),o&=!(i&&n.includes("@list")),!o)throw new s("Invalid JSON-LD syntax; @context @container value must be one of the following: "+r.join(", "),"jsonld.SyntaxError",{code:"invalid container mapping",context:t});if(h.reverse&&!n.every(e=>["@index","@set"].includes(e)))throw new s("Invalid JSON-LD syntax; @context @container value for a @reverse type definition must be @index or @set.","jsonld.SyntaxError",{code:"invalid reverse property",context:t});h["@container"]=n}if("@index"in a){if(!("@container"in a)||!h["@container"].includes("@index"))throw new s(`Invalid JSON-LD syntax; @index without @index in @container: "${a["@index"]}" on term "${n}".`,"jsonld.SyntaxError",{code:"invalid term definition",context:t});if(!l(a["@index"])||0===a["@index"].indexOf("@"))throw new s(`Invalid JSON-LD syntax; @index must expand to an IRI: "${a["@index"]}" on term "${n}".`,"jsonld.SyntaxError",{code:"invalid term definition",context:t});h["@index"]=a["@index"]}if("@context"in a&&(h["@context"]=a["@context"]),"@language"in a&&!("@type"in a)){let e=a["@language"];if(null!==e&&!l(e))throw new s("Invalid JSON-LD syntax; @context @language value must be a string or null.","jsonld.SyntaxError",{code:"invalid language mapping",context:t});null!==e&&(e=e.toLowerCase()),h["@language"]=e}if("@prefix"in a){if(n.match(/:|\//))throw new s("Invalid JSON-LD syntax; @context @prefix used on a compact IRI term","jsonld.SyntaxError",{code:"invalid term definition",context:t});if(w.isKeyword(h["@id"]))throw new s("Invalid JSON-LD syntax; keywords may not be used as prefixes","jsonld.SyntaxError",{code:"invalid term definition",context:t});if("boolean"!=typeof a["@prefix"])throw new s("Invalid JSON-LD syntax; @context value for @prefix must be boolean","jsonld.SyntaxError",{code:"invalid @prefix value",context:t});h._prefix=!0===a["@prefix"]}if("@direction"in a){const e=a["@direction"];if(null!==e&&"ltr"!==e&&"rtl"!==e)throw new s('Invalid JSON-LD syntax; @direction value must be null, "ltr", or "rtl".',"jsonld.SyntaxError",{code:"invalid base direction",context:t});h["@direction"]=e}if("@nest"in a){const e=a["@nest"];if(!l(e)||"@nest"!==e&&0===e.indexOf("@"))throw new s("Invalid JSON-LD syntax; @context @nest value must be a string which is not a keyword other than @nest.","jsonld.SyntaxError",{code:"invalid @nest value",context:t});h["@nest"]=e} +// disallow aliasing @context and @preserve +const x=h["@id"];if("@context"===x||"@preserve"===x)throw new s("Invalid JSON-LD syntax; @context and @preserve cannot be aliased.","jsonld.SyntaxError",{code:"invalid keyword alias",context:t});if(d&&d.protected&&!i&&(e.protected[n]=!0,h.protected=!0,!function e(t,n){if(!t||"object"!=typeof t||!n||"object"!=typeof n)return t===n;const r=Array.isArray(t);if(r!==Array.isArray(n))return!1;if(r){if(t.length!==n.length)return!1;for(let r=0;rj(e,t,n,void 0,void 0,r),w.getInitialContext=e=>{const t=JSON.stringify({processingMode:e.processingMode}),n=b.get(t);if(n)return n;const r={processingMode:e.processingMode,mappings:new Map,inverse:null,getInverse:function(){const e=this;if(e.inverse)return e.inverse;const t=e.inverse={},n=e.fastCurieMap={},r={},a=(e["@language"]||"@none").toLowerCase(),s=e["@direction"],c=e.mappings,u=[...c.keys()].sort(x);for(const e of u){const o=c.get(e);if(null===o)continue;let u=o["@container"]||"@none";if(u=[].concat(u).sort().join(""),null===o["@id"])continue;const l=m(o["@id"]);for(const c of l){let l=t[c];const d=w.isKeyword(c);if(l)d||o._termHasColon||r[c].push(e);else if(t[c]=l={},!d&&!o._termHasColon){r[c]=[e];const t={iri:c,terms:r[c]};c[0]in n?n[c[0]].push(t):n[c[0]]=[t]}if(l[u]||(l[u]={"@language":{},"@type":{},"@any":{}}),l=l[u],i(e,l["@any"],"@none"),o.reverse)i(e,l["@type"],"@reverse");else if("@none"===o["@type"])i(e,l["@any"],"@none"),i(e,l["@language"],"@none"),i(e,l["@type"],"@none");else if("@type"in o)i(e,l["@type"],o["@type"]);else if("@language"in o&&"@direction"in o){const t=o["@language"],n=o["@direction"];i(e,l["@language"],t&&n?`${t}_${n}`.toLowerCase():t?t.toLowerCase():n?"_"+n:"@null")}else"@language"in o?i(e,l["@language"],(o["@language"]||"@null").toLowerCase()):"@direction"in o?o["@direction"]?i(e,l["@language"],"_"+o["@direction"]):i(e,l["@language"],"@none"):s?(i(e,l["@language"],"_"+s),i(e,l["@language"],"@none"),i(e,l["@type"],"@none")):(i(e,l["@language"],a),i(e,l["@language"],"@none"),i(e,l["@type"],"@none"))}}for(const e in n)o(n,e,1);return t},clone:function(){const e={};e.mappings=a.clone(this.mappings),e.clone=this.clone,e.inverse=null,e.getInverse=this.getInverse,e.protected=a.clone(this.protected),this.previousContext&&(e.previousContext=this.previousContext.clone());e.revertToPreviousContext=this.revertToPreviousContext,"@base"in this&&(e["@base"]=this["@base"]);"@language"in this&&(e["@language"]=this["@language"]);"@vocab"in this&&(e["@vocab"]=this["@vocab"]);return e},revertToPreviousContext:function(){if(!this.previousContext)return this;return this.previousContext.clone()},protected:{}};return 1e4===b.size&&b.clear(),b.set(t,r),r;function o(e,t,n){const r=e[t],i=e[t]={};let a,s;for(const e of r)a=e.iri,s=n>=a.length?"":a[n],s in i?i[s].push(e):i[s]=[e];for(const e in i)""!==e&&o(i,e,n+1)}function i(e,t,n){t.hasOwnProperty(n)||(t[n]=e)}},w.getContextValue=(e,t,n)=>{if(null===t){if("@context"===n)return;return null}if(e.mappings.has(t)){const r=e.mappings.get(t);if(d(n))return r;if(r.hasOwnProperty(n))return r[n]}return"@language"===n&&n in e||"@direction"===n&&n in e?e[n]:"@context"!==n?null:void 0},w.processingMode=(e,t)=>t.toString()>="1.1"?!e.processingMode||e.processingMode>="json-ld-"+t.toString():"json-ld-1.0"===e.processingMode,w.isKeyword=e=>{if(!l(e)||"@"!==e[0])return!1;switch(e){case"@base":case"@container":case"@context":case"@default":case"@direction":case"@embed":case"@explicit":case"@graph":case"@id":case"@included":case"@index":case"@json":case"@language":case"@list":case"@nest":case"@none":case"@omitDefault":case"@prefix":case"@preserve":case"@protected":case"@requireAll":case"@reverse":case"@set":case"@type":case"@value":case"@version":case"@vocab":return!0}return!1}},function(e,t,n){"use strict";var r=n(11),o=n(5),i=n(119),a=n(54),s=n(55),c=n(70),u=n(13),l=n(123),d=Object.getOwnPropertyDescriptor;t.f=r?d:function(e,t){if(e=s(e),t=c(t),l)try{return d(e,t)}catch(e){}if(u(e,t))return a(!o(i.f,e,t),e[t])}},function(e,t,n){"use strict";var r=n(20),o=n(38);e.exports=function(e,t){var n=e[t];return o(n)?void 0:r(n)}},function(e,t,n){"use strict";var r=String;e.exports=function(e){try{return r(e)}catch(e){return"Object"}}},function(e,t,n){"use strict";var r=n(185),o=n(10),i=n(186);e.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var e,t=!1,n={};try{(e=r(Object.prototype,"__proto__","set"))(n,[]),t=n instanceof Array}catch(e){}return function(n,r){return o(n),i(r),t?e(n,r):n.__proto__=r,n}}():void 0)},function(e,t,n){"use strict";var r=n(69),o=Function.prototype,i=o.apply,a=o.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?a.bind(i):function(){return a.apply(i,arguments)})},function(e,t,n){"use strict";var r=n(48),o=n(20),i=n(69),a=r(r.bind);e.exports=function(e,t){return o(e),void 0===t?e:i?a(e,t):function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";var r=n(33),o=n(2);e.exports=function(e){if("Function"===r(e))return o(e)}},function(e,t,n){"use strict";var r,o=n(10),i=n(200),a=n(92),s=n(91),c=n(132),u=n(72),l=n(90),d=l("IE_PROTO"),f=function(){},p=function(e){return"