diff --git a/.gitignore b/.gitignore index c1f2078c66ab2bfdebafe285c2e2468c54d21508..35c4e8888e2c59e60f5e977b13b02d42864bd6d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /node_modules /dist +/cache coverage .nyc_output /cypress/screenshots @@ -7,3 +8,4 @@ coverage cypress/downloads .vscode .DS_Store +.npm diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c158bd76fad529d7776bbfcb2a64a4041d76e0ee..98a37e7e455ce6ee64afd663f86dba8b8b9cca96 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,6 +32,7 @@ test: before_script: - npm ci script: + - npm run lint - npm run check-types - npm run build - npm test diff --git a/.jshintrc b/.jshintrc index 53b202cb9fa3d1b2149361ca3027de37933f0a1f..2b6f469f0ce2d3d4c5828858c035c204bf976ff9 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,3 +1,3 @@ { "esversion": 6 -} \ No newline at end of file +} diff --git a/biome.jsonc b/biome.jsonc new file mode 100644 index 0000000000000000000000000000000000000000..19a07f8c359703c8f09ba9203c7427a726345418 --- /dev/null +++ b/biome.jsonc @@ -0,0 +1,51 @@ +{ + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": false + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "organizeImports": { + "enabled": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "noParameterAssign": "warn", + "noYodaExpression": "error", + "useExplicitLengthCheck": "error" + }, + "complexity": { + "noBannedTypes": "warn", + "noExcessiveCognitiveComplexity": "warn", + "noUselessUndefinedInitialization": "warn" + }, + "suspicious": { + "noConsoleLog": "warn", + "noExplicitAny": "warn", + "noAsyncPromiseExecutor": "warn", + "useAwait": "error" + }, + "correctness": { + "noUnusedFunctionParameters": "error", + "noUnusedVariables": "error", + "useImportExtensions": "error" + } + } + }, + "javascript": { + "formatter": { + "arrowParentheses": "asNeeded", + "quoteStyle": "single" + } + } +} diff --git a/cypress.config.ts b/cypress.config.ts index 9d7bb283a1d1bf5980cbfc6d8f59e9f642c5d6e5..27d7f890dc7d7bff5e52513c5e0f8364c2b53701 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,15 +1,12 @@ -import { defineConfig } from 'cypress' +import { defineConfig } from 'cypress'; export default defineConfig({ defaultCommandTimeout: 8000, screenshotOnRunFailure: false, video: false, e2e: { - specPattern: [ - "cypress/e2e/unit/*.cy.ts", - "cypress/e2e/e2e/*.cy.ts" - ], + specPattern: ['cypress/e2e/unit/*.cy.ts', 'cypress/e2e/e2e/*.cy.ts'], baseUrl: 'http://0.0.0.0:3000', experimentalRunAllSpecs: true, }, -}) +}); diff --git a/cypress/e2e/e2e/alias.cy.ts b/cypress/e2e/e2e/alias.cy.ts index 31796888a027a30537fba0a70c7f044c4fd9a064..0174c537f89d81c0adb115f5a50ae5c3b9b51dcb 100644 --- a/cypress/e2e/e2e/alias.cy.ts +++ b/cypress/e2e/e2e/alias.cy.ts @@ -1,96 +1,136 @@ -describe('alias', function() { +describe('alias', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/alias.html') + cy.visit('/examples/e2e/alias.html'); }); it('display users with alias', () => { - cy.get('#alias-test > div').children().eq(0) + cy.get('#alias-test > div') + .children() + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); - cy.get('#alias-test > div > solid-display > div').children().eq(0) + cy.get('#alias-test > div > solid-display > div') + .children() + .eq(0) .should('have.attr', 'name', '@id') .should('have.attr', 'value', '/examples/data/list/user-1.jsonld'); - cy.get('#alias-test > div > solid-display > div').children().eq(1) + cy.get('#alias-test > div > solid-display > div') + .children() + .eq(1) .should('have.attr', 'name', '@id as user_id') .should('have.attr', 'value', '/examples/data/list/user-1.jsonld'); - cy.get('#alias-test > div > solid-display > div').children().eq(2) + cy.get('#alias-test > div > solid-display > div') + .children() + .eq(2) .should('have.attr', 'name', 'username') .should('have.attr', 'value', 'admin'); - cy.get('#alias-test > div > solid-display > div').children().eq(3) + cy.get('#alias-test > div > solid-display > div') + .children() + .eq(3) .should('have.attr', 'name', 'username as strangename') .should('have.attr', 'value', 'admin'); - cy.get('#alias-test > div').children().eq(1) + cy.get('#alias-test > div') + .children() + .eq(1) .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); - cy.get('#alias-test > div').children().eq(1) + cy.get('#alias-test > div') + .children() + .eq(1) .find('div > solid-display-value:nth-child(2)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', '@id as user_id'); - expect($element).to.have.attr('value', '/examples/data/list/user-2.jsonld'); + expect($element).to.have.attr( + 'value', + '/examples/data/list/user-2.jsonld', + ); }); - cy.get('#alias-test > div').children().eq(1) + cy.get('#alias-test > div') + .children() + .eq(1) .find('div > solid-display-value:nth-child(4)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', 'username as strangename'); expect($element).to.have.attr('value', 'paris'); }); - cy.get('#alias-test > div').children().eq(2) + cy.get('#alias-test > div') + .children() + .eq(2) .find('div > solid-display-value:nth-child(2)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', '@id as user_id'); - expect($element).to.have.attr('value', '/examples/data/list/user-4.jsonld'); + expect($element).to.have.attr( + 'value', + '/examples/data/list/user-4.jsonld', + ); }); - cy.get('#alias-test > div').children().eq(2) + cy.get('#alias-test > div') + .children() + .eq(2) .find('div > solid-display-value:nth-child(4)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', 'username as strangename'); expect($element).to.have.attr('value', 'pierre'); }); }); it('display users with alias for additional fields and sets', () => { - cy.get('#alias-test-2 > div').children().eq(0) + cy.get('#alias-test-2 > div') + .children() + .eq(0) .find('div > solid-display-value:nth-child(6)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', 'email as ratatouille'); expect($element).to.have.attr('value', 'test-user@example.com'); }); - cy.get('#alias-test-2 > div').children().eq(1) + cy.get('#alias-test-2 > div') + .children() + .eq(1) .find('div > solid-display-value:nth-child(6)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', 'email as ratatouille'); expect($element).to.have.attr('value', 'paris@hilton.hi'); }); - cy.get('#alias-test-2 > div').children().eq(2) + cy.get('#alias-test-2 > div') + .children() + .eq(2) .find('div > solid-set-default > solid-display-value:nth-child(2)') - .should(($element) => { + .should($element => { expect($element).to.have.attr('name', 'username as strangename'); expect($element).to.have.attr('value', 'pierre'); }); }); it('display users with alias and custom widget on aliased field', () => { - cy.get('#alias-test-3 > div').children().eq(0) - .find('div:nth-child(1) > custom-widget:nth-child(2) > div:nth-child(1) > solid-display:nth-child(1) > div:nth-child(1) > solid-display-value:nth-child(4)') - .should(($element) => { + cy.get('#alias-test-3 > div') + .children() + .eq(0) + .find( + 'div:nth-child(1) > custom-widget:nth-child(2) > div:nth-child(1) > solid-display:nth-child(1) > div:nth-child(1) > solid-display-value:nth-child(4)', + ) + .should($element => { expect($element).to.have.attr('name', 'username as strangename'); expect($element).to.have.attr('value', 'admin'); - }); + }); - cy.get('#alias-test-3 > div').children().eq(3) - .find('div:nth-child(1) > custom-widget:nth-child(2) > div:nth-child(1) > solid-display:nth-child(1) > div:nth-child(1) > solid-display-value:nth-child(4)') - .should(($element) => { + cy.get('#alias-test-3 > div') + .children() + .eq(3) + .find( + 'div:nth-child(1) > custom-widget:nth-child(2) > div:nth-child(1) > solid-display:nth-child(1) > div:nth-child(1) > solid-display-value:nth-child(4)', + ) + .should($element => { expect($element).to.have.attr('name', 'username as strangename'); expect($element).to.have.attr('value', 'not-member-paris'); - }); + }); }); -}); \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/array-field.cy.ts b/cypress/e2e/e2e/array-field.cy.ts index 3c901a6b7f26a82754bbb1174ebdfbd3b48a7632..5f00e773c574df5e8b766f2d65ae295315375cdb 100644 --- a/cypress/e2e/e2e/array-field.cy.ts +++ b/cypress/e2e/e2e/array-field.cy.ts @@ -1,45 +1,85 @@ -describe('array-field', function() { +describe('array-field', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/array-field.html') + cy.visit('/examples/e2e/array-field.html'); }); it('array-[field]', () => { // data-src in solid-display pointed on user-*.jsonld - cy.get('#display-members > div').children().eq(0) + cy.get('#display-members > div') + .children() + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); - cy.get('#display-members > div').children().eq(1) - .should('have.attr','data-src', '/examples/data/list/user-1.jsonld'); + cy.get('#display-members > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); // Group's name not displayed - cy.get('#display-members > div').children().eq(0) - .find('solid-display-value').should('not.contain.value', 'LDP_circle_members_1'); - cy.get('#display-members > div').children().eq(1) - .find('solid-display-value').should('not.contain.value', 'LDP_circle_members_1'); + cy.get('#display-members > div') + .children() + .eq(0) + .find('solid-display-value') + .should('not.contain.value', 'LDP_circle_members_1'); + cy.get('#display-members > div') + .children() + .eq(1) + .find('solid-display-value') + .should('not.contain.value', 'LDP_circle_members_1'); // User's name displayed - cy.get('#display-members > div').children().eq(0) - .find('solid-display-value').should('have.attr', 'value', 'Benoit Alessandroni'); - cy.get('#display-members > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'Blaise Pascal'); + cy.get('#display-members > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'Benoit Alessandroni'); + cy.get('#display-members > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'Blaise Pascal'); }); it('array-field and order-asc', () => { - cy.get('#display-members-asc > div').children().eq(0) - .find('solid-display-value').should('have.attr', 'value', 'Benoit Alessandroni'); - cy.get('#display-members-asc > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'Blaise Pascal'); - cy.get('#display-members-asc > div').children().eq(2) - .find('solid-display-value').should('have.attr','value', 'Eric Cantona'); - cy.get('#display-members-asc > div').children().eq(3) - .find('solid-display-value').should('have.attr','value', 'Vitali Klitschko'); + cy.get('#display-members-asc > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'Benoit Alessandroni'); + cy.get('#display-members-asc > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'Blaise Pascal'); + cy.get('#display-members-asc > div') + .children() + .eq(2) + .find('solid-display-value') + .should('have.attr', 'value', 'Eric Cantona'); + cy.get('#display-members-asc > div') + .children() + .eq(3) + .find('solid-display-value') + .should('have.attr', 'value', 'Vitali Klitschko'); }); it('array-field and order-desc', () => { - cy.get('#display-members-desc > div').children().eq(0) - .find('solid-display-value').should('have.attr','value', 'Vitali Klitschko'); - cy.get('#display-members-desc > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'Eric Cantona'); - cy.get('#display-members-desc > div').children().eq(2) - .find('solid-display-value').should('have.attr','value', 'Blaise Pascal'); - cy.get('#display-members-desc > div').children().eq(3) - .find('solid-display-value').should('have.attr', 'value', 'Benoit Alessandroni'); + cy.get('#display-members-desc > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'Vitali Klitschko'); + cy.get('#display-members-desc > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'Eric Cantona'); + cy.get('#display-members-desc > div') + .children() + .eq(2) + .find('solid-display-value') + .should('have.attr', 'value', 'Blaise Pascal'); + cy.get('#display-members-desc > div') + .children() + .eq(3) + .find('solid-display-value') + .should('have.attr', 'value', 'Benoit Alessandroni'); }); }); diff --git a/cypress/e2e/e2e/auto-range.cy.ts b/cypress/e2e/e2e/auto-range.cy.ts index daea28fe74346993a15c5636d1bcf481eac97333..c2844b2c6338d0fdf966fb4b5104de2d169c6009 100644 --- a/cypress/e2e/e2e/auto-range.cy.ts +++ b/cypress/e2e/e2e/auto-range.cy.ts @@ -1,104 +1,165 @@ -describe('auto-range attribute', function() { +describe('auto-range attribute', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/auto-range.html') - }) + cy.visit('/examples/e2e/auto-range.html'); + }); it('solid-form-search + simple auto-range-[field]', () => { - cy.get('#simple-auto-range') - .should('have.attr', 'range-skills'); + cy.get('#simple-auto-range').should('have.attr', 'range-skills'); // one auto-range-[field] => one solid-form-dropdown - cy.get('#simple-auto-range > form') - .children().should('have.length', 1); + cy.get('#simple-auto-range > form').children().should('have.length', 1); cy.get('#simple-auto-range') .find('select') .should('have.attr', 'name', 'skills') - .children().should('have.length', 5); + .children() + .should('have.length', 5); // Skills value visible once in the dropdown - cy.get('#simple-auto-range > form > solid-form-dropdown > select > option').eq(1) + cy.get('#simple-auto-range > form > solid-form-dropdown > select > option') + .eq(1) .should('contain', 'HTML'); - cy.get('#simple-auto-range > form > solid-form-dropdown > select > option').eq(2) + cy.get('#simple-auto-range > form > solid-form-dropdown > select > option') + .eq(2) .should('contain', 'CSS'); - cy.get('#simple-auto-range > form > solid-form-dropdown > select > option').eq(3) + cy.get('#simple-auto-range > form > solid-form-dropdown > select > option') + .eq(3) .should('contain', 'DevOps'); - cy.get('#simple-auto-range > form > solid-form-dropdown > select > option').eq(4) + cy.get('#simple-auto-range > form > solid-form-dropdown > select > option') + .eq(4) .should('contain', 'Node'); // Each skill visible several times - cy.get('#auto-range1 > div') - .children().should('have.length', 3) - cy.get('#auto-range1 > div > solid-display').eq(0) + cy.get('#auto-range1 > div').children().should('have.length', 3); + cy.get('#auto-range1 > div > solid-display') + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld') - .find('solid-display[solid-container]').children().children().should('have.length', 1).and('contain', 'HTML') - cy.get('#auto-range1 > div > solid-display').eq(1) + .find('solid-display[solid-container]') + .children() + .children() + .should('have.length', 1) + .and('contain', 'HTML'); + cy.get('#auto-range1 > div > solid-display') + .eq(1) .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld') - .find('solid-display[solid-container]').children().children().should('have.length', 3).and('contain', 'HTML').and('contain', 'CSS').and('contain', 'DevOps') - cy.get('#auto-range1 > div > solid-display').eq(2) + .find('solid-display[solid-container]') + .children() + .children() + .should('have.length', 3) + .and('contain', 'HTML') + .and('contain', 'CSS') + .and('contain', 'DevOps'); + cy.get('#auto-range1 > div > solid-display') + .eq(2) .should('have.attr', 'data-src', '/examples/data/list/user-5.jsonld') - .find('solid-display[solid-container]').children().children().should('have.length', 3).and('contain', 'HTML').and('contain', 'DevOps').and('contain', 'Node') + .find('solid-display[solid-container]') + .children() + .children() + .should('have.length', 3) + .and('contain', 'HTML') + .and('contain', 'DevOps') + .and('contain', 'Node'); // User visible after selection - cy.get('#simple-auto-range') - .find('select').select('Node') - cy.get('#auto-range1 > div').children().should('have.length', 1) - cy.get('#auto-range1 > div > solid-display') - .should('have.attr', 'data-src', '/examples/data/list/user-5.jsonld') + cy.get('#simple-auto-range').find('select').select('Node'); + cy.get('#auto-range1 > div').children().should('have.length', 1); + cy.get('#auto-range1 > div > solid-display').should( + 'have.attr', + 'data-src', + '/examples/data/list/user-5.jsonld', + ); }); it('solid-form-search with 2 auto-range-[field] + 2 solid-display', () => { - cy.get('#double-auto-range').should('have.attr', 'range-skills') - cy.get('#double-auto-range').should('have.attr', 'range-profile') + cy.get('#double-auto-range').should('have.attr', 'range-skills'); + cy.get('#double-auto-range').should('have.attr', 'range-profile'); // two auto-range-[field] => two solid-form-dropdown - cy.get('#double-auto-range > form') - .children().should('have.length', 2); + cy.get('#double-auto-range > form').children().should('have.length', 2); cy.get('#double-auto-range') .find('select[name="profile"]') - .children().should('have.length', 6); + .children() + .should('have.length', 6); cy.get('#double-auto-range') .find('select[name="skills"]') - .children().should('have.length', 6); + .children() + .should('have.length', 6); // Each profile value visible once in the dropdown - cy.get('#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option').eq(1) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option', + ) + .eq(1) .should('contain', 'profile 1'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option').eq(2) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option', + ) + .eq(2) .should('contain', 'profile 2'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option').eq(3) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option', + ) + .eq(3) .should('contain', 'profile 3'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option').eq(4) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option', + ) + .eq(4) .should('contain', 'profile 4'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option').eq(5) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="profile"] > select > option', + ) + .eq(5) .should('contain', 'profile 5'); // Each skill value visible once in the dropdown - cy.get('#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option').eq(1) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option', + ) + .eq(1) .should('contain', 'CSS'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option').eq(2) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option', + ) + .eq(2) .should('contain', 'Javascript'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option').eq(3) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option', + ) + .eq(3) .should('contain', 'HTML'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option').eq(4) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option', + ) + .eq(4) .should('contain', 'DevOps'); - cy.get('#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option').eq(5) + cy.get( + '#double-auto-range > form > solid-form-dropdown[name="skills"] > select > option', + ) + .eq(5) .should('contain', 'Node'); // User(s) visible after selection + cy.get('#double-auto-range').find('select[name="skills"]').select('HTML'); + cy.get('#auto-range-double > div').children().should('have.length', 1); + cy.get('#auto-range-double > div > solid-display').should( + 'have.attr', + 'data-src', + '/examples/data/list/user-2.jsonld', + ); + cy.get('#auto-range-double2 > div').children().should('have.length', 3); + cy.get('#auto-range-double2 > div > solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); + cy.get('#auto-range-double2 > div > solid-display') + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); + cy.get('#auto-range-double2 > div > solid-display') + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/user-5.jsonld'); + cy.get('#double-auto-range') - .find('select[name="skills"]').select('HTML') - cy.get('#auto-range-double > div').children().should('have.length', 1) - cy.get('#auto-range-double > div > solid-display') - .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld') - cy.get('#auto-range-double2 > div').children().should('have.length', 3) - cy.get('#auto-range-double2 > div > solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld') - cy.get('#auto-range-double2 > div > solid-display').eq(1) - .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld') - cy.get('#auto-range-double2 > div > solid-display').eq(2) - .should('have.attr', 'data-src', '/examples/data/list/user-5.jsonld') - - cy.get('#double-auto-range') - .find('select[name="profile"]').select('profile 4') - cy.get('#auto-range-double > div').should('be.empty') - cy.get('#auto-range-double2 > div').children().should('have.length', 1) - cy.get('#auto-range-double2 > div > solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld') + .find('select[name="profile"]') + .select('profile 4'); + cy.get('#auto-range-double > div').should('be.empty'); + cy.get('#auto-range-double2 > div').children().should('have.length', 1); + cy.get('#auto-range-double2 > div > solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/binded-attributes.cy.ts b/cypress/e2e/e2e/binded-attributes.cy.ts index 1981f79f7816fc7f6f9b2cb3a0c91aabfa2fcfe7..e941166011e3d4a908e8bf32ece6c2fe31564d29 100644 --- a/cypress/e2e/e2e/binded-attributes.cy.ts +++ b/cypress/e2e/e2e/binded-attributes.cy.ts @@ -1,16 +1,26 @@ // TODO: We should make tests run independently of one another -describe('binded-attributes', { testIsolation: false }, function() { +describe('binded-attributes', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/binded-attributes.html') + cy.visit('/examples/e2e/binded-attributes.html'); }); it('replace store://resource and store://container and store://user', () => { cy.get('#events') - .should('have.attr', 'value-custom-id', '/examples/data/list/events.jsonld') + .should( + 'have.attr', + 'value-custom-id', + '/examples/data/list/events.jsonld', + ) .and('have.attr', 'value-child-date', 'store://resource.date'); - cy.get('#events solid-display[data-src="/examples/data/list/event-1.jsonld"]') - .should('have.attr', 'value-custom-id', '/examples/data/list/events.jsonld') + cy.get( + '#events solid-display[data-src="/examples/data/list/event-1.jsonld"]', + ) + .should( + 'have.attr', + 'value-custom-id', + '/examples/data/list/events.jsonld', + ) .and('have.attr', 'value-child-date', '2020-07-09'); cy.get('#events').contains('Workshop').click(); @@ -20,15 +30,21 @@ describe('binded-attributes', { testIsolation: false }, function() { .should('have.attr', 'data-src', '/examples/data/list/event-2.jsonld') .and('have.attr', 'value-custom-field', '2020-05-10') .and('have.attr', 'value-wrong-field', 'store://container.@id'); - cy.get('#infos solid-display-value[name="custom-field"]') - .should('have.text', '2020-05-10'); - cy.get('#infos solid-display-value[name="wrong-field"]') - .should('have.text', 'store://container.@id'); + cy.get('#infos solid-display-value[name="custom-field"]').should( + 'have.text', + '2020-05-10', + ); + cy.get('#infos solid-display-value[name="wrong-field"]').should( + 'have.text', + 'store://container.@id', + ); // Works in solid-table cy.get('#table') - .find('tr[data-resource="/examples/data/list/event-1.jsonld"] solid-display-value[name="temp"]') - .should('have.attr', 'value', '/examples/data/list/event-1.jsonld') + .find( + 'tr[data-resource="/examples/data/list/event-1.jsonld"] solid-display-value[name="temp"]', + ) + .should('have.attr', 'value', '/examples/data/list/event-1.jsonld'); // Reset attribute cy.get('solid-route').contains('Events').click(); @@ -36,19 +52,25 @@ describe('binded-attributes', { testIsolation: false }, function() { cy.get('#infos') .should('have.attr', 'data-src', '/examples/data/list/event-1.jsonld') .and('have.attr', 'value-custom-field', '2020-07-09'); - cy.get('#infos solid-display-value[name="custom-field"]') - .should('have.text', '2020-07-09'); - }) + cy.get('#infos solid-display-value[name="custom-field"]').should( + 'have.text', + '2020-07-09', + ); + }); it('replace store://user', () => { - cy.get('#infos') - .should('have.attr', 'value-user', 'Paris'); - cy.get('#infos solid-display-value[name="user"]') - .should('have.text', 'Paris'); - + cy.get('#infos').should('have.attr', 'value-user', 'Paris'); + cy.get('#infos solid-display-value[name="user"]').should( + 'have.text', + 'Paris', + ); + // Back home cy.get('solid-route[name=home]').click(); cy.get('[data-view=home] solid-delete button').should('have.text', 'admin'); - cy.get('[data-view=home] solid-form-search input[type=text]').should('have.value', 'Test'); - }) -}) + cy.get('[data-view=home] solid-form-search input[type=text]').should( + 'have.value', + 'Test', + ); + }); +}); diff --git a/cypress/e2e/e2e/default-data-context.cy.ts b/cypress/e2e/e2e/default-data-context.cy.ts index ac2e2888f10dfe142433887e97be2d7e9cbde070..43e7e70301f55d5e8069a6e7f68bc460ea98a475 100644 --- a/cypress/e2e/e2e/default-data-context.cy.ts +++ b/cypress/e2e/e2e/default-data-context.cy.ts @@ -1,13 +1,11 @@ -describe('default-data-context', function() { +describe('default-data-context', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/default-data-context.html') + cy.visit('/examples/e2e/default-data-context.html'); }); it('default-data-context', () => { - cy.get('solid-display > div').children().eq(0) - .contains('admin'); + cy.get('solid-display > div').children().eq(0).contains('admin'); - cy.get('solid-display > div').children().eq(1) - .contains('Test User'); + cy.get('solid-display > div').children().eq(1).contains('Test User'); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/event-reset-file.cy.ts b/cypress/e2e/e2e/event-reset-file.cy.ts index dc4e01f3488c49fe9c6c2c929c1554d5d0001770..b5c6508335fce0fa1fb7181aa9305536a1e2ce97 100644 --- a/cypress/e2e/e2e/event-reset-file.cy.ts +++ b/cypress/e2e/e2e/event-reset-file.cy.ts @@ -1,165 +1,179 @@ -describe('event-reset-file', { testIsolation: false }, function() { - this.beforeAll('visit', () => { - cy.visit('/examples/e2e/event-reset-file.html'); - cy.intercept('PUT', 'examples/data/list/event-1.jsonld', {}).as('put') - cy.intercept('PUT', 'examples/data/list/event-empty.jsonld', {}).as('put-empty') +describe('event-reset-file', { testIsolation: false }, function () { + this.beforeAll('visit', () => { + cy.visit('/examples/e2e/event-reset-file.html'); + cy.intercept('PUT', 'examples/data/list/event-1.jsonld', {}).as('put'); + cy.intercept('PUT', 'examples/data/list/event-empty.jsonld', {}).as( + 'put-empty', + ); + }); + + it('should reset form values to initial values after submit event', () => { + cy.get('#form-image').within(() => { + cy.get('input[name="someimage"]') + .should( + 'have.value', + 'https://cdn.startinblox.com/logos/spacelinkers.png', + ) + .type('New Name'); + cy.get('input[type="submit"]').click(); + cy.get('input[name="someimage"]').should( + 'have.value', + 'https://cdn.startinblox.com/logos/spacelinkers.png', + ); }); - - it('should reset form values to initial values after submit event', () => { - - cy.get('#form-image').within(() => { - cy.get('input[name="someimage"]').should('have.value', 'https://cdn.startinblox.com/logos/spacelinkers.png').type('New Name'); - cy.get('input[type="submit"]').click(); - cy.get('input[name="someimage"]').should('have.value', 'https://cdn.startinblox.com/logos/spacelinkers.png'); - }); - - cy.get('#form-1').within(() => { - cy.get('input[name="name"]').should('have.value', 'Coliving').type('New Name'); - cy.get('input[type="submit"]').click(); - - cy.get('input[name="name"]').should('have.value', 'Coliving'); - }); - - cy.get('#form-2').within(() => { - cy.get('input[name="name"]').as('nameInput'); - cy.get('@nameInput').should('have.value', ''); - cy.get('@nameInput').type('New Name'); - cy.get('input[type="submit"]').click(); - - cy.get('@nameInput').should('have.value', ''); - }); - - //[naked] - cy.get('#form-3').within(() => { - cy.get('input[name="name"]').as('nameInput'); - cy.get('@nameInput').type('New Name'); - cy.get('@nameInput').blur(); - - cy.get('@nameInput').should('have.value', 'Coliving'); - }); - - //[naked][autosave] - cy.get('#form-4').within(() => { - cy.get('input[name="name"]').as('nameInput'); - cy.get('@nameInput').clear(); - cy.get('@nameInput').type('New Name'); - cy.get('@nameInput').blur(); - - cy.get('@nameInput').should('have.value', 'New Name'); - }); - - cy.get('#form-5').within(() => { - cy.get('input[name="name"]').as('nameInput'); - cy.get('@nameInput').type('New Name'); - - cy.get('input[type="reset"]').click(); - cy.get('@nameInput').should('have.value', 'Coliving'); - - cy.get('@nameInput').type('New Name'); - cy.get('input[type="submit"]').click(); - cy.get('@nameInput').should('have.value', 'Coliving'); - }); - }); -}) -const Event3Response1 = { - "@id":"http://localhost:8000/events/3/", - "img":"/upload/b9e5d66dda.jpg", - "@context":"https://cdn.startinblox.com/owl/context.jsonld"}; + cy.get('#form-1').within(() => { + cy.get('input[name="name"]') + .should('have.value', 'Coliving') + .type('New Name'); + cy.get('input[type="submit"]').click(); -const Event4Response1 = { - "@id":"http://localhost:8000/events/4/", - "img":"https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg", - "@context":"https://cdn.startinblox.com/owl/context.jsonld"} + cy.get('input[name="name"]').should('have.value', 'Coliving'); + }); -const Event3Response2 = { - "@id":"http://localhost:8000/events/3/", - "img":"/new/url/image", - "@context":"https://cdn.startinblox.com/owl/context.jsonld"} + cy.get('#form-2').within(() => { + cy.get('input[name="name"]').as('nameInput'); + cy.get('@nameInput').should('have.value', ''); + cy.get('@nameInput').type('New Name'); + cy.get('input[type="submit"]').click(); -const Event4Response2 = { - "@id":"http://localhost:8000/events/4/", - "img":"/new/url/image2", - "@context":"https://cdn.startinblox.com/owl/context.jsonld"} + cy.get('@nameInput').should('have.value', ''); + }); + //[naked] + cy.get('#form-3').within(() => { + cy.get('input[name="name"]').as('nameInput'); + cy.get('@nameInput').type('New Name'); + cy.get('@nameInput').blur(); -describe('event-reset-file-with-route', { testIsolation: false }, function() { - this.beforeAll('visit', () => { - cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response1); - cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response1); - cy.visit('/examples/e2e/event-reset-file-with-route.html'); + cy.get('@nameInput').should('have.value', 'Coliving'); }); - - it('should update image source in image input in first route', () => { - cy.get('solid-route[name="route-1"]').click() - cy.get('#form-1').within(() => { - cy.get('input[name="img"]').as('nameInput'); - cy.get('@nameInput').should('have.value',"/upload/b9e5d66dda.jpg" ); - cy.get('@nameInput').type('/new/url/image'); - - cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response2); - cy.intercept('PUT', 'http://localhost:8000/events/3/', {}); - - cy.get('input[type="submit"]').click(); - cy.get('@nameInput').should('have.value',"/new/url/image" ); - }); + + //[naked][autosave] + cy.get('#form-4').within(() => { + cy.get('input[name="name"]').as('nameInput'); + cy.get('@nameInput').clear(); + cy.get('@nameInput').type('New Name'); + cy.get('@nameInput').blur(); + + cy.get('@nameInput').should('have.value', 'New Name'); }); - it('should update image source in image input in second route', () => { - cy.get('solid-route[name="route-2"]').click() - cy.get('#form-2').within(() => { - cy.get('input[name="img"]').as('nameInput2'); - cy.get('@nameInput2').should('have.value',"https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg" ); - cy.get('@nameInput2').type('/new/url/image2'); + cy.get('#form-5').within(() => { + cy.get('input[name="name"]').as('nameInput'); + cy.get('@nameInput').type('New Name'); - cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response2); - cy.intercept('PUT', 'http://localhost:8000/events/4/', {}); + cy.get('input[type="reset"]').click(); + cy.get('@nameInput').should('have.value', 'Coliving'); - cy.get('input[type="submit"]').click(); - cy.get('@nameInput2').should('have.value',"/new/url/image2" ); - }); + cy.get('@nameInput').type('New Name'); + cy.get('input[type="submit"]').click(); + cy.get('@nameInput').should('have.value', 'Coliving'); }); + }); +}); - it('should keep updated values when switch between routes', () => { - cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response1); - cy.intercept('GET', 'http://localhost:8000/events/4/',Event4Response1); - cy.visit('/examples/e2e/event-reset-file-with-route.html'); +const Event3Response1 = { + '@id': 'http://localhost:8000/events/3/', + img: '/upload/b9e5d66dda.jpg', + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', +}; - cy.get('solid-route[name="route-1"]').click() - cy.get('#form-1').within(() => { - cy.get('input[name="img"]').as('nameInput'); - cy.get('@nameInput').should('have.value',"/upload/b9e5d66dda.jpg" ); - cy.get('@nameInput').type('/new/url/image'); +const Event4Response1 = { + '@id': 'http://localhost:8000/events/4/', + img: 'https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg', + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', +}; + +const Event3Response2 = { + '@id': 'http://localhost:8000/events/3/', + img: '/new/url/image', + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', +}; - cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response2); - cy.intercept('PUT', 'http://localhost:8000/events/3/', {}); +const Event4Response2 = { + '@id': 'http://localhost:8000/events/4/', + img: '/new/url/image2', + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', +}; + +describe('event-reset-file-with-route', { testIsolation: false }, function () { + this.beforeAll('visit', () => { + cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response1); + cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response1); + cy.visit('/examples/e2e/event-reset-file-with-route.html'); + }); + + it('should update image source in image input in first route', () => { + cy.get('solid-route[name="route-1"]').click(); + cy.get('#form-1').within(() => { + cy.get('input[name="img"]').as('nameInput'); + cy.get('@nameInput').should('have.value', '/upload/b9e5d66dda.jpg'); + cy.get('@nameInput').type('/new/url/image'); + + cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response2); + cy.intercept('PUT', 'http://localhost:8000/events/3/', {}); + + cy.get('input[type="submit"]').click(); + cy.get('@nameInput').should('have.value', '/new/url/image'); + }); + }); + + it('should update image source in image input in second route', () => { + cy.get('solid-route[name="route-2"]').click(); + cy.get('#form-2').within(() => { + cy.get('input[name="img"]').as('nameInput2'); + cy.get('@nameInput2').should( + 'have.value', + 'https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg', + ); + cy.get('@nameInput2').type('/new/url/image2'); + + cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response2); + cy.intercept('PUT', 'http://localhost:8000/events/4/', {}); + + cy.get('input[type="submit"]').click(); + cy.get('@nameInput2').should('have.value', '/new/url/image2'); + }); + }); - cy.get('input[type="submit"]').click(); - cy.get('@nameInput').should('have.value',"/new/url/image" ); - }); + it('should keep updated values when switch between routes', () => { + cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response1); + cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response1); + cy.visit('/examples/e2e/event-reset-file-with-route.html'); - cy.get('solid-route[name="route-2"]').click() - cy.get('#form-2').within(() => { - cy.get('input[name="img"]').as('nameInput2'); - cy.get('@nameInput2').should('have.value',"https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg" ); - cy.get('@nameInput2').type('/new/url/image2'); + cy.get('solid-route[name="route-1"]').click(); + cy.get('#form-1').within(() => { + cy.get('input[name="img"]').as('nameInput'); + cy.get('@nameInput').should('have.value', '/upload/b9e5d66dda.jpg'); + cy.get('@nameInput').type('/new/url/image'); - cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response2); - cy.intercept('PUT', 'http://localhost:8000/events/4/', {}); + cy.intercept('GET', 'http://localhost:8000/events/3/', Event3Response2); + cy.intercept('PUT', 'http://localhost:8000/events/3/', {}); - cy.get('input[type="submit"]').click(); - cy.get('@nameInput2').should('have.value',"/new/url/image2" ); - }); + cy.get('input[type="submit"]').click(); + cy.get('@nameInput').should('have.value', '/new/url/image'); + }); + cy.get('solid-route[name="route-2"]').click(); + cy.get('#form-2').within(() => { + cy.get('input[name="img"]').as('nameInput2'); + cy.get('@nameInput2').should( + 'have.value', + 'https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg', + ); + cy.get('@nameInput2').type('/new/url/image2'); - cy.get('solid-route[name="route-1"]').click() - cy.get('@nameInput').should('have.value',"/new/url/image" ); - cy.get('solid-route[name="route-2"]').click() - cy.get('@nameInput2').should('have.value',"/new/url/image2" ); + cy.intercept('GET', 'http://localhost:8000/events/4/', Event4Response2); + cy.intercept('PUT', 'http://localhost:8000/events/4/', {}); + cy.get('input[type="submit"]').click(); + cy.get('@nameInput2').should('have.value', '/new/url/image2'); }); -}); - - - \ No newline at end of file + cy.get('solid-route[name="route-1"]').click(); + cy.get('@nameInput').should('have.value', '/new/url/image'); + cy.get('solid-route[name="route-2"]').click(); + cy.get('@nameInput2').should('have.value', '/new/url/image2'); + }); +}); diff --git a/cypress/e2e/e2e/extra-context.cy.ts b/cypress/e2e/e2e/extra-context.cy.ts index 86234b857299bded7990d1545a0782ec5206a292..c3da674672f6bbe91dd156c1390dccf4d3c34300 100644 --- a/cypress/e2e/e2e/extra-context.cy.ts +++ b/cypress/e2e/e2e/extra-context.cy.ts @@ -1,13 +1,11 @@ -describe('extra-context', function() { +describe('extra-context', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/extra-context.html') + cy.visit('/examples/e2e/extra-context.html'); }); it('default-data-context', () => { - cy.get('solid-display > div').children().eq(0) - .contains('admin'); + cy.get('solid-display > div').children().eq(0).contains('admin'); - cy.get('solid-display > div').children().eq(1) - .contains('Test User'); + cy.get('solid-display > div').children().eq(1).contains('Test User'); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/federation.cy.ts b/cypress/e2e/e2e/federation.cy.ts index 909451ce7e10e055fa9e88c04c376b60d98230c4..98cba05b2155b291ac6b0d526df47baaccdcf5e0 100644 --- a/cypress/e2e/e2e/federation.cy.ts +++ b/cypress/e2e/e2e/federation.cy.ts @@ -3,93 +3,141 @@ let beenCalled = false; describe('federation', { testIsolation: false }, function () { this.beforeAll('visit', () => { cy.visit('/examples/e2e/federation.html'); - }) + }); this.beforeEach(() => { - cy.intercept('http://server.com/skills', (req) => { + cy.intercept('http://server.com/skills', req => { beenCalled = true; req.reply({ body: { - "@context": "https://cdn.startinblox.com/owl/context.jsonld", - "@id": "http://server.com/skills", - "@type": "ldp:Container", - "ldp:contains": [ - {"@id": "http://server.com/skills/1", "name": "HTML"} - ] - } - }) - }) + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', + '@id': 'http://server.com/skills', + '@type': 'ldp:Container', + 'ldp:contains': [ + { '@id': 'http://server.com/skills/1', name: 'HTML' }, + ], + }, + }); + }); }); it('check children', () => { cy.get('#federation-1').as('federation'); - cy.get('@federation').find('> div').children().should('have.length', 4) - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]') + cy.get('@federation').find('> div').children().should('have.length', 4); + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-1.jsonld') .and('contain.text', 'Circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-2.jsonld') .and('contain.text', 'Another circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-3.jsonld') .and('contain.text', 'Circle from server 2'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-4.jsonld') .and('contain.text', 'Another circle from server 2'); }); it('supports nested sources', () => { cy.get('#federation-2').as('federation'); - cy.get('@federation').find('> div').children().should('have.length', 6) - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]') + cy.get('@federation').find('> div').children().should('have.length', 6); + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-1.jsonld') .and('contain.text', 'Circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-2.jsonld') .and('contain.text', 'Another circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-3.jsonld') .and('contain.text', 'Circle from server 2'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-4.jsonld') .and('contain.text', 'Another circle from server 2'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-5.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-5.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-5.jsonld') .and('contain.text', 'Circle from server 3'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-6.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-6.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-6.jsonld') .and('contain.text', 'Circle from server 4'); }); - it("can fail one source", () => { + it('can fail one source', () => { cy.intercept('GET', '/examples/data/federation/circles-server3.jsonld', { - statusCode: 403 - }) + statusCode: 403, + }); cy.reload(); cy.get('#federation-2').as('federation'); cy.get('@federation').find('> div').children().should('have.length', 5); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]') - .and('contain.text', '/examples/data/federation/circles-1.jsonld') - .and('contain.text', 'Circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-1.jsonld"]', + ) + .and('contain.text', '/examples/data/federation/circles-1.jsonld') + .and('contain.text', 'Circle from server 1'); + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-2.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-2.jsonld') .and('contain.text', 'Another circle from server 1'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-3.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-3.jsonld') .and('contain.text', 'Circle from server 2'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-4.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-4.jsonld') .and('contain.text', 'Another circle from server 2'); - cy.get('@federation').find('> div > solid-display[data-src="/examples/data/federation/circles-6.jsonld"]') + cy.get('@federation') + .find( + '> div > solid-display[data-src="/examples/data/federation/circles-6.jsonld"]', + ) .should('contain.text', '/examples/data/federation/circles-6.jsonld') .and('contain.text', 'Circle from server 4'); - }) + }); - it("does not fetch local federations", () => { + it('does not fetch local federations', () => { expect(beenCalled).to.be.false; - cy.get('#loadSkills').click() - cy.get('#federation-3 solid-display > div').children().should('have.length', 1).then(() => { - expect(beenCalled).to.be.true; - }) - }) -}) + cy.get('#loadSkills').click(); + cy.get('#federation-3 solid-display > div') + .children() + .should('have.length', 1) + .then(() => { + expect(beenCalled).to.be.true; + }); + }); +}); diff --git a/cypress/e2e/e2e/fields-string.cy.ts b/cypress/e2e/e2e/fields-string.cy.ts index a89334193ee2a8c60724d020dbedcb38c1943c60..0b82b312a8946ba0dddeb7961a4a061199d04b1e 100644 --- a/cypress/e2e/e2e/fields-string.cy.ts +++ b/cypress/e2e/e2e/fields-string.cy.ts @@ -1,25 +1,19 @@ -describe('fields-string', function() { +describe('fields-string', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/fields-string.html') + cy.visit('/examples/e2e/fields-string.html'); }); it('display strings', () => { cy.get('#list-1 > div').as('list1'); cy.get('#list-2 > div').as('list2'); - cy.get('@list1').children() - .should('have.length', 4); - cy.get('@list2').children() - .should('have.length', 4); + cy.get('@list1').children().should('have.length', 4); + cy.get('@list2').children().should('have.length', 4); - cy.get('@list1').find('>span').eq(0) - .should('have.text', 'Name: ') - cy.get('@list2').find('>span').eq(0) - .should('have.text', 'Name: ') + cy.get('@list1').find('>span').eq(0).should('have.text', 'Name: '); + cy.get('@list2').find('>span').eq(0).should('have.text', 'Name: '); - cy.get('@list1').find('>span').eq(1) - .should('have.text', ', description: ') - cy.get('@list2').find('>span').eq(1) - .should('have.text', ', description: ') + cy.get('@list1').find('>span').eq(1).should('have.text', ', description: '); + cy.get('@list2').find('>span').eq(1).should('have.text', ', description: '); }); -}) +}); diff --git a/cypress/e2e/e2e/filteredBy.cy.ts b/cypress/e2e/e2e/filteredBy.cy.ts index 7fe8f5197750d90b8f8d6646f39c0cd192386b8b..b5790490652a28c5b1715c295d1db8ce1cff4210 100644 --- a/cypress/e2e/e2e/filteredBy.cy.ts +++ b/cypress/e2e/e2e/filteredBy.cy.ts @@ -1,13 +1,23 @@ -describe('simple Startin’blox e2e test', function() { +describe('simple Startin’blox e2e test', () => { it('check children count', () => { - cy.visit('/examples/filtered.html') - cy.get('#filter1 input').type('ma#er') // match "mayer" - cy.get('#filter2 input').type('linds') // match "lindsay", "collins" & "rollins" - cy.get('main > div:nth-child(1) > solid-display > div > solid-display').its('length').should('eq', 1); - cy.get('main > div:nth-child(2) > solid-display > div > solid-display').its('length').should('eq', 1); - cy.get('#filter1 input').clear().type('john') // match "johnston.ashley" & "frye.johns" - cy.get('main > div:nth-child(1) > solid-display > div > solid-display').its('length').should('eq', 2); - cy.get('main > div:nth-child(2) > form input[value="filter2"]').click({force: true}); - cy.get('main > div:nth-child(2) > solid-display > div > solid-display').its('length').should('eq', 3); - }) -}) + cy.visit('/examples/filtered.html'); + cy.get('#filter1 input').type('ma#er'); // match "mayer" + cy.get('#filter2 input').type('linds'); // match "lindsay", "collins" & "rollins" + cy.get('main > div:nth-child(1) > solid-display > div > solid-display') + .its('length') + .should('eq', 1); + cy.get('main > div:nth-child(2) > solid-display > div > solid-display') + .its('length') + .should('eq', 1); + cy.get('#filter1 input').clear().type('john'); // match "johnston.ashley" & "frye.johns" + cy.get('main > div:nth-child(1) > solid-display > div > solid-display') + .its('length') + .should('eq', 2); + cy.get('main > div:nth-child(2) > form input[value="filter2"]').click({ + force: true, + }); + cy.get('main > div:nth-child(2) > solid-display > div > solid-display') + .its('length') + .should('eq', 3); + }); +}); diff --git a/cypress/e2e/e2e/group-by.cy.ts b/cypress/e2e/e2e/group-by.cy.ts index f362cbeda73c7f5508e03df9374ae30a5546520e..fa41cb6f298c43c5c2b95a16d0d2f6c3a1f779c2 100644 --- a/cypress/e2e/e2e/group-by.cy.ts +++ b/cypress/e2e/e2e/group-by.cy.ts @@ -1,30 +1,33 @@ -describe('group-by', function() { +describe('group-by', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/group-by.html') - }) + cy.visit('/examples/e2e/group-by.html'); + }); /** - * Groups resource at loading time - */ + * Groups resource at loading time + */ it('groups resources', () => { cy.get('#list-1 > div > solid-group-default') // get groups - .should('have.length', 3) // check number - .and('have.class', 'custom-group-class'); // and class + .should('have.length', 3) // check number + .and('have.class', 'custom-group-class'); // and class cy.get('#list-1 > div > solid-group-default:first-child > span') // check title span .should('have.length', 1) .contains('2020-07-09'); cy.get('#list-1 > div > solid-group-default:first-child > div') // check content div - .should('have.length', 1) - .and('have.attr', 'data-content'); - cy.get('#list-1 > div > solid-group-default:first-child > div > solid-display') // check solid-display - .should('have.length', 1); - }) + .should('have.length', 1) + .and('have.attr', 'data-content'); + cy.get( + '#list-1 > div > solid-group-default:first-child > div > solid-display', + ) // check solid-display + .should('have.length', 1); + }); /** - * Group and pagination work together - */ + * Group and pagination work together + */ it('groups resources and paginate', () => { - cy.get('#list-2 > div').within(() => { // in list-2 + cy.get('#list-2 > div').within(() => { + // in list-2 cy.get('> solid-group-default').eq(1).as('groupRow'); // get second group cy.get('@groupRow').find('nav').as('navPages'); // check if nav is here @@ -34,21 +37,30 @@ describe('group-by', function() { cy.get('@navPages').find('> span [data-id=count]').contains('2'); // Test content - cy.get('@groupRow').find('solid-display-value[name]').contains('Workshop'); + cy.get('@groupRow') + .find('solid-display-value[name]') + .contains('Workshop'); cy.get('@navPages').find('[data-id=next]').click(); }); - cy.get('#list-2 > div > solid-group-default').eq(1).find('solid-display-value[name]').contains('Assemblée générale'); + cy.get('#list-2 > div > solid-group-default') + .eq(1) + .find('solid-display-value[name]') + .contains('Assemblée générale'); }); - + /** - * Group widgets - */ + * Group widgets + */ it('groups resources in custom widgets', () => { cy.get('#list-3 > div > custom-group').should('have.length', 3); - cy.get('#list-3 > div > custom-group').eq(0).find('h2') - .should('contain', "2020") - cy.get('#list-3 > div > custom-group').eq(0).find('section') - .should('have.attr', "data-content"); - }) -}) + cy.get('#list-3 > div > custom-group') + .eq(0) + .find('h2') + .should('contain', '2020'); + cy.get('#list-3 > div > custom-group') + .eq(0) + .find('section') + .should('have.attr', 'data-content'); + }); +}); diff --git a/cypress/e2e/e2e/helpers.cy.ts b/cypress/e2e/e2e/helpers.cy.ts index dba41bdba17b6abd652e73f82cb92695769c8c52..ef0010687a7bf4747094954dc7f9b37809c95fbf 100644 --- a/cypress/e2e/e2e/helpers.cy.ts +++ b/cypress/e2e/e2e/helpers.cy.ts @@ -1,6 +1,6 @@ -import sleep from '../sleep' +import sleep from '../sleep.ts'; -describe('helpers', function() { +describe('helpers', function () { let helpers: typeof import('../../../src/libs/helpers'); let win: Window; let doc: Document; @@ -11,62 +11,68 @@ describe('helpers', function() { doc = win.document; ///@ts-ignore helpers = win.helpers; - doc - .querySelectorAll('script') - .forEach(script => script.remove()); + for (const script of doc.querySelectorAll('script')) script.remove(); }); }); describe('generalComparator Function Tests', () => { it('should compare two numbers correctly', () => { - expect(helpers.generalComparator(5, 10)).to.equal(-5); - expect(helpers.generalComparator(10, 5)).to.equal(5); - expect(helpers.generalComparator(5, 5)).to.equal(0); + expect(helpers.generalComparator(5, 10)).to.equal(-5); + expect(helpers.generalComparator(10, 5)).to.equal(5); + expect(helpers.generalComparator(5, 5)).to.equal(0); }); it('should compare two strings correctly', () => { - expect(helpers.generalComparator('apple', 'banana')).to.be.lessThan(0); - expect(helpers.generalComparator('panana', 'banana')).to.be.greaterThan(0); - expect(helpers.generalComparator('apple', 'apple')).to.equal(0); + expect(helpers.generalComparator('apple', 'banana')).to.be.lessThan(0); + expect(helpers.generalComparator('panana', 'banana')).to.be.greaterThan( + 0, + ); + expect(helpers.generalComparator('apple', 'apple')).to.equal(0); }); it('should compare dates correctly', () => { - const date1 = new Date('2024-01-01'); - const date2 = new Date('2024-12-31'); - expect(helpers.generalComparator(date1, date2)).to.be.lessThan(0); - expect(helpers.generalComparator(date2, date1)).to.be.greaterThan(0); - expect(helpers.generalComparator(date1, date1)).to.equal(0); + const date1 = new Date('2024-01-01'); + const date2 = new Date('2024-12-31'); + expect(helpers.generalComparator(date1, date2)).to.be.lessThan(0); + expect(helpers.generalComparator(date2, date1)).to.be.greaterThan(0); + expect(helpers.generalComparator(date1, date1)).to.equal(0); }); it('should compare booleans correctly', () => { - expect(helpers.generalComparator(true, false)).to.equal(1); - expect(helpers.generalComparator(false, true)).to.equal(-1); - expect(helpers.generalComparator(true, true)).to.equal(0); + expect(helpers.generalComparator(true, false)).to.equal(1); + expect(helpers.generalComparator(false, true)).to.equal(-1); + expect(helpers.generalComparator(true, true)).to.equal(0); }); it('should compare arrays by length', () => { - expect(helpers.generalComparator([1, 2], [1, 2, 3])).to.be.lessThan(0); - expect(helpers.generalComparator([1, 2, 3], [1, 2])).to.be.greaterThan(0); - expect(helpers.generalComparator([1, 2, 3], [4, 5, 6])).to.equal(0); + expect(helpers.generalComparator([1, 2], [1, 2, 3])).to.be.lessThan(0); + expect(helpers.generalComparator([1, 2, 3], [1, 2])).to.be.greaterThan(0); + expect(helpers.generalComparator([1, 2, 3], [4, 5, 6])).to.equal(0); }); it('should compare objects by number of keys', () => { - expect(helpers.generalComparator({ a: 1 }, { a: 1, b: 2 })).to.be.lessThan(0); - expect(helpers.generalComparator({ a: 1, b: 2 }, { a: 1 })).to.be.greaterThan(0); - expect(helpers.generalComparator({ a: 1, b: 2 }, { x: 10, y: 20 })).to.equal(0); + expect( + helpers.generalComparator({ a: 1 }, { a: 1, b: 2 }), + ).to.be.lessThan(0); + expect( + helpers.generalComparator({ a: 1, b: 2 }, { a: 1 }), + ).to.be.greaterThan(0); + expect( + helpers.generalComparator({ a: 1, b: 2 }, { x: 10, y: 20 }), + ).to.equal(0); }); it('should handle null or undefined values', () => { - expect(helpers.generalComparator(null, undefined)).to.equal(0); - expect(helpers.generalComparator(null, 1)).to.equal(-1); - expect(helpers.generalComparator(1, null)).to.equal(1); + expect(helpers.generalComparator(null, undefined)).to.equal(0); + expect(helpers.generalComparator(null, 1)).to.equal(-1); + expect(helpers.generalComparator(1, null)).to.equal(1); }); it('should handle different orders correctly', () => { - expect(helpers.generalComparator(5, 10, 'asc')).to.be.lessThan(0); - expect(helpers.generalComparator(5, 10, 'desc')).to.be.greaterThan(0); + expect(helpers.generalComparator(5, 10, 'asc')).to.be.lessThan(0); + expect(helpers.generalComparator(5, 10, 'desc')).to.be.greaterThan(0); }); -}); + }); describe('importCSS', () => { it('add one stylesheet', () => { @@ -96,9 +102,7 @@ describe('helpers', function() { const url = 'helpers.css'; helpers.importCSS(url); helpers.importCSS(url); - cy.get('link') - .its('length') - .should('eq', 1); + cy.get('link').its('length').should('eq', 1); }); }); @@ -107,12 +111,16 @@ describe('helpers', function() { helpers.importInlineCSS('test1', 'html {background-color: green}'); cy.get('html').should('have.css', 'background-color', 'rgb(0, 128, 0)'); }); - + it('avoid import stylesheet twice', () => { helpers.importInlineCSS('test2', 'html {background-color: green}'); helpers.importInlineCSS('test2', 'html {background-color: red}'); cy.get('html').should('have.css', 'background-color', 'rgb(0, 128, 0)'); - cy.get('html').should('not.have.css', 'background-color', 'rgb(255, 0, 0)'); + cy.get('html').should( + 'not.have.css', + 'background-color', + 'rgb(255, 0, 0)', + ); }); }); @@ -142,24 +150,22 @@ describe('helpers', function() { expect(srcs).deep.eq(urls.map(url => new URL(url, doc.baseURI).href)); }); }); - + it('add script only once', () => { const url = 'script'; helpers.importJS(url); helpers.importJS(url); - cy.get('script') - .its('length') - .should('eq', 1); + cy.get('script').its('length').should('eq', 1); }); }); - describe('defineComponent', function() { + describe('defineComponent', () => { it('define my-component', () => { expect(win.customElements.get('my-component')).to.be.undefined; helpers.defineComponent('my-component', class extends HTMLElement {}); expect(win.customElements.get('my-component')).to.not.be.undefined; }); - + it('show a warning', () => { const spy = cy.spy((win as Window & typeof globalThis).console, 'warn'); helpers.defineComponent('my-component', class extends HTMLElement {}); @@ -168,83 +174,96 @@ describe('helpers', function() { }); }); - - describe('asyncQuerySelector', function () { + describe('asyncQuerySelector', () => { it('select an element already in document', async () => { - const list = doc.querySelector('#async-qs ul')! - const list2 = await helpers.asyncQuerySelector('#async-qs ul') - expect(list2).to.equal(list) - }) + const list = doc.querySelector('#async-qs ul'); + const list2 = await helpers.asyncQuerySelector('#async-qs ul'); + expect(list2).to.equal(list); + }); it('select an element already in another element', async () => { - const list = doc.querySelector('#async-qs ul')! - const first1 = list.querySelector<HTMLLIElement>(':scope > :first-child') + const list = doc.querySelector('#async-qs ul') as HTMLUListElement; + const first1 = list.querySelector<HTMLLIElement>(':scope > :first-child'); const first2 = await helpers.asyncQuerySelector<HTMLLIElement>( ':scope > :first-child', list, - ) - expect(first2).to.equal(first1!) - }) + ); + expect(first2).to.equal(first1); + }); it('select an element not yet in the DOM', async () => { - const list = doc.querySelector('#async-qs ul')! - const li = doc.createElement('li') - li.classList.add('added') - setTimeout(() => list.append(li)) - const added1 = list.querySelector(':scope > .added') - expect(added1).to.be.null - const added2 = await helpers.asyncQuerySelector(':scope > .added', list) - const added3 = list.querySelector(':scope > .added') - expect(added2).to.equal(added3!) - }) + const list = doc.querySelector('#async-qs ul') as HTMLUListElement; + const li = doc.createElement('li'); + li.classList.add('added'); + setTimeout(() => list.append(li)); + const added1 = list.querySelector(':scope > .added'); + expect(added1).to.be.null; + const added2 = await helpers.asyncQuerySelector(':scope > .added', list); + const added3 = list.querySelector(':scope > .added'); + expect(added2).to.equal(added3); + }); it('select an element not yet matching selector', async () => { - const list = doc.querySelector('#async-qs ul')! - const li = doc.createElement('li') - list.append(li) - setTimeout(() => li.classList.add('classed')) - const classed1 = list.querySelector(':scope > .classed') - expect(classed1).to.be.null - const classed2 = await helpers.asyncQuerySelector(':scope > .classed', list) - const classed3 = list.querySelector(':scope > .classed') - expect(classed2).to.equal(classed3!) - }) + const list = doc.querySelector('#async-qs ul') as HTMLUListElement; + const li = doc.createElement('li'); + list.append(li); + setTimeout(() => li.classList.add('classed')); + const classed1 = list.querySelector(':scope > .classed'); + expect(classed1).to.be.null; + const classed2 = await helpers.asyncQuerySelector( + ':scope > .classed', + list, + ); + const classed3 = list.querySelector(':scope > .classed'); + expect(classed2).to.equal(classed3); + }); it('select an element generated by a solid-display', () => { cy.get('#async-qs').then(async div => { - const sd = div.append(/* html */ `<solid-display data-src="/examples/data/list/event-1.jsonld" + const sd = + div.append(/* html */ `<solid-display data-src="/examples/data/list/event-1.jsonld" fields="event, name, date" widget-date="solid-display-value-date" - >`)[0] - const sdv = await helpers.asyncQuerySelector('solid-display-value-date', sd) - expect(sdv).has.nested.property('component.name', 'date') - }) - }) - }) + >`)[0]; + const sdv = await helpers.asyncQuerySelector( + 'solid-display-value-date', + sd, + ); + expect(sdv).has.nested.property('component.name', 'date'); + }); + }); + }); describe('asyncQuerySelectorAll', () => { - const items: Element[] = [] + const items: Element[] = []; it('select currents and futures elements in DOM', async () => { - const list = doc.querySelector('#async-qs ol')! - ;(async () => { - for await (const li of helpers.asyncQuerySelectorAll('li', list)) items.push(li) - })() - await sleep() - expect(items).to.have.length(2) + const list = doc.querySelector('#async-qs ol'); + if (!list) throw new Error('no `#async-qs ol`'); + (async () => { + for await (const li of helpers.asyncQuerySelectorAll('li', list)) + items.push(li); + })(); + await sleep(); + expect(items).to.have.length(2); for (let index = 0; index < 3; index++) - list.append(doc.createElement('li')) - await sleep() - expect(items).to.have.length(5) - }) + list.append(doc.createElement('li')); + await sleep(); + expect(items).to.have.length(5); + }); it('select elements generated by a solid-display', () => { cy.get('#async-qs').then(async div => { - const sd = div.append(/* html */ `<solid-display data-src="/examples/data/list/users.jsonld">`)[0] - let limit = 20 - for await (const sdv of helpers.asyncQuerySelectorAll<HTMLElement>('solid-display-value', sd)) { - if (limit-- <= 0) break - expect(sdv).has.nested.property('component.name') - sdv.style.background = '#9f9' + const sd = div.append( + /* html */ `<solid-display data-src="/examples/data/list/users.jsonld">`, + )[0]; + let limit = 20; + for await (const sdv of helpers.asyncQuerySelectorAll<HTMLElement>( + 'solid-display-value', + sd, + )) { + if (limit-- <= 0) break; + expect(sdv).has.nested.property('component.name'); + sdv.style.background = '#9f9'; } - }) - }) - }) + }); + }); + }); }); diff --git a/cypress/e2e/e2e/navigate-active.cy.ts b/cypress/e2e/e2e/navigate-active.cy.ts index 477b3d0a9bcd3bd1deb0cce9efedf0b671c4a9e2..a57be6a0903da39d5dd1ce0b9425532e8fad026c 100644 --- a/cypress/e2e/e2e/navigate-active.cy.ts +++ b/cypress/e2e/e2e/navigate-active.cy.ts @@ -1,29 +1,53 @@ // TODO: We should make tests run independently of one another describe('uses active on navigate', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/active-navigate.html').as("loadPage") + cy.visit('/examples/e2e/active-navigate.html').as('loadPage'); }); it('set active by default | unset active on leaveRoute | set active on enterRoute', () => { - cy.get('solid-display[data-src="/examples/data/list/user-2.jsonld"]').should('exist').and('have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-1.jsonld"]').should('exist').and('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-3.jsonld"]').should('exist').and('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-4.jsonld"]').should('exist').and('not.have.attr', 'active'); + cy.get('solid-display[data-src="/examples/data/list/user-2.jsonld"]') + .should('exist') + .and('have.attr', 'active'); + cy.get('solid-display[data-src="/examples/data/list/user-1.jsonld"]') + .should('exist') + .and('not.have.attr', 'active'); + cy.get('solid-display[data-src="/examples/data/list/user-3.jsonld"]') + .should('exist') + .and('not.have.attr', 'active'); + cy.get('solid-display[data-src="/examples/data/list/user-4.jsonld"]') + .should('exist') + .and('not.have.attr', 'active'); }); - it("unset active on leaveRoute", () => { + it('unset active on leaveRoute', () => { cy.get('#leave-route').click(); - cy.get('solid-display[data-src="/examples/data/list/user-1.jsonld"]').should('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-2.jsonld"]').should('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-3.jsonld"]').should('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-4.jsonld"]').should('not.have.attr', 'active'); - }) + cy.get( + 'solid-display[data-src="/examples/data/list/user-1.jsonld"]', + ).should('not.have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-2.jsonld"]', + ).should('not.have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-3.jsonld"]', + ).should('not.have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-4.jsonld"]', + ).should('not.have.attr', 'active'); + }); - it("set active on enterRoute", () => { + it('set active on enterRoute', () => { cy.get('#enter-route').click(); - cy.get('solid-display[data-src="/examples/data/list/user-1.jsonld"]').should('have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-2.jsonld"]').should('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-3.jsonld"]').should('not.have.attr', 'active'); - cy.get('solid-display[data-src="/examples/data/list/user-4.jsonld"]').should('not.have.attr', 'active'); - }) -}) + cy.get( + 'solid-display[data-src="/examples/data/list/user-1.jsonld"]', + ).should('have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-2.jsonld"]', + ).should('not.have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-3.jsonld"]', + ).should('not.have.attr', 'active'); + cy.get( + 'solid-display[data-src="/examples/data/list/user-4.jsonld"]', + ).should('not.have.attr', 'active'); + }); +}); diff --git a/cypress/e2e/e2e/nested-field.cy.ts b/cypress/e2e/e2e/nested-field.cy.ts index 1261f17ae345c31844ce8e16fb7a3f0951e46aaf..2dd49149971e5b1d3b2af54ee0df7ae2f51deee5 100644 --- a/cypress/e2e/e2e/nested-field.cy.ts +++ b/cypress/e2e/e2e/nested-field.cy.ts @@ -1,43 +1,73 @@ -describe('nested-field', function() { +describe('nested-field', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/nested-field.html') + cy.visit('/examples/e2e/nested-field.html'); }); it('nested-[field]', () => { // data-src in solid-display pointed on skill-*.jsonld - cy.get('#display-skills > div').children().eq(0) + cy.get('#display-skills > div') + .children() + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld'); - cy.get('#display-skills > div').children().eq(1) - .should('have.attr','data-src', '/examples/data/list/skill-3.jsonld'); + cy.get('#display-skills > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld'); // User's name not displayed - cy.get('#display-skills > div').children().eq(0) - .find('solid-display-value').should('not.contain.value', 'Test User'); - cy.get('#display-skills > div').children().eq(1) - .find('solid-display-value').should('not.contain.value', 'Test User'); + cy.get('#display-skills > div') + .children() + .eq(0) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); + cy.get('#display-skills > div') + .children() + .eq(1) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); // Skills' name displayed - cy.get('#display-skills > div').children().eq(0) - .find('solid-display-value').should('have.attr', 'value', 'CSS'); - cy.get('#display-skills > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'Javascript'); + cy.get('#display-skills > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'CSS'); + cy.get('#display-skills > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'Javascript'); }); - it('nested-[field] on related object', () => { // data-src in solid-display pointed on skill-*.jsonld - cy.get('#display-job-skills > div').children().eq(0) + cy.get('#display-job-skills > div') + .children() + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld'); - cy.get('#display-job-skills > div').children().eq(1) - .should('have.attr','data-src', '/examples/data/list/skill-4.jsonld'); + cy.get('#display-job-skills > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld'); // User's name not displayed - cy.get('#display-job-skills > div').children().eq(0) - .find('solid-display-value').should('not.contain.value', 'Test User'); - cy.get('#display-job-skills > div').children().eq(1) - .find('solid-display-value').should('not.contain.value', 'Test User'); + cy.get('#display-job-skills > div') + .children() + .eq(0) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); + cy.get('#display-job-skills > div') + .children() + .eq(1) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); // Skills' name displayed - cy.get('#display-job-skills > div').children().eq(0) - .find('solid-display-value').should('have.attr', 'value', 'HTML'); - cy.get('#display-job-skills > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'DevOps'); + cy.get('#display-job-skills > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'HTML'); + cy.get('#display-job-skills > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'DevOps'); }); - }); diff --git a/cypress/e2e/e2e/next.cy.ts b/cypress/e2e/e2e/next.cy.ts index 576b2431c3bd2348b1133835d30e2a4d77d17d8a..c598d578ad3ced7e95bb9b9621a832a2ff2ea8c4 100644 --- a/cypress/e2e/e2e/next.cy.ts +++ b/cypress/e2e/e2e/next.cy.ts @@ -1,21 +1,24 @@ // TODO: We should make tests run independently of one another -describe('next', { testIsolation: false }, function() { +describe('next', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/next.html') + cy.visit('/examples/e2e/next.html'); }); it('goes to next', () => { cy.get('#list-1 > div').as('list'); - cy.get('@list').children() - .should('have.length', 8); + cy.get('@list').children().should('have.length', 8); // Check next in solid-display cy.get('@list').contains('PHP').click(); - cy.get('#detail > div').should('be.visible').should('contain', '/examples/data/list/skill-5.jsonld') - cy.location().should((loc) => { - expect(loc.hash).to.eq('#view/@%2Fexamples%2Fdata%2Flist%2Fskill-5.jsonld@') - }) + cy.get('#detail > div') + .should('be.visible') + .should('contain', '/examples/data/list/skill-5.jsonld'); + cy.location().should(loc => { + expect(loc.hash).to.eq( + '#view/@%2Fexamples%2Fdata%2Flist%2Fskill-5.jsonld@', + ); + }); }); it('uses the right id with nested components', () => { @@ -23,18 +26,26 @@ describe('next', { testIsolation: false }, function() { // Check next in solid-display cy.get('@list').contains('CSS').click(); - cy.get('#user-detail > div').should('be.visible').should('contain', '/examples/data/list/user-1.jsonld') - cy.location().should((loc) => { - expect(loc.hash).to.eq('#user/@%2Fexamples%2Fdata%2Flist%2Fuser-1.jsonld@') - }) + cy.get('#user-detail > div') + .should('be.visible') + .should('contain', '/examples/data/list/user-1.jsonld'); + cy.location().should(loc => { + expect(loc.hash).to.eq( + '#user/@%2Fexamples%2Fdata%2Flist%2Fuser-1.jsonld@', + ); + }); }); // Check next mixin on solid-display with keyboard it('next mixin accessibility', () => { cy.get('body').tab().tab().type('{enter}'); //.tab() from plugin to use tab keypress - cy.get('#detail > div').should('be.visible').should('contain', '/examples/data/list/skill-2.jsonld') - cy.location().should((loc) => { - expect(loc.hash).to.eq('#view/@%2Fexamples%2Fdata%2Flist%2Fskill-2.jsonld@') - }) + cy.get('#detail > div') + .should('be.visible') + .should('contain', '/examples/data/list/skill-2.jsonld'); + cy.location().should(loc => { + expect(loc.hash).to.eq( + '#view/@%2Fexamples%2Fdata%2Flist%2Fskill-2.jsonld@', + ); + }); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/no-render.cy.ts b/cypress/e2e/e2e/no-render.cy.ts index 8bf53b44a8c78c3731296f2b7101da90d7dd62c5..6605910e6ebaa934941979878fd8da11f2b84d9c 100644 --- a/cypress/e2e/e2e/no-render.cy.ts +++ b/cypress/e2e/e2e/no-render.cy.ts @@ -1,4 +1,4 @@ -describe('no-render', function() { +describe('no-render', function () { let win: Window; this.beforeEach('visit', () => { @@ -7,20 +7,22 @@ describe('no-render', function() { win = w; }); }); - + it('blocks rendering', () => { cy.spy(win.sibStore, 'fetchData'); - cy.get('#list').as('list') + cy.get('#list').as('list'); cy.wait(500); - cy.get('@list').children() - .should('have.length', 0); + cy.get('@list').children().should('have.length', 0); cy.get('@list').then($el => { expect(win.sibStore.fetchData).to.have.callCount(0); $el.removeAttr('no-render'); - cy.get('@list').find(' > div').children() - .should('have.length', 8).then(() => { + cy.get('@list') + .find(' > div') + .children() + .should('have.length', 8) + .then(() => { expect(win.sibStore.fetchData).to.be.called; }); }); @@ -29,30 +31,30 @@ describe('no-render', function() { it('blocks nested rendering', () => { cy.spy(win.sibStore, 'fetchData'); - cy.get('#nested-list').as('list') + cy.get('#nested-list').as('list'); cy.wait(500); - cy.get('@list').children() - .should('have.length', 0); + cy.get('@list').children().should('have.length', 0); cy.get('@list').then($el => { expect(win.sibStore.fetchData).to.have.callCount(0); $el.removeAttr('no-render'); - cy.get('@list').find(' > div').children() - .should('have.length', 4).then(() => { + cy.get('@list') + .find(' > div') + .children() + .should('have.length', 4) + .then(() => { expect(win.sibStore.fetchData).to.be.called; }); }); }); it('blocks rendering if no data-src', () => { - cy.get('#form').as('form') + cy.get('#form').as('form'); cy.wait(500); - cy.get('@form').children() - .should('have.length', 0); + cy.get('@form').children().should('have.length', 0); - cy.get('#form-search').as('form-search') - cy.wait(500); - cy.get('@form-search').children() - .should('have.length', 0); + cy.get('#form-search').as('form-search'); + cy.wait(500); + cy.get('@form-search').children().should('have.length', 0); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/order-by.cy.ts b/cypress/e2e/e2e/order-by.cy.ts index 33403a83232e14b91fb0b598881bdc96b4b49ea2..4f17cf305757c3578efafbbaea377d886f4f915c 100644 --- a/cypress/e2e/e2e/order-by.cy.ts +++ b/cypress/e2e/e2e/order-by.cy.ts @@ -1,92 +1,130 @@ // TODO: We should make tests run independently of one another -describe('order-by', { testIsolation: false }, function() { +describe('order-by', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/order-by.html') + cy.visit('/examples/e2e/order-by.html'); }); /** - * Order-asc - */ + * Order-asc + */ it('order-asc', () => { cy.get('#list-1 > div').as('list'); - cy.get('@list').children() - .should('have.length', 8); + cy.get('@list').children().should('have.length', 8); // Check elements order - cy.get('@list').find('solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-2.jsonld'); - cy.get('solid-display-value[name="name"]').contains('CSS'); - }); - - cy.get('@list').find('solid-display').eq(1) - .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-4.jsonld'); - cy.get('solid-display-value[name="name"]').contains('DevOps'); - }); - - cy.get('@list').find('solid-display').eq(2) - .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-6.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Git'); - }); - - cy.get('@list').find('solid-display').eq(3) - .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-1.jsonld'); - cy.get('solid-display-value[name="name"]').contains('HTML'); - }); - - cy.get('@list').find('solid-display').eq(4) - .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-3.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Javascript'); - }); - - cy.get('@list').find('solid-display').eq(5) - .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-8.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Node'); - }); - - cy.get('@list').find('solid-display').eq(6) - .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-5.jsonld'); - cy.get('solid-display-value[name="name"]').contains('PHP'); - }); - - cy.get('@list').find('solid-display').eq(7) - .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-7.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Python'); - }); + cy.get('@list') + .find('solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-2.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('CSS'); + }); + + cy.get('@list') + .find('solid-display') + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-4.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('DevOps'); + }); + + cy.get('@list') + .find('solid-display') + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-6.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Git'); + }); + + cy.get('@list') + .find('solid-display') + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-1.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('HTML'); + }); + + cy.get('@list') + .find('solid-display') + .eq(4) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-3.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Javascript'); + }); + + cy.get('@list') + .find('solid-display') + .eq(5) + .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-8.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Node'); + }); + + cy.get('@list') + .find('solid-display') + .eq(6) + .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-5.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('PHP'); + }); + + cy.get('@list') + .find('solid-display') + .eq(7) + .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-7.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Python'); + }); }); /** - * order-by-random - */ + * order-by-random + */ it('sorts resources by random', () => { cy.get('#list-2').as('list'); - cy.get('@list').find('> div').children() - .should('have.length', 8); - - cy.get('@list').find('> div > solid-display').then($div => { - let currentOrder = Array.from($div.map((_index, el) => el.dataset.src)) - cy.get('#reloadList').click(); - cy.get('@list').find('> div > solid-display').then($newDiv => { - let newOrder = Array.from($newDiv.map((_index, el) => el.dataset.src)) - expect(currentOrder).to.not.include.ordered.members(newOrder); - }) - }); + cy.get('@list').find('> div').children().should('have.length', 8); + + cy.get('@list') + .find('> div > solid-display') + .then($div => { + const currentOrder = Array.from( + $div.map((_index, el) => el.dataset.src), + ); + cy.get('#reloadList').click(); + cy.get('@list') + .find('> div > solid-display') + .then($newDiv => { + const newOrder = Array.from( + $newDiv.map((_index, el) => el.dataset.src), + ); + expect(currentOrder).to.not.include.ordered.members(newOrder); + }); + }); }); /** @@ -95,64 +133,95 @@ describe('order-by', { testIsolation: false }, function() { it('order-desc', () => { cy.get('#list-3 > div').as('list'); - cy.get('@list').children() - .should('have.length', 8); + cy.get('@list').children().should('have.length', 8); // Check elements order - cy.get('@list').find('solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-7.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Python'); - }); - - cy.get('@list').find('solid-display').eq(1) - .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-5.jsonld'); - cy.get('solid-display-value[name="name"]').contains('PHP'); - }); - - cy.get('@list').find('solid-display').eq(2) - .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-8.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Node'); - }); - - cy.get('@list').find('solid-display').eq(3) - .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-3.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Javascript'); - }); - - cy.get('@list').find('solid-display').eq(4) - .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-1.jsonld'); - cy.get('solid-display-value[name="name"]').contains('HTML'); - }); - - cy.get('@list').find('solid-display').eq(5) - .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-6.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Git'); - }); - - cy.get('@list').find('solid-display').eq(6) - .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-4.jsonld'); - cy.get('solid-display-value[name="name"]').contains('DevOps'); - }); - - cy.get('@list').find('solid-display').eq(7) - .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-2.jsonld'); - cy.get('solid-display-value[name="name"]').contains('CSS'); - }); + cy.get('@list') + .find('solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-7.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Python'); + }); + + cy.get('@list') + .find('solid-display') + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-5.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('PHP'); + }); + + cy.get('@list') + .find('solid-display') + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-8.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Node'); + }); + + cy.get('@list') + .find('solid-display') + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-3.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Javascript'); + }); + + cy.get('@list') + .find('solid-display') + .eq(4) + .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-1.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('HTML'); + }); + + cy.get('@list') + .find('solid-display') + .eq(5) + .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-6.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Git'); + }); + + cy.get('@list') + .find('solid-display') + .eq(6) + .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-4.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('DevOps'); + }); + + cy.get('@list') + .find('solid-display') + .eq(7) + .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-2.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('CSS'); + }); }); /** @@ -160,64 +229,95 @@ describe('order-by', { testIsolation: false }, function() { */ it('number', () => { cy.get('#list-4 > div').as('list'); - cy.get('@list').children() - .should('have.length', 8); + cy.get('@list').children().should('have.length', 8); // Check elements order - cy.get('@list').find('solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-1.jsonld'); - cy.get('solid-display-value[name="name"]').contains('HTML'); - }); - - cy.get('@list').find('solid-display').eq(1) - .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-3.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Javascript'); - }); - - cy.get('@list').find('solid-display').eq(2) - .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-2.jsonld'); - cy.get('solid-display-value[name="name"]').contains('CSS'); - }); - - cy.get('@list').find('solid-display').eq(3) - .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-4.jsonld'); - cy.get('solid-display-value[name="name"]').contains('DevOps'); - }); - - cy.get('@list').find('solid-display').eq(4) - .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-5.jsonld'); - cy.get('solid-display-value[name="name"]').contains('PHP'); - }); - - cy.get('@list').find('solid-display').eq(5) - .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-6.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Git'); - }); - - cy.get('@list').find('solid-display').eq(6) - .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-7.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Python'); - }); - - cy.get('@list').find('solid-display').eq(7) - .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-8.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Node'); - }); + cy.get('@list') + .find('solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-1.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('HTML'); + }); + + cy.get('@list') + .find('solid-display') + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-3.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Javascript'); + }); + + cy.get('@list') + .find('solid-display') + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-2.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('CSS'); + }); + + cy.get('@list') + .find('solid-display') + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-4.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('DevOps'); + }); + + cy.get('@list') + .find('solid-display') + .eq(4) + .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-5.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('PHP'); + }); + + cy.get('@list') + .find('solid-display') + .eq(5) + .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-6.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Git'); + }); + + cy.get('@list') + .find('solid-display') + .eq(6) + .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-7.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Python'); + }); + + cy.get('@list') + .find('solid-display') + .eq(7) + .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-8.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Node'); + }); }); /** @@ -226,64 +326,95 @@ describe('order-by', { testIsolation: false }, function() { it('order-by', () => { cy.get('#list-5 > div').as('list'); - cy.get('@list').children() - .should('have.length', 8); + cy.get('@list').children().should('have.length', 8); // Check elements order - cy.get('@list').find('solid-display').eq(0) - .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-2.jsonld'); - cy.get('solid-display-value[name="name"]').contains('CSS'); - }); - - cy.get('@list').find('solid-display').eq(1) - .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-4.jsonld'); - cy.get('solid-display-value[name="name"]').contains('DevOps'); - }); - - cy.get('@list').find('solid-display').eq(2) - .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-6.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Git'); - }); - - cy.get('@list').find('solid-display').eq(3) - .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-1.jsonld'); - cy.get('solid-display-value[name="name"]').contains('HTML'); - }); - - cy.get('@list').find('solid-display').eq(4) - .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-3.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Javascript'); - }); - - cy.get('@list').find('solid-display').eq(5) - .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-8.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Node'); - }); - - cy.get('@list').find('solid-display').eq(6) - .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-5.jsonld'); - cy.get('solid-display-value[name="name"]').contains('PHP'); - }); - - cy.get('@list').find('solid-display').eq(7) - .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') - .within(() => { - cy.get('solid-display-value[name="@id"]').contains('/examples/data/list/skill-7.jsonld'); - cy.get('solid-display-value[name="name"]').contains('Python'); - }); + cy.get('@list') + .find('solid-display') + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-2.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('CSS'); + }); + + cy.get('@list') + .find('solid-display') + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-4.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-4.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('DevOps'); + }); + + cy.get('@list') + .find('solid-display') + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/skill-6.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-6.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Git'); + }); + + cy.get('@list') + .find('solid-display') + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/skill-1.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-1.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('HTML'); + }); + + cy.get('@list') + .find('solid-display') + .eq(4) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-3.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Javascript'); + }); + + cy.get('@list') + .find('solid-display') + .eq(5) + .should('have.attr', 'data-src', '/examples/data/list/skill-8.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-8.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Node'); + }); + + cy.get('@list') + .find('solid-display') + .eq(6) + .should('have.attr', 'data-src', '/examples/data/list/skill-5.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-5.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('PHP'); + }); + + cy.get('@list') + .find('solid-display') + .eq(7) + .should('have.attr', 'data-src', '/examples/data/list/skill-7.jsonld') + .within(() => { + cy.get('solid-display-value[name="@id"]').contains( + '/examples/data/list/skill-7.jsonld', + ); + cy.get('solid-display-value[name="name"]').contains('Python'); + }); }); /** @@ -293,17 +424,41 @@ describe('order-by', { testIsolation: false }, function() { cy.get('#sorter select[name="field"]').select('username'); cy.get('#sorter select[name="order"]').select('desc'); cy.get('#list-6 > div').children().should('have.length', 4); - cy.get('#list-6 > div').children().eq(0).should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); - cy.get('#list-6 > div').children().eq(1).should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); - cy.get('#list-6 > div').children().eq(2).should('have.attr', 'data-src', '/examples/data/list/user-3.jsonld'); - cy.get('#list-6 > div').children().eq(3).should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/user-3.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); cy.get('#sorter select[name="field"]').select('email'); cy.get('#sorter select[name="order"]').select('asc'); cy.get('#list-6 > div').children().should('have.length', 4); - cy.get('#list-6 > div').children().eq(0).should('have.attr', 'data-src', '/examples/data/list/user-3.jsonld'); - cy.get('#list-6 > div').children().eq(1).should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); - cy.get('#list-6 > div').children().eq(2).should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); - cy.get('#list-6 > div').children().eq(3).should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/user-3.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/user-2.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(2) + .should('have.attr', 'data-src', '/examples/data/list/user-4.jsonld'); + cy.get('#list-6 > div') + .children() + .eq(3) + .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); }); -}) +}); diff --git a/cypress/e2e/e2e/paginate-by.cy.ts b/cypress/e2e/e2e/paginate-by.cy.ts index bd740a03d74b503d7dd824ec67b2bddf366e731b..194ab6ea2940592ee8e7aaa101c05e0aaa444452 100644 --- a/cypress/e2e/e2e/paginate-by.cy.ts +++ b/cypress/e2e/e2e/paginate-by.cy.ts @@ -1,37 +1,40 @@ // TODO: We should make tests run independently of one another -describe('paginate-by', { testIsolation: false }, function() { +describe('paginate-by', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/paginate-by.html') + cy.visit('/examples/e2e/paginate-by.html'); }); /** - * Paginates at loading time - */ + * Paginates at loading time + */ it('paginates resources', () => { - cy.get('#list-1 > nav').as('nav') - .should('have.length', 1); + cy.get('#list-1 > nav').as('nav').should('have.length', 1); // Check buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('have.length', 1) - .and('be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('have.length', 1) - .and('not.be.disabled'); + cy.get('@nav') + .find('button[data-id="prev"]') + .should('have.length', 1) + .and('be.disabled'); + cy.get('@nav') + .find('button[data-id="next"]') + .should('have.length', 1) + .and('not.be.disabled'); // Check page infos - cy.get('@nav').find('> span > span:first-child') - .should('have.attr', 'data-id', 'current') - .contains('1'); - - cy.get('@nav').find('> span > span:last-child') - .should('have.attr', 'data-id', 'count') - .contains('2'); + cy.get('@nav') + .find('> span > span:first-child') + .should('have.attr', 'data-id', 'current') + .contains('1'); + + cy.get('@nav') + .find('> span > span:last-child') + .should('have.attr', 'data-id', 'count') + .contains('2'); }); /** - * Navigate between pages - */ + * Navigate between pages + */ it('goes to prev/next page', () => { cy.get('#list-1').as('list'); cy.get('#list-1 > nav').as('nav'); @@ -50,17 +53,13 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('@list').contains('user-4.jsonld'); // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('not.be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('be.disabled'); + cy.get('@nav').find('button[data-id="prev"]').should('not.be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('be.disabled'); // Check pager infos - cy.get('@nav').find('> span [data-id=current]') - .contains('2'); + cy.get('@nav').find('> span [data-id=current]').contains('2'); - cy.get('@nav').find('> span [data-id=count]') - .contains('2'); + cy.get('@nav').find('> span [data-id=count]').contains('2'); // Click prev cy.get('@nav').find('button[data-id="prev"]').click(); @@ -71,22 +70,18 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('@list').contains('user-4.jsonld').should('not.exist'); // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('not.be.disabled'); + cy.get('@nav').find('button[data-id="prev"]').should('be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('not.be.disabled'); // Check pager infos - cy.get('@nav').find('> span [data-id=current]') - .contains('1'); + cy.get('@nav').find('> span [data-id=current]').contains('1'); - cy.get('@nav').find('> span [data-id=count]') - .contains('2'); + cy.get('@nav').find('> span [data-id=count]').contains('2'); }); /** - * Pagination loop - */ + * Pagination loop + */ it('loops pagination', () => { cy.get('#list-2').as('list'); cy.get('#list-2 > nav').as('nav'); @@ -105,17 +100,13 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('@list').contains('user-4.jsonld'); // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('not.be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('not.be.disabled'); + cy.get('@nav').find('button[data-id="prev"]').should('not.be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('not.be.disabled'); // Check pager infos - cy.get('@nav').find('> span [data-id=current]') - .contains('2'); + cy.get('@nav').find('> span [data-id=current]').contains('2'); - cy.get('@nav').find('> span [data-id=count]') - .contains('2'); + cy.get('@nav').find('> span [data-id=count]').contains('2'); // Click next again cy.get('@nav').find('button[data-id="next"]').click(); @@ -126,17 +117,13 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('@list').contains('user-4.jsonld').should('not.exist'); // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('not.be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('not.be.disabled'); + cy.get('@nav').find('button[data-id="prev"]').should('not.be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('not.be.disabled'); // Check pager infos - cy.get('@nav').find('> span [data-id=current]') - .contains('1'); + cy.get('@nav').find('> span [data-id=current]').contains('1'); - cy.get('@nav').find('> span [data-id=count]') - .contains('2'); + cy.get('@nav').find('> span [data-id=count]').contains('2'); // Click previous cy.get('@nav').find('button[data-id="prev"]').click(); @@ -147,22 +134,18 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('@list').contains('user-4.jsonld'); // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('not.be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('not.be.disabled'); + cy.get('@nav').find('button[data-id="prev"]').should('not.be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('not.be.disabled'); // Check pager infos - cy.get('@nav').find('> span [data-id=current]') - .contains('2'); + cy.get('@nav').find('> span [data-id=current]').contains('2'); - cy.get('@nav').find('> span [data-id=count]') - .contains('2'); + cy.get('@nav').find('> span [data-id=count]').contains('2'); }); /** - * Paginate and search - */ + * Paginate and search + */ it('search and paginate', () => { cy.get('#list-3').as('list'); cy.get('@list').find('button[data-id="next"]').click(); @@ -182,4 +165,4 @@ describe('paginate-by', { testIsolation: false }, function() { cy.get('#list-3 > nav').should('be.hidden'); }); -}) +}); diff --git a/cypress/e2e/e2e/reactivity-e2e.cy.ts b/cypress/e2e/e2e/reactivity-e2e.cy.ts index 089343835717fd327afbd80b0b9f5b5bc8a8c61c..b676d48d53e0443467c6e29e5d19f3052e06b5a4 100644 --- a/cypress/e2e/e2e/reactivity-e2e.cy.ts +++ b/cypress/e2e/e2e/reactivity-e2e.cy.ts @@ -2,231 +2,303 @@ describe('Reactivity e2e test2', { testIsolation: false }, function () { this.beforeAll('visit', () => { cy.intercept('GET', 'https://ldp-server2.test/users/', { - fixture: "users-nantes.jsonld" - }) + fixture: 'users-nantes.jsonld', + }); cy.intercept('GET', 'https://ldp-server.test/users/', { - fixture: "users-paris.jsonld" - }) + fixture: 'users-paris.jsonld', + }); cy.intercept('GET', '**/sources/users/', { - fixture: "users-source.jsonld" - }) + fixture: 'users-source.jsonld', + }); cy.intercept('GET', '**/users/matthieu/', { - fixture: "users-matthieu.jsonld" - }) + fixture: 'users-matthieu.jsonld', + }); cy.intercept('GET', '**/users/matthieu/circles/', { - fixture: "users-matthieu-circles.jsonld" - }) + fixture: 'users-matthieu-circles.jsonld', + }); cy.intercept('GET', '**/profiles/matthieu/', { - fixture: "profiles-matthieu.jsonld" - }) + fixture: 'profiles-matthieu.jsonld', + }); cy.intercept('GET', '**/profiles/jbpasquier/', { - fixture: "profiles-jbpasquier.jsonld" - }) + fixture: 'profiles-jbpasquier.jsonld', + }); cy.intercept('GET', '**/profiles/alex/', { - fixture: "profiles-alex.jsonld" - }) + fixture: 'profiles-alex.jsonld', + }); cy.intercept('GET', '**/circles/16/', { - fixture: "circles-16.jsonld" - }) + fixture: 'circles-16.jsonld', + }); cy.intercept('GET', '**/circles/17/members/', { - fixture: "circles-17-members.jsonld" - }) + fixture: 'circles-17-members.jsonld', + }); cy.visit('/examples/e2e/reactivity-e2e-test.html'); - }) + }); it('check display', () => { cy.intercept('GET', 'https://ldp-server2.test/users/', { - fixture: "users-nantes.jsonld" - }) + fixture: 'users-nantes.jsonld', + }); cy.intercept('GET', 'https://ldp-server.test/users/', { - fixture: "users-paris.jsonld" // add fixture in case everything is not loaded yet - }) - - cy.get('solid-display#user > div > solid-display-value:nth-child(1)').should('have.attr', 'name', 'first_name').should('contain', 'Matthieu'); - cy.get('solid-display#user > div > solid-display-value:nth-child(2)').should('have.attr', 'name', 'last_name').should('contain', 'Fesselier'); - cy.get('solid-display#user > div > solid-display-value:nth-child(3)').should('have.attr', 'name', 'username').should('contain', 'matthieu'); - cy.get('solid-display#user > div > solid-display-value:nth-child(4)').should('have.attr', 'name', 'profile.city').should('contain', 'Rennes'); - cy.get('solid-display#profile > div > solid-display-value:nth-child(1)').should('have.attr', 'name', 'city').should('contain', 'Rennes'); - cy.get('solid-display#circle > div > solid-display-value:nth-child(1)').should('have.attr', 'name', 'owner.profile.city').should('contain', 'Rennes'); - cy.get('solid-display#profile-widget > div > custom-widget').should('have.attr', 'name', 'profile'); - cy.get('solid-display#profile-widget > div > custom-widget > div').should('contain', 'Rennes'); + fixture: 'users-paris.jsonld', // add fixture in case everything is not loaded yet + }); + + cy.get('solid-display#user > div > solid-display-value:nth-child(1)') + .should('have.attr', 'name', 'first_name') + .should('contain', 'Matthieu'); + cy.get('solid-display#user > div > solid-display-value:nth-child(2)') + .should('have.attr', 'name', 'last_name') + .should('contain', 'Fesselier'); + cy.get('solid-display#user > div > solid-display-value:nth-child(3)') + .should('have.attr', 'name', 'username') + .should('contain', 'matthieu'); + cy.get('solid-display#user > div > solid-display-value:nth-child(4)') + .should('have.attr', 'name', 'profile.city') + .should('contain', 'Rennes'); + cy.get('solid-display#profile > div > solid-display-value:nth-child(1)') + .should('have.attr', 'name', 'city') + .should('contain', 'Rennes'); + cy.get('solid-display#circle > div > solid-display-value:nth-child(1)') + .should('have.attr', 'name', 'owner.profile.city') + .should('contain', 'Rennes'); + cy.get('solid-display#profile-widget > div > custom-widget').should( + 'have.attr', + 'name', + 'profile', + ); + cy.get('solid-display#profile-widget > div > custom-widget > div').should( + 'contain', + 'Rennes', + ); cy.get('solid-display#federation solid-display').should('have.length', 3); cy.get('solid-display#circles-user solid-display').should('have.length', 1); }); it('has reactive nested resources', () => { - cy.intercept("PATCH", '**/profiles/matthieu/', - { + cy.intercept('PATCH', '**/profiles/matthieu/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) + }); - cy.intercept("PATCH", '**/users/matthieu/', - { + cy.intercept('PATCH', '**/users/matthieu/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) - - cy.intercept("GET", '**/users/matthieu/', { - fixture: "users-matthieu.jsonld" - }) - cy.intercept("GET", '**/profiles/matthieu/', { - fixture: "profiles-matthieu-edited.jsonld" - }) - cy.intercept("GET", '**/sources/users/', { - fixture: "users-source.jsonld" - }) - cy.intercept("GET", 'https://ldp-server.test/users/', { - fixture: "users-paris.jsonld" - }) - cy.intercept("GET", 'https://ldp-server2.test/users/', { - fixture: "users-nantes.jsonld" - }) + }); + + cy.intercept('GET', '**/users/matthieu/', { + fixture: 'users-matthieu.jsonld', + }); + cy.intercept('GET', '**/profiles/matthieu/', { + fixture: 'profiles-matthieu-edited.jsonld', + }); + cy.intercept('GET', '**/sources/users/', { + fixture: 'users-source.jsonld', + }); + cy.intercept('GET', 'https://ldp-server.test/users/', { + fixture: 'users-paris.jsonld', + }); + cy.intercept('GET', 'https://ldp-server2.test/users/', { + fixture: 'users-nantes.jsonld', + }); cy.get('solid-form#profile-form input[name="city"]').clear().type('Paris'); cy.get('solid-form#profile-form input[type=submit]').click(); // Nested resource in dot field - cy.get('solid-display#user > div > solid-display-value[name="profile.city"]').should('contain', 'Paris'); + cy.get( + 'solid-display#user > div > solid-display-value[name="profile.city"]', + ).should('contain', 'Paris'); // Nested resource in nested field - cy.get('solid-display#profile > div > solid-display-value[name="city"]').should('contain', 'Paris'); + cy.get( + 'solid-display#profile > div > solid-display-value[name="city"]', + ).should('contain', 'Paris'); // Nested resource in custom widget - cy.get('solid-display#profile-widget > div > custom-widget[name="profile"] > div').should('contain', 'Paris'); + cy.get( + 'solid-display#profile-widget > div > custom-widget[name="profile"] > div', + ).should('contain', 'Paris'); // Nested field in form - cy.intercept("GET", '**/profiles/matthieu/', { - fixture: "profiles-matthieu-edited-2.jsonld" - }) - cy.get('solid-form#user-form-city input[name="profile.city"]').clear().type('Briouze'); + cy.intercept('GET', '**/profiles/matthieu/', { + fixture: 'profiles-matthieu-edited-2.jsonld', + }); + cy.get('solid-form#user-form-city input[name="profile.city"]') + .clear() + .type('Briouze'); cy.get('solid-form#user-form-city input[type=submit]').click(); - cy.get('solid-display#user > div > solid-display-value[name="profile.city"]').should('have.text', 'Briouze'); - cy.get('solid-display#profile > div > solid-display-value[name="city"]').should('have.text', 'Briouze'); - cy.get('solid-display#profile-widget > div > custom-widget[name="profile"] > div').should('have.text', 'Briouze'); + cy.get( + 'solid-display#user > div > solid-display-value[name="profile.city"]', + ).should('have.text', 'Briouze'); + cy.get( + 'solid-display#profile > div > solid-display-value[name="city"]', + ).should('have.text', 'Briouze'); + cy.get( + 'solid-display#profile-widget > div > custom-widget[name="profile"] > div', + ).should('have.text', 'Briouze'); // Nested resource in multi dot field // cy.get('solid-display#circle > solid-display-value[name="owner.profile.city"]').should('contain', 'Paris'); DOES NOT WORK YET }); it('has reactive properties', () => { - cy.intercept("GET", '**/users/matthieu/', { - fixture: "users-matthieu-edited.jsonld" - }) - cy.intercept("GET", '**/sources/users/', { - fixture: "users-source.jsonld" - }) - cy.intercept("GET", 'https://ldp-server.test/users/', { - fixture: "users-edited.jsonld" - }) - cy.intercept("GET", 'https://ldp-server2.test/users/', { - fixture: "users-nantes.jsonld" - }) - cy.intercept("GET", '**/users/jbpasquier/', { - fixture: "users-jbpasquier.jsonld" - }) + cy.intercept('GET', '**/users/matthieu/', { + fixture: 'users-matthieu-edited.jsonld', + }); + cy.intercept('GET', '**/sources/users/', { + fixture: 'users-source.jsonld', + }); + cy.intercept('GET', 'https://ldp-server.test/users/', { + fixture: 'users-edited.jsonld', + }); + cy.intercept('GET', 'https://ldp-server2.test/users/', { + fixture: 'users-nantes.jsonld', + }); + cy.intercept('GET', '**/users/jbpasquier/', { + fixture: 'users-jbpasquier.jsonld', + }); cy.intercept('GET', '**/profiles/jbpasquier/', { - fixture: "profiles-jbpasquier.jsonld" - }) - cy.intercept("GET", '**/users/alex/', { - fixture: "users-alex.jsonld" - }) + fixture: 'profiles-jbpasquier.jsonld', + }); + cy.intercept('GET', '**/users/alex/', { + fixture: 'users-alex.jsonld', + }); cy.intercept('GET', '**/profiles/alex/', { - fixture: "profiles-alex.jsonld" - }) + fixture: 'profiles-alex.jsonld', + }); - cy.intercept("PATCH", '**/users/matthieu/', { + cy.intercept('PATCH', '**/users/matthieu/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) + }); - cy.intercept("POST", "https://ldp-server.test/users/", { + cy.intercept('POST', 'https://ldp-server.test/users/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) + }); - cy.intercept("DELETE", "**/users/alex/", { + cy.intercept('DELETE', '**/users/alex/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) + }); // Fill matthieu's form - cy.get('solid-form#user-form input[name="first_name"]').clear().type('Test'); + cy.get('solid-form#user-form input[name="first_name"]') + .clear() + .type('Test'); cy.get('solid-form#user-form input[name="last_name"]').clear().type('User'); cy.get('solid-form#user-form input[name="username"]').clear().type('admin'); cy.get('solid-form#user-form input[type=submit]').click(); // Single solid-display - cy.get('solid-display#user > div > solid-display-value[name="first_name"]').should('contain', 'Test'); - cy.get('solid-display#user > div > solid-display-value[name="last_name"]').should('contain', 'User'); - cy.get('solid-display#user > div > solid-display-value[name="username"]').should('contain', 'admin'); + cy.get( + 'solid-display#user > div > solid-display-value[name="first_name"]', + ).should('contain', 'Test'); + cy.get( + 'solid-display#user > div > solid-display-value[name="last_name"]', + ).should('contain', 'User'); + cy.get( + 'solid-display#user > div > solid-display-value[name="username"]', + ).should('contain', 'admin'); // List solid-display & range - const src = "https://ldp-server.test/users/matthieu/"; - cy.get(`solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="first_name"]`).should('contain', 'Test'); - cy.get(`solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="last_name"]`).should('contain', 'User'); - cy.get(`solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="username"]`).should('contain', 'admin'); - cy.get(`solid-form#range option[value='{"@id": "${src}"}']`).should('contain', 'Test User'); + const src = 'https://ldp-server.test/users/matthieu/'; + cy.get( + `solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="first_name"]`, + ).should('contain', 'Test'); + cy.get( + `solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="last_name"]`, + ).should('contain', 'User'); + cy.get( + `solid-display#users solid-display[data-src="${src}"] > div > solid-display-value[name="username"]`, + ).should('contain', 'admin'); + cy.get(`solid-form#range option[value='{"@id": "${src}"}']`).should( + 'contain', + 'Test User', + ); // Federation - cy.get(`solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="first_name"]`).should('contain', 'Test'); - cy.get(`solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="last_name"]`).should('contain', 'User'); - cy.get(`solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="username"]`).should('contain', 'admin'); + cy.get( + `solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="first_name"]`, + ).should('contain', 'Test'); + cy.get( + `solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="last_name"]`, + ).should('contain', 'User'); + cy.get( + `solid-display#federation solid-display[data-src="${src}"] > div > solid-display-value[name="username"]`, + ).should('contain', 'admin'); // Fill new user form - cy.get('solid-form#users-form input[name="first_name"]').clear().type('Alex'); - cy.get('solid-form#users-form input[name="last_name"]').clear().type('Bourlier'); + cy.get('solid-form#users-form input[name="first_name"]') + .clear() + .type('Alex'); + cy.get('solid-form#users-form input[name="last_name"]') + .clear() + .type('Bourlier'); cy.get('solid-form#users-form input[name="username"]').clear().type('alex'); cy.get('solid-form#users-form input[type=submit]').click(); // List solid-display & range - const newSrc = "https://ldp-server.test/users/alex/"; - cy.get(`solid-display#users solid-display`).should('have.length', 3); - cy.get(`solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="first_name"]`).should('contain', 'Alex'); - cy.get(`solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="last_name"]`).should('contain', 'Bourlier'); - cy.get(`solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="username"]`).should('contain', 'alex'); - cy.get(`solid-form#range option`).should('have.length', 4); + const newSrc = 'https://ldp-server.test/users/alex/'; + cy.get('solid-display#users solid-display').should('have.length', 3); + cy.get( + `solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="first_name"]`, + ).should('contain', 'Alex'); + cy.get( + `solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="last_name"]`, + ).should('contain', 'Bourlier'); + cy.get( + `solid-display#users solid-display[data-src="${newSrc}"] > div > solid-display-value[name="username"]`, + ).should('contain', 'alex'); + cy.get('solid-form#range option').should('have.length', 4); // Federation - cy.get(`solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="first_name"]`).should('contain', 'Alex'); - cy.get(`solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="last_name"]`).should('contain', 'Bourlier'); - cy.get(`solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="username"]`).should('contain', 'alex'); + cy.get( + `solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="first_name"]`, + ).should('contain', 'Alex'); + cy.get( + `solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="last_name"]`, + ).should('contain', 'Bourlier'); + cy.get( + `solid-display#federation solid-display[data-src="${newSrc}"] > div > solid-display-value[name="username"]`, + ).should('contain', 'alex'); // delete user & range - cy.intercept("GET", 'https://ldp-server.test/users/', { - fixture: "users-paris.jsonld" - }) + cy.intercept('GET', 'https://ldp-server.test/users/', { + fixture: 'users-paris.jsonld', + }); cy.get('solid-delete#delete-user > button').click(); - cy.get(`solid-display#users solid-display`).should('have.length', 2); - cy.get(`solid-form#range option`).should('have.length', 3); + cy.get('solid-display#users solid-display').should('have.length', 2); + cy.get('solid-form#range option').should('have.length', 3); // cy.get(`solid-display#federation solid-display`).should('have.length', 3); NOT WORKING: should we loop on subscription index? }); it('makes virtual containers reactive', () => { - cy.intercept("GET", '**/users/matthieu/circles/', { - fixture: "users-matthieu-circles-edited.jsonld" - }) - cy.intercept("GET", '**/circles/17/members/', { - fixture: "circles-17-members.jsonld" - }) - - cy.intercept("POST", "https://ldp-server.test/circles/17/members/", { + cy.intercept('GET', '**/users/matthieu/circles/', { + fixture: 'users-matthieu-circles-edited.jsonld', + }); + cy.intercept('GET', '**/circles/17/members/', { + fixture: 'circles-17-members.jsonld', + }); + + cy.intercept('POST', 'https://ldp-server.test/circles/17/members/', { headers: { - "content-type": "application/ld+json" + 'content-type': 'application/ld+json', }, - }) + }); - cy.get('solid-form#circles-user-form input[name="name"]').clear().type('New circle'); + cy.get('solid-form#circles-user-form input[name="name"]') + .clear() + .type('New circle'); cy.get('solid-form#circles-user-form input[type=submit]').click(); cy.get('solid-display#circles-user solid-display').should('have.length', 2); }); -}) +}); diff --git a/cypress/e2e/e2e/search.cy.ts b/cypress/e2e/e2e/search.cy.ts index 7a01d6bd4bd3a790bb6a5743d9da393a6d466eab..6b03230c86d7cea0d021bd0e7df0cedf6007a46f 100644 --- a/cypress/e2e/e2e/search.cy.ts +++ b/cypress/e2e/e2e/search.cy.ts @@ -1,61 +1,72 @@ // TODO: We should make tests run independently of one another -describe('solid-form-search widget', { testIsolation: false }, function() { +describe('solid-form-search widget', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/search.html') - }) + cy.visit('/examples/e2e/search.html'); + }); it('solid-form-search', () => { cy.get('solid-form-search#filter1') .find('select') .should('have.attr', 'name', 'username') - .children().and('have.length', 6) + .children() + .and('have.length', 6); cy.get('solid-form-search#filter1') - .find('option').eq(0) + .find('option') + .eq(0) .should('have.attr', 'value', '') .contains('-'); cy.get('solid-form-search#filter1') - .find('option').eq(1) + .find('option') + .eq(1) .should('have.attr', 'value', 'admin') .contains('admin'); - + cy.get('solid-form-search#filter2') .find('select') .should('have.attr', 'name', 'last_name') - .children().and('have.length', 5); + .children() + .and('have.length', 5); cy.get('solid-form-search#filter2') - .find('option').eq(0) + .find('option') + .eq(0) .should('have.attr', 'value', '') .contains('-'); cy.get('solid-form-search#filter2') - .find('option').eq(1) + .find('option') + .eq(1) .should('have.attr', 'value', 'a') .contains('User'); }); it('solid-form-search + submit-button', () => { cy.get('#filter3') - .find('input[type=submit]').as('btn') + .find('input[type=submit]') + .as('btn') .should('have.attr', 'value', 'update result'); cy.get('#filter3 > form').find('div').children('input[type="submit"]'); cy.get('#display3 > div > solid-display').should('have.length', 4); cy.get('#filter3 select').select('User'); cy.get('#display3 > div > solid-display').should('have.length', 4); - cy.get('@btn').click() + cy.get('@btn').click(); cy.get('#display3 > div > solid-display').should('have.length', 1); }); it('solid-form-search + submit-widget', () => { - cy.get('solid-form-search#filter-submit-widget').find('input[type="submit"]') + cy.get('solid-form-search#filter-submit-widget') + .find('input[type="submit"]') .should('not.exist'); - cy.get('solid-form-search#filter-submit-widget').find('button[type="submit"]') + cy.get('solid-form-search#filter-submit-widget') + .find('button[type="submit"]') .should('exist') .and('have.text', 'OK'); }); it('solid-form-search + class-submit-button', () => { cy.get('solid-form-search#filter-class-submit-button') - .find('div').should('have.class', 'button-class') - .find('input').should('exist'); + .find('div') + .should('have.class', 'button-class') + .find('input') + .should('exist'); }); it('solid-form-search + start-value & end-value', () => { @@ -63,15 +74,13 @@ describe('solid-form-search widget', { testIsolation: false }, function() { .find('solid-form-rangedate') .should('have.attr', 'start-value', '2020-06-01') .and('have.attr', 'end-value', '2021-01-12'); - cy.get('#display4 > div ') - .children().should('have.length', 2) + cy.get('#display4 > div ').children().should('have.length', 2); cy.get('#filter5 > form') .find('solid-form-rangenumber') .should('have.attr', 'start-value', '2') .and('have.attr', 'end-value', '10'); - cy.get('#display5 > div ') - .children().should('have.length', 3) + cy.get('#display5 > div ').children().should('have.length', 3); }); it('solid-form-search + search-[field]', () => { @@ -79,28 +88,30 @@ describe('solid-form-search widget', { testIsolation: false }, function() { .find('solid-form-label-text') .should('have.attr', 'name', 'global_name') .find('input') - .type('em') + .type('em'); cy.get('#display-search-field-1 > div') - .children().should('have.length', 1) + .children() + .should('have.length', 1) .filter('solid-display[data-src="/examples/data/list/user-3.jsonld"]'); cy.get('#display-search-field-2 > div') - .children().should('have.length', 1) + .children() + .should('have.length', 1) .filter('solid-display[data-src="/examples/data/list/event-4.jsonld"]'); }); it('solid-form-search + solid-form-hidden', () => { - cy.get('#display-filter-hidden > div') - .children().should('have.length', 2) + cy.get('#display-filter-hidden > div').children().should('have.length', 2); cy.get('#display-filter-hidden-bool > div') - .children().should('have.length', 2) + .children() + .should('have.length', 2); cy.get('#display-filter-hidden-num > div') - .children().should('have.length', 2) + .children() + .should('have.length', 2); }); it('solid-form-search + fakeField', () => { - cy.get('#display-fake-field > div ') - .children().should('have.length', 4) + cy.get('#display-fake-field > div ').children().should('have.length', 4); cy.get('#filter-fake-field > form') .find('solid-form-label-text') @@ -108,91 +119,103 @@ describe('solid-form-search widget', { testIsolation: false }, function() { .find('input') .type('em'); - cy.get('#display-fake-field > div ') - .children().should('have.length', 0) + cy.get('#display-fake-field > div ').children().should('have.length', 0); }); it('solid-form-search + solid-form-hidden', () => { - cy.get('#display-filter-hidden > div') - .children().should('have.length', 2) + cy.get('#display-filter-hidden > div').children().should('have.length', 2); cy.get('#display-filter-hidden-bool > div') - .children().should('have.length', 2) + .children() + .should('have.length', 2); cy.get('#display-filter-hidden-num > div') - .children().should('have.length', 2) + .children() + .should('have.length', 2); }); it('solid-form-search + container', () => { - cy.get('#filter-container > div ') - .children().should('have.length', 4) + cy.get('#filter-container > div ').children().should('have.length', 4); - cy.get('#skill-search > form') - .find('select') - .select('HTML'); + cy.get('#skill-search > form').find('select').select('HTML'); - cy.get('#filter-container > div ') - .children().should('have.length', 2) + cy.get('#filter-container > div ').children().should('have.length', 2); }); it('solid-form-search + subject=null', () => { - cy.get('#display-null-subject solid-display-value[name="profile.available"][value=""]').should('exist') - cy.get('#filter-null-subject input').type("foo") - cy.get('#display-null-subject solid-display-value[name="profile.available"][value=""]').should('not.exist') + cy.get( + '#display-null-subject solid-display-value[name="profile.available"][value=""]', + ).should('exist'); + cy.get('#filter-null-subject input').type('foo'); + cy.get( + '#display-null-subject solid-display-value[name="profile.available"][value=""]', + ).should('not.exist'); }); it('solid-form-search + resource', () => { - cy.get('#display-profile-search > div').children().should('have.length', '1') - cy.get('#display-profile-search > div > solid-display').should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld') + cy.get('#display-profile-search > div') + .children() + .should('have.length', '1'); + cy.get('#display-profile-search > div > solid-display').should( + 'have.attr', + 'data-src', + '/examples/data/list/user-1.jsonld', + ); }); it('solid-form-search + number', () => { - cy.get('#number-search solid-form-label-text[name=username] input').type('123'); - cy.get('#display-number-search > div').children().should('have.length', 0) + cy.get('#number-search solid-form-label-text[name=username] input').type( + '123', + ); + cy.get('#display-number-search > div').children().should('have.length', 0); }); it('solid-form-search + empty-widget', () => { + cy.get('#span-empty-widget > div').children().should('have.length', 4); + cy.get('#filter-with-empty-widget').find('input').type('rrr'); cy.get('#span-empty-widget > div') - .children().should('have.length', 4); - cy.get('#filter-with-empty-widget') - .find('input').type('rrr'); - cy.get('#span-empty-widget > div') - .children().should('have.length', 1) + .children() + .should('have.length', 1) .and('contain', 'Pierre DLC'); - cy.get('#filter-with-empty-widget') - .find('input').type('r'); + cy.get('#filter-with-empty-widget').find('input').type('r'); cy.get('#span-empty-widget > span') - .children().should('have.length', 1) + .children() + .should('have.length', 1) .and('contain', 'No name found'); - cy.get('#filter-with-empty-widget') - .find('input').type('{backspace}'); + cy.get('#filter-with-empty-widget').find('input').type('{backspace}'); cy.get('#span-empty-widget > div') - .children().should('have.length', 1) + .children() + .should('have.length', 1) .and('contain', 'Pierre DLC'); - }) + }); it('solid-form-search + checkboxes', () => { cy.get('#enum-checkboxes-display > div') - .children().should('have.length', 8); + .children() + .should('have.length', 8); cy.get('#enum-checkboxes') - .find('input[value="HTML"]').check({ force: true }); + .find('input[value="HTML"]') + .check({ force: true }); cy.get('#enum-checkboxes-display > div') - .children().should('have.length', 1); + .children() + .should('have.length', 1); cy.get('#enum-checkboxes') - .find('input[value="CSS"]').check({ force: true }); + .find('input[value="CSS"]') + .check({ force: true }); cy.get('#enum-checkboxes-display > div') - .children().should('have.length', 2); - }) + .children() + .should('have.length', 2); + }); it('solid-form-search + debounce', () => { - const input = cy.get('#filter-debounce input') - input.type('p') - cy.wait(1000) - cy.get('#debounce>div>solid-display').should('not.have.length', 4) - input.type('hp') - cy.get('#debounce>div>solid-display').should('have.length', 1) + const input = cy.get('#filter-debounce input'); + input.type('p'); + cy.wait(1000); + cy.get('#debounce>div>solid-display').should('not.have.length', 4); + input.type('hp'); + cy.get('#debounce>div>solid-display').should('have.length', 1); }); it('solid-form-search + enter should not trigger default submit', () => { diff --git a/cypress/e2e/e2e/server-pagination.cy.ts b/cypress/e2e/e2e/server-pagination.cy.ts index 34c52c7a6b1e6e9db9f7391b6aa265732227abc2..f0dbae8f5ef2722a055cb27a8d7cf76775be8bbb 100644 --- a/cypress/e2e/e2e/server-pagination.cy.ts +++ b/cypress/e2e/e2e/server-pagination.cy.ts @@ -1,95 +1,112 @@ // TODO: We should make tests run independently of one another describe('server-pagination', { testIsolation: false }, function () { - this.beforeAll('visit', () => { - cy.visit('/examples/e2e/server-pagination.html') - }); - - /** - * Paginates from server - */ - it('paginates resources', () => { - cy.get('#list-1 > nav').as('nav') - .should('have.length', 1); - - // Check buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('have.length', 1) - .and('be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('have.length', 1) - .and('not.be.disabled'); - - // Check page infos - cy.get('@nav').find('> span') - .should('have.attr', 'data-id', 'current') - .contains('1'); - }); - - it('goes to prev/next page', () => { - cy.get('#list-1').as('list'); - cy.get('#list-1 > nav').as('nav'); - - // Click next -> To investigate how to answer paginated responses in the test context (static files) - cy.get('@list').contains('/examples/data/list/--user-0.jsonld'); - cy.get('@list').contains('/examples/data/list/--user-1.jsonld'); - cy.get('@list').contains('/examples/data/list/--user-2.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-3.jsonld').should('not.exist'); - // cy.get('@list').contains('user-4.jsonld').should('not.exist'); - - cy.get('@nav').find('button[data-id="next"]').click(); - - // Click next -> To investigate how to answer paginated responses in the test context (static files) - cy.get('@list').contains('/examples/data/list/--user-1.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-0.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-2.jsonld'); - cy.get('@list').contains('/examples/data/list/--user-3.jsonld'); - - // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('not.be.disabled'); - - // Check pager infos - cy.get('@nav').find('> [data-id=current]') - .contains('2'); - - // Click prev - cy.get('@nav').find('button[data-id="prev"]').click(); - - // Check pager buttons - cy.get('@nav').find('button[data-id="prev"]') - .should('be.disabled'); - cy.get('@nav').find('button[data-id="next"]') - .should('not.be.disabled'); - - // Check pager infos - cy.get('@nav').find('> [data-id=current]') - .contains('1'); - }); + this.beforeAll('visit', () => { + cy.visit('/examples/e2e/server-pagination.html'); + }); + + /** + * Paginates from server + */ + it('paginates resources', () => { + cy.get('#list-1 > nav').as('nav').should('have.length', 1); + + // Check buttons + cy.get('@nav') + .find('button[data-id="prev"]') + .should('have.length', 1) + .and('be.disabled'); + cy.get('@nav') + .find('button[data-id="next"]') + .should('have.length', 1) + .and('not.be.disabled'); + + // Check page infos + cy.get('@nav') + .find('> span') + .should('have.attr', 'data-id', 'current') + .contains('1'); + }); + + it('goes to prev/next page', () => { + cy.get('#list-1').as('list'); + cy.get('#list-1 > nav').as('nav'); + + // Click next -> To investigate how to answer paginated responses in the test context (static files) + cy.get('@list').contains('/examples/data/list/--user-0.jsonld'); + cy.get('@list').contains('/examples/data/list/--user-1.jsonld'); + cy.get('@list') + .contains('/examples/data/list/--user-2.jsonld') + .should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-3.jsonld') + .should('not.exist'); + // cy.get('@list').contains('user-4.jsonld').should('not.exist'); + + cy.get('@nav').find('button[data-id="next"]').click(); + + // Click next -> To investigate how to answer paginated responses in the test context (static files) + cy.get('@list') + .contains('/examples/data/list/--user-1.jsonld') + .should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-0.jsonld') + .should('not.exist'); + cy.get('@list').contains('/examples/data/list/--user-2.jsonld'); + cy.get('@list').contains('/examples/data/list/--user-3.jsonld'); + + // Check pager buttons + cy.get('@nav').find('button[data-id="prev"]').should('not.be.disabled'); + + // Check pager infos + cy.get('@nav').find('> [data-id=current]').contains('2'); + + // Click prev + cy.get('@nav').find('button[data-id="prev"]').click(); + + // Check pager buttons + cy.get('@nav').find('button[data-id="prev"]').should('be.disabled'); + cy.get('@nav').find('button[data-id="next"]').should('not.be.disabled'); + + // Check pager infos + cy.get('@nav').find('> [data-id=current]').contains('1'); + }); /** - * Paginate and search client-side - */ + * Paginate and search client-side + */ it('search and paginate', () => { cy.get('#list-2').as('list'); cy.get('@list').contains('/examples/data/list/--user-2.jsonld'); cy.get('@list').contains('/examples/data/list/--user-3.jsonld'); - + cy.get('@list').find('button[data-id="next"]').click(); - cy.get('@list').contains('/examples/data/list/--user-2.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-3.jsonld').should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-2.jsonld') + .should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-3.jsonld') + .should('not.exist'); cy.get('@list').contains('/examples/data/list/--user-6.jsonld'); cy.get('@list').contains('/examples/data/list/--user-7.jsonld'); - + // search cy.get('#username-form').find('input[name="username"]').type('henry'); - cy.get('@list').contains('/examples/data/list/--user-10.jsonld').should('exist'); - cy.get('@list').contains('/examples/data/list/--user-6.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-7.jsonld').should('not.exist'); - cy.get('@list').contains('/examples/data/list/--user-8.jsonld').should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-10.jsonld') + .should('exist'); + cy.get('@list') + .contains('/examples/data/list/--user-6.jsonld') + .should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-7.jsonld') + .should('not.exist'); + cy.get('@list') + .contains('/examples/data/list/--user-8.jsonld') + .should('not.exist'); //TODO: Improvement: hide the navigation when searching // cy.get('#list-2 > nav').should('be.hidden'); }); -}); \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/server-search.cy.ts b/cypress/e2e/e2e/server-search.cy.ts index 7da1dce22093ff7235681024e90e7905e230bfe2..a0cd329302e3d9b98c1944c0195dff739d707bdb 100644 --- a/cypress/e2e/e2e/server-search.cy.ts +++ b/cypress/e2e/e2e/server-search.cy.ts @@ -1,47 +1,49 @@ describe('server-search', function () { - this.beforeEach('visit', () => { - cy.visit('/examples/e2e/server-search.html'); - }) - - /** - * Server Search only test - */ - it('server search', () => { - // Get forms - cy.get("#search-form-1").as('forms'); - - // Check firstname field - cy.get("@forms").find("input[name='first_name']").as('first_name') - cy.get('@first_name').type('Santiago') - - // Start Search - cy.get('@forms').find('input[type="submit"]').as("forms_submit") - cy.get('@forms_submit').click() - - // Check result - cy.get('#result1') - .should('have.attr', 'data-src', '/mock/users.jsonld') - .find('div > solid-display').should('have.length', 1); - }) - - /** - * Server Search with Server pagination test - */ - it('server-search with server-pagination', () => { - // Get forms - cy.get("#search-form-2").as('forms'); - - // Check firstname field - cy.get("@forms").find("input[name='first_name']").as('first_name') - cy.get('@first_name').type('an') - - // Start Search - cy.get('@forms').find('input[type="submit"]').as("forms_submit") - cy.get('@forms_submit').click() - - // Check result - cy.get('#result2') - .should('have.attr', 'data-src', '/mock/users.jsonld') - .find('div > solid-display').should('have.length', 5); - }); -}) \ No newline at end of file + this.beforeEach('visit', () => { + cy.visit('/examples/e2e/server-search.html'); + }); + + /** + * Server Search only test + */ + it('server search', () => { + // Get forms + cy.get('#search-form-1').as('forms'); + + // Check firstname field + cy.get('@forms').find("input[name='first_name']").as('first_name'); + cy.get('@first_name').type('Santiago'); + + // Start Search + cy.get('@forms').find('input[type="submit"]').as('forms_submit'); + cy.get('@forms_submit').click(); + + // Check result + cy.get('#result1') + .should('have.attr', 'data-src', '/mock/users.jsonld') + .find('div > solid-display') + .should('have.length', 1); + }); + + /** + * Server Search with Server pagination test + */ + it('server-search with server-pagination', () => { + // Get forms + cy.get('#search-form-2').as('forms'); + + // Check firstname field + cy.get('@forms').find("input[name='first_name']").as('first_name'); + cy.get('@first_name').type('an'); + + // Start Search + cy.get('@forms').find('input[type="submit"]').as('forms_submit'); + cy.get('@forms_submit').click(); + + // Check result + cy.get('#result2') + .should('have.attr', 'data-src', '/mock/users.jsonld') + .find('div > solid-display') + .should('have.length', 5); + }); +}); diff --git a/cypress/e2e/e2e/sib-register.cy.ts b/cypress/e2e/e2e/sib-register.cy.ts index fb785b1d7b533478a3803a471a01abd84b3e07a6..3f08ab8e5422faabadb3835a6abaa0df4f64e676 100644 --- a/cypress/e2e/e2e/sib-register.cy.ts +++ b/cypress/e2e/e2e/sib-register.cy.ts @@ -1,4 +1,4 @@ -describe('Component factory', function() { +describe('Component factory', function () { let Sib: typeof import('../../../src/libs/Sib').Sib; let win: Window; let doc: Document; @@ -11,9 +11,8 @@ describe('Component factory', function() { cnsl = (win as Window & typeof globalThis).console; ///@ts-ignore Sib = win.Sib; - win.document - .querySelectorAll('script') - .forEach(script => script.remove()); + for (const script of win.document.querySelectorAll('script')) + script.remove(); }); }); diff --git a/cypress/e2e/e2e/simple-startinblox-e2e.cy.ts b/cypress/e2e/e2e/simple-startinblox-e2e.cy.ts index c45081bca6b7931b63c0010a42d0a6a58103dd0c..b6508c704626ec73cbe082874fd2eaad3a5790ed 100644 --- a/cypress/e2e/e2e/simple-startinblox-e2e.cy.ts +++ b/cypress/e2e/e2e/simple-startinblox-e2e.cy.ts @@ -1,15 +1,17 @@ -describe('simple Startin’blox e2e test', function() { +describe('simple Startin’blox e2e test', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/simple-startinblox-e2e-test.html') - }) + cy.visit('/examples/e2e/simple-startinblox-e2e-test.html'); + }); it('check children count', () => { - cy.get('body > solid-display > div').children().should('have.length', 4) - }) + cy.get('body > solid-display > div').children().should('have.length', 4); + }); it('check first children content', () => { - cy.get('body > solid-display > div > solid-display:first-child > div > solid-display-value:first-child') + cy.get( + 'body > solid-display > div > solid-display:first-child > div > solid-display-value:first-child', + ) .should('have.attr', 'name', 'first_name') - .should('contain', 'Test') - }) -}) + .should('contain', 'Test'); + }); +}); diff --git a/cypress/e2e/e2e/solid-ac-checker.cy.ts b/cypress/e2e/e2e/solid-ac-checker.cy.ts index 3c691a366aebc0353e81931a560bca7a0d7e358e..962b8c8371c6e330b5f1964a042316b4b04d9421 100644 --- a/cypress/e2e/e2e/solid-ac-checker.cy.ts +++ b/cypress/e2e/e2e/solid-ac-checker.cy.ts @@ -1,6 +1,6 @@ -describe('solid-ac-checker', function() { +describe('solid-ac-checker', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/solid-ac-checker.html') + cy.visit('/examples/e2e/solid-ac-checker.html'); }); it('permission attribute', () => { @@ -20,4 +20,4 @@ describe('solid-ac-checker', function() { cy.get('#ac-checker-3').should('not.have.attr', 'hidden'); cy.get('#test3').should('be.visible'); }); -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/solid-delete.cy.ts b/cypress/e2e/e2e/solid-delete.cy.ts index d95e10cf2c97dd02093aaa672b27bf8e7f3fba67..f7e986dce8dc8cd70d59edaf77cc5faffc581e23 100644 --- a/cypress/e2e/e2e/solid-delete.cy.ts +++ b/cypress/e2e/e2e/solid-delete.cy.ts @@ -11,18 +11,19 @@ describe('solid-delete', function () { it('calls store.delete and send events', () => { cy.spy(win.sibStore, 'delete'); - cy.intercept("DELETE", '**/project.jsonld', - { - statusCode: 204 - }) + cy.intercept('DELETE', '**/project.jsonld', { + statusCode: 204, + }); // button created cy.get('solid-delete#test1').find('button').should('have.length', 1); cy.get('solid-delete#test1 button').should('have.text', 'Supprimer'); // on click, store.delete is called - cy.get('solid-delete#test1 button').click({ force: true }).then(() => { - expect(win.sibStore.delete).to.be.called; - }); + cy.get('solid-delete#test1 button') + .click({ force: true }) + .then(() => { + expect(win.sibStore.delete).to.be.called; + }); // events have been fired cy.get('#res') .should('contain', 'save: /examples/data/project.jsonld') @@ -33,12 +34,11 @@ describe('solid-delete', function () { it('does not send events on failure', () => { cy.reload(); - cy.intercept("DELETE", '**/project.jsonld', - { - statusCode: 403 - }) + cy.intercept('DELETE', '**/project.jsonld', { + statusCode: 403, + }); - cy.get('solid-delete#test1 button').click({ force: true }) + cy.get('solid-delete#test1 button').click({ force: true }); // if server fails, events not fired cy.get('#res').should('be.empty'); }); @@ -46,8 +46,10 @@ describe('solid-delete', function () { it('re-render when label change', () => { cy.get('solid-delete#test1').then(el => { el.attr('data-label', 'Supprimer la ressource'); - cy.get('solid-delete#test1 > button').should('have.text', 'Supprimer la ressource'); - }) + cy.get('solid-delete#test1 > button').should( + 'have.text', + 'Supprimer la ressource', + ); + }); }); -}) - +}); diff --git a/cypress/e2e/e2e/solid-display.cy.ts b/cypress/e2e/e2e/solid-display.cy.ts index 450219e64563cf2a4a1881edbe89a1ccdf397f5f..7631e04d57117e52df32ae684f66b944dcc11c70 100644 --- a/cypress/e2e/e2e/solid-display.cy.ts +++ b/cypress/e2e/e2e/solid-display.cy.ts @@ -1,44 +1,59 @@ -describe('solid-display', function() { +describe('solid-display', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/solid-display.html') + cy.visit('/examples/e2e/solid-display.html'); }); it('display event', () => { - cy.get('#display-1>div').children().eq(0).should('have.attr', 'name', 'event') + cy.get('#display-1>div') + .children() + .eq(0) + .should('have.attr', 'name', 'event') .should('have.attr', 'value', 'Event name and date : ') .should('have.class', 'presentationEvent'); - cy.get('#display-2 solid-set-default').should('have.attr', 'name', 'completeName') + cy.get('#display-2 solid-set-default') + .should('have.attr', 'name', 'completeName') .should('have.class', 'completeName') - .children().should('have.length', 3); + .children() + .should('have.length', 3); }); it('handle fields attribute', () => { // all fields - cy.get('#display-3>div').children().eq(0) - .should('not.have.attr', 'fields'); - cy.get('#display-3>div').children().eq(0) - .find('>div').children() + cy.get('#display-3>div').children().eq(0).should('not.have.attr', 'fields'); + cy.get('#display-3>div') + .children() + .eq(0) + .find('>div') + .children() .should('have.length', 10); - cy.get('#display-3 > div ') - .find("[name=permissions]") - .should('not.exist'); - + cy.get('#display-3 > div ').find('[name=permissions]').should('not.exist'); + // child-[field] attribute - cy.get('#display-3 > div').children().eq(0) + cy.get('#display-3 > div') + .children() + .eq(0) .should('have.attr', 'attribute-child', 'child-value'); - cy.get('#display-3 > div').children().eq(1) + cy.get('#display-3 > div') + .children() + .eq(1) .should('have.attr', 'attribute-child', 'child-value'); - cy.get('#display-3 > div').children().eq(2) + cy.get('#display-3 > div') + .children() + .eq(2) .should('have.attr', 'attribute-chIld', 'child-value'); - cy.get('#display-3 > div').children().eq(3) + cy.get('#display-3 > div') + .children() + .eq(3) .should('have.attr', 'attribute-child', 'child-value'); // no fields - cy.get('#display-4>div').children() - .should('have.attr', 'fields', ''); - cy.get('#display-4>div').children().eq(0) - .find('>div').children() + cy.get('#display-4>div').children().should('have.attr', 'fields', ''); + cy.get('#display-4>div') + .children() + .eq(0) + .find('>div') + .children() .should('have.length', 0); }); @@ -50,34 +65,41 @@ describe('solid-display', function() { }); it('required mixin', () => { - cy.get('#display-6 > div') - .children().should('have.length', 4); + cy.get('#display-6 > div').children().should('have.length', 4); cy.get('#display-7').should('have.attr', 'required-ocean'); - cy.get('#display-7 > div') - .children().should('have.length', 0); + cy.get('#display-7 > div').children().should('have.length', 0); cy.get('#display-8').should('have.attr', 'required-city'); + cy.get('#display-8 > div').children().should('have.length', 2); cy.get('#display-8 > div') - .children().should('have.length', 2) - cy.get('#display-8 > div').children().eq(0) - .should('have.attr', 'data-src', '/examples/data/list/event-3.jsonld'); - cy.get('#display-8 > div').children().eq(1) - .should('have.attr', 'data-src', '/examples/data/list/event-4.jsonld'); + .children() + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/event-3.jsonld'); + cy.get('#display-8 > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/event-4.jsonld'); cy.get('#display-9').should('have.attr', 'required-place'); + cy.get('#display-9 > div').children().should('have.length', 2); + cy.get('#display-9 > div') + .children() + .eq(0) + .should('have.attr', 'data-src', '/examples/data/list/event-2.jsonld'); cy.get('#display-9 > div') - .children().should('have.length', 2); - cy.get('#display-9 > div').children().eq(0) - .should('have.attr', 'data-src', '/examples/data/list/event-2.jsonld'); - cy.get('#display-9 > div').children().eq(1) - .should('have.attr', 'data-src', '/examples/data/list/event-3.jsonld'); + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/event-3.jsonld'); cy.get('#display-10').should('have.attr', 'required-city'); cy.get('#display-10').should('have.attr', 'required-place'); - cy.get('#display-10 > div').children().should('have.length', 1) - cy.get('#display-10 > div > solid-display') - .should('have.attr', 'data-src', '/examples/data/list/event-3.jsonld');; + cy.get('#display-10 > div').children().should('have.length', 1); + cy.get('#display-10 > div > solid-display').should( + 'have.attr', + 'data-src', + '/examples/data/list/event-3.jsonld', + ); }); it('list-mixin : solid-container & solid-resource attributes', () => { @@ -85,71 +107,112 @@ describe('solid-display', function() { cy.get('#display-11 > div').children().should('have.length', 4); cy.get('#display-12').should('have.attr', 'solid-resource'); - cy.get('#display-12 > div').children().should('have.length',1); + cy.get('#display-12 > div').children().should('have.length', 1); }); it('list-mixin : empty-value', () => { cy.get('#display-13').find('no-skill'); - cy.get('#display-13 > span > no-skill').contains('No skill yet') + cy.get('#display-13 > span > no-skill').contains('No skill yet'); }); it('define src attribute of solid-link by action', () => { - cy.get('#display-14 > div > solid-action') - .should('have.attr', 'src', '/examples/data/list/user-1.jsonld'); - cy.get('#display-14 > div > solid-action > solid-link') - .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld'); + cy.get('#display-14 > div > solid-action').should( + 'have.attr', + 'src', + '/examples/data/list/user-1.jsonld', + ); + cy.get('#display-14 > div > solid-action > solid-link').should( + 'have.attr', + 'data-src', + '/examples/data/list/user-1.jsonld', + ); - cy.get('#display-15 > div > solid-action') - .should('have.attr', 'src', 'other-resource'); - cy.get('#display-15 > div > solid-action > solid-link') - .should('have.attr', 'data-src', 'other-resource'); - }); + cy.get('#display-15 > div > solid-action').should( + 'have.attr', + 'src', + 'other-resource', + ); + cy.get('#display-15 > div > solid-action > solid-link').should( + 'have.attr', + 'data-src', + 'other-resource', + ); + }); it('handle default-[field] attribute', () => { - cy.get('#default-field > div solid-display-value') - .should('have.text', 'not defined'); + cy.get('#default-field > div solid-display-value').should( + 'have.text', + 'not defined', + ); }); it('counter mixin', () => { - cy.get('#display-16').children().eq(0) + cy.get('#display-16') + .children() + .eq(0) .should('contain', '8 skills displayed :'); - cy.get('#display-16').children().eq(1) - .find('div').should('have.length', '8'); + cy.get('#display-16') + .children() + .eq(1) + .find('div') + .should('have.length', '8'); }); it('highlighter-mixin', () => { - cy.get('#display-17 > div').children().eq(0) - .find('solid-display-value').should('contain', 'Javascript') + cy.get('#display-17 > div') + .children() + .eq(0) + .find('solid-display-value') + .should('contain', 'Javascript'); }); it('nested-[field]', () => { // data-src in solid-display pointed on skill-*.jsonld - cy.get('#display-18 > div').children().eq(0) + cy.get('#display-18 > div') + .children() + .eq(0) .should('have.attr', 'data-src', '/examples/data/list/skill-2.jsonld'); - cy.get('#display-18 > div').children().eq(1) - .should('have.attr','data-src', '/examples/data/list/skill-3.jsonld'); + cy.get('#display-18 > div') + .children() + .eq(1) + .should('have.attr', 'data-src', '/examples/data/list/skill-3.jsonld'); // User's name not displayed - cy.get('#display-18 > div').children().eq(0) - .find('solid-display-value').should('not.contain.value', 'Test User'); - cy.get('#display-18 > div').children().eq(1) - .find('solid-display-value').should('not.contain.value', 'Test User'); + cy.get('#display-18 > div') + .children() + .eq(0) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); + cy.get('#display-18 > div') + .children() + .eq(1) + .find('solid-display-value') + .should('not.contain.value', 'Test User'); // Skills' name displayed - cy.get('#display-18 > div').children().eq(0) - .find('solid-display-value').should('have.attr', 'value', 'CSS'); - cy.get('#display-18 > div').children().eq(1) - .find('solid-display-value').should('have.attr','value', 'Javascript'); + cy.get('#display-18 > div') + .children() + .eq(0) + .find('solid-display-value') + .should('have.attr', 'value', 'CSS'); + cy.get('#display-18 > div') + .children() + .eq(1) + .find('solid-display-value') + .should('have.attr', 'value', 'Javascript'); }); it('default-widget', () => { // default-widget applied to every child cy.get('#display-19 > div') - .find('solid-display-link').eq(0) + .find('solid-display-link') + .eq(0) .should('have.attr', 'name', 'name'); cy.get('#display-19 > div') - .find('solid-display-link').eq(1) + .find('solid-display-link') + .eq(1) .should('have.attr', 'name', 'email'); cy.get('#display-19 > div') - .find('solid-display-link').eq(2) + .find('solid-display-link') + .eq(2) .should('have.attr', 'name', 'username'); // default-widget applied to several children @@ -157,32 +220,44 @@ describe('solid-display', function() { .find('solid-display-div') .should('have.attr', 'name', 'name'); cy.get('#display-20 > div') - .find('solid-display-link').eq(0) + .find('solid-display-link') + .eq(0) .should('have.attr', 'name', 'email'); cy.get('#display-20 > div') - .find('solid-display-link').eq(1) + .find('solid-display-link') + .eq(1) .should('have.attr', 'name', 'username'); }); it('oembed template', () => { cy.get('#display-21 > div') .find('solid-display-value-oembed') - .should('have.attr', 'value', 'https://www.audiomack.com/oembed?url=https%3A%2F%2Faudiomack.com%2Faudiomack%2Fplaylist%2Fjust-chillin&format=json'); + .should( + 'have.attr', + 'value', + 'https://www.audiomack.com/oembed?url=https%3A%2F%2Faudiomack.com%2Faudiomack%2Fplaylist%2Fjust-chillin&format=json', + ); }); it('default-widget-[field]', () => { + cy.get('#display-22 > div').children().should('have.length', 4); + cy.get('#display-22 > div').children().eq(1).should('contain', 'Rennes'); + cy.get('#display-22 > div > custom-default-widget').should( + 'contain', + 'Field empty', + ); cy.get('#display-22 > div') - .children().should('have.length', 4); - cy.get('#display-22 > div').children().eq(1) - .should('contain', 'Rennes'); - cy.get('#display-22 > div > custom-default-widget') - .should('contain', 'Field empty'); - cy.get('#display-22 > div').children().eq(0) + .children() + .eq(0) .should('contain', 'Field empty'); - cy.get('#display-22 > div').children().eq(2) + cy.get('#display-22 > div') + .children() + .eq(2) .should('contain', 'Field empty'); - cy.get('#display-22 > div > custom-default-widget-website') - .should('contain', 'No website'); + cy.get('#display-22 > div > custom-default-widget-website').should( + 'contain', + 'No website', + ); }); it('dispatch event when widget rendered', () => { @@ -191,46 +266,68 @@ describe('solid-display', function() { it('widget for empty set', () => { // empty set widget displayed + cy.get('#widget-empty-set1 > div').children().should('have.length', 2); cy.get('#widget-empty-set1 > div') - .children().should('have.length', 2); - cy.get('#widget-empty-set1 > div') - .children().eq(1).children() + .children() + .eq(1) + .children() .should('have.length', 1); cy.get('#widget-empty-set1 > div') - .children().eq(1) + .children() + .eq(1) .should('contain', 'set empty'); // empty set widget not displayed + cy.get('#widget-empty-set2 > div').children().should('have.length', 2); cy.get('#widget-empty-set2 > div') - .children().should('have.length', 2); - cy.get('#widget-empty-set2 > div') - .children().eq(1).children() + .children() + .eq(1) + .children() .should('have.length', 3); cy.get('#widget-empty-set2 > div') - .children().eq(1).should('contain', 'Paris') + .children() + .eq(1) + .should('contain', 'Paris') .and('not.contain', 'set empty'); // empty set with value attribute displayed + cy.get('#widget-empty-set3 > div').children().should('have.length', 2); cy.get('#widget-empty-set3 > div') - .children().should('have.length', 2); - cy.get('#widget-empty-set3 > div') - .children().eq(1) + .children() + .eq(1) .should('have.attr', 'value', 'empty set value'); cy.get('#widget-empty-set3 > div') - .children().eq(1).should('contain', 'empty set value') + .children() + .eq(1) + .should('contain', 'empty set value') .and('not.contain', 'set empty'); }); - it('solid-set-div-label', () => { + it('solid-set-div-label', () => { + cy.get('#solid-set-div-label > div').children().should('have.length', 4); + cy.get('#solid-set-div-label > div') + .children() + .eq(0) + .find('solid-set-div-label') + .children() + .should('have.length', 2); + cy.get( + '#solid-set-div-label > div > solid-display > div > solid-set-div-label', + ) + .find('label') + .should('contain', 'identity'); cy.get('#solid-set-div-label > div') - .children().should('have.length', 4); - cy.get('#solid-set-div-label > div').children().eq(0) - .find('solid-set-div-label').children().should('have.length', 2); - cy.get('#solid-set-div-label > div > solid-display > div > solid-set-div-label') - .find('label').should('contain', 'identity'); - cy.get('#solid-set-div-label > div').children().eq(1) - .find('label').should('contain', 'identity'); - cy.get('#solid-set-div-label > div').children().eq(2) - .find('label').should('contain', 'identity'); - cy.get('#solid-set-div-label > div').children().eq(3) - .find('label').should('contain', 'identity'); - }) -}) \ No newline at end of file + .children() + .eq(1) + .find('label') + .should('contain', 'identity'); + cy.get('#solid-set-div-label > div') + .children() + .eq(2) + .find('label') + .should('contain', 'identity'); + cy.get('#solid-set-div-label > div') + .children() + .eq(3) + .find('label') + .should('contain', 'identity'); + }); +}); diff --git a/cypress/e2e/e2e/solid-form-file.cy.ts b/cypress/e2e/e2e/solid-form-file.cy.ts index c48f2cfd3c07d2935744be0b7a556d04f7035685..4d6fad10c9fdc8fa5aaefd7c23636270ad09d792 100644 --- a/cypress/e2e/e2e/solid-form-file.cy.ts +++ b/cypress/e2e/e2e/solid-form-file.cy.ts @@ -1,55 +1,97 @@ // TODO: We should make tests run independently of one another -describe('solid-form-file test', { testIsolation: false }, function() { +describe('solid-form-file test', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/solid-form-file.html') + cy.visit('/examples/e2e/solid-form-file.html'); }); - it('upload file with solid-form-file', function() { - cy.get('#form-file [name=picture]+input[type=file]').uploadFile('../../fake-image.svg') + it('upload file with solid-form-file', () => { + cy.get('#form-file [name=picture] input[type=file]').uploadFile( + '../../fake-image.svg', + ); cy.get('#form-file input[name=picture]').should($i => { - expect($i.val()).to.match(/\/upload\/[0-9a-f]+.jpg$/) - }) - }) + expect($i.val()).to.match(/\/upload\/[0-9a-f]+.jpg$/); + }); + }); - it('upload image with solid-form-file-image', function() { - cy.get('#form-image solid-form-image input[type=file]').uploadFile('../../fake-image.svg') + it('upload image with solid-form-file-image', () => { + cy.get('#form-image solid-form-image input[type=file]').uploadFile( + '../../fake-image.svg', + ); cy.get('#form-image solid-form-image img').should($i => { - expect($i.attr('src')).to.not.match(/\/upload\/fruits.jpg$/) - expect($i.attr('src')).to.match(/\/upload\/[0-9a-f]+.jpg$/) - }) - }) - - it('resets the file', function() { - cy.get('#reset-file solid-form-file input[type=file]').uploadFile('../../fake-image.svg') + expect($i.attr('src')).to.not.match(/\/upload\/fruits.jpg$/); + expect($i.attr('src')).to.match(/\/upload\/[0-9a-f]+.jpg$/); + }); + }); + + it('resets the file', () => { + cy.get('#reset-file solid-form-file input[type=file]').uploadFile( + '../../fake-image.svg', + ); cy.get('#reset-file solid-form-file input[name=picture]').should($i => { - expect($i.val()).to.match(/\/upload\/[0-9a-f]+.jpg$/) - }) + expect($i.val()).to.match(/\/upload\/[0-9a-f]+.jpg$/); + }); cy.wait(500); cy.get('#reset-file input[type=reset]').click(); cy.get('#reset-file solid-form-file input[type=file]').should('be.empty'); - cy.get('#reset-file solid-form-file input[type=text]').should('have.value', '../../upload/fruits.jpg'); + cy.get('#reset-file solid-form-file input[type=text]').should( + 'have.value', + '../../upload/fruits.jpg', + ); cy.get('#reset-file solid-form-file button').should('have.attr', 'hidden'); - }) + }); - it('resets the image', function () { - cy.get('#reset-image solid-form-image input[type=file]').uploadFile('../../fake-image.svg') + it('resets the image', () => { + cy.get('#reset-image solid-form-image input[type=file]').uploadFile( + '../../fake-image.svg', + ); cy.get('#reset-image solid-form-image img').should($i => { - expect($i.attr('src')).to.not.match(/\/upload\/fruits.jpg$/) - expect($i.attr('src')).to.match(/\/upload\/[0-9a-f]+.jpg$/) - }) + expect($i.attr('src')).to.not.match(/\/upload\/fruits.jpg$/); + expect($i.attr('src')).to.match(/\/upload\/[0-9a-f]+.jpg$/); + }); cy.get('#reset-image input[type=reset]').click(); cy.get('#reset-image solid-form-image img').should($i => { - expect($i.attr('src')).to.match(/\/upload\/fruits.jpg$/) - }) + expect($i.attr('src')).to.match(/\/upload\/fruits.jpg$/); + }); cy.get('#reset-image solid-form-image input[type=file]').should('be.empty'); - cy.get('#reset-image solid-form-image input[type=text]').should('have.value', '../../upload/fruits.jpg'); - cy.get('#reset-image solid-form-image button').should('have.attr', 'hidden'); + cy.get('#reset-image solid-form-image input[type=text]').should( + 'have.value', + '../../upload/fruits.jpg', + ); + cy.get('#reset-image solid-form-image button').should( + 'have.attr', + 'hidden', + ); }); - it('handles required', function() { - cy.get('#form-required-image solid-form-image input[type=text]').should('have.attr', 'required') - cy.get('#form-required-image solid-form-image input[type=file]').should('not.have.attr', 'required') - cy.get('#form-required-file solid-form-file input[type=text]').should('have.attr', 'required') - cy.get('#form-required-file solid-form-file input[type=file]').should('not.have.attr', 'required') - }) -}) \ No newline at end of file + it('handles required', () => { + cy.get('#form-required-image solid-form-image input[type=text]').should( + 'have.attr', + 'required', + ); + cy.get('#form-required-image solid-form-image input[type=file]').should( + 'not.have.attr', + 'required', + ); + cy.get('#form-required-file solid-form-file input[type=text]').should( + 'have.attr', + 'required', + ); + cy.get('#form-required-file solid-form-file input[type=file]').should( + 'not.have.attr', + 'required', + ); + }); + + it('displays file name if source not empty', () => { + cy.visit('/examples/e2e/solid-form-file.html'); // if not then page is not updated, and another file is uploaded from the prev test + cy.get( + '#form-file solid-form-file[name=picture] a[href="../../upload/fruits.jpg"]', + ).contains('fruits.jpg'); + cy.get( + '#reset-file solid-form-file[name=picture] a[href="../../upload/fruits.jpg"]', + ).contains('fruits.jpg'); + cy.get( + '#form-required-file solid-form-file[name=picture] a[href="../../upload/fruits.jpg"]', + ).contains('fruits.jpg'); + }); +}); diff --git a/cypress/e2e/e2e/solid-form-richtext.cy.ts b/cypress/e2e/e2e/solid-form-richtext.cy.ts index 430b07f08330da4c71948a2349daeb58a9fa5f06..3643f68fc816067fdef9f1b594f973cfa37273ab 100644 --- a/cypress/e2e/e2e/solid-form-richtext.cy.ts +++ b/cypress/e2e/e2e/solid-form-richtext.cy.ts @@ -1,86 +1,121 @@ describe('solid-form-richtext test', function () { - this.beforeEach('visit', () => { - cy.visit('/examples/e2e/solid-form-richtext.html'); - }); + this.beforeEach('visit', () => { + cy.visit('/examples/e2e/solid-form-richtext.html'); + }); - it('Submitting form with filled rich text input should not display an error', () => { - cy.get('solid-form div[data-richtext] p').should('not.have.length', 0); - cy.get('#form-1 input[type="submit"]').click(); - cy.get('#form-1 div[data-richtext] .required-error-message').should('not.exist'); - cy.get('#form-1 div[data-richtext] .error-border-richtext').should('not.exist'); - }); + it('Submitting form with filled rich text input should not display an error', () => { + cy.get('solid-form div[data-richtext] p').should('not.have.length', 0); + cy.get('#form-1 input[type="submit"]').click(); + cy.get('#form-1 div[data-richtext] .required-error-message').should( + 'not.exist', + ); + cy.get('#form-1 div[data-richtext] .error-border-richtext').should( + 'not.exist', + ); + }); + + it('Submitting form with empty rich text input should display an error mesage', () => { + cy.get('#form-1 div[data-richtext] [contenteditable]') + .should('have.text', 'some description') + .clear(); + cy.get('#form-1 div[data-richtext] p').clear(); + cy.get('#form-1 input[type="submit"]').click(); + cy.get('#form-1 div[data-richtext] .required-error-message').should( + 'exist', + ); + cy.get('#form-1 div[data-richtext].error-border-richtext').should('exist'); + }); - it('Submitting form with empty rich text input should display an error mesage', () => { - cy.get('#form-1 div[data-richtext] p').clear(); - cy.get('#form-1 input[type="submit"]').click(); - cy.get('#form-1 div[data-richtext] .required-error-message').should('exist'); - cy.get('#form-1 div[data-richtext].error-border-richtext').should('exist'); - }); - - it('Error message disappears when retyping in rich text input', () => { - // Empty fields , error is shown - cy.get('#form-1 div[data-richtext] p').clear(); - cy.get('#form-1 input[type="submit"]').click(); - cy.get('#form-1 div[data-richtext] .required-error-message').should('exist'); - cy.get('#form-1 div[data-richtext].error-border-richtext').should('exist'); + it('Error message disappears when retyping in rich text input', () => { + // Empty fields , error is shown + cy.get('#form-1 div[data-richtext] [contenteditable]') + .should('have.text', 'some description') + .clear(); + cy.get('#form-1 input[type="submit"]').click(); + cy.get('#form-1 div[data-richtext] .required-error-message').should( + 'exist', + ); + cy.get('#form-1 div[data-richtext].error-border-richtext').should('exist'); - // Retype text , error disapears - cy.get('#form-1 div[data-richtext] p').type('some text'); - cy.get('#form-1 input[type="submit"]').click(); - cy.get('#form-1 div[data-richtext] .required-error-message').should('not.exist'); - cy.get('#form-1 div[data-richtext] .error-border-richtext').should('not.exist'); - }); + // Retype text , error disapears + cy.get('#form-1 div[data-richtext] p').type('some text'); + cy.get('#form-1 input[type="submit"]').click(); + cy.get('#form-1 div[data-richtext] .required-error-message').should( + 'not.exist', + ); + cy.get('#form-1 div[data-richtext] .error-border-richtext').should( + 'not.exist', + ); + }); - it('Placeholder is displayed text value is empty if placeholder is assigned', () => { - cy.get('#form-1 div[data-richtext] p').clear(); - cy.get('#form-1 div[data-richtext] div[data-placeholder]').should('exist') - cy.get('#form-1 div[data-richtext] div[data-placeholder]').should('have.attr', 'data-placeholder', 'some placeholder') - }); + it('Placeholder is displayed text value is empty if placeholder is assigned', () => { + cy.get('#form-1 div[data-richtext] p').clear(); + cy.get('#form-1 div[data-richtext] div[data-placeholder]').should('exist'); + cy.get('#form-1 div[data-richtext] div[data-placeholder]').should( + 'have.attr', + 'data-placeholder', + 'some placeholder', + ); + }); - it('richtext html rendering', () => { - cy.get('#form-2 solid-form-richtext') - .children().should('have.have.length', 2) - .find('button') - .and('have.attr', 'class', 'ql-bold'); - cy.get('#form-2 solid-form-richtext').then($el => { - expect((<any>$el[0]).component.getValue()).to.equal('**Jean-Bernard**\n'); - cy.get('#form-2 solid-form-richtext .ql-editor').type('{selectall}Jean-Claude{selectall}') - cy.get('#form-2 solid-form-richtext .ql-italic') - .click() - cy.get('#form-2 solid-form-richtext .ql-bold') - .click() - cy.get('#form-2 solid-form-richtext .ql-editor') - .find('em') - .should('have.text', 'Jean-Claude') - cy.get('#form-2 solid-form-richtext').then($el => { - expect((<any>$el[0]).component.getValue()).to.equal('_Jean-Claude_\n') - }); - }); - // add link button in richtext mixin - cy.get('#form-3 solid-form-richtext > div ').children().eq(4) - .find('button') - .and('have.attr', 'class', 'ql-link'); - cy.get('#form-3 solid-form-richtext .ql-editor').type('{selectall}test link{selectall}') - cy.get('#form-3 solid-form-richtext .ql-link') - .click() - cy.get('#form-3 solid-form-richtext > div[name=name] > div[data-mode=link] > input[type=text]') - .type('http://www.yesnoif.com/') - cy.get('#form-3 solid-form-richtext > div[name=name] > div[data-mode=link] > a[class=ql-action]') - .click() - cy.get('#form-3 solid-form-richtext .ql-editor') - .find('a').should('have.attr', 'href', 'http://www.yesnoif.com/') - .and('contain', 'test link'); - // verify value format sent in the form - cy.get('#form-3 input[type=submit]').click() - cy.get('#form-3').then($el => { - return (<any>$el[0]).component.getFormValue().then(res => { - expect(res.name).to.equal('[test link](http://www.yesnoif.com/)\n'); - }); - }); - // value stocked in markdown well displayed in the solid-form-richtext - cy.get('#form-4 solid-form-richtext > div[name=website]') - .find('a').should('have.attr', 'href', 'http://drawing.garden/') - .and('contain', 'my site') + it('richtext html rendering', () => { + cy.get('#form-2 solid-form-richtext') + .children() + .should('have.have.length', 2) + .find('button') + .and('have.attr', 'class', 'ql-bold'); + cy.get('#form-2 solid-form-richtext').then($el => { + expect((<any>$el[0]).component.getValue()).to.equal('**Jean-Bernard**\n'); + cy.get('#form-2 solid-form-richtext .ql-editor').type( + '{selectall}Jean-Claude{selectall}', + ); + cy.get('#form-2 solid-form-richtext .ql-italic').click(); + cy.get('#form-2 solid-form-richtext .ql-bold').click(); + cy.get('#form-2 solid-form-richtext .ql-editor') + .find('em') + .should('have.text', 'Jean-Claude'); + cy.get('#form-2 solid-form-richtext').then($el => { + expect((<any>$el[0]).component.getValue()).to.equal('_Jean-Claude_\n'); }); + }); + // add link button in richtext mixin + cy.get('#form-3 solid-form-richtext > div ') + .children() + .eq(4) + .find('button') + .and('have.attr', 'class', 'ql-link'); + cy.get('#form-3 solid-form-richtext .ql-editor').type( + '{selectall}test link{selectall}', + ); + cy.get('#form-3 solid-form-richtext .ql-link').click(); + cy.get( + '#form-3 solid-form-richtext > div[name=name] > div[data-mode=link] > input[type=text]', + ).type('http://www.yesnoif.com/'); + cy.get( + '#form-3 solid-form-richtext > div[name=name] > div[data-mode=link] > a[class=ql-action]', + ).click(); + cy.get('#form-3 solid-form-richtext .ql-editor') + .find('a') + .should('have.attr', 'href', 'http://www.yesnoif.com/') + .and('contain', 'test link'); + // verify value format sent in the form + cy.get('#form-3 input[type=submit]').click(); + cy.get('#form-3').then($el => { + return (<any>$el[0]).component.getFormValue().then(res => { + expect(res.name).to.equal('[test link](http://www.yesnoif.com/)\n'); + }); + }); + // value stocked in markdown well displayed in the solid-form-richtext + cy.get('#form-4 solid-form-richtext > div[name=website]') + .find('a') + .should('have.attr', 'href', 'http://drawing.garden/') + .and('contain', 'my site'); + }); -}) \ No newline at end of file + it('Editor displays correctly multiple new lines', () => { + cy.get('#form-5 div[data-richtext] [contenteditable]').should( + 'have.html', + '<p>Première ligne</p><p><br></p><p><br></p><p><br></p><p>Seconde Ligne avec quatre sauts de ligne</p>', + ); + }); +}); diff --git a/cypress/e2e/e2e/solid-form.cy.ts b/cypress/e2e/e2e/solid-form.cy.ts index aa7c53051c1ddb401a0c27948fc3e43cd60da202..824c10fa2dace4f9b22dfb7a0c9869d55fc36ec3 100644 --- a/cypress/e2e/e2e/solid-form.cy.ts +++ b/cypress/e2e/e2e/solid-form.cy.ts @@ -1,18 +1,20 @@ // TODO: We should make tests run independently of one another -describe('solid-form', { testIsolation: false }, function() { +describe('solid-form', { testIsolation: false }, function () { let win: Window; this.beforeAll('visit', () => { cy.visit('/examples/e2e/solid-form.html'); cy.window().then(w => { win = w; }); - }); it('creation form', () => { - cy.get('#form-1 input[type=text]').should('have.length', 2) + cy.get('#form-1 input[type=text]').should('have.length', 2); cy.get('#form-1 input[type=text][name=name]').should('have.value', ''); - cy.get('#form-1 input[type=text][name="contact.email"]').should('have.value', ''); + cy.get('#form-1 input[type=text][name="contact.email"]').should( + 'have.value', + '', + ); cy.get('#form-1').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ name: '', contact: { email: '' } }); @@ -25,12 +27,11 @@ describe('solid-form', { testIsolation: false }, function() { cy.get('input[type=text]').should('have.length', 2); cy.get('input[name=with]').should('exist'); cy.get('input[name=field]').should('exist'); - }) - + }); }); it('edition form', () => { - cy.get('#form-edition-1 input[type=text]').should('have.length', 2) + cy.get('#form-edition-1 input[type=text]').should('have.length', 2); cy.get('#form-edition-1 input[type=text][name=name]') .should('have.value', 'Coliving') .type(' in BZH'); @@ -41,55 +42,58 @@ describe('solid-form', { testIsolation: false }, function() { cy.get('#form-edition-1').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ - "@id": "/examples/data/list/event-1.jsonld", + '@id': '/examples/data/list/event-1.jsonld', contact: { email: 'admin@example.com', - "@id": "/examples/data/list/user-1.jsonld", + '@id': '/examples/data/list/user-1.jsonld', }, name: 'Coliving in BZH', }); }); }); - cy.intercept("PUT", '**/event-1.jsonld', { + cy.intercept('PUT', '**/event-1.jsonld', { headers: { - contentType: 'application/ld+json' - } - }) + contentType: 'application/ld+json', + }, + }); - cy.get('#form-edition-2 input[type=text][name=name]') - .type(' in BZH'); - cy.get('#form-edition-2 select').select('Pierre DLC') + cy.get('#form-edition-2 input[type=text][name=name]').type(' in BZH'); + cy.get('#form-edition-2 select').select('Pierre DLC'); cy.get('#form-edition-2').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ name: 'Coliving in BZH', contact: { - "@id": "/examples/data/list/user-4.jsonld", + '@id': '/examples/data/list/user-4.jsonld', }, - "@id": "/examples/data/list/event-1.jsonld", + '@id': '/examples/data/list/event-1.jsonld', }); }); }); cy.get('#form-edition-2 input[type="submit"]').click(); // After submit, form is re-rendered properly - cy.get('#form-edition-2 input[type=text][name=name]') - .should('have.value', 'Coliving'); - cy.get('#form-edition-2 select') - .should('have.value', '{"@id": "/examples/data/list/user-1.jsonld"}'); + cy.get('#form-edition-2 input[type=text][name=name]').should( + 'have.value', + 'Coliving', + ); + cy.get('#form-edition-2 select').should( + 'have.value', + '{"@id": "/examples/data/list/user-1.jsonld"}', + ); // Nested container cy.get('#form-edition-3').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ skills: { - "ldp:contains": [ - { "@id": "/examples/data/list/skill-2.jsonld" }, - { "@id": "/examples/data/list/skill-3.jsonld" }, + 'ldp:contains': [ + { '@id': '/examples/data/list/skill-2.jsonld' }, + { '@id': '/examples/data/list/skill-3.jsonld' }, ], - "@id": "/examples/data/list/user-1-skills.jsonld", + '@id': '/examples/data/list/user-1-skills.jsonld', }, - "@id": "/examples/data/list/user-1.jsonld" + '@id': '/examples/data/list/user-1.jsonld', }); }); }); @@ -100,17 +104,17 @@ describe('solid-form', { testIsolation: false }, function() { .should('have.attr', 'range', '/examples/data/list/skills.jsonld') .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld') .should('have.attr', 'order-desc', 'name') - .should('have.attr', 'name', 'skills') + .should('have.attr', 'name', 'skills'); cy.get('#form-3 solid-form-label-placeholder-text') .should('have.attr', 'label', 'Test label') .should('have.attr', 'placeholder', 'test placeholder') .should('have.attr', 'class', 'test-class') - .should('have.attr', 'required') + .should('have.attr', 'required'); cy.get('#form-3 solid-form-label-placeholder-text') .find('input') - .should('have.attr', 'placeholder', 'test placeholder') + .should('have.attr', 'placeholder', 'test placeholder'); }); it('solid-form + pattern, title attributes', () => { @@ -128,94 +132,90 @@ describe('solid-form', { testIsolation: false }, function() { .find('input[type=submit]') .should('have.value', 'Register'); - cy.get('solid-form#form-6') - .then(el => { - el.attr('submit-button', 'Register the user'); - cy.get('solid-form#form-6') + cy.get('solid-form#form-6').then(el => { + el.attr('submit-button', 'Register the user'); + cy.get('solid-form#form-6') .find('input[type=submit]') .should('have.value', 'Register the user'); - }) - cy.get('solid-form-search#form-search-6') - .then(el => { - el.attr('submit-button', 'Register the user'); - cy.get('solid-form-search#form-search-6') + }); + cy.get('solid-form-search#form-search-6').then(el => { + el.attr('submit-button', 'Register the user'); + cy.get('solid-form-search#form-search-6') .find('input[type=submit]') .should('have.value', 'Register the user'); - }) + }); }); it('show errors without resetting', () => { cy.intercept('POST', '**/events.jsonld', { statusCode: 400, - body: { - "name": - [ - "Ensure this field has no more than 10 characters." - ], - "batches": { - "title": ["Title too long", "Title not unique"], - "tasks": { - "@id": ["Task with this urlid already exists."], - "amount": ["Should be > 0"] - } + body: { + name: ['Ensure this field has no more than 10 characters.'], + batches: { + title: ['Title too long', 'Title not unique'], + tasks: { + '@id': ['Task with this urlid already exists.'], + amount: ['Should be > 0'], + }, }, - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', }, headers: { - 'content-type': 'application/ld+json' - } - }) + 'content-type': 'application/ld+json', + }, + }); cy.get('solid-form#form-7') .find('input[name=name]') .type('Mon très long titre'); - cy.get('solid-form#form-7') - .find('input[type=submit]') - .click(); + cy.get('solid-form#form-7').find('input[type=submit]').click(); cy.get('solid-form#form-7') .find('[data-id="error"]') .should('contain', 'A validation error occurred.') .and('not.contain', '@context'); cy.get('solid-form#form-7') .find('input[name=name]') - .should('have.value', 'Mon très long titre') + .should('have.value', 'Mon très long titre'); cy.get('solid-form#form-7') .find('.error[name=name] .error-message') - .should('contain', 'Ensure this field has no more than 10 characters.') + .should('contain', 'Ensure this field has no more than 10 characters.'); cy.get('solid-form#form-7') .find('.error[name="batches.title"] .error-message') - .should('contain', 'Title too long') + .should('contain', 'Title too long'); cy.get('solid-form#form-7') .find('.error[name="batches.tasks"] .error-message') - .should('contain', 'Task with this urlid already exists.') + .should('contain', 'Task with this urlid already exists.'); cy.get('solid-form#form-7') .find('.error[name="batches.tasks"] .error-message') - .should('contain', 'Should be > 0') + .should('contain', 'Should be > 0'); // removes error after new submission - cy.intercept("POST", '**/events.jsonld', { + cy.intercept('POST', '**/events.jsonld', { headers: { - contentType: 'application/ld+json' + contentType: 'application/ld+json', }, - body: 'ok' - }) + body: 'ok', + }); - cy.get('solid-form#form-7') - .find('input[type=submit]') - .click(); - cy.get('solid-form#form-7') - .find('[data-id="error"]').should('be.empty') + cy.get('solid-form#form-7').find('input[type=submit]').click(); + cy.get('solid-form#form-7').find('[data-id="error"]').should('be.empty'); }); it('partial attribute', () => { cy.spy(win.sibStore, 'put'); - cy.get('#form-8').find('input[type=submit]').click().then(() => { - expect(win.sibStore.put).to.be.called; - }); + cy.get('#form-8') + .find('input[type=submit]') + .click() + .then(() => { + expect(win.sibStore.put).to.be.called; + }); cy.spy(win.sibStore, 'patch'); - cy.get('#form-9').find('input[type=submit]').click().then(() => { - expect(win.sibStore.patch).to.be.called; - }); + cy.get('#form-9') + .find('input[type=submit]') + .click() + .then(() => { + expect(win.sibStore.patch).to.be.called; + }); }); it('naked attribute', () => { @@ -224,129 +224,155 @@ describe('solid-form', { testIsolation: false }, function() { it('loader-id attribute', () => { cy.get('#form-loader').should('have.attr', 'hidden'); - cy.intercept("POST", '**/users.jsonld', { - delay: 3000 - }) - - cy.get('#form-11') - .find('input[name=name]') - .type('Tryphon'); - cy.get('#form-11') - .find('input[type=submit]') - .click(); + cy.intercept('POST', '**/users.jsonld', { + delay: 3000, + }); + + cy.get('#form-11').find('input[name=name]').type('Tryphon'); + cy.get('#form-11').find('input[type=submit]').click(); cy.get('#form-loader').should('not.have.attr', 'hidden'); }); it('solid-form with addable attributes', () => { // Verify addable's attributes are passed in the solid-form-dropdown-addable cy.get('solid-form#form-addable > form > solid-form-dropdown-addable') - .should('have.attr', 'name', 'skills') - .and('have.attr', 'addable-data-src', '/examples/data/list/users.jsonld') - .and('have.attr', 'addable-fields', 'name') - .and('have.attr', 'addable-widget-name', 'solid-form-text-placeholder-label') - .and('have.attr', 'addable-placeholder-name', 'Enter skill name') - .and('have.attr', 'addable-submit-button', 'Send name') + .should('have.attr', 'name', 'skills') + .and('have.attr', 'addable-data-src', '/examples/data/list/users.jsonld') + .and('have.attr', 'addable-fields', 'name') + .and( + 'have.attr', + 'addable-widget-name', + 'solid-form-text-placeholder-label', + ) + .and('have.attr', 'addable-placeholder-name', 'Enter skill name') + .and('have.attr', 'addable-submit-button', 'Send name'); }); it('autocomplete attribute', () => { - cy.get('solid-form#form-12 > form > solid-form-label-text').eq(0) - .should('have.attr', 'autocomplete', 'off') - cy.get('solid-form#form-12 > form > solid-form-label-text').eq(0) + cy.get('solid-form#form-12 > form > solid-form-label-text') + .eq(0) + .should('have.attr', 'autocomplete', 'off'); + cy.get('solid-form#form-12 > form > solid-form-label-text') + .eq(0) .find('input[type=text]') - .should('have.attr', 'autocomplete', 'off') - cy.get('solid-form#form-12 > form > solid-form-label-text').eq(1) - .should('not.have.attr', 'autocomplete') + .should('have.attr', 'autocomplete', 'off'); + cy.get('solid-form#form-12 > form > solid-form-label-text') + .eq(1) + .should('not.have.attr', 'autocomplete'); }); it('autosaves form', () => { cy.spy(win.sibStore, 'patch'); - cy.get('solid-form#form-autosave').find('input[type="submit"]') + cy.get('solid-form#form-autosave') + .find('input[type="submit"]') .should('not.exist'); - cy.get('solid-form#form-autosave input[name="username"]').type('a').then(() => { - expect(win.sibStore.patch).to.have.callCount(0); - }); - cy.get('solid-form#form-autosave input[name="username"]').blur().then(() => { - cy.wait(200).then(() => { - expect(win.sibStore.patch).to.have.callCount(1); + cy.get('solid-form#form-autosave input[name="username"]') + .type('a') + .then(() => { + expect(win.sibStore.patch).to.have.callCount(0); + }); + cy.get('solid-form#form-autosave input[name="username"]') + .blur() + .then(() => { + cy.wait(200).then(() => { + expect(win.sibStore.patch).to.have.callCount(1); + }); + }); + cy.get('solid-form#form-autosave [data-index="skills0"] button') + .click() + .then(() => { + expect(win.sibStore.patch).to.have.callCount(2); }); - }); - cy.get('solid-form#form-autosave [data-index="skills0"] button').click().then(() => { - expect(win.sibStore.patch).to.have.callCount(2); - }); cy.get('solid-form#form-autosave [data-index="skills1"] select') - .select("PHP") - .then(() => { - cy.wait(200).then(() => { - expect(win.sibStore.patch).to.have.callCount(3); - }) - }); + .select('PHP') + .then(() => { + cy.wait(200).then(() => { + expect(win.sibStore.patch).to.have.callCount(3); + }); + }); // Without autosave, no requests - cy.get('solid-form#form-autosave').then(($el) => { + cy.get('solid-form#form-autosave').then($el => { $el.removeAttr('autosave'); - cy.get('solid-form#form-autosave input[name="username"]').type('a').blur().then(() => { - expect(win.sibStore.patch).to.have.callCount(3); - }); + cy.get('solid-form#form-autosave input[name="username"]') + .type('a') + .blur() + .then(() => { + expect(win.sibStore.patch).to.have.callCount(3); + }); }); }); it('submit-widget attribute', () => { - cy.get('solid-form#form-submit-widget').find('input[type="submit"]') + cy.get('solid-form#form-submit-widget') + .find('input[type="submit"]') .should('not.exist'); - cy.get('solid-form#form-submit-widget').find('div').children('button[type="submit"]') + cy.get('solid-form#form-submit-widget') + .find('div') + .children('button[type="submit"]') .should('exist') .and('have.text', 'OK'); }); it('solid-form-time widget with attributes', () => { cy.spy(win.sibStore, 'post'); - cy.get('solid-form#time-widget').find('input[name="name"]') - .type('webinar'); + cy.get('solid-form#time-widget').find('input[name="name"]').type('webinar'); // Check min attribute consideration - cy.get('solid-form#time-widget').find('input[type="time"]') - .type('11:00'); - cy.get('solid-form#time-widget').find('input[type="submit"]') - .click().then(() => { + cy.get('solid-form#time-widget').find('input[type="time"]').type('11:00'); + cy.get('solid-form#time-widget') + .find('input[type="submit"]') + .click() + .then(() => { expect(win.sibStore.post).not.be.called; }); // Check max attribute consideration - cy.get('solid-form#time-widget').find('input[type="time"]') - .type('16:00'); - cy.get('solid-form#time-widget').find('input[type="submit"]') - .click().then(() => { + cy.get('solid-form#time-widget').find('input[type="time"]').type('16:00'); + cy.get('solid-form#time-widget') + .find('input[type="submit"]') + .click() + .then(() => { expect(win.sibStore.post).not.be.called; }); // Check step attribute consideration - cy.get('solid-form#time-widget').find('input[type="time"]') - .type('13:10'); - cy.get('solid-form#time-widget').find('input[type="submit"]') - .click().then(() => { + cy.get('solid-form#time-widget').find('input[type="time"]').type('13:10'); + cy.get('solid-form#time-widget') + .find('input[type="submit"]') + .click() + .then(() => { expect(win.sibStore.post).not.be.called; }); - cy.get('solid-form#time-widget').find('input[type="time"]') - .type('13:00'); - cy.get('solid-form#time-widget').find('input[type="submit"]') - .click().then(() => { + cy.get('solid-form#time-widget').find('input[type="time"]').type('13:00'); + cy.get('solid-form#time-widget') + .find('input[type="submit"]') + .click() + .then(() => { expect(win.sibStore.post).to.be.called; }); }); it('minlength attribute', () => { cy.spy(win.sibStore, 'post'); - cy.get('solid-form#minlength').find('input[type="text"]') + cy.get('solid-form#minlength') + .find('input[type="text"]') .type('{selectall}Sacha'); - cy.get('solid-form#minlength').find('input[type="submit"]').click() + cy.get('solid-form#minlength') + .find('input[type="submit"]') + .click() .then(() => { expect(win.sibStore.post).not.be.called; }); }); it('class-submit-button attribute', () => { - cy.get('solid-form#class-submit-button > form').find('div') + cy.get('solid-form#class-submit-button > form') + .find('div') .should('have.attr', 'class', 'submitB-class') - .find('input[type="submit"]').should('exist'); - cy.get('solid-form#class-submit-button2 > form').find('div') + .find('input[type="submit"]') + .should('exist'); + cy.get('solid-form#class-submit-button2 > form') + .find('div') .should('have.attr', 'class', 'submitB-class2') - .find('button').should('exist'); + .find('button') + .should('exist'); }); -}) +}); diff --git a/cypress/e2e/e2e/solid-lang.cy.ts b/cypress/e2e/e2e/solid-lang.cy.ts index 742fbfbcab6c2c97099ba3020a72e2b35bfa03e3..b35bf7cceda26921ff252415834bf47120990740 100644 --- a/cypress/e2e/e2e/solid-lang.cy.ts +++ b/cypress/e2e/e2e/solid-lang.cy.ts @@ -1,22 +1,24 @@ -describe('solid-lang', function() { +describe('solid-lang', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/solid-lang.html') + cy.visit('/examples/e2e/solid-lang.html'); }); - + it('test solid-lang', () => { // mark in window object to show reload - cy.window().then((w: any) => w.beforeReload = true) - - // initilization of a property - cy.window().should('have.prop', 'beforeReload', true) - - - cy.contains('English').click().should(() => { - expect(localStorage.getItem('language')).to.eq('en') + cy.window().then((w: any) => { + w.beforeReload = true; }); - // reload verification : if no property, it confirms the page reload - cy.window().should('not.have.prop', 'beforeReload') - }) -}) + // initilization of a property + cy.window().should('have.prop', 'beforeReload', true); + cy.contains('English') + .click() + .should(() => { + expect(localStorage.getItem('language')).to.eq('en'); + }); + + // reload verification : if no property, it confirms the page reload + cy.window().should('not.have.prop', 'beforeReload'); + }); +}); diff --git a/cypress/e2e/e2e/solid-map.cy.ts b/cypress/e2e/e2e/solid-map.cy.ts deleted file mode 100644 index 71468bf0e891599d00198b0e27c0e1dd9e64148f..0000000000000000000000000000000000000000 --- a/cypress/e2e/e2e/solid-map.cy.ts +++ /dev/null @@ -1,60 +0,0 @@ -describe('solid-map', function() { - this.beforeEach('visit', () => { - cy.visit('/examples/e2e/solid-map.html') - }) - - it('display markers', () => { - cy.get('#map-1 .leaflet-marker-pane').children().should('have.length', 6) - }) - - it('display content in popup markers', () => { - cy.get('#map-2 .leaflet-marker-pane').children().first().click({force: true}) - cy.get('#map-2 .leaflet-popup-pane').children().should('have.length', 1) - cy.get('#map-2 .leaflet-popup-content solid-display') - .should('have.length', 1) - .and('have.attr', 'data-src', '/examples/data/map/event-1.jsonld') - cy.get('#map-2 .leaflet-popup-content solid-display > div > solid-set-default') - .should('have.length', 1) - .and('have.attr', 'name', 'infos') - cy.get('#map-2 .leaflet-popup-content solid-display > div > solid-set-default[name=infos] > solid-display-value').should('have.length', 2) - cy.get('#map-2 .leaflet-popup-content solid-display > div > solid-set-default[name=infos] > solid-display-value[name=name]').contains('Test 1') - cy.get('#map-2 .leaflet-popup-content solid-display > div > solid-set-default[name=infos] > solid-display-value[name=category]').contains('showcase event') - }) - - it('groups markers', () => { - cy.get('#map-3 .leaflet-marker-pane .group-meetup').should('have.length', 4) - cy.get('#map-3 .leaflet-marker-pane .group-showcaseevent').should('have.length', 2) - }) - - it('applies attributes', () => { - cy.get('#map-4 .leaflet-marker-pane').children().first().click({force: true}) - cy.get('#map-4 .leaflet-popup-content solid-display-div[name=name]') - .should('have.length', 1) - .should('have.class', 'test-class-name') - cy.get('#map-4 .leaflet-popup-content solid-display-div[name=name] button') - .should('have.length', 1) - .contains('Modifier') - .click() - cy.get('#map-4 .leaflet-popup-content solid-display-div[name=name] > div') - .should('have.attr', "contenteditable") - }) - - it('filters markers', () => { - cy.get('#filter input[name=category]').type('showcase') - cy.get('#map-5 .leaflet-marker-pane').children().should('have.length', 2) - cy.get('#map-5 span#counter').contains('2 results') - cy.get('#filter input[name=category]').clear().type('mee') - cy.get('#map-5 .leaflet-marker-pane').children().should('have.length', 4) - cy.get('#map-5 span#counter').contains('4 results') - }) - - it('markers clusters', () => { - cy.get('#map-6 .leaflet-marker-pane').children().should('have.length', 3) - cy.get('#map-6 .leaflet-marker-pane').children().eq(2) - .find('span').should('contain', '4') - }) - - it('display federated markers', () => { - cy.get('#map-federated .leaflet-marker-pane').children().should('have.length', 7) - }) -}) diff --git a/cypress/e2e/e2e/solid-table.cy.ts b/cypress/e2e/e2e/solid-table.cy.ts index 3c3b9e2c0ad372b3a3bc5d8986c1c091a365d9dc..5cd5789fb41ec8072a59d596a786f1b399f37b51 100644 --- a/cypress/e2e/e2e/solid-table.cy.ts +++ b/cypress/e2e/e2e/solid-table.cy.ts @@ -1,7 +1,7 @@ // TODO: We should make tests run independently of one another describe('solid-table', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/solid-table.html') + cy.visit('/examples/e2e/solid-table.html'); }); it('display users', () => { @@ -26,23 +26,27 @@ describe('solid-table', { testIsolation: false }, function () { // HEADER // Checkbox first - .children().eq(0) + .children() + .eq(0) .should('have.length', 1) .filter('input[type="checkbox"]') // Custom label .parents('tr') - .find('th').eq(1) + .find('th') + .eq(1) .should('contain', 'First Name') // Default label .parents('tr') - .find('th').eq(2) + .find('th') + .eq(2) .should('contain', 'last_name') // FIRST LINE .parents('table') - .find('tr').eq(1) + .find('tr') + .eq(1) .should('have.attr', 'data-resource', '/examples/data/list/user-3.jsonld') .children('td') .should('have.length', 5) @@ -55,13 +59,15 @@ describe('solid-table', { testIsolation: false }, function () { // First name .parents('tr') - .find('td').eq(1) + .find('td') + .eq(1) .find('solid-display-value') .should('have.text', 'Not A') // Custom widget .parents('tr') - .find('td').eq(3) + .find('td') + .eq(3) .find('solid-display-link-mailto') .find('a'); }); @@ -70,46 +76,55 @@ describe('solid-table', { testIsolation: false }, function () { cy.get('#table-users') // Line 2 - .find('input[type="checkbox"][data-selection]').eq(1) + .find('input[type="checkbox"][data-selection]') + .eq(1) .check() // Line 3 - .parents('table').find('input[type="checkbox"][data-selection]').eq(2) + .parents('table') + .find('input[type="checkbox"][data-selection]') + .eq(2) .check(); // Check data cy.get('#table-users').then($el => { expect((<any>$el[0]).component.selectedLines).to.deep.equal([ - '/examples/data/list/user-2.jsonld', '/examples/data/list/user-4.jsonld' - ]) + '/examples/data/list/user-2.jsonld', + '/examples/data/list/user-4.jsonld', + ]); }); // Select all - cy.get('#table-users') - .find('input[type="checkbox"]').eq(0).check(); + cy.get('#table-users').find('input[type="checkbox"]').eq(0).check(); cy.get('#table-users').then($el => { expect((<any>$el[0]).component.selectedLines).to.deep.equal([ - '/examples/data/list/user-3.jsonld', '/examples/data/list/user-2.jsonld', '/examples/data/list/user-4.jsonld', '/examples/data/list/user-1.jsonld' - ]) + '/examples/data/list/user-3.jsonld', + '/examples/data/list/user-2.jsonld', + '/examples/data/list/user-4.jsonld', + '/examples/data/list/user-1.jsonld', + ]); }); // Unselect all - cy.get('#table-users') - .find('input[type="checkbox"]').eq(0).uncheck(); + cy.get('#table-users').find('input[type="checkbox"]').eq(0).uncheck(); cy.get('#table-users').then($el => { - expect((<any>$el[0]).component.selectedLines).to.deep.equal([]) + expect((<any>$el[0]).component.selectedLines).to.deep.equal([]); }); }); it('orders lines', () => { cy.get('#table-users solid-display-value[name="first_name"]') - .eq(0).should('have.text', 'Not A'); + .eq(0) + .should('have.text', 'Not A'); cy.get('#table-users solid-display-value[name="first_name"]') - .eq(1).should('have.text', 'Paris'); + .eq(1) + .should('have.text', 'Paris'); cy.get('#table-users solid-display-value[name="first_name"]') - .eq(2).should('have.text', 'Pierre'); + .eq(2) + .should('have.text', 'Pierre'); cy.get('#table-users solid-display-value[name="first_name"]') - .eq(3).should('have.text', 'Test'); + .eq(3) + .should('have.text', 'Test'); }); it('shows user-1', () => { @@ -135,28 +150,33 @@ describe('solid-table', { testIsolation: false }, function () { .find('solid-display-value') .should('have.text', 'Test') // Last name - .parents('tr').find('td') + .parents('tr') + .find('td') .eq(1) .find('solid-display-value') .should('have.text', 'User') // email - .parents('tr').find('td') + .parents('tr') + .find('td') .eq(2) .find('solid-display-value') .should('have.text', 'test-user@example.com') // username - .parents('tr').find('td') + .parents('tr') + .find('td') .eq(3) .find('solid-display-value') - .should('have.text', 'admin') + .should('have.text', 'admin'); }); it('makes cells editable', () => { cy.get('#table-users-editable') - .find('tr').eq(0) + .find('tr') + .eq(0) // first_name - .find('td').eq(0) + .find('td') + .eq(0) .find('solid-form') .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld') .and('have.attr', 'fields', 'first_name') @@ -165,8 +185,10 @@ describe('solid-table', { testIsolation: false }, function () { .should('have.value', 'Test') // last_name - .parents('tr').eq(0) - .find('td').eq(1) + .parents('tr') + .eq(0) + .find('td') + .eq(1) .find('solid-form') .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld') .and('have.attr', 'fields', 'last_name') @@ -174,8 +196,10 @@ describe('solid-table', { testIsolation: false }, function () { .and('have.attr', 'partial', '') // email - .parents('tr').eq(0) - .find('td').eq(2) + .parents('tr') + .eq(0) + .find('td') + .eq(2) .find('solid-form') .should('have.attr', 'data-src', '/examples/data/list/user-1.jsonld') .and('have.attr', 'fields', 'email') @@ -189,18 +213,22 @@ describe('solid-table', { testIsolation: false }, function () { cy.get('#table-skills') // Line 2 (CSS) - .find('input[type="checkbox"][data-selection]').eq(1) + .find('input[type="checkbox"][data-selection]') + .eq(1) .check() // Line 3 (Javascript) - .parents('table').find('input[type="checkbox"][data-selection]').eq(2) + .parents('table') + .find('input[type="checkbox"][data-selection]') + .eq(2) .check(); // Check data cy.get('#table-skills').then($el => { expect((<any>$el[0]).component.selectedLines).to.deep.equal([ - '/examples/data/list/skill-2.jsonld', '/examples/data/list/skill-3.jsonld' - ]) + '/examples/data/list/skill-2.jsonld', + '/examples/data/list/skill-3.jsonld', + ]); }); // Order list @@ -209,112 +237,132 @@ describe('solid-table', { testIsolation: false }, function () { // Check data cy.get('#table-skills').then($el => { expect((<any>$el[0]).component.selectedLines).to.deep.equal([ - '/examples/data/list/skill-2.jsonld', '/examples/data/list/skill-3.jsonld' - ]) + '/examples/data/list/skill-2.jsonld', + '/examples/data/list/skill-3.jsonld', + ]); }); cy.get('#table-skills') // Line 1 (CSS) - .find('input[type="checkbox"][data-selection]').eq(0) + .find('input[type="checkbox"][data-selection]') + .eq(0) .should('be.checked') // Line 2 (DevOps) - .parents('table').find('input[type="checkbox"][data-selection]').eq(1) + .parents('table') + .find('input[type="checkbox"][data-selection]') + .eq(1) .should('not.be.checked') // Line 3 (Git) - .parents('table').find('input[type="checkbox"][data-selection]').eq(2) + .parents('table') + .find('input[type="checkbox"][data-selection]') + .eq(2) .should('not.be.checked') // Line 5 (Javascript) - .parents('table').find('input[type="checkbox"][data-selection]').eq(4) - .should('be.checked') + .parents('table') + .find('input[type="checkbox"][data-selection]') + .eq(4) + .should('be.checked'); }); it('numbers displayed', () => { cy.get('#table-skills') // Check numbers displayed - .find('solid-display-value[name="order"]').eq(0) - .should('be.visible').and('contain', '5'); + .find('solid-display-value[name="order"]') + .eq(0) + .should('be.visible') + .and('contain', '5'); }); - it('grouped ordered tables', () => { - cy.get('#grouped-table') - .within(() => { + cy.get('#grouped-table').within(() => { cy.get('solid-group-default').should('have.length', 4); cy.get('solid-group-default').each((item, index) => { if (index === 0) { - cy.wrap(item).find('span').contains('Opéra3') + cy.wrap(item).find('span').contains('Opéra3'); } if (index === 1) { - cy.wrap(item).find('span').contains('Opéra2') + cy.wrap(item).find('span').contains('Opéra2'); } if (index === 2) { - cy.wrap(item).find('span').contains('Opéra') + cy.wrap(item).find('span').contains('Opéra'); } - }); + }); }); - cy.get('#grouped-table-year-desc') - .within(() => { + cy.get('#grouped-table-year-desc').within(() => { cy.get('solid-group-default').should('have.length', 4); cy.get('solid-group-default').each((item, index) => { if (index === 0) { - cy.wrap(item).find('span').contains('2020') + cy.wrap(item).find('span').contains('2020'); } if (index === 1) { - cy.wrap(item).find('span').contains('2019') + cy.wrap(item).find('span').contains('2019'); } if (index === 2) { - cy.wrap(item).find('span').contains('2017') + cy.wrap(item).find('span').contains('2017'); } if (index === 3) { - cy.wrap(item).find('span').contains('2015') + cy.wrap(item).find('span').contains('2015'); } - }); + }); }); - cy.get('#grouped-table-year-asc') - .within(() => { + cy.get('#grouped-table-year-asc').within(() => { cy.get('solid-group-default').should('have.length', 4); cy.get('solid-group-default').each((item, index) => { if (index === 0) { - cy.wrap(item).find('span').contains('2015') + cy.wrap(item).find('span').contains('2015'); } if (index === 1) { - cy.wrap(item).find('span').contains('2017') + cy.wrap(item).find('span').contains('2017'); } if (index === 2) { - cy.wrap(item).find('span').contains('2019') + cy.wrap(item).find('span').contains('2019'); } if (index === 3) { - cy.wrap(item).find('span').contains('2020') + cy.wrap(item).find('span').contains('2020'); } - }); + }); }); - cy.get('#grouped-table-date-asc') - .within(() => { + cy.get('#grouped-table-date-desc').within(() => { cy.get('solid-group-default').should('have.length', 4); cy.get('solid-group-default').each((item, index) => { if (index === 0) { - cy.wrap(item).find('span').contains('2020-07-09') + cy.wrap(item).find('span').contains('2020-07-09'); } if (index === 1) { - cy.wrap(item).find('span').contains('2020-05-10') + cy.wrap(item).find('span').contains('2020-05-10'); } if (index === 2) { - cy.wrap(item).find('span').contains('2017-05-10') + cy.wrap(item).find('span').contains('2017-05-10'); } if (index === 3) { - cy.wrap(item).find('span').contains('2015-05-10') + cy.wrap(item).find('span').contains('2015-05-10'); } - }); + }); }); - + cy.get('#grouped-table-date-asc').within(() => { + cy.get('solid-group-default').should('have.length', 4); + cy.get('solid-group-default').each((item, index) => { + if (index === 0) { + cy.wrap(item).find('span').contains('2015-05-10'); + } + if (index === 1) { + cy.wrap(item).find('span').contains('2017-05-10'); + } + if (index === 2) { + cy.wrap(item).find('span').contains('2020-05-10'); + } + if (index === 3) { + cy.wrap(item).find('span').contains('2020-07-09'); + } + }); + }); }); - -}) \ No newline at end of file +}); diff --git a/cypress/e2e/e2e/solid-widget.cy.ts b/cypress/e2e/e2e/solid-widget.cy.ts index 6800e7be61c8cba327daab412d6193bf3c463a24..57f000efac78a92dcd80de313b33be67ef002c2f 100644 --- a/cypress/e2e/e2e/solid-widget.cy.ts +++ b/cypress/e2e/e2e/solid-widget.cy.ts @@ -1,7 +1,7 @@ // TODO: We should make tests run independently of one another describe('solid-widget', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/solid-widget.html') + cy.visit('/examples/e2e/solid-widget.html'); }); // Display @@ -45,7 +45,6 @@ describe('solid-widget', { testIsolation: false }, function () { cy.get('#display-5') .find('custom-widget-5 span[name=value]') .should('have.text', 'next-view'); - }); // Form @@ -57,36 +56,45 @@ describe('solid-widget', { testIsolation: false }, function () { cy.get('#form-1').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ - "email": "new-email@example.com" - }) - }) + email: 'new-email@example.com', + }); + }); }); }); it('form edition', () => { - cy.get('#form-2') - .find('custom-form-widget-2 input'); + cy.get('#form-2').find('custom-form-widget-2 input'); cy.get('#form-2').then($el => { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ - "email": "test-user@example.com", - "@id": "/examples/data/list/user-1.jsonld", - }) - }) + email: 'test-user@example.com', + '@id': '/examples/data/list/user-1.jsonld', + }); + }); }); }); it('form nested', () => { cy.get('#form-3') - .find('custom-form-widget-3').eq(0) + .find('custom-form-widget-3') + .eq(0) .find('solid-form') - .should('have.attr', 'data-src', '/examples/data/nested-forms/batch-1.jsonld'); + .should( + 'have.attr', + 'data-src', + '/examples/data/nested-forms/batch-1.jsonld', + ); cy.get('#form-3') - .find('custom-form-widget-3').eq(1) + .find('custom-form-widget-3') + .eq(1) .find('solid-form') - .should('have.attr', 'data-src', '/examples/data/nested-forms/batch-2.jsonld') + .should( + 'have.attr', + 'data-src', + '/examples/data/nested-forms/batch-2.jsonld', + ) .find('input[name=title]') .type(' automatique'); @@ -94,21 +102,22 @@ describe('solid-widget', { testIsolation: false }, function () { return (<any>$el[0]).component.getFormValue().then(res => { expect(res).to.deep.equal({ batches: { - "ldp:contains": [ + 'ldp:contains': [ { - title: "Développement", - "@id": "/examples/data/nested-forms/batch-1.jsonld" + title: 'Développement', + '@id': '/examples/data/nested-forms/batch-1.jsonld', }, { - title: "Déploiement automatique", - "@id": "/examples/data/nested-forms/batch-2.jsonld" - } + title: 'Déploiement automatique', + '@id': '/examples/data/nested-forms/batch-2.jsonld', + }, ], - "@id": "/examples/data/nested-forms/customer-invoice-1-batches.jsonld", + '@id': + '/examples/data/nested-forms/customer-invoice-1-batches.jsonld', }, - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" - }) - }) + '@id': '/examples/data/nested-forms/customer-invoice-1.jsonld', + }); + }); }); }); diff --git a/cypress/e2e/e2e/translation.cy.ts b/cypress/e2e/e2e/translation.cy.ts index 440a90812c118dfcd0927280cd0dfc94037a68b8..4f5507a6088362c260ca5190d026e72f830ba8f6 100644 --- a/cypress/e2e/e2e/translation.cy.ts +++ b/cypress/e2e/e2e/translation.cy.ts @@ -3,86 +3,111 @@ describe('translation', function () { cy.visit('/examples/e2e/translation.html', { onBeforeLoad(win) { Object.defineProperty(win.navigator, 'language', { - value: 'fr' - }) - } + value: 'fr', + }); + }, }); }); it('French translation in validation attributes, submit buttons, autocompletion mixin', () => { // french in confirm and buttons const stub = cy.stub(); - cy.on('window:confirm', stub) + cy.on('window:confirm', stub); cy.get('solid-delete#confirm') - .find('button').should('contain', 'Supprimer') + .find('button') + .should('contain', 'Supprimer') .click() .then(() => { - expect(stub.getCall(0)).to.be.calledWith('Merci de confirmer votre choix'); + expect(stub.getCall(0)).to.be.calledWith( + 'Merci de confirmer votre choix', + ); }); cy.get('solid-form#void-submitbutton') - .find('input[type=submit]').should('contain', 'Envoyer'); + .find('input[type=submit]') + .should('contain', 'Envoyer'); // french in dialog, buttons customized cy.get('solid-delete#dialog') - .find('button').should('contain', 'Delete data'); + .find('button') + .should('contain', 'Delete data'); cy.get('solid-delete#dialog > dialog') .should('contain', 'Merci de confirmer votre choix') .and('contain', 'Oui') .and('contain', 'Annuler'); cy.get('solid-form#custom-submitbutton') - .find('input[type=submit]').should('contain', 'Send form'); + .find('input[type=submit]') + .should('contain', 'Send form'); // french in autompletion multipleselect cy.get('solid-form-search#translation-autocomp') - .find('.ss-disabled').should('contain', 'Sélectionner une valeur') + .find('.ss-placeholder') + .filter(':visible') + .should('contain', 'Sélectionner une valeur') .click(); - cy.get('solid-form-search#translation-autocomp') - .find('.ss-search').children().should('have.attr', 'placeholder', 'Rechercher') - .wait(200).type('00'); - cy.get('solid-form-search#translation-autocomp') - .find('.ss-list').children().contains('Aucun résultat') + cy.get('.ss-content') + .find('.ss-search') + .filter(':visible') + .children() + .should('have.attr', 'placeholder', 'Rechercher') + .wait(200) + .type('00'); + cy.get('.ss-content') + .find('.ss-list') + .children() + .contains('Aucun résultat'); }); it('English translation in validation attributes, submit buttons, autocompletion mixin', () => { cy.get('#en').click(); // english in confirm and buttons const stub = cy.stub(); - cy.on('window:confirm', stub) + cy.on('window:confirm', stub); cy.get('solid-delete#confirm') - .find('button').should('contain', 'Delete') + .find('button') + .should('contain', 'Delete') .click() .then(() => { expect(stub.getCall(0)).to.be.calledWith('Please, confirm your choice'); }); cy.get('solid-form#void-submitbutton') - .find('input[type=submit]').should('contain', 'Submit'); + .find('input[type=submit]') + .should('contain', 'Submit'); // english in dialog, buttons customized cy.get('solid-delete#dialog') - .find('button').should('contain', 'Delete data'); + .find('button') + .should('contain', 'Delete data'); cy.get('solid-delete#dialog > dialog') .should('contain', 'Please, confirm your choice') .and('contain', 'Yes') .and('contain', 'Cancel'); cy.get('solid-form#custom-submitbutton') - .find('input[type=submit]').should('contain', 'Send form'); + .find('input[type=submit]') + .should('contain', 'Send form'); // english in autompletion multipleselect cy.get('solid-form-search#translation-autocomp') - .find('.ss-disabled').should('contain', 'Select a value') + .find('.ss-placeholder') + .filter(':visible') + .should('contain', 'Select a value') .click(); - cy.get('solid-form-search#translation-autocomp') - .find('.ss-search').children().should('have.attr', 'placeholder', 'Search') - .wait(200).type('00'); - cy.get('solid-form-search#translation-autocomp') - .find('.ss-list').children().contains('No result') + cy.get('.ss-content') + .find('.ss-search') + .filter(':visible') + .children() + .should('have.attr', 'placeholder', 'Search') + .wait(200) + .type('00'); + cy.get('.ss-content').find('.ss-list').children().contains('No result'); }); it('Missing translation file', () => { cy.get('#fr').find('button').click(); - cy.get('solid-delete#confirm').find('button').should('contain', 'Supprimer'); + cy.get('solid-delete#confirm') + .find('button') + .should('contain', 'Supprimer'); // Asking to get a missing file, English loaded by default cy.get('#it').find('button').click(); cy.get('solid-delete#confirm').find('button').should('contain', 'Delete'); - }) -}); \ No newline at end of file + }); +}); diff --git a/cypress/e2e/e2e/validation.cy.ts b/cypress/e2e/e2e/validation.cy.ts index 00cbac81472cf7eccdc280c6058a94549fb799a5..7afb4d815588229f327b7b91aa1cafa5aed60d98 100644 --- a/cypress/e2e/e2e/validation.cy.ts +++ b/cypress/e2e/e2e/validation.cy.ts @@ -5,9 +5,9 @@ describe('validation', function () { cy.visit('/examples/e2e/validation.html', { onBeforeLoad(win) { Object.defineProperty(win.navigator, 'language', { - value: 'en' - }) - } + value: 'en', + }); + }, }); cy.window().then(w => { win = w; @@ -17,105 +17,136 @@ describe('validation', function () { it('confirm popup on solid-delete', () => { const stub = cy.stub(); - cy.on('window:confirm', stub) + cy.on('window:confirm', stub); cy.get('solid-delete#confirm') .should('have.attr', 'confirmation-type', 'confirm') - .and('have.attr', 'confirmation-message') + .and('have.attr', 'confirmation-message'); cy.get('solid-delete#confirm') .find('button') .click() .then(() => { - expect(stub.getCall(0)).to.be.calledWith('Are you sure ?') + expect(stub.getCall(0)).to.be.calledWith('Are you sure ?'); }); }); it('confirm popup on solid-form', () => { const stub = cy.stub(); - cy.on('window:confirm', stub) + cy.on('window:confirm', stub); cy.get('solid-form#confirm') .find('input[type=submit]') .click() .then(() => { - expect(stub.getCall(0)).to.be.calledWith('Please, confirm your choice') //message by default displayed in English translation + expect(stub.getCall(0)).to.be.calledWith('Please, confirm your choice'); //message by default displayed in English translation }); }); it('dialog popup on solid-form', () => { // simple dialog popup cy.get('solid-form#simple-dialog > dialog') - .find('p').should('contain', 'Please, confirm your choice')//message by default displayed in English translation - cy.get('solid-form#simple-dialog > dialog > div').children().eq(0) - .should('contain', 'Yes') - cy.get('solid-form#simple-dialog > dialog > div').children().eq(1) - .should('contain', 'Cancel') + .find('p') + .should('contain', 'Please, confirm your choice'); //message by default displayed in English translation + cy.get('solid-form#simple-dialog > dialog > div') + .children() + .eq(0) + .should('contain', 'Yes'); + cy.get('solid-form#simple-dialog > dialog > div') + .children() + .eq(1) + .should('contain', 'Cancel'); cy.get('solid-form#simple-dialog > dialog') - .find('button').should('have.not.attr', 'class') + .find('button') + .should('have.not.attr', 'class'); //custom dialog popup cy.get('solid-form#custom-dialog > dialog') - .find('p').should('contain', 'Custom message : Are you sure ?') - cy.get('solid-form#custom-dialog > dialog > div').children().eq(0) + .find('p') + .should('contain', 'Custom message : Are you sure ?'); + cy.get('solid-form#custom-dialog > dialog > div') + .children() + .eq(0) .should('contain', 'Certainly') - .and('have.attr', 'class', 'submit-button') - cy.get('solid-form#custom-dialog > dialog > div').children().eq(1) + .and('have.attr', 'class', 'submit-button'); + cy.get('solid-form#custom-dialog > dialog > div') + .children() + .eq(1) .should('contain', 'Quit') - .and('have.attr', 'class', 'cancel-button') + .and('have.attr', 'class', 'cancel-button'); }); it('actions on dialog popup', () => { //dialog modal correctly opened and closed with buttons - cy.get('solid-form#custom-dialog > form > solid-form-label-text > input') - .type('{selectall}Presentation') - cy.get('solid-form#custom-dialog > form > div > input').click() - cy.get('solid-form#custom-dialog > dialog') - .should('have.attr', 'open') + cy.get( + 'solid-form#custom-dialog > form > solid-form-label-text > input', + ).type('{selectall}Presentation'); + cy.get('solid-form#custom-dialog > form > div > input').click(); + cy.get('solid-form#custom-dialog > dialog').should('have.attr', 'open'); - cy.get('solid-form#custom-dialog > dialog > div').children().eq(1).click() - cy.get('solid-form#custom-dialog > dialog') - .should('not.have.attr', 'open') - cy.get('solid-form#custom-dialog > form > div > input').click() - cy.get('solid-form#custom-dialog > dialog') - .should('have.attr', 'open') + cy.get('solid-form#custom-dialog > dialog > div').children().eq(1).click(); + cy.get('solid-form#custom-dialog > dialog').should('not.have.attr', 'open'); + cy.get('solid-form#custom-dialog > form > div > input').click(); + cy.get('solid-form#custom-dialog > dialog').should('have.attr', 'open'); //form well sent, data well deleted cy.spy(win.sibStore, 'post'); - cy.get('solid-form#custom-dialog > dialog > div').children().eq(0).click().then(() => { - expect(win.sibStore.post).to.be.called; - cy.get('solid-form#custom-dialog > dialog') - .should('not.have.attr', 'open') - }); + cy.get('solid-form#custom-dialog > dialog > div') + .children() + .eq(0) + .click() + .then(() => { + expect(win.sibStore.post).to.be.called; + cy.get('solid-form#custom-dialog > dialog').should( + 'not.have.attr', + 'open', + ); + }); cy.spy(win.sibStore, 'delete'); - cy.get('solid-delete#delete-data > dialog > div').children().eq(0).click({ force: true }).then(() => { - expect(win.sibStore.delete).to.be.called; - cy.get('solid-delete#delete-data > dialog') - .should('not.have.attr', 'open') - }); + cy.get('solid-delete#delete-data > dialog > div') + .children() + .eq(0) + .click({ force: true }) + .then(() => { + expect(win.sibStore.delete).to.be.called; + cy.get('solid-delete#delete-data > dialog').should( + 'not.have.attr', + 'open', + ); + }); }); it('confirmation-type missing', () => { cy.spy(cnsl, 'warn'); - cy.get('solid-delete#missing-type').find('button').click().then(() => { - expect(cnsl.warn).to.be.called; - }); + cy.get('solid-delete#missing-type') + .find('button') + .click() + .then(() => { + expect(cnsl.warn).to.be.called; + }); }); it('confirmation widget', () => { cy.get('solid-form#confirmation-widget') .find('dialog') - .find('my-widget-confirm').should('have.attr', 'value', '/examples/data/project.jsonld') - .find('solid-display-value').should('have.attr', 'value', 'Envoyer une fusée') - cy.get('solid-form#confirmation-widget > form > div > input') - .click() + .find('my-widget-confirm') + .should('have.attr', 'value', '/examples/data/project.jsonld') + .find('solid-display-value') + .should('have.attr', 'value', 'Envoyer une fusée'); + cy.get('solid-form#confirmation-widget > form > div > input').click(); cy.get('solid-form#confirmation-widget') - .find('dialog').should('contain', 'Envoyer une fusée') - .find('div').children().eq(1).click(); + .find('dialog') + .should('contain', 'Envoyer une fusée') + .find('div') + .children() + .eq(1) + .click(); cy.get('solid-delete#confirmation-widget') .find('dialog') - .find('my-widget-confirm2').should('have.attr', 'value', '/examples/data/project.jsonld') - .find('solid-display-value').should('have.attr', 'value', 'Envoyer une fusée') - cy.get('solid-delete#confirmation-widget > button') - .click() + .find('my-widget-confirm2') + .should('have.attr', 'value', '/examples/data/project.jsonld') + .find('solid-display-value') + .should('have.attr', 'value', 'Envoyer une fusée'); + cy.get('solid-delete#confirmation-widget > button').click(); cy.get('solid-delete#confirmation-widget') - .find('dialog').should('contain', 'Envoyer une fusée') - }) -}); \ No newline at end of file + .find('dialog') + .should('contain', 'Envoyer une fusée'); + }); +}); diff --git a/cypress/e2e/e2e/widgets-custom.cy.ts b/cypress/e2e/e2e/widgets-custom.cy.ts index f1785d364fc424284434b8a21058c1ac22d64486..6ab4beefece48a85b52f945c767528e24bfc6bf6 100644 --- a/cypress/e2e/e2e/widgets-custom.cy.ts +++ b/cypress/e2e/e2e/widgets-custom.cy.ts @@ -1,7 +1,7 @@ describe('custom widgets', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/widgets-custom.html') - }) + cy.visit('/examples/e2e/widgets-custom.html'); + }); it('set value', () => { cy.get('solid-display#test1') @@ -9,12 +9,12 @@ describe('custom widgets', function () { .should('have.length', 1) .find('h1') .should('contain', 'Envoyer une fusée'); - }) + }); it('set attributes', () => { cy.get('solid-display#test2') .find('custom-widget') .should('have.length', 1) - .and('have.attr', 'class', 'test-class') - }) -}) + .and('have.attr', 'class', 'test-class'); + }); +}); diff --git a/cypress/e2e/e2e/widgets-display-multiple.cy.ts b/cypress/e2e/e2e/widgets-display-multiple.cy.ts index 595a285e853a2da45fd4afdc43024b71294fc1dc..a1b8d4d53c53d9d5dda9aab6087ee89de07010bd 100644 --- a/cypress/e2e/e2e/widgets-display-multiple.cy.ts +++ b/cypress/e2e/e2e/widgets-display-multiple.cy.ts @@ -1,6 +1,6 @@ -describe('multiple widgets', function() { +describe('multiple widgets', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/widgets-display-multiple.html') + cy.visit('/examples/e2e/widgets-display-multiple.html'); }); it('solid-display-multiple and empty widget', () => { @@ -9,14 +9,17 @@ describe('multiple widgets', function() { .find('empty-skills') .should('contain', 'This username has no skills'); cy.get('solid-multiple#noskill > solid-display > span') - .children().should('have.length', 1); + .children() + .should('have.length', 1); cy.get('solid-multiple#skills') .should('have.attr', 'empty-widget', 'empty-skills') - .find('solid-display-value') + .find('solid-display-value'); cy.get('solid-multiple#skills > solid-display > div') - .children().should('have.length', 2); + .children() + .should('have.length', 2); cy.get('solid-multiple#skills > solid-display > span') - .children().should('not.exist') + .children() + .should('not.exist'); }); -}) +}); diff --git a/cypress/e2e/e2e/widgets-display.cy.ts b/cypress/e2e/e2e/widgets-display.cy.ts index 3ba5dfd53132bafaa1ea9b7faf093033f7509ffe..dd85fccdce680c01bb937722858f1f6188ea8044 100644 --- a/cypress/e2e/e2e/widgets-display.cy.ts +++ b/cypress/e2e/e2e/widgets-display.cy.ts @@ -1,36 +1,36 @@ describe('display widgets', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/widgets-display.html') - }) + cy.visit('/examples/e2e/widgets-display.html'); + }); it('solid-display-value', () => { cy.get('solid-display-value') .should('contain', 'test value 1') - .children().should('have.length', 0); - }) + .children() + .should('have.length', 0); + }); it('solid-display-div', () => { cy.get('solid-display-div#test1') .should('contain', 'test value 1') .find('> div') .should('have.length', 1) - .should('have.attr', 'name', 'test1') - }) + .should('have.attr', 'name', 'test1'); + }); it('solid-display-div editable', () => { - cy.intercept("PATCH", '**/resource-1.jsonld', { + cy.intercept('PATCH', '**/resource-1.jsonld', { headers: { - contentType: 'application/ld+json' - } - }) - cy.intercept("GET", '**/resource-1.jsonld', { + contentType: 'application/ld+json', + }, + }); + cy.intercept('GET', '**/resource-1.jsonld', { headers: { - contentType: 'application/ld+json' - } - }) - - cy.get('solid-display-div#test2') - .children().should('have.length', 2); + contentType: 'application/ld+json', + }, + }); + + cy.get('solid-display-div#test2').children().should('have.length', 2); cy.get('solid-display-div#test2') .find('> div') .should('have.attr', 'data-editable', ''); @@ -50,8 +50,8 @@ describe('display widgets', function () { .should('have.length', 1) .and('have.attr', 'name', 'test1') .and('have.attr', 'href', 'http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-link-mailto', () => { cy.get('solid-display-link-mailto') @@ -59,19 +59,19 @@ describe('display widgets', function () { .should('have.length', 1) .and('have.attr', 'name', 'test1') .and('have.attr', 'href', 'mailto:http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-link-mailto-label', () => { cy.get('solid-display-link-mailto-label') .find('label') - .should('contain', 'mail: ') + .should('contain', 'mail: '); cy.get('solid-display-link-mailto-label') .find('a') .should('have.attr', 'name', 'test1') .and('have.attr', 'href', 'mailto:http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-link-tel', () => { cy.get('solid-display-link-tel') @@ -79,19 +79,19 @@ describe('display widgets', function () { .should('have.length', 1) .and('have.attr', 'name', 'test1') .and('have.attr', 'href', 'tel:http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-link-tel-label', () => { cy.get('solid-display-link-tel-label') .find('label') - .should('contain', 'tel: ') + .should('contain', 'tel: '); cy.get('solid-display-link-tel-label') .find('a') .should('have.attr', 'name', 'test1') .and('have.attr', 'href', 'tel:http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-link-blank', () => { cy.get('solid-display-link-blank') @@ -101,19 +101,19 @@ describe('display widgets', function () { .and('have.attr', 'href', 'http://example.com') .and('have.attr', 'target', '_blank') .and('have.attr', 'link-text', 'link text') - .and('contain', 'link text') - }) - + .and('contain', 'link text'); + }); + it('solid-display-link-blank-label', () => { cy.get('solid-display-link-blank-label') .find('label') - .should('contain', 'blank test: ') + .should('contain', 'blank test: '); cy.get('solid-display-link-blank-label') .find('a') .should('have.attr', 'name', 'test1') .and('have.attr', 'href', 'http://example.com') - .and('contain', 'http://example.com') - }) + .and('contain', 'http://example.com'); + }); it('solid-display-img', () => { cy.get('solid-display-img') @@ -121,8 +121,8 @@ describe('display widgets', function () { .should('have.length', 1) .and('have.attr', 'name', 'test1') .and('have.attr', 'src', 'test-img.png') - .and('have.attr', 'alt', 'alternative text') - }) + .and('have.attr', 'alt', 'alternative text'); + }); it('solid-display-boolean', () => { cy.get('solid-display-boolean[name=test1]') @@ -131,9 +131,9 @@ describe('display widgets', function () { .and('contain', 'Is displayed ?'); cy.get('solid-display-boolean[name=test2]') .find('label') - .should('not.exist') - }) - + .should('not.exist'); + }); + it('solid-display-label-div', () => { cy.get('solid-display-label-div[name=test1]') .find('label') @@ -152,7 +152,7 @@ describe('display widgets', function () { .find('> div') .should('have.length', 1) .and('contain', 'test value 1'); - }) + }); it('solid-display-date-div', () => { cy.get('solid-display-date-div') @@ -162,7 +162,7 @@ describe('display widgets', function () { .and('contain', '28') .and('contain', '5') .and('contain', '2020'); - }) + }); it('solid-display-datetime-div', () => { cy.get('solid-display-datetime-div') @@ -174,14 +174,14 @@ describe('display widgets', function () { .and('contain', '2020') .and('contain', '00') .and('contain', ':'); - }) + }); it('solid-display-multiline-div', () => { cy.get('solid-display-multiline-div') .find('> div') .should('have.length', 1) - .and('contain.html', '<br>') - }) + .and('contain.html', '<br>'); + }); it('solid-multiple', () => { cy.get('solid-multiple') @@ -195,34 +195,36 @@ describe('display widgets', function () { .and('contain', 'CSS') .and('contain', 'Javascript') .and('not.contain', 'DevOps') - .and('not.contain', 'HTML') - }) + .and('not.contain', 'HTML'); + }); it('solid-action', () => { - cy.get('solid-action').first() + cy.get('solid-action') + .first() .find('solid-link') .should('have.attr', 'data-src', 'resource-1.jsonld') .and('have.attr', 'next', 'next-page') .and('contain', 'test1'); - }) + }); it('solid-action', () => { - cy.get('solid-action').last() + cy.get('solid-action') + .last() .find('solid-link') .should('have.attr', 'data-src', 'resource-1.jsonld') .and('have.attr', 'next', 'next-page') .and('contain', 'link text'); - }) + }); it('solid-action-label', () => { cy.get('solid-action-label') .find('label') - .should('contain', 'label solid-action: ') + .should('contain', 'label solid-action: '); cy.get('solid-action-label') .find('solid-link') .should('have.attr', 'data-src', 'resource-1.jsonld') .and('have.attr', 'next', 'next-page') .and('contain', 'test1'); - }) + }); it('solid-display-div-markdown', () => { cy.get('solid-display-div-markdown') @@ -231,9 +233,7 @@ describe('display widgets', function () { cy.get('solid-display-div-markdown') .find('strong') .should('contain', 'bold'); - cy.get('solid-display-div-markdown') - .find('em') - .should('contain', 'italic'); + cy.get('solid-display-div-markdown').find('em').should('contain', 'italic'); cy.get('solid-display-div-markdown') .find('a') .should('contain', 'link') @@ -242,40 +242,54 @@ describe('display widgets', function () { // Change value to something else cy.get('solid-display-div-markdown') .invoke('attr', 'value', '**bold** [link](http://corndog.io/)') - .find('em').should('not.exist'); + .find('em') + .should('not.exist'); // Change value to empty cy.get('solid-display-div-markdown') .invoke('attr', 'value', '') .find('div[name="test display markdown"]') - .children().should('have.length', 0) + .children() + .should('have.length', 0); }); - + it('solid-display-div-autolink', () => { - cy.get('solid-display-div-autolink > div').children() + cy.get('solid-display-div-autolink > div') + .children() .should('have.length', 2); - cy.get('solid-display-div-autolink > div').children().eq(0) + cy.get('solid-display-div-autolink > div') + .children() + .eq(0) .should('have.attr', 'href', 'http://www.w3.org'); - cy.get('solid-display-div-autolink > div').children().eq(1) - .should('have.attr', 'href', 'http://www.window-swap.com') + cy.get('solid-display-div-autolink > div') + .children() + .eq(1) + .should('have.attr', 'href', 'http://www.window-swap.com'); }); it('solid-display-value-oembed', () => { - cy.intercept("GET", 'https://ldp-server2.test/oembed/', { + cy.intercept('GET', 'https://ldp-server2.test/oembed/', { headers: { - contentType: 'application/ld+json' - }, fixture: "oembed.jsonld" + contentType: 'application/ld+json', + }, + fixture: 'oembed.jsonld', + }); - }) - - cy.get('solid-display-value-oembed').children() - .should('have.length', 1); + cy.get('solid-display-value-oembed').children().should('have.length', 1); cy.get('solid-display-value-oembed > iframe') - .should('have.attr', 'src', 'https://www.youtube.com/embed/M3r2XDceM6A?feature=oembed') + .should( + 'have.attr', + 'src', + 'https://www.youtube.com/embed/M3r2XDceM6A?feature=oembed', + ) .and('have.attr', 'width', '200') .and('have.attr', 'height', '113') .and('have.attr', 'frameborder', '0') - .and('have.attr', 'allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share') + .and( + 'have.attr', + 'allow', + 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share', + ) .and('have.attr', 'allowfullscreen'); }); -}) +}); diff --git a/cypress/e2e/e2e/widgets-form-multiple.cy.ts b/cypress/e2e/e2e/widgets-form-multiple.cy.ts index 8424d9e37ff62a7fc14d9adc9156bb5e4d66c0aa..2851f1306fd5768fd2e9cfe7fea21f361fae6bb9 100644 --- a/cypress/e2e/e2e/widgets-form-multiple.cy.ts +++ b/cypress/e2e/e2e/widgets-form-multiple.cy.ts @@ -1,12 +1,11 @@ // TODO: We should make tests run independently of one another describe('multiple widgets', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/widgets-form-multiple.html') - }) + cy.visit('/examples/e2e/widgets-form-multiple.html'); + }); it('solid-form-multiple', () => { - cy.get('solid-form-multiple#test1') - .children().should('have.length', 1); + cy.get('solid-form-multiple#test1').children().should('have.length', 1); cy.get('solid-form-multiple#test1') .find('button') @@ -14,18 +13,18 @@ describe('multiple widgets', { testIsolation: false }, function () { .click(); // add a line // Check new line - cy.get('solid-form-multiple#test1') - .children().should('have.length', 2); + cy.get('solid-form-multiple#test1').children().should('have.length', 2); cy.get('solid-form-multiple#test1 > div[data-index="test0"]') - .children().should('have.length', 2); + .children() + .should('have.length', 2); cy.get('solid-form-multiple#test1 > div[data-index="test0"]') .find('solid-form-text') .should('have.attr', 'data-holder', '') .should('have.attr', 'value', '') .should('have.attr', 'range', '') - .should('have.attr', 'name', 'test') + .should('have.attr', 'name', 'test'); // Remove line cy.get('solid-form-multiple#test1 > div[data-index="test0"]') @@ -33,22 +32,21 @@ describe('multiple widgets', { testIsolation: false }, function () { .should('contain', '×') .click(); - cy.get('solid-form-multiple#test1') - .children().should('have.length', 1); - cy.get('solid-form-multiple#test1 > div[data-index="test0"]').should('not.exist') - }) + cy.get('solid-form-multiple#test1').children().should('have.length', 1); + cy.get('solid-form-multiple#test1 > div[data-index="test0"]').should( + 'not.exist', + ); + }); it('solid-form-multiple and range', () => { - cy.get('solid-form-multiple#test2') - .find('button').contains('+') - .click(); // add a line + cy.get('solid-form-multiple#test2').find('button').contains('+').click(); // add a line // Check new line - cy.get('solid-form-multiple#test2') - .children().should('have.length', 2); + cy.get('solid-form-multiple#test2').children().should('have.length', 2); cy.get('solid-form-multiple#test2 > div[data-index="test0"]') - .children().should('have.length', 2); + .children() + .should('have.length', 2); cy.get('solid-form-multiple#test2 > div[data-index="test0"]') // check attributes .find('solid-form-dropdown') @@ -56,32 +54,43 @@ describe('multiple widgets', { testIsolation: false }, function () { .should('have.attr', 'value', '') .should('have.attr', 'range', '/examples/data/list/skills.jsonld') .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld') - .should('have.attr', 'name', 'test') + .should('have.attr', 'name', 'test'); - cy.get('solid-form-multiple#test2 > div[data-index="test0"] solid-form-dropdown') + cy.get( + 'solid-form-multiple#test2 > div[data-index="test0"] solid-form-dropdown', + ) .find('select > option') // check options .should('have.length', 9) - .eq(4).should('contain', 'DevOps'); + .eq(4) + .should('contain', 'DevOps'); // add 2 new lines cy.get('solid-form-multiple#test2') - .find('button').contains('+') + .find('button') + .contains('+') .click() .click(); cy.get('solid-form-multiple#test2') // check children added - .children().should('have.length', 4); + .children() + .should('have.length', 4); - cy.get('solid-form-multiple#test2 > div[data-index="test1"] solid-form-dropdown') - .find('select > option').should('have.length', 9); // check options of children + cy.get( + 'solid-form-multiple#test2 > div[data-index="test1"] solid-form-dropdown', + ) + .find('select > option') + .should('have.length', 9); // check options of children // Select values - cy.get('solid-form-multiple#test2 > div[data-index="test0"] solid-form-dropdown > select') - .select('DevOps'); - cy.get('solid-form-multiple#test2 > div[data-index="test1"] solid-form-dropdown > select') - .select('HTML'); - cy.get('solid-form-multiple#test2 > div[data-index="test2"] solid-form-dropdown > select') - .select('Javascript'); + cy.get( + 'solid-form-multiple#test2 > div[data-index="test0"] solid-form-dropdown > select', + ).select('DevOps'); + cy.get( + 'solid-form-multiple#test2 > div[data-index="test1"] solid-form-dropdown > select', + ).select('HTML'); + cy.get( + 'solid-form-multiple#test2 > div[data-index="test2"] solid-form-dropdown > select', + ).select('Javascript'); // Remove line cy.get('solid-form-multiple#test2 > div[data-index="test0"]') @@ -90,62 +99,104 @@ describe('multiple widgets', { testIsolation: false }, function () { .click(); cy.get('solid-form-multiple#test2') // check children - .children().should('have.length', 3); - cy.get('solid-form-multiple#test2 > div[data-index="test0"]').should('not.exist') - cy.get('solid-form-multiple#test2 > div[data-index="test1"]').should('exist') - cy.get('solid-form-multiple#test2 > div[data-index="test2"]').should('exist') + .children() + .should('have.length', 3); + cy.get('solid-form-multiple#test2 > div[data-index="test0"]').should( + 'not.exist', + ); + cy.get('solid-form-multiple#test2 > div[data-index="test1"]').should( + 'exist', + ); + cy.get('solid-form-multiple#test2 > div[data-index="test2"]').should( + 'exist', + ); // Check select values still here - cy.get('solid-form-multiple#test2 > div[data-index="test1"] select') - .should('have.value', '{"@id": "/examples/data/list/skill-1.jsonld"}'); - cy.get('solid-form-multiple#test2 > div[data-index="test2"] select') - .should('have.value', '{"@id": "/examples/data/list/skill-3.jsonld"}'); + cy.get('solid-form-multiple#test2 > div[data-index="test1"] select').should( + 'have.value', + '{"@id": "/examples/data/list/skill-1.jsonld"}', + ); + cy.get('solid-form-multiple#test2 > div[data-index="test2"] select').should( + 'have.value', + '{"@id": "/examples/data/list/skill-3.jsonld"}', + ); // Check widget value - cy.get('solid-form-multiple#test2').then($el => { // Check API + cy.get('solid-form-multiple#test2').then($el => { + // Check API expect((<any>$el[0]).component.value).to.equal(''); // value attribute - expect((<any>$el[0]).component.getValue()).to.deep.equal(['{"@id": "/examples/data/list/skill-1.jsonld"}', '{"@id": "/examples/data/list/skill-3.jsonld"}']); // form value + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + '{"@id": "/examples/data/list/skill-1.jsonld"}', + '{"@id": "/examples/data/list/skill-3.jsonld"}', + ]); // form value }); - }) + }); it('solid-form-multiple and value', () => { cy.get('solid-form-multiple#test3') // check data-src - .should('have.attr', 'data-src', '/examples/data/list/user-1-skills.jsonld') - .children().should('have.length', 3); - - cy.get('solid-form-multiple#test3 > button') - .should('contain', 'add'); - cy.get('solid-form-multiple#test3 > div[data-index="test0"] > button') - .should('contain', 'remove'); - - cy.get('solid-form-multiple#test3 > div[data-index="test0"] solid-form-dropdown') - .should('have.attr', 'value', '/examples/data/list/skill-2.jsonld'); - cy.get('solid-form-multiple#test3 > div[data-index="test1"] solid-form-dropdown') - .should('have.attr', 'value', '/examples/data/list/skill-3.jsonld'); + .should( + 'have.attr', + 'data-src', + '/examples/data/list/user-1-skills.jsonld', + ) + .children() + .should('have.length', 3); + + cy.get('solid-form-multiple#test3 > button').should('contain', 'add'); + cy.get( + 'solid-form-multiple#test3 > div[data-index="test0"] > button', + ).should('contain', 'remove'); + + cy.get( + 'solid-form-multiple#test3 > div[data-index="test0"] solid-form-dropdown', + ).should('have.attr', 'value', '/examples/data/list/skill-2.jsonld'); + cy.get( + 'solid-form-multiple#test3 > div[data-index="test1"] solid-form-dropdown', + ).should('have.attr', 'value', '/examples/data/list/skill-3.jsonld'); // Check widget value - cy.get('solid-form-multiple#test3').then($el => { // Check API - expect((<any>$el[0]).component.value).to.equal('/examples/data/list/user-1-skills.jsonld'); // value attribute - expect((<any>$el[0]).component.getValue()).to.deep.equal(['{"@id": "/examples/data/list/skill-2.jsonld"}', '{"@id": "/examples/data/list/skill-3.jsonld"}']); // form value + cy.get('solid-form-multiple#test3').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal( + '/examples/data/list/user-1-skills.jsonld', + ); // value attribute + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + '{"@id": "/examples/data/list/skill-2.jsonld"}', + '{"@id": "/examples/data/list/skill-3.jsonld"}', + ]); // form value }); - cy.get('solid-form-multiple#test3 > div[data-index="test1"] button').click(); //remove line - - cy.get('solid-form-multiple#test3').then($el => { // Check API - expect((<any>$el[0]).component.value).to.equal('/examples/data/list/user-1-skills.jsonld'); // value attribute - expect((<any>$el[0]).component.getValue()).to.deep.equal(['{"@id": "/examples/data/list/skill-2.jsonld"}']); // form value + cy.get( + 'solid-form-multiple#test3 > div[data-index="test1"] button', + ).click(); //remove line + + cy.get('solid-form-multiple#test3').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal( + '/examples/data/list/user-1-skills.jsonld', + ); // value attribute + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + '{"@id": "/examples/data/list/skill-2.jsonld"}', + ]); // form value }); - cy.get('solid-form-multiple#test3 > button') - .should('have.class', 'class-addbutton'); - cy.get('solid-form-multiple#test3 > div[data-index="test0"] > button') - .should('have.class', 'class-removebutton'); + cy.get('solid-form-multiple#test3 > button').should( + 'have.class', + 'class-addbutton', + ); + cy.get( + 'solid-form-multiple#test3 > div[data-index="test0"] > button', + ).should('have.class', 'class-removebutton'); }); - it('solid-form-multipleselect', () => { cy.get('solid-form-multipleselect') // check data-src - .should('have.attr', 'data-src', '/examples/data/list/user-1-skills.jsonld') - .children().should('have.length', 1); + .should( + 'have.attr', + 'data-src', + '/examples/data/list/user-1-skills.jsonld', + ) + .children() + .should('have.length', 1); cy.get('solid-form-multipleselect') .find('solid-form-dropdown') @@ -153,22 +204,39 @@ describe('multiple widgets', { testIsolation: false }, function () { .should('have.attr', 'name', 'test') .should('have.attr', 'range', '/examples/data/list/skills.jsonld') .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld') - .should('have.attr', 'values', '["/examples/data/list/skill-2.jsonld","/examples/data/list/skill-3.jsonld"]'); - - cy.get('solid-form-multipleselect').then($el => { // Check API - expect((<any>$el[0]).component.value).to.equal('/examples/data/list/user-1-skills.jsonld'); // value attribute - expect((<any>$el[0]).component.getValue()).to.deep.equal([{ "@id": "/examples/data/list/skill-2.jsonld" }, { "@id": "/examples/data/list/skill-3.jsonld" }]); // form value + .should( + 'have.attr', + 'values', + '["/examples/data/list/skill-2.jsonld","/examples/data/list/skill-3.jsonld"]', + ); + + cy.get('solid-form-multipleselect').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal( + '/examples/data/list/user-1-skills.jsonld', + ); // value attribute + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + { '@id': '/examples/data/list/skill-2.jsonld' }, + { '@id': '/examples/data/list/skill-3.jsonld' }, + ]); // form value }); - cy.get('solid-form-multipleselect select').select(['CSS', 'Javascript', 'DevOps']); - cy.get('solid-form-multipleselect').then($el => { // Check API - expect((<any>$el[0]).component.getValue()).to.deep.equal([{ "@id": "/examples/data/list/skill-2.jsonld" }, { "@id": "/examples/data/list/skill-3.jsonld" }, { "@id": "/examples/data/list/skill-4.jsonld" }]); // form value + cy.get('solid-form-multipleselect select').select([ + 'CSS', + 'Javascript', + 'DevOps', + ]); + cy.get('solid-form-multipleselect').then($el => { + // Check API + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + { '@id': '/examples/data/list/skill-2.jsonld' }, + { '@id': '/examples/data/list/skill-3.jsonld' }, + { '@id': '/examples/data/list/skill-4.jsonld' }, + ]); // form value }); }); it('solid-form-multipleselect-autocompletion', () => { - cy.get('solid-form-multipleselect-autocompletion') - .children().should('have.length', 1); cy.get('solid-form-multipleselect-autocompletion') .find('solid-form-dropdown') .should('have.attr', 'data-holder', '') @@ -177,64 +245,86 @@ describe('multiple widgets', { testIsolation: false }, function () { .and('have.attr', 'range', '/examples/data/list/skills.jsonld') .and('have.attr', 'data-src', '/examples/data/list/skills.jsonld') .and('have.attr', 'order-asc', 'name'); - cy.get('solid-form-multipleselect-autocompletion > solid-form-dropdown') - .children().should('have.length', 2); cy.get('solid-form-multipleselect-autocompletion > solid-form-dropdown') .find('select') .should('have.attr', 'data-holder', '') .and('have.attr', 'multiple', 'multiple') .and('have.attr', 'name', 'test1') .and('have.attr', 'style', 'display: none;') - .and('have.attr', 'data-ssid'); - cy.get('solid-form-multipleselect-autocompletion > solid-form-dropdown') - .find('> div') - .children().should('have.length', 2); - cy.get('solid-form-multipleselect-autocompletion > solid-form-dropdown .ss-option').eq(0) + .and('have.attr', 'data-id'); + cy.get( + 'solid-form-multipleselect-autocompletion > div.ss-content > div.ss-list .ss-option', + ) + .eq(0) .should('contain', 'CSS'); // select values - cy.get('solid-form-multipleselect-autocompletion .ss-main').click(); - cy.get('solid-form-multipleselect-autocompletion .ss-content.ss-open .ss-option').eq(1).click(); - cy.get('solid-form-multipleselect-autocompletion .ss-option').eq(1) - .should('have.class', 'ss-option-selected'); + cy.get('solid-form-multipleselect-autocompletion .ss-main') + .filter(':visible') + .eq(0) + .click(); + cy.get( + 'solid-form-multipleselect-autocompletion .ss-content.ss-open-below .ss-option', + ) + .eq(1) + .click(); + cy.get('solid-form-multipleselect-autocompletion .ss-option') + .eq(1) + .should('have.class', 'ss-selected'); cy.get('solid-form-multipleselect-autocompletion .ss-values') - .children().should('have.length', 1) + .eq(1) + .children() + .should('have.length', 1) .should('contain', 'DevOps'); - cy.get('solid-form-multipleselect-autocompletion') - .find('.ss-add').click(); }); it('solid-form-autocompletion-placeholder & search attributes', () => { // attributes for placeholders and text displayed in SlimSelect cy.get('#search-attr') - .find('.ss-disabled').contains('Sélectionne une compétence') - .click({force: true}); + .find('.ss-placeholder') + .filter(':visible') + .contains('Sélectionne une compétence') + .click({ force: true }); cy.get('solid-form-multipleselect-autocompletion-placeholder') - .find('.ss-search').children().should('have.attr', 'placeholder', 'Rechercher par clavier') + .find('.ss-search') + .children() + .eq(0) + .should('have.attr', 'placeholder', 'Rechercher par clavier') .wait(200) .type('00'); cy.get('#search-attr') - .find('.ss-list').children().contains('Pas de concordance') - }) + .find('.ss-list') + .children() + .contains('Pas de concordance'); + }); it('solid-form-checkboxes', () => { cy.get('solid-form-checkboxes#test1') .find('solid-form-multicheckbox > div[name=test1]') - .children().should('have.length', 8); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(0) + .children() + .should('have.length', 8); + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(0) .should('not.have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(1) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(1) .should('have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(2) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(2) .should('have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(3) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(3) .should('not.have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(4) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(4) .should('not.have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(5) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(5) .should('not.have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(6) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(6) .should('not.have.attr', 'checked'); - cy.get('solid-form-checkboxes#test1 input[type=checkbox]').eq(7) + cy.get('solid-form-checkboxes#test1 input[type=checkbox]') + .eq(7) .should('not.have.attr', 'checked'); // Get value @@ -242,8 +332,9 @@ describe('multiple widgets', { testIsolation: false }, function () { .find('input[value="html"]') .check({ force: true }); - cy.get('solid-form-checkboxes#test2').then($el => { // Check API + cy.get('solid-form-checkboxes#test2').then($el => { + // Check API expect((<any>$el[0]).component.getValue()).to.deep.equal(['html']); // form value }); }); -}) +}); diff --git a/cypress/e2e/e2e/widgets-form.cy.ts b/cypress/e2e/e2e/widgets-form.cy.ts index e498933041f81348c5734b75ac4cd291d48b969f..9d755fc321eccea2abe87191978d7bba751e757a 100644 --- a/cypress/e2e/e2e/widgets-form.cy.ts +++ b/cypress/e2e/e2e/widgets-form.cy.ts @@ -2,12 +2,11 @@ describe('form widgets', { testIsolation: false }, function () { this.beforeAll('visit', () => { cy.clock(Date.UTC(2020, 11, 15), ['Date']); // Define fake date for start-value="today" test - cy.visit('/examples/e2e/widgets-form.html') - }) + cy.visit('/examples/e2e/widgets-form.html'); + }); it('solid-form-text', () => { - cy.get('solid-form-text') - .children().should('have.length', 1); + cy.get('solid-form-text').children().should('have.length', 1); cy.get('solid-form-text') // check attributes .find('input') @@ -15,50 +14,54 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'name', 'test1') .and('have.attr', 'value', 'test value 1') .and('have.attr', 'data-holder'); - cy.get('solid-form-text').then($el => { // check API value + cy.get('solid-form-text').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal('test value 1'); // form value }); cy.get('solid-form-text > input') // type value .clear() .type('new value'); - cy.get('solid-form-text > input') - .and('have.attr', 'value', 'test value 1'); // attr does not change + cy.get('solid-form-text > input').and('have.attr', 'value', 'test value 1'); // attr does not change - cy.get('solid-form-text').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('test value 1'); // value attribute + cy.get('solid-form-text').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('test value 1'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal('new value'); // form value }); cy.get('solid-form-text > input') // clear value .clear(); - cy.get('solid-form-text').then($el => { // Check API + cy.get('solid-form-text').then($el => { + // Check API expect((<any>$el[0]).component.getValue()).to.equal(''); // value attribute }); }); it('solid-form-text + label and placeholders', () => { + cy.get('solid-form-text-label').children().should('have.length', 2); cy.get('solid-form-text-label') - .children().should('have.length', 2); - cy.get('solid-form-text-label') - .find('> label').should('contain', 'My label'); + .find('> label') + .should('contain', 'My label'); + cy.get('solid-form-text-placeholder').children().should('have.length', 1); cy.get('solid-form-text-placeholder') - .children().should('have.length', 1); - cy.get('solid-form-text-placeholder') - .find('> input').should('have.attr', 'placeholder', 'My placeholder'); + .find('> input') + .should('have.attr', 'placeholder', 'My placeholder'); cy.get('solid-form-text-label-placeholder') - .children().should('have.length', 2); + .children() + .should('have.length', 2); cy.get('solid-form-text-label-placeholder') - .find('> label').should('contain', 'test1'); + .find('> label') + .should('contain', 'test1'); cy.get('solid-form-text-label-placeholder') - .find('> input').should('have.attr', 'placeholder', 'test1'); + .find('> input') + .should('have.attr', 'placeholder', 'test1'); }); it('solid-form-textarea', () => { - cy.get('solid-form-textarea') - .children().should('have.length', 1); + cy.get('solid-form-textarea').children().should('have.length', 1); cy.get('solid-form-textarea') // check attributes .find('textarea') @@ -66,7 +69,8 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'maxlength', '15') .and('have.attr', 'data-holder'); - cy.get('solid-form-textarea').then($el => { // check API value + cy.get('solid-form-textarea').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal('test value 1'); // form value }); @@ -74,25 +78,24 @@ describe('form widgets', { testIsolation: false }, function () { .clear() .type('new value'); - - cy.get('solid-form-textarea').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('test value 1'); // value attribute + cy.get('solid-form-textarea').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('test value 1'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal('new value'); // form value }); cy.get('solid-form-textarea > textarea') // type value .clear() .type('new value with a maxlength'); - cy.get('solid-form-textarea').then($el => { // Check API + cy.get('solid-form-textarea').then($el => { + // Check API expect((<any>$el[0]).component.getValue()).to.equal('new value with '); // maxlength attribute effect }); - }) + }); it('solid-form-checkbox', () => { - cy.get('solid-form-checkbox') - .children().should('have.length', 1); - cy.get('solid-form-checkbox > label') - .children().should('have.length', 2); + cy.get('solid-form-checkbox').children().should('have.length', 1); + cy.get('solid-form-checkbox > label').children().should('have.length', 2); cy.get('solid-form-checkbox') // check attributes .find('input') @@ -100,30 +103,27 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'type', 'checkbox') .and('have.attr', 'data-holder', '') .and('have.attr', 'checked'); - cy.get('solid-form-checkbox') - .find('div') - .contains('test1'); - + cy.get('solid-form-checkbox').find('div').contains('test1'); - cy.get('solid-form-checkbox').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('true'); // value attribute + cy.get('solid-form-checkbox').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('true'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal(true); // form value }); - cy.get('solid-form-checkbox') // Change value - .find('input').click(); - + .find('input') + .click(); - cy.get('solid-form-checkbox').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('true'); // value attribute + cy.get('solid-form-checkbox').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('true'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal(false); // form value }); - }) + }); it('solid-form-date', () => { - cy.get('solid-form-date#test1') - .children().should('have.length', 1); + cy.get('solid-form-date#test1').children().should('have.length', 1); // check attributes cy.get('solid-form-date#test1') .find('input') @@ -132,29 +132,27 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'value', '2020-05-21') .and('have.attr', 'data-holder'); // type value - cy.get('solid-form-date#test1 > input') - .clear() - .type('2020-12-31'); - cy.get('solid-form-date#test1 > input') - .and('have.attr', 'value', '2020-05-21'); // attr does not change + cy.get('solid-form-date#test1 > input').clear().type('2020-12-31'); + cy.get('solid-form-date#test1 > input').and( + 'have.attr', + 'value', + '2020-05-21', + ); // attr does not change // Check API cy.get('solid-form-date#test1').then($el => { - expect((<any>$el[0]).component['value']).to.equal('2020-05-21'); // value attribute + expect((<any>$el[0]).component.value).to.equal('2020-05-21'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal('2020-12-31'); // form value }); cy.get('solid-form-date#test2') .find('input') .and('have.attr', 'value', '2020-05-21'); - cy.get('solid-form-date#test3') - .find('input') - .and('have.attr', 'value', ''); - }) + cy.get('solid-form-date#test3').find('input').and('have.attr', 'value', ''); + }); it('solid-form-number', () => { - cy.get('solid-form-number') - .children().should('have.length', 1); + cy.get('solid-form-number').children().should('have.length', 1); cy.get('solid-form-number') // check attributes .find('input') @@ -165,36 +163,35 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'max', '7') .and('have.attr', 'data-holder'); - cy.get('solid-form-number').then($el => { // check API value + cy.get('solid-form-number').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal(5); // form value }); cy.get('solid-form-number > input') // type value .clear() .type('8'); - cy.get('solid-form-number > input') - .and('have.attr', 'value', '5'); // attr does not change - + cy.get('solid-form-number > input').and('have.attr', 'value', '5'); // attr does not change - cy.get('solid-form-number').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('5'); // value attribute + cy.get('solid-form-number').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('5'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal(8); // form value }); - // step attribute + // step attribute cy.get('solid-form-number > input') // type value .clear() .type('{upArrow}{upArrow}{upArrow}'); - cy.get('solid-form-number').then($el => { // check API value + cy.get('solid-form-number').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal(6); // form value }); - }); it('solid-form-email', () => { - cy.get('solid-form-email') - .children().should('have.length', 1); + cy.get('solid-form-email').children().should('have.length', 1); cy.get('solid-form-email') // check attributes .find('input') @@ -203,26 +200,29 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'value', 'test@test.com') .and('have.attr', 'data-holder'); - cy.get('solid-form-email').then($el => { // check API value + cy.get('solid-form-email').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal('test@test.com'); // form value }); cy.get('solid-form-email > input') // type value .clear() .type('new@example.com'); - cy.get('solid-form-email > input') - .and('have.attr', 'value', 'test@test.com'); // attr does not change - - - cy.get('solid-form-email').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('test@test.com'); // value attribute + cy.get('solid-form-email > input').and( + 'have.attr', + 'value', + 'test@test.com', + ); // attr does not change + + cy.get('solid-form-email').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('test@test.com'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal('new@example.com'); // form value }); }); it('solid-form-hidden', () => { - cy.get('solid-form-hidden') - .children().should('have.length', 1); + cy.get('solid-form-hidden').children().should('have.length', 1); cy.get('solid-form-hidden') // check attributes .find('input') @@ -231,113 +231,162 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'value', 'test value 1') .and('have.attr', 'data-holder'); - cy.get('solid-form-hidden').then($el => { // check API value + cy.get('solid-form-hidden').then($el => { + // check API value expect((<any>$el[0]).component.getValue()).to.equal('test value 1'); // form value }); cy.get('solid-form-hidden > input') // type value .invoke('attr', 'value', 'new value'); - cy.get('solid-form-hidden').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal('test value 1'); // value attribute + cy.get('solid-form-hidden').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal('test value 1'); // value attribute expect((<any>$el[0]).component.getValue()).to.equal('new value'); // form value }); - }) + }); it('solid-form-dropdown', () => { // With no initial value cy.get('solid-form-dropdown#test1') .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld') - .children().should('have.length', 1); + .children() + .should('have.length', 1); cy.get('solid-form-dropdown#test1') // check attributes .find('select') .and('have.attr', 'name', 'test1') .and('have.attr', 'data-holder', '') - .children().and('have.length', 9); + .children() + .and('have.length', 9); - cy.get('solid-form-dropdown#test1 > select > option').eq(0) // check options + cy.get('solid-form-dropdown#test1 > select > option') + .eq(0) // check options .should('have.attr', 'value', '') .contains('-'); - cy.get('solid-form-dropdown#test1 > select > option').eq(1) - .should('have.attr', 'value', '{"@id": "/examples/data/list/skill-1.jsonld"}') + cy.get('solid-form-dropdown#test1 > select > option') + .eq(1) + .should( + 'have.attr', + 'value', + '{"@id": "/examples/data/list/skill-1.jsonld"}', + ) .contains('HTML'); - cy.get('solid-form-dropdown#test1').then($el => { // Check API value + cy.get('solid-form-dropdown#test1').then($el => { + // Check API value expect((<any>$el[0]).component.getValue()).to.equal(''); // form value }); - cy.get('solid-form-dropdown#test1 > select').select('CSS').should('have.value', '{"@id": "/examples/data/list/skill-2.jsonld"}'); // test change value + cy.get('solid-form-dropdown#test1 > select') + .select('CSS') + .should('have.value', '{"@id": "/examples/data/list/skill-2.jsonld"}'); // test change value - cy.get('solid-form-dropdown#test1').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal(''); // value attribute - expect((<any>$el[0]).component.getValue()).to.equal('{"@id": "/examples/data/list/skill-2.jsonld"}'); // form value + cy.get('solid-form-dropdown#test1').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal(''); // value attribute + expect((<any>$el[0]).component.getValue()).to.equal( + '{"@id": "/examples/data/list/skill-2.jsonld"}', + ); // form value expect((<any>$el[0]).component.context).to.be.not.empty; // check storeMixin properties expect((<any>$el[0]).component.resourceId).to.be.not.empty; // check storeMixin properties }); // With initial value - cy.get('solid-form-dropdown#test2 > select').should('have.value', '{"@id": "/examples/data/list/skill-2.jsonld"}'); + cy.get('solid-form-dropdown#test2 > select').should( + 'have.value', + '{"@id": "/examples/data/list/skill-2.jsonld"}', + ); cy.get('solid-form-dropdown#test2').then($el => { - expect((<any>$el[0]).component['value']).to.equal('/examples/data/list/skill-2.jsonld'); // value attribute - expect((<any>$el[0]).component.getValue()).to.equal('{"@id": "/examples/data/list/skill-2.jsonld"}'); // form value + expect((<any>$el[0]).component.value).to.equal( + '/examples/data/list/skill-2.jsonld', + ); // value attribute + expect((<any>$el[0]).component.getValue()).to.equal( + '{"@id": "/examples/data/list/skill-2.jsonld"}', + ); // form value }); // With optionLabel - cy.get('solid-form-dropdown#test3 > select > option').eq(1) - .should('have.attr', 'value', '{"@id": "/examples/data/list/skill-1.jsonld"}') + cy.get('solid-form-dropdown#test3 > select > option') + .eq(1) + .should( + 'have.attr', + 'value', + '{"@id": "/examples/data/list/skill-1.jsonld"}', + ) .contains('/examples/data/list/skill-1.jsonld'); // With multiple cy.get('solid-form-dropdown#test4 > select') .should('have.attr', 'multiple', 'multiple') - .children().should('have.length', 8); + .children() + .should('have.length', 8); cy.get('solid-form-dropdown#test4').then($el => { - expect((<any>$el[0]).component.getValue()).to.deep.equal([{ '@id': '/examples/data/list/skill-1.jsonld' }, { '@id': '/examples/data/list/skill-3.jsonld' }]); // form value + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + { '@id': '/examples/data/list/skill-1.jsonld' }, + { '@id': '/examples/data/list/skill-3.jsonld' }, + ]); // form value }); - cy.get('solid-form-dropdown#test4 > select').select(['CSS', 'Javascript']) // change value + cy.get('solid-form-dropdown#test4 > select').select(['CSS', 'Javascript']); // change value cy.get('solid-form-dropdown#test4').then($el => { - expect((<any>$el[0]).component.getValue()).to.deep.equal([{ '@id': '/examples/data/list/skill-2.jsonld' }, { '@id': '/examples/data/list/skill-3.jsonld' }]); // form value + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + { '@id': '/examples/data/list/skill-2.jsonld' }, + { '@id': '/examples/data/list/skill-3.jsonld' }, + ]); // form value }); // With order-desc - cy.get('solid-form-dropdown#test5 > select > option').eq(1) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(1) .should('contain', 'Python'); - cy.get('solid-form-dropdown#test5 > select > option').eq(2) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(2) .should('contain', 'PHP'); - cy.get('solid-form-dropdown#test5 > select > option').eq(3) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(3) .should('contain', 'Node'); - cy.get('solid-form-dropdown#test5 > select > option').eq(4) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(4) .should('contain', 'Javascript'); - cy.get('solid-form-dropdown#test5 > select > option').eq(5) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(5) .should('contain', 'HTML'); - cy.get('solid-form-dropdown#test5 > select > option').eq(6) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(6) .should('contain', 'Git'); - cy.get('solid-form-dropdown#test5 > select > option').eq(7) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(7) .should('contain', 'DevOps'); - cy.get('solid-form-dropdown#test5 > select > option').eq(8) + cy.get('solid-form-dropdown#test5 > select > option') + .eq(8) .should('contain', 'CSS'); // With federation - cy.get('solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-1.jsonld\\"}"]') - .should('contain', 'Circle from server 1'); - cy.get('solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-2.jsonld\\"}"]') - .should('contain', 'Another circle from server 1'); - cy.get('solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-3.jsonld\\"}"]') - .should('contain', 'Circle from server 2'); - cy.get('solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-4.jsonld\\"}"]') - .should('contain', 'Another circle from server 2'); + cy.get( + 'solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-1.jsonld\\"}"]', + ).should('contain', 'Circle from server 1'); + cy.get( + 'solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-2.jsonld\\"}"]', + ).should('contain', 'Another circle from server 1'); + cy.get( + 'solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-3.jsonld\\"}"]', + ).should('contain', 'Circle from server 2'); + cy.get( + 'solid-form-dropdown#test6 > select > option[value="{\\"@id\\": \\"/examples/data/federation/circles-4.jsonld\\"}"]', + ).should('contain', 'Another circle from server 2'); // With enumeration in range cy.get('solid-form-dropdown#test7 > select') .should('have.value', 'option1') - .children().should('have.length', 5) + .children() + .should('have.length', 5) .eq(2) .should('have.attr', 'value', 'option2') .should('contain', 'option2'); cy.get('solid-form-dropdown#test8 > select') - .children().should('have.length', 4) + .children() + .should('have.length', 4) .eq(1) .should('have.attr', 'value', '1') .should('contain', 'option a'); @@ -347,72 +396,105 @@ describe('form widgets', { testIsolation: false }, function () { .children() .should('have.length', 8); cy.get('solid-form-dropdown-autocompletion-placeholder > div') - .find('div .ss-search').children() + .find('div.ss-search') + .children() .eq(0) .should('have.attr', 'placeholder', 'Skills :'); cy.get('solid-form-dropdown-autocompletion-placeholder > div') - .find('div .ss-list') + .find('div.ss-list') + .first() .children() .should('have.length', 8) .should('not.contain', 'Skills :'); // With option-value cy.get('solid-form-dropdown#test10 > select') - .children().eq(2) + .children() + .eq(2) .should('have.attr', 'value', 'CSS') .should('contain', 'CSS'); cy.get('solid-form-dropdown#test11 > select') - .children().eq(2) - .should('have.attr', 'value', '{"@id": "/examples/data/list/profile-2.jsonld"}'); + .children() + .eq(2) + .should( + 'have.attr', + 'value', + '{"@id": "/examples/data/list/profile-2.jsonld"}', + ); cy.get('solid-form-dropdown#test12 > select') - .children().eq(2) - .should('have.attr', 'value', '{"@id": "/examples/data/list/profile-2.jsonld"}'); - }) + .children() + .eq(2) + .should( + 'have.attr', + 'value', + '{"@id": "/examples/data/list/profile-2.jsonld"}', + ); + }); it('solid-form-radio', () => { // With no initial value cy.get('solid-form-radio#test1') .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld') - .children().should('have.length', 1); + .children() + .should('have.length', 1); cy.get('solid-form-radio#test1') // check attributes .find('> div') .and('have.attr', 'name', 'test1') - .children().and('have.length', 8); + .children() + .and('have.length', 8); - cy.get('solid-form-radio#test1 > div > label').eq(0) // check options + cy.get('solid-form-radio#test1 > div > label') + .eq(0) // check options .contains('HTML') .parent() .find('input') .should('have.attr', 'type', 'radio') - .should('have.attr', 'value', '{"@id": "/examples/data/list/skill-1.jsonld"}'); - - cy.get('solid-form-radio#test1').then($el => { // Check API value + .should( + 'have.attr', + 'value', + '{"@id": "/examples/data/list/skill-1.jsonld"}', + ); + + cy.get('solid-form-radio#test1').then($el => { + // Check API value expect((<any>$el[0]).component.getValue()).to.equal(''); // form value }); cy.get('solid-form-radio#test1 > div > label').eq(1).click(); // test change value - cy.get('solid-form-radio#test1').then($el => { // Check API - expect((<any>$el[0]).component['value']).to.equal(''); // value attribute - expect((<any>$el[0]).component.getValue()).to.equal('{"@id": "/examples/data/list/skill-2.jsonld"}'); // form value + cy.get('solid-form-radio#test1').then($el => { + // Check API + expect((<any>$el[0]).component.value).to.equal(''); // value attribute + expect((<any>$el[0]).component.getValue()).to.equal( + '{"@id": "/examples/data/list/skill-2.jsonld"}', + ); // form value expect((<any>$el[0]).component.context).to.be.not.empty; // check storeMixin properties expect((<any>$el[0]).component.resourceId).to.be.not.empty; // check storeMixin properties }); // With initial value - cy.get('solid-form-radio#test2 label').eq(2).find('input').should('have.attr', 'checked', 'checked'); + cy.get('solid-form-radio#test2 label') + .eq(2) + .find('input') + .should('have.attr', 'checked', 'checked'); cy.get('solid-form-radio#test2').then($el => { - expect((<any>$el[0]).component['value']).to.equal('/examples/data/list/skill-3.jsonld'); // value attribute - expect((<any>$el[0]).component.getValue()).to.equal('{"@id": "/examples/data/list/skill-3.jsonld"}'); // form value + expect((<any>$el[0]).component.value).to.equal( + '/examples/data/list/skill-3.jsonld', + ); // value attribute + expect((<any>$el[0]).component.getValue()).to.equal( + '{"@id": "/examples/data/list/skill-3.jsonld"}', + ); // form value }); cy.get('solid-form-radio#test3') .find('> div') .and('have.attr', 'name', 'test3') - .children().and('have.length', '3'); + .children() + .and('have.length', '3'); - cy.get('solid-form-radio#test3 > div > label').eq(0) + cy.get('solid-form-radio#test3 > div > label') + .eq(0) .contains('option1') .parent() .find('input') @@ -421,54 +503,66 @@ describe('form widgets', { testIsolation: false }, function () { // Test click on multiple radio cy.get('solid-form-radio#test3 input[type=radio][value="option1"]') - .check().should('be.checked'); - cy.get('solid-form-radio#test3 input[type=radio][value="option2"]') - .should('not.be.checked'); - cy.get('solid-form-radio#test3 input[type=radio][value="option3"]') - .should('not.be.checked'); + .check() + .should('be.checked'); + cy.get('solid-form-radio#test3 input[type=radio][value="option2"]').should( + 'not.be.checked', + ); + cy.get('solid-form-radio#test3 input[type=radio][value="option3"]').should( + 'not.be.checked', + ); cy.get('solid-form-radio#test3 input[type=radio][value="option3"]') - .check().should('be.checked'); - cy.get('solid-form-radio#test3 input[type=radio][value="option1"]') - .should('not.be.checked'); - cy.get('solid-form-radio#test3 input[type=radio][value="option2"]') - .should('not.be.checked'); + .check() + .should('be.checked'); + cy.get('solid-form-radio#test3 input[type=radio][value="option1"]').should( + 'not.be.checked', + ); + cy.get('solid-form-radio#test3 input[type=radio][value="option2"]').should( + 'not.be.checked', + ); cy.get('solid-form-radio#test4') .find('> div') .and('have.attr', 'name', 'test4') - .children().and('have.length', '4') + .children() + .and('have.length', '4'); - cy.get('solid-form-radio#test4 > div > label').eq(0) + cy.get('solid-form-radio#test4 > div > label') + .eq(0) .contains('option1') .parent() .find('input') .should('have.attr', 'type', 'radio') .should('have.attr', 'value', 'a'); - }) + }); it('solid-form-checkboxes', () => { cy.get('#test-checkboxes') - .find('label:nth-child(-2n + 6)').click({ multiple: true }) + .find('label:nth-child(-2n + 6)') + .click({ multiple: true }); cy.get('#test-checkboxes').then(async ($el: any) => { const values = await $el[0].component.getValue(); expect(values).to.deep.equal([ - { "@id": "/examples/data/list/skill-2.jsonld" }, - { "@id": "/examples/data/list/skill-4.jsonld" }, - { "@id": "/examples/data/list/skill-6.jsonld" }, + { '@id': '/examples/data/list/skill-2.jsonld' }, + { '@id': '/examples/data/list/skill-4.jsonld' }, + { '@id': '/examples/data/list/skill-6.jsonld' }, ]); }); - }) + }); it('solid-form-rangenumber', () => { cy.get('solid-form-rangenumber[name=test1]') - .children().should('have.length', 2); + .children() + .should('have.length', 2); - cy.get('solid-form-rangenumber > input').eq(0) + cy.get('solid-form-rangenumber > input') + .eq(0) .should('have.attr', 'data-holder', '') .and('have.attr', 'type', 'number') .and('have.attr', 'name', 'test1-start'); - cy.get('solid-form-rangenumber > input').eq(1) + cy.get('solid-form-rangenumber > input') + .eq(1) .should('have.attr', 'data-holder', '') .and('have.attr', 'type', 'number') .and('have.attr', 'name', 'test1-end'); @@ -487,21 +581,26 @@ describe('form widgets', { testIsolation: false }, function () { }); // Addition start-value-[field] and end-value-[field] attributes - cy.get('solid-form-rangenumber[name=test2] > input').eq(0) - .should('have.attr', 'value', '2') - cy.get('solid-form-rangenumber[name=test2] > input').eq(1) - .should('have.attr', 'value', '10') + cy.get('solid-form-rangenumber[name=test2] > input') + .eq(0) + .should('have.attr', 'value', '2'); + cy.get('solid-form-rangenumber[name=test2] > input') + .eq(1) + .should('have.attr', 'value', '10'); }); it('solid-form-rangedate', () => { cy.get('solid-form-rangedate[name=test1]') - .children().should('have.length', 2); + .children() + .should('have.length', 2); - cy.get('solid-form-rangedate > input').eq(0) + cy.get('solid-form-rangedate > input') + .eq(0) .should('have.attr', 'data-holder', '') .and('have.attr', 'type', 'date') .and('have.attr', 'name', 'test1-start'); - cy.get('solid-form-rangedate > input').eq(1) + cy.get('solid-form-rangedate > input') + .eq(1) .should('have.attr', 'data-holder', '') .and('have.attr', 'type', 'date') .and('have.attr', 'name', 'test1-end'); @@ -512,50 +611,69 @@ describe('form widgets', { testIsolation: false }, function () { cy.get('solid-form-rangedate > input').eq(0).type('2020-02-12'); cy.get('solid-form-rangedate').then($el => { - expect((<any>$el[0]).component.getValue()).to.deep.equal(['2020-02-12', '']); // form value + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + '2020-02-12', + '', + ]); // form value }); cy.get('solid-form-rangedate > input').eq(1).type('2020-05-24'); cy.get('solid-form-rangedate').then($el => { - expect((<any>$el[0]).component.getValue()).to.deep.equal(['2020-02-12', '2020-05-24']); // form value + expect((<any>$el[0]).component.getValue()).to.deep.equal([ + '2020-02-12', + '2020-05-24', + ]); // form value }); // Addition start-value-[field] and end-value-[field] attributes - cy.get('solid-form-rangedate[name=test2] > input').eq(0) - .should('have.attr', 'value', '2020-12-15') - cy.get('solid-form-rangedate[name=test2] > input').eq(1) - .should('have.attr', 'value', '2222-12-22') + cy.get('solid-form-rangedate[name=test2] > input') + .eq(0) + .should('have.attr', 'value', '2020-12-15'); + cy.get('solid-form-rangedate[name=test2] > input') + .eq(1) + .should('have.attr', 'value', '2222-12-22'); }); it('solid-form-color', () => { - cy.get('solid-form-color') - .children().should('have.length', 1) + cy.get('solid-form-color').children().should('have.length', 1); - cy.get('solid-form-color > input') - .should('have.attr', 'type', 'color') + cy.get('solid-form-color > input').should('have.attr', 'type', 'color'); }); it('solid-form-text-labellast', () => { - cy.get('solid-form-text-labellast').children() - .should('have.length', 2); - cy.get('solid-form-text-labellast').find('label').last() + cy.get('solid-form-text-labellast').children().should('have.length', 2); + cy.get('solid-form-text-labellast') + .find('label') + .last() .should('contain', 'test labellast'); }); it('solid-form-dropdown-addable', () => { // Without addable-data-src provided cy.get('solid-form-dropdown-addable#test1') - .children().should('have.length', 2); - cy.get('solid-form-dropdown-addable#test1 > solid-form') - .should('have.attr', 'data-src', '/examples/data/list/skills.jsonld'); + .children() + .should('have.length', 2); + cy.get('solid-form-dropdown-addable#test1 > solid-form').should( + 'have.attr', + 'data-src', + '/examples/data/list/skills.jsonld', + ); cy.get('solid-form-dropdown-addable#test1 > solid-form > form') - .children().should('have.length', 3) - cy.get('solid-form-dropdown-addable#test1 > solid-form > form > solid-form-label-text').eq(0) - .should('have.attr', 'name', 'name') - cy.get('solid-form-dropdown-addable#test1 > solid-form > form > solid-form-label-text').eq(1) - .should('have.attr', 'name', 'order') - cy.get('solid-form-dropdown-addable#test1 > solid-form > form > div > input') - .should('have.attr', 'type', 'submit') + .children() + .should('have.length', 3); + cy.get( + 'solid-form-dropdown-addable#test1 > solid-form > form > solid-form-label-text', + ) + .eq(0) + .should('have.attr', 'name', 'name'); + cy.get( + 'solid-form-dropdown-addable#test1 > solid-form > form > solid-form-label-text', + ) + .eq(1) + .should('have.attr', 'name', 'order'); + cy.get( + 'solid-form-dropdown-addable#test1 > solid-form > form > div > input', + ).should('have.attr', 'type', 'submit'); // With addable-data-src provided @@ -565,52 +683,73 @@ describe('form widgets', { testIsolation: false }, function () { .and('have.attr', 'fields', 'name, username, age') .and('have.attr', 'widget-name', 'solid-form-text-placeholder-label') .and('have.attr', 'placeholder-name', 'Enter your name') - .and('have.attr', 'submit-button', 'Send data') + .and('have.attr', 'submit-button', 'Send data'); cy.get('solid-form-dropdown-addable#test2 > solid-form > form') - .children().should('have.length', 4) - // Verify attributes and values in tags created by widget - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label') + .children() + .should('have.length', 4); + // Verify attributes and values in tags created by widget + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label', + ) .should('have.attr', 'name', 'name') - .and('have.attr', 'placeholder', 'Enter your name') - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label') - .find('label').should('contain', 'name') - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label') - .find('input').should('have.attr', 'placeholder', 'Enter your name') - - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > solid-form-label-text').eq(0) - .should('have.attr', 'name', 'username') - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > solid-form-label-text').eq(1) - .should('have.attr', 'name', 'age') - cy.get('solid-form-dropdown-addable#test2 > solid-form > form > div > input') + .and('have.attr', 'placeholder', 'Enter your name'); + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label', + ) + .find('label') + .should('contain', 'name'); + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > solid-form-text-placeholder-label', + ) + .find('input') + .should('have.attr', 'placeholder', 'Enter your name'); + + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > solid-form-label-text', + ) + .eq(0) + .should('have.attr', 'name', 'username'); + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > solid-form-label-text', + ) + .eq(1) + .should('have.attr', 'name', 'age'); + cy.get( + 'solid-form-dropdown-addable#test2 > solid-form > form > div > input', + ) .should('have.attr', 'type', 'submit') - .and('have.attr', 'value', 'Send data') + .and('have.attr', 'value', 'Send data'); }); it('solid-form-password', () => { + cy.get('solid-form-label-password').children().should('have.length', 2); cy.get('solid-form-label-password') - .children().should('have.length', 2); - cy.get('solid-form-label-password') - .children().eq(0).should('contain', 'password'); + .children() + .eq(0) + .should('contain', 'password'); cy.get('solid-form-label-password > input') .should('have.attr', 'type', 'password') .and('have.value', 'password123'); }); it('solid-form-time', () => { + cy.get('solid-form-label-time#time1').children().should('have.length', 2); cy.get('solid-form-label-time#time1') - .children().should('have.length', 2); - cy.get('solid-form-label-time#time1') - .children().eq(0).should('contain', 'time'); + .children() + .eq(0) + .should('contain', 'time'); cy.get('solid-form-label-time#time1 > input') .should('have.attr', 'type', 'time') .and('have.value', '15:15'); cy.get('solid-form-label-time#time2') - .children().eq(0).should('contain', 'start time'); + .children() + .eq(0) + .should('contain', 'start time'); cy.get('solid-form-label-time#time2 > input') .should('have.attr', 'type', 'time') - .and('have.attr', 'min', "12:00") - .and('have.attr', 'max', "14:00") - .and('have.attr', 'step', "3600"); + .and('have.attr', 'min', '12:00') + .and('have.attr', 'max', '14:00') + .and('have.attr', 'step', '3600'); }); -}) +}); diff --git a/cypress/e2e/e2e/widgets-sets.cy.ts b/cypress/e2e/e2e/widgets-sets.cy.ts index cf3524621d1aaa4f5a958091e8fcdffdaca2ac2d..00cc7f4cd9cf3c66b1abe2b7b60fea963e197e18 100644 --- a/cypress/e2e/e2e/widgets-sets.cy.ts +++ b/cypress/e2e/e2e/widgets-sets.cy.ts @@ -1,26 +1,19 @@ -describe('set widget', function() { +describe('set widget', function () { this.beforeEach('visit', () => { - cy.visit('/examples/e2e/widgets-sets.html') - }) + cy.visit('/examples/e2e/widgets-sets.html'); + }); it('solid-set-default', () => { - cy.get('solid-set-default') - .children().should('have.length', 0); - }) + cy.get('solid-set-default').children().should('have.length', 0); + }); it('solid-set-div', () => { - cy.get('solid-set-div') - .children().should('have.length', 1); - cy.get('solid-set-div') - .find('div') - .should('have.attr', 'data-content', ''); - }) - + cy.get('solid-set-div').children().should('have.length', 1); + cy.get('solid-set-div').find('div').should('have.attr', 'data-content', ''); + }); + it('solid-set-ul', () => { - cy.get('solid-set-ul') - .children().should('have.length', 1); - cy.get('solid-set-ul') - .find('ul') - .should('have.attr', 'data-content', ''); - }) -}) + cy.get('solid-set-ul').children().should('have.length', 1); + cy.get('solid-set-ul').find('ul').should('have.attr', 'data-content', ''); + }); +}); diff --git a/cypress/e2e/sleep.ts b/cypress/e2e/sleep.ts index c3f3d43fba5dde86a93654b00b405621b05fb3e9..4c58c343861092547a22f5cef3ef5331d80add0c 100644 --- a/cypress/e2e/sleep.ts +++ b/cypress/e2e/sleep.ts @@ -1,3 +1,3 @@ export default function sleep(time = 0) { - return new Promise(resolve => setTimeout(resolve, time)) + return new Promise(resolve => setTimeout(resolve, time)); } diff --git a/cypress/e2e/unit/ComponentFactory.cy.ts b/cypress/e2e/unit/ComponentFactory.cy.ts index 9d44e782753e99c083bfcfc4ffd77d11e5308e3e..0cac4c787faf94caa5004aa24a05fbf2006de0b2 100644 --- a/cypress/e2e/unit/ComponentFactory.cy.ts +++ b/cypress/e2e/unit/ComponentFactory.cy.ts @@ -1,4 +1,4 @@ -import { ComponentFactory } from '../../../src/libs/ComponentFactory'; +import { ComponentFactory } from '../../../src/libs/ComponentFactory.ts'; const MixinTestTwo = { name: 'mixin2', @@ -67,7 +67,7 @@ const Component = { myAttribute: { type: String, default: 'awesome', - callback: function() { + callback: function () { this.change = true; }, }, @@ -93,7 +93,7 @@ const Component = { message: '', }, get accessorTest() { - return 'hello ' + this.accessorValue; + return `hello ${this.accessorValue}`; }, created() { this.message += '!!'; @@ -112,7 +112,7 @@ const Component = { }, }; -describe('Component factory', function() { +describe('Component factory', () => { it('expose html element', () => { const ComponentConstructor = ComponentFactory.build(Component); const component = new ComponentConstructor(document.createElement('p')); diff --git a/cypress/e2e/unit/Compositor.cy.ts b/cypress/e2e/unit/Compositor.cy.ts index 552335eb99c9fabdb5c7db34fb8c1141eaee5d67..10d3933e5b107e6a0e079003cf795ba10a175473 100644 --- a/cypress/e2e/unit/Compositor.cy.ts +++ b/cypress/e2e/unit/Compositor.cy.ts @@ -1,4 +1,4 @@ -import { Compositor } from '../../../src/libs/Compositor'; +import { Compositor } from '../../../src/libs/Compositor.ts'; const MixinTestTwo = { name: 'mixin2', @@ -73,7 +73,7 @@ const component = { }, }, get accessorTest() { - return 'hello ' + this.accessorValue; + return `hello ${this.accessorValue}`; }, created() { console.log('created3'); @@ -92,7 +92,7 @@ const component = { }, }; -describe('Mixin Compositor', function() { +describe('Mixin Compositor', () => { it('merge mixin', () => { const result = Compositor.mergeMixin(component); expect(result.length).eq(2); @@ -133,11 +133,11 @@ describe('Mixin Compositor', function() { const hookNames = Reflect.ownKeys(result); expect(hookNames.length).eq(3); - hookNames.forEach(hookName => { - result[hookName].forEach(hook => { + for (const hookName of hookNames) { + for (const hook of result[hookName]) { expect(typeof hook).eq('function'); - }); - }); + } + } expect(result.created.length).eq(3); expect(result.attached.length).eq(2); @@ -157,22 +157,22 @@ describe('Mixin Compositor', function() { const accessors = Object.keys(result); expect(accessors.length).eq(1); - accessors.forEach(accessorName => { + for (const accessorName of accessors) { expect(typeof result[accessorName].get).eq('function'); expect(typeof result[accessorName].set).eq('function'); - }); + } - expect(result['accessorTest'].get.toString()).eq( + expect(result.accessorTest.get.toString()).eq( Reflect.getOwnPropertyDescriptor( component, 'accessorTest', - )!.get!.toString(), + )?.get?.toString(), ); - expect(result['accessorTest'].set.toString()).eq( + expect(result.accessorTest.set.toString()).eq( Reflect.getOwnPropertyDescriptor( MixinTestOne, 'accessorTest', - )!.set!.toString(), + )?.set?.toString(), ); }); @@ -185,9 +185,9 @@ describe('Mixin Compositor', function() { const methodNames = Array.from(result.keys()); expect(methodNames.length).eq(4); - methodNames.forEach(methodName => { + for (const methodName of methodNames) { expect(typeof result.get(methodName)).eq('function'); - }); + } expect(result.get('methodA').toString()).eq( MixinTestOne.methodA.toString(), diff --git a/cypress/e2e/unit/helpers.cy.ts b/cypress/e2e/unit/helpers.cy.ts index 3dd5784c5b6d950e0916a0066921d21ab3c5a516..16a1d65bd151560f5f5a8239a34f8876239ad588 100644 --- a/cypress/e2e/unit/helpers.cy.ts +++ b/cypress/e2e/unit/helpers.cy.ts @@ -1,28 +1,28 @@ import { - uniqID, - stringToDom, - setDeepProperty, - parseFieldsString, - findClosingBracketMatchIndex, - evalTemplateString, AsyncIterableBuilder, -} from '../../../src/libs/helpers'; + evalTemplateString, + findClosingBracketMatchIndex, + parseFieldsString, + setDeepProperty, + stringToDom, + uniqID, +} from '../../../src/libs/helpers.ts'; /** * uniqID */ -describe('uniqID', function() { +describe('uniqID', () => { it('returns an id', () => { - let test = uniqID(); + const test = uniqID(); expect(test).to.match(/[_].{10}/g); }); it('returns a different id 50 times in a row', () => { - let ids: string[] = []; + const ids: string[] = []; const arraySize = 50; for (let index = 0; index < arraySize; index++) { ids.push(uniqID()); } - let noDuplicates = [...new Set(ids)]; + const noDuplicates = [...new Set(ids)]; expect(noDuplicates.length).to.eq(arraySize); }); }); @@ -30,7 +30,7 @@ describe('uniqID', function() { /** * stringToDom */ -describe('stringToDom', function() { +describe('stringToDom', () => { it('returns a fragment', () => { const fragment = stringToDom('<h1>Test element</h1>'); expect(fragment.constructor.name).to.eq('DocumentFragment'); @@ -54,7 +54,7 @@ describe('stringToDom', function() { /** * setDeepProperty */ -describe('setDeepProperty', function() { +describe('setDeepProperty', () => { it('set properties', () => { const object = { name: 'test', @@ -91,7 +91,7 @@ describe('setDeepProperty', function() { /** * parseFieldsString */ -describe('parseFieldsString', function() { +describe('parseFieldsString', () => { it('returns first level of fields', () => { const fields = 'field1, field2(field3,field4, field5( field6, field7) ), field8,field9'; @@ -108,7 +108,7 @@ describe('parseFieldsString', function() { /** * findClosingBracketMatchIndex */ -describe('findClosingBracketMatchIndex', function() { +describe('findClosingBracketMatchIndex', () => { it('throw error', () => { const fields = 'field1, field2(field3,field4, field5( field6, field7) ), field8,field9'; @@ -140,7 +140,7 @@ describe('findClosingBracketMatchIndex', function() { /** * evalTemplateString */ -describe('evalTemplateString', function() { +describe('evalTemplateString', () => { it('render template with values', async () => { const values = { val1: 'test 1', @@ -177,9 +177,7 @@ describe('evalTemplateString', function() { </div> `; const promise = new Cypress.Promise((resolve, reject) => { - evalTemplateString(template, values) - .then(resolve) - .catch(reject); + evalTemplateString(template, values).then(resolve).catch(reject); }); promise.finally(() => { expect(promise.isRejected).to.be.true; @@ -265,7 +263,7 @@ describe('evalTemplateString', function() { // } // ] // }; - + // const newValue = transformArrayToContainer(value); // expect(newValue).to.deep.equal({ // "@id": "myresource", @@ -296,27 +294,27 @@ describe('evalTemplateString', function() { // }) // }) // }) -import sleep from '../sleep' -describe('AsyncIterableBuilder', () => { +import sleep from '../sleep.ts'; +describe('AsyncIterableBuilder', () => { it('create an asyncIterable', async () => { - const { iterable, next } = new AsyncIterableBuilder<number>() - next(1) - next(2) - const values: number[] = [] - let done = false - ;(async () => { + const { iterable, next } = new AsyncIterableBuilder<number>(); + next(1); + next(2); + const values: number[] = []; + let done = false; + (async () => { for await (const number of iterable) { - values.push(number) + values.push(number); } - done = true - })() - await sleep() - expect(values).to.deep.eq([1, 2]) - expect(done).to.be.false - next(3) - next(4, true) - await sleep() - expect(values).to.deep.eq([1, 2, 3, 4]) - expect(done).to.be.true - }) -}) \ No newline at end of file + done = true; + })(); + await sleep(); + expect(values).to.deep.eq([1, 2]); + expect(done).to.be.false; + next(3); + next(4, true); + await sleep(); + expect(values).to.deep.eq([1, 2, 3, 4]); + expect(done).to.be.true; + }); +}); diff --git a/cypress/e2e/unit/store.cy.ts b/cypress/e2e/unit/store.cy.ts index 6957f79c1cd3141d09b5c5177b51e35a43491447..e379d2ca001eb45c9bd9ef02b99b814b8caad997 100644 --- a/cypress/e2e/unit/store.cy.ts +++ b/cypress/e2e/unit/store.cy.ts @@ -10,23 +10,25 @@ export const base_context = { acl: 'http://www.w3.org/ns/auth/acl#', permissions: 'acl:accessControl', mode: 'acl:mode', - geo: "http://www.w3.org/2003/01/geo/wgs84_pos#", - lat: "geo:lat", - lng: "geo:long" + geo: 'http://www.w3.org/2003/01/geo/wgs84_pos#', + lat: 'geo:lat', + lng: 'geo:long', }; // FIXME: Fix this tests suite describe('store', { testIsolation: false }, function () { this.beforeAll('visit', () => { - cy.visit('/examples/e2e/store.html') - }) + cy.visit('/examples/e2e/store.html'); + }); it('has prototype', () => { cy.window().then((win: any) => { // properties expect(win.sibStore.cache).to.exist; expect(win.sibStore.subscriptionIndex).to.exist; - expect(win.sibStore.loadingList).to.be.a('Set').and.have.property('size', 0); + expect(win.sibStore.loadingList) + .to.be.a('Set') + .and.have.property('size', 0); expect(win.sibStore.headers).to.exist; // public methods expect(win.sibStore.fetchAuthn).to.be.a('function'); @@ -41,227 +43,205 @@ describe('store', { testIsolation: false }, function () { expect(win.sibStore.selectLanguage).to.be.a('function'); // PubSub expect(win.PubSub).to.exist; - }) + }); }); it('save local data', () => { cy.window().then(async (win: any) => { const store = win.sibStore; - const customID = "myCustomID"; - const url = `store://local.${customID}` + const customID = 'myCustomID'; + const url = `store://local.${customID}`; // Now the context needs to be explicitly defined const dataToSave1 = { foo: 'bar', - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', }; await store.setLocalData(dataToSave1, url); - let dataRead1 = await store.getData(url); - expect(await dataRead1!['foo']).eq('bar'); + const dataRead1 = await store.getData(url); + expect(await dataRead1?.foo).eq('bar'); store.clearCache(url); }); }); it('replaces local data', () => { - cy.intercept("GET", "*/data/list/users.jsonld").as('users') + cy.intercept('GET', '*/data/list/users.jsonld').as('users'); cy.window().then(async (win: any) => { const store = win.sibStore; await store.getData('/examples/data/list/user-1.jsonld', base_context); const dataToSave1 = { - "@id": "/examples/data/list/user-1.jsonld", - "@type": "foaf:user", - "username": "local user", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" - } - await store.setLocalData(dataToSave1, '/examples/data/list/user-1.jsonld'); + '@id': '/examples/data/list/user-1.jsonld', + '@type': 'foaf:user', + username: 'local user', + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', + }; + await store.setLocalData( + dataToSave1, + '/examples/data/list/user-1.jsonld', + ); const dataRead = store.get('/examples/data/list/user-1.jsonld'); - expect(await dataRead['username']).eq('local user'); - expect(await dataRead['email']).not.exist; + expect(await dataRead.username).eq('local user'); + expect(await dataRead.email).not.exist; store.clearCache('/examples/data/list/user-1.jsonld'); }); }); it('fetches data and cache it', () => { - cy.intercept("GET", "/examples/data/list/users.jsonld", { + cy.intercept('GET', '/examples/data/list/users.jsonld', { statusCode: 200, body: { - "@id": "/examples/data/list/users.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ + '@id': '/examples/data/list/users.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [ { - "@id": "/examples/data/list/user-1.jsonld", - "first_name": "Test", - "last_name": "User", - "name": "Test User", - "username": "admin", - "email": "test-user@example.com", - "available": true, - "years_experience": 3, - "skills": { - "@id": "/examples/data/list/user-1-skills.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ + '@id': '/examples/data/list/user-1.jsonld', + first_name: 'Test', + last_name: 'User', + name: 'Test User', + username: 'admin', + email: 'test-user@example.com', + available: true, + years_experience: 3, + skills: { + '@id': '/examples/data/list/user-1-skills.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [ { - "@id": "/examples/data/list/skill-2.jsonld" + '@id': '/examples/data/list/skill-2.jsonld', }, { - "@id": "/examples/data/list/skill-3.jsonld" - } + '@id': '/examples/data/list/skill-3.jsonld', + }, ], - "permissions": [ - "view" - ] + permissions: ['view'], }, - "profile": { - "@id": "/examples/data/list/profile-1.jsonld" + profile: { + '@id': '/examples/data/list/profile-1.jsonld', }, - "@type": "foaf:user", - "permissions": [ - "view" - ] + '@type': 'foaf:user', + permissions: ['view'], }, { - "@id": "/examples/data/list/user-2.jsonld", - "first_name": "Paris", - "last_name": "Hilton", - "name": "Paris Hilton", - "username": "paris", - "email": "paris@hilton.hi", - "available": true, - "years_experience": 5, - "skills": { - "@id": "/examples/data/list/user-2-skills.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ + '@id': '/examples/data/list/user-2.jsonld', + first_name: 'Paris', + last_name: 'Hilton', + name: 'Paris Hilton', + username: 'paris', + email: 'paris@hilton.hi', + available: true, + years_experience: 5, + skills: { + '@id': '/examples/data/list/user-2-skills.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [ { - "@id": "/examples/data/list/skill-1.jsonld" - } + '@id': '/examples/data/list/skill-1.jsonld', + }, ], - "permissions": [ - "view" - ] + permissions: ['view'], }, - "profile": { - "@id": "/examples/data/list/profile-2.jsonld" + profile: { + '@id': '/examples/data/list/profile-2.jsonld', }, - "@type": "foaf:user", - "permissions": [ - "view" - ] + '@type': 'foaf:user', + permissions: ['view'], }, { - "@id": "/examples/data/list/user-4.jsonld", - "first_name": "Pierre", - "last_name": "DLC", - "name": "Pierre DLC", - "username": "pierre", - "email": "pierredelacroix@happy-dev.fr", - "available": false, - "years_experience": 5, - "skills": { - "@id": "/examples/data/list/user-4-skills.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ + '@id': '/examples/data/list/user-4.jsonld', + first_name: 'Pierre', + last_name: 'DLC', + name: 'Pierre DLC', + username: 'pierre', + email: 'pierredelacroix@happy-dev.fr', + available: false, + years_experience: 5, + skills: { + '@id': '/examples/data/list/user-4-skills.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [ { - "@id": "/examples/data/list/skill-1.jsonld" + '@id': '/examples/data/list/skill-1.jsonld', }, { - "@id": "/examples/data/list/skill-2.jsonld" + '@id': '/examples/data/list/skill-2.jsonld', }, { - "@id": "/examples/data/list/skill-4.jsonld" - } + '@id': '/examples/data/list/skill-4.jsonld', + }, ], - "permissions": [ - "view" - ] + permissions: ['view'], }, - "profile": { - "@id": "/examples/data/list/profile-4.jsonld" + profile: { + '@id': '/examples/data/list/profile-4.jsonld', }, - "@type": "foaf:user", - "permissions": [ - "view" - ] + '@type': 'foaf:user', + permissions: ['view'], }, { - "@id": "/examples/data/list/user-3.jsonld", - "first_name": "Not A", - "last_name": "Paris Member", - "name": "Not A Paris Member", - "username": "not-member-paris", - "email": "not-a@paris.members", - "available": false, - "years_experience": 7, - "skills": { - "@id": "/examples/data/list/user-3-skills.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ - - ], - "permissions": [ - "view" - ] + '@id': '/examples/data/list/user-3.jsonld', + first_name: 'Not A', + last_name: 'Paris Member', + name: 'Not A Paris Member', + username: 'not-member-paris', + email: 'not-a@paris.members', + available: false, + years_experience: 7, + skills: { + '@id': '/examples/data/list/user-3-skills.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [], + permissions: ['view'], }, - "profile": { - "@id": "/examples/data/list/profile-3.jsonld" + profile: { + '@id': '/examples/data/list/profile-3.jsonld', }, - "@type": "foaf:user", - "permissions": [ - "view" - ] - } - ], - "permissions": [ - "view" + '@type': 'foaf:user', + permissions: ['view'], + }, ], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + permissions: ['view'], + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', }, headers: { - 'content-type': 'application/ld+json' - } - }).as('users') + 'content-type': 'application/ld+json', + }, + }).as('users'); - cy.intercept("GET", "/examples/data/extra-context/user-6.jsonld", { + cy.intercept('GET', '/examples/data/extra-context/user-6.jsonld', { statusCode: 200, body: { - "@id": "/examples/data/extra-context/user-6.jsonld", - "first_name": "Test", - "last_name": "User", - "username": "admin", - "email": "test-user@example.com", - "name": "Test User", - "profile": { - "@id": "/examples/data/extra-context/profile-6.jsonld", - "@context": { - "picture": "foaf:depiction" + '@id': '/examples/data/extra-context/user-6.jsonld', + first_name: 'Test', + last_name: 'User', + username: 'admin', + email: 'test-user@example.com', + name: 'Test User', + profile: { + '@id': '/examples/data/extra-context/profile-6.jsonld', + '@context': { + picture: 'foaf:depiction', }, - "picture": "my-avatar.png" + picture: 'my-avatar.png', }, - "@type": "foaf:user", - "permissions": [ - "view" - ], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + '@type': 'foaf:user', + permissions: ['view'], + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', }, headers: { - 'content-type': 'application/ld+json' - } - }).as('user-6') + 'content-type': 'application/ld+json', + }, + }).as('user-6'); cy.window() .its('sibStore') .invoke('getData', '/examples/data/list/users.jsonld', base_context); - cy.get('@users').its("response.statusCode").should('equal', 200); + cy.get('@users').its('response.statusCode').should('equal', 200); - cy.window() - .its('sibStore.cache').should('have.length', 13); // cache - cy.window() - .its('sibStore.loadingList').should('have.property', 'size', 0); // loading list - cy.window() - .its('sibStore.subscriptionIndex').should('have.length', 8); // Subscription index + cy.window().its('sibStore.cache').should('have.length', 13); // cache + cy.window().its('sibStore.loadingList').should('have.property', 'size', 0); // loading list + cy.window().its('sibStore.subscriptionIndex').should('have.length', 8); // Subscription index cy.window() .its('sibStore') @@ -271,57 +251,69 @@ describe('store', { testIsolation: false }, function () { // properties are expanded cy.window() .its('sibStore') - .invoke('getData', '/examples/data/extra-context/user-6.jsonld', base_context); + .invoke( + 'getData', + '/examples/data/extra-context/user-6.jsonld', + base_context, + ); cy.window() .its('sibStore') .invoke('get', '/examples/data/extra-context/user-6.jsonld') .invoke('getResourceData') - .should('have.property', 'https://cdn.startinblox.com/owl#email', "test-user@example.com"); // @vocab + .should( + 'have.property', + 'https://cdn.startinblox.com/owl#email', + 'test-user@example.com', + ); // @vocab cy.window() .its('sibStore') .invoke('get', '/examples/data/extra-context/profile-6.jsonld') .invoke('getResourceData') - .should('have.property', 'http://xmlns.com/foaf/0.1/depiction', "my-avatar.png"); // nested additionnal context + .should( + 'have.property', + 'http://xmlns.com/foaf/0.1/depiction', + 'my-avatar.png', + ); // nested additionnal context }); it('send xhr requests', () => { - cy.intercept("PATCH", "/examples/data/list/user-1.jsonld", { + cy.intercept('PATCH', '/examples/data/list/user-1.jsonld', { headers: { - 'content-type': 'application/ld+json' - } - }).as("patch") - - cy.intercept("PUT", "/examples/data/list/user-1.jsonld", { + 'content-type': 'application/ld+json', + }, + }).as('patch'); + + cy.intercept('PUT', '/examples/data/list/user-1.jsonld', { headers: { - 'content-type': 'application/ld+json' - } - }).as("put") - - cy.intercept("POST", "/examples/data/list/users.jsonld", { + 'content-type': 'application/ld+json', + }, + }).as('put'); + + cy.intercept('POST', '/examples/data/list/users.jsonld', { headers: { - 'content-type': 'application/ld+json' - } - }).as("post") + 'content-type': 'application/ld+json', + }, + }).as('post'); - cy.intercept("DELETE", "/examples/data/list/user-1.jsonld", { + cy.intercept('DELETE', '/examples/data/list/user-1.jsonld', { headers: { - 'content-type': 'application/ld+json' - } - }).as("delete") + 'content-type': 'application/ld+json', + }, + }).as('delete'); - cy.intercept("GET", `${baseUrl}/examples/data/list/user-1.jsonld`, { + cy.intercept('GET', `${baseUrl}/examples/data/list/user-1.jsonld`, { statusCode: 200, body: { - "@id": "/examples/data/list/user-1.jsonld", - "@type": "foaf:user", - "first_name": "Matthieu", - "last_name": "Garcia", - "email": "matthieu@example.com" + '@id': '/examples/data/list/user-1.jsonld', + '@type': 'foaf:user', + first_name: 'Matthieu', + last_name: 'Garcia', + email: 'matthieu@example.com', }, headers: { - 'content-type': 'application/ld+json' - } - }).as("get") + 'content-type': 'application/ld+json', + }, + }).as('get'); cy.window().then((win: any) => { cy.spy(win.sibStore, 'clearCache'); @@ -331,27 +323,49 @@ describe('store', { testIsolation: false }, function () { cy.window() .its('sibStore') .invoke('fetchData', '/examples/data/list/user-1.jsonld'); - cy.get('@get').its("request.url").should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); - + cy.get('@get') + .its('request.url') + .should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); + cy.window() .its('sibStore') - .invoke('patch', { first_name: 'Monsieur' }, '/examples/data/list/user-1.jsonld'); - cy.get('@patch').its("request.url").should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); + .invoke( + 'patch', + { first_name: 'Monsieur' }, + '/examples/data/list/user-1.jsonld', + ); + cy.get('@patch') + .its('request.url') + .should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); cy.window() .its('sibStore') - .invoke('put', { first_name: 'Monsieur' }, '/examples/data/list/user-1.jsonld'); - cy.get('@put').its("request.url").should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); + .invoke( + 'put', + { first_name: 'Monsieur' }, + '/examples/data/list/user-1.jsonld', + ); + cy.get('@put') + .its('request.url') + .should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); cy.window() .its('sibStore') - .invoke('post', { first_name: 'Monsieur' }, '/examples/data/list/users.jsonld'); - cy.get('@post').its("request.url").should('equal', `${baseUrl}/examples/data/list/users.jsonld`); + .invoke( + 'post', + { first_name: 'Monsieur' }, + '/examples/data/list/users.jsonld', + ); + cy.get('@post') + .its('request.url') + .should('equal', `${baseUrl}/examples/data/list/users.jsonld`); cy.window() .its('sibStore') .invoke('delete', '/examples/data/list/user-1.jsonld'); - cy.get('@delete').its("request.url").should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); + cy.get('@delete') + .its('request.url') + .should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); cy.window().then((win: any) => { expect(win.sibStore.clearCache).to.be.called; @@ -362,7 +376,9 @@ describe('store', { testIsolation: false }, function () { it('expands id', () => { cy.window() .its('sibStore') - .invoke('_getExpandedId', 'user:1/', { 'user': "https://ldp-server.test/users/" }) + .invoke('_getExpandedId', 'user:1/', { + user: 'https://ldp-server.test/users/', + }) .should('equal', 'https://ldp-server.test/users/1/'); cy.window() @@ -377,8 +393,7 @@ describe('store', { testIsolation: false }, function () { }); it('clears cache', () => { - cy.window() - .its('sibStore.cache').should('have.length', 15); + cy.window().its('sibStore.cache').should('have.length', 15); cy.window() .its('sibStore') @@ -389,26 +404,26 @@ describe('store', { testIsolation: false }, function () { .its('sibStore') .invoke('clearCache', '/examples/data/list/user-1.jsonld'); - cy.window() - .its('sibStore.cache').should('have.length', 14); + cy.window().its('sibStore.cache').should('have.length', 14); cy.window() .its('sibStore') .invoke('get', '/examples/data/list/user-1.jsonld') .should('not.exist'); - cy.window() - .its('sibStore') - .invoke('clearCache', 'wrong-id.jsonld'); + cy.window().its('sibStore').invoke('clearCache', 'wrong-id.jsonld'); - cy.window() - .its('sibStore.cache').should('have.length', 14); + cy.window().its('sibStore.cache').should('have.length', 14); }); it('subscribes resource', () => { cy.window() .its('sibStore') - .invoke('subscribeResourceTo', 'ldp-server.test/circles/', 'ldp-server.test/circles/1/'); + .invoke( + 'subscribeResourceTo', + 'ldp-server.test/circles/', + 'ldp-server.test/circles/1/', + ); cy.window().then((win: any) => { expect(win.sibStore.subscriptionIndex).to.have.length(9); @@ -419,65 +434,117 @@ describe('store', { testIsolation: false }, function () { cy.window() .its('sibStore') - .invoke('subscribeResourceTo', 'ldp-server.test/users/matthieu/', 'ldp-server.test/circles/1/'); + .invoke( + 'subscribeResourceTo', + 'ldp-server.test/users/matthieu/', + 'ldp-server.test/circles/1/', + ); cy.window().then((win: any) => { expect(win.sibStore.subscriptionIndex).to.have.length(9); expect(win.sibStore.subscriptionIndex.get('ldp-server.test/circles/1/')) .to.have.length(2) - .and.to.have.members(['ldp-server.test/circles/', 'ldp-server.test/users/matthieu/']); + .and.to.have.members([ + 'ldp-server.test/circles/', + 'ldp-server.test/users/matthieu/', + ]); }); }); it('subscribes virtual container', () => { cy.window() .its('sibStore') - .invoke('subscribeVirtualContainerTo', 'ldp-server.test/circles/joinable', 'ldp-server.test/circles/1/members'); + .invoke( + 'subscribeVirtualContainerTo', + 'ldp-server.test/circles/joinable', + 'ldp-server.test/circles/1/members', + ); cy.window().then((win: any) => { expect(win.sibStore.subscriptionVirtualContainersIndex).to.have.length(1); - expect(win.sibStore.subscriptionVirtualContainersIndex.get('ldp-server.test/circles/1/members')) + expect( + win.sibStore.subscriptionVirtualContainersIndex.get( + 'ldp-server.test/circles/1/members', + ), + ) .to.have.length(1) .and.to.have.members(['ldp-server.test/circles/joinable']); }); cy.window() .its('sibStore') - .invoke('subscribeVirtualContainerTo', 'ldp-server.test/users/matthieu/circles', 'ldp-server.test/circles/1/members'); + .invoke( + 'subscribeVirtualContainerTo', + 'ldp-server.test/users/matthieu/circles', + 'ldp-server.test/circles/1/members', + ); cy.window().then((win: any) => { expect(win.sibStore.subscriptionVirtualContainersIndex).to.have.length(1); - expect(win.sibStore.subscriptionVirtualContainersIndex.get('ldp-server.test/circles/1/members')) + expect( + win.sibStore.subscriptionVirtualContainersIndex.get( + 'ldp-server.test/circles/1/members', + ), + ) .to.have.length(2) - .and.to.have.members(['ldp-server.test/users/matthieu/circles', 'ldp-server.test/circles/joinable']); + .and.to.have.members([ + 'ldp-server.test/users/matthieu/circles', + 'ldp-server.test/circles/joinable', + ]); }); cy.window() - .its('sibStore') - .invoke('subscribeVirtualContainerTo', 'ldp-server.test/circles/joinable', 'ldp-server.test/circles/1/members'); + .its('sibStore') + .invoke( + 'subscribeVirtualContainerTo', + 'ldp-server.test/circles/joinable', + 'ldp-server.test/circles/1/members', + ); cy.window().then((win: any) => { expect(win.sibStore.subscriptionVirtualContainersIndex).to.have.length(1); - expect(win.sibStore.subscriptionVirtualContainersIndex.get('ldp-server.test/circles/1/members')) + expect( + win.sibStore.subscriptionVirtualContainersIndex.get( + 'ldp-server.test/circles/1/members', + ), + ) .to.have.length(2) - .and.to.have.members(['ldp-server.test/users/matthieu/circles', 'ldp-server.test/circles/joinable']); + .and.to.have.members([ + 'ldp-server.test/users/matthieu/circles', + 'ldp-server.test/circles/joinable', + ]); }); }); it('gets absolute iri', () => { cy.window() .its('sibStore') - .invoke('_getAbsoluteIri', '/examples/data/list/users.jsonld', base_context, '') + .invoke( + '_getAbsoluteIri', + '/examples/data/list/users.jsonld', + base_context, + '', + ) .should('equal', `${baseUrl}/examples/data/list/users.jsonld`); cy.window() .its('sibStore') - .invoke('_getAbsoluteIri', 'user-1.jsonld', base_context, '/examples/data/list/users.jsonld') + .invoke( + '_getAbsoluteIri', + 'user-1.jsonld', + base_context, + '/examples/data/list/users.jsonld', + ) .should('equal', `${baseUrl}/examples/data/list/user-1.jsonld`); cy.window() .its('sibStore') - .invoke('_getAbsoluteIri', 'https://ldp-server.test/circles/', base_context, '') + .invoke( + '_getAbsoluteIri', + 'https://ldp-server.test/circles/', + base_context, + '', + ) .should('equal', 'https://ldp-server.test/circles/'); }); @@ -488,28 +555,34 @@ describe('store', { testIsolation: false }, function () { await store.getData('/examples/data/list/user-1.jsonld', base_context); const resource = { - "@id": "/examples/data/list/user-1.jsonld", - name: "Test User", + '@id': '/examples/data/list/user-1.jsonld', + name: 'Test User', available: true, skills: { - "@id": "/examples/data/list/user-1-skills.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ + '@id': '/examples/data/list/user-1-skills.jsonld', + '@type': 'ldp:Container', + 'ldp:contains': [ { - "@id": "/examples/data/list/skill-2.jsonld" + '@id': '/examples/data/list/skill-2.jsonld', }, { - "@id": "/examples/data/list/skill-3.jsonld" - } + '@id': '/examples/data/list/skill-3.jsonld', + }, ], }, profile: { - "@id": "/examples/data/list/profile-1.jsonld" + '@id': '/examples/data/list/profile-1.jsonld', }, - "@type": "foaf:user" + '@type': 'foaf:user', }; - const nestedResources = await store.getNestedResources(resource, '/examples/data/list/user-1.jsonld'); - expect(nestedResources).to.deep.equal(["/examples/data/list/user-1-skills.jsonld", "/examples/data/list/profile-1.jsonld"]); + const nestedResources = await store.getNestedResources( + resource, + '/examples/data/list/user-1.jsonld', + ); + expect(nestedResources).to.deep.equal([ + '/examples/data/list/user-1-skills.jsonld', + '/examples/data/list/profile-1.jsonld', + ]); expect(store.fetchData).to.be.calledOnce; }); }); @@ -522,7 +595,10 @@ describe('store', { testIsolation: false }, function () { cy.spy(store, 'fetchData'); expect(store.cache).to.have.length(15); - await store.refreshResources(['/examples/data/list/user-1.jsonld', '/examples/data/list/users.jsonld']); + await store.refreshResources([ + '/examples/data/list/user-1.jsonld', + '/examples/data/list/users.jsonld', + ]); expect(store.clearCache).to.be.calledTwice; expect(store.getData).to.be.calledTwice; @@ -536,7 +612,10 @@ describe('store', { testIsolation: false }, function () { cy.window().then(async (win: any) => { const store = win.sibStore; cy.spy(win.PubSub, 'publish'); - await store.notifyResources(['/examples/data/list/user-1.jsonld', '/examples/data/list/users.jsonld']); + await store.notifyResources([ + '/examples/data/list/user-1.jsonld', + '/examples/data/list/users.jsonld', + ]); expect(win.PubSub.publish).to.be.calledTwice; }); }); @@ -544,24 +623,30 @@ describe('store', { testIsolation: false }, function () { it('refreshResource and localData', () => { cy.window().then(async (win: any) => { const store = win.sibStore; - await store.setLocalData({ - "@context": "https://cdn.startinblox.com/owl/context.jsonld", - "@id": "store://local.2", - "name": "ok", - }, "store://local.2"); - - await store.setLocalData({ - "@context": "https://cdn.startinblox.com/owl/context.jsonld", - "@id": "store://local.1", - "ref": { "@id": "store://local.2" }, - }, "store://local.1"); + await store.setLocalData( + { + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', + '@id': 'store://local.2', + name: 'ok', + }, + 'store://local.2', + ); + + await store.setLocalData( + { + '@context': 'https://cdn.startinblox.com/owl/context.jsonld', + '@id': 'store://local.1', + ref: { '@id': 'store://local.2' }, + }, + 'store://local.1', + ); cy.wait(100).then(async () => { - const resource = store.get('store://local.2') + const resource = store.get('store://local.2'); expect(resource).to.exist; - const name = await resource['name'] + const name = await resource.name; expect(name).to.equal('ok'); - } ); + }); }); }); -}); \ No newline at end of file +}); diff --git a/cypress/fixtures/circles-16.jsonld b/cypress/fixtures/circles-16.jsonld index 2153cd98bc9482a27e3c2466d8ee539fb354bf4f..8def997cf65fbd697dc2028a8abfcd0c6f1b44a7 100644 --- a/cypress/fixtures/circles-16.jsonld +++ b/cypress/fixtures/circles-16.jsonld @@ -10,10 +10,6 @@ "@id": "https://ldp-server.test/users/matthieu/" }, "@type": "hd:circle", - "permissions": [ - "view", - "change", - "delete" - ], + "permissions": ["view", "change", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/circles-17-members.jsonld b/cypress/fixtures/circles-17-members.jsonld index 22c625e2d9f326015b9c0ae6475f7231bbdb0335..7a26fc37ad18ad82b7da9329f89834a783a54ce2 100644 --- a/cypress/fixtures/circles-17-members.jsonld +++ b/cypress/fixtures/circles-17-members.jsonld @@ -1,11 +1,7 @@ { "@id": "https://ldp-server.test/circles/17/members/", "@type": "ldp:Container", - "ldp:contains": [ - ], - "permissions": [ - "add", - "view" - ], + "ldp:contains": [], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/oembed.jsonld b/cypress/fixtures/oembed.jsonld index 95a03703d222e11ed6f70e5e90fb9507908bcfe4..2abbe728a5538ae510dcfa82a0806bc4ee60ebba 100644 --- a/cypress/fixtures/oembed.jsonld +++ b/cypress/fixtures/oembed.jsonld @@ -13,4 +13,3 @@ "thumbnail_url": "https://i.ytimg.com/vi/M3r2XDceM6A/hqdefault.jpg", "html": "<iframe width=\"200\" height=\"113\" src=\"https://www.youtube.com/embed/M3r2XDceM6A?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>" } - \ No newline at end of file diff --git a/cypress/fixtures/profiles-alex.jsonld b/cypress/fixtures/profiles-alex.jsonld index 927901f93491c034c1f14c33db50688d61f5e129..0f8a2ca727dccb632f35d0dd123285b1db30db88 100644 --- a/cypress/fixtures/profiles-alex.jsonld +++ b/cypress/fixtures/profiles-alex.jsonld @@ -9,8 +9,6 @@ "user": { "@id": "https://ldp-server.test/users/alex/" }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/profiles-jbpasquier.jsonld b/cypress/fixtures/profiles-jbpasquier.jsonld index 943f90f4017107ec49508c45161578e9a858d1ce..c5c49ddc0c8331d631cf66856045eb5443158ccc 100644 --- a/cypress/fixtures/profiles-jbpasquier.jsonld +++ b/cypress/fixtures/profiles-jbpasquier.jsonld @@ -9,8 +9,6 @@ "user": { "@id": "https://ldp-server.test/users/jbpasquier/" }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/profiles-matthieu-edited-2.jsonld b/cypress/fixtures/profiles-matthieu-edited-2.jsonld index 2cf1a1ebc1e36c900b8e5a95c3d989cc621e8e4b..7fed20f57d624f3a56e6df01f0f6900ba0a015dd 100644 --- a/cypress/fixtures/profiles-matthieu-edited-2.jsonld +++ b/cypress/fixtures/profiles-matthieu-edited-2.jsonld @@ -9,8 +9,6 @@ "user": { "@id": "https://ldp-server.test/users/matthieu/" }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/profiles-matthieu-edited.jsonld b/cypress/fixtures/profiles-matthieu-edited.jsonld index 1d3e0d34f5d82e689d393e30e5e2045cb0a2b41c..e51509306fa25aa4248230ead47d6a0e6e89e24d 100644 --- a/cypress/fixtures/profiles-matthieu-edited.jsonld +++ b/cypress/fixtures/profiles-matthieu-edited.jsonld @@ -9,8 +9,6 @@ "user": { "@id": "https://ldp-server.test/users/matthieu/" }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/profiles-matthieu.jsonld b/cypress/fixtures/profiles-matthieu.jsonld index 5a1b6638183fc4cb41436c2ba2e737d75c8b6b30..5c47e1631a649e8eca879ed5518785509799c206 100644 --- a/cypress/fixtures/profiles-matthieu.jsonld +++ b/cypress/fixtures/profiles-matthieu.jsonld @@ -9,8 +9,6 @@ "user": { "@id": "https://ldp-server.test/users/matthieu/" }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-alex.jsonld b/cypress/fixtures/users-alex.jsonld index f9e6284ec8946b1bbd1f2bc49409abe146279ea9..64506e7746220fd647aab7b14d8b63d2792876fa 100644 --- a/cypress/fixtures/users-alex.jsonld +++ b/cypress/fixtures/users-alex.jsonld @@ -15,8 +15,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] } diff --git a/cypress/fixtures/users-edited.jsonld b/cypress/fixtures/users-edited.jsonld index 5f518d91f2526b327f0baf60dbb23d60904f56a7..8a204e56a154f8e4a3fa5b3f9cb9c55230ea3791 100644 --- a/cypress/fixtures/users-edited.jsonld +++ b/cypress/fixtures/users-edited.jsonld @@ -16,10 +16,7 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] }, { "@id": "https://ldp-server.test/users/jbpasquier/", @@ -35,9 +32,7 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "https://ldp-server.test/users/alex/", @@ -53,14 +48,9 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-jbpasquier.jsonld b/cypress/fixtures/users-jbpasquier.jsonld index bc5472ae2e79fca8d7b267aa5761a3c4024f0517..392e5a7d29eba34c045d7b2018fba3afebea9a85 100644 --- a/cypress/fixtures/users-jbpasquier.jsonld +++ b/cypress/fixtures/users-jbpasquier.jsonld @@ -15,8 +15,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] } diff --git a/cypress/fixtures/users-matthieu-circles-edited.jsonld b/cypress/fixtures/users-matthieu-circles-edited.jsonld index 0defa5d0b5520509326f71d484046ebb802039fa..8dfa8711a541a7193be9f6b321f42e125661fac7 100644 --- a/cypress/fixtures/users-matthieu-circles-edited.jsonld +++ b/cypress/fixtures/users-matthieu-circles-edited.jsonld @@ -12,10 +12,7 @@ "name": "circle one" }, "@type": "hd:circlemember", - "permissions": [ - "view", - "delete" - ] + "permissions": ["view", "delete"] }, { "@id": "https://ldp-server.test/circle-members/127/", @@ -27,15 +24,9 @@ "name": "circle two" }, "@type": "hd:circlemember", - "permissions": [ - "view", - "delete" - ] + "permissions": ["view", "delete"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-matthieu-circles.jsonld b/cypress/fixtures/users-matthieu-circles.jsonld index 9a59dfb8be044492d3185ed1bcddee0533f82bf4..21fe2692c22ac44b740a79dcc876455d68b64afa 100644 --- a/cypress/fixtures/users-matthieu-circles.jsonld +++ b/cypress/fixtures/users-matthieu-circles.jsonld @@ -12,15 +12,9 @@ "name": "circle one" }, "@type": "hd:circlemember", - "permissions": [ - "view", - "delete" - ] + "permissions": ["view", "delete"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-matthieu-edited.jsonld b/cypress/fixtures/users-matthieu-edited.jsonld index 1b9e7ceb1d9b39cf91c5522a52c61dfbdbbf5406..5d8134e66a8fbab39551a617337917dfdec6fb9c 100644 --- a/cypress/fixtures/users-matthieu-edited.jsonld +++ b/cypress/fixtures/users-matthieu-edited.jsonld @@ -15,8 +15,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] } diff --git a/cypress/fixtures/users-matthieu.jsonld b/cypress/fixtures/users-matthieu.jsonld index 5154239aa4a3001f40dad128ef24822ad10e730a..ecc6e12b4290a03f63ce41907960ae026144e21a 100644 --- a/cypress/fixtures/users-matthieu.jsonld +++ b/cypress/fixtures/users-matthieu.jsonld @@ -15,8 +15,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] } diff --git a/cypress/fixtures/users-nantes.jsonld b/cypress/fixtures/users-nantes.jsonld index 4380d82982217ac1a9fd1f2a2d7e16e5192855ec..7a6d3a3a216aaaac5043b2430bcb49116ebc1e38 100644 --- a/cypress/fixtures/users-nantes.jsonld +++ b/cypress/fixtures/users-nantes.jsonld @@ -16,14 +16,9 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-paris.jsonld b/cypress/fixtures/users-paris.jsonld index e7be80cebe27e158f8ca7179047b6bff57925b37..7647ca2cae2ee5affc75477d831622765763734c 100644 --- a/cypress/fixtures/users-paris.jsonld +++ b/cypress/fixtures/users-paris.jsonld @@ -16,10 +16,7 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view", - "change" - ] + "permissions": ["view", "change"] }, { "@id": "https://ldp-server.test/users/jbpasquier/", @@ -35,14 +32,9 @@ "@context": { "get_full_name": "rdfs:label" }, - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/cypress/fixtures/users-source.jsonld b/cypress/fixtures/users-source.jsonld index 9058bca692f517b73bb3e782753ff92544d3f4d3..459ef51e9b06b518e3ad0cc035cc279ebcba5f16 100644 --- a/cypress/fixtures/users-source.jsonld +++ b/cypress/fixtures/users-source.jsonld @@ -6,21 +6,15 @@ "federation": "users", "@id": "https://ldp-server.test/users/", "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "federation": "users", "@id": "https://ldp-server2.test/users/", "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/cypress/index.d.ts b/cypress/index.d.ts index 6f0b0745ec4da0e1e2f4209a29885ba0c764b3c1..9e0ae69c8908a67c6c91448ed0001beda2ff8be9 100644 --- a/cypress/index.d.ts +++ b/cypress/index.d.ts @@ -1,14 +1,13 @@ - declare namespace Cypress { interface Chainable { /** * Load file in <input type="file"> * @example cy.get('input[type=file]').uploadFile('./img/image.jpg') - */ - uploadFile(fileName: string): Chainable<Element> + */ + uploadFile(fileName: string): Chainable<Element>; } } interface Window { - sibStore: any -} \ No newline at end of file + sibStore: import('../src/libs/store/store').Store; +} diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 6a17dae138f15b08b917d4f0eec705fab80f253c..15a942ee17b9caa15e90e0aa1506fd47277cd160 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -11,4 +11,4 @@ // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) -module.exports = (on, config) => {}; +module.exports = (_on, _config) => {}; diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 11869a8c4403a5f66ccda26026461b0bc704e977..ab88c9664ca6a61e0cf39306d3b3fc56e050e9bc 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -24,16 +24,20 @@ // -- This will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) -Cypress.Commands.add('uploadFile', { prevSubject: true }, (subject, fileName) => { - cy.fixture(fileName).then((content) => { - const el = subject[0] - const testFile = new File([content], fileName) - const dataTransfer = new DataTransfer() - dataTransfer.items.add(testFile) - el.files = dataTransfer.files - cy.wrap(subject).trigger('change', { force: true }) - }) -}); +Cypress.Commands.add( + 'uploadFile', + { prevSubject: true }, + (subject, fileName) => { + cy.fixture(fileName).then(content => { + const el = subject[0]; + const testFile = new File([content], fileName); + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(testFile); + el.files = dataTransfer.files; + cy.wrap(subject).trigger('change', { force: true }); + }); + }, +); Cypress.Commands.add('iframe', { prevSubject: 'element' }, $iframe => { return new Cypress.Promise(resolve => { @@ -41,4 +45,4 @@ Cypress.Commands.add('iframe', { prevSubject: 'element' }, $iframe => { resolve($iframe.contents().find('body')); }); }); -}); \ No newline at end of file +}); diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js index 537ef46fb10f6ad823f1decaabef1401653458cc..d7d0b817fb9e9374b2d4113e35ca3bb705735985 100644 --- a/cypress/support/e2e.js +++ b/cypress/support/e2e.js @@ -14,7 +14,7 @@ // *********************************************************** // Import commands.js using ES2015 syntax: -import './commands' +import './commands.js'; // Alternatively you can use CommonJS syntax: // require('./commands') @@ -25,5 +25,5 @@ import '@rckeller/cypress-unfetch'; import 'cypress-plugin-tab'; Cypress.on('uncaught:exception', () => { - return false -}) + return false; +}); diff --git a/examples/data/calendar/event-1.jsonld b/examples/data/calendar/event-1.jsonld deleted file mode 100644 index d7d6820f7e28224f2287dc1b21bad536fe79ab06..0000000000000000000000000000000000000000 --- a/examples/data/calendar/event-1.jsonld +++ /dev/null @@ -1,7 +0,0 @@ -{ - "@id": "/examples/data/calendar/event-1.jsonld", - "name": "Test", - "deadline": "2019-09-09T19:55:44Z", - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/calendar/event-2.jsonld b/examples/data/calendar/event-2.jsonld deleted file mode 100644 index e27b349852768e38b14ac5ca8763940b7e0ca80f..0000000000000000000000000000000000000000 --- a/examples/data/calendar/event-2.jsonld +++ /dev/null @@ -1,7 +0,0 @@ -{ - "@id": "/examples/data/calendar/event-2.jsonld", - "name": "Test demain", - "deadline": "2019-09-10T19:55:56Z", - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/calendar/events.jsonld b/examples/data/calendar/events.jsonld deleted file mode 100644 index d539f88e8dd03d0d2fc63dc709d37b3a13b1c853..0000000000000000000000000000000000000000 --- a/examples/data/calendar/events.jsonld +++ /dev/null @@ -1,16 +0,0 @@ -{ - "@type": "ldp:Container", - "ldp:contains": [{ - "@id": "/examples/data/calendar/event-1.jsonld", - "name": "Test", - "deadline": "2019-09-09T19:55:44Z", - "permissions": [] - }, { - "@id": "/examples/data/calendar/event-2.jsonld", - "name": "Test demain", - "deadline": "2019-09-10T19:55:56Z", - "permissions": [] - }], - "@id": "/examples/data/calendar/events.jsonld", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/carrot.jsonld b/examples/data/carrot.jsonld index 86eb0aad420678934ec511bb753d7d8beab4565f..9fd84be63ac1fadb4a097bc6e0462ca7fd6347cb 100644 --- a/examples/data/carrot.jsonld +++ b/examples/data/carrot.jsonld @@ -11,11 +11,5 @@ "dfc-b:hasType": { "@id": "dfc-pt:carrot" }, - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ] -} \ No newline at end of file + "permissions": ["view", "control", "add", "delete", "change"] +} diff --git a/examples/data/dfc-enterprise.jsonld b/examples/data/dfc-enterprise.jsonld index 59c979faf1ec754aecbdf8adf6f416bc6c4f3d51..76b20af8e4708ee6dae08a022a30eba14d706caf 100644 --- a/examples/data/dfc-enterprise.jsonld +++ b/examples/data/dfc-enterprise.jsonld @@ -52,11 +52,5 @@ "dfc-b:offeredThrough": "http://test.host/api/dfc/enterprises/10000/offers/10001" } ], - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ] -} \ No newline at end of file + "permissions": ["view", "control", "add", "delete", "change"] +} diff --git a/examples/data/empty-container.jsonld b/examples/data/empty-container.jsonld index 5251752e0bb74dc488b34df851128ed217f6cc8f..c3f49e87a9a1fe70a51dc319f853a5813f15827f 100644 --- a/examples/data/empty-container.jsonld +++ b/examples/data/empty-container.jsonld @@ -2,12 +2,6 @@ "@id": "/examples/data/empty-container.jsonld", "@type": "ldp:Container", "ldp:contains": [], - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ], + "permissions": ["view", "control", "add", "delete", "change"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/extra-context/user-1.jsonld b/examples/data/extra-context/user-1.jsonld index 1eb8d30d633e019ed0a9a343d1a7a16d96aebadb..f3626b9327232a3294f5768163126fe256c49990 100644 --- a/examples/data/extra-context/user-1.jsonld +++ b/examples/data/extra-context/user-1.jsonld @@ -6,8 +6,6 @@ "email": "test-user@example.com", "name": "Test User", "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/extra-context/user-2.jsonld b/examples/data/extra-context/user-2.jsonld index b71760abef6c6ab2d0138513e3b4d6db5aa8e180..c6cbf400b82690f8d2c34c29dc822ccc1b6d1c78 100644 --- a/examples/data/extra-context/user-2.jsonld +++ b/examples/data/extra-context/user-2.jsonld @@ -6,8 +6,6 @@ "email": "paris@hilton.hi", "name": "Paris Hilton", "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/extra-context/user-6.jsonld b/examples/data/extra-context/user-6.jsonld index e94bd05e1edb23a0c140c7664cbf606cd60a519d..d5c361311efc398bb8bebdc87ac193b28ba02f6e 100644 --- a/examples/data/extra-context/user-6.jsonld +++ b/examples/data/extra-context/user-6.jsonld @@ -13,8 +13,6 @@ "picture": "my-avatar.png" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/extra-context/users.jsonld b/examples/data/extra-context/users.jsonld index e8e0d5da776b10e9423cdbc0bd28a3ef4d49326f..0085b852f1b8fc1fb6ed9697d0d5c367fc7f22b7 100644 --- a/examples/data/extra-context/users.jsonld +++ b/examples/data/extra-context/users.jsonld @@ -10,9 +10,7 @@ "email": "test-user@example.com", "name": "Test User", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "http://localhost:3000/examples/data/extra-context/user-2.jsonld", @@ -22,13 +20,9 @@ "email": "paris@hilton.hi", "name": "Paris Hilton", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/federation/circles-server1.jsonld b/examples/data/federation/circles-server1.jsonld index cdc45002afdc371a5df5dfa366d079054b64cab6..ced7e406094241f9020e5d60cd39bfeb1306ebca 100644 --- a/examples/data/federation/circles-server1.jsonld +++ b/examples/data/federation/circles-server1.jsonld @@ -13,9 +13,7 @@ "jabberID": "3oa55lvwyzs6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-2.jsonld", @@ -28,14 +26,9 @@ "jabberID": "3oa55lvwyqq6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/circles-server2.jsonld b/examples/data/federation/circles-server2.jsonld index 064c55d345a8cacebd55cbe0c2d665031a763e81..63de5a56dbe2a357fc0dc9855f14bcb91e9bf30a 100644 --- a/examples/data/federation/circles-server2.jsonld +++ b/examples/data/federation/circles-server2.jsonld @@ -13,9 +13,7 @@ "jabberID": "3oa5aaaazee6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-4.jsonld", @@ -28,14 +26,9 @@ "jabberID": "3oa55lvwyqq6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/circles-server3.jsonld b/examples/data/federation/circles-server3.jsonld index 106257fc7b5dc9a4008dd6040546524d0604548e..8dfc96e220369a1881629d75596e25a2aa82c3f7 100644 --- a/examples/data/federation/circles-server3.jsonld +++ b/examples/data/federation/circles-server3.jsonld @@ -13,9 +13,7 @@ "jabberID": "3oa5aaaazee6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-1.jsonld", @@ -28,14 +26,9 @@ "jabberID": "3oa55lvwyzs6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/circles-server4.jsonld b/examples/data/federation/circles-server4.jsonld index 2567bcfd9cc86aafc299f4fd2173e48639446133..9b86be1616c417240a88da924f5d8797ea02b555 100644 --- a/examples/data/federation/circles-server4.jsonld +++ b/examples/data/federation/circles-server4.jsonld @@ -13,14 +13,9 @@ "jabberID": "3oa5aaaazee6@conference.test1.startinblox.com", "jabberRoom": true, "@type": "hd:circle", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "add", - "view" - ], + "permissions": ["add", "view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/nested-source.jsonld b/examples/data/federation/nested-source.jsonld index dbc759f9942ce47861fa4ae1e924fe189047d250..12f8db3cbf59747c3858e8c79d83f166fe825e14 100644 --- a/examples/data/federation/nested-source.jsonld +++ b/examples/data/federation/nested-source.jsonld @@ -6,9 +6,7 @@ "federation": "circles", "@id": "/examples/data/federation/circles-server1.jsonld", "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-server2.jsonld", @@ -23,8 +21,6 @@ "@type": "sib:federatedContainer" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/source1.jsonld b/examples/data/federation/source1.jsonld index 12e8c65c44e05393e49d78e22335469692392e17..3574646526f62de8ae560152046da28966403c21 100644 --- a/examples/data/federation/source1.jsonld +++ b/examples/data/federation/source1.jsonld @@ -6,17 +6,13 @@ "federation": "circles", "@id": "/examples/data/federation/circles-server1.jsonld", "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-server2.jsonld", "@type": "sib:federatedContainer" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/federation/source2.jsonld b/examples/data/federation/source2.jsonld index 91a2a8e94952d65efe08270c6e7fb0f3f060cc73..5d2b0818720b8774ecfaa985203bd4e1c8e0b061 100644 --- a/examples/data/federation/source2.jsonld +++ b/examples/data/federation/source2.jsonld @@ -6,17 +6,13 @@ "federation": "circles", "@id": "/examples/data/federation/circles-server3.jsonld", "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/federation/circles-server4.jsonld", "@type": "sib:federatedContainer" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/galaxy.jsonld b/examples/data/galaxy.jsonld index 72e86a46149804d2a34507d6e142e632571b3520..19603f083b1c6839ea34f61a711a7a78fb7f46cc 100644 --- a/examples/data/galaxy.jsonld +++ b/examples/data/galaxy.jsonld @@ -179,11 +179,5 @@ } } ], - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ] -} \ No newline at end of file + "permissions": ["view", "control", "add", "delete", "change"] +} diff --git a/examples/data/groups/group1.jsonld b/examples/data/groups/group1.jsonld index 7537d63429c65d8b0555b25abeecbf46c5da34f2..658ee380b4cb73fa32925e62fc8847a5419e7aeb 100644 --- a/examples/data/groups/group1.jsonld +++ b/examples/data/groups/group1.jsonld @@ -8,8 +8,6 @@ "@id": "/examples/data/list/--user-2.jsonld" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/image.jsonld b/examples/data/image.jsonld index 532b474c0a044f79f75e31a036b8aa5e88eba5bf..e9625b972470a5f27bc7fa25bac4a395d0447180 100644 --- a/examples/data/image.jsonld +++ b/examples/data/image.jsonld @@ -4,11 +4,5 @@ "description": "basket containing apples, oranges, kiwis, bananas, pineapples\u2026", "picture": "../../upload/fruits.jpg", "@context": "https://cdn.startinblox.com/owl/context.jsonld", - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ] -} \ No newline at end of file + "permissions": ["view", "control", "add", "delete", "change"] +} diff --git a/examples/data/list/chewbacca.jsonld b/examples/data/list/chewbacca.jsonld index 2a94287b075d04ab2c76b850f280e9c694c9f378..ffeec6d6415a19fdf8ddb618ad23f5fe26212d32 100644 --- a/examples/data/list/chewbacca.jsonld +++ b/examples/data/list/chewbacca.jsonld @@ -1,5 +1,5 @@ { - "@id": "/examples/data/list/examples/data/list/chewbacca.jsonld", - "name": "Chewbacca", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/examples/data/list/chewbacca.jsonld", + "name": "Chewbacca", + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/colibris.jsonld b/examples/data/list/colibris.jsonld index f47c67f8dda3735a913ce964a04a11957421a8f7..4204ed56e1aa182e0e73e68687defb69e7b8a1d2 100644 --- a/examples/data/list/colibris.jsonld +++ b/examples/data/list/colibris.jsonld @@ -5,139 +5,71 @@ "ldp:contains": [ { "@id": "/examples/data/list/universite.jsonld", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/bots.jsonld", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/miniparcours", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/users", - "@type": [ - "ldp:BasicContainer", - "ldp:Container", - "ldp:Resource" - ] + "@type": ["ldp:BasicContainer", "ldp:Container", "ldp:Resource"] }, { "@id": "/examples/data/list/lafabrique", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/laboutique", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/lemouvement", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/groupeslocaux", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/activities", - "@type": [ - "ldp:BasicContainer", - "ldp:Container", - "ldp:Resource" - ] + "@type": ["ldp:BasicContainer", "ldp:Container", "ldp:Resource"] }, { "@id": "/examples/data/list/lemag", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/status", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/themes", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/files", - "@type": [ - "ldp:BasicContainer", - "ldp:Container", - "ldp:Resource" - ] + "@type": ["ldp:BasicContainer", "ldp:Container", "ldp:Resource"] }, { "@id": "/examples/data/list/@types", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/services", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/skills", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] }, { "@id": "/examples/data/list/presdecheznous", - "@type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "@type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] } ] } diff --git a/examples/data/list/community-group.jsonld b/examples/data/list/community-group.jsonld index eafa7d00fb99e61f7a916b4661e4c945176242c4..300f75a14a20b3f624e688bff49b845820325efd 100644 --- a/examples/data/list/community-group.jsonld +++ b/examples/data/list/community-group.jsonld @@ -33,7 +33,5 @@ "user_set": "foaf:member" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] } diff --git a/examples/data/list/darth-vader.json b/examples/data/list/darth-vader.json index b6b8d6d33291c099626d699402c640de5bc8c71b..912d99ac54fe5f269327a51f3e90dbc381428745 100644 --- a/examples/data/list/darth-vader.json +++ b/examples/data/list/darth-vader.json @@ -1,5 +1,5 @@ { - "@id": "/examples/data/list/examples/data/list/darth-vader.json", - "name": "Darth Vader", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/examples/data/list/darth-vader.json", + "name": "Darth Vader", + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-1.jsonld b/examples/data/list/event-1.jsonld index be932c4d2ecdf13a612e080caf647566dd7733d1..2695942f2daa9bb6497181ef7b6f4918a089f9c5 100644 --- a/examples/data/list/event-1.jsonld +++ b/examples/data/list/event-1.jsonld @@ -1,12 +1,12 @@ { - "@id": "/examples/data/list/event-1.jsonld", - "name": "Coliving", - "date": "2020-07-09", - "seats": 12, - "description": "some description", - "contact": { - "@id": "/examples/data/list/user-1.jsonld" - }, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/event-1.jsonld", + "name": "Coliving", + "date": "2020-07-09", + "seats": 12, + "description": "some description", + "contact": { + "@id": "/examples/data/list/user-1.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-2.jsonld b/examples/data/list/event-2.jsonld index 63a038775cf9306851b8d3d0f2bb5766792f9bd6..5ead38247ac30be1f8e1732d456c4de24aaab4f1 100644 --- a/examples/data/list/event-2.jsonld +++ b/examples/data/list/event-2.jsonld @@ -1,11 +1,11 @@ { - "@id": "/examples/data/list/event-2.jsonld", - "name": "Workshop", - "date": "2020-05-10", - "seats": 2, - "contact": { - "@id": "/examples/data/list/user-2.jsonld" - }, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/event-2.jsonld", + "name": "Workshop", + "date": "2020-05-10", + "seats": 2, + "contact": { + "@id": "/examples/data/list/user-2.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-3.jsonld b/examples/data/list/event-3.jsonld index 7b60d50788b0a245fa94fa85859dd990cc13ce21..f147886cbc7714f6dd89f9da179cc9f672ab4137 100644 --- a/examples/data/list/event-3.jsonld +++ b/examples/data/list/event-3.jsonld @@ -1,11 +1,11 @@ { - "@id": "/examples/data/list/event-3.jsonld", - "name": "Réunion d'information", - "date": "2020-07-10", - "seats": 230, - "contact": { - "@id": "/examples/data/list/user-3.jsonld" - }, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/event-3.jsonld", + "name": "Réunion d'information", + "date": "2020-07-10", + "seats": 230, + "contact": { + "@id": "/examples/data/list/user-3.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-4.jsonld b/examples/data/list/event-4.jsonld index f93aa92769ea323141871faaceeb4eb5b2a81389..0bb9359867f7999872bfb7f9533015e41af36b43 100644 --- a/examples/data/list/event-4.jsonld +++ b/examples/data/list/event-4.jsonld @@ -1,11 +1,11 @@ { - "@id": "/examples/data/list/event-4.jsonld", - "name": "Assemblée générale", - "date": "2020-05-10", - "seats": 55, - "contact": { - "@id": "/examples/data/list/user-4.jsonld" - }, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/event-4.jsonld", + "name": "Assemblée générale", + "date": "2020-05-10", + "seats": 55, + "contact": { + "@id": "/examples/data/list/user-4.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-5.jsonld b/examples/data/list/event-5.jsonld index e81d0a811373ed71a890bd8919beb114068d7a6a..4e9540f5f89b81e402cc9a4f193ba2c64c21d140 100644 --- a/examples/data/list/event-5.jsonld +++ b/examples/data/list/event-5.jsonld @@ -1,67 +1,67 @@ { - "@type": "ldp:Container", - "ldp:contains": [ - { - "@id": "/examples/data/list/event-1.jsonld", - "name": "Coliving", - "date": "2020-07-09", - "year": 2020, - "seats": 12, - "place":"", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-2.jsonld", - "name": "Workshop3", - "date": "2020-05-10", - "year": 2020, - "seats": 2, - "place":"Opéra", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-3.jsonld", - "name": "Workshop1", - "date": "2017-05-10", - "year": 2017, - "seats": 23, - "place":"Opéra3", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-4.jsonld", - "name": "Workshop", - "date": "2015-05-10", - "year": 2015, - "seats": 2, - "place":"Opéra2", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-5.jsonld", - "name": "Réunion d'information", - "date": "2020-07-10", - "year": 2020, - "seats": 36, - "place":"Couvent des jacobins", - "city":"Rennes", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-6.jsonld", - "name": "Assemblée générale", - "date": "2020-05-10", - "year": 2019, - "seats": 5, - "place":"", - "city":"Marseille", - "permissions": [] - } - ], - "@id": "/examples/data/list/event-5.jsonld", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@type": "ldp:Container", + "ldp:contains": [ + { + "@id": "/examples/data/list/event-1.jsonld", + "name": "Coliving", + "date": "2020-07-09", + "year": 2020, + "seats": 12, + "place": "", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-2.jsonld", + "name": "Workshop3", + "date": "2020-05-10", + "year": 2020, + "seats": 2, + "place": "Opéra", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-3.jsonld", + "name": "Workshop1", + "date": "2017-05-10", + "year": 2017, + "seats": 23, + "place": "Opéra3", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-4.jsonld", + "name": "Workshop", + "date": "2015-05-10", + "year": 2015, + "seats": 2, + "place": "Opéra2", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-5.jsonld", + "name": "Réunion d'information", + "date": "2020-07-10", + "year": 2020, + "seats": 36, + "place": "Couvent des jacobins", + "city": "Rennes", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-6.jsonld", + "name": "Assemblée générale", + "date": "2020-05-10", + "year": 2019, + "seats": 5, + "place": "", + "city": "Marseille", + "permissions": [] + } + ], + "@id": "/examples/data/list/event-5.jsonld", + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/event-6.jsonld b/examples/data/list/event-6.jsonld new file mode 100644 index 0000000000000000000000000000000000000000..9a36c477e9fb38b07a3a749ed14a5777be59e5eb --- /dev/null +++ b/examples/data/list/event-6.jsonld @@ -0,0 +1,12 @@ +{ + "@id": "/examples/data/list/event-6.jsonld", + "name": "Coliving", + "date": "2020-07-09", + "seats": 12, + "description": "Première ligne\r\n\r\n\r\n\r\nSeconde Ligne avec quatre sauts de ligne", + "contact": { + "@id": "/examples/data/list/user-1.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/list/event-empty.jsonld b/examples/data/list/event-empty.jsonld index d35de1493fdb1fd6c1039e84935bb3d254730674..c952e62f6d5adb7a34f2dbe28eeb328c41dfeec1 100644 --- a/examples/data/list/event-empty.jsonld +++ b/examples/data/list/event-empty.jsonld @@ -1,12 +1,12 @@ { - "@id": "/examples/data/list/event-empty.jsonld", - "name": "", - "date": "", - "seats": 0, - "description": "", - "contact": { - "@id": "/examples/data/list/user-1.jsonld" - }, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@id": "/examples/data/list/event-empty.jsonld", + "name": "", + "date": "", + "seats": 0, + "description": "", + "contact": { + "@id": "/examples/data/list/user-1.jsonld" + }, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/events.jsonld b/examples/data/list/events.jsonld index 85d9a78b8662b10582981a727dcb72d28e0ada47..453a9df42208e04fb9c77129dd996313b12210c3 100644 --- a/examples/data/list/events.jsonld +++ b/examples/data/list/events.jsonld @@ -1,43 +1,43 @@ { - "@type": "ldp:Container", - "ldp:contains": [ - { - "@id": "/examples/data/list/event-1.jsonld", - "name": "Coliving", - "date": "2020-07-09", - "seats": 12, - "place":"", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-2.jsonld", - "name": "Workshop", - "date": "2020-05-10", - "seats": 2, - "place":"Opéra", - "city":"", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-3.jsonld", - "name": "Réunion d'information", - "date": "2020-07-10", - "seats": 36, - "place":"Couvent des jacobins", - "city":"Rennes", - "permissions": [] - }, - { - "@id": "/examples/data/list/event-4.jsonld", - "name": "Assemblée générale", - "date": "2020-05-10", - "seats": 5, - "place":"", - "city":"Marseille", - "permissions": [] - } - ], - "@id": "/examples/data/list/events.jsonld", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" + "@type": "ldp:Container", + "ldp:contains": [ + { + "@id": "/examples/data/list/event-1.jsonld", + "name": "Coliving", + "date": "2020-07-09", + "seats": 12, + "place": "", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-2.jsonld", + "name": "Workshop", + "date": "2020-05-10", + "seats": 2, + "place": "Opéra", + "city": "", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-3.jsonld", + "name": "Réunion d'information", + "date": "2020-07-10", + "seats": 36, + "place": "Couvent des jacobins", + "city": "Rennes", + "permissions": [] + }, + { + "@id": "/examples/data/list/event-4.jsonld", + "name": "Assemblée générale", + "date": "2020-05-10", + "seats": 5, + "place": "", + "city": "Marseille", + "permissions": [] + } + ], + "@id": "/examples/data/list/events.jsonld", + "@context": "https://cdn.startinblox.com/owl/context.jsonld" } diff --git a/examples/data/list/group-3.jsonld b/examples/data/list/group-3.jsonld index ba821d132f41c1198bfbaa0389b0fc5ac6f4ab46..103d8374c46ae337640b7488a6c65eb5bda24c2a 100644 --- a/examples/data/list/group-3.jsonld +++ b/examples/data/list/group-3.jsonld @@ -1,50 +1,50 @@ { "name": "LDP_circle_members_1", "members": [ - { - "@id": "/examples/data/list/user-2.jsonld", - "@type": "foaf:user", - "name": "Benoit Alessandroni", - "email": "benoit@toto.com", - "last_name": "Alessandroni", - "first_name": "Benoit", - "@context": { - "get_full_name": "rdfs:label" - } - }, - { - "@id": "/examples/data/list/user-1.jsonld", - "@type": "foaf:user", - "name": "Blaise Pascal", - "email": "blaise@toto.com", - "last_name": "Pascal", - "first_name": "Blaise", - "@context": { - "get_full_name": "rdfs:label" - } - }, - { - "@id": "/examples/data/list/user-3.jsonld", - "@type": "foaf:user", - "name": "Vitali Klitschko", - "email": "blaise@toto.com", - "last_name": "Klitschko", - "first_name": "Vitali", - "@context": { - "get_full_name": "rdfs:label" - } - }, - { - "@id": "/examples/data/list/user-4.jsonld", - "@type": "foaf:user", - "name": "Eric Cantona", - "email": "cantona@toto.com", - "last_name": "Cantona", - "first_name": "Eric", - "@context": { - "get_full_name": "rdfs:label" - } + { + "@id": "/examples/data/list/user-2.jsonld", + "@type": "foaf:user", + "name": "Benoit Alessandroni", + "email": "benoit@toto.com", + "last_name": "Alessandroni", + "first_name": "Benoit", + "@context": { + "get_full_name": "rdfs:label" + } + }, + { + "@id": "/examples/data/list/user-1.jsonld", + "@type": "foaf:user", + "name": "Blaise Pascal", + "email": "blaise@toto.com", + "last_name": "Pascal", + "first_name": "Blaise", + "@context": { + "get_full_name": "rdfs:label" + } + }, + { + "@id": "/examples/data/list/user-3.jsonld", + "@type": "foaf:user", + "name": "Vitali Klitschko", + "email": "blaise@toto.com", + "last_name": "Klitschko", + "first_name": "Vitali", + "@context": { + "get_full_name": "rdfs:label" + } + }, + { + "@id": "/examples/data/list/user-4.jsonld", + "@type": "foaf:user", + "name": "Eric Cantona", + "email": "cantona@toto.com", + "last_name": "Cantona", + "first_name": "Eric", + "@context": { + "get_full_name": "rdfs:label" } + } ], "events": { "@type": "ldp:Container", @@ -55,8 +55,8 @@ "name": "Coliving", "date": "2020-07-09", "seats": 12, - "place":"", - "city":"", + "place": "", + "city": "", "permissions": [] }, { @@ -64,8 +64,8 @@ "name": "Workshop", "date": "2020-05-10", "seats": 2, - "place":"Opéra", - "city":"", + "place": "Opéra", + "city": "", "permissions": [] } ] @@ -77,7 +77,5 @@ "admin_circle": null, "@id": "/examples/data/list/group-3.jsonld", "@type": "foaf:Group", - "@context": [ - "https://cdn.startinblox.com/owl/context.jsonld" - ] + "@context": ["https://cdn.startinblox.com/owl/context.jsonld"] } diff --git a/examples/data/list/job-1.jsonld b/examples/data/list/job-1.jsonld index a256e69b19a3deaea83a6800d9b4d46eab257f2f..2c493c67a4ec107ff31eafdbe8cdd20379ed3563 100644 --- a/examples/data/list/job-1.jsonld +++ b/examples/data/list/job-1.jsonld @@ -11,11 +11,9 @@ }, { "@id": "/examples/data/list/skill-4.jsonld" - } + } ] }, - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/profile-1.jsonld b/examples/data/list/profile-1.jsonld index e00d67bf93c88163ce6c9163ca1754b440dc0e1e..7074cc28524ead26bf9c889b57969aa7bfd102a1 100644 --- a/examples/data/list/profile-1.jsonld +++ b/examples/data/list/profile-1.jsonld @@ -10,8 +10,6 @@ "city": "Paris", "phone": "06-03-23-98-23", "website": "www.startinblox.com", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/profile-2.jsonld b/examples/data/list/profile-2.jsonld index 558806b3203ab457f0321be3187ad53d12c2aabd..8c6dcee1dc9d20b3c8ea9e8b12d9d5178a9e0cb7 100644 --- a/examples/data/list/profile-2.jsonld +++ b/examples/data/list/profile-2.jsonld @@ -10,8 +10,6 @@ "city": "Paris", "phone": "", "website": "", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/profile-3.jsonld b/examples/data/list/profile-3.jsonld index 4ec2e70412edda351cf65d2e3db305a92f7417fa..b5520a0afd0c9455e4e6a7e8e2f486738dc21de0 100644 --- a/examples/data/list/profile-3.jsonld +++ b/examples/data/list/profile-3.jsonld @@ -10,8 +10,6 @@ "city": "Rennes", "phone": "", "website": "", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/profile-4.jsonld b/examples/data/list/profile-4.jsonld index c51f3cb339986e2699f26b812ba99006f8351f47..850f2999fa1c3219e91fa6f64685008c66df8179 100644 --- a/examples/data/list/profile-4.jsonld +++ b/examples/data/list/profile-4.jsonld @@ -10,8 +10,6 @@ "city": "", "phone": "", "website": "", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/profile-5.jsonld b/examples/data/list/profile-5.jsonld index cf52fc446b06c10f3156b191ce3c7571583fc209..67be8b94b954a59879f084b4b483f6a4985716dd 100644 --- a/examples/data/list/profile-5.jsonld +++ b/examples/data/list/profile-5.jsonld @@ -10,8 +10,6 @@ "city": "", "phone": "", "website": "[my site](http://drawing.garden/)", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-1.jsonld b/examples/data/list/skill-1.jsonld index 779d8d675982ed044b64a6164dcab78be286960b..efee030021df598eb7291bc969f89403f4566948 100644 --- a/examples/data/list/skill-1.jsonld +++ b/examples/data/list/skill-1.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-1.jsonld", "name": "HTML", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-2.jsonld b/examples/data/list/skill-2.jsonld index 53f546588d7cbdbfeddbd7d8594c1e549e2e02dd..074f19e2882950a954370380bf322c44778dab0a 100644 --- a/examples/data/list/skill-2.jsonld +++ b/examples/data/list/skill-2.jsonld @@ -20,11 +20,6 @@ } ] }, - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-3.jsonld b/examples/data/list/skill-3.jsonld index e13029aafad01b0b7ebfb451977a865ffd31d435..492846fd6629cdb39626d543515f0705a636e493 100644 --- a/examples/data/list/skill-3.jsonld +++ b/examples/data/list/skill-3.jsonld @@ -20,11 +20,6 @@ } ] }, - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-4.jsonld b/examples/data/list/skill-4.jsonld index 718aceeb14adb379db77542ada490eb1e6dd2f5a..97a2298c619dadf3e7cff0f0d011b8d9dd84668b 100644 --- a/examples/data/list/skill-4.jsonld +++ b/examples/data/list/skill-4.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-4.jsonld", "name": "DevOps", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-5.jsonld b/examples/data/list/skill-5.jsonld index 536ff49c5fe9af265f6f1bfe22e3cdfe1d1f3ad4..8264f8cd185ae8f0ea8a81585328afcab1aebee5 100644 --- a/examples/data/list/skill-5.jsonld +++ b/examples/data/list/skill-5.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-5.jsonld", "name": "PHP", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-6.jsonld b/examples/data/list/skill-6.jsonld index f0e706eb1c46f9ca4763bf4c958a6c1bfc0ad089..158dee7c85d2632fd05b5fb33e6e5835d446965b 100644 --- a/examples/data/list/skill-6.jsonld +++ b/examples/data/list/skill-6.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-6.jsonld", "name": "Git", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-7.jsonld b/examples/data/list/skill-7.jsonld index 9f5f34b1b39c35a9793d84fa55006d9e9abb1c5a..9cf2d4aac9b2c3d6c5482e15c3aa09c1763dcd43 100644 --- a/examples/data/list/skill-7.jsonld +++ b/examples/data/list/skill-7.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-7.jsonld", "name": "Python", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skill-8.jsonld b/examples/data/list/skill-8.jsonld index 077b844032fab34fafc068a15b1e59aa3660cbae..fc771b9846368f51feb35ee81b047bdf1c21cd7c 100644 --- a/examples/data/list/skill-8.jsonld +++ b/examples/data/list/skill-8.jsonld @@ -2,11 +2,6 @@ "@id": "/examples/data/list/skill-8.jsonld", "name": "Node", "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ], + "permissions": ["view", "change", "control", "delete"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/skills.jsonld b/examples/data/list/skills.jsonld index fdc0d5b59db714cb2c4e433bb36456ced729f902..2ab8fccbacbdaa00c2ba065ae2e0f83364e8e4eb 100644 --- a/examples/data/list/skills.jsonld +++ b/examples/data/list/skills.jsonld @@ -7,8 +7,7 @@ "name": "HTML", "order": 1, "@type": "hd:skill", - "permissions": [ - ] + "permissions": [] }, { "@id": "/examples/data/list/skill-2.jsonld", @@ -21,69 +20,44 @@ "name": "Javascript", "order": 2, "@type": "hd:skill", - "permissions": [ - ] + "permissions": [] }, { "@id": "/examples/data/list/skill-4.jsonld", "name": "DevOps", "order": 10, "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ] + "permissions": ["view", "change", "control", "delete"] }, { "@id": "/examples/data/list/skill-5.jsonld", "name": "PHP", "order": 15, "@type": "hd:skill", - "permissions": [ - ] + "permissions": [] }, { "@id": "/examples/data/list/skill-6.jsonld", "name": "Git", "order": 20, "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ] + "permissions": ["view", "change", "control", "delete"] }, { "@id": "/examples/data/list/skill-7.jsonld", "name": "Python", "order": 27, "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ] + "permissions": ["view", "change", "control", "delete"] }, { "@id": "/examples/data/list/skill-8.jsonld", "name": "Node", "order": 30, "@type": "hd:skill", - "permissions": [ - "view", - "change", - "control", - "delete" - ] + "permissions": ["view", "change", "control", "delete"] } ], - "permissions": [ - "view", - "add" - ], + "permissions": ["view", "add"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/starwars-origin.jsonld b/examples/data/list/starwars-origin.jsonld index 05e14fcc5223736d61d2935933c6d3d3d1c729f3..fb422c740bb1777a505b7656cd6bd63917394e7e 100644 --- a/examples/data/list/starwars-origin.jsonld +++ b/examples/data/list/starwars-origin.jsonld @@ -4,14 +4,18 @@ "@type": "hd:film", "ebu:originalTitle": "Star Wars", "characters": { - "@id": "/examples/data/list/local.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ - { "@id": "/examples/data/list/examples/data/list/darth-vader.json" }, - { "@id": "/examples/data/list/examples/data/list/chewbacca.jsonld", "name": "tata" }, - { - "@id": "/examples/data/list/examples/data/list/hansolo.jsonld", "name": "trotro" - } - ] + "@id": "/examples/data/list/local.jsonld", + "@type": "ldp:Container", + "ldp:contains": [ + { "@id": "/examples/data/list/examples/data/list/darth-vader.json" }, + { + "@id": "/examples/data/list/examples/data/list/chewbacca.jsonld", + "name": "tata" + }, + { + "@id": "/examples/data/list/examples/data/list/hansolo.jsonld", + "name": "trotro" + } + ] } -} \ No newline at end of file +} diff --git a/examples/data/list/starwars.jsonld b/examples/data/list/starwars.jsonld index 8a63d48517c78b263ba0248f0af904b5f7505916..b36632a3cda98ed6eef72aaea90e9650a63388ab 100644 --- a/examples/data/list/starwars.jsonld +++ b/examples/data/list/starwars.jsonld @@ -14,5 +14,5 @@ "name": "Han solo" } ], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/list/types.jsonld b/examples/data/list/types.jsonld index 7f18cb03cde79dfb7677c05f7f41567d0dee03f5..a3455fbf5db64f3b71a1c662ef8f315029649493 100644 --- a/examples/data/list/types.jsonld +++ b/examples/data/list/types.jsonld @@ -1,10 +1,7 @@ { "@context": "https://colibris.social/context.json", "id": "https://colibris.social/types", - "type": [ - "ldp:Container", - "ldp:BasicContainer" - ], + "type": ["ldp:Container", "ldp:BasicContainer"], "ldp:contains": [ { "id": "https://colibris.social/types/camping", diff --git a/examples/data/list/universite.jsonld b/examples/data/list/universite.jsonld index 02156fb52b13bb503d54ceecbc26d52d84982ba6..9508e428a06d1324f45b5ec549f17287f55cbe66 100644 --- a/examples/data/list/universite.jsonld +++ b/examples/data/list/universite.jsonld @@ -1,18 +1,11 @@ { "@context": "https://colibris.social/context.json", "id": "/examples/data/list/universite.jsonld", - "type": [ - "ldp:Container", - "ldp:BasicContainer" - ], + "type": ["ldp:Container", "ldp:BasicContainer"], "ldp:contains": [ { "id": "/examples/data/list/universite/courses.jsonld", - "type": [ - "ldp:Container", - "ldp:BasicContainer", - "ldp:Resource" - ] + "type": ["ldp:Container", "ldp:BasicContainer", "ldp:Resource"] } ] } diff --git a/examples/data/list/universite/courses.jsonld b/examples/data/list/universite/courses.jsonld index 56eb50a0fccfa61832490a2bd88955dc3b2ae373..ffff6b670c8923422a6f5255fe5ad0e2fff45c19 100644 --- a/examples/data/list/universite/courses.jsonld +++ b/examples/data/list/universite/courses.jsonld @@ -1,10 +1,7 @@ { "@context": "https://cdn.startinblox.com/owl/context.jsonld", "id": "/examples/data/list/universite/courses.jsonld", - "type": [ - "ldp:Container", - "ldp:BasicContainer" - ], + "type": ["ldp:Container", "ldp:BasicContainer"], "ldp:contains": [ { "id": "universite/courses/concevoir-une-oasis-partie-2-la-creation-du-collectif-0", diff --git a/examples/data/list/user-1-skills.jsonld b/examples/data/list/user-1-skills.jsonld index 8db9211c9626fa17bd915772be0d51d21ceb2949..1708ecaa0946a572c3558e8739def08dde47bb2b 100644 --- a/examples/data/list/user-1-skills.jsonld +++ b/examples/data/list/user-1-skills.jsonld @@ -9,8 +9,6 @@ "@id": "/examples/data/list/skill-3.jsonld" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-1.jsonld b/examples/data/list/user-1.jsonld index 20b6d1367b11f39b8690c60176f987df9359482b..f2f7ab94030410ddefba8a52ab15b99aa8d9bc43 100644 --- a/examples/data/list/user-1.jsonld +++ b/examples/data/list/user-1.jsonld @@ -17,9 +17,7 @@ "@id": "/examples/data/list/skill-3.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "job": { "@id": "/examples/data/list/job-1.jsonld" @@ -28,8 +26,6 @@ "@id": "/examples/data/list/profile-1.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-2-skills.jsonld b/examples/data/list/user-2-skills.jsonld index 67f2ee4aa9746da22016dd792e5685bafbf3138d..0cac47d59f56dc4f393cb31e67510c943f2e7638 100644 --- a/examples/data/list/user-2-skills.jsonld +++ b/examples/data/list/user-2-skills.jsonld @@ -6,8 +6,6 @@ "@id": "/examples/data/list/skill-1.jsonld" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-2.jsonld b/examples/data/list/user-2.jsonld index 17586e2bfcd588df397f25485797309c874547ff..499a5a0bc93da3c8ebe7e54f8c3a3c4b06365dfd 100644 --- a/examples/data/list/user-2.jsonld +++ b/examples/data/list/user-2.jsonld @@ -14,16 +14,12 @@ "@id": "/examples/data/list/skill-1.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-2.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-3-skills.jsonld b/examples/data/list/user-3-skills.jsonld index ffe5dbcceb75003259f9a5f4846ae2e3872a4876..af30fae84916e1c01cb286332e34eb093e0e8e1f 100644 --- a/examples/data/list/user-3-skills.jsonld +++ b/examples/data/list/user-3-skills.jsonld @@ -1,11 +1,7 @@ { "@id": "/examples/data/list/user-3-skills.jsonld", "@type": "ldp:Container", - "ldp:contains": [ - - ], - "permissions": [ - "view" - ], + "ldp:contains": [], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-3.jsonld b/examples/data/list/user-3.jsonld index 31b4e6baa8b7a95ac704be33561f0e11a461a1d5..146fd0f052f65d96bc6cdae31e62d6e17a8bad95 100644 --- a/examples/data/list/user-3.jsonld +++ b/examples/data/list/user-3.jsonld @@ -9,19 +9,13 @@ "skills": { "@id": "/examples/data/list/user-3-skills.jsonld", "@type": "ldp:Container", - "ldp:contains": [ - - ], - "permissions": [ - "view" - ] + "ldp:contains": [], + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-3.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-4-skills.jsonld b/examples/data/list/user-4-skills.jsonld index 078d534ef47090adf7ae5aec9e0b6e409c1ad16f..37fbd60c7c5bfef21d877227faa25c1171da90b3 100644 --- a/examples/data/list/user-4-skills.jsonld +++ b/examples/data/list/user-4-skills.jsonld @@ -12,8 +12,6 @@ "@id": "/examples/data/list/skill-4.jsonld" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-4.jsonld b/examples/data/list/user-4.jsonld index d18fcd9d5201524c335090ef853ff4d100a52475..ccd661a4bf2a83a2f27146c22f1d133640997cdd 100644 --- a/examples/data/list/user-4.jsonld +++ b/examples/data/list/user-4.jsonld @@ -20,16 +20,12 @@ "@id": "/examples/data/list/skill-4.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-4.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-5-skills.jsonld b/examples/data/list/user-5-skills.jsonld index 737dd30139336713a0493d28d2244855c98046d7..a437071cd38de50f7470e5e7c5e24e1c606da37e 100644 --- a/examples/data/list/user-5-skills.jsonld +++ b/examples/data/list/user-5-skills.jsonld @@ -12,8 +12,6 @@ "@id": "/examples/data/list/skill-8.jsonld" } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/user-5.jsonld b/examples/data/list/user-5.jsonld index ceffd4dac632a5acaba86f79f3d8717a25ccd767..658c1a7aef018b0c2b8bfd3fb8da7d7ac7354c9d 100644 --- a/examples/data/list/user-5.jsonld +++ b/examples/data/list/user-5.jsonld @@ -20,16 +20,12 @@ "@id": "/examples/data/list/skill-8.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-5.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/users-group1.jsonld b/examples/data/list/users-group1.jsonld index de9fa3b3586905dcfa3952a413689b7c8dafdbac..9e6a188f623c9408e6219239f2533071bd7250a1 100644 --- a/examples/data/list/users-group1.jsonld +++ b/examples/data/list/users-group1.jsonld @@ -22,17 +22,13 @@ "@id": "/examples/data/list/skill-3.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-1.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-2.jsonld", @@ -51,17 +47,13 @@ "@id": "/examples/data/list/skill-1.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-2.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-3.jsonld", @@ -75,24 +67,16 @@ "skills": { "@id": "/examples/data/list/user-3-skills.jsonld", "@type": "ldp:Container", - "ldp:contains": [ - - ], - "permissions": [ - "view" - ] + "ldp:contains": [], + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-3.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/users-group2.jsonld b/examples/data/list/users-group2.jsonld index 9aeb2bae8652dbce987289e5114a106612dcf83c..acd5eedc47af9ef192c161c1c59d0a27e701a546 100644 --- a/examples/data/list/users-group2.jsonld +++ b/examples/data/list/users-group2.jsonld @@ -19,17 +19,13 @@ "@id": "/examples/data/list/skill-1.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-2.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-4.jsonld", @@ -54,17 +50,13 @@ "@id": "/examples/data/list/skill-4.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-4.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-5.jsonld", @@ -88,21 +80,15 @@ "@id": "/examples/data/list/skill-8.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-5.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/users-long.jsonld b/examples/data/list/users-long.jsonld index 82e62771967b0e1ea4cc024fa89cd6eb8dad30ae..f286a947d1df8e7a9a16a5ef8d480c5f91f73c03 100644 --- a/examples/data/list/users-long.jsonld +++ b/examples/data/list/users-long.jsonld @@ -1,9 +1,7 @@ { "@id": "/examples/data/list/users-long.jsonld", "@type": "ldp:Container", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld", "ldp:contains": [ { @@ -14,9 +12,7 @@ "username": "mayer.glenn", "email": "mayer.glenn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-1.jsonld", @@ -26,9 +22,7 @@ "username": "santiago.fowler", "email": "santiago.fowler@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-2.jsonld", @@ -38,9 +32,7 @@ "username": "imelda.kemp", "email": "imelda.kemp@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-3.jsonld", @@ -50,9 +42,7 @@ "username": "tillman.mcmahon", "email": "tillman.mcmahon@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-4.jsonld", @@ -62,9 +52,7 @@ "username": "torres.henry", "email": "torres.henry@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-5.jsonld", @@ -74,9 +62,7 @@ "username": "ines.head", "email": "ines.head@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-6.jsonld", @@ -86,9 +72,7 @@ "username": "cotton.sullivan", "email": "cotton.sullivan@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-7.jsonld", @@ -98,9 +82,7 @@ "username": "nelda.armstrong", "email": "nelda.armstrong@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-8.jsonld", @@ -110,9 +92,7 @@ "username": "marianne.gentry", "email": "marianne.gentry@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-9.jsonld", @@ -122,9 +102,7 @@ "username": "sweet.petersen", "email": "sweet.petersen@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-10.jsonld", @@ -134,9 +112,7 @@ "username": "henry.noble", "email": "henry.noble@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-11.jsonld", @@ -146,9 +122,7 @@ "username": "rhodes.michael", "email": "rhodes.michael@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-12.jsonld", @@ -158,9 +132,7 @@ "username": "browning.sherman", "email": "browning.sherman@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-13.jsonld", @@ -170,9 +142,7 @@ "username": "ellen.walter", "email": "ellen.walter@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-14.jsonld", @@ -182,9 +152,7 @@ "username": "jolene.winters", "email": "jolene.winters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-15.jsonld", @@ -194,9 +162,7 @@ "username": "benton.powell", "email": "benton.powell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-16.jsonld", @@ -206,9 +172,7 @@ "username": "lott.franklin", "email": "lott.franklin@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-17.jsonld", @@ -218,9 +182,7 @@ "username": "noble.ramirez", "email": "noble.ramirez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-18.jsonld", @@ -230,9 +192,7 @@ "username": "case.gillespie", "email": "case.gillespie@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-19.jsonld", @@ -242,9 +202,7 @@ "username": "oneill.frank", "email": "oneill.frank@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-20.jsonld", @@ -254,9 +212,7 @@ "username": "francesca.tanner", "email": "francesca.tanner@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-21.jsonld", @@ -266,9 +222,7 @@ "username": "shauna.floyd", "email": "shauna.floyd@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-22.jsonld", @@ -278,9 +232,7 @@ "username": "michelle.terrell", "email": "michelle.terrell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-23.jsonld", @@ -290,9 +242,7 @@ "username": "carmella.bennett", "email": "carmella.bennett@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-24.jsonld", @@ -302,9 +252,7 @@ "username": "levine.morrison", "email": "levine.morrison@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-25.jsonld", @@ -314,9 +262,7 @@ "username": "janice.lane", "email": "janice.lane@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-26.jsonld", @@ -326,9 +272,7 @@ "username": "woods.clay", "email": "woods.clay@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-27.jsonld", @@ -338,9 +282,7 @@ "username": "anna.abbott", "email": "anna.abbott@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-28.jsonld", @@ -350,9 +292,7 @@ "username": "atkins.levine", "email": "atkins.levine@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-29.jsonld", @@ -362,9 +302,7 @@ "username": "tiffany.dunn", "email": "tiffany.dunn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-30.jsonld", @@ -374,9 +312,7 @@ "username": "valarie.lindsay", "email": "valarie.lindsay@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-31.jsonld", @@ -386,9 +322,7 @@ "username": "finley.solis", "email": "finley.solis@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-32.jsonld", @@ -398,9 +332,7 @@ "username": "mclaughlin.wagner", "email": "mclaughlin.wagner@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-33.jsonld", @@ -410,9 +342,7 @@ "username": "roslyn.hyde", "email": "roslyn.hyde@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-34.jsonld", @@ -422,9 +352,7 @@ "username": "rosetta.craig", "email": "rosetta.craig@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-35.jsonld", @@ -434,9 +362,7 @@ "username": "geraldine.waters", "email": "geraldine.waters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-36.jsonld", @@ -446,9 +372,7 @@ "username": "zamora.ellison", "email": "zamora.ellison@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-37.jsonld", @@ -458,9 +382,7 @@ "username": "eileen.cantu", "email": "eileen.cantu@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-38.jsonld", @@ -470,9 +392,7 @@ "username": "lynette.oconnor", "email": "lynette.oconnor@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-39.jsonld", @@ -482,9 +402,7 @@ "username": "maritza.middleton", "email": "maritza.middleton@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-40.jsonld", @@ -494,9 +412,7 @@ "username": "norman.peters", "email": "norman.peters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-41.jsonld", @@ -506,9 +422,7 @@ "username": "lane.navarro", "email": "lane.navarro@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-42.jsonld", @@ -518,9 +432,7 @@ "username": "oliver.fulton", "email": "oliver.fulton@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-43.jsonld", @@ -530,9 +442,7 @@ "username": "dale.bishop", "email": "dale.bishop@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-44.jsonld", @@ -542,9 +452,7 @@ "username": "wise.vazquez", "email": "wise.vazquez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-45.jsonld", @@ -554,9 +462,7 @@ "username": "gilliam.moran", "email": "gilliam.moran@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-46.jsonld", @@ -566,9 +472,7 @@ "username": "ellison.wilson", "email": "ellison.wilson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-47.jsonld", @@ -578,9 +482,7 @@ "username": "fanny.sandoval", "email": "fanny.sandoval@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-48.jsonld", @@ -590,9 +492,7 @@ "username": "hale.macdonald", "email": "hale.macdonald@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-49.jsonld", @@ -602,9 +502,7 @@ "username": "riley.mcfarland", "email": "riley.mcfarland@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-50.jsonld", @@ -614,9 +512,7 @@ "username": "prince.wilkerson", "email": "prince.wilkerson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-51.jsonld", @@ -626,9 +522,7 @@ "username": "barnett.klein", "email": "barnett.klein@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-52.jsonld", @@ -638,9 +532,7 @@ "username": "amy.collins", "email": "amy.collins@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-53.jsonld", @@ -650,9 +542,7 @@ "username": "wells.grant", "email": "wells.grant@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-54.jsonld", @@ -662,9 +552,7 @@ "username": "melton.peterson", "email": "melton.peterson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-55.jsonld", @@ -674,9 +562,7 @@ "username": "davenport.townsend", "email": "davenport.townsend@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-56.jsonld", @@ -686,9 +572,7 @@ "username": "mayo.flynn", "email": "mayo.flynn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-57.jsonld", @@ -698,9 +582,7 @@ "username": "latoya.haynes", "email": "latoya.haynes@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-58.jsonld", @@ -710,9 +592,7 @@ "username": "catherine.parrish", "email": "catherine.parrish@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-59.jsonld", @@ -722,9 +602,7 @@ "username": "bernadette.roman", "email": "bernadette.roman@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-60.jsonld", @@ -734,9 +612,7 @@ "username": "jeanne.rosa", "email": "jeanne.rosa@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-61.jsonld", @@ -746,9 +622,7 @@ "username": "ward.cunningham", "email": "ward.cunningham@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-62.jsonld", @@ -758,9 +632,7 @@ "username": "melba.nelson", "email": "melba.nelson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-63.jsonld", @@ -770,9 +642,7 @@ "username": "johnston.ashley", "email": "johnston.ashley@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-64.jsonld", @@ -782,9 +652,7 @@ "username": "mavis.sellers", "email": "mavis.sellers@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-65.jsonld", @@ -794,9 +662,7 @@ "username": "veronica.rollins", "email": "veronica.rollins@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-66.jsonld", @@ -806,9 +672,7 @@ "username": "renee.melendez", "email": "renee.melendez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-67.jsonld", @@ -818,9 +682,7 @@ "username": "mccarty.gates", "email": "mccarty.gates@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-68.jsonld", @@ -830,9 +692,7 @@ "username": "day.rios", "email": "day.rios@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-69.jsonld", @@ -842,9 +702,7 @@ "username": "frye.johns", "email": "frye.johns@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-70.jsonld", @@ -854,9 +712,7 @@ "username": "cheryl.wilkinson", "email": "cheryl.wilkinson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-71.jsonld", @@ -866,9 +722,7 @@ "username": "munoz.douglas", "email": "munoz.douglas@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-72.jsonld", @@ -878,9 +732,7 @@ "username": "debra.cook", "email": "debra.cook@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-73.jsonld", @@ -890,9 +742,7 @@ "username": "schneider.villarreal", "email": "schneider.villarreal@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-74.jsonld", @@ -902,9 +752,7 @@ "username": "hayes.holloway", "email": "hayes.holloway@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-75.jsonld", @@ -914,9 +762,7 @@ "username": "buck.velazquez", "email": "buck.velazquez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-76.jsonld", @@ -926,9 +772,7 @@ "username": "aida.pugh", "email": "aida.pugh@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-77.jsonld", @@ -938,9 +782,7 @@ "username": "pamela.olsen", "email": "pamela.olsen@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-78.jsonld", @@ -950,9 +792,7 @@ "username": "trudy.lucas", "email": "trudy.lucas@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-79.jsonld", @@ -962,9 +802,7 @@ "username": "madge.casey", "email": "madge.casey@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-80.jsonld", @@ -974,9 +812,7 @@ "username": "nicole.palmer", "email": "nicole.palmer@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-81.jsonld", @@ -986,9 +822,7 @@ "username": "hopper.harrell", "email": "hopper.harrell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-82.jsonld", @@ -998,9 +832,7 @@ "username": "chelsea.kennedy", "email": "chelsea.kennedy@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-83.jsonld", @@ -1010,9 +842,7 @@ "username": "townsend.morin", "email": "townsend.morin@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-84.jsonld", @@ -1022,9 +852,7 @@ "username": "valenzuela.herring", "email": "valenzuela.herring@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-85.jsonld", @@ -1034,9 +862,7 @@ "username": "iris.durham", "email": "iris.durham@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-86.jsonld", @@ -1046,9 +872,7 @@ "username": "guerrero.wooten", "email": "guerrero.wooten@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ] -} \ No newline at end of file +} diff --git a/examples/data/list/users-mocked.jsonld b/examples/data/list/users-mocked.jsonld index 66976ac647467bb0f5b90db3e0eb33534c9b089d..d98da4bfe4ead2316a6d2ada7c611002a85761e9 100644 --- a/examples/data/list/users-mocked.jsonld +++ b/examples/data/list/users-mocked.jsonld @@ -1,9 +1,7 @@ { "@id": "/mock/users.jsonld", "@type": "ldp:Container", - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld", "ldp:contains": [ { @@ -14,9 +12,7 @@ "username": "mayer.glenn", "email": "mayer.glenn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-1.jsonld", @@ -26,9 +22,7 @@ "username": "santiago.fowler", "email": "santiago.fowler@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-2.jsonld", @@ -38,9 +32,7 @@ "username": "imelda.kemp", "email": "imelda.kemp@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-3.jsonld", @@ -50,9 +42,7 @@ "username": "tillman.mcmahon", "email": "tillman.mcmahon@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-4.jsonld", @@ -62,9 +52,7 @@ "username": "torres.henry", "email": "torres.henry@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-5.jsonld", @@ -74,9 +62,7 @@ "username": "ines.head", "email": "ines.head@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-6.jsonld", @@ -86,9 +72,7 @@ "username": "cotton.sullivan", "email": "cotton.sullivan@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-7.jsonld", @@ -98,9 +82,7 @@ "username": "nelda.armstrong", "email": "nelda.armstrong@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-8.jsonld", @@ -110,9 +92,7 @@ "username": "marianne.gentry", "email": "marianne.gentry@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-9.jsonld", @@ -122,9 +102,7 @@ "username": "sweet.petersen", "email": "sweet.petersen@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-10.jsonld", @@ -134,9 +112,7 @@ "username": "henry.noble", "email": "henry.noble@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-11.jsonld", @@ -146,9 +122,7 @@ "username": "rhodes.michael", "email": "rhodes.michael@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-12.jsonld", @@ -158,9 +132,7 @@ "username": "browning.sherman", "email": "browning.sherman@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-13.jsonld", @@ -170,9 +142,7 @@ "username": "ellen.walter", "email": "ellen.walter@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-14.jsonld", @@ -182,9 +152,7 @@ "username": "jolene.winters", "email": "jolene.winters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-15.jsonld", @@ -194,9 +162,7 @@ "username": "benton.powell", "email": "benton.powell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-16.jsonld", @@ -206,9 +172,7 @@ "username": "lott.franklin", "email": "lott.franklin@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-17.jsonld", @@ -218,9 +182,7 @@ "username": "noble.ramirez", "email": "noble.ramirez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-18.jsonld", @@ -230,9 +192,7 @@ "username": "case.gillespie", "email": "case.gillespie@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-19.jsonld", @@ -242,9 +202,7 @@ "username": "oneill.frank", "email": "oneill.frank@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-20.jsonld", @@ -254,9 +212,7 @@ "username": "francesca.tanner", "email": "francesca.tanner@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-21.jsonld", @@ -266,9 +222,7 @@ "username": "shauna.floyd", "email": "shauna.floyd@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-22.jsonld", @@ -278,9 +232,7 @@ "username": "michelle.terrell", "email": "michelle.terrell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-23.jsonld", @@ -290,9 +242,7 @@ "username": "carmella.bennett", "email": "carmella.bennett@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-24.jsonld", @@ -302,9 +252,7 @@ "username": "levine.morrison", "email": "levine.morrison@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-25.jsonld", @@ -314,9 +262,7 @@ "username": "janice.lane", "email": "janice.lane@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-26.jsonld", @@ -326,9 +272,7 @@ "username": "woods.clay", "email": "woods.clay@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-27.jsonld", @@ -338,9 +282,7 @@ "username": "anna.abbott", "email": "anna.abbott@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-28.jsonld", @@ -350,9 +292,7 @@ "username": "atkins.levine", "email": "atkins.levine@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-29.jsonld", @@ -362,9 +302,7 @@ "username": "tiffany.dunn", "email": "tiffany.dunn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-30.jsonld", @@ -374,9 +312,7 @@ "username": "valarie.lindsay", "email": "valarie.lindsay@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-31.jsonld", @@ -386,9 +322,7 @@ "username": "finley.solis", "email": "finley.solis@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-32.jsonld", @@ -398,9 +332,7 @@ "username": "mclaughlin.wagner", "email": "mclaughlin.wagner@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-33.jsonld", @@ -410,9 +342,7 @@ "username": "roslyn.hyde", "email": "roslyn.hyde@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-34.jsonld", @@ -422,9 +352,7 @@ "username": "rosetta.craig", "email": "rosetta.craig@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-35.jsonld", @@ -434,9 +362,7 @@ "username": "geraldine.waters", "email": "geraldine.waters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-36.jsonld", @@ -446,9 +372,7 @@ "username": "zamora.ellison", "email": "zamora.ellison@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-37.jsonld", @@ -458,9 +382,7 @@ "username": "eileen.cantu", "email": "eileen.cantu@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-38.jsonld", @@ -470,9 +392,7 @@ "username": "lynette.oconnor", "email": "lynette.oconnor@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-39.jsonld", @@ -482,9 +402,7 @@ "username": "maritza.middleton", "email": "maritza.middleton@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-40.jsonld", @@ -494,9 +412,7 @@ "username": "norman.peters", "email": "norman.peters@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-41.jsonld", @@ -506,9 +422,7 @@ "username": "lane.navarro", "email": "lane.navarro@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-42.jsonld", @@ -518,9 +432,7 @@ "username": "oliver.fulton", "email": "oliver.fulton@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-43.jsonld", @@ -530,9 +442,7 @@ "username": "dale.bishop", "email": "dale.bishop@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-44.jsonld", @@ -542,9 +452,7 @@ "username": "wise.vazquez", "email": "wise.vazquez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-45.jsonld", @@ -554,9 +462,7 @@ "username": "gilliam.moran", "email": "gilliam.moran@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-46.jsonld", @@ -566,9 +472,7 @@ "username": "ellison.wilson", "email": "ellison.wilson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-47.jsonld", @@ -578,9 +482,7 @@ "username": "fanny.sandoval", "email": "fanny.sandoval@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-48.jsonld", @@ -590,9 +492,7 @@ "username": "hale.macdonald", "email": "hale.macdonald@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-49.jsonld", @@ -602,9 +502,7 @@ "username": "riley.mcfarland", "email": "riley.mcfarland@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-50.jsonld", @@ -614,9 +512,7 @@ "username": "prince.wilkerson", "email": "prince.wilkerson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-51.jsonld", @@ -626,9 +522,7 @@ "username": "barnett.klein", "email": "barnett.klein@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-52.jsonld", @@ -638,9 +532,7 @@ "username": "amy.collins", "email": "amy.collins@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-53.jsonld", @@ -650,9 +542,7 @@ "username": "wells.grant", "email": "wells.grant@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-54.jsonld", @@ -662,9 +552,7 @@ "username": "melton.peterson", "email": "melton.peterson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-55.jsonld", @@ -674,9 +562,7 @@ "username": "davenport.townsend", "email": "davenport.townsend@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-56.jsonld", @@ -686,9 +572,7 @@ "username": "mayo.flynn", "email": "mayo.flynn@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-57.jsonld", @@ -698,9 +582,7 @@ "username": "latoya.haynes", "email": "latoya.haynes@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-58.jsonld", @@ -710,9 +592,7 @@ "username": "catherine.parrish", "email": "catherine.parrish@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-59.jsonld", @@ -722,9 +602,7 @@ "username": "bernadette.roman", "email": "bernadette.roman@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-60.jsonld", @@ -734,9 +612,7 @@ "username": "jeanne.rosa", "email": "jeanne.rosa@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-61.jsonld", @@ -746,9 +622,7 @@ "username": "ward.cunningham", "email": "ward.cunningham@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-62.jsonld", @@ -758,9 +632,7 @@ "username": "melba.nelson", "email": "melba.nelson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-63.jsonld", @@ -770,9 +642,7 @@ "username": "johnston.ashley", "email": "johnston.ashley@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-64.jsonld", @@ -782,9 +652,7 @@ "username": "mavis.sellers", "email": "mavis.sellers@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-65.jsonld", @@ -794,9 +662,7 @@ "username": "veronica.rollins", "email": "veronica.rollins@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-66.jsonld", @@ -806,9 +672,7 @@ "username": "renee.melendez", "email": "renee.melendez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-67.jsonld", @@ -818,9 +682,7 @@ "username": "mccarty.gates", "email": "mccarty.gates@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-68.jsonld", @@ -830,9 +692,7 @@ "username": "day.rios", "email": "day.rios@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-69.jsonld", @@ -842,9 +702,7 @@ "username": "frye.johns", "email": "frye.johns@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-70.jsonld", @@ -854,9 +712,7 @@ "username": "cheryl.wilkinson", "email": "cheryl.wilkinson@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-71.jsonld", @@ -866,9 +722,7 @@ "username": "munoz.douglas", "email": "munoz.douglas@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-72.jsonld", @@ -878,9 +732,7 @@ "username": "debra.cook", "email": "debra.cook@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-73.jsonld", @@ -890,9 +742,7 @@ "username": "schneider.villarreal", "email": "schneider.villarreal@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-74.jsonld", @@ -902,9 +752,7 @@ "username": "hayes.holloway", "email": "hayes.holloway@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-75.jsonld", @@ -914,9 +762,7 @@ "username": "buck.velazquez", "email": "buck.velazquez@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-76.jsonld", @@ -926,9 +772,7 @@ "username": "aida.pugh", "email": "aida.pugh@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-77.jsonld", @@ -938,9 +782,7 @@ "username": "pamela.olsen", "email": "pamela.olsen@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-78.jsonld", @@ -950,9 +792,7 @@ "username": "trudy.lucas", "email": "trudy.lucas@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-79.jsonld", @@ -962,9 +802,7 @@ "username": "madge.casey", "email": "madge.casey@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-80.jsonld", @@ -974,9 +812,7 @@ "username": "nicole.palmer", "email": "nicole.palmer@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-81.jsonld", @@ -986,9 +822,7 @@ "username": "hopper.harrell", "email": "hopper.harrell@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-82.jsonld", @@ -998,9 +832,7 @@ "username": "chelsea.kennedy", "email": "chelsea.kennedy@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-83.jsonld", @@ -1010,9 +842,7 @@ "username": "townsend.morin", "email": "townsend.morin@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-84.jsonld", @@ -1022,9 +852,7 @@ "username": "valenzuela.herring", "email": "valenzuela.herring@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-85.jsonld", @@ -1034,9 +862,7 @@ "username": "iris.durham", "email": "iris.durham@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/--user-86.jsonld", @@ -1046,9 +872,7 @@ "username": "guerrero.wooten", "email": "guerrero.wooten@example.com", "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ] } diff --git a/examples/data/list/users.jsonld b/examples/data/list/users.jsonld index a866540238bb9ae4db270763591c17101e4f2bd9..b9c1b0b79650e5230f113f4ea24ffb2c284360aa 100644 --- a/examples/data/list/users.jsonld +++ b/examples/data/list/users.jsonld @@ -22,17 +22,13 @@ "@id": "/examples/data/list/skill-3.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-1.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-2.jsonld", @@ -51,17 +47,13 @@ "@id": "/examples/data/list/skill-1.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-2.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-4.jsonld", @@ -86,17 +78,13 @@ "@id": "/examples/data/list/skill-4.jsonld" } ], - "permissions": [ - "view" - ] + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-4.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] }, { "@id": "/examples/data/list/user-3.jsonld", @@ -110,24 +98,16 @@ "skills": { "@id": "/examples/data/list/user-3-skills.jsonld", "@type": "ldp:Container", - "ldp:contains": [ - - ], - "permissions": [ - "view" - ] + "ldp:contains": [], + "permissions": ["view"] }, "profile": { "@id": "/examples/data/list/profile-3.jsonld" }, "@type": "foaf:user", - "permissions": [ - "view" - ] + "permissions": ["view"] } ], - "permissions": [ - "view" - ], + "permissions": ["view"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/list/users/balessan.jsonld b/examples/data/list/users/balessan.jsonld index 517684404a2072d53f0554df241e0ff8e63c353a..314b62454a883b5199051e884ef230d8f010285d 100644 --- a/examples/data/list/users/balessan.jsonld +++ b/examples/data/list/users/balessan.jsonld @@ -261,11 +261,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "change", - "control", - "view", - "delete", - "add" - ] + "permissions": ["change", "control", "view", "delete", "add"] } diff --git a/examples/data/list/users/blaisepascal.jsonld b/examples/data/list/users/blaisepascal.jsonld index 32ab48bdd87f3cd04318b6900c852e0080609df9..752a80ad82a66495a24887d824e659114f8bbcbe 100644 --- a/examples/data/list/users/blaisepascal.jsonld +++ b/examples/data/list/users/blaisepascal.jsonld @@ -170,11 +170,5 @@ "get_full_name": "rdfs:label" } ], - "permissions": [ - "change", - "control", - "view", - "delete", - "add" - ] + "permissions": ["change", "control", "view", "delete", "add"] } diff --git a/examples/data/map/event-1.jsonld b/examples/data/map/event-1.jsonld deleted file mode 100644 index b745c872fcfab7fce50f42cd066903b3e076b5d3..0000000000000000000000000000000000000000 --- a/examples/data/map/event-1.jsonld +++ /dev/null @@ -1,9 +0,0 @@ -{ - "@id": "/examples/data/map/event-1.jsonld", - "name": "Test", - "category": "showcase event", - "lat": "21.028511", - "lng": "105.804817", - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/map/event-2.jsonld b/examples/data/map/event-2.jsonld deleted file mode 100644 index ddf97bf9efd41b383fff5020c0c35fd6db141f2a..0000000000000000000000000000000000000000 --- a/examples/data/map/event-2.jsonld +++ /dev/null @@ -1,9 +0,0 @@ -{ - "@id": "/examples/data/map/event-2.jsonld", - "name": "Test", - "category": "meetup", - "lat": "48.864716", - "lng": "2.349014", - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/map/event-3.jsonld b/examples/data/map/event-3.jsonld deleted file mode 100644 index d081d5f15cfeb5346269b0486462236c5ac8a134..0000000000000000000000000000000000000000 --- a/examples/data/map/event-3.jsonld +++ /dev/null @@ -1,9 +0,0 @@ -{ - "@id": "/examples/data/map/event-3.jsonld", - "name": "Test 3", - "category": "showcase event", - "lat": "41.8902102", - "lng": "12.4922309", - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/map/events.jsonld b/examples/data/map/events.jsonld deleted file mode 100644 index b674eef61e8c49d82525eda84e0f00d310f378dd..0000000000000000000000000000000000000000 --- a/examples/data/map/events.jsonld +++ /dev/null @@ -1,55 +0,0 @@ -{ - "@type": "ldp:Container", - "ldp:contains": [ - { - "name": "Test 1, Vietnam, Asia", - "category": "showcase event", - "lat": "21.028511", - "lng": "105.804817", - "permissions": [], - "@id": "/examples/data/map/event-1.jsonld" - }, - { - "name": "Test 2, France, Europe", - "category": "meetup", - "lat": "48.864716", - "lng": "2.349014", - "permissions": [], - "@id": "/examples/data/map/event-2.jsonld" - }, - { - "name": "Test 3, Italy, Europe", - "category": "showcase event", - "lat": "41.8902102", - "lng": "12.4922309", - "permissions": [], - "@id": "/examples/data/map/event-3.jsonld" - }, - { - "name": "Test 4, France, Europe", - "category": "meetup", - "lat": "48.63976", - "lng": "-2.42516", - "permissions": [], - "@id": "/examples/data/map/event-4.jsonld" - }, - { - "name": "Test 5, France, Europe", - "category": "meetup", - "lat": "48.64636", - "lng": "-2.41981", - "permissions": [], - "@id": "/examples/data/map/event-5.jsonld" - }, - { - "name": "Test 6, France, Europe", - "category": "meetup", - "lat": "48.63683", - "lng": "-2.47765", - "permissions": [], - "@id": "/examples/data/map/event-6.jsonld" - } - ], - "@id": "/examples/data/map/events.jsonld", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/map/other-events.jsonld b/examples/data/map/other-events.jsonld deleted file mode 100644 index 16f5e8c92cc3ce560bc84f6ac356eddcfab5e879..0000000000000000000000000000000000000000 --- a/examples/data/map/other-events.jsonld +++ /dev/null @@ -1,15 +0,0 @@ -{ - "@type": "ldp:Container", - "ldp:contains": [ - { - "name": "Test 7, New York", - "category": "other event", - "lat": "40.741895", - "lng": "-73.989308", - "permissions": [], - "@id": "/examples/data/map/event-7.jsonld" - } - ], - "@id": "/examples/data/map/other-events.jsonld", - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/map/source.jsonld b/examples/data/map/source.jsonld deleted file mode 100644 index 97a5affe76ab233a4d7ea4be05b19727705125db..0000000000000000000000000000000000000000 --- a/examples/data/map/source.jsonld +++ /dev/null @@ -1,22 +0,0 @@ -{ - "@id": "/examples/data/map/source.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ - { - "federation": "events", - "@id": "/examples/data/map/events.jsonld", - "@type": "sib:federatedContainer", - "permissions": [ - "view" - ] - }, - { - "@id": "/examples/data/map/other-events.jsonld", - "@type": "sib:federatedContainer" - } - ], - "permissions": [ - "view" - ], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} diff --git a/examples/data/nested-forms/batch-1.jsonld b/examples/data/nested-forms/batch-1.jsonld index ed143312759357cf6f1171c7ee71f43339177867..724febeca3eb89cd7fe58e39b31d2b735e6b6f0b 100644 --- a/examples/data/nested-forms/batch-1.jsonld +++ b/examples/data/nested-forms/batch-1.jsonld @@ -1,12 +1,12 @@ { - "@id": "/examples/data/nested-forms/batch-1.jsonld", - "invoice": { - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" - }, - "title": "Développement", - "creationDate": "2020-10-02", - "modificationDate": "2020-10-04", - "htAmount": 1500, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file + "@id": "/examples/data/nested-forms/batch-1.jsonld", + "invoice": { + "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" + }, + "title": "Développement", + "creationDate": "2020-10-02", + "modificationDate": "2020-10-04", + "htAmount": 1500, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/nested-forms/batch-2.jsonld b/examples/data/nested-forms/batch-2.jsonld index 6fed5861423fdf969907f09a79f6027ab4c0d1cd..ea3043847ecc650ef813b6244e48f0a78531df26 100644 --- a/examples/data/nested-forms/batch-2.jsonld +++ b/examples/data/nested-forms/batch-2.jsonld @@ -1,12 +1,12 @@ { - "@id": "/examples/data/nested-forms/batch-2.jsonld", - "invoice": { - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" - }, - "title": "Déploiement", - "creationDate": "2020-10-02", - "modificationDate": "2020-10-04", - "htAmount": 500, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file + "@id": "/examples/data/nested-forms/batch-2.jsonld", + "invoice": { + "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" + }, + "title": "Déploiement", + "creationDate": "2020-10-02", + "modificationDate": "2020-10-04", + "htAmount": 500, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/nested-forms/customer-invoice-1-batches.jsonld b/examples/data/nested-forms/customer-invoice-1-batches.jsonld index 3e4fb5ed83f9ebaf13b39e9d580fe43c521ad81c..6098b6cad2e6074864b59d46de2f46e4887fdbd6 100644 --- a/examples/data/nested-forms/customer-invoice-1-batches.jsonld +++ b/examples/data/nested-forms/customer-invoice-1-batches.jsonld @@ -1,30 +1,30 @@ { - "@id": "/examples/data/nested-forms/customer-invoice-1-batches.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ - { - "@id": "/examples/data/nested-forms/batch-1.jsonld", - "invoice": { - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" - }, - "title": "Développement", - "creationDate": "2020-10-02", - "modificationDate": "2020-10-04", - "htAmount": 1500, - "permissions": [] - }, - { - "@id": "/examples/data/nested-forms/batch-2.jsonld", - "invoice": { - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" - }, - "title": "Déploiement", - "creationDate": "2020-10-02", - "modificationDate": "2020-10-04", - "htAmount": 500, - "permissions": [] - } - ], - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file + "@id": "/examples/data/nested-forms/customer-invoice-1-batches.jsonld", + "@type": "ldp:Container", + "ldp:contains": [ + { + "@id": "/examples/data/nested-forms/batch-1.jsonld", + "invoice": { + "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" + }, + "title": "Développement", + "creationDate": "2020-10-02", + "modificationDate": "2020-10-04", + "htAmount": 1500, + "permissions": [] + }, + { + "@id": "/examples/data/nested-forms/batch-2.jsonld", + "invoice": { + "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld" + }, + "title": "Déploiement", + "creationDate": "2020-10-02", + "modificationDate": "2020-10-04", + "htAmount": 500, + "permissions": [] + } + ], + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/nested-forms/customer-invoice-1.jsonld b/examples/data/nested-forms/customer-invoice-1.jsonld index 6d03b5b11f06974645dc2f6538face928c70f310..eac5c2fe4a94d10a0c2c315df1d228040dd1ed6b 100644 --- a/examples/data/nested-forms/customer-invoice-1.jsonld +++ b/examples/data/nested-forms/customer-invoice-1.jsonld @@ -1,31 +1,31 @@ { - "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld", - "@type": "hd:customerinvoice", - "customer": { - "@id": "/examples/data/nested-forms/customer-1.jsonld" - }, - "project": { - "@id": "/examples/data/nested-forms/project-1.jsonld" - }, - "batches": { - "@id": "/examples/data/nested-forms/customer-invoice-1-batches.jsonld", - "@type": "ldp:Container", - "ldp:contains": [ - { "@id": "/examples/data/nested-forms/batch-1.jsonld" }, - { "@id": "/examples/data/nested-forms/batch-2.jsonld" } - ] - }, - "identifier": "F-202001", - "title": "Création plateforme Coopedia", - "state": "pending", - "tvaRate": 20, - "creationDate": "2020-10-02", - "modificationDate": "2020-10-04", - "invoicingDate": "2020-10-10", - "additionalText": "Pénalités de retard: 4%", - "htAmount": 2000, - "tvaAmount": 400, - "ttcAmount": 2400, - "permissions": [], - "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file + "@id": "/examples/data/nested-forms/customer-invoice-1.jsonld", + "@type": "hd:customerinvoice", + "customer": { + "@id": "/examples/data/nested-forms/customer-1.jsonld" + }, + "project": { + "@id": "/examples/data/nested-forms/project-1.jsonld" + }, + "batches": { + "@id": "/examples/data/nested-forms/customer-invoice-1-batches.jsonld", + "@type": "ldp:Container", + "ldp:contains": [ + { "@id": "/examples/data/nested-forms/batch-1.jsonld" }, + { "@id": "/examples/data/nested-forms/batch-2.jsonld" } + ] + }, + "identifier": "F-202001", + "title": "Création plateforme Coopedia", + "state": "pending", + "tvaRate": 20, + "creationDate": "2020-10-02", + "modificationDate": "2020-10-04", + "invoicingDate": "2020-10-10", + "additionalText": "Pénalités de retard: 4%", + "htAmount": 2000, + "tvaAmount": 400, + "ttcAmount": 2400, + "permissions": [], + "@context": "https://cdn.startinblox.com/owl/context.jsonld" +} diff --git a/examples/data/project.jsonld b/examples/data/project.jsonld index 18beaf044e647ac42b694d7c0938333f68cc8a0a..dbe84128da0b2d2b48ff7e3b28fc3b99213e1f0f 100644 --- a/examples/data/project.jsonld +++ b/examples/data/project.jsonld @@ -10,11 +10,6 @@ "jabberRoom": true, "texte": "ceci est un texte avec du **markdown** \u00e0 l'int\u00e9rieur and a [link](https://startinblox.com).", "@type": "doap:project", - "permissions": [ - "control", - "add", - "delete", - "change" - ], + "permissions": ["control", "add", "delete", "change"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/project2.jsonld b/examples/data/project2.jsonld index 7a326b5d183b9469cc7f0ac5305315d610d66fb3..b7064441ca6f08df9ac369c5c9b0bf107a51c692 100644 --- a/examples/data/project2.jsonld +++ b/examples/data/project2.jsonld @@ -9,12 +9,6 @@ "jabberID": "fusee@conference.happy-dev.fr", "jabberRoom": true, "@type": "doap:project", - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ], + "permissions": ["view", "control", "add", "delete", "change"], "@context": "https://cdn.startinblox.com/owl/context.jsonld" -} \ No newline at end of file +} diff --git a/examples/data/xwiki.jsonld b/examples/data/xwiki.jsonld index 6fa92f63f83bb6ad9bfef04ef48759edba4290f0..7a874e44d20c9246d1abba0b2b5498dc9df6a7c8 100644 --- a/examples/data/xwiki.jsonld +++ b/examples/data/xwiki.jsonld @@ -116,11 +116,5 @@ "fieldName": "wysiwyg" } }, - "permissions": [ - "view", - "control", - "add", - "delete", - "change" - ] -} \ No newline at end of file + "permissions": ["view", "control", "add", "delete", "change"] +} diff --git a/examples/e2e/helpers.css b/examples/e2e/helpers.css index 2c7f3bdd4d2178687f7def9fe0d9f4b87813c2d3..600a424a9e0a638f5bd337cf391c11072ae282f9 100644 --- a/examples/e2e/helpers.css +++ b/examples/e2e/helpers.css @@ -1,7 +1,7 @@ -html{ +html { background-color: green; } -html::before{ - content: 'styles loaded'; -} \ No newline at end of file +html::before { + content: "styles loaded"; +} diff --git a/examples/e2e/helpers.js b/examples/e2e/helpers.js index 42c4dd90b24341485349999706c67a0bffae5698..7a663e542b7a790542b4b5d2e2639503944f685b 100644 --- a/examples/e2e/helpers.js +++ b/examples/e2e/helpers.js @@ -1 +1 @@ -window.scriptLoaded = true; \ No newline at end of file +window.scriptLoaded = true; diff --git a/examples/e2e/solid-form-richtext.html b/examples/e2e/solid-form-richtext.html index fe111ed4d5ce4561b1afea183538414225000672..ab4266e0fa734fa4027950a3ed817964def83fc9 100644 --- a/examples/e2e/solid-form-richtext.html +++ b/examples/e2e/solid-form-richtext.html @@ -47,6 +47,14 @@ widget-website="solid-form-richtext" ></solid-form> + <h3>multiple new lines</h3> + <solid-form + id="form-5" + data-src="/examples/data/list/event-6.jsonld" + fields="description" + widget-description="solid-form-richtext"> + </solid-form> + <style> .id { font-family: monospace; diff --git a/examples/e2e/solid-map.html b/examples/e2e/solid-map.html deleted file mode 100644 index 764012730b628f63e2560bcf69d922f593847914..0000000000000000000000000000000000000000 --- a/examples/e2e/solid-map.html +++ /dev/null @@ -1,86 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta http-equiv="X-UA-Compatible" content="ie=edge" /> - <title>SIB test: solid-map</title> - <script type="module" src="../../dist/index.js"></script> - <script> - document.addEventListener("DOMContentLoaded", event => { - document.querySelector("solid-map").addEventListener("resourceSelect", event => console.log(event.detail.resource)); - }); - </script> - - <link rel="stylesheet" href="../styles.css" /> - </head> - - <body> - <h2>solid-map</h2> - - <solid-map - id="map-1" - data-src="/examples/data/map/events.jsonld" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - <br> - <solid-map - id="map-2" - data-src="/examples/data/map/events.jsonld" - fields="infos(name, category)" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - <br> - <solid-map - id="map-3" - data-src="/examples/data/map/events.jsonld" - group-by="category" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - <br> - <solid-map - id="map-4" - data-src="/examples/data/map/events.jsonld" - fields="infos(name, category)" - group-by="category" - class-name="test-class-name" - widget-name="solid-display-div" - editable-name - style="display: block; width: 800px; height: 600px;" - ></solid-map> - <br> - <solid-form-search - id="filter" - fields="category" - ></solid-form-search> - <br> - <solid-map - id="map-5" - data-src="/examples/data/map/events.jsonld" - fields="name, category" - filtered-by="filter" - counter-template="<span id='counter'>${counter} results<span>" - style="display: block; width: 800px; height: 600px;" - ></solid-map> -<br> - <solid-map - id="map-6" - data-src="/examples/data/map/events.jsonld" - fields="name, category" - style="display: block; width: 800px; height: 600px;" - clustering - ></solid-map> - <br> - <solid-map - id="map-federated" - data-src="/examples/data/map/source.jsonld" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - - <style> - .group-meetup { - border-color: coral; - } - </style> - </body> -</html> diff --git a/examples/e2e/solid-table.html b/examples/e2e/solid-table.html index 4b3ed9a3107a84f5562b857974afb79fed441183..f377f69baf474cb6a240c7ac71d18d226162b92e 100644 --- a/examples/e2e/solid-table.html +++ b/examples/e2e/solid-table.html @@ -93,6 +93,15 @@ order-group-asc ></solid-table> + <h4>Table grouped by desc date</h4> + <solid-table + id="grouped-table-date-desc" + data-src="/examples/data/list/event-5.jsonld" + fields="name, date, place, year" + group-by="date" + order-group-desc + ></solid-table> + <h4>Table grouped by asc date</h4> <solid-table id="grouped-table-date-asc" diff --git a/examples/filtered-map.html b/examples/filtered-map.html deleted file mode 100644 index ed9bcb1e8559fb914f0b3a415ab46786a56fd9dd..0000000000000000000000000000000000000000 --- a/examples/filtered-map.html +++ /dev/null @@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta http-equiv="X-UA-Compatible" content="ie=edge" /> - <title>SIB test: filtered solid-map</title> - <script type="module" src="../dist/index.js"></script> - <script> - document.addEventListener("DOMContentLoaded", event => { - document.querySelector("solid-map").addEventListener("resourceSelect", event => console.log(event.detail.resource)); - }); - </script> - - <link rel="stylesheet" href="styles.css" /> - </head> - - <body> - <h2>Filtered Solid Map</h2> - <solid-form-search - id="filter" - fields="name" - label-name='Filter places (try "Europe")' - submit-button="update map" - ></solid-form-search> - <solid-map - data-src="/examples/data/map/events.jsonld" - fields="infos(name, category)" - group-by="category" - filtered-by="filter" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - - <style> - .group-meetup { - border-color: coral; - } - </style> - </body> -</html> diff --git a/examples/filtered.html b/examples/filtered.html index 6b7a8922cd3f6a7df8720f47c0be37d298b9a841..cd3f1886782fb3b6380d77610b653f5bfe0debd9 100644 --- a/examples/filtered.html +++ b/examples/filtered.html @@ -29,16 +29,17 @@ function change(input) { if (!(input instanceof HTMLInputElement)) return; const value = input.value; - const elm = input.closest('form').nextElementSibling; + const elm = input.closest("form").nextElementSibling; elm.component.filteredBy = value; } - document.addEventListener('DOMContentLoaded', () => { - document.querySelector('main').addEventListener('change', ({ target }) => - change(target), - ); - [...document.querySelectorAll('input[type=radio]')] - .filter((elm) => elm.checked) - .forEach(change); + document.addEventListener("DOMContentLoaded", () => { + document + .querySelector("main") + .addEventListener("change", ({ target }) => change(target)); + for (const input of document.querySelectorAll("input[type=radio]")) { + if (!input.checked) continue; + change(input); + } }); </script> </head> @@ -61,7 +62,7 @@ <div> <h3>solid-display 1</h3> <form> - filteredBy: + filteredBy: <label ><input type="radio" name="filterBy" value="filter1" checked /> filter1</label @@ -80,7 +81,7 @@ <div> <h3>solid-display 2</h3> <form> - filteredBy: + filteredBy: <label ><input type="radio" name="filterBy" value="filter1" checked /> filter1</label diff --git a/examples/pagination.html b/examples/pagination.html index 89bb6486ac6e1d388ebcbcce7a68942f70215458..18c57fc011aeae3d60acff269c40068074dfbdc7 100644 --- a/examples/pagination.html +++ b/examples/pagination.html @@ -27,6 +27,17 @@ search-fields="email" paginate-by="2" ></solid-display> - </details> + </details> + + <details> + <summary>Search + Pagination + Order:</summary> + <solid-display + data-src="/examples/data/list/users-medium.jsonld" + fields="@id, username, first_name, last_name, email" + order-asc="first_name" + search-fields="email" + paginate-by="2" + ></solid-display> + </details> </body> </html> diff --git a/examples/solid-calendar.html b/examples/solid-calendar.html deleted file mode 100644 index 00aa4c3b23e98316f626f2ad968a3c832fdcaed9..0000000000000000000000000000000000000000 --- a/examples/solid-calendar.html +++ /dev/null @@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta http-equiv="X-UA-Compatible" content="ie=edge" /> - <title>SIB test: solid-calendar</title> - <script type="module" src="../dist/components/solid-calendar.js"></script> - <script> - document.addEventListener('DOMContentLoaded', event => { - document - .querySelector('solid-calendar') - .addEventListener('resourceSelect', event => - console.log(event.detail.resource), - ); - }); - </script> - <style> - solid-calendar { - display: block; - width: 800px; - height: 600px; - border: 1px solid red; - position: relative; - } - .tui-view-7{ - height: 100% !important; - } - </style> - </head> - <body> - <h2>solid-calendar</h2> - <solid-calendar data-src="/examples/data/calendar/events.jsonld"></solid-calendar> - </body> -</html> diff --git a/examples/solid-form-auto-complete.html b/examples/solid-form-auto-complete.html new file mode 100644 index 0000000000000000000000000000000000000000..3589279cf08f500932a21e0f8bab57867244fa91 --- /dev/null +++ b/examples/solid-form-auto-complete.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>SIB test: solid-form auto-complete</title> + <script type="module" src="../dist/index.js"></script> + <link rel="stylesheet" href="styles.css" /> + </head> + + <body> + <h1>Auto complete</h1> + <h2>Single skill</h2> + <solid-form + data-src="/examples/data/list/user-1.jsonld" + fields="skills" + widget-skills="solid-form-dropdown-autocompletion" + range-skills="/examples/data/list/skills.jsonld" + ></solid-form> + <h2>Multiple skills</h2> + <solid-form + data-src="/examples/data/list/user-1.jsonld" + fields="skills" + range-skills="/examples/data/list/skills.jsonld" + multiple-skills="solid-form-multipleselect-autocompletion" + ></solid-form> + + <h2>New Widget Factory</h2> + <script type="module"> + import { newWidgetFactory } from '../../dist/index.js'; + + newWidgetFactory('solid-form-dropdown-autocompletion-placeholder'); + </script> + + <solid-form-dropdown-autocompletion-placeholder + id="test9" + name="test9" + search-placeholder="Skills :" + range="/examples/data/list/skills.jsonld" + ></solid-form-dropdown-autocompletion-placeholder> + </body> +</html> diff --git a/examples/solid-form.html b/examples/solid-form.html index 696c9fb6b2ca5979ee1fc352a053c1fad347ca62..b13ab928c234881632825702fd126997deb4d3f4 100644 --- a/examples/solid-form.html +++ b/examples/solid-form.html @@ -120,7 +120,7 @@ data-src="/examples/data/list/event-1.jsonld" fields="contact" widget-contact="solid-form-dropdown-autocompletion" - range-contact="data/list/users.jsonld" + range-contact="/examples/data/list/skills.jsonld" ></solid-form> <h2>Multiple skills</h2> <solid-form diff --git a/examples/solid-map.html b/examples/solid-map.html deleted file mode 100644 index c746cf378d3bf607fefeb51b73e2938b8c66e876..0000000000000000000000000000000000000000 --- a/examples/solid-map.html +++ /dev/null @@ -1,33 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <meta http-equiv="X-UA-Compatible" content="ie=edge" /> - <title>SIB test: solid-map</title> - <script type="module" src="../dist/index.js"></script> - <script> - document.addEventListener("DOMContentLoaded", event => { - document.querySelector("solid-map").addEventListener("resourceSelect", event => console.log(event.detail.resource)); - }); - </script> - - <link rel="stylesheet" href="styles.css" /> - </head> - - <body> - <h2>Solid Map</h2> - <solid-map - data-src="/examples/data/map/events.jsonld" - fields="infos(name, category)" - group-by="category" - style="display: block; width: 800px; height: 600px;" - ></solid-map> - - <style> - .group-meetup { - border-color: coral; - } - </style> - </body> -</html> diff --git a/examples/styles.css b/examples/styles.css index 812f75b7ba65dd643cca127203dfe2acdf0ddcfd..4b0a6e768699146d1d0f5f038c142722321864dd 100644 --- a/examples/styles.css +++ b/examples/styles.css @@ -44,7 +44,7 @@ solid-route[active] { background-color: #ccc; } -[active]{ +[active] { outline: 2px dotted; } diff --git a/index.html b/index.html index 71adacda37fb78942c391115d536d28c51740f92..ce13ee5c44c2e05b6efa06363d802c27e3b35e6b 100644 --- a/index.html +++ b/index.html @@ -26,8 +26,6 @@ <li><a href="./examples/solid-display.html">solid-display</a></li> <li><a href="./examples/solid-display-server-search.html">solid-display, with server search</a></li> <li><a href="./examples/solid-form.html">solid-form</a></li> - <li><a href="./examples/solid-map.html">solid-map</a></li> - <li><a href="./examples/solid-calendar.html">solid-calendar</a></li> <li><a href="./examples/solid-delete.html">solid-delete</a></li> <li><a href="./examples/solid-ac-checker.html">solid-ac-checker</a></li> <li><a href="./examples/solid-widget.html">solid-widget</a></li> @@ -46,6 +44,7 @@ <li><a href="./examples/nested-form.html">nested-form</a></li> <li><a href="./examples/validation.html">solid-form + confirm or dialog popup</a></li> <li><a href="./examples/auto-range.html">auto-range</a></li> + <li><a href="./examples/solid-form-auto-complete.html">solid-form auto-complete</a></li> </ul> </li> <li> @@ -53,7 +52,6 @@ <ul> <li><a href="./examples/search.html">search</a></li> <li><a href="./examples/filtered.html">filtered-by</a></li> - <li><a href="./examples/filtered-map.html">filtered-by + solid-map</a></li> <li><a href="./examples/pagination.html">pagination</a></li> <li><a href="./examples/counter.html">counter</a></li> <li><a href="./examples/order-by.html">order-by</a></li> diff --git a/package-lock.json b/package-lock.json index bbf27f56cd82e4291cc73e97b85ae22cbed79544..c1bac42d0f61b8ebd609075e3f162e995dfc2965 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,41 +9,192 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "cors": "^2.8.5" + "cors": "^2.8.5", + "lit": "^3.2.1", + "loglevel": "^1.9.1" }, "devDependencies": { + "@biomejs/biome": "1.9.4", "@rckeller/cypress-unfetch": "^1.0.1", "@types/autolinker": "^2.0.0", - "@types/leaflet": "^1.5.21", - "@types/leaflet.markercluster": "^1.4.3", - "@types/markdown-it": "^12.0.1", - "@types/node": "^20.5.0", - "@types/pubsub-js": "^1.8.2", - "@types/quill": "^2.0.4", - "autolinker": "^3.14.2", - "cypress": "^13.2.0", + "@types/jsonld": "^1.5.15", + "@types/markdown-it": "^14.1.2", + "@types/markdown-it-link-attributes": "^3.0.5", + "@types/node": "^22.7.1", + "@types/pubsub-js": "^1.8.6", + "autolinker": "^4.0.0", + "cypress": "^13.14.2", "cypress-plugin-tab": "^1.0.5", - "delta-markdown-for-quill": "0.0.9", "dialog-polyfill": "^0.5.6", - "express": "^4.17.1", + "express": "^4.21.0", "find-free-port": "^2.0.0", - "fuse.js": "^6.4.6", - "jsonld": "^8.3.1", + "fuse.js": "^7.0.0", + "jsonld": "^8.3.2", "jsonld-context-parser": "^1.3.4", - "leaflet": "1.7.1", - "leaflet.markercluster": "1.5.3", - "lit-html": "^1.3.0", - "markdown-it": "^12.0.4", + "markdown-it": "^14.1.0", "markdown-it-link-attributes": "4.0.1", - "markdown-to-quill-delta": "^0.7.0", - "pubsub-js": "^1.9.2", - "quill": "^1.3.7", + "pubsub-js": "^1.9.4", + "quill": "^2.0.3", "quill-delta-to-markdown": "^0.6.0", - "semver": "7.5.4", - "slim-select": "^1.27.0", - "tui-calendar": "^1.13.0", - "typescript": "^4.9.5", - "vite": "^5.0.12" + "semver": "7.6.3", + "slim-select": "^2.9.2", + "typescript": "^5.6.2", + "vite": "^5.4.8" + } + }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" } }, "node_modules/@colors/colors": { @@ -57,9 +208,9 @@ } }, "node_modules/@cypress/request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", - "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", + "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", @@ -68,16 +219,16 @@ "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", + "form-data": "~4.0.0", + "http-signature": "~1.4.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.10.4", + "qs": "6.13.0", "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" }, @@ -85,21 +236,6 @@ "node": ">= 6" } }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@cypress/xvfb": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", @@ -134,9 +270,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", "cpu": [ "ppc64" ], @@ -150,9 +286,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", "cpu": [ "arm" ], @@ -166,9 +302,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", "cpu": [ "arm64" ], @@ -182,9 +318,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", "cpu": [ "x64" ], @@ -198,9 +334,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", "cpu": [ "arm64" ], @@ -214,9 +350,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", "cpu": [ "x64" ], @@ -230,9 +366,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", "cpu": [ "arm64" ], @@ -246,9 +382,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", "cpu": [ "x64" ], @@ -262,9 +398,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", "cpu": [ "arm" ], @@ -278,9 +414,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", "cpu": [ "arm64" ], @@ -294,9 +430,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", "cpu": [ "ia32" ], @@ -310,9 +446,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", "cpu": [ "loong64" ], @@ -326,9 +462,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", "cpu": [ "mips64el" ], @@ -342,9 +478,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", "cpu": [ "ppc64" ], @@ -358,9 +494,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", "cpu": [ "riscv64" ], @@ -374,9 +510,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", "cpu": [ "s390x" ], @@ -390,9 +526,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -406,9 +542,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", "cpu": [ "x64" ], @@ -422,9 +558,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", "cpu": [ "x64" ], @@ -438,9 +574,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", "cpu": [ "x64" ], @@ -454,9 +590,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", "cpu": [ "arm64" ], @@ -470,9 +606,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", "cpu": [ "ia32" ], @@ -486,9 +622,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", "cpu": [ "x64" ], @@ -580,6 +716,19 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz", + "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==" + }, + "node_modules/@lit/reactive-element": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0" + } + }, "node_modules/@rckeller/cypress-unfetch": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rckeller/cypress-unfetch/-/cypress-unfetch-1.0.1.tgz", @@ -590,9 +739,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", - "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", "cpu": [ "arm" ], @@ -603,9 +752,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", - "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", "cpu": [ "arm64" ], @@ -616,9 +765,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", - "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", + "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", "cpu": [ "arm64" ], @@ -629,9 +778,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", - "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", "cpu": [ "x64" ], @@ -641,10 +790,49 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", - "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", "cpu": [ "arm" ], @@ -655,9 +843,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", - "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", "cpu": [ "arm64" ], @@ -668,9 +856,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", - "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", "cpu": [ "arm64" ], @@ -680,10 +868,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", - "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", "cpu": [ "riscv64" ], @@ -693,10 +894,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", - "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", "cpu": [ "x64" ], @@ -707,9 +921,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", - "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", "cpu": [ "x64" ], @@ -720,9 +934,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", - "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", "cpu": [ "arm64" ], @@ -733,9 +947,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", - "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", "cpu": [ "ia32" ], @@ -746,9 +960,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", - "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", "cpu": [ "x64" ], @@ -768,104 +982,66 @@ "autolinker": "*" } }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "dependencies": { - "@types/ms": "*" - } - }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/geojson": { - "version": "7946.0.10", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", - "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, - "node_modules/@types/leaflet": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.3.tgz", - "integrity": "sha512-Caa1lYOgKVqDkDZVWkto2Z5JtVo09spEaUt2S69LiugbBpoqQu92HYFMGUbYezZbnBkyOxMNPXHSgRrRY5UyIA==", - "dev": true, - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/leaflet.markercluster": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/leaflet.markercluster/-/leaflet.markercluster-1.5.1.tgz", - "integrity": "sha512-gzJzP10qO6Zkts5QNVmSAEDLYicQHTEBLT9HZpFrJiSww9eDAs5OWHvIskldf41MvDv1gbMukuEBQEawHn+wtA==", + "node_modules/@types/jsonld": { + "version": "1.5.15", + "resolved": "https://registry.npmjs.org/@types/jsonld/-/jsonld-1.5.15.tgz", + "integrity": "sha512-PlAFPZjL+AuGYmwlqwKEL0IMP8M8RexH0NIPGfCVWSQ041H2rR/8OlyZSD7KsCVoN8vCfWdtWDBxX8yBVP+xow==", "dev": true, - "dependencies": { - "@types/leaflet": "*" - } + "license": "MIT" }, "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "dev": true }, "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "dev": true, "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/@types/mdast": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", - "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "node_modules/@types/markdown-it-link-attributes": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/markdown-it-link-attributes/-/markdown-it-link-attributes-3.0.5.tgz", + "integrity": "sha512-VZ2BGN3ywUg7mBD8W6PwR8ChpOxaQSBDbLqPgvNI+uIra3zY2af1eG/3XzWTKjEraTWskMKnZqZd6m1fDF67Bg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/unist": "^2" + "@types/markdown-it": "*" } }, "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", - "dev": true - }, - "node_modules/@types/ms": { - "version": "0.7.34", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", - "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true }, "node_modules/@types/node": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", - "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", - "dev": true - }, - "node_modules/@types/pubsub-js": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@types/pubsub-js/-/pubsub-js-1.8.3.tgz", - "integrity": "sha512-6BqY04dh2UV1dNV690tyJVJYQ0U6qBH4tU+FCwY1Mhl8jOPOP9qiIvgLnB59cVik/E6/R002oXZpGiDm+2C8eA==", - "dev": true - }, - "node_modules/@types/quill": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/quill/-/quill-2.0.10.tgz", - "integrity": "sha512-L6OHONEj2v4NRbWQOsn7j1N0SyzhRR3M4g1M6j/uuIwIsIW2ShWHhwbqNvH8hSmVktzqu0lITfdnqVOQ4qkrhA==", + "version": "22.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", + "integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==", "dev": true, "dependencies": { - "parchment": "^1.1.2", - "quill-delta": "^4.0.1" + "undici-types": "~6.20.0" } }, + "node_modules/@types/pubsub-js": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@types/pubsub-js/-/pubsub-js-1.8.6.tgz", + "integrity": "sha512-Kwug5cwV0paUDm/NfwDx1sp9xI0bGIvmWJjJWCU8NngkCCMt3EIC7oPDvb6fV7BR8kPpFyyBu4D11bda/2MdPA==", + "dev": true + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -878,11 +1054,10 @@ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", "dev": true }, - "node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "dev": true + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, "node_modules/@types/yauzl": { "version": "2.10.0", @@ -1070,9 +1245,9 @@ } }, "node_modules/autolinker": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.16.2.tgz", - "integrity": "sha512-JiYl7j2Z19F9NdTmirENSUUIIL/9MytEWtmzhfmsKPCp9E+G35Y0UNCMoM9tFigxT59qSc8Ml2dlZXOCVTYwuA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-4.0.0.tgz", + "integrity": "sha512-fl5Kh6BmEEZx+IWBfEirnRUU5+cOiV0OK7PEt0RBKvJMJ8GaRseIOeDU3FKf4j3CE5HVefcjHmhYPOcaVt0bZw==", "dev": true, "dependencies": { "tslib": "^2.3.0" @@ -1088,25 +1263,9 @@ } }, "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, "node_modules/base64-js": { @@ -1150,16 +1309,45 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1220,14 +1408,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1245,26 +1438,6 @@ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -1275,9 +1448,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", + "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", "dev": true, "funding": [ { @@ -1341,15 +1514,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -1377,30 +1541,6 @@ "node": ">=4.0.0" } }, - "node_modules/commonmark": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.26.0.tgz", - "integrity": "sha512-0PvjGTgkIjIdImgpt1xgR049Nyz/x27vhYT+C0ZkNuxEiys/lJZKotOVKa4y7JbtMsTutg/gCLH+13DFnaOjWg==", - "dev": true, - "dependencies": { - "entities": "~ 1.1.1", - "mdurl": "~ 1.0.1", - "minimist": "~ 1.2.0", - "string.prototype.repeat": "^0.2.0" - }, - "bin": { - "commonmark": "bin/commonmark" - }, - "engines": { - "node": "*" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1423,9 +1563,9 @@ } }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "engines": { "node": ">= 0.6" @@ -1437,6 +1577,12 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -1470,24 +1616,24 @@ "dev": true }, "node_modules/cypress": { - "version": "13.5.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.5.1.tgz", - "integrity": "sha512-yqLViT0D/lPI8Kkm7ciF/x/DCK/H/DnogdGyiTnQgX4OVR2aM30PtK+kvklTOD1u3TuItiD9wUQAF8EYWtyZug==", + "version": "13.16.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz", + "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==", "dev": true, "hasInstallScript": true, "dependencies": { - "@cypress/request": "^3.0.0", + "@cypress/request": "^3.0.6", "@cypress/xvfb": "^1.2.4", - "@types/node": "^18.17.5", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", "arch": "^2.2.0", "blob-util": "^2.0.2", "bluebird": "^3.7.2", - "buffer": "^5.6.0", + "buffer": "^5.7.1", "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", + "ci-info": "^4.0.0", "cli-cursor": "^3.1.0", "cli-table3": "~0.6.1", "commander": "^6.2.1", @@ -1502,7 +1648,6 @@ "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", - "is-ci": "^3.0.0", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", @@ -1516,7 +1661,8 @@ "request-progress": "^3.0.0", "semver": "^7.5.3", "supports-color": "^8.1.1", - "tmp": "~0.2.1", + "tmp": "~0.2.3", + "tree-kill": "1.2.2", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, @@ -1536,15 +1682,6 @@ "ally.js": "^1.4.1" } }, - "node_modules/cypress/node_modules/@types/node": { - "version": "18.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.11.tgz", - "integrity": "sha512-c1vku6qnTeujJneYH94/4aq73XrVcsJe35UPyAsSok1ijiKrkRzK+AxQPSpNMUnC03roWBBwJx/9I8V7lQoxmA==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/cypress/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -1683,59 +1820,15 @@ } } }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dev": true, - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1753,37 +1846,6 @@ "node": ">=0.4.0" } }, - "node_modules/delta-markdown-for-quill": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/delta-markdown-for-quill/-/delta-markdown-for-quill-0.0.9.tgz", - "integrity": "sha512-Pb6LjAey0I1N5od660V3cisq7XBRK1VOS7ctJbm6z98fNRj1w6Kd0HT8Boqvsue42FfQ0+6UVfwFXyug8THKLA==", - "dev": true, - "dependencies": { - "commonmark": "^0.26.0", - "lodash": "^4.16.4", - "quill-delta": "^3.4.0" - } - }, - "node_modules/delta-markdown-for-quill/node_modules/fast-diff": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", - "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", - "dev": true - }, - "node_modules/delta-markdown-for-quill/node_modules/quill-delta": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", - "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", - "dev": true, - "dependencies": { - "deep-equal": "^1.0.1", - "extend": "^3.0.2", - "fast-diff": "1.1.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1793,15 +1855,6 @@ "node": ">= 0.8" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -1818,21 +1871,6 @@ "integrity": "sha512-ZbVDJI9uvxPAKze6z146rmfUZjBqNEwcnFTVamQzXH+svluiV7swmVIGr7miwADgfgt1G2JQIytypM9fbyhX4w==", "dev": true }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dompurify": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.7.tgz", - "integrity": "sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ==", - "dev": true - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1856,9 +1894,9 @@ "dev": true }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "engines": { "node": ">= 0.8" @@ -1907,16 +1945,31 @@ "node": ">=8.6" } }, - "node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } }, "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -1926,29 +1979,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/escape-html": { @@ -1991,9 +2044,9 @@ "dev": true }, "node_modules/eventemitter3": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true }, "node_modules/execa": { @@ -2032,37 +2085,37 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -2073,30 +2126,6 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2112,21 +2141,6 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2162,12 +2176,6 @@ "node >=0.6.0" ] }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -2216,13 +2224,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -2264,17 +2272,17 @@ } }, "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, "node_modules/formdata-polyfill": { @@ -2322,12 +2330,6 @@ "node": ">=10" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2351,35 +2353,30 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/fuse.js": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", - "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz", + "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2417,26 +2414,6 @@ "assert-plus": "^1.0.0" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -2471,12 +2448,12 @@ "dev": true }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2506,21 +2483,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -2550,14 +2512,14 @@ } }, "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", + "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "sshpk": "^1.18.0" }, "engines": { "node": ">=0.10" @@ -2613,16 +2575,6 @@ "node": ">=8" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2647,72 +2599,6 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2747,34 +2633,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -2900,15 +2758,6 @@ "verror": "1.10.0" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ky": { "version": "0.33.3", "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", @@ -2973,28 +2822,13 @@ "node": "> 0.8" } }, - "node_modules/leaflet": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.7.1.tgz", - "integrity": "sha512-/xwPEBidtg69Q3HlqPdU3DnrXQOvQU/CCHA1tcDQVzOwm91YMYaILjNp7L4Eaw5Z4sOYdbBz6koWyibppd8Zqw==", - "dev": true - }, - "node_modules/leaflet.markercluster": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", - "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", - "dev": true, - "peerDependencies": { - "leaflet": "^1.3.1" - } - }, "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/listr2": { @@ -3024,11 +2858,33 @@ } } }, + "node_modules/lit": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz", + "integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==", + "dependencies": { + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.1.0", + "lit-html": "^3.2.0" + } + }, + "node_modules/lit-element": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz", + "integrity": "sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.2.0" + } + }, "node_modules/lit-html": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.4.1.tgz", - "integrity": "sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.1.tgz", + "integrity": "sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } }, "node_modules/lodash": { "version": "4.17.21", @@ -3036,6 +2892,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -3222,14 +3084,16 @@ "node": ">=8" } }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "dev": true, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "engines": { + "node": ">= 0.6.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" } }, "node_modules/lru-cache": { @@ -3245,19 +3109,20 @@ } }, "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, "dependencies": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdown-it-link-attributes": { @@ -3267,234 +3132,21 @@ "dev": true }, "node_modules/markdown-it/node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/markdown-to-quill-delta": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/markdown-to-quill-delta/-/markdown-to-quill-delta-0.7.0.tgz", - "integrity": "sha512-FLBUAd8vW7vuUR0hu1I8+8+meJQ3B+Jk5NsxFkJ4WE4g6zj8PrvPj+rLV11SZqEQ3J3kaUoBSxgJR7zMcokfgQ==", - "dev": true, - "dependencies": { - "quill-delta": "^4.1.0", - "remark-gfm": "^3.0.1", - "remark-parse": "^10.0.1", - "unified": "^10.1.2", - "unist-util-visit": "^4.1.0" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", - "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", - "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "mdast-util-to-string": "^3.1.0", - "micromark": "^3.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-decode-string": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "unist-util-stringify-position": "^3.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", - "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", - "dev": true, - "dependencies": { - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-gfm-autolink-literal": "^1.0.0", - "mdast-util-gfm-footnote": "^1.0.0", - "mdast-util-gfm-strikethrough": "^1.0.0", - "mdast-util-gfm-table": "^1.0.0", - "mdast-util-gfm-task-list-item": "^1.0.0", - "mdast-util-to-markdown": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", - "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "ccount": "^2.0.0", - "mdast-util-find-and-replace": "^2.0.0", - "micromark-util-character": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", - "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0", - "micromark-util-normalize-identifier": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", - "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", - "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "mdast-util-to-markdown": "^1.3.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", - "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-to-markdown": "^1.3.0" + "node": ">=0.12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", - "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", - "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^3.0.0", - "mdast-util-to-string": "^3.0.0", - "micromark-util-decode-string": "^1.0.0", - "unist-util-visit": "^4.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", - "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "node_modules/markdown-it/node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, "node_modules/media-typer": { @@ -3507,10 +3159,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -3527,569 +3182,6 @@ "node": ">= 0.6" } }, - "node_modules/micromark": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", - "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "micromark-core-commonmark": "^1.0.1", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz", - "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-factory-destination": "^1.0.0", - "micromark-factory-label": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-factory-title": "^1.0.0", - "micromark-factory-whitespace": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-html-tag-name": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-subtokenize": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.1", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", - "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", - "dev": true, - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^1.0.0", - "micromark-extension-gfm-footnote": "^1.0.0", - "micromark-extension-gfm-strikethrough": "^1.0.0", - "micromark-extension-gfm-table": "^1.0.0", - "micromark-extension-gfm-tagfilter": "^1.0.0", - "micromark-extension-gfm-task-list-item": "^1.0.0", - "micromark-util-combine-extensions": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", - "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", - "dev": true, - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", - "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", - "dev": true, - "dependencies": { - "micromark-core-commonmark": "^1.0.0", - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-normalize-identifier": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", - "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", - "dev": true, - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-classify-character": "^1.0.0", - "micromark-util-resolve-all": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", - "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", - "dev": true, - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", - "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", - "dev": true, - "dependencies": { - "micromark-util-types": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", - "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", - "dev": true, - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz", - "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz", - "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", - "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz", - "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz", - "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-factory-space": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", - "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz", - "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz", - "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz", - "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz", - "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz", - "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^1.0.0", - "micromark-util-decode-numeric-character-reference": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz", - "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-html-tag-name": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz", - "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz", - "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz", - "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-types": "^1.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz", - "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-character": "^1.0.0", - "micromark-util-encode": "^1.0.0", - "micromark-util-symbol": "^1.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz", - "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "dependencies": { - "micromark-util-chunked": "^1.0.0", - "micromark-util-symbol": "^1.0.0", - "micromark-util-types": "^1.0.0", - "uvu": "^0.5.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", - "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, - "node_modules/micromark-util-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", - "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ] - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -4129,19 +3221,7 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": ">=6" } }, "node_modules/minimist": { @@ -4153,15 +3233,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4169,9 +3240,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -4254,23 +3325,10 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, "engines": { "node": ">= 0.4" }, @@ -4278,15 +3336,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -4344,12 +3393,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parchment": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", - "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", - "dev": true - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -4359,15 +3402,6 @@ "node": ">= 0.8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4378,9 +3412,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, "node_modules/pend": { @@ -4396,9 +3430,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "node_modules/pify": { @@ -4417,9 +3451,9 @@ "dev": true }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -4437,8 +3471,8 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -4484,12 +3518,6 @@ "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/pubsub-js": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/pubsub-js/-/pubsub-js-1.9.4.tgz", @@ -4506,22 +3534,22 @@ "once": "^1.3.1" } }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -4530,35 +3558,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, "node_modules/quill": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", - "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", - "dev": true, - "dependencies": { - "clone": "^2.1.1", - "deep-equal": "^1.0.1", - "eventemitter3": "^2.0.3", - "extend": "^3.0.2", - "parchment": "^1.1.4", - "quill-delta": "^3.6.2" - } - }, - "node_modules/quill-delta": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-4.2.2.tgz", - "integrity": "sha512-qjbn82b/yJzOjstBgkhtBjN2TNK+ZHP/BgUQO+j6bRhWQQdmj2lH6hXG7+nwwLF41Xgn//7/83lxs9n2BkTtTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", "dev": true, "dependencies": { - "fast-diff": "1.2.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" } }, "node_modules/quill-delta-to-markdown": { @@ -4574,23 +3586,29 @@ } }, "node_modules/quill/node_modules/fast-diff": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", - "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/quill/node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", "dev": true }, "node_modules/quill/node_modules/quill-delta": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", - "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", "dev": true, "dependencies": { - "deep-equal": "^1.0.1", - "extend": "^3.0.2", - "fast-diff": "1.1.2" + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" }, "engines": { - "node": ">=0.10" + "node": ">= 12.0.0" } }, "node_modules/range-parser": { @@ -4602,33 +3620,31 @@ "node": ">= 0.6" } }, - "node_modules/rdf-canonize": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", - "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { - "setimmediate": "^1.0.5" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/rdf-canonize": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", + "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "setimmediate": "^1.0.5" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, "node_modules/relative-to-absolute-iri": { @@ -4637,37 +3653,6 @@ "integrity": "sha512-Xjyl4HmIzg2jzK/Un2gELqbcE8Fxy85A/aLSHE6PE/3+OGsFwmKVA1vRyGaz6vLWSqLDMHA+5rjD/xbibSQN1Q==", "dev": true }, - "node_modules/remark-gfm": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", - "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-gfm": "^2.0.0", - "micromark-extension-gfm": "^2.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", - "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "mdast-util-from-markdown": "^1.0.0", - "unified": "^10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", @@ -4677,12 +3662,6 @@ "throttleit": "^1.0.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -4702,28 +3681,13 @@ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "dev": true }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", - "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", "dev": true, "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -4733,19 +3697,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.6", - "@rollup/rollup-android-arm64": "4.9.6", - "@rollup/rollup-darwin-arm64": "4.9.6", - "@rollup/rollup-darwin-x64": "4.9.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", - "@rollup/rollup-linux-arm64-gnu": "4.9.6", - "@rollup/rollup-linux-arm64-musl": "4.9.6", - "@rollup/rollup-linux-riscv64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-musl": "4.9.6", - "@rollup/rollup-win32-arm64-msvc": "4.9.6", - "@rollup/rollup-win32-ia32-msvc": "4.9.6", - "@rollup/rollup-win32-x64-msvc": "4.9.6", + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", "fsevents": "~2.3.2" } }, @@ -4758,18 +3727,6 @@ "tslib": "^2.1.0" } }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4797,13 +3754,10 @@ "dev": true }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -4812,9 +3766,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", @@ -4850,6 +3804,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4857,31 +3820,32 @@ "dev": true }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/set-function-length": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", - "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "define-data-property": "^1.1.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4921,14 +3885,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4988,13 +3956,10 @@ "dev": true }, "node_modules/slim-select": { - "version": "1.27.1", - "resolved": "https://registry.npmjs.org/slim-select/-/slim-select-1.27.1.tgz", - "integrity": "sha512-LvJ02cKKk6/jSHIcQv7dZwkQSXHLCVQR3v3lo8RJUssUUcmKPkpBmTpQ8au8KSMkxwca9+yeg+dO0iHAaVr5Aw==", - "dev": true, - "engines": { - "node": ">=8" - } + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/slim-select/-/slim-select-2.10.0.tgz", + "integrity": "sha512-sOKXH8YlgspTn+wy1jYbscVlFbBsAIOmtrmx1e16sV+NbYDTIyJCCdLH0EL9gDxDdHzBgE/s5XZ+VChaxz0JGg==", + "dev": true }, "node_modules/source-map": { "version": "0.6.1", @@ -5008,9 +3973,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -5076,12 +4041,6 @@ "node": ">=8" } }, - "node_modules/string.prototype.repeat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", - "integrity": "sha512-1BH+X+1hSthZFW+X+JaUkjkkUPwIlLEMJBLANN3hOob3RhEk5snLWNECDnYbgn/m5c5JV7Ersu1Yubaf+05cIA==", - "dev": true - }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5143,16 +4102,31 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "node_modules/tldts": { + "version": "6.1.64", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.64.tgz", + "integrity": "sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw==", "dev": true, "dependencies": { - "rimraf": "^3.0.0" + "tldts-core": "^6.1.64" }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.64", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.64.tgz", + "integrity": "sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/toidentifier": { @@ -5165,37 +4139,24 @@ } }, "node_modules/tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "dev": true, "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "bin": { + "tree-kill": "cli.js" } }, "node_modules/tslib": { @@ -5204,39 +4165,6 @@ "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==", "dev": true }, - "node_modules/tui-calendar": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/tui-calendar/-/tui-calendar-1.15.3.tgz", - "integrity": "sha512-S+QxtSPunLUNIX/eHoHcBB9XlPVT15Wh6ItR62n5K/Gq3WeSQdyhdbsuZJYV9z75bgJbFzp6x32v2yEPm6iWrg==", - "dev": true, - "dependencies": { - "dompurify": "^2.3.1", - "tui-code-snippet": "^1.5.0", - "tui-date-picker": "^4.3.0", - "tui-time-picker": "^2.1.4" - } - }, - "node_modules/tui-code-snippet": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/tui-code-snippet/-/tui-code-snippet-1.5.2.tgz", - "integrity": "sha512-6UqTlQaaC1KLcmC0HAoq5dtl1G4Fib+R+NC7pmaV7kiIlZ7JqKhUmnOoGRcreAyzd81UTK/vCvhrw9QJskpCFQ==", - "dev": true - }, - "node_modules/tui-date-picker": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/tui-date-picker/-/tui-date-picker-4.3.3.tgz", - "integrity": "sha512-/2YoLnj5c1e+Ag1ZZYOgzEs2o0v7Ol7c5UAnBj438zGlkwkMxyH0HwP2pVqqIYX05WE7K0+6nTWVMybS8otBgw==", - "dev": true, - "dependencies": { - "tui-time-picker": "^2.1.6" - } - }, - "node_modules/tui-time-picker": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/tui-time-picker/-/tui-time-picker-2.1.6.tgz", - "integrity": "sha512-4Jmo3wjGS+Ii4/qQgt5DaFEohHpB3U6BzWeTODVVFHD9sx3NOsbomY9K0xMobSLODi+tQEH7wfOtNU0IJmcQ6Q==", - "dev": true - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5281,22 +4209,22 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true }, "node_modules/undici": { @@ -5312,9 +4240,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true }, "node_modules/unfetch": { @@ -5323,80 +4251,6 @@ "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", "dev": true }, - "node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", - "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.1.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", - "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -5424,16 +4278,6 @@ "node": ">=8" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -5452,24 +4296,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -5492,51 +4318,15 @@ "extsprintf": "^1.2.0" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/vite": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", - "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.32", - "rollup": "^4.2.0" + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -5555,6 +4345,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -5572,6 +4363,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -5684,16 +4478,6 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } } } } diff --git a/package.json b/package.json index 22e33da36d43c814e04fe0be4372475fa03b92dd..c50bd5459c6298d5413f8441d05b97ca2d7ff29e 100644 --- a/package.json +++ b/package.json @@ -8,14 +8,14 @@ "directories": { "example": "examples" }, - "files": [ - "dist", - "doc" - ], + "files": ["dist", "doc"], "scripts": { "build": "vite build", - "watch": "vite build --watch", + "watch": "vite build --watch --sourcemap 'inline'", "serve": "node --watch server.js", + "lint": "biome check --diagnostic-level=error", + "lint-all": "biome check", + "lint-fix": "biome check --write", "check-types": "tsc", "test": "node server.js --test", "cypress": "node server.js --test-ui", @@ -65,40 +65,36 @@ "access": "public" }, "devDependencies": { + "@biomejs/biome": "1.9.4", "@rckeller/cypress-unfetch": "^1.0.1", "@types/autolinker": "^2.0.0", - "@types/leaflet": "^1.5.21", - "@types/leaflet.markercluster": "^1.4.3", - "@types/markdown-it": "^12.0.1", - "@types/node": "^20.5.0", - "@types/pubsub-js": "^1.8.2", - "@types/quill": "^2.0.4", - "autolinker": "^3.14.2", - "cypress": "^13.2.0", + "@types/jsonld": "^1.5.15", + "@types/markdown-it": "^14.1.2", + "@types/markdown-it-link-attributes": "^3.0.5", + "@types/node": "^22.7.1", + "@types/pubsub-js": "^1.8.6", + "autolinker": "^4.0.0", + "cypress": "^13.14.2", "cypress-plugin-tab": "^1.0.5", - "delta-markdown-for-quill": "0.0.9", "dialog-polyfill": "^0.5.6", - "express": "^4.17.1", + "express": "^4.21.0", "find-free-port": "^2.0.0", - "fuse.js": "^6.4.6", - "jsonld": "^8.3.1", + "fuse.js": "^7.0.0", + "jsonld": "^8.3.2", "jsonld-context-parser": "^1.3.4", - "leaflet": "1.7.1", - "leaflet.markercluster": "1.5.3", - "lit-html": "^1.3.0", - "markdown-it": "^12.0.4", + "markdown-it": "^14.1.0", "markdown-it-link-attributes": "4.0.1", - "markdown-to-quill-delta": "^0.7.0", - "pubsub-js": "^1.9.2", - "quill": "^1.3.7", + "pubsub-js": "^1.9.4", + "quill": "^2.0.3", "quill-delta-to-markdown": "^0.6.0", - "semver": "7.5.4", - "slim-select": "^1.27.0", - "tui-calendar": "^1.13.0", - "typescript": "^4.9.5", - "vite": "^5.0.12" + "semver": "7.6.3", + "slim-select": "^2.9.2", + "typescript": "^5.6.2", + "vite": "^5.4.8" }, "dependencies": { - "cors": "^2.8.5" + "cors": "^2.8.5", + "lit": "^3.2.1", + "loglevel": "^1.9.1" } } diff --git a/server.js b/server.js index 3f08c387985beaf982fc5479a3d839703647f386..ce97cb81a922cca40e9eb6fc334776dbf5377d35 100644 --- a/server.js +++ b/server.js @@ -1,22 +1,25 @@ -import crypto from 'crypto'; +// @ts-check + +import crypto from 'node:crypto'; +import fs from 'node:fs/promises'; +import path from 'node:path'; +import url from 'node:url'; +import cors from 'cors'; import cypress from 'cypress'; -import url from 'url'; -import path from 'path'; import express from 'express'; import findFreePort from 'find-free-port'; -import fs from 'fs/promises'; -import cors from 'cors'; const port = findFreePort(3000); const app = express(); const distPath = '.'; - app.use(cors()); +// Set the browser language to English to ensure consistent test conditions. +process.env.ELECTRON_EXTRA_LAUNCH_ARGS = '--lang=en'; (async () => { const updateURLs = /.*jsonld/; const server = app .use(express.static(distPath)) .use(express.json({ type: 'application/*+json' })) - .get('/favicon.ico', (req, rep) => rep.send()) + .get('/favicon.ico', (_req, rep) => void rep.send()) // Handle upload .post('/upload', (req, rep) => { const originalUrl = url.format({ @@ -27,28 +30,28 @@ app.use(cors()); rep.setHeader('location', `${originalUrl}/${uniqID()}.jpg`); setTimeout(() => rep.send(), 1200); }) - .get(/^\/upload\/.+/, (req, rep) => { + .get(/^\/upload\/.+/, (_req, rep) => { rep.sendFile(path.resolve('./fake-image.svg')); }) .get('/mock/users.jsonld', async (req, res) => { const limit = Number(req.query.limit); const offset = Number(req.query.offset); - const val = req.query['search-terms'] || ''; + const val = String(req.query['search-terms'] || ''); const jsonData = await fs.readFile( './examples/data/list/users-mocked.jsonld', - { encoding: 'utf8' } + { encoding: 'utf8' }, ); const data = JSON.parse(jsonData); - const list = data['ldp:contains'].filter((user) => - user['first_name'].toLowerCase().includes(val.toLowerCase()) + const list = data['ldp:contains'].filter(user => + user.first_name.toLowerCase().includes(val.toLowerCase()), ); data['ldp:contains'] = limit ? list.slice(offset, offset + limit) : list; res.send(data); res.end(); }) - .get('/examples/', (req, rep) => rep.redirect('/')) + .get('/examples/', (_req, rep) => rep.redirect('/')) // Listen for write requests .patch(updateURLs, handleUpdate) .post(updateURLs, handleUpdate) @@ -64,13 +67,17 @@ app.use(cors()); console.log(addr); return; } + /** @type {Partial<CypressCommandLine.CypressOpenOptions>}) */ + const opt = { + testingType: 'e2e', + browser: 'electron', + config: { + e2e: { baseUrl: addr }, + }, + }; + /** @type {void | undefined | CypressCommandLine.CypressRunResult | CypressCommandLine.CypressFailedRunResult} */ let test; try { - const opt = { - config: { - baseUrl: addr, - }, - }; test = process.argv.includes('--test-ui') ? await cypress.open(opt) : await cypress.run(opt); @@ -78,7 +85,7 @@ app.use(cors()); console.error(error); } finally { server.close(); - if (test.totalFailed) { + if (test && 'totalFailed' in test && test.totalFailed > 0) { process.exit(1); } } @@ -95,7 +102,7 @@ function uniqID() { } function handleUpdate(req, rep) { - if (req.headers['content-type'] != 'application/ld+json') { + if (req.headers['content-type'] !== 'application/ld+json') { rep.status(500).send('Content not JSON'); return; } diff --git a/src/components/solid-ac-checker.ts b/src/components/solid-ac-checker.ts index 4f5d1034debd7f867e800acc6d51ef5827ae3830..745c9e28f0aaed8bd61dfeda5ba70c7ebefb196f 100644 --- a/src/components/solid-ac-checker.ts +++ b/src/components/solid-ac-checker.ts @@ -1,6 +1,7 @@ import JSONLDContextParser from 'jsonld-context-parser'; -import { Sib } from '../libs/Sib'; -import { StoreMixin } from '../mixins/storeMixin'; +import { Sib } from '../libs/Sib.ts'; +import { trackRenderAsync } from '../logger.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; export const SolidAcChecker = { name: 'solid-ac-checker', @@ -13,32 +14,40 @@ export const SolidAcChecker = { noPermission: { type: String, default: '', - } + }, }, - - async populate(): Promise<void> { + populate: trackRenderAsync(async function (): Promise<void> { if (!this.resource) return; let displayElement: boolean; const ContextParser = JSONLDContextParser.ContextParser; const permissions = await this.resource.permissions; - if (this.permission) { // User has permission of ... - displayElement = permissions.some((p:any) => { - return ContextParser.expandTerm(p, this.context, true) === this.permission; + if (this.permission) { + // User has permission of ... + displayElement = permissions.some((p: any) => { + return ( + ContextParser.expandTerm(p, this.context, true) === this.permission + ); }); - } else if (this.noPermission) { // User has no permission of ... - displayElement = permissions.every((p:any) => { - return ContextParser.expandTerm(p, this.context, true) !== this.noPermission; + } else if (this.noPermission) { + // User has no permission of ... + displayElement = permissions.every((p: any) => { + return ( + ContextParser.expandTerm(p, this.context, true) !== this.noPermission + ); }); - } else { // No parameter provided - console.warn('solid-ac-checker: you should define at least one of "permission" or "no-permission" attribute.'); + } else { + // No parameter provided + console.warn( + 'solid-ac-checker: you should define at least one of "permission" or "no-permission" attribute.', + ); return; } if (displayElement) this.element.removeAttribute('hidden'); - }, + }, 'SolidAcChecker:populate'), empty(): void { this.element.setAttribute('hidden', ''); - } + }, }; -Sib.register(SolidAcChecker); \ No newline at end of file +Sib.register(SolidAcChecker); diff --git a/src/components/solid-calendar.ts b/src/components/solid-calendar.ts deleted file mode 100644 index ea14e232bf4afe78941e5e6172af9896014813b1..0000000000000000000000000000000000000000 --- a/src/components/solid-calendar.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Sib } from '../libs/Sib'; -import { ListMixin } from '../mixins/listMixin'; -import { StoreMixin } from '../mixins/storeMixin'; -import { NextMixin } from '../mixins/nextMixin'; -import { store } from '../libs/store/store'; -import { importInlineCSS, uniqID } from '../libs/helpers'; - -import Calendar from 'tui-calendar'; -import { html, render } from 'lit-html'; - -export const SolidCalendar = { - name: 'solid-calendar', - use: [ - ListMixin, - StoreMixin, - NextMixin - ], - initialState: { - subscriptions: null - }, - created(): void { - importInlineCSS('tui-calendar', () => import('tui-calendar/dist/tui-calendar.css?inline')) - - const id = uniqID(); - const template = html` - <div id=${id} style="width:100%;height:100%;"></div> - `; - render(template, this.element); - this.calendar = new Calendar(this.element.querySelector(`#${id}`), { defaultView: 'month' }); - this.calendar.on('clickSchedule', this.dispatchSelect.bind(this)); - this.subscriptions = new Map(); - }, - get extra_context(): object { - return { date: "http://www.w3.org/2001/XMLSchema#dateTime" } - }, - dispatchSelect(event: Event): void { - const resource = { '@id': event['schedule'].id }; - this.element.dispatchEvent( - new CustomEvent('resourceSelect', { detail: { resource: resource } }), - ); - this.goToNext(resource); - }, - async appendChildElt(resourceId: string) { - const resource = await store.getData(resourceId, this.context); - if(!resource) return; - if (!this.subscriptions.get(resourceId)) { - this.subscriptions.set(resourceId, PubSub.subscribe(resourceId, () => this.updateDOM())) - } // TODO : mixin gestion des enfants - const date = await resource['date']; - const name = await resource['name']; - - if (name && date) { - this.calendar.createSchedules([ - { - id: resource['@id'], - title: name.toString(), - category: 'time', - start: date.toString(), - }, - ]); - } - }, - empty(): void { - this.calendar.clear(); - } -}; - -Sib.register(SolidCalendar); \ No newline at end of file diff --git a/src/components/solid-delete.ts b/src/components/solid-delete.ts index b6797de2daeec17ca2fe5210931e6e4864b7e16d..796614951852448dba65d885f57143320de99a41 100644 --- a/src/components/solid-delete.ts +++ b/src/components/solid-delete.ts @@ -1,11 +1,12 @@ -import { Sib } from '../libs/Sib'; -import { store } from '../libs/store/store'; -import { NextMixin } from '../mixins/nextMixin'; -import { ValidationMixin } from '../mixins/validationMixin'; -import { AttributeBinderMixin } from '../mixins/attributeBinderMixin'; +import { Sib } from '../libs/Sib.ts'; +import { store } from '../libs/store/store.ts'; +import { AttributeBinderMixin } from '../mixins/attributeBinderMixin.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { ValidationMixin } from '../mixins/validationMixin.ts'; -import { html, render } from 'lit-html'; -import { ContextMixin } from '../mixins/contextMixin'; +import { html, render } from 'lit'; +import { trackRenderAsync } from '../logger.ts'; +import { ContextMixin } from '../mixins/contextMixin.ts'; export const SolidDelete = { name: 'solid-delete', @@ -15,7 +16,7 @@ export const SolidDelete = { type: String, default: null, callback: function () { - this.resourceId = this.dataSrc; + this.resourceId = this.dataSrc; }, }, dataLabel: { @@ -24,7 +25,7 @@ export const SolidDelete = { callback: function (newValue: string, oldValue: string) { if (newValue !== oldValue) this.planRender(); }, - } + }, }, initialState: { renderPlanned: false, @@ -41,7 +42,7 @@ export const SolidDelete = { }); } }, - async delete(e: Event): Promise<void> { + delete(e: Event) { e.stopPropagation(); if (!this.dataSrc) return; this.performAction(); // In validationMixin, method defining what to do according to the present attributes @@ -50,25 +51,26 @@ export const SolidDelete = { return store.delete(this.dataSrc, this.context).then(response => { if (!response.ok) return; this.goToNext(null); - const eventData = { detail: { resource: { "@id": this.dataSrc } }, bubbles: true }; + const eventData = { + detail: { resource: { '@id': this.dataSrc } }, + bubbles: true, + }; this.element.dispatchEvent(new CustomEvent('save', eventData)); this.element.dispatchEvent(new CustomEvent('resourceDeleted', eventData)); // Deprecated. To remove in 0.15 - }) + }); }, - validateModal() { // Send method to validationMixin, used by the dialog modal and performAction method + validateModal() { + // Send method to validationMixin, used by the dialog modal and performAction method return this.deletion(); }, update() { this.render(); }, - async render(): Promise<void> { + render: trackRenderAsync(async function (): Promise<void> { await this.replaceAttributesData(false); - const button = html` - <button @click=${this.delete.bind(this)}>${this.dataLabel || this.t("solid-delete.button")}</button> - ${this.getModalDialog()} - `; + const button = html`<button @click=${this.delete.bind(this)}>${this.dataLabel || this.t('solid-delete.button')}</button>${this.getModalDialog()}`; render(button, this.element); - } + }, 'SolidDelete:render'), }; -Sib.register(SolidDelete); \ No newline at end of file +Sib.register(SolidDelete); diff --git a/src/components/solid-display.ts b/src/components/solid-display.ts index df4f833f2807e874b913453a615a523e149c2aae..98e49babbbb5b2eb251219c1ff0a8dd4a09b386b 100644 --- a/src/components/solid-display.ts +++ b/src/components/solid-display.ts @@ -1,20 +1,22 @@ -import { Sib } from '../libs/Sib'; -import { WidgetMixin } from '../mixins/widgetMixin'; -import { ListMixin } from '../mixins/listMixin'; -import { StoreMixin } from '../mixins/storeMixin'; -import { PaginateMixin } from '../mixins/paginateMixin'; -import { FilterMixin } from '../mixins/filterMixin'; -import { CounterMixin } from '../mixins/counterMixin'; -import { SorterMixin } from '../mixins/sorterMixin'; -import { GrouperMixin } from '../mixins/grouperMixin'; -import { FederationMixin } from '../mixins/federationMixin'; -import { HighlighterMixin } from '../mixins/highlighterMixin'; -import { NextMixin } from '../mixins/nextMixin'; -import { RequiredMixin } from '../mixins/requiredMixin'; -import { spread } from '../libs/lit-helpers'; +import { Sib } from '../libs/Sib.ts'; +import { spread } from '../libs/lit-helpers.ts'; +import { CounterMixin } from '../mixins/counterMixin.ts'; +import { FederationMixin } from '../mixins/federationMixin.ts'; +import { FilterMixin } from '../mixins/filterMixin.ts'; +import { GrouperMixin } from '../mixins/grouperMixin.ts'; +import { HighlighterMixin } from '../mixins/highlighterMixin.ts'; +import { ListMixin } from '../mixins/listMixin.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { PaginateMixin } from '../mixins/paginateMixin.ts'; +import { RequiredMixin } from '../mixins/requiredMixin.ts'; +import { SorterMixin } from '../mixins/sorterMixin.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; +import { WidgetMixin } from '../mixins/widgetMixin.ts'; -import { html, render } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { trackRenderAsync } from '../logger.ts'; export const SolidDisplay = { name: 'solid-display', @@ -41,18 +43,20 @@ export const SolidDisplay = { initialState: { activeSubscription: null, removeActiveSubscription: null, + resources: [], }, created(): void { // Set route active at initialization const route = document.querySelector('solid-route[active]') as any; if (!route) return; setTimeout(() => { - if (route['resourceId'] === this.resourceId) this.addActiveCallback(); + if (route.resourceId === this.resourceId) this.addActiveCallback(); }); }, detached(): void { if (this.activeSubscription) PubSub.unsubscribe(this.activeSubscription); - if (this.removeActiveSubscription) PubSub.unsubscribe(this.removeActiveSubscription); + if (this.removeActiveSubscription) + PubSub.unsubscribe(this.removeActiveSubscription); }, // Update subscription when id changes updateNavigateSubscription() { @@ -60,8 +64,8 @@ export const SolidDisplay = { if (this.resourceId) { this.activeSubscription = PubSub.subscribe( - 'enterRoute.' + this.resourceId, - this.addActiveCallback.bind(this) + `enterRoute.${this.resourceId}`, + this.addActiveCallback.bind(this), ); } }, @@ -69,7 +73,7 @@ export const SolidDisplay = { this.element.setAttribute('active', ''); this.removeActiveSubscription = PubSub.subscribe( 'leaveRoute', - this.removeActiveCallback.bind(this) + this.removeActiveCallback.bind(this), ); }, removeActiveCallback() { @@ -87,18 +91,18 @@ export const SolidDisplay = { }, // Here "even.target" points to the content of the widgets of the children of solid-display dispatchSelect(event: Event, resourceId: string): void { - const linkTarget = (event!.target as Element).closest('a'); - if (linkTarget && linkTarget.hasAttribute('href')) return; - const resource = { "@id": resourceId }; + const linkTarget = (event?.target as Element).closest('a'); + if (linkTarget?.hasAttribute('href')) return; + const resource = { '@id': resourceId }; this.element.dispatchEvent( new CustomEvent('resourceSelect', { detail: { resource: resource } }), ); this.goToNext(resource); }, - - enterKeydownAction (event, resourceId: string): void { + + enterKeydownAction(event, resourceId: string): void { if (event.keyCode === 13) { - const resource = { "@id" : resourceId }; + const resource = { '@id': resourceId }; this.goToNext(resource); } }, @@ -108,7 +112,7 @@ export const SolidDisplay = { * @param attributes */ getChildTemplate(resourceId: string, attributes: object) { - let template = html` + const template = html` <solid-display data-src=${resourceId} @click=${(event: Event) => this.dispatchSelect(event, resourceId)} @@ -116,7 +120,7 @@ export const SolidDisplay = { fields=${ifDefined(this.fields)} ...=${spread(attributes)} ></solid-display> - ` + `; return template; }, @@ -126,8 +130,9 @@ export const SolidDisplay = { */ async appendSingleElt(parent: HTMLElement): Promise<void> { const fields = await this.getFields(); - const widgetTemplates = await Promise.all( // generate all widget templates - fields.map((field: string) => this.createWidgetTemplate(field)) + const widgetTemplates = await Promise.all( + // generate all widget templates + fields.map((field: string) => this.createWidgetTemplate(field)), ); render(html`${widgetTemplates}`, parent); }, @@ -141,59 +146,55 @@ export const SolidDisplay = { * @param div * @param context */ - async renderDOM( + renderDOM: trackRenderAsync(async function ( resources: object[], - listPostProcessors: Function[], + listPostProcessors: PostProcessorRegistry, div: HTMLElement, context: string, ) { const attributes = this.getChildAttributes(); // get attributes of children only once // and create a child template for each resource - const template = html`${resources.map(r => r ? this.getChildTemplate(r['@id'], attributes) : null)}`; + const template = html`${resources.map(r => (r ? this.getChildTemplate(r['@id'], attributes) : null))}`; render(template, div); const nextProcessor = listPostProcessors.shift(); + if (nextProcessor) - await nextProcessor( - resources, - listPostProcessors, - div, - context - ); - }, + await nextProcessor(resources, listPostProcessors, div, context); + }, 'SolidDisplay:renderDom'), /** * Get attributes to dispatch to children from current element */ getChildAttributes() { - const attributes:{[key:string]: string} = {}; - for (let attr of this.element.attributes) { + const attributes: { [key: string]: string } = {}; + for (const attr of this.element.attributes) { //copy widget and value attributes if ( - attr.name.startsWith('value-') || - attr.name.startsWith('label-') || - attr.name.startsWith('placeholder-') || - attr.name.startsWith('widget-') || - attr.name.startsWith('class-') || - attr.name.startsWith('multiple-') || - attr.name.startsWith('editable-') || - attr.name.startsWith('action-') || - attr.name.startsWith('default-') || - attr.name.startsWith('link-text-') || - attr.name.startsWith('target-src-') || - attr.name.startsWith('data-label-') || - attr.name == 'extra-context' + attr.name.startsWith('value-') || + attr.name.startsWith('label-') || + attr.name.startsWith('placeholder-') || + attr.name.startsWith('widget-') || + attr.name.startsWith('class-') || + attr.name.startsWith('multiple-') || + attr.name.startsWith('editable-') || + attr.name.startsWith('action-') || + attr.name.startsWith('default-') || + attr.name.startsWith('link-text-') || + attr.name.startsWith('target-src-') || + attr.name.startsWith('data-label-') || + attr.name === 'extra-context' ) attributes[attr.name] = attr.value; if (attr.name.startsWith('child-')) attributes[attr.name.replace(/^child-/, '')] = attr.value; - if (attr.name == 'next') { - attributes['role'] = 'button'; - attributes['tabindex'] = '0'; + if (attr.name === 'next') { + attributes.role = 'button'; + attributes.tabindex = '0'; } } return attributes; - } + }, }; Sib.register(SolidDisplay); diff --git a/src/components/solid-form-search.ts b/src/components/solid-form-search.ts index f165b54c5295e1f51a2ca9f153e58fd4db320645..02a30c819d749bc12b52200b49995b3b189be259 100644 --- a/src/components/solid-form-search.ts +++ b/src/components/solid-form-search.ts @@ -1,19 +1,20 @@ -import { Sib } from '../libs/Sib'; -import { WidgetMixin } from '../mixins/widgetMixin'; -import { AttributeBinderMixin } from '../mixins/attributeBinderMixin'; -import { ContextMixin } from '../mixins/contextMixin'; -import type { WidgetInterface } from '../mixins/interfaces'; -import { newWidgetFactory } from '../new-widgets/new-widget-factory'; +import { Sib } from '../libs/Sib.ts'; +import { AttributeBinderMixin } from '../mixins/attributeBinderMixin.ts'; +import { ContextMixin } from '../mixins/contextMixin.ts'; +import type { WidgetInterface } from '../mixins/interfaces.ts'; +import { WidgetMixin } from '../mixins/widgetMixin.ts'; +import { newWidgetFactory } from '../new-widgets/new-widget-factory.ts'; -import { html, render } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; -import { uniqID } from '../libs/helpers'; -import type { SearchQuery, FilterEventOptions } from '../libs/interfaces'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { uniqID } from '../libs/helpers.ts'; +import type { FilterEventOptions, SearchQuery } from '../libs/interfaces.ts'; +import { trackRenderAsync } from '../logger.ts'; export const SolidFormSearch = { name: 'solid-form-search', use: [WidgetMixin, AttributeBinderMixin, ContextMixin], - debounceTimeout: undefined as (number | undefined), + debounceTimeout: undefined as number | undefined, attributes: { defaultWidget: { type: String, @@ -28,7 +29,7 @@ export const SolidFormSearch = { }, submitWidget: { type: String, - default: undefined + default: undefined, }, classSubmitButton: { type: String, @@ -38,13 +39,13 @@ export const SolidFormSearch = { type: String, default: null, callback: function (value: boolean) { - if (value === null) this.populate() - } + if (value === null) this.populate(); + }, }, debounce: { type: Number, - default: 0 // Avoiding blink effect with static values - } + default: 0, // Avoiding blink effect with static values + }, }, initialState: { error: '', @@ -64,10 +65,10 @@ export const SolidFormSearch = { get value(): SearchQuery { const values: SearchQuery = {}; - this.widgets.forEach((widget) => { - if (widget == null) return; + for (const widget of this.widgets) { + if (widget == null) continue; const name = (widget.component || widget).name; - if (name == null) return; + if (name == null) continue; let value = widget.component ? widget.component.getValue() : widget.value; try { value = JSON.parse(value); @@ -76,62 +77,75 @@ export const SolidFormSearch = { type: widget.component.type, list: !!widget.component.multiple, value: value, - } + }; values[name] = value; - }); + } return values; }, - getWidget(field: string, isSet: boolean = false): WidgetInterface { + getWidget(field: string, isSet = false): WidgetInterface { let tagName = ''; // If auto-range-[field] exists, create range-[field] and sets its value - if(this.element.hasAttribute('auto-range-' + field) && !this.element.hasAttribute('range-' + field)) { + if ( + this.element.hasAttribute(`auto-range-${field}`) && + !this.element.hasAttribute(`range-${field}`) + ) { const idField = `${this.rangeId}_${field}`; - this.element.setAttribute('range-' + field, 'store://local.' + idField); + this.element.setAttribute(`range-${field}`, `store://local.${idField}`); this.populate(); } - - const widgetAttribute = this.element.getAttribute('widget-' + field); + + const widgetAttribute = this.element.getAttribute(`widget-${field}`); // Choose widget - if (!widgetAttribute && (this.element.hasAttribute('range-' + field) || this.element.hasAttribute('enum-' + field))) { - tagName = 'solid-form-dropdown' + if ( + !widgetAttribute && + (this.element.hasAttribute(`range-${field}`) || + this.element.hasAttribute(`enum-${field}`)) + ) { + tagName = 'solid-form-dropdown'; } else { - tagName = widgetAttribute || (!isSet ? this.defaultWidget : this.defaultSetWidget); + tagName = + widgetAttribute || + (!isSet ? this.defaultWidget : this.defaultSetWidget); } // Create widget - if (!customElements.get(tagName)) { // component does not exist + if (!customElements.get(tagName)) { + // component does not exist if (tagName.startsWith('solid')) newWidgetFactory(tagName); // solid- -> create it } return this.widgetFromTagName(tagName); }, - async attach(elm: any) { - if(this.attachedElements.has(elm)) return; + async attach(elm: unknown) { + if (this.attachedElements.has(elm)) return; this.attachedElements.add(elm); await this.updateAutoRanges(); }, - async detach(elm: any) { - if(!this.attachedElements.has(elm)) return; + async detach(elm: unknown) { + if (!this.attachedElements.has(elm)) return; this.attachedElements.delete(elm); await this.updateAutoRanges(); }, async updateAutoRanges() { - for(const attr of (this.element as Element).attributes) { - if (!attr['name'].startsWith('auto-range-')) continue; - let fieldName = attr.value !== '' ? attr.value : attr['name'].replace('auto-range-', ''); + for (const attr of (this.element as Element).attributes) { + if (!attr.name.startsWith('auto-range-')) continue; + const fieldName = + attr.value !== '' ? attr.value : attr.name.replace('auto-range-', ''); const autoRangeValues = new Set(); - for(const elm of this.attachedElements) { - for(const value of await elm.getValuesOfField(fieldName)) { + for (const elm of this.attachedElements) { + for (const value of await elm.getValuesOfField(fieldName)) { autoRangeValues.add(value); } } const idField = `${this.rangeId}_${fieldName}`; const id = `store://local.${idField}`; - const ldpContains = Array.from(autoRangeValues).map(id => ({'@id' : id})); + const ldpContains = Array.from(autoRangeValues).map(id => ({ + '@id': id, + })); const data = { - "@type": "ldp:Container", - "@context": this.context, - "ldp:contains" : ldpContains, + '@type': 'ldp:Container', + '@context': this.context, + 'ldp:contains': ldpContains, }; sibStore.setLocalData(data, id); } @@ -152,45 +166,44 @@ export const SolidFormSearch = { detail: { value: eventOptions.value, inputLabel: eventOptions.inputLabel, - type: eventOptions.type - } + type: eventOptions.type, + }, }), ); }, - async inputChange(input: EventTarget): Promise<void> { + inputChange(input: EventTarget) { // FIXME: Improve this as we need to support more than input and single select. // What about multiple select, checkboxes, radio buttons, etc? - let parentElementLabel = (input as HTMLInputElement)?.parentElement?.getAttribute('label'); + const parentElementLabel = ( + input as HTMLInputElement + )?.parentElement?.getAttribute('label'); try { - const selectedLabel = (input as HTMLSelectElement).selectedOptions[0].textContent?.trim(); - this.change( - this.value, - { - value: selectedLabel, - inputLabel: parentElementLabel, - type: 'select' - } - ); + const selectedLabel = ( + input as HTMLSelectElement + ).selectedOptions[0].textContent?.trim(); + this.change(this.value, { + value: selectedLabel, + inputLabel: parentElementLabel, + type: 'select', + }); } catch { - this.change(this.value, - { - value: (input as HTMLInputElement).value, - inputLabel: parentElementLabel, - type: 'input' - } - ); + this.change(this.value, { + value: (input as HTMLInputElement).value, + inputLabel: parentElementLabel, + type: 'input', + }); } }, getSubmitTemplate() { return html` <div class=${ifDefined(this.classSubmitButton)}> - ${this.submitWidget === 'button' ? html` - <button type="submit">${this.submitButton || ''}</button> - ` : html` - <input type="submit" value=${ifDefined(this.submitButton || undefined)}> - `} + ${ + this.submitWidget === 'button' + ? html`<button type="submit">${this.submitButton || ''}</button>` + : html`<input type="submit" value=${ifDefined(this.submitButton || undefined)}>` + } </div> - ` + `; }, empty(): void {}, debounceInput(input: EventTarget | null) { @@ -200,7 +213,7 @@ export const SolidFormSearch = { this.inputChange(input); }, this.debounce); }, - async populate(): Promise<void> { + populate: trackRenderAsync(async function (): Promise<void> { await this.replaceAttributesData(); if (this.submitButton == null) { this.element.addEventListener('input', (e: Event) => { @@ -212,15 +225,17 @@ export const SolidFormSearch = { this.inputChange(e.target); }); const fields = await this.getFields(); - const widgetTemplates = await Promise.all(fields.map((field: string) => this.createWidgetTemplate(field))); + const widgetTemplates = await Promise.all( + fields.map((field: string) => this.createWidgetTemplate(field)), + ); const template = html` - <form> - ${widgetTemplates} - ${this.submitButton == null ? '' : this.getSubmitTemplate()} - </form> - `; + <form> + ${widgetTemplates} + ${this.submitButton == null ? '' : this.getSubmitTemplate()} + </form> + `; render(template, this.element); - } + }, 'SolidFormSearch:populate'), }; -Sib.register(SolidFormSearch); \ No newline at end of file +Sib.register(SolidFormSearch); diff --git a/src/components/solid-form.ts b/src/components/solid-form.ts index b79e2da7145429591ab7abce1d68087bd5c7f8ea..b7dc1bd48d341e57d411d6a627a0f42beea5259a 100644 --- a/src/components/solid-form.ts +++ b/src/components/solid-form.ts @@ -1,14 +1,15 @@ -import { Sib } from '../libs/Sib'; -import { WidgetMixin } from '../mixins/widgetMixin'; -import { StoreMixin } from '../mixins/storeMixin'; -import { NextMixin } from '../mixins/nextMixin'; -import { ValidationMixin } from '../mixins/validationMixin'; -import { store } from '../libs/store/store'; -import { setDeepProperty, transformArrayToContainer } from '../libs/helpers'; -import type { WidgetInterface } from '../mixins/interfaces'; +import { Sib } from '../libs/Sib.ts'; +import { setDeepProperty, transformArrayToContainer } from '../libs/helpers.ts'; +import { store } from '../libs/store/store.ts'; +import type { WidgetInterface } from '../mixins/interfaces.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; +import { ValidationMixin } from '../mixins/validationMixin.ts'; +import { WidgetMixin } from '../mixins/widgetMixin.ts'; -import { html, render } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { trackRenderAsync } from '../logger.ts'; export const SolidForm = { name: 'solid-form', @@ -16,7 +17,7 @@ export const SolidForm = { attributes: { autosave: { type: Boolean, - default: null + default: null, }, classSubmitButton: { type: String, @@ -24,15 +25,15 @@ export const SolidForm = { }, defaultWidget: { type: String, - default: 'solid-form-label-text' + default: 'solid-form-label-text', }, naked: { type: Boolean, - default: null + default: null, }, partial: { type: Boolean, - default: null + default: null, }, submitButton: { type: String, @@ -43,11 +44,11 @@ export const SolidForm = { }, submitWidget: { type: String, - default: null + default: null, }, }, initialState: { - error: '' + error: '', }, get defaultMultipleWidget(): string { return 'solid-multiple-form'; @@ -57,17 +58,18 @@ export const SolidForm = { }, get value(): object { const values = {}; - this.widgets.forEach((widget) => { + for (const widget of this.widgets) { const name = (widget.component || widget).name; - if (name == null) return; + if (name == null) continue; let value = widget.component ? widget.component.getValue() : widget.value; try { value = JSON.parse(value); - } catch (e) {} + } catch {} setDeepProperty(values, name.split('.'), value); - }); + } // add @id if edition - if (this.resource && !this.resource.isContainer?.()) values['@id'] = this.resourceId; + if (this.resource && !this.resource.isContainer?.()) + values['@id'] = this.resourceId; return values; }, get isNaked(): boolean { @@ -80,43 +82,54 @@ export const SolidForm = { return !('@id' in formValue); }, async getFormValue() { - let value = this.value; + const value = this.value; if (this.resource && !this.resource.isContainer?.()) { - for (let predicate of Object.keys(this.value)) { + for (const predicate of Object.keys(this.value)) { // add @id for nested resources let object = await this.resource[predicate]; // edge-case where object is null because predicate needs to be expanded manually (arrays) if (!object) { - object = await this.resource[store.getExpandedPredicate(predicate, this.context)]; + object = + await this.resource[ + store.getExpandedPredicate(predicate, this.context) + ]; } // Nested containers - if (object - && object['@id'] - && !value[predicate]['@id']) value[predicate]['@id'] = object['@id']; + if (object?.['@id'] && !value[predicate]['@id']) + value[predicate]['@id'] = object['@id']; //FIXME: Edge case of array support, ugly management - if (object && !object['@id'] - && Array.isArray(object) - && value[predicate].length == 0 - && object.length > 0) { + if ( + object && + !object['@id'] && + Array.isArray(object) && + value[predicate].length === 0 && + object.length > 0 + ) { value[predicate] = object; } } } return transformArrayToContainer(value); }, - getWidget(field: string, isSet: boolean = false): WidgetInterface { + getWidget(field: string, isSet = false): WidgetInterface { let tagName = ''; - const widgetAttribute = this.element.getAttribute('widget-' + field); + const widgetAttribute = this.element.getAttribute(`widget-${field}`); // Choose widget - if (!widgetAttribute && this.element.hasAttribute('upload-url-' + field)) { - tagName = 'solid-form-file' - } else if (!widgetAttribute && (this.element.hasAttribute('range-' + field) || this.element.hasAttribute('enum-' + field))) { - tagName = 'solid-form-dropdown' + if (!widgetAttribute && this.element.hasAttribute(`upload-url-${field}`)) { + tagName = 'solid-form-file'; + } else if ( + !widgetAttribute && + (this.element.hasAttribute(`range-${field}`) || + this.element.hasAttribute(`enum-${field}`)) + ) { + tagName = 'solid-form-dropdown'; } else { - tagName = widgetAttribute || (!isSet ? this.defaultWidget : this.defaultSetWidget); + tagName = + widgetAttribute || + (!isSet ? this.defaultWidget : this.defaultSetWidget); } // Create widget return this.widgetFromTagName(tagName); @@ -129,23 +142,24 @@ export const SolidForm = { }), ); }, - async save(): Promise<object> { + async save() { this.toggleLoaderHidden(false); this.hideError(); const resource = await this.getFormValue(); resource['@context'] = this.context; - let saved; + let saved: string | null | undefined; try { if (this.partial == null) { - saved = resource['@id'] ? - await store.put(resource, this.resourceId) : - await store.post(resource, this.resourceId); + saved = resource['@id'] + ? await store.put(resource, this.resourceId) + : await store.post(resource, this.resourceId); } else { saved = await store.patch(resource, this.resourceId); } } catch (e: any) { this.toggleLoaderHidden(true); - if (e) { // if server error + if (e?.json) { + // if server error e.json().then(error => this.showError(error)); throw e; } @@ -155,7 +169,7 @@ export const SolidForm = { bubbles: true, detail: { resource: resource, - id: saved || null + id: saved || null, }, }), ); @@ -165,10 +179,12 @@ export const SolidForm = { async submitForm(): Promise<void> { let id: string; try { - id = await this.save() || this.getFormValue()['@id']; - } catch (e) { return; } + id = (await this.save()) || this.getFormValue()['@id']; + } catch (_e) { + return; + } this.reset(); - this.goToNext({'@id': id}) + this.goToNext({ '@id': id }); }, async onInput(): Promise<void> { const formValue = await this.getFormValue(); @@ -179,37 +195,41 @@ export const SolidForm = { if (!this.isCreationForm(formValue) && this.isSavingAutomatically) this.submitForm(); // if autosave, submitForm }, - displayErrorMessage(errors: [string, any][], errorFullName: string = '') { - errors.forEach((member: [string, any]) => { - let errorNextName: string = Object.values(member)[0]; - let subErrorName = (errorFullName === "" ? errorNextName : errorFullName.concat('.' + errorNextName)); - let errorFieldName = "" + displayErrorMessage(errors: [string, any][], errorFullName = '') { + for (const member of errors) { + const errorNextName: string = Object.values(member)[0]; + const subErrorName = + errorFullName === '' + ? errorNextName + : `${errorFullName}.${errorNextName}`; + let errorFieldName = ''; - if (errorFullName) errorFieldName = errorFullName.concat('.' + errorNextName); + if (errorFullName) errorFieldName = `${errorFullName}.${errorNextName}`; else errorFieldName = errorNextName; if (errorFieldName) { - let formField = this.element.querySelector(`[name="${errorFieldName}"]`); + const formField = this.element.querySelector( + `[name="${errorFieldName}"]`, + ); if (formField) { formField.classList.add('error'); - let errorParagraph = document.createElement('p'); + const errorParagraph = document.createElement('p'); if (Array.isArray(Object.values(member)[1]) === true) { - Object.values(member)[1].forEach((error) => { - let errorText = document.createElement('p'); + for (const error of Object.values(member)[1]) { + const errorText = document.createElement('p'); errorText.textContent = error; errorParagraph.appendChild(errorText); - }); + } } else if (typeof Object.values(member)[1] === 'object') { - // @ts-ignore - for (const [key, value] of Object.entries(Object.values(member)[1])) { + for (const value of Object.values(Object.values(member)[1])) { if (Array.isArray(value)) { - value.forEach((error) => { - let errorText = document.createElement('p'); + for (const error of value) { + const errorText = document.createElement('p'); errorText.textContent = error; errorParagraph.appendChild(errorText); - }); + } } else if (typeof value === 'string') { - let errorText = document.createElement('p'); + const errorText = document.createElement('p'); errorText.textContent = value; errorParagraph.appendChild(errorText); } @@ -223,30 +243,32 @@ export const SolidForm = { } if (!Array.isArray(Object.values(member)[1]) === true) { - let objectErrors = Object.values(member)[1]; - let subErrors = Object.entries(objectErrors); - this.displayErrorMessage(subErrors, subErrorName) + const objectErrors = Object.values(member)[1]; + const subErrors = Object.entries(objectErrors); + this.displayErrorMessage(subErrors, subErrorName); } - }); + } }, empty(): void {}, showError(e: object) { - let errors = Object.entries(e).filter(field => !field[0].startsWith('@context')); + const errors = Object.entries(e).filter( + field => !field[0].startsWith('@context'), + ); this.displayErrorMessage(errors); - const errorTemplate = html` - <p>${this.t('solid-form.validation-error')}</p> - `; + const errorTemplate = html`<p>${this.t('solid-form.validation-error')}</p>`; // Validation message in english ? const parentElement = this.element.querySelector('[data-id=error]'); if (parentElement) render(errorTemplate, parentElement); }, hideError() { - let formErrors = this.element.querySelectorAll('.error-message'); - if (formErrors) formErrors.forEach((error) => error.remove()); + const formErrors = this.element.querySelectorAll('.error-message'); + if (formErrors) for (const error of formErrors) error.remove(); - let errorFields = this.element.querySelectorAll('.error'); - if (errorFields) errorFields.forEach((errorField) => errorField.classList.remove('error')); + const errorFields = this.element.querySelectorAll('.error'); + if (errorFields) + for (const errorField of errorFields) + errorField.classList.remove('error'); const parentElement = this.element.querySelector('[data-id=error]'); if (parentElement) render('', parentElement); @@ -260,48 +282,55 @@ export const SolidForm = { this.performAction(); // In validationMixin, method defining what to do according to the present attributes } }, - validateModal() { //send method to validationMixin, used by the dialog modal and performAction method + validateModal() { + //send method to validationMixin, used by the dialog modal and performAction method return this.submitForm(); }, onReset() { - if (!this.isNaked) setTimeout(() => this.onInput()) + if (!this.isNaked) setTimeout(() => this.onInput()); }, getSubmitTemplate() { return html` <div class=${ifDefined(this.classSubmitButton)}> - ${this.submitWidget === 'button' ? html` - <button type="submit">${this.submitButton || this.t("solid-form.submit-button")}</button> - ` : html` - <input type="submit" value=${this.submitButton || this.t("solid-form.submit-button")}> - `} + ${ + this.submitWidget === 'button' + ? html`<button type="submit">${this.submitButton || this.t('solid-form.submit-button')}</button>` + : html`<input type="submit" value=${this.submitButton || this.t('solid-form.submit-button')}>` + } </div> - ` + `; }, - async populate(): Promise<void> { + populate: trackRenderAsync(async function (): Promise<void> { this.element.oninput = () => this.onInput(); // prevent from firing change multiple times this.element.onchange = () => this.onChange(); const fields = await this.getFields(); - const widgetTemplates = await Promise.all(fields.map((field: string) => this.createWidgetTemplate(field))); + const widgetTemplates = await Promise.all( + fields.map((field: string) => this.createWidgetTemplate(field)), + ); const template = html` - <div data-id="error"></div> - ${!this.isNaked ? html` - <form - @submit=${this.onSubmit.bind(this)} - @reset=${this.onReset.bind(this)} - > - ${widgetTemplates} - ${!this.isSavingAutomatically ? this.getSubmitTemplate() : ''} - ${this.element.hasAttribute('reset') - ? html`<input type="reset" />` : ''} - </form> - ` : html` - ${widgetTemplates} - ` - } - ${this.getModalDialog()} - `; + <div data-id="error"></div> + ${ + !this.isNaked + ? html` + <form + @submit=${this.onSubmit.bind(this)} + @reset=${this.onReset.bind(this)} + > + ${widgetTemplates} + ${!this.isSavingAutomatically ? this.getSubmitTemplate() : ''} + ${ + this.element.hasAttribute('reset') + ? html`<input type="reset" />` + : '' + } + </form> + ` + : html`${widgetTemplates}` + } + ${this.getModalDialog()} + `; render(template, this.element); - } + }, 'SolidForm:populate'), }; -Sib.register(SolidForm); \ No newline at end of file +Sib.register(SolidForm); diff --git a/src/components/solid-lang.ts b/src/components/solid-lang.ts index 82b5c254419ae3b9cf97b482d4d4894fd546883b..1f30d969ba0440377a0c813b059058ed80903ebe 100644 --- a/src/components/solid-lang.ts +++ b/src/components/solid-lang.ts @@ -1,7 +1,7 @@ -import { Sib } from '../libs/Sib'; -import { store } from '../libs/store/store'; +import { Sib } from '../libs/Sib.ts'; +import { store } from '../libs/store/store.ts'; -import { html, render } from 'lit-html'; +import { html, render } from 'lit'; export const SolidLang = { name: 'solid-lang', @@ -9,34 +9,28 @@ export const SolidLang = { attributes: { lang: { type: String, - default: null + default: null, }, dataLabel: { type: String, - default: null - } + default: null, + }, }, created(): void { this.render(); }, - languageLoader () { + languageLoader() { store.selectLanguage(this.lang); location.reload(); }, render() { - let template = html` - <button - @click=${this.languageLoader.bind(this)} - > - ${this.dataLabel} - </button> - `; + const template = html`<button @click=${this.languageLoader.bind(this)}>${this.dataLabel}</button>`; render(template, this.element); - } + }, }; -Sib.register(SolidLang); \ No newline at end of file +Sib.register(SolidLang); diff --git a/src/components/solid-map.ts b/src/components/solid-map.ts deleted file mode 100644 index 9c80693fa964c1f743fc93c7b87ed998b0456e1c..0000000000000000000000000000000000000000 --- a/src/components/solid-map.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { Sib } from '../libs/Sib'; -import { ListMixin } from '../mixins/listMixin'; -import { StoreMixin } from '../mixins/storeMixin'; -import { WidgetMixin } from '../mixins/widgetMixin'; -import { CounterMixin } from '../mixins/counterMixin'; -import { FilterMixin } from '../mixins/filterMixin'; -import { FederationMixin } from '../mixins/federationMixin'; -import { GrouperMixin } from '../mixins/grouperMixin'; -import { NextMixin } from '../mixins/nextMixin'; -import { store } from '../libs/store/store'; -import { importInlineCSS, uniqID } from '../libs/helpers'; -import { spread } from '../libs/lit-helpers'; - -//@ts-ignore -import L, { MarkerOptions } from 'https://cdn.skypack.dev/leaflet'; // TODO : revert to "leaflet" when apps up to date -import 'https://cdn.skypack.dev/leaflet.markercluster'; // TODO : revert to "leaflet.markercluster" when apps up to date - -import { html, render } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; - -export const SolidMap = { - name: 'solid-map', - use: [ - WidgetMixin, - ListMixin, - StoreMixin, - GrouperMixin, - CounterMixin, - FilterMixin, - FederationMixin, - NextMixin, - ], - attributes: { - clustering: { - type: Boolean, - default: null - } - }, - initialState: { - markers: { - default: null - }, - subscriptions: null, - resetPlanned: false, - hasBeenResetOnce: false - }, - created(): void { - importInlineCSS('leaflet', () => import('leaflet/dist/leaflet.css?inline')) - importInlineCSS('default-theme', () => import('../style/default-theme.css?inline')) - importInlineCSS('marker-cluster', () => import('leaflet.markercluster/dist/MarkerCluster.css?inline')) - importInlineCSS('marker-cluster-default', () => import('leaflet.markercluster/dist/MarkerCluster.Default.css?inline')) - - // reset when it becomes visible to prevent bug https://git.startinblox.com/framework/sib-core/issues/661 - document.body.addEventListener('navigate', () => - setTimeout(() => this.isVisible && !this.hasBeenResetOnce && this.reset()) - ); - this.markers = []; - this.subscriptions = new Map(); - }, - get isVisible() { - return this.element.offsetParent !== null - }, - attached(): void { - const id = uniqID(); - const template = html` - <div id=${id} style="width:100%;height:100%;"></div> - `; - render(template, this.element); - - const div = this.element.querySelector(`#${id}`); - this.map = L.map(div); - - L.tileLayer( - 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png' - ).addTo(this.map); - - if (this.clustering !== null) { - this.markersCluster = L.markerClusterGroup(); - this.map.addLayer(this.markersCluster); - } - }, - reset() { - if (this.isVisible) { // reset only if visible - this.map.invalidateSize(); - - if (this.markers.length) { - this.map.fitBounds(L.featureGroup(this.markers).getBounds()); // Center map on markers if some available - } else { - this.map.fitWorld(); // ... or on the world if not - } - this.hasBeenResetOnce = true; - } - }, - /** - * Execute a reset only if none is planned already - */ - planReset() { - if (!this.resetPlanned) { - this.resetPlanned = true; - setTimeout(() => { - this.reset(); - this.resetPlanned = false; - }) - } - }, - dispatchSelect(event: CustomEvent): void { - const target = event.target as Element; - const resource = target['options'].resource; - this.element.dispatchEvent( - new CustomEvent('resourceSelect', { detail: { resource: resource } }) - ); - this.goToNext(resource); - }, - - /** - * Override listMixin method: initialize a marker on the map - * @param resourceId: id of the resource to display - * @param groupClass: class of the group of markers - */ - async appendChildElt(resourceId: string, groupClass: string) { - const resource = await store.getData(resourceId, this.context); - if (!this.subscriptions.get(resourceId)) { - this.subscriptions.set(resourceId, PubSub.subscribe(resourceId, () => this.updateDOM())) - } - if (!resource) return; - const lat = await resource['lat']; - const lng = await resource['lng']; - - if (lat && lng) { - const icon = L.divIcon({ // create the icon, doc here: https://leafletjs.com/reference-1.6.0.html#icon - className: 'sib-custom-marker ' + groupClass, // default class used for styling - iconSize: [8, 8], - iconAnchor: [12, 34], - popupAnchor: [0,-34] - }); - - // create a marker, doc here: https://leafletjs.com/reference-1.6.0.html#marker - const marker = L.marker( - [lat.toString(), lng.toString()], - {resource, icon} as MarkerOptions - ); - if(this.clustering === null) marker.addTo(this.map); - else this.markersCluster.addLayer(marker); - marker.on('click', this.dispatchSelect.bind(this)); - - if (this.fields !== null) { // show popups only if fields attribute - marker.bindPopup(() => this.getPopupContent(resourceId), { minWidth: 150 }) // re-generate popup solid-display - } - - this.markers.push(marker); - } - }, - /** - * Generate the solid-display of the popup - * @param resourceId: id of the popup clicked - */ - getPopupContent(resourceId: string) { - const attributes:{[key:string]: string} = {}; - - for (let attr of this.element.attributes) { - //copy widget and value attributes - if ( - attr.name.startsWith('value-') || - attr.name.startsWith('label-') || - attr.name.startsWith('widget-') || - attr.name.startsWith('class-') || - attr.name.startsWith('multiple-') || - attr.name.startsWith('editable-') || - attr.name.startsWith('action-') || - attr.name.startsWith('default-') || - attr.name == 'extra-context' - ) - attributes[attr.name] = attr.value; - if (attr.name.startsWith('child-')) - attributes[attr.name.replace(/^child-/, '')] = attr.value; - } - - const div = document.createElement('div'); - const template = html` - <solid-display - fields="${ifDefined(this.fields)}" - data-src="${resourceId}" - ...=${spread(attributes)} - ></solid-display> - `; - render(template, div); - return div.querySelector('solid-display'); - }, - /** - * Override widgetMixin method: empty the map - */ - empty(): void { - if (!this.map) return; - if (this.markersCluster) this.map.removeLayer(this.markersCluster); - for (let marker of this.markers) this.map.removeLayer(marker); - if(this.clustering !== null) { - this.markersCluster = L.markerClusterGroup(); - this.map.addLayer(this.markersCluster); - } - this.markers = []; - }, - /** - * Override groupMixin method - * @param groupName: value of the group - */ - renderGroup(groupName: string) { - const sanitizedGroupName = encodeURIComponent(groupName.toLowerCase()).replace(/%[0-9A-F]{2}/gi, ''); - const div = document.createElement('div'); // used to pass group info to renderDOM - div.dataset.groupClass = 'group-' + sanitizedGroupName; - return div; - }, - /** - * Override listMixin method: display all the resources - * @param resources - * @param listPostProcessors - * @param div - * @param context - */ - async renderDOM(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string) { - const groupClass = div.dataset.groupClass || ''; // get the group class from the useless div element - await Promise.all(resources.map(resource => this.appendChildElt(resource['@id'], groupClass))) - this.planReset(); - - const nextProcessor = listPostProcessors.shift(); - if(nextProcessor) await nextProcessor(resources, listPostProcessors, div, context); - } -}; - -Sib.register(SolidMap); \ No newline at end of file diff --git a/src/components/solid-member-add.ts b/src/components/solid-member-add.ts index b58d4c90bb307249137bece7b8848669cab431f2..75846c17ed142851c9dd85a974ccf2f5076750d2 100644 --- a/src/components/solid-member-add.ts +++ b/src/components/solid-member-add.ts @@ -1,13 +1,13 @@ -import { Sib } from '../libs/Sib'; -import { base_context, store } from '../libs/store/store'; -import { NextMixin } from '../mixins/nextMixin'; -import { ValidationMixin } from '../mixins/validationMixin'; +import { Sib } from '../libs/Sib.ts'; +import { base_context, store } from '../libs/store/store.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { ValidationMixin } from '../mixins/validationMixin.ts'; -import { html, render } from 'lit-html'; -import { ContextMixin } from '../mixins/contextMixin'; -import { newWidgetFactory } from '../new-widgets/new-widget-factory'; -import { StoreMixin } from '../mixins/storeMixin'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { ContextMixin } from '../mixins/contextMixin.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; +import { newWidgetFactory } from '../new-widgets/new-widget-factory.ts'; export const SolidMemberAdd = { name: 'solid-member-add', @@ -30,11 +30,11 @@ export const SolidMemberAdd = { }, classSubmitButton: { type: String, - default: undefined + default: undefined, }, orderAsc: { type: String, - default: undefined + default: undefined, }, }, initialState: { @@ -53,45 +53,56 @@ export const SolidMemberAdd = { }); } }, - async addMember(e: Event): Promise<void> { + addMember(e: Event) { if (!this.dataSrc || !this.resourceId) return; e.preventDefault(); this.performAction(); // In validationMixin, method defining what to do according to the present attributes }, async addMembership() { this.currentMembers.push(JSON.parse(this.dataTargetSrc)); - let currentRes = { - "@context": this.context, - "user_set": this.currentMembers - } + const currentRes = { + '@context': this.context, + user_set: this.currentMembers, + }; return store.patch(currentRes, this.resourceId).then(response => { if (!response) { - console.warn(`Error while adding user ${this.dataTargetSrc} to group ${this.resourceId}`); + console.warn( + `Error while adding user ${this.dataTargetSrc} to group ${this.resourceId}`, + ); return; } this.goToNext(null); - const eventData = { detail: { resource: { "@id": this.dataSrc } }, bubbles: true }; + const eventData = { + detail: { resource: { '@id': this.dataSrc } }, + bubbles: true, + }; this.element.dispatchEvent(new CustomEvent('save', eventData)); this.element.dispatchEvent(new CustomEvent('memberAdded', eventData)); // Deprecated. To remove in 0.15 this.planRender(); - }) + }); }, - validateModal() { // Send method to validationMixin, used by the dialog modal and performAction method + validateModal() { + // Send method to validationMixin, used by the dialog modal and performAction method return this.addMembership(); }, changeSelectedUser(e: Event) { if (!e.target || !(e.target as HTMLElement).firstElementChild) return; //FIXME: disgusting way to get the @id of the autocomplete slimselect widget value - this.dataTargetSrc = ((e.target as HTMLElement).firstElementChild as HTMLSelectElement)?.value; + this.dataTargetSrc = ( + (e.target as HTMLElement).firstElementChild as HTMLSelectElement + )?.value; }, async populate(): Promise<void> { if (!this.resource) return; // Check if current user is member of this group ? - let memberPredicate = store.getExpandedPredicate('user_set', base_context); + const memberPredicate = store.getExpandedPredicate( + 'user_set', + base_context, + ); // Here we now retrieve an array of proxy, when we would like an array of @ids only this.currentMembers = await this.resource[memberPredicate]; @@ -99,9 +110,11 @@ export const SolidMemberAdd = { this.currentMembers = [this.currentMembers]; } // In each item in this.currentMembers, I'd like to return only their @id and store it in this.currentMembers - this.currentMembers = this.currentMembers.map(member => { return {"@id": member['@id'] } }); + this.currentMembers = this.currentMembers.map(member => { + return { '@id': member['@id'] }; + }); - let button = html` + const button = html` <solid-ac-checker data-src="${this.dataSrc}" permission="acl:Write" > @@ -127,7 +140,7 @@ export const SolidMemberAdd = { </solid-ac-checker> `; render(button, this.element); - } + }, }; -Sib.register(SolidMemberAdd); \ No newline at end of file +Sib.register(SolidMemberAdd); diff --git a/src/components/solid-member-delete.ts b/src/components/solid-member-delete.ts index 9e90c1ba0f6d322f5284b17c7c3c95cc08525e2b..39e2f764fd5e5965d254d805fa64b76c57fb757c 100644 --- a/src/components/solid-member-delete.ts +++ b/src/components/solid-member-delete.ts @@ -1,11 +1,12 @@ -import { Sib } from '../libs/Sib'; -import { base_context, store } from '../libs/store/store'; -import { NextMixin } from '../mixins/nextMixin'; -import { ValidationMixin } from '../mixins/validationMixin'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { Sib } from '../libs/Sib.ts'; +import { base_context, store } from '../libs/store/store.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { ValidationMixin } from '../mixins/validationMixin.ts'; -import { html, render } from 'lit-html'; -import { ContextMixin } from '../mixins/contextMixin'; +import { html, render } from 'lit'; +import { trackRenderAsync } from '../logger.ts'; +import { ContextMixin } from '../mixins/contextMixin.ts'; export const SolidMemberDelete = { name: 'solid-member-delete', @@ -33,12 +34,12 @@ export const SolidMemberDelete = { callback: function (newValue: string, oldValue: string) { if (newValue !== oldValue) { this.planRender(); - } + } }, }, dataUnknownMember: { type: String, - default: "Given user is not a member of this group", + default: 'Given user is not a member of this group', callback: function (newValue: string, oldValue: string) { if (newValue !== oldValue) this.planRender(); }, @@ -62,20 +63,23 @@ export const SolidMemberDelete = { if (!this.resource) return; // Check if current user is member of this group ? - let memberPredicate = store.getExpandedPredicate('user_set', base_context); + const memberPredicate = store.getExpandedPredicate( + 'user_set', + base_context, + ); this.currentMembers = await this.resource[memberPredicate]; if (!Array.isArray(this.currentMembers)) { this.currentMembers = [this.currentMembers]; } - this.currentMembers = this.currentMembers.map((member) => { - return { "@id": member['@id'] }; + this.currentMembers = this.currentMembers.map(member => { + return { '@id': member['@id'] }; }); // Check if current user is member of this group this.isMember = this.currentMembers - ? this.currentMembers.some((member) => member['@id'] === this.dataTargetSrc) + ? this.currentMembers.some(member => member['@id'] === this.dataTargetSrc) : false; }, planRender() { @@ -87,45 +91,50 @@ export const SolidMemberDelete = { }); } }, - async removeMember(e: Event): Promise<void> { + removeMember(e: Event) { e.stopPropagation(); if (!this.dataSrc) return; this.performAction(); // In validationMixin, method defining what to do according to the present attributes }, async deleteMembership() { - let userSet = this.currentMembers.filter((value) => { + const userSet = this.currentMembers.filter(value => { const userId = value['@id']; - if (userId == this.dataTargetSrc) - return false; - else return true; + if (userId === this.dataTargetSrc) return false; + return true; }); - let currentRes = { - "@context": this.context, - "user_set": userSet - } + const currentRes = { + '@context': this.context, + user_set: userSet, + }; return store.patch(currentRes, this.dataSrc).then(response => { if (!response) { - console.warn(`Error while removing user ${this.dataTargetSrc} from group ${this.dataSrc}`); + console.warn( + `Error while removing user ${this.dataTargetSrc} from group ${this.dataSrc}`, + ); return; } this.goToNext(null); - const eventData = { detail: { resource: { "@id": this.dataSrc } }, bubbles: true }; + const eventData = { + detail: { resource: { '@id': this.dataSrc } }, + bubbles: true, + }; this.element.dispatchEvent(new CustomEvent('save', eventData)); this.element.dispatchEvent(new CustomEvent('memberRemoved', eventData)); // Deprecated. To remove in 0.15 this.planRender(); - }) + }); }, - validateModal() { // Send method to validationMixin, used by the dialog modal and performAction method + validateModal() { + // Send method to validationMixin, used by the dialog modal and performAction method return this.deleteMembership(); }, update() { this.render(); }, - async render(): Promise<void> { + render: trackRenderAsync(async function (): Promise<void> { // await this.replaceAttributesData(false); await this.populate(); - let button = html`` + let button = html``; if (this.isMember) { button = html` <solid-ac-checker data-src="${this.dataSrc}" @@ -134,18 +143,16 @@ export const SolidMemberDelete = { > <button @click=${this.removeMember.bind(this)}> - ${this.dataLabel || this.t("solid-delete-member.button")} + ${this.dataLabel || this.t('solid-delete-member.button')} </button> ${this.getModalDialog()} </solid-ac-checker> `; } else { - button = html` - <span>${this.dataUnknownMember || this.t("solid-member-unknown.span")}</span> - `; + button = html`<span>${this.dataUnknownMember || this.t('solid-member-unknown.span')}</span>`; } render(button, this.element); - } + }, 'SolidMemberDelete:render'), }; -Sib.register(SolidMemberDelete); \ No newline at end of file +Sib.register(SolidMemberDelete); diff --git a/src/components/solid-membership.ts b/src/components/solid-membership.ts index 0e898e90f77fe859d15dcc4193a91abd8888ded9..af719c70535e75f825d918a77112ebd0db27775e 100644 --- a/src/components/solid-membership.ts +++ b/src/components/solid-membership.ts @@ -1,11 +1,12 @@ -import { Sib } from '../libs/Sib'; -import { base_context, store } from '../libs/store/store'; -import { NextMixin } from '../mixins/nextMixin'; -import { ValidationMixin } from '../mixins/validationMixin'; +import { Sib } from '../libs/Sib.ts'; +import { base_context, store } from '../libs/store/store.ts'; +import { NextMixin } from '../mixins/nextMixin.ts'; +import { ValidationMixin } from '../mixins/validationMixin.ts'; -import { html, render } from 'lit-html'; -import { ContextMixin } from '../mixins/contextMixin'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { trackRenderAsync } from '../logger.ts'; +import { ContextMixin } from '../mixins/contextMixin.ts'; export const SolidMembership = { name: 'solid-membership', @@ -20,7 +21,7 @@ export const SolidMembership = { }, dataTargetSrc: { type: String, - default: null + default: null, }, dataLeaveLabel: { type: String, @@ -39,7 +40,7 @@ export const SolidMembership = { classSubmitButton: { type: String, default: undefined, - } + }, }, initialState: { renderPlanned: false, @@ -51,13 +52,11 @@ export const SolidMembership = { if (!store.session) return; // Retrieve the current user from the current store authenticated session - let currentUserSession = await store.session; + const currentUserSession = await store.session; if (!currentUserSession) return; - if (!this.dataTargetSrc) - this.userId = await currentUserSession.webId; - else - this.userId = this.dataTargetSrc; + if (!this.dataTargetSrc) this.userId = await currentUserSession.webId; + else this.userId = this.dataTargetSrc; if (!this.userId) return; @@ -66,18 +65,23 @@ export const SolidMembership = { if (!this.resource) return; // Check if current user is member of this group ? - let memberPredicate = store.getExpandedPredicate('user_set', base_context); + const memberPredicate = store.getExpandedPredicate( + 'user_set', + base_context, + ); this.currentMembers = await this.resource[memberPredicate]; if (!Array.isArray(this.currentMembers)) { this.currentMembers = [this.currentMembers]; } - this.currentMembers = this.currentMembers.map(member => { return {"@id": member['@id'] } }); + this.currentMembers = this.currentMembers.map(member => { + return { '@id': member['@id'] }; + }); // Check if current user is member of this group this.isMember = this.currentMembers - ? this.currentMembers.some((member) => member['@id'] === this.userId) + ? this.currentMembers.some(member => member['@id'] === this.userId) : false; }, planRender() { @@ -89,92 +93,101 @@ export const SolidMembership = { }); } }, - async changeMembership(e: Event): Promise<void> { + changeMembership(e: Event) { e.stopPropagation(); if (!this.dataSrc) return; this.performAction(); // In validationMixin, method defining what to do according to the present attributes }, async joinGroup() { - this.currentMembers.push({"@id": this.userId}); - let currentRes = { - "@context": this.context, - "user_set": this.currentMembers - } + this.currentMembers.push({ '@id': this.userId }); + const currentRes = { + '@context': this.context, + user_set: this.currentMembers, + }; return store.patch(currentRes, this.dataSrc).then(response => { if (!response) { - console.warn(`Error while joining group ${this.dataSrc} for user ${this.userId}`); + console.warn( + `Error while joining group ${this.dataSrc} for user ${this.userId}`, + ); return; } this.goToNext(null); - const eventData = { detail: { resource: { "@id": this.dataSrc } }, bubbles: true }; + const eventData = { + detail: { resource: { '@id': this.dataSrc } }, + bubbles: true, + }; this.element.dispatchEvent(new CustomEvent('save', eventData)); this.element.dispatchEvent(new CustomEvent('memberAdded', eventData)); // Deprecated. To remove in 0.15 this.planRender(); }); }, async leaveGroup() { - let userSet = this.currentMembers.filter((value) => { + const userSet = this.currentMembers.filter(value => { const userId = value['@id']; - if (userId == this.userId) - return false; - else return true; + if (userId === this.userId) return false; + return true; }); - let currentRes = { - "@context": this.context, - "user_set": userSet - } + const currentRes = { + '@context': this.context, + user_set: userSet, + }; return store.patch(currentRes, this.dataSrc).then(response => { if (!response) { - console.warn(`Error while leaving group ${this.dataSrc} for user ${this.userId}`); + console.warn( + `Error while leaving group ${this.dataSrc} for user ${this.userId}`, + ); return; } this.goToNext(null); - const eventData = { detail: { resource: { "@id": this.dataSrc } }, bubbles: true }; + const eventData = { + detail: { resource: { '@id': this.dataSrc } }, + bubbles: true, + }; this.element.dispatchEvent(new CustomEvent('save', eventData)); this.element.dispatchEvent(new CustomEvent('memberRemoved', eventData)); // Deprecated. To remove in 0.15 this.planRender(); - }) + }); }, switchMembership() { if (this.isMember) { return this.leaveGroup(); - } else { - return this.joinGroup(); } + return this.joinGroup(); }, - validateModal() { // Send method to validationMixin, used by the dialog modal and performAction method + validateModal() { + // Send method to validationMixin, used by the dialog modal and performAction method return this.switchMembership(); }, update() { this.render(); }, - async render(): Promise<void> { + render: trackRenderAsync(async function (): Promise<void> { await this.populate(); let button = html``; if (this.isMember) { button = html` - <solid-ac-checker data-src="${this.dataSrc}" - permission="acl:Read" - class=${ifDefined(`${this.classSubmitButton ? 'leave ' + this.classSubmitButton: 'leave'}`)} - > - <button @click=${this.changeMembership.bind(this)}>${this.dataLeaveLabel || this.t("solid-leave-group.button")}</button> - ${this.getModalDialog()} - </solid-ac-checker> - `; + <solid-ac-checker data-src="${this.dataSrc}" + permission="acl:Read" + class=${ifDefined(`${this.classSubmitButton ? `leave ${this.classSubmitButton}` : 'leave'}`)} + > + <button @click=${this.changeMembership.bind(this)}>${this.dataLeaveLabel || this.t('solid-leave-group.button')}</button> + ${this.getModalDialog()} + </solid-ac-checker> + `; } else { button = html` - <solid-ac-checker data-src="${this.dataSrc}" - permission="acl:Read" - class=${ifDefined(`${this.classSubmitButton ? 'join ' + this.classSubmitButton: 'join'}`)} - > - <button @click=${this.changeMembership.bind(this)}>${this.dataJoinLabel || this.t("solid-join-group.button")}</button> - ${this.getModalDialog()} - </solid-ac-checker> - `; + <solid-ac-checker data-src="${this.dataSrc}" + permission="acl:Read" + class=${ifDefined(`${this.classSubmitButton ? `join ${this.classSubmitButton}` : 'join'}`)} + > + <button @click=${this.changeMembership.bind(this)}>${this.dataJoinLabel || this.t('solid-join-group.button')}</button> + ${this.getModalDialog()} + </solid-ac-checker> + `; } render(button, this.element); - } + }, 'SolidMembership:render'), }; -Sib.register(SolidMembership); \ No newline at end of file +Sib.register(SolidMembership); diff --git a/src/components/solid-table.ts b/src/components/solid-table.ts index 519733c805d5fc98c62b3985c284273ab7cade24..0718f5fd81e3762d95791aff303cd8276b0803ee 100644 --- a/src/components/solid-table.ts +++ b/src/components/solid-table.ts @@ -1,21 +1,23 @@ -import type { Resource } from '../mixins/interfaces'; -import { Sib } from '../libs/Sib'; -import { store } from '../libs/store/store'; -import { WidgetMixin } from '../mixins/widgetMixin'; -import { ListMixin } from '../mixins/listMixin'; -import { StoreMixin } from '../mixins/storeMixin'; -import { PaginateMixin } from '../mixins/paginateMixin'; -import { FilterMixin } from '../mixins/filterMixin'; -import { CounterMixin } from '../mixins/counterMixin'; -import { SorterMixin } from '../mixins/sorterMixin'; -import { GrouperMixin } from '../mixins/grouperMixin'; -import { FederationMixin } from '../mixins/federationMixin'; -import { HighlighterMixin } from '../mixins/highlighterMixin'; -import { RequiredMixin } from '../mixins/requiredMixin'; +import { Sib } from '../libs/Sib.ts'; +import { store } from '../libs/store/store.ts'; +import { CounterMixin } from '../mixins/counterMixin.ts'; +import { FederationMixin } from '../mixins/federationMixin.ts'; +import { FilterMixin } from '../mixins/filterMixin.ts'; +import { GrouperMixin } from '../mixins/grouperMixin.ts'; +import { HighlighterMixin } from '../mixins/highlighterMixin.ts'; +import type { Resource } from '../mixins/interfaces.ts'; +import { ListMixin } from '../mixins/listMixin.ts'; +import { PaginateMixin } from '../mixins/paginateMixin.ts'; +import { RequiredMixin } from '../mixins/requiredMixin.ts'; +import { SorterMixin } from '../mixins/sorterMixin.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; +import { WidgetMixin } from '../mixins/widgetMixin.ts'; -import { html, render } from 'lit-html'; -import { until } from 'lit-html/directives/until'; -import { spread } from '../libs/lit-helpers'; +import { html, render } from 'lit'; +import { until } from 'lit/directives/until.js'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { spread } from '../libs/lit-helpers.ts'; +import { trackRenderAsync } from '../logger.ts'; export const SolidTable = { name: 'solid-table', @@ -46,6 +48,9 @@ export const SolidTable = { default: null, }, }, + initialState: { + resources: [], + }, get parentElement(): string { return 'table'; }, @@ -57,8 +62,11 @@ export const SolidTable = { }, get selectedLines() { if (this.selectable === null) return []; - return (Array.from(this.element.querySelectorAll('input[data-selection]:checked')) as Element[]) - .map(e => e?.closest('[data-resource]')?.getAttribute('data-resource')); + return ( + Array.from( + this.element.querySelectorAll('input[data-selection]:checked'), + ) as Element[] + ).map(e => e?.closest('[data-resource]')?.getAttribute('data-resource')); }, /** * Select all lines @@ -66,7 +74,11 @@ export const SolidTable = { */ selectAll(e) { if (this.selectable === null) return; - for (const checkbox of Array.from(this.element.querySelectorAll('input[data-selection]') as HTMLInputElement[])) { + for (const checkbox of Array.from( + this.element.querySelectorAll( + 'input[data-selection]', + ) as HTMLInputElement[], + )) { checkbox.checked = e.target.checked; } }, @@ -75,7 +87,11 @@ export const SolidTable = { */ unselectAll(): void { if (this.selectable === null) return; - for (const checkbox of Array.from(this.element.querySelectorAll('input[data-selection]') as HTMLInputElement[])) { + for (const checkbox of Array.from( + this.element.querySelectorAll( + 'input[data-selection]', + ) as HTMLInputElement[], + )) { checkbox.checked = false; } }, @@ -86,7 +102,9 @@ export const SolidTable = { selectLines(lines: string[]) { if (this.selectable === null || lines.length === 0) return; for (const line of lines) { - const checkbox = this.element.querySelector(`[data-resource="${line}"] input[data-selection]`); + const checkbox = this.element.querySelector( + `[data-resource="${line}"] input[data-selection]`, + ); if (checkbox) checkbox.checked = true; } }, @@ -95,13 +113,15 @@ export const SolidTable = { * @param field * @param resource */ - async createCellWidget(field: string, resource: Resource) { + createCellWidget(field: string, resource: Resource) { // if regular widget - if (!this.element.hasAttribute('editable-' + field)) return this.createWidgetTemplate(field, resource, true); + if (!this.element.hasAttribute(`editable-${field}`)) + return this.createWidgetTemplate(field, resource, true); // if editable widget const attributes = {}; - const formWidgetAttributes = [ // attributes to give to the form widget + const formWidgetAttributes = [ + // attributes to give to the form widget 'range', 'enum', 'placeholder', @@ -113,16 +133,19 @@ export const SolidTable = { 'max', 'pattern', 'title', - 'widget' + 'widget', ]; - for (let attr of formWidgetAttributes) this.addToAttributes(`${attr}-${field}`, `${attr}-${field}`, attributes) + for (const attr of formWidgetAttributes) + this.addToAttributes(`${attr}-${field}`, `${attr}-${field}`, attributes); - const formAttributes = [ // attributes to give to the form + const formAttributes = [ + // attributes to give to the form 'class', 'submit-button', - 'next' + 'next', ]; - for (let attr of formAttributes) this.addToAttributes(`${attr}-${field}`, attr, attributes) + for (const attr of formAttributes) + this.addToAttributes(`${attr}-${field}`, attr, attributes); return html` <solid-form @@ -139,18 +162,12 @@ export const SolidTable = { * @param fields */ getHeader(fields: string[]) { - let template = html` + const template = html` <tr> - ${this.selectable !== null ? html` - <th> - <input type="checkbox" @change="${this.selectAll.bind(this)}" /> - </th>` : ''} - ${fields.map((field: string) => html` - <th> - ${this.element.hasAttribute('label-'+field) ? this.element.getAttribute('label-'+field) : field} - </th>`)} + ${this.selectable !== null ? html`<th><input type="checkbox" @change="${this.selectAll.bind(this)}" /></th>` : ''} + ${fields.map((field: string) => html`<th>${this.element.hasAttribute(`label-${field}`) ? this.element.getAttribute(`label-${field}`) : field}</th>`)} </tr> - ` + `; return template; }, /** @@ -160,15 +177,12 @@ export const SolidTable = { */ async getChildTemplate(resourceId: string, fields) { const resource = await store.getData(resourceId, this.context); - let template = html` + const template = html` <tr data-resource="${resourceId}"> - ${this.selectable !== null ? html` - <td> - <input type="checkbox" data-selection /> - </td>` : ''} + ${this.selectable !== null ? html`<td><input type="checkbox" data-selection /></td>` : ''} ${fields.map((field: string) => html`<td>${until(this.createCellWidget(field, resource))}</td>`)} </tr> - ` + `; return template; }, @@ -179,10 +193,7 @@ export const SolidTable = { async appendSingleElt(parent: HTMLElement): Promise<void> { const fields = await this.getFields(); - const template = html` - ${this.header !== null ? this.getHeader(fields) : ''} - ${until(this.getChildTemplate(this.resource['@id'], fields))} - `; + const template = html`${this.header !== null ? this.getHeader(fields) : ''}${until(this.getChildTemplate(this.resource['@id'], fields))}`; render(template, parent); }, @@ -195,21 +206,18 @@ export const SolidTable = { * @param div * @param context */ - async renderDOM( + renderDOM: trackRenderAsync(async function ( resources: object[], - listPostProcessors: Function[], + listPostProcessors: PostProcessorRegistry, div: HTMLElement, context: string, ) { const selectedLines = [...this.selectedLines]; // save selected lines before moving them const fields = await this.getFields(); const childTemplates = await Promise.all( - resources.map(r => r ? this.getChildTemplate(r['@id'], fields) : null) + resources.map(r => (r ? this.getChildTemplate(r['@id'], fields) : null)), ); - const template = html` - ${this.header !== null ? this.getHeader(fields) : ''} - ${childTemplates} - `; // create a child template for each resource + const template = html`${this.header !== null ? this.getHeader(fields) : ''}${childTemplates}`; // create a child template for each resource render(template, div); // Re-select the right lines @@ -218,13 +226,8 @@ export const SolidTable = { const nextProcessor = listPostProcessors.shift(); if (nextProcessor) - await nextProcessor( - resources, - listPostProcessors, - div, - context - ); - }, + await nextProcessor(resources, listPostProcessors, div, context); + }, 'SolidTable:renderDom'), }; Sib.register(SolidTable); diff --git a/src/components/solid-widget.ts b/src/components/solid-widget.ts index 09a2853d40ee898bcac95647fbcf01f2151aed4f..cad09985431f9b338fdc84ca2ab6fa8b79c90ba2 100644 --- a/src/components/solid-widget.ts +++ b/src/components/solid-widget.ts @@ -1,11 +1,11 @@ -import { Sib } from '../libs/Sib'; -import { StoreMixin } from '../mixins/storeMixin'; -import { BaseWidgetMixin } from '../new-widgets/baseWidgetMixin'; -import { FormMixin } from '../new-widgets/templatesDependencies/formMixin'; -import { ActionMixin } from '../new-widgets/attributeMixins/actionMixin'; -import { evalTemplateString } from '../libs/helpers'; -import { html, render } from 'lit-html'; -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +import { html, render } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { Sib } from '../libs/Sib.ts'; +import { evalTemplateString } from '../libs/helpers.ts'; +import { StoreMixin } from '../mixins/storeMixin.ts'; +import { ActionMixin } from '../new-widgets/attributeMixins/actionMixin.ts'; +import { BaseWidgetMixin } from '../new-widgets/baseWidgetMixin.ts'; +import { FormMixin } from '../new-widgets/templatesDependencies/formMixin.ts'; export const SolidWidget = { name: 'solid-widget', @@ -13,35 +13,33 @@ export const SolidWidget = { attributes: { name: { type: String, - default: "", - required: true - } + default: '', + required: true, + }, }, attached(): void { if (!this.name) return; const template = this.template; const newWidget = { name: this.name, - use: [ - BaseWidgetMixin, - StoreMixin, - FormMixin, - ActionMixin - ], + use: [BaseWidgetMixin, StoreMixin, FormMixin, ActionMixin], attributes: { label: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'label'); - } + }, }, }, get template() { - return () => this.evalTemplate(template).then((tpl: string) => html`${unsafeHTML(tpl)}`) + return () => + this.evalTemplate(template).then( + (tpl: string) => html`${unsafeHTML(tpl)}`, + ); }, evalTemplate(template: string) { - const tpl = evalTemplateString(template, { + const tpl = evalTemplateString(template, { name: this.name, value: this.value || this.resource || '', src: this.src, @@ -54,14 +52,16 @@ export const SolidWidget = { render(await template, this.element); }, // For form widgets, handle nested solid-form + // TODO: type custom elements getValueFromElement(element: any) { - if (element.tagName === "SOLID-FORM") return element.component.value; // nested solid-form - else if (element.component) return element.component.getValue(); // form widget + if (element.tagName === 'SOLID-FORM') return element.component.value; // nested solid-form + if (element.component) return element.component.getValue(); // form widget return element.value; // input }, - updateDOM() { // override StoreMixin method to launch render when resource fetched + updateDOM() { + // override StoreMixin method to launch render when resource fetched this.planRender(); - } + }, }; Sib.register(newWidget); // and register component @@ -72,7 +72,7 @@ export const SolidWidget = { get childTemplate(): string | null { const child = this.element.querySelector('template[data-range]'); return child ? child.innerHTML : null; - } + }, }; -Sib.register(SolidWidget); \ No newline at end of file +Sib.register(SolidWidget); diff --git a/src/index.ts b/src/index.ts index bc7b32ce4a7ab1c6716ea4243d738e33227f8d34..28f6c5c40e42b551d819badef4828f92e651ceb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,55 +1,54 @@ -import "./libs/polyfills.js"; +import './libs/polyfills.js'; +import { SolidAcChecker } from './components/solid-ac-checker.ts'; +import { SolidDelete } from './components/solid-delete.ts'; // Components -import { SolidDisplay } from './components/solid-display'; -import { SolidForm } from './components/solid-form'; -import { SolidFormSearch } from './components/solid-form-search'; -import { SolidWidget } from './components/solid-widget'; -import { SolidAcChecker } from './components/solid-ac-checker'; -import { SolidDelete } from './components/solid-delete'; -import { SolidLang } from './components/solid-lang'; -import { SolidTable } from './components/solid-table'; -import { SolidMap } from './components/solid-map'; -import { SolidMembership } from './components/solid-membership'; -import { SolidMemberDelete } from './components/solid-member-delete'; -import { SolidMemberAdd } from './components/solid-member-add'; +import { SolidDisplay } from './components/solid-display.ts'; +import { SolidFormSearch } from './components/solid-form-search.ts'; +import { SolidForm } from './components/solid-form.ts'; +import { SolidLang } from './components/solid-lang.ts'; +import { SolidMemberAdd } from './components/solid-member-add.ts'; +import { SolidMemberDelete } from './components/solid-member-delete.ts'; +import { SolidMembership } from './components/solid-membership.ts'; +import { SolidTable } from './components/solid-table.ts'; +import { SolidWidget } from './components/solid-widget.ts'; // Mixins -import { CounterMixin } from './mixins/counterMixin'; -import { FederationMixin } from './mixins/federationMixin'; -import { FilterMixin } from './mixins/filterMixin'; -import { GrouperMixin } from './mixins/grouperMixin'; -import { HighlighterMixin } from './mixins/highlighterMixin'; -import { ListMixin } from './mixins/listMixin'; -import { NextMixin } from './mixins/nextMixin'; -import { PaginateMixin } from './mixins/paginateMixin'; -import { RequiredMixin } from './mixins/requiredMixin'; -import { SorterMixin } from './mixins/sorterMixin'; -import { StoreMixin } from './mixins/storeMixin'; -import { TranslationMixin } from './mixins/translationMixin'; -import { ValidationMixin } from './mixins/validationMixin'; -import { WidgetMixin } from './mixins/widgetMixin'; +import { CounterMixin } from './mixins/counterMixin.ts'; +import { FederationMixin } from './mixins/federationMixin.ts'; +import { FilterMixin } from './mixins/filterMixin.ts'; +import { GrouperMixin } from './mixins/grouperMixin.ts'; +import { HighlighterMixin } from './mixins/highlighterMixin.ts'; +import { ListMixin } from './mixins/listMixin.ts'; +import { NextMixin } from './mixins/nextMixin.ts'; +import { PaginateMixin } from './mixins/paginateMixin.ts'; +import { RequiredMixin } from './mixins/requiredMixin.ts'; +import { SorterMixin } from './mixins/sorterMixin.ts'; +import { StoreMixin } from './mixins/storeMixin.ts'; +import { TranslationMixin } from './mixins/translationMixin.ts'; +import { ValidationMixin } from './mixins/validationMixin.ts'; +import { WidgetMixin } from './mixins/widgetMixin.ts'; +import * as AttributeMixins from './new-widgets/attributeMixins/index.ts'; +import { BaseWidgetMixin } from './new-widgets/baseWidgetMixin.ts'; +import * as CallbackMixins from './new-widgets/callbackMixins/index.ts'; // New widgets system -import { newWidgetFactory } from './new-widgets/new-widget-factory'; -import { BaseWidgetMixin } from './new-widgets/baseWidgetMixin'; -import * as AttributeMixins from './new-widgets/attributeMixins'; -import * as CallbackMixins from './new-widgets/callbackMixins'; -import * as TemplateAdditionMixins from './new-widgets/templateAdditionMixins'; -import * as Templates from './new-widgets/templates'; -import * as TemplatesDependenciesMixins from './new-widgets/templatesDependencies'; +import { newWidgetFactory } from './new-widgets/new-widget-factory.ts'; +import * as TemplateAdditionMixins from './new-widgets/templateAdditionMixins/index.ts'; +import * as Templates from './new-widgets/templates/index.ts'; +import * as TemplatesDependenciesMixins from './new-widgets/templatesDependencies/index.ts'; +import { Sib } from './libs/Sib.ts'; +import * as Helpers from './libs/helpers.ts'; // Libs -import { store, base_context as baseContext } from './libs/store/store'; -import { Sib } from './libs/Sib'; -import SolidTemplateElement from './solid-template-element'; -import { widgetFactory } from './widgets/widget-factory'; -import * as Helpers from './libs/helpers'; +import { base_context as baseContext, store } from './libs/store/store.ts'; +import SolidTemplateElement from './solid-template-element.ts'; +import { widgetFactory } from './widgets/widget-factory.ts'; // lit-html -import { html, render } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; -import { until } from 'lit-html/directives/until'; -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { until } from 'lit/directives/until.js'; export { // Components @@ -61,11 +60,9 @@ export { SolidDelete, SolidLang, SolidTable, - SolidMap, SolidMembership, SolidMemberDelete, SolidMemberAdd, - // Mixins CounterMixin, FederationMixin, @@ -81,14 +78,12 @@ export { TranslationMixin, ValidationMixin, WidgetMixin, - // New widgets system AttributeMixins, CallbackMixins, TemplateAdditionMixins, TemplatesDependenciesMixins, Templates, - // Libs store, Sib, @@ -98,11 +93,10 @@ export { BaseWidgetMixin, Helpers, baseContext, - // lit-html html, render, ifDefined, until, - unsafeHTML -} \ No newline at end of file + unsafeHTML, +}; diff --git a/src/libs/Component.ts b/src/libs/Component.ts index e655a190b121a10725782304e8ec84d151dc6ee2..21e4b49d51294adec5b0b2c091c0e26fc2567233 100644 --- a/src/libs/Component.ts +++ b/src/libs/Component.ts @@ -1,15 +1,18 @@ -import type { ComponentInterface } from "./interfaces.js"; +import { Profiler } from '../logger.ts'; +import type { ComponentInterface } from './interfaces.js'; export abstract class Component implements ComponentInterface { public element: HTMLElement; + public profiler: Profiler; constructor(element: HTMLElement) { this.element = element; + this.profiler = new Profiler(); } created() {} attached() {} detached() {} - attributesCallback(_key: string, _value: any, _oldValue: any):void {} + attributesCallback(_key: string, _value: unknown, _oldValue: unknown): void {} } diff --git a/src/libs/ComponentFactory.ts b/src/libs/ComponentFactory.ts index 3f0228ea1dbea7de05f82711f9ecb240370bae78..373cdf7ea285a21f667e8c8c3c8fc724a720aaae 100644 --- a/src/libs/ComponentFactory.ts +++ b/src/libs/ComponentFactory.ts @@ -1,56 +1,78 @@ -import { Compositor } from './Compositor'; -import { Component } from './Component'; +import { Component } from './Component.ts'; +import { Compositor } from './Compositor.ts'; import type { - MixinStaticInterface, + AccessorStaticInterface, + ArrayOfHooksInterface, AttributesDefinitionInterface, ComponentConstructorInterface, - ArrayOfHooksInterface, - AccessorStaticInterface -} from './interfaces'; + MixinStaticInterface, +} from './interfaces.ts'; -export class ComponentFactory { - public static build(component: MixinStaticInterface): ComponentConstructorInterface { - const { initialState, attributes, methods, hooks, accessors, name } = Compositor.merge(component, Compositor.mergeMixin(component)); +export const ComponentFactory = { + build(component: MixinStaticInterface): ComponentConstructorInterface { + const { initialState, attributes, methods, hooks, accessors, name } = + Compositor.merge(component, Compositor.mergeMixin(component)); let componentConstructor = class extends Component {}; - componentConstructor = ComponentFactory.bindInitialState(componentConstructor, initialState); - componentConstructor = ComponentFactory.bindAttributes(componentConstructor, attributes); - componentConstructor = ComponentFactory.bindMethods(componentConstructor, methods); - componentConstructor = ComponentFactory.bindAccessors(componentConstructor, accessors); - componentConstructor = ComponentFactory.bindHooks(componentConstructor, hooks); + componentConstructor = ComponentFactory.bindInitialState( + componentConstructor, + initialState, + ); + componentConstructor = ComponentFactory.bindAttributes( + componentConstructor, + attributes, + ); + componentConstructor = ComponentFactory.bindMethods( + componentConstructor, + methods, + ); + componentConstructor = ComponentFactory.bindAccessors( + componentConstructor, + accessors, + ); + componentConstructor = ComponentFactory.bindHooks( + componentConstructor, + hooks, + ); Reflect.defineProperty(componentConstructor, 'name', { value: name, }); return componentConstructor; - } - - protected static bindInitialState(componentConstructor: ComponentConstructorInterface, initialState: object | undefined):any { + }, + bindInitialState( + componentConstructor: ComponentConstructorInterface, + initialState?: object, + ): ComponentConstructorInterface { if (initialState) { - Reflect.ownKeys(initialState).forEach(key => { + for (const key of Reflect.ownKeys(initialState)) { Reflect.defineProperty(componentConstructor.prototype, key, { enumerable: true, writable: true, value: initialState[key], }); - }); + } } return componentConstructor; - } - - protected static bindAttributes(componentConstructor: ComponentConstructorInterface, attributes: AttributesDefinitionInterface | undefined): ComponentConstructorInterface { + }, + bindAttributes( + componentConstructor: ComponentConstructorInterface, + attributes?: AttributesDefinitionInterface, + ): ComponentConstructorInterface { if (attributes) { - const attributesList = Reflect.ownKeys(attributes).map(key => String(key)); + const attributesList = Reflect.ownKeys(attributes).map(key => + String(key), + ); const attributesCallback = {}; - attributesList.forEach(key => { + for (const key of attributesList) { const { default: def, type, required, callback } = attributes[key]; - let fromType; - let toType; + let fromType: (value: string) => unknown; + let toType: (value: unknown) => unknown; switch (type) { case String: @@ -75,7 +97,9 @@ export class ComponentFactory { break; } - const attribute = key.replace(/([a-z0-9])([A-Z0-9])/g, '$1-$2').toLowerCase(); + const attribute = key + .replace(/([a-z0-9])([A-Z0-9])/g, '$1-$2') + .toLowerCase(); Reflect.defineProperty(componentConstructor.prototype, key, { enumerable: true, @@ -107,43 +131,61 @@ export class ComponentFactory { if (callback && typeof callback === 'function') { attributesCallback[key] = callback; } - }); + } Reflect.defineProperty(componentConstructor, 'observedAttributes', { - get: () => attributesList.map(attr => attr.replace(/([a-z0-9])([A-Z0-9])/g, '$1-$2').toLowerCase()), + get: () => + attributesList.map(attr => + attr.replace(/([a-z0-9])([A-Z0-9])/g, '$1-$2').toLowerCase(), + ), }); - Reflect.defineProperty(componentConstructor.prototype, 'attributesCallback', { - value: function(key, newValue, oldValue) { - if (key in attributesCallback) { - Reflect.apply(attributesCallback[key], this, [newValue, oldValue]); - } - } - }); + Reflect.defineProperty( + componentConstructor.prototype, + 'attributesCallback', + { + value: function (key, newValue, oldValue) { + if (key in attributesCallback) { + Reflect.apply(attributesCallback[key], this, [ + newValue, + oldValue, + ]); + } + }, + }, + ); - Reflect.defineProperty(componentConstructor.prototype, 'attributesCallback', attributesCallback); + Reflect.defineProperty( + componentConstructor.prototype, + 'attributesCallback', + attributesCallback, + ); } return componentConstructor; - } - - protected static bindAccessors(componentConstructor: ComponentConstructorInterface, accessors: AccessorStaticInterface): ComponentConstructorInterface { + }, + bindAccessors( + componentConstructor: ComponentConstructorInterface, + accessors?: AccessorStaticInterface, + ): ComponentConstructorInterface { if (accessors) { - Object.keys(accessors).forEach(property => { + for (const property of Object.keys(accessors)) { Reflect.defineProperty(componentConstructor.prototype, property, { get: function () { - return Reflect.apply(accessors[property].get, this, []) + return Reflect.apply(accessors[property].get, this, []); }, set: function (value) { - return Reflect.apply(accessors[property].set, this, [value]) - } + return Reflect.apply(accessors[property].set, this, [value]); + }, }); - }); + } } return componentConstructor; - } - - protected static bindMethods(componentConstructor: ComponentConstructorInterface, methods: Map<string, Function>): ComponentConstructorInterface { - methods.forEach((method, methodName: string) => { + }, + bindMethods( + componentConstructor: ComponentConstructorInterface, + methods: Map<string, Function>, + ): ComponentConstructorInterface { + methods.forEach((method, methodName) => { Reflect.defineProperty(componentConstructor.prototype, methodName, { value: function (...args) { return Reflect.apply(method, this, args); @@ -151,32 +193,34 @@ export class ComponentFactory { }); }); return componentConstructor; - } - - protected static bindHooks(componentConstructor: ComponentConstructorInterface, hooks: ArrayOfHooksInterface): ComponentConstructorInterface { + }, + bindHooks( + componentConstructor: ComponentConstructorInterface, + hooks: ArrayOfHooksInterface, + ): ComponentConstructorInterface { Reflect.defineProperty(componentConstructor.prototype, 'created', { - value: function() { - hooks.created.forEach(hook => { + value: function () { + for (const hook of hooks.created) { Reflect.apply(hook, this, []); - }); + } }, }); Reflect.defineProperty(componentConstructor.prototype, 'attached', { - value: function() { - hooks.attached.forEach(hook => { + value: function () { + for (const hook of hooks.attached) { Reflect.apply(hook, this, []); - }); + } }, }); Reflect.defineProperty(componentConstructor.prototype, 'detached', { - value: function() { - hooks.detached.forEach(hook => { + value: function () { + for (const hook of hooks.detached) { Reflect.apply(hook, this, []); - }); + } }, }); return componentConstructor; - } -} + }, +}; diff --git a/src/libs/Compositor.ts b/src/libs/Compositor.ts index 829e2698da85ec2d7b5e68db39726ce059c7d0e7..b0a07842d2f399d458d7339433fccd65c8a2f525 100644 --- a/src/libs/Compositor.ts +++ b/src/libs/Compositor.ts @@ -1,44 +1,43 @@ import type { - MixinStaticInterface, - ComponentStaticInterface, - AttributesDefinitionInterface, + AccessorStaticInterface, ArrayOfHooksInterface, - AccessorStaticInterface -} from './interfaces'; + AttributesDefinitionInterface, + ComponentStaticInterface, + MixinStaticInterface, +} from './interfaces.ts'; const HOOKS = ['created', 'attached', 'detached']; -const API = [ - 'name', - 'use', - 'attributes', - 'initialState', - ...HOOKS, -]; +const API = ['name', 'use', 'attributes', 'initialState', ...HOOKS]; -export class Compositor { - public static merge(component: MixinStaticInterface, mixins: MixinStaticInterface[]): ComponentStaticInterface { +export const Compositor = { + merge( + component: MixinStaticInterface, + mixins: MixinStaticInterface[], + ): ComponentStaticInterface { return { name: component.name, - attributes: Compositor.mergeAttributes([ component, ...mixins ]), - initialState: Compositor.mergeInitialState([ component, ...mixins ]), - methods: Compositor.mergeMethods([ component, ...mixins]), - accessors: Compositor.mergeAccessors([ component, ...mixins]), - hooks: Compositor.mergeHooks([ component, ...mixins ]), + attributes: Compositor.mergeAttributes([component, ...mixins]), + initialState: Compositor.mergeInitialState([component, ...mixins]), + methods: Compositor.mergeMethods([component, ...mixins]), + accessors: Compositor.mergeAccessors([component, ...mixins]), + hooks: Compositor.mergeHooks([component, ...mixins]), }; - } - - public static mergeMixin(component: MixinStaticInterface): MixinStaticInterface[] { - function deepMergeMixin(mixinAccumulator: Map<MixinStaticInterface, MixinStaticInterface>, currentMixin: MixinStaticInterface) { + }, + mergeMixin(component: MixinStaticInterface): MixinStaticInterface[] { + function deepMergeMixin( + mixinAccumulator: Map<MixinStaticInterface, MixinStaticInterface>, + currentMixin: MixinStaticInterface, + ) { const { use: currentMixins } = currentMixin; if (currentMixins) { - currentMixins.forEach(mix => { + for (const mix of currentMixins) { if (!mixinAccumulator.has(mix)) { mixinAccumulator.set(mix, mix); deepMergeMixin(mixinAccumulator, mix); } else { console.warn(`Duplicate mixin import (${mix.name})`); } - }); + } } } @@ -46,88 +45,75 @@ export class Compositor { deepMergeMixin(mixins, component); return Array.from(mixins.values()); - } - - public static mergeAttributes(mixins: MixinStaticInterface[]): AttributesDefinitionInterface { + }, + mergeAttributes( + mixins: MixinStaticInterface[], + ): AttributesDefinitionInterface { let attributes = {}; - mixins.forEach(mixin => { - if (!!mixin.attributes) { - attributes = {...mixin.attributes, ...attributes }; + for (const mixin of mixins) { + if (mixin.attributes) { + attributes = { ...mixin.attributes, ...attributes }; } - }); + } return attributes; - } + }, + mergeInitialState(mixins: MixinStaticInterface[]) { + let initialState: any = {}; - public static mergeInitialState(mixins: MixinStaticInterface[]): any { - let initialState = {}; - - mixins.forEach(mixin => { - if (!!mixin.initialState) { - initialState = {...mixin.initialState, ...initialState }; - } - }); + for (const mixin of mixins) { + if (!mixin.initialState) continue; + initialState = { ...mixin.initialState, ...initialState }; + } return initialState; - } - - public static mergeHooks(mixins: MixinStaticInterface[]): ArrayOfHooksInterface { + }, + mergeHooks(mixins: MixinStaticInterface[]): ArrayOfHooksInterface { const hooks = { created: [], attached: [], detached: [], }; - mixins - .reverse() - .forEach(mixin => { - HOOKS.forEach(hookName => { - if(!!mixin[hookName] && typeof mixin[hookName] === 'function') { - hooks[hookName].push(mixin[hookName]); - } - }); - }); - + for (const mixin of mixins.reverse()) { + for (const hookName of HOOKS) { + if (!!mixin[hookName] && typeof mixin[hookName] === 'function') { + hooks[hookName].push(mixin[hookName]); + } + } + } return hooks; - } - - public static mergeMethods(mixins: MixinStaticInterface[]): Map<any, any> { + }, + mergeMethods(mixins: MixinStaticInterface[]): Map<any, any> { const methods = new Map(); - mixins.reverse().forEach(mixin => { - const keys = Reflect - .ownKeys(mixin) - .filter(key => ( - typeof key === 'string' && - API.indexOf(key) < 0 && - !Object.getOwnPropertyDescriptor(mixin, key)!.get && - !Object.getOwnPropertyDescriptor(mixin, key)!.set && - typeof mixin[key] === 'function')); - - keys.forEach(key => { + for (const mixin of mixins.reverse()) { + for (const key of Reflect.ownKeys(mixin)) { + if (typeof key !== 'string') continue; + if (API.includes(key)) continue; + const descriptor = Object.getOwnPropertyDescriptor(mixin, key); + if (descriptor?.get || descriptor?.set) continue; + if (typeof mixin[key] !== 'function') continue; methods.set(key, mixin[key]); - }); - }); + } + } return methods; - } - - public static mergeAccessors(mixins: MixinStaticInterface[]): AccessorStaticInterface { + }, + mergeAccessors(mixins: MixinStaticInterface[]): AccessorStaticInterface { const accessors = {}; - mixins.reverse().forEach(mixin => { - Reflect - .ownKeys(mixin) - .filter(key => ( - typeof key === 'string' && - API.indexOf(key) < 0 && - (Object.getOwnPropertyDescriptor(mixin, key)!.get || Object.getOwnPropertyDescriptor(mixin, key)!.set) - )) - .forEach(prop => { + for (const mixin of mixins.reverse()) { + for (const prop of Reflect.ownKeys(mixin)) { + if (typeof prop !== 'string') continue; + if (API.includes(prop)) continue; + const descriptor = Object.getOwnPropertyDescriptor(mixin, prop); + if (!descriptor) continue; + if (!descriptor.get && !descriptor.set) continue; accessors[prop] = { ...accessors[prop] }; - if (Reflect.getOwnPropertyDescriptor(mixin, prop)!.get) accessors[prop].get = Reflect.getOwnPropertyDescriptor(mixin, prop)!.get; - if (Reflect.getOwnPropertyDescriptor(mixin, prop)!.set) accessors[prop].set = Reflect.getOwnPropertyDescriptor(mixin, prop)!.set; - }); - }); + if (descriptor.get) accessors[prop].get = descriptor.get; + if (descriptor.set) accessors[prop].set = descriptor.set; + } + } return accessors; - } -} + }, +}; diff --git a/src/libs/PostProcessorRegistry.ts b/src/libs/PostProcessorRegistry.ts new file mode 100644 index 0000000000000000000000000000000000000000..ef855e17b13ef66017cdd02e8134ddd75df8f289 --- /dev/null +++ b/src/libs/PostProcessorRegistry.ts @@ -0,0 +1,76 @@ +export type PostProcessor = { + name: string; + fn: Function; +}; + +export class PostProcessorRegistry { + private currentPostProcessors: PostProcessor[]; + + constructor(currentPostProcessors: PostProcessor[] = []) { + this.currentPostProcessors = [...currentPostProcessors]; + } + + public attach(callback: Function, callbackName: string): void { + this.currentPostProcessors.push({ name: callbackName, fn: callback }); + } + + public getPostProcessors(): PostProcessor[] { + return this.currentPostProcessors; + } + + public printCurrentCallbacks(): void { + if (this.currentPostProcessors.length === 0) { + console.log('No post-processors registered.'); + } else { + console.log('Registered post-processors:'); + for (const postProcessor of this.currentPostProcessors) { + console.log(`- ${postProcessor.name}`); + } + } + } + + public getFormattedCallbacks(): string { + if (this.currentPostProcessors.length === 0) { + return 'No post-processors registered.'; + } + let formattedText = 'Registered post-processors:\n'; + for (const postProcessor of this.currentPostProcessors) { + formattedText += `- ${postProcessor.name}\n`; + } + return formattedText.trim(); + } + + static printFormattedCallbacks( + currentPostProcessors: PostProcessor[], + ): string { + if (currentPostProcessors.length === 0) { + return 'No post-processors registered.'; + } + let formattedText = 'Registered post-processors:\n'; + for (const postProcessor of currentPostProcessors) { + formattedText += `- ${postProcessor.name}\n`; + } + return formattedText.trim(); + } + + public whichCallbackExecutedNext(): string { + if (this.currentPostProcessors.length === 0) { + return 'No post-processors registered.'; + } + return `Next post-processor to be executed is: ${this.currentPostProcessors[0].name}`; + } + + public deepCopy(): PostProcessorRegistry { + const copy = new PostProcessorRegistry(this.currentPostProcessors); + return copy; + } + + public shift(): Function | undefined { + const res = this.currentPostProcessors.shift(); + + if (res) { + return res.fn; + } + return undefined; + } +} diff --git a/src/libs/Sib.ts b/src/libs/Sib.ts index c11e6804357c2c0416e103b19e758b51314e15e6..2f45ac29612342796e7e45f74eb0730073d51f36 100644 --- a/src/libs/Sib.ts +++ b/src/libs/Sib.ts @@ -1,54 +1,46 @@ -import { ComponentFactory } from "./ComponentFactory.js"; -import { defineComponent } from "./helpers.js"; +import { ComponentFactory } from './ComponentFactory.js'; +import { defineComponent } from './helpers.js'; import type { - ComponentConstructorInterface, - ComponentInterface, - MixinStaticInterface -} from "./interfaces.js"; - -export class Sib { - public static register(componentDefinition: MixinStaticInterface):void { - const component = ComponentFactory.build(componentDefinition); - const cls = this.toElement(component); - defineComponent(component.name, cls); - } - - protected static toElement(component: ComponentConstructorInterface): typeof HTMLElement { - return class extends HTMLElement { - private _component: ComponentInterface | null = null; - - constructor() { - super(); - this.component = new component(this); - this.component.created(); - } - - get component(): ComponentInterface { - if (this._component === null) { - throw new Error('No component found'); - } - return this._component; - } - set component(component: ComponentInterface) { - this._component = component; - } - - static get observedAttributes() { - return (<any>component).observedAttributes; - } - - attributeChangedCallback(name, oldValue, newValue) { - const attr = name.replace(/([a-z0-9])-([a-z0-9])/g, (_c, p1, p2) => `${p1}${p2.toUpperCase()}`); - this.component.attributesCallback(attr, newValue, oldValue); - } - - connectedCallback() { - this.component.attached(); - } - - disconnectedCallback() { - this.component.detached(); - } - } - } -} + ComponentConstructorInterface, + ComponentInterface, + MixinStaticInterface, +} from './interfaces.js'; + +export const Sib = { + register(componentDefinition: MixinStaticInterface): void { + const component = ComponentFactory.build(componentDefinition); + const cls = Sib.toElement(component); + defineComponent(component.name, cls); + }, + toElement(component: ComponentConstructorInterface): typeof HTMLElement { + return class extends HTMLElement { + private component: ComponentInterface; + + constructor() { + super(); + this.component = new component(this); + this.component.created(); + } + + static get observedAttributes() { + return (<any>component).observedAttributes; + } + + attributeChangedCallback(name, oldValue, newValue) { + const attr = name.replace( + /([a-z0-9])-([a-z0-9])/g, + (_c, p1, p2) => `${p1}${p2.toUpperCase()}`, + ); + this.component.attributesCallback(attr, newValue, oldValue); + } + + connectedCallback() { + this.component.attached(); + } + + disconnectedCallback() { + this.component.detached(); + } + }; + }, +}; diff --git a/src/libs/async-query-selector-types.ts b/src/libs/async-query-selector-types.ts index 5bfd0121b3f637a397c8f675805d9705cb3acb53..d6ff9d56b0eb616545e8016bf80062651ebacf3d 100644 --- a/src/libs/async-query-selector-types.ts +++ b/src/libs/async-query-selector-types.ts @@ -2,50 +2,46 @@ export type AsyncQuerySelectorType = { <K extends keyof HTMLElementTagNameMap>( selectors: K, parent?: ParentNode, - ): Promise<HTMLElementTagNameMap[K]> + ): Promise<HTMLElementTagNameMap[K]>; <K extends keyof SVGElementTagNameMap>( selectors: K, parent?: ParentNode, - ): Promise<SVGElementTagNameMap[K]> - //@ts-ignore + ): Promise<SVGElementTagNameMap[K]>; <K extends keyof MathMLElementTagNameMap>( selectors: K, parent?: ParentNode, - //@ts-ignore - ): Promise<MathMLElementTagNameMap[K]> + ): Promise<MathMLElementTagNameMap[K]>; /** @deprecated */ <K extends keyof HTMLElementDeprecatedTagNameMap>( selectors: K, parent?: ParentNode, - ): Promise<HTMLElementDeprecatedTagNameMap[K]> + ): Promise<HTMLElementDeprecatedTagNameMap[K]>; <E extends Element = Element>( selectors: string, parent?: ParentNode, - ): Promise<E> -} + ): Promise<E>; +}; export type AsyncQuerySelectorAllType = { <K extends keyof HTMLElementTagNameMap>( selectors: K, parent?: ParentNode, - ): AsyncIterable<HTMLElementTagNameMap[K]> + ): AsyncIterable<HTMLElementTagNameMap[K]>; <K extends keyof SVGElementTagNameMap>( selectors: K, parent?: ParentNode, - ): AsyncIterable<SVGElementTagNameMap[K]> - //@ts-ignore + ): AsyncIterable<SVGElementTagNameMap[K]>; <K extends keyof MathMLElementTagNameMap>( selectors: K, parent?: ParentNode, - //@ts-ignore - ): AsyncIterable<MathMLElementTagNameMap[K]> + ): AsyncIterable<MathMLElementTagNameMap[K]>; /** @deprecated */ <K extends keyof HTMLElementDeprecatedTagNameMap>( selectors: K, parent?: ParentNode, - ): AsyncIterable<HTMLElementDeprecatedTagNameMap[K]> + ): AsyncIterable<HTMLElementDeprecatedTagNameMap[K]>; <E extends Element = Element>( selectors: string, parent?: ParentNode, - ): AsyncIterable<E> -} + ): AsyncIterable<E>; +}; diff --git a/src/libs/filter.ts b/src/libs/filter.ts index 6082d904bac63a9fcfdb3e25d4b0ffe8a371b21a..755298e46cd28c6cab32058545cf7550b431bb26 100644 --- a/src/libs/filter.ts +++ b/src/libs/filter.ts @@ -1,5 +1,10 @@ -import { parseFieldsString, findClosingBracketMatchIndex, compare, uniqID } from "./helpers"; -import type { Query, SearchQuery } from "./interfaces"; +import { + compare, + findClosingBracketMatchIndex, + parseFieldsString, + uniqID, +} from './helpers.ts'; +import type { Query, SearchQuery } from './interfaces.ts'; /** * Check if the field is a set @@ -9,9 +14,9 @@ import type { Query, SearchQuery } from "./interfaces"; */ const isSet = (field: string, fields: string): boolean => { if (!fields) return false; - let foundSets = fields.match(getSetRegexp(field)); + const foundSets = fields.match(getSetRegexp(field)); return foundSets ? foundSets.length > 0 : false; -} +}; /** * Get the list of fields in the set * @param field - set name to get @@ -21,32 +26,33 @@ const isSet = (field: string, fields: string): boolean => { const getSet = (field: string, fields: string): string[] => { const setString = fields.match(getSetRegexp(field)); if (!setString) return []; - const firstSetBracket = fields.indexOf(setString[0]) + (setString[0].length) - 1; + const firstSetBracket = + fields.indexOf(setString[0]) + setString[0].length - 1; const lastSetBracket = findClosingBracketMatchIndex(fields, firstSetBracket); const set = fields.substring(firstSetBracket + 1, lastSetBracket); return parseFieldsString(set); -} +}; const getSetRegexp = (field: string) => { - return new RegExp(`(^|\\,|\\(|\\s)\\s*${field}\\s*\\(`, 'g') -} + return new RegExp(`(^|\\,|\\(|\\s)\\s*${field}\\s*\\(`, 'g'); +}; /** * Check if the field is a special search field * @param field - field to test * @param searchForm - current search form * @returns true if the field is a special search field */ -const isSearchField = (field: string, searchForm: any) => { - return searchForm.hasAttribute('search-' + field); -} +const isSearchField = (field: string, searchForm: Element) => { + return searchForm.hasAttribute(`search-${field}`); +}; /** * Get the fields targetted by a search field * @param field - search field to get * @param searchForm - current search form * @returns a list of fields targetted by the current search field */ -const getSearchField = (field: string, searchForm: any): string[] => { - return parseFieldsString(searchForm.getAttribute('search-' + field)); -} +const getSearchField = (field: string, searchForm: Element): string[] => { + return parseFieldsString(searchForm.getAttribute(`search-${field}`) || ''); +}; /** * Throw or simply return value @@ -58,7 +64,7 @@ const orThrow = (throwOn: boolean | undefined, ret: boolean) => { if (throwOn === true && ret) throw true; if (throwOn === false && !ret) throw false; return ret; -} +}; /** * Compare a value to the query @@ -67,30 +73,39 @@ const orThrow = (throwOn: boolean | undefined, ret: boolean) => { * @param throwOn - should function throw error on True or False * @returns true if value matches, throw error otherwise */ -const matchValue = async (val: any, query: Query, throwOn?: boolean): Promise<boolean> => { +const matchValue = async ( + val: any, + query: Query, + throwOn?: boolean, +): Promise<boolean> => { const subject = await val; if (subject == null && query.value === '') return orThrow(throwOn, true); // filter not set and subject not existing -> ignore filter - if (subject == null) return orThrow(throwOn, false); // return false; // property does not exist on resource - if (query.list) { // Filter on a container - if(query.value.length === 0) return orThrow(throwOn, true); - for(const v of query.value) { - if (await matchValue(subject, { type: query.type, value: v, list: false })) { // do not throw here, we need the result + if (subject == null) return orThrow(throwOn, false); // return false; // property does not exist on resource + if (query.list) { + // Filter on a container + if (query.value.length === 0) return orThrow(throwOn, true); + for (const v of query.value) { + if ( + await matchValue(subject, { type: query.type, value: v, list: false }) + ) { + // do not throw here, we need the result return orThrow(throwOn, true); } } return orThrow(throwOn, false); } if (subject.isContainer?.()) { - let ret: any = Promise.resolve(query.value === ''); // if no query, return a match + let ret: boolean | Promise<boolean> = Promise.resolve(query.value === ''); // if no query, return a match for (const value of subject['ldp:contains']) { - ret = await ret || await matchValue(value, query); // do not throw here, we need the result + ret = (await ret) || (await matchValue(value, query)); // do not throw here, we need the result if (ret) return orThrow(throwOn, true); } return orThrow(throwOn, await ret); - } else if(Array.isArray(subject)) { - let ret: any = Promise.resolve(query.value === ''); // if no query, return a match + } + if (Array.isArray(subject)) { + let ret: boolean | Promise<boolean> = Promise.resolve(query.value === ''); // if no query, return a match for (const value of subject) { - ret = await ret || await matchValue(value, query); // do not throw here, we need the result + ret = (await ret) || (await matchValue(value, query)); // do not throw here, we need the result if (ret) { return true; } @@ -99,7 +114,7 @@ const matchValue = async (val: any, query: Query, throwOn?: boolean): Promise<bo } return orThrow(throwOn, compare[query.type](subject, query.value)); -} +}; /** * Cache properties of a filter to avoid repeated parsing @@ -112,15 +127,17 @@ const cacheFieldsProps = ( cacheKey: string, filter: string, fields: string, - searchForm: any + searchForm: any, ) => { if (!window.cachePropsSearchFilter[cacheKey]) { window.cachePropsSearchFilter[cacheKey] = { setFields: isSet(filter, fields) ? getSet(filter, fields) : null, - setSearchFields: isSearchField(filter, searchForm) ? getSearchField(filter, searchForm) : null - } + setSearchFields: isSearchField(filter, searchForm) + ? getSearchField(filter, searchForm) + : null, + }; } -} +}; /** * Allow to traverse a multi-depth path to filter on resources of a given type @@ -129,18 +146,22 @@ const cacheFieldsProps = ( * @param targetedType The type of resources we are looking for * @returns The list of all resources ids found of given type */ -const traversePath = async (resource: object, path: string[], targetedType: string): Promise<object[]> => { +const traversePath = async ( + resource: object, + path: string[], + targetedType: string, +): Promise<object[]> => { let result: object[] = []; let currentRes: any; let remainingPath: string[] = path; - if (!path.length) return []; + if (path.length === 0) return []; // Split and get first item try { currentRes = await resource[path[0]]; const lastPath1El = path.shift(); - if(lastPath1El) remainingPath = path; + if (lastPath1El) remainingPath = path; if (currentRes && remainingPath.length > 1) { result = await traversePath(currentRes, remainingPath, targetedType); // Await the result of traversePath @@ -156,9 +177,9 @@ const traversePath = async (resource: object, path: string[], targetedType: stri } if (!Array.isArray(targetsRes)) targetsRes = [targetsRes]; - for(const targetRes of targetsRes) { - if (!result.some(item => item["@id"] === targetRes["@id"])) { - result.push({"@id": targetRes["@id"]}); + for (const targetRes of targetsRes) { + if (!result.some(item => item['@id'] === targetRes['@id'])) { + result.push({ '@id': targetRes['@id'] }); } } } @@ -170,8 +191,7 @@ const traversePath = async (resource: object, path: string[], targetedType: stri } // console.log(`TraversePath result for ${resource['@id']} : `, await result); return result; -} - +}; /** * Check if one resource match one filter @@ -191,7 +211,7 @@ const matchFilter = async ( fieldsAttr: string, searchForm: any, filterId: string, - throwOn: boolean + throwOn: boolean, ) => { let fields: string[] | null = null; @@ -202,9 +222,11 @@ const matchFilter = async ( fields = window.cachePropsSearchFilter[cacheKey].setFields; } else if (window.cachePropsSearchFilter[cacheKey].setSearchFields !== null) { fields = window.cachePropsSearchFilter[cacheKey].setSearchFields; - } else { // search on 1 field + } else { + // search on 1 field //FIXME: Better assumption that just using ldp:contains does the job ? - if (!(await resource[filter]) && filter.includes('ldp:contains')) { // nested field + if (!(await resource[filter]) && filter.includes('ldp:contains')) { + // nested field // console.log(`No ${filter} found for ${resource['@id']} and ${filter} is a nested field. Trying to traverse path.`); const path1: string[] = filter.split('.'); const targetedType = path1[path1.length - 1]; @@ -214,33 +236,40 @@ const matchFilter = async ( targetIds = await traversePath(resource, path1, targetedType); // console.log(`TargetIds : ${targetIds} found for ${await resource['name']} : ${resource['@id']}`); - if (!Array.isArray(targetIds) || targetIds.length === 0 && query.value !== '') { + if ( + !Array.isArray(targetIds) || + (targetIds.length === 0 && query.value !== '') + ) { // console.log(`No targetIds found for ${resource['@id']} returning false`); - throw throwOn ? false : true; + throw !throwOn; } // console.log(`Do we have a match for ${resource['@id']} ?`, match); - return await matchValue(targetIds, query, throwOn);; + return await matchValue(targetIds, query, throwOn); } return matchValue(resource[filter], query, throwOn); } // search on multiple fields try { - await Promise.all((fields || []).map(field => - matchFilter( - resource, - field, - query, - fieldsAttr, - searchForm, - filterId, - true // stop searching when 1 filter is true (= OR) - ) - )); - } catch (e) { return true; } + await Promise.all( + (fields || []).map(field => + matchFilter( + resource, + field, + query, + fieldsAttr, + searchForm, + filterId, + true, // stop searching when 1 filter is true (= OR) + ), + ), + ); + } catch { + return true; + } throw false; -} +}; /** * Check if one resource match all the filters @@ -258,25 +287,29 @@ const matchFilters = async ( filterNames: string[], fields: string, searchForm: any, - filterId: string + filterId: string, ): Promise<boolean> => { // return true if all filters values are contained in the corresponding field of the resource try { - await Promise.all(filterNames.map(async (filter) => { - let match = await matchFilter( + await Promise.all( + filterNames.map(async filter => { + const match = await matchFilter( resource, filter, filters[filter], fields, searchForm, filterId, - false // stop searching when 1 filter is false (= AND) + false, // stop searching when 1 filter is false (= AND) ); return match; - })); - } catch (e) { return false; } + }), + ); + } catch (_e) { + return false; + } return true; -} +}; /** * Check which resources match the filters @@ -286,29 +319,29 @@ const matchFilters = async ( * @param searchForm - searchForm component * @returns resources filtered */ -const searchInResources = async ( +const searchInResources = ( resources: object[], filters: SearchQuery, fields: string, - searchForm: any + searchForm: any, ) => { // Optim: use cache to do these things only once const filterNames = Object.keys(filters); const filterId = uniqID(); window.cachePropsSearchFilter = {}; - return Promise.all(resources.map(async (resource) => { - let match = await matchFilters( - resource, - filters, - filterNames, - fields, - searchForm, - filterId - ); - return match; - })); -} - -export { - searchInResources + return Promise.all( + resources.map(async resource => { + const match = await matchFilters( + resource, + filters, + filterNames, + fields, + searchForm, + filterId, + ); + return match; + }), + ); }; + +export { searchInResources }; diff --git a/src/libs/helpers.ts b/src/libs/helpers.ts index 2eea9a0f7fbe3e9ed154d04be80a58f2872a2ca5..adf004efb7efca41d16e7aaab2b0c5d2c11dec94 100644 --- a/src/libs/helpers.ts +++ b/src/libs/helpers.ts @@ -1,7 +1,7 @@ -import Fuse from "fuse.js"; +import Fuse from 'fuse.js'; function uniqID(): string { - return '_' + (Math.random() * Math.pow(36, 20)).toString(36).slice(0, 10); + return `_${(Math.random() * 36 ** 20).toString(36).slice(0, 10)}`; } function stringToDom(html: string): DocumentFragment { @@ -10,22 +10,25 @@ function stringToDom(html: string): DocumentFragment { return template.content; } -async function evalTemplateString(str: string, variables: {[key:string]:any} = {}) { +const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor; +async function evalTemplateString( + str: string, + variables: { [key: string]: unknown } = {}, +) { const keys = Object.keys(variables); const values = keys.map(key => variables[key]); try { - const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor - const func = AsyncFunction.call(null, ...keys, 'return `' + str + '`'); + const func = AsyncFunction.call(null, ...keys, `return \`${str}\``); return await func(...values); } catch (e) { console.log(e); - throw new SyntaxError('`' + str + '`'); + throw new SyntaxError(`\`${str}\``); } } function importCSS(...stylesheets: string[]) { - const linksElements: HTMLLinkElement[] = []; - for(let url of stylesheets) { + const linksElements: HTMLLinkElement[] = []; + for (let url of stylesheets) { url = relativeSource(url); let link = Array.from(document.head.querySelectorAll('link')).find( link => link.href === url, @@ -36,38 +39,38 @@ function importCSS(...stylesheets: string[]) { link.href = url; document.head.appendChild(link); linksElements.push(link); - }; + } return linksElements; } /** * @param id an uniq id to avoid import a style twice * @param importer a callback returning this `import()` promise * @returns the style element - * + * * typical use: * ```js - * importInlineCSS('bootstrap', () => import('./css/bootstrap.css?inline')) + * importInlineCSS('bootstrap', () => import('./css/bootstrap.css?inline')) * // adding '?inline' lets Vite convert css to js * ``` */ function importInlineCSS( id: string, - importer: string | (() => string | Promise<string | { default: string }>) + importer: string | (() => string | Promise<string | { default: string }>), ) { id = `sib-inline-css-${id}`; let style = document.head.querySelector<HTMLStyleElement>(`style#${id}`); if (style) return style; - style = document.createElement("style"); + style = document.createElement('style'); style.id = id; document.head.appendChild(style); (async () => { let textContent: string; - if (typeof importer === "string") textContent = importer; + if (typeof importer === 'string') textContent = importer; else { const imported = await importer(); - if (typeof imported === "string") textContent = imported; - else textContent = imported.default || ""; + if (typeof imported === 'string') textContent = imported; + else textContent = imported.default || ''; } style.textContent = textContent; })(); @@ -91,11 +94,11 @@ function importJS(...plugins: string[]): HTMLScriptElement[] { function relativeSource(source: string) { if (!source.match(/^\..?\//)) return new URL(source, document.baseURI).href; const e = new Error(); - if(!e.stack) return source; + if (!e.stack) return source; const f2 = e.stack.split('\n').filter(l => l.includes(':'))[2]; - let line = f2.match(/[a-z]+:.*$/); + const line = f2.match(/[a-z]+:.*$/); if (!line) return source; - const calledFile = line[0].replace(/(\:[0-9]+){2}\)?$/,''); + const calledFile = line[0].replace(/(\:[0-9]+){2}\)?$/, ''); source = new URL(source, calledFile).href; return source; } @@ -103,17 +106,17 @@ function relativeSource(source: string) { function loadScript(source: string) { source = relativeSource(source); return new Promise(resolve => { - var script = document.createElement('script'); - var head = document.querySelector('head'); + const script = document.createElement('script'); + const head = document.querySelector('head'); script.async = true; script.onload = () => setTimeout(resolve, 0); script.src = source; - if(head) head.appendChild(script); + if (head) head.appendChild(script); }); } function domIsReady(): Promise<void> { - return new Promise(function(resolve) { + return new Promise(resolve => { if (document.readyState === 'complete') { resolve(); } else { @@ -122,43 +125,48 @@ function domIsReady(): Promise<void> { }); } -function setDeepProperty(obj: {[index:string]:any}, path: string[], value: any) { +function setDeepProperty( + obj: { [index: string]: any }, + path: string[], + value: any, +) { const name = path.shift(); if (name) { if (!(name in obj)) obj[name] = {}; - if (path.length) setDeepProperty(obj[name], path, value); + if (path.length > 0) setDeepProperty(obj[name], path, value); else obj[name] = value; } } function parseFieldsString(fields: string): string[] { if (!fields) return []; - let fieldsArray: string[]; - // remove all sets from fields - while(fields.indexOf('(') > 0){ - let firstBracket = fields.indexOf('('); - let noset = fields.substring(firstBracket, findClosingBracketMatchIndex(fields, firstBracket)+1) - fields = fields.replace(noset, '') + while (fields.indexOf('(') > 0) { + const firstBracket = fields.indexOf('('); + const noset = fields.substring( + firstBracket, + findClosingBracketMatchIndex(fields, firstBracket) + 1, + ); + fields = fields.replace(noset, ''); } const re = /((^\s*|,)\s*)(("(\\"|[^"])*")|('(\\'|[^'])*')|[^,]*)/gm; // match , not inside quotes - fieldsArray = fields.match(re) || []; // separate fields + const fieldsArray = fields.match(re) || []; // separate fields if (!fieldsArray) return []; - return fieldsArray.map(a => a.replace(/^[\s,]+/, '')) // remove commas and spaces + return fieldsArray.map(a => a.replace(/^[\s,]+/, '')); // remove commas and spaces } function findClosingBracketMatchIndex(str: string, pos: number) { - if (str[pos] != '(') throw new Error("No '(' at index " + pos); + if (str[pos] !== '(') throw new Error(`No '(' at index ${pos}`); let depth = 1; for (let i = pos + 1; i < str.length; i++) { switch (str[i]) { - case '(': - depth++; - break; - case ')': - if (--depth == 0) return i; - break; + case '(': + depth++; + break; + case ')': + if (--depth === 0) return i; + break; } } return -1; @@ -168,7 +176,9 @@ function defineComponent(tagName: string, componentClass: typeof HTMLElement) { if (!customElements.get(tagName)) { customElements.define(tagName, componentClass); } else { - console.warn(`Warning: the component "${tagName}" has already been loaded in another version of sib-core.`) + console.warn( + `Warning: the component "${tagName}" has already been loaded in another version of sib-core.`, + ); } } @@ -182,8 +192,9 @@ function fuzzyCompare(subject: string, search: string) { const compare: { [k: string]: (subject: any, query: any) => boolean } = { string(subject: string, query: string) { - if(query === '') return true; - if(subject.toString().toLowerCase().includes(String(query).toLowerCase())) return true; + if (query === '') return true; + if (subject.toString().toLowerCase().includes(String(query).toLowerCase())) + return true; return fuzzyCompare(subject, query); }, boolean(subject: boolean, query: boolean) { @@ -204,46 +215,49 @@ const compare: { [k: string]: (subject: any, query: any) => boolean } = { }, resource(subject, query) { // dropdown default ' - ' option return an empty string - if(query === '') return true; + if (query === '') return true; if (!query['@id']) return false; - const ret = (subject['@id'] === query['@id']); + const ret = subject['@id'] === query['@id']; return ret; - } + }, }; -function generalComparator(a, b, order = 'asc') { - let comparison = 0; - +function generalComparator( + a: unknown, + b: unknown, + order: 'asc' | 'desc' = 'asc', +): number { + if (order === 'desc') return generalComparator(b, a); + if (a == null && b == null) return 0; + if (a === b || Object.is(a, b)) return 0; if (typeof a === 'boolean' && typeof b === 'boolean') { - comparison = (a === b) ? 0 : a ? 1 : -1; - } else if (!isNaN(a) && !isNaN(b)) { - comparison = Number(a) - Number(b); - } else if (Array.isArray(a) && Array.isArray(b)) { - comparison = a.length - b.length; - } else if (!isNaN(Date.parse(a)) && !isNaN(Date.parse(b))) { - const dateA = new Date(a); - const dateB = new Date(a); - comparison = dateA.getTime() - dateB.getTime(); - } else if (typeof a === 'object' && typeof b === 'object') { - const aKeys = Object.keys(a); - const bKeys = Object.keys(b); - comparison = aKeys.length - bKeys.length; - } else if (a == null || b == null) { - comparison = a == null ? (b == null ? 0 : -1) : (b == null ? 1 : 0); - } else { - comparison = a.toString().localeCompare(b.toString()); + return a === b ? 0 : a ? 1 : -1; } - - if (order === 'desc') { - comparison = comparison * -1; + if (!Number.isNaN(Number(a)) && !Number.isNaN(Number(b))) { + return Number(a) - Number(b); } - return comparison; -}; - + if (Array.isArray(a) && Array.isArray(b)) { + return a.length - b.length; + } + const dateA = Date.parse(String(a)); + const dateB = Date.parse(String(b)); + if (!Number.isNaN(dateA) && !Number.isNaN(dateB)) { + return dateA - dateB; + } + if (a && b && typeof a === 'object' && typeof b === 'object') { + const aKeys = Object.keys(a); + const bKeys = Object.keys(b); + return aKeys.length - bKeys.length; + } + if (a == null) return -1; + if (b == null) return 1; + return String(a).localeCompare(String(b)); +} function transformArrayToContainer(resource: object) { const newValue = { ...resource }; - for (let predicate of Object.keys(newValue)) { // iterate over all properties + for (const predicate of Object.keys(newValue)) { + // iterate over all properties const predicateValue = newValue[predicate]; if (!predicateValue || typeof predicateValue !== 'object') continue; // undefined or literal, do nothing if (['permissions', '@context'].includes(predicate)) continue; // do not transform permissions and context @@ -253,58 +267,67 @@ function transformArrayToContainer(resource: object) { newValue[predicate] = transformArrayToContainer(resource[predicate]); } - if (Array.isArray(predicateValue) && predicateValue['@id']) { // Do not systematically transform arrays to containers + if (Array.isArray(predicateValue) && predicateValue['@id']) { + // Do not systematically transform arrays to containers newValue[predicate] = { '@id': predicateValue['@id'], - 'ldp:contains': [...predicateValue] + 'ldp:contains': [...predicateValue], }; - newValue[predicate]['ldp:contains'].forEach((childPredicate: any, index: number) => { // but check all nested resources - newValue[predicate]['ldp:contains'][index] = transformArrayToContainer(childPredicate); - }); + newValue[predicate]['ldp:contains'].forEach( + (childPredicate: any, index: number) => { + // but check all nested resources + newValue[predicate]['ldp:contains'][index] = + transformArrayToContainer(childPredicate); + }, + ); } } return newValue; } export default class AsyncIterableBuilder<Type> { - readonly #values: Promise<{ value: Type; done: boolean }>[] = [] - #resolve!: (value: { value: Type; done: boolean }) => void - readonly iterable: AsyncIterable<Type> - readonly next: (value: Type, done?: boolean) => void + readonly #values: Promise<{ value: Type; done: boolean }>[] = []; + #resolve!: (value: { value: Type; done: boolean }) => void; + readonly iterable: AsyncIterable<Type>; + readonly next: (value: Type, done?: boolean) => void; constructor() { - this.#nextPromise() - this.iterable = this.#createIterable() - this.next = this.#next.bind(this) + this.#nextPromise(); + this.iterable = this.#createIterable(); + this.next = this.#next.bind(this); } async *#createIterable() { for (let index = 0; ; index++) { - const { value, done } = await this.#values[index] - delete this.#values[index] - yield value - if (done) return + const { value, done } = await this.#values[index]; + delete this.#values[index]; + yield value; + if (done) return; } } - #next(value: Type, done: boolean = false) { - this.#resolve({ value, done }) - this.#nextPromise() + #next(value: Type, done = false) { + this.#resolve({ value, done }); + this.#nextPromise(); } #nextPromise() { - this.#values.push(new Promise(resolve => (this.#resolve = resolve))) + this.#values.push( + new Promise(resolve => { + this.#resolve = resolve; + }), + ); } } -import { +import type { AsyncQuerySelectorAllType, AsyncQuerySelectorType, -} from './async-query-selector-types'; +} from './async-query-selector-types.ts'; const asyncQuerySelector: AsyncQuerySelectorType = ( selector: string, - parent: ParentNode = document + parent: ParentNode = document, ) => new Promise<Element>(resolve => { const element = parent.querySelector(selector); @@ -324,7 +347,7 @@ const asyncQuerySelector: AsyncQuerySelectorType = ( const asyncQuerySelectorAll: AsyncQuerySelectorAllType = ( selector: string, - parent: ParentNode = document + parent: ParentNode = document, ) => { const delivered = new WeakSet<Element>(); const { next, iterable } = new AsyncIterableBuilder<Element>(); diff --git a/src/libs/interfaces.ts b/src/libs/interfaces.ts index 54e839b2fbf4356ffb14d7cd920500632c8238cf..144ae01b44a728e7714202748c595e8b12b45115 100644 --- a/src/libs/interfaces.ts +++ b/src/libs/interfaces.ts @@ -1,9 +1,11 @@ +import type { Profiler } from '../logger.ts'; + export interface AccessorStaticInterface { [key: string]: { get: Function; set: Function; - } -}; + }; +} export interface ArrayOfHooksInterface { created: HookInterface[]; @@ -11,9 +13,10 @@ export interface ArrayOfHooksInterface { detached: HookInterface[]; } -export interface AttributeChangedCallbackInterface { - (newValue: any, oldValue: any): void; -}; +export type AttributeChangedCallbackInterface = ( + newValue: any, + oldValue: any, +) => void; export interface AttributeDefinitionInterface { type?: any; @@ -26,24 +29,29 @@ export interface AttributesDefinitionInterface { [key: string]: AttributeDefinitionInterface; } -export type ComponentConstructorInterface = new (element: HTMLElement) => ComponentInterface; +export type ComponentConstructorInterface = new ( + element: HTMLElement, +) => ComponentInterface; export interface ComponentInterface { + profiler: Profiler; element: HTMLElement; - created():void; - attached():void; - detached():void; + created(): void; + attached(): void; + detached(): void; - attributesCallback(key: string, value: any, oldValue: any):void; + attributesCallback(key: string, value: any, oldValue: any): void; } -export interface ComponentStaticInterface extends HasAttributesDefinitionInterface, HasInitialStateInterface { - name: String; +export interface ComponentStaticInterface + extends HasAttributesDefinitionInterface, + HasInitialStateInterface { + name: string; hooks: ArrayOfHooksInterface; methods: Map<string, Function>; accessors: AccessorStaticInterface; -}; +} export interface HasAttributesDefinitionInterface { attributes?: AttributesDefinitionInterface | undefined; @@ -63,30 +71,32 @@ export interface HasMixinsInterface { use?: MixinStaticInterface[] | undefined; } -export interface HookInterface { - (): void; -}; +export type HookInterface = () => void; -export interface MixinStaticInterface extends HasAttributesDefinitionInterface, HasMixinsInterface, HasInitialStateInterface, HasHooksInterface { - name: String; -}; +export interface MixinStaticInterface + extends HasAttributesDefinitionInterface, + HasMixinsInterface, + HasInitialStateInterface, + HasHooksInterface { + name: string; +} export interface LocationResourceInterface { lat?: HookInterface; lng?: HookInterface; } export interface Query { - value: any - type: "boolean" | "number" | "range" | "resource" | "string"; - list: boolean + value: any; + type: 'boolean' | 'number' | 'range' | 'resource' | 'string'; + list: boolean; } export interface SearchQuery { - [key: string]: Query + [key: string]: Query; } export interface FilterEventOptions { value: string; inputLabel: string; type: string; -} \ No newline at end of file +} diff --git a/src/libs/lit-helpers.ts b/src/libs/lit-helpers.ts index 90d61adb5ee36c656366b5c012bf5402a6a3a4f6..3d953992f78ff36357db7ca6bd93154174b739ab 100644 --- a/src/libs/lit-helpers.ts +++ b/src/libs/lit-helpers.ts @@ -2,167 +2,220 @@ * Spread function from open-wc/lit-helpers * More informations here: https://open-wc.org/developing/lit-helpers.html */ -import {html, TemplateResult, directive, noChange } from 'lit-html'; + +import { + type AttributePart, + type BooleanAttributePart, + type ChildPart, + type ElementPart, + type EventPart, + type PropertyPart, + type TemplateResult, + html, + noChange, +} from 'lit'; + +import { + Directive, + type PartInfo, + PartType, + directive, +} from 'lit/directive.js'; + +type SpreadPartType = + | ChildPart + | AttributePart + | BooleanAttributePart + | EventPart + | PropertyPart + | ElementPart; const prevCache = new WeakMap(); -export const spread = directive((spreadData) => (part) => { - const prevData = prevCache.get(part); - if (prevData === spreadData) { - return; + +class SpreadDirective extends Directive { + spreadData: any; + + constructor(partInfo: PartInfo) { + super(partInfo); + this.spreadData = null; } - prevCache.set(part, spreadData); - - if (spreadData) { - for (const key in spreadData) { - const value = spreadData[key]; - if (value === noChange) continue; - - const prefix = key[0]; - const { element } = part.committer; - - if (prefix === '@') { - const prevHandler = prevData && prevData[key]; - if (!prevHandler || prevHandler !== value) { - const name = key.slice(1); - if (prevHandler) element.removeEventListener(name, prevHandler); - element.addEventListener(name, value); - } - continue; - } - if (prefix === '.') { - if (!prevData || prevData[key] !== value) { - element[key.slice(1)] = value; - } - continue; - } - if (prefix === '?') { - if (!prevData || prevData[key] !== value) { - const name = key.slice(1); - if (value) { - element.setAttribute(name, ''); - } else { - element.removeAttribute(name); - } - } - continue; - } - if (!prevData || prevData[key] !== value) { - if (value != null) { - element.setAttribute(key, String(value)); - } else { - element.removeAttribute(key); - } - } - } + + render(spreadData: any) { + this.spreadData = spreadData; + return noChange; } - if (prevData) { - for (const key in prevData) { - if (!spreadData || !(key in spreadData)) { + override update(part: SpreadPartType, [spreadData]: any) { + const prevData = prevCache.get(part); + + if (prevData === spreadData) { + return noChange; + } + + let element: HTMLElement; + prevCache.set(part, spreadData); + + if (part.type === PartType.ATTRIBUTE || part.type === PartType.PROPERTY) { + element = part.element; + } else { + console.warn( + 'Unsupported part type or missing element, skipping update.', + ); + return noChange; + } + + if (spreadData) { + for (const key in spreadData) { + const value = spreadData[key]; + if (value === noChange) continue; + const prefix = key[0]; - const { element } = part.committer; + // Handle event listeners (e.g., @click) if (prefix === '@') { - element.removeEventListener(key.slice(1), prevData[key]); + const prevHandler = prevData?.[key]; + if (!prevHandler || prevHandler !== value) { + const name = key.slice(1); // Extract event name + if (prevHandler) element.removeEventListener(name, prevHandler); + element.addEventListener(name, value); + } continue; } + + // Handle properties (e.g., .value) if (prefix === '.') { - element[key.slice(1)] = undefined; + if (!prevData || prevData[key] !== value) { + element[key.slice(1)] = value; + } continue; } + + // Handle boolean attributes (e.g., ?disabled) if (prefix === '?') { - element.removeAttribute(key.slice(1)); + const attrName = key.slice(1); // Extract attribute name + if (!prevData || prevData[key] !== value) { + if (value) { + element.setAttribute(attrName, ''); + } else { + element.removeAttribute(attrName); + } + } continue; } - element.removeAttribute(key); + + // Handle regular attributes (e.g., class, id) + if (!prevData || prevData[key] !== value) { + if (value != null) { + element.setAttribute(key, String(value)); + } else { + element.removeAttribute(key); + } + } + } + } + + // Remove any old attributes or event listeners no longer in spreadData + if (prevData) { + for (const key in prevData) { + if (!spreadData || !(key in spreadData)) { + const prefix = key[0]; + + if (prefix === '@') { + element.removeEventListener(key.slice(1), prevData[key]); + continue; + } + if (prefix === '.') { + element[key.slice(1)] = undefined; + continue; + } + if (prefix === '?') { + element.removeAttribute(key.slice(1)); + continue; + } + element.removeAttribute(key); + } } } + + return noChange; } -}); +} +export const spread = directive(SpreadDirective); interface CachedNeedlessValue { - value: any; - index: number; + value: any; + index: number; } interface CachedTemplateStrings { - strings: string[]; - needlessValues: CachedNeedlessValue[]; + strings: TemplateStringsArray; + needlessValues: CachedNeedlessValue[]; } -function dropIndices(arr: any[], needlessValues: CachedNeedlessValue[]): any[] { - const newArr: any[] = []; - let j = 0; +const templateStringsCache = new WeakMap< + TemplateStringsArray, + CachedTemplateStrings[] +>(); - for (let i = 0, n = arr.length; i < n; ++i) { - if (needlessValues[j].index === i) { - ++j; - } else { - newArr.push(arr[i]); - } +function filterOutNeedlessValues( + arr: any[], + needlessValues: CachedNeedlessValue[], +): any[] { + return arr.filter((_, i) => !needlessValues.some(nv => nv.index === i)); +} + +export function preHTML( + strings: TemplateStringsArray, + ...values: any[] +): TemplateResult { + let cachedStrings = templateStringsCache.get(strings); + + if (cachedStrings) { + for (const cached of cachedStrings) { + const { needlessValues } = cached; + const isSame = needlessValues.every(nv => values[nv.index] === nv.value); + + if (isSame) { + // Return cached template result if values match + return html( + cached.strings, + ...filterOutNeedlessValues(values, needlessValues), + ); + } } + } - return newArr; -} + // No match found, so we need to create new template strings and cache them + const needlessValues: CachedNeedlessValue[] = []; + const newStrings: string[] = []; -const templateStringsCache = new WeakMap<TemplateStringsArray, CachedTemplateStrings[]>(); - -// Convert dynamic tags to template strings -// example: <${'div'}>${'this is example'}</${'div'}> => <div>${'this is example'}</div> -export function preHTML(strings: TemplateStringsArray, ...values: any[]): TemplateResult { - // check cache !important return equal link at first argument - let cachedStrings = templateStringsCache.get(strings) as CachedTemplateStrings[]; - if (cachedStrings) { - for (let i = 0, n = cachedStrings.length; i < n; ++i) { - const needlessValues = cachedStrings[i].needlessValues; - let isSame = true; - for (let ii = 0, nn = needlessValues.length; ii < nn; ++ii) { - if (values[needlessValues[ii].index] !== needlessValues[ii].value) { - isSame = false; - break; - } - } + for (let i = 0; i < strings.length; i++) { + let str = strings[i]; - if (isSame) { - return html( - cachedStrings[i].strings as any, - ...dropIndices(values, needlessValues) - ); - } - } + while (str.endsWith('<') || (str.length >= 2 && str.endsWith('</'))) { + needlessValues.push({ value: values[i], index: i }); + str += values[i] + strings[++i]; } - const needlessValues: CachedNeedlessValue[] = []; - const newStrings: string[] = []; - - let str: string; - for (let i = 0, n = strings.length; i < n; ++i) { - str = strings[i]; - - while ( - str[str.length - 1] === '<' // open tag - || (str[str.length - 2] === '<' && str[str.length - 1] === '/') // close tag - ) { - needlessValues.push({ - value: values[i], - index: i, - }); - str += values[i] + strings[++i]; - } + newStrings.push(str); + } - newStrings.push(str); - } + // Convert newStrings back to TemplateStringsArray type + const finalStrings = Object.assign([...newStrings], { raw: strings.raw }); - if (!cachedStrings) { - cachedStrings = []; - templateStringsCache.set(strings, cachedStrings); - } + if (!cachedStrings) { + cachedStrings = []; + templateStringsCache.set(strings, cachedStrings); + } - cachedStrings.push({ - strings: newStrings, - needlessValues, - }); + cachedStrings.push({ + strings: finalStrings as TemplateStringsArray, + needlessValues, + }); - return html(newStrings as any, ...dropIndices(values, needlessValues)); -} \ No newline at end of file + return html( + finalStrings as TemplateStringsArray, + ...filterOutNeedlessValues(values, needlessValues), + ); +} diff --git a/src/libs/polyfills.ts b/src/libs/polyfills.ts index 6ad45348f625a6f90531f9dcb537ba32dfc2cbfc..f79eb489520b09186714c6b77f5a1468412e2295 100644 --- a/src/libs/polyfills.ts +++ b/src/libs/polyfills.ts @@ -3,11 +3,11 @@ if (!('flat' in Array.prototype)) { Object.defineProperty(Array.prototype, 'flat', { configurable: true, value: function flat(this: any[], depth = 1) { - depth = isNaN(depth) ? 1 : Number(depth); + depth = Number.isNaN(depth) ? 1 : Number(depth); if (depth === 0) return Array.prototype.slice.call(this); return Array.prototype.reduce.call<any, any[], any[]>( this, - function(acc:any[], cur: any) { + (acc: any[], cur: any) => { if (Array.isArray(cur)) { acc.push.apply(acc, flat.call(cur, depth - 1)); } else { @@ -24,7 +24,7 @@ if (!('flat' in Array.prototype)) { // Element.prototype.toggleAttribute if (!Element.prototype.toggleAttribute) { - Element.prototype.toggleAttribute = function(name, force = undefined) { + Element.prototype.toggleAttribute = function (name, force = undefined) { if (force !== undefined) force = !!force; if (this.hasAttribute(name)) { @@ -40,4 +40,4 @@ if (!Element.prototype.toggleAttribute) { }; } -export {} +export {}; diff --git a/src/libs/store/custom-getter.ts b/src/libs/store/custom-getter.ts index 15d7457312776584b29e996e46e0f084a85530c4..317b09bef84af61e15f7712491a61371f39390cd 100644 --- a/src/libs/store/custom-getter.ts +++ b/src/libs/store/custom-getter.ts @@ -1,316 +1,387 @@ import JSONLDContextParser from 'jsonld-context-parser'; -import { store } from './store'; -import type { Resource } from '../../mixins/interfaces'; +import type { Resource } from '../../mixins/interfaces.ts'; +import { store } from './store.ts'; const ContextParser = JSONLDContextParser.ContextParser; - export class CustomGetter { - resource: any; // content of the requested resource - resourceId: string; - clientContext: object; // context given by the app - serverContext: object; // context given by the server - parentId: string; // id of the parent resource, used to get the absolute url of the current resource - containerTypes: string[]; // types of resources interpreted as containers - serverPagination: object; // pagination attributes to give to server - serverSearch: object; // search attributes to give to server - - constructor( - resourceId: string, - resource: object, - clientContext: object, - serverContext: object, - parentId: string = "", - serverPagination: object = {}, - serverSearch: object = {}) { - this.clientContext = clientContext; - this.serverContext = serverContext; - this.parentId = parentId; - this.resource = resource; - this.resourceId = resourceId; - this.serverPagination = serverPagination; - this.serverSearch = serverSearch; - - this.containerTypes = [ - this.getExpandedPredicate("ldp:Container"), - this.getExpandedPredicate("ldp:BasicContainer"), - this.getExpandedPredicate("ldp:DirectContainer"), - this.getExpandedPredicate("ldp:IndirectContainer"), - this.getExpandedPredicate("sib:federatedContainer"), - ]; - } - - /** - * Get the property of a resource for a given path - * Which means that if the resource is not complete, it will fetch it - * And that we handle the `.` notation, traversing the path recursively - * @param path: string - */ - async get(path: any) { - if (!path) return; - - // Specific case where the predicates is a full IRI, avoid splitting it on the dot notation - try { - let isUrl = new URL(path); - // My goal is to be able to solve user['circles.ldp:contains'] on the fly - // If we do not check the url protocol, then it is considered valid - if (!isUrl.protocol.startsWith('http')) throw new Error('Not a valid HTTP url'); - // If the path is a HTTP-scheme based URL, we need to fetch the resource directly - if (isUrl) { - let resources = this.resource[this.getExpandedPredicate(path)]; - if (!resources) return undefined; - if (!Array.isArray(resources)) resources = [resources]; // convert to array if compacted to 1 resource - - let result = resources ? resources.map((res: object) => { - let resource: any = store.get(res['@id']); - if (resource) return resource; - - // if not in cache, generate the basic resource - resource = new CustomGetter(res['@id'], { '@id': res['@id'] }, this.clientContext, this.serverContext, this.parentId).getProxy() - store.cacheResource(res['@id'], resource); // put it in cache - return resource; // and return it - }) : []; - - return result; - } - } catch (e) { - if (!path.split) return undefined; - - // Split the path on each dots - const path1: string[] = path.split('.'); - - // Intermediate path var to request each resource individually until the path traversal is completed - const path2: string[] = []; - - // Actual value found from the store, if any - let value: any; - - if (!this.isFullResource()) { // if resource is not complete, fetch it first - await this.getResource(this.resourceId, {...this.clientContext, ...this.serverContext}, this.parentId); - } - - // If the path contains dot, we need to traverse the path recursively - // We do that by poping one element from path1 at each step and affecting it to path2 - // Trying to get the value from it - while (true) { - value = await this.resource[this.getExpandedPredicate(path1[0])]; - - if (path1.length <= 1) break; // no dot path - const lastPath1El = path1.pop(); - if(lastPath1El) path2.unshift(lastPath1El); - } - - if (path2.length === 0) { // end of the path - if (!value || !value['@id']) return this.getLiteralValue(value); // no value or not a resource - return await this.getResource(value['@id'], {...this.clientContext, ...this.serverContext}, this.parentId || this.resourceId); // return complete resource - } - if (!value || !value['@id']) return undefined; - - let resource = await this.getResource(value['@id'], {...this.clientContext, ...this.serverContext}, this.parentId || this.resourceId); - store.subscribeResourceTo(this.resourceId, value['@id']); - return resource ? await resource[path2.join('.')] : undefined; // return value - } - } - - /** - * Return value depending of the current language - * @param value - * @returns - */ - getLiteralValue(value: any): string|string[]|null { - if (typeof value === "object") { // value object: https://www.w3.org/TR/json-ld11/#value-objects - if (value['@value']) { // 1 language - return value['@value']; - } else if (Array.isArray(value)) { - if (value.length === 0) return null; - if(Array.isArray(value[0])) { // multiple languages - const ln = store._getLanguage(); - let translatedValue = value.find(v => v['@language'] && v['@language'] === ln); // find current language - if (!translatedValue) translatedValue = value.find(v => v['@language'] && v['@language'] === 'en'); // default to en - return translatedValue ? (translatedValue['@value'] || null) : null; // return value when no translated value is found - } - return value; - } - } - return value; // simple value - } - - - /** - * Cache resource in the store, and return the created proxy - * @param id - * @param context - * @param iriParent - */ - async getResource(id: string, context: object, iriParent: string, forceFetch: boolean = false): Promise<Resource | null> { - if (id.startsWith('_:b')) return store.get(id + iriParent); // anonymous node = get from cache - return store.getData(id, context, iriParent, undefined ,forceFetch); - } - - - /** - * Return true if the resource is a container - */ - isContainer(): boolean { - if (this.resource["@type"]) { // @type is an array - if (Array.isArray(this.resource["@type"])) - return this.containerTypes.some(type => this.resource["@type"].includes(type)); - return this.containerTypes.includes(this.resource["@type"]); - } else if (this.resource["type"]) { - if (Array.isArray(this.resource["type"])) - return this.containerTypes.some(type => this.resource["type"].includes(type)); - return this.containerTypes.includes(this.resource["type"]); - } - - return false; - } - - /** - * Return true if the given key in the current resource in an array - */ - isArray(): boolean { - if (Array.isArray(this.resource)) - return true; - - return false; - } - - - /** - * Get all properties of a resource - */ - getProperties(): string[] { - return Object.keys(this.resource).map(prop => this.getCompactedPredicate(prop)); - } - - /** - * Get children of container as objects - */ - getChildren(predicateName : string): object[] { - return this.resource[this.getExpandedPredicate(predicateName)] || []; - } - - /** - * Get children of container as Proxys - */ - getLdpContains(): CustomGetter[]|null { - let children = this.resource[this.getExpandedPredicate("ldp:contains")]; - if (!children) return null; - if (!Array.isArray(children)) children = [children]; // convert to array if compacted to 1 resource - - let result = children ? children.map((res: object) => { - let resource: any = store.get(res['@id']); - if (resource) return resource; - - // if not in cache, generate the basic resource - resource = new CustomGetter(res['@id'], { '@id': res['@id'] }, this.clientContext, this.serverContext, this.parentId).getProxy() - store.cacheResource(res['@id'], resource); // put it in cache - return resource; // and return it - }) : []; + resource: any; // content of the requested resource + resourceId: string; + clientContext: object; // context given by the app + serverContext: object; // context given by the server + parentId: string; // id of the parent resource, used to get the absolute url of the current resource + containerTypes: string[]; // types of resources interpreted as containers + serverPagination: object; // pagination attributes to give to server + serverSearch: object; // search attributes to give to server + + constructor( + resourceId: string, + resource: object, + clientContext: object, + serverContext: object, + parentId = '', + serverPagination: object = {}, + serverSearch: object = {}, + ) { + this.clientContext = clientContext; + this.serverContext = serverContext; + this.parentId = parentId; + this.resource = resource; + this.resourceId = resourceId; + this.serverPagination = serverPagination; + this.serverSearch = serverSearch; + + this.containerTypes = [ + this.getExpandedPredicate('ldp:Container'), + this.getExpandedPredicate('ldp:BasicContainer'), + this.getExpandedPredicate('ldp:DirectContainer'), + this.getExpandedPredicate('ldp:IndirectContainer'), + this.getExpandedPredicate('sib:federatedContainer'), + ]; + } + + /** + * Get the property of a resource for a given path + * Which means that if the resource is not complete, it will fetch it + * And that we handle the `.` notation, traversing the path recursively + * @param path: string + */ + async get(path: any) { + if (!path) return; + + // Specific case where the predicates is a full IRI, avoid splitting it on the dot notation + try { + const isUrl = new URL(path); + // My goal is to be able to solve user['circles.ldp:contains'] on the fly + // If we do not check the url protocol, then it is considered valid + if (!isUrl.protocol.startsWith('http')) + throw new Error('Not a valid HTTP url'); + // If the path is a HTTP-scheme based URL, we need to fetch the resource directly + if (isUrl) { + let resources = this.resource[this.getExpandedPredicate(path)]; + if (!resources) return undefined; + if (!Array.isArray(resources)) resources = [resources]; // convert to array if compacted to 1 resource + + const result = resources + ? resources.map((res: object) => { + let resource: any = store.get(res['@id']); + if (resource) return resource; + + // if not in cache, generate the basic resource + resource = new CustomGetter( + res['@id'], + { '@id': res['@id'] }, + this.clientContext, + this.serverContext, + this.parentId, + ).getProxy(); + store.cacheResource(res['@id'], resource); // put it in cache + return resource; // and return it + }) + : []; return result; + } + } catch { + if (!path.split) return undefined; + + // Split the path on each dots + const path1: string[] = path.split('.'); + + // Intermediate path var to request each resource individually until the path traversal is completed + const path2: string[] = []; + + // Actual value found from the store, if any + let value: any; + + if (!this.isFullResource()) { + // if resource is not complete, fetch it first + await this.getResource( + this.resourceId, + { ...this.clientContext, ...this.serverContext }, + this.parentId, + ); + } + + // If the path contains dot, we need to traverse the path recursively + // We do that by poping one element from path1 at each step and affecting it to path2 + // Trying to get the value from it + while (true) { + value = await this.resource[this.getExpandedPredicate(path1[0])]; + + if (path1.length <= 1) break; // no dot path + const lastPath1El = path1.pop(); + if (lastPath1El) path2.unshift(lastPath1El); + } + + if (path2.length === 0) { + // end of the path + if (!value || !value['@id']) return this.getLiteralValue(value); // no value or not a resource + return await this.getResource( + value['@id'], + { ...this.clientContext, ...this.serverContext }, + this.parentId || this.resourceId, + ); // return complete resource + } + if (!value || !value['@id']) return undefined; + + const resource = await this.getResource( + value['@id'], + { ...this.clientContext, ...this.serverContext }, + this.parentId || this.resourceId, + ); + store.subscribeResourceTo(this.resourceId, value['@id']); + return resource ? await resource[path2.join('.')] : undefined; // return value } - - - merge(resource: CustomGetter) { - this.resource = { ...this.getResourceData(), ...resource.getResourceData() } + } + + /** + * Return value depending of the current language + * @param value + * @returns + */ + getLiteralValue(value: any): string | string[] | null { + if (typeof value !== 'object') return value; + // value object: https://www.w3.org/TR/json-ld11/#value-objects + if (value['@value']) return value['@value']; // 1 language + if (!Array.isArray(value)) return value; + if (value.length === 0) return null; + if (!Array.isArray(value[0])) return value; + // multiple languages + const ln = store._getLanguage(); + let translatedValue = value.find( + v => v['@language'] && v['@language'] === ln, + ); // find current language + if (!translatedValue) + translatedValue = value.find( + v => v['@language'] && v['@language'] === 'en', + ); // default to en + return translatedValue?.['@value'] ?? null; // return value when no translated value is found + } + + /** + * Cache resource in the store, and return the created proxy + * @param id + * @param context + * @param iriParent + */ + async getResource( + id: string, + context: object, + iriParent: string, + forceFetch = false, + ): Promise<Resource | null> { + if (id.startsWith('_:b')) return await store.get(id + iriParent); // anonymous node = get from cache + return store.getData(id, context, iriParent, undefined, forceFetch); + } + + /** + * Return true if the resource is a container + */ + isContainer(): boolean { + if (this.resource['@type']) { + // @type is an array + if (Array.isArray(this.resource['@type'])) + return this.containerTypes.some(type => + this.resource['@type'].includes(type), + ); + return this.containerTypes.includes(this.resource['@type']); } - - getResourceData(): object { return this.resource } - - /** - * return true resource seems complete - * @param prop - */ - isFullResource(): boolean { - let propertiesKeys = Object.keys(this.resource).filter(p => !p.startsWith('@')); - if (this.resource['@id'].startsWith('_:b')) return true; // anonymous node = considered as always full - - if (propertiesKeys.length === 1 && propertiesKeys[0] === this.getExpandedPredicate('permissions')) - return false; // If only the permissions are present, then the resource is not complete - else if (propertiesKeys.length > 0) return true; - + if (!this.resource.type) return false; + + if (Array.isArray(this.resource.type)) + return this.containerTypes.some(type => + this.resource.type.includes(type), + ); + return this.containerTypes.includes(this.resource.type); + } + + /** + * Return true if the given key in the current resource in an array + */ + isArray(): boolean { + if (Array.isArray(this.resource)) return true; + + return false; + } + + /** + * Get all properties of a resource + */ + getProperties(): string[] { + return Object.keys(this.resource).map(prop => + this.getCompactedPredicate(prop), + ); + } + + /** + * Get children of container as objects + */ + getChildren(predicateName: string): object[] { + return this.resource[this.getExpandedPredicate(predicateName)] || []; + } + + /** + * Get children of container as Proxys + */ + getLdpContains(): CustomGetter[] | null { + let children = this.resource[this.getExpandedPredicate('ldp:contains')]; + if (!children) return null; + if (!Array.isArray(children)) children = [children]; // convert to array if compacted to 1 resource + + const result = children + ? children.map((res: object) => { + let resource: any = store.get(res['@id']); + if (resource) return resource; + + // if not in cache, generate the basic resource + resource = new CustomGetter( + res['@id'], + { '@id': res['@id'] }, + this.clientContext, + this.serverContext, + this.parentId, + ).getProxy(); + store.cacheResource(res['@id'], resource); // put it in cache + return resource; // and return it + }) + : []; + + return result; + } + + merge(resource: CustomGetter) { + this.resource = { + ...this.getResourceData(), + ...resource.getResourceData(), + }; + } + + getResourceData(): object { + return this.resource; + } + + /** + * return true resource seems complete + * @param prop + */ + isFullResource(): boolean { + const propertiesKeys = Object.keys(this.resource).filter( + p => !p.startsWith('@'), + ); + if (this.resource['@id'].startsWith('_:b')) return true; // anonymous node = considered as always full + + if ( + propertiesKeys.length === 1 && + propertiesKeys[0] === this.getExpandedPredicate('permissions') + ) return false; + if (propertiesKeys.length > 0) return true; + + return false; + } + + /** + * Get permissions of a resource + * @param resourceId + * @returns + */ + async getPermissions(): Promise<string[]> { + let permissions = this.resource[this.getExpandedPredicate('permissions')]; + if (!permissions) { + // if no permission, re-fetch data from store + await this.getResource( + this.resourceId, + { ...this.clientContext, ...this.serverContext }, + this.parentId, + true, + ); + permissions = this.resource[this.getExpandedPredicate('permissions')]; } - /** - * Get permissions of a resource - * @param resourceId - * @returns - */ - async getPermissions(): Promise<string[]> { - let permissions = this.resource[this.getExpandedPredicate("permissions")]; - if (!permissions) { // if no permission, re-fetch data from store - await this.getResource( - this.resourceId, - { ...this.clientContext, ...this.serverContext }, - this.parentId, - true - ); - permissions = this.resource[this.getExpandedPredicate("permissions")]; + if (!Array.isArray(permissions)) permissions = [permissions]; // convert to array if compacted to 1 resource + + return permissions ? permissions : []; + } + + /** + * returns compacted @type of resource + */ + getType(): string { + return this.resource['@type'] + ? this.getCompactedIri(this.resource['@type']) + : ''; + } + + /** + * Remove the resource from the cache + */ + clearCache(): void { + store.clearCache(this.resourceId); + } + + getExpandedPredicate(property: string) { + return ContextParser.expandTerm( + property, + { ...this.clientContext, ...this.serverContext }, + true, + ); + } + getCompactedPredicate(property: string) { + return ContextParser.compactIri( + property, + { ...this.clientContext, ...this.serverContext }, + true, + ); + } + getCompactedIri(id: string) { + return ContextParser.compactIri(id, { + ...this.clientContext, + ...this.serverContext, + }); + } + toString() { + return this.getCompactedIri(this.resource['@id']); + } + [Symbol.toPrimitive]() { + return this.getCompactedIri(this.resource['@id']); + } + + /** + * Returns a Proxy which handles the different get requests + */ + getProxy() { + return new Proxy(this, { + get: (resource, property) => { + if (!this.resource) return undefined; + if (typeof resource[property] === 'function') + return resource[property].bind(resource); + + switch (property) { + case '@id': + if (this.resource['@id']) + return this.getCompactedIri(this.resource['@id']); + console.log(this.resource, this.resource['@id']); + return; + case '@type': + return this.resource['@type']; // return synchronously + case 'properties': + return this.getProperties(); + case 'ldp:contains': + return this.getLdpContains(); // returns standard arrays synchronously + case 'permissions': + return this.getPermissions(); // get expanded permissions + case 'clientContext': + return this.clientContext; // get saved client context to re-fetch easily a resource + case 'serverContext': + return this.serverContext; // get saved client context to re-fetch easily a resource + case 'then': + return; + default: + // FIXME: missing 'await' + return resource.get(property); } - - if (!Array.isArray(permissions)) permissions = [permissions]; // convert to array if compacted to 1 resource - - return permissions ? permissions : []; - } - - /** - * returns compacted @type of resource - */ - getType(): string { - return this.resource['@type'] ? this.getCompactedIri(this.resource['@type']) : ''; - } - - /** - * Remove the resource from the cache - */ - clearCache(): void { - store.clearCache(this.resourceId); - } - - getExpandedPredicate(property: string) { return ContextParser.expandTerm(property, { ...this.clientContext, ...this.serverContext }, true) } - getCompactedPredicate(property: string) { return ContextParser.compactIri(property, { ...this.clientContext, ...this.serverContext }, true) } - getCompactedIri(id: string) { return ContextParser.compactIri(id, { ...this.clientContext, ...this.serverContext }) } - toString() { return this.getCompactedIri(this.resource['@id']) } - [Symbol.toPrimitive]() { return this.getCompactedIri(this.resource['@id']) } - - - /** - * Returns a Proxy which handles the different get requests - */ - getProxy() { - return new Proxy(this, { - get: (resource, property) => { - if (!this.resource) return undefined; - if (typeof resource[property] === 'function') return resource[property].bind(resource); - - switch (property) { - case '@id': - if (this.resource['@id']) - return this.getCompactedIri(this.resource['@id']); // Compact @id if possible - else - console.log(this.resource, this.resource['@id']); - return; - case '@type': - return this.resource['@type']; // return synchronously - case 'properties': - return this.getProperties(); - case 'ldp:contains': - return this.getLdpContains(); // returns standard arrays synchronously - case 'permissions': - return this.getPermissions(); // get expanded permissions - case 'clientContext': - return this.clientContext; // get saved client context to re-fetch easily a resource - case 'serverContext': - return this.serverContext; // get saved client context to re-fetch easily a resource - case 'then': - return; - default: - // FIXME: missing 'await' - return resource.get(property) - } - } - }) - } -} \ No newline at end of file + }, + }); + } +} diff --git a/src/libs/store/server-pagination.ts b/src/libs/store/server-pagination.ts index 4edcc9d87b1df0d542b2e3a6c162d41c84195884..3222a343813716163581662f134cd59f8e16f663 100644 --- a/src/libs/store/server-pagination.ts +++ b/src/libs/store/server-pagination.ts @@ -1,24 +1,29 @@ export interface ServerPaginationOptions { - offset: number; - limit: number; + offset: number; + limit: number; } export function formatAttributesToServerPaginationOptions( - elementAttributes: { name: string, value: number }[] + elementAttributes: { name: string; value: number }[], ): ServerPaginationOptions | undefined { - const attributes = new Map(Array.from(elementAttributes).map(({ name, value }) => [name, value])) - const limit = attributes.get('limit'); - const offset = attributes.get('offset'); - if (!offset || !limit) return; - return { - limit: limit, - offset: offset, - } + const attributes = new Map( + Array.from(elementAttributes).map(({ name, value }) => [name, value]), + ); + const limit = attributes.get('limit'); + const offset = attributes.get('offset'); + if (!offset || !limit) return; + return { + limit: limit, + offset: offset, + }; } -export function appendServerPaginationToIri(iri: string, options: ServerPaginationOptions): string { - const first = iri.includes('?') ? '&' : '?'; - const limit = options.limit; - const offset = options.offset; - return `${iri}${first}limit=${limit}&offset=${offset}`; -} \ No newline at end of file +export function appendServerPaginationToIri( + iri: string, + options: ServerPaginationOptions, +): string { + const first = iri.includes('?') ? '&' : '?'; + const limit = options.limit; + const offset = options.offset; + return `${iri}${first}limit=${limit}&offset=${offset}`; +} diff --git a/src/libs/store/server-search.ts b/src/libs/store/server-search.ts index 2ca9e85b563a1a7278603fed17689a4a612ab18b..51b797564c3e056c8e17579c189d25c3e244724d 100644 --- a/src/libs/store/server-search.ts +++ b/src/libs/store/server-search.ts @@ -5,22 +5,27 @@ export interface ServerSearchOptions { } export function formatAttributesToServerSearchOptions( - elementAttributes: Iterable<Attr> + elementAttributes: Iterable<Attr>, ): Partial<ServerSearchOptions> { - const attributes = new Map(Array.from(elementAttributes).map(({ name, value }) => [name, value])); - const fields = attributes.get('server-search-fields')?.split(",").map((field) => field.trim()); + const attributes = new Map( + Array.from(elementAttributes).map(({ name, value }) => [name, value]), + ); + const fields = attributes + .get('server-search-fields') + ?.split(',') + .map(field => field.trim()); const value = attributes.get('server-search-value')?.trim(); const method = attributes.get('server-search-method')?.trim(); return { fields: fields && fields.length > 0 ? fields : undefined, value: value ? value : undefined, - method: method ? method : undefined - } + method: method ? method : undefined, + }; } export function mergeServerSearchOptions( attributesOptions?: Partial<ServerSearchOptions>, - dynamicOptions?: Partial<ServerSearchOptions> + dynamicOptions?: Partial<ServerSearchOptions>, ): ServerSearchOptions | undefined { const fields = attributesOptions?.fields ?? dynamicOptions?.fields; const value = dynamicOptions?.value ?? attributesOptions?.value; @@ -29,10 +34,13 @@ export function mergeServerSearchOptions( return { fields, value, method }; } -export function appendServerSearchToIri(iri: string, options: ServerSearchOptions): string { +export function appendServerSearchToIri( + iri: string, + options: ServerSearchOptions, +): string { const first = iri.includes('?') ? '&' : '?'; const fields = options.fields.map(encodeURIComponent).join(','); const value = encodeURIComponent(options.value); const method = encodeURIComponent(options.method ?? 'ibasic'); return `${iri}${first}search-fields=${fields}&search-terms=${value}&search-method=${method}`; -} \ No newline at end of file +} diff --git a/src/libs/store/store.ts b/src/libs/store/store.ts index c632f8506c412fc09c3c13ff29ec34655bc9a255..03342e7a0cd8fbacbd449d5fd383c00954b01d54 100644 --- a/src/libs/store/store.ts +++ b/src/libs/store/store.ts @@ -1,51 +1,50 @@ import JSONLDContextParser from 'jsonld-context-parser'; -//@ts-ignore -import PubSub from 'https://cdn.skypack.dev/pubsub-js'; +import PubSub from 'pubsub-js'; import jsonld from 'jsonld'; -import { CustomGetter } from './custom-getter'; +import { CustomGetter } from './custom-getter.ts'; -import type { Resource } from '../../mixins/interfaces'; -import type { ServerSearchOptions } from './server-search'; -import { appendServerSearchToIri } from './server-search'; +import type { Resource } from '../../mixins/interfaces.ts'; +import type { ServerSearchOptions } from './server-search.ts'; +import { appendServerSearchToIri } from './server-search.ts'; -import type { ServerPaginationOptions } from './server-pagination'; -import { appendServerPaginationToIri } from './server-pagination'; +import type { ServerPaginationOptions } from './server-pagination.ts'; +import { appendServerPaginationToIri } from './server-pagination.ts'; const ContextParser = JSONLDContextParser.ContextParser; const myParser = new ContextParser(); export const base_context = { - '@vocab': "https://cdn.startinblox.com/owl#", - foaf: "http://xmlns.com/foaf/0.1/", - doap: "http://usefulinc.com/ns/doap#", - ldp: "http://www.w3.org/ns/ldp#", - rdfs: "http://www.w3.org/2000/01/rdf-schema#", - rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", - xsd: "http://www.w3.org/2001/XMLSchema#", - geo: "http://www.w3.org/2003/01/geo/wgs84_pos#", - acl: "http://www.w3.org/ns/auth/acl#", - hd: "http://cdn.startinblox.com/owl/ttl/vocab.ttl#", - sib: "http://cdn.startinblox.com/owl/ttl/vocab.ttl#", - name: "rdfs:label", - deadline: "xsd:dateTime", - lat: "geo:lat", - lng: "geo:long", - jabberID: "foaf:jabberID", - permissions: "acl:accessControl", - mode: "acl:mode", - view: "acl:Read", - change: "acl:Write", - add: "acl:Append", - delete: "acl:Delete", - control: "acl:Control" + '@vocab': 'https://cdn.startinblox.com/owl#', + foaf: 'http://xmlns.com/foaf/0.1/', + doap: 'http://usefulinc.com/ns/doap#', + ldp: 'http://www.w3.org/ns/ldp#', + rdfs: 'http://www.w3.org/2000/01/rdf-schema#', + rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + xsd: 'http://www.w3.org/2001/XMLSchema#', + geo: 'http://www.w3.org/2003/01/geo/wgs84_pos#', + acl: 'http://www.w3.org/ns/auth/acl#', + hd: 'http://cdn.startinblox.com/owl/ttl/vocab.ttl#', + sib: 'http://cdn.startinblox.com/owl/ttl/vocab.ttl#', + name: 'rdfs:label', + deadline: 'xsd:dateTime', + lat: 'geo:lat', + lng: 'geo:long', + jabberID: 'foaf:jabberID', + permissions: 'acl:accessControl', + mode: 'acl:mode', + view: 'acl:Read', + change: 'acl:Write', + add: 'acl:Append', + delete: 'acl:Delete', + control: 'acl:Control', }; -class Store { +export class Store { cache: Map<string, any>; subscriptionIndex: Map<string, any>; // index of all the containers per resource subscriptionVirtualContainersIndex: Map<string, any>; // index of all the containers per resource - loadingList: Set<String>; + loadingList: Set<string>; headers: object; fetch: Promise<any> | undefined; session: Promise<any> | undefined; @@ -55,7 +54,11 @@ class Store { this.subscriptionIndex = new Map(); this.subscriptionVirtualContainersIndex = new Map(); this.loadingList = new Set(); - this.headers = {'Accept': 'application/ld+json', 'Content-Type': 'application/ld+json', 'Cache-Control': 'must-revalidate'}; + this.headers = { + Accept: 'application/ld+json', + 'Content-Type': 'application/ld+json', + 'Cache-Control': 'must-revalidate', + }; this.fetch = this.storeOptions.fetchMethod; this.session = this.storeOptions.session; } @@ -70,7 +73,7 @@ class Store { * @param serverPagination - Server pagination options * @param serverSearch - Server search options * @param predicateName - predicate name if we target a specific predicate from the resource, useful for arrays - * + * * @returns The fetched resource * * @async @@ -78,28 +81,35 @@ class Store { async getData( id: string, context: any = {}, - parentId = "", + parentId = '', localData?: object, - forceFetch: boolean = false, + forceFetch = false, serverPagination?: ServerPaginationOptions, - serverSearch?: ServerSearchOptions - ): Promise<Resource|null> { + serverSearch?: ServerSearchOptions, + ): Promise<Resource | null> { let key = id; if (serverPagination) { - key = appendServerPaginationToIri(key, serverPagination) + key = appendServerPaginationToIri(key, serverPagination); } if (serverSearch) { - key = appendServerSearchToIri(key, serverSearch) + key = appendServerSearchToIri(key, serverSearch); } - if (localData == null && this.cache.has(key) && !this.loadingList.has(key)) { + if ( + localData == null && + this.cache.has(key) && + !this.loadingList.has(key) + ) { const resource = this.get(key); - if (resource && resource.isFullResource?.() && !forceFetch) return resource; // if resource is not complete, re-fetch it + if (resource?.isFullResource?.() && !forceFetch) return await resource; // if resource is not complete, re-fetch it } - return new Promise(async (resolve) => { - document.addEventListener('resourceReady', this.resolveResource(key, resolve)); + return new Promise(async resolve => { + document.addEventListener( + 'resourceReady', + this.resolveResource(key, resolve), + ); if (this.loadingList.has(key)) return; this.loadingList.add(key); @@ -107,25 +117,57 @@ class Store { // Generate proxy const clientContext = await myParser.parse(context); let resource: any = null; - if(this._isLocalId(id)) { - if(localData == null) localData = {}; - localData["@id"] = id; + if (this._isLocalId(id)) { + if (localData == null) localData = {}; + localData['@id'] = id; resource = localData; - } else try { - resource = localData || await this.fetchData(id, clientContext, parentId, serverPagination, serverSearch); - } catch (error) { console.error(error) } + } else + try { + resource = + localData || + (await this.fetchData( + id, + clientContext, + parentId, + serverPagination, + serverSearch, + )); + } catch (error) { + console.error(error); + } if (!resource) { this.loadingList.delete(key); - document.dispatchEvent(new CustomEvent('resourceReady', { detail: { id: key, resource: null, fetchedResource: null } })); + document.dispatchEvent( + new CustomEvent('resourceReady', { + detail: { id: key, resource: null, fetchedResource: null }, + }), + ); return; } - const serverContext = await myParser.parse([resource['@context'] || base_context]); + const serverContext = await myParser.parse([ + resource['@context'] || base_context, + ]); // const resourceProxy = new CustomGetter(key, resource, clientContext, serverContext, parentId ? parentId : key, serverPagination, serverSearch).getProxy(); // Cache proxy - await this.cacheGraph(resource, clientContext, serverContext, parentId ? parentId : key, serverPagination, serverSearch); + await this.cacheGraph( + resource, + clientContext, + serverContext, + parentId ? parentId : key, + serverPagination, + serverSearch, + ); this.loadingList.delete(key); - document.dispatchEvent(new CustomEvent('resourceReady', { detail: { id: key, resource: this.get(key), fetchedResource: resource } })); + document.dispatchEvent( + new CustomEvent('resourceReady', { + detail: { + id: key, + resource: this.get(key), + fetchedResource: resource, + }, + }), + ); }); } @@ -133,14 +175,14 @@ class Store { let authenticated = false; if (this.session) authenticated = await this.session; - if (this.fetch && authenticated) { // authenticated - return this.fetch.then(fn => fn(iri, options)) - } else { // anonymous - if (options.headers) options.headers = this._convertHeaders(options.headers); - return fetch(iri, options).then(function(response) { - return response; - }); + if (this.fetch && authenticated) { + // authenticated + return this.fetch.then(fn => fn(iri, options)); } + // anonymous + if (options.headers) + options.headers = this._convertHeaders(options.headers); + return fetch(iri, options).then(response => response); } /** @@ -155,21 +197,21 @@ class Store { async fetchData( id: string, context = {}, - parentId = "", + parentId = '', serverPagination?: ServerPaginationOptions, - serverSearch?: ServerSearchOptions + serverSearch?: ServerSearchOptions, ) { let iri = this._getAbsoluteIri(id, context, parentId); - if (serverPagination) iri = appendServerPaginationToIri(iri, serverPagination); + if (serverPagination) + iri = appendServerPaginationToIri(iri, serverPagination); if (serverSearch) iri = appendServerSearchToIri(iri, serverSearch); const headers = { ...this.headers, - 'accept-language': this._getLanguage() + 'accept-language': this._getLanguage(), // 'Prefer' : 'return=representation; max-triple-count="100"' // Commenting out for now as it raises CORS errors }; - /** * Fetch data with authentication if available (sib-auth) * @param iri - iri to call @@ -179,14 +221,14 @@ class Store { return this.fetchAuthn(iri, { method: 'GET', headers: headers, - credentials: 'include' - }).then((response) => { + credentials: 'include', + }).then(response => { if (!response.ok) return; return response.json(); - }) + }); } - /** + /** * Cache the whole graph * @param resource - graph fetched * @param clientContext - context of the client app @@ -201,7 +243,7 @@ class Store { parentContext: object, parentId: string, serverPagination?: ServerPaginationOptions, - serverSearch?: ServerSearchOptions + serverSearch?: ServerSearchOptions, ) { // Flatten and compact the graph, which is an issue with large containers having child permissions serialized // Because @@ -211,11 +253,13 @@ class Store { // So either we do not modify the key of the blank nodes to force them into the cache // Either we modify it by adding the parentId and we end up with // a lot of cached permissions objects associated with the container top resource (like xxxxx/circles/) - const flattenedResources = await jsonld.flatten(resource); - const compactedResources: any[] = await Promise.all(flattenedResources.map(r => jsonld.compact(r, {}))) - for (let resource of compactedResources) { - let id = resource['@id'] || resource['id']; - let key = resource['@id'] || resource['id']; + const flattenedResources: any = await jsonld.flatten(resource); + const compactedResources: any[] = await Promise.all( + flattenedResources.map(r => jsonld.compact(r, {})), + ); + for (const resource of compactedResources) { + const id = resource['@id'] || resource.id; + let key = resource['@id'] || resource.id; if (!key) console.log('No key or id for resource:', resource); if (key === '/') key = parentId; @@ -225,17 +269,34 @@ class Store { // Using a dedicated method in the custom-getter. // We have to add the server search and pagination attributes again here to the resource cache key - if (key === id && resource['@type'] == this.getExpandedPredicate("ldp:Container", clientContext)) { // Add only pagination and search params to the original resource - if (serverPagination) key = appendServerPaginationToIri(key, serverPagination); + if ( + key === id && + resource['@type'] === + this.getExpandedPredicate('ldp:Container', clientContext) + ) { + // Add only pagination and search params to the original resource + if (serverPagination) + key = appendServerPaginationToIri(key, serverPagination); if (serverSearch) key = appendServerSearchToIri(key, serverSearch); } - const resourceProxy = new CustomGetter(key, resource, clientContext, parentContext, parentId, serverPagination, serverSearch).getProxy(); - if (resourceProxy.isContainer()) this.subscribeChildren(resourceProxy, id); - - if (this.get(key)) { // if already cached, merge data + const resourceProxy = new CustomGetter( + key, + resource, + clientContext, + parentContext, + parentId, + serverPagination, + serverSearch, + ).getProxy(); + if (resourceProxy.isContainer()) + this.subscribeChildren(resourceProxy, id); + + if (this.get(key)) { + // if already cached, merge data this.cache.get(key).merge(resourceProxy); - } else { // else, put in cache + } else { + // else, put in cache this.cacheResource(key, resourceProxy); } } @@ -263,14 +324,16 @@ class Store { method: method, headers: this.headers, body: JSON.stringify(resource), - credentials: 'include' + credentials: 'include', }); const resourceProxy = store.get(id); - const clientContext = resourceProxy ? {...resourceProxy.clientContext, ...resource['@context']} : resource['@context'] + const clientContext = resourceProxy + ? { ...resourceProxy.clientContext, ...resource['@context'] } + : resource['@context']; this.clearCache(id); await this.getData(id, clientContext, '', resource); - return {ok: true} + return { ok: true }; } /** @@ -279,11 +342,11 @@ class Store { */ subscribeChildren(container: CustomGetter, containerId: string) { if (!container['ldp:contains']) return; - for (let res of container['ldp:contains']) { - this.subscribeResourceTo(containerId, res['@id'] || res['id']); + for (const res of container['ldp:contains']) { + this.subscribeResourceTo(containerId, res['@id'] || res.id); } } - + /** * Update a resource * @param method - can be POST, PUT or PATCH @@ -292,27 +355,39 @@ class Store { * @returns void */ async _updateResource(method: string, resource: object, id: string) { - if (!['POST', 'PUT', 'PATCH', '_LOCAL'].includes(method)) throw new Error('Error: method not allowed'); + if (!['POST', 'PUT', 'PATCH', '_LOCAL'].includes(method)) + throw new Error('Error: method not allowed'); const context = await myParser.parse([resource['@context'] || {}]); // parse context before expandTerm const expandedId = this._getExpandedId(id, context); - return this._fetch(method, resource, id).then(async(response) => { + return this._fetch(method, resource, id).then(async response => { if (response.ok) { - if(method !== '_LOCAL') { + if (method !== '_LOCAL') { this.clearCache(expandedId); } // clear cache - this.getData(expandedId, resource['@context']).then(async () => { // re-fetch data + this.getData(expandedId, resource['@context']).then(async () => { + // re-fetch data const nestedResources = await this.getNestedResources(resource, id); - const resourcesToRefresh = this.subscriptionVirtualContainersIndex.get(expandedId) || []; - const resourcesToNotify = this.subscriptionIndex.get(expandedId) || []; - - return this.refreshResources([...nestedResources, ...resourcesToRefresh]) // refresh related resources - .then(resourceIds => this.notifyResources([expandedId, ...resourceIds, ...resourcesToNotify])); // notify components + const resourcesToRefresh = + this.subscriptionVirtualContainersIndex.get(expandedId) || []; + const resourcesToNotify = + this.subscriptionIndex.get(expandedId) || []; + + return this.refreshResources([ + ...nestedResources, + ...resourcesToRefresh, + ]) // refresh related resources + .then(resourceIds => + this.notifyResources([ + expandedId, + ...resourceIds, + ...resourcesToNotify, + ]), + ); // notify components }); return response.headers?.get('Location') || null; - } else { - throw response; } + throw response; }); } @@ -323,18 +398,25 @@ class Store { */ async refreshResources(resourceIds: string[]) { resourceIds = [...new Set(resourceIds.filter(id => this.cache.has(id)))]; // remove duplicates and not cached resources - const resourceWithContexts = resourceIds.map(resourceId => ({ "id": resourceId, "context": store.get(resourceId)?.clientContext })); + const resourceWithContexts = resourceIds.map(resourceId => ({ + id: resourceId, + context: store.get(resourceId)?.clientContext, + })); for (const resource of resourceWithContexts) { if (!this._isLocalId(resource.id)) this.clearCache(resource.id); } - await Promise.all(resourceWithContexts.map(({ id, context }) => this.getData(id, context || base_context))) + await Promise.all( + resourceWithContexts.map(({ id, context }) => + this.getData(id, context || base_context), + ), + ); return resourceIds; } /** * Notifies all components for a list of ids * @param resourceIds - */ - async notifyResources(resourceIds: string[]) { + notifyResources(resourceIds: string[]) { resourceIds = [...new Set(resourceIds)]; // remove duplicates for (const id of resourceIds) PubSub.publish(id); } @@ -344,16 +426,18 @@ class Store { * @param resource - object * @param id - string */ - async getNestedResources(resource: object, id: string) { + getNestedResources(resource: object, id: string) { const cachedResource = store.get(id); if (!cachedResource || cachedResource.isContainer?.()) return []; - let nestedProperties:any[] = []; + const nestedProperties: any[] = []; const excludeKeys = ['@context']; - for (let p of Object.keys(resource)) { - if (resource[p] - && typeof resource[p] === 'object' - && !excludeKeys.includes(p) - && resource[p]['@id']) { + for (const p of Object.keys(resource)) { + if ( + resource[p] && + typeof resource[p] === 'object' && + !excludeKeys.includes(p) && + resource[p]['@id'] + ) { nestedProperties.push(resource[p]['@id']); } } @@ -366,7 +450,11 @@ class Store { * * @returns Resource (Proxy) if in the cache, null otherwise */ - get(id: string, serverPagination?: ServerPaginationOptions, serverSearch?: ServerSearchOptions): Resource | null { + get( + id: string, + serverPagination?: ServerPaginationOptions, + serverSearch?: ServerSearchOptions, + ): Resource | null { if (serverPagination) { id = appendServerPaginationToIri(id, serverPagination); } @@ -378,7 +466,6 @@ class Store { return this.cache.get(id) || null; } - /** * Removes a resource from the cache * @param id - id of the resource to remove from the cache @@ -388,9 +475,10 @@ class Store { // For federation, clear each source const resource = this.cache.get(id); if (resource['@type'] === 'ldp:Container') { - resource['ldp:contains'].forEach((child: object) => { - if (child && child['@type'] === 'ldp:Container') this.cache.delete(child['@id']) - }) + for (const child of resource['ldp:contains']) { + if (child && child['@type'] === 'ldp:Container') + this.cache.delete(child['@id']); + } } this.cache.delete(id); @@ -404,7 +492,7 @@ class Store { * * @returns id of the posted resource */ - async setLocalData(resource: object, id: string): Promise<string | null> { + setLocalData(resource: object, id: string): Promise<string | null> { return this._updateResource('_LOCAL', resource, id); } @@ -415,7 +503,7 @@ class Store { * * @returns id of the posted resource */ - async post(resource: object, id: string): Promise<string | null> { + post(resource: object, id: string): Promise<string | null> { return this._updateResource('POST', resource, id); } @@ -426,7 +514,7 @@ class Store { * * @returns id of the edited resource */ - async put(resource: object, id: string): Promise<string | null> { + put(resource: object, id: string): Promise<string | null> { return this._updateResource('PUT', resource, id); } @@ -437,7 +525,7 @@ class Store { * * @returns id of the edited resource */ - async patch(resource: object, id: string): Promise<string | null> { + patch(resource: object, id: string): Promise<string | null> { return this._updateResource('PATCH', resource, id); } @@ -453,14 +541,16 @@ class Store { const deleted = await this.fetchAuthn(expandedId, { method: 'DELETE', headers: this.headers, - credentials: 'include' + credentials: 'include', }); - const resourcesToNotify = this.subscriptionIndex.get(expandedId) || []; - const resourcesToRefresh = this.subscriptionVirtualContainersIndex.get(expandedId) || []; + const resourcesToNotify = this.subscriptionIndex.get(expandedId) || []; + const resourcesToRefresh = + this.subscriptionVirtualContainersIndex.get(expandedId) || []; - this.refreshResources([...resourcesToNotify, ...resourcesToRefresh]) - .then(resourceIds => this.notifyResources(resourceIds)); + this.refreshResources([...resourcesToNotify, ...resourcesToRefresh]).then( + resourceIds => this.notifyResources(resourceIds), + ); return deleted; } @@ -472,14 +562,16 @@ class Store { */ _convertHeaders(headersObject: object): Headers { const headers = new Headers(); - for (const [key, value] of Object.entries(headersObject)){ + for (const [key, value] of Object.entries(headersObject)) { headers.set(key, value as string); } return headers; } _getExpandedId(id: string, context: object) { - return (context && Object.keys(context)) ? ContextParser.expandTerm(id, context) : id; + return context && Object.keys(context) + ? ContextParser.expandTerm(id, context) + : id; } /** @@ -489,9 +581,8 @@ class Store { * @returns The fully expanded term */ getExpandedPredicate(property: string, context: object | null) { - if (!context) - return ContextParser.expandTerm(property, base_context, true) - return ContextParser.expandTerm(property, context, true) + if (!context) return ContextParser.expandTerm(property, base_context, true); + return ContextParser.expandTerm(property, context, true); } /** @@ -501,9 +592,8 @@ class Store { * @returns The compacted term */ getCompactedIri(property: string, context: object | null) { - if (!context) - return ContextParser.compactIri(property, base_context, true) - return ContextParser.compactIri(property, context, true) + if (!context) return ContextParser.compactIri(property, base_context, true); + return ContextParser.compactIri(property, context, true); } /** @@ -521,8 +611,11 @@ class Store { * @param nestedResourceId - id of the resource which will change */ subscribeResourceTo(resourceId: string, nestedResourceId: string) { - const existingSubscriptions = this.subscriptionIndex.get(nestedResourceId) || []; - this.subscriptionIndex.set(nestedResourceId, [...new Set([...existingSubscriptions, resourceId])]) + const existingSubscriptions = + this.subscriptionIndex.get(nestedResourceId) || []; + this.subscriptionIndex.set(nestedResourceId, [ + ...new Set([...existingSubscriptions, resourceId]), + ]); } /** @@ -530,9 +623,15 @@ class Store { * @param virtualContainerId - id of the container which needs to be updated * @param nestedResourceId - id of the resource which will change */ - subscribeVirtualContainerTo(virtualContainerId: string, nestedResourceId: string) { - const existingSubscriptions = this.subscriptionVirtualContainersIndex.get(nestedResourceId) || []; - this.subscriptionVirtualContainersIndex.set(nestedResourceId, [...new Set([...existingSubscriptions, virtualContainerId])]) + subscribeVirtualContainerTo( + virtualContainerId: string, + nestedResourceId: string, + ) { + const existingSubscriptions = + this.subscriptionVirtualContainersIndex.get(nestedResourceId) || []; + this.subscriptionVirtualContainersIndex.set(nestedResourceId, [ + ...new Set([...existingSubscriptions, virtualContainerId]), + ]); } /** @@ -543,8 +642,9 @@ class Store { */ _getAbsoluteIri(id: string, context: object, parentId: string): string { let iri = ContextParser.expandTerm(id, context); // expand if reduced ids - if (parentId && !parentId.startsWith('store://local')) { // and get full URL from parent caller for local files - let parentIri = new URL(parentId, document.location.href).href; + if (parentId && !parentId.startsWith('store://local')) { + // and get full URL from parent caller for local files + const parentIri = new URL(parentId, document.location.href).href; iri = new URL(iri, parentIri).href; } else { iri = new URL(iri, document.location.href).href; @@ -563,7 +663,9 @@ class Store { * Return language of the users */ _getLanguage() { - return localStorage.getItem('language') || window.navigator.language.slice(0,2); + return ( + localStorage.getItem('language') || window.navigator.language.slice(0, 2) + ); } /** @@ -574,10 +676,10 @@ class Store { localStorage.setItem('language', selectedLanguageCode); } - resolveResource = function(id: string, resolve) { - const handler = function(event) { + resolveResource = (id: string, resolve) => { + const handler = event => { if (event.detail.id === id) { - if(event.detail.resource) { + if (event.detail.resource) { resolve(event.detail.resource); } else { resolve(event.detail.fetchedResource); @@ -595,18 +697,18 @@ if (window.sibStore) { store = window.sibStore; } else { const sibAuth = document.querySelector('sib-auth'); - const storeOptions: StoreOptions = {} + const storeOptions: StoreOptions = {}; if (sibAuth) { const sibAuthDefined = customElements.whenDefined(sibAuth.localName); - storeOptions.session = sibAuthDefined.then(() => (sibAuth as any).session) - storeOptions.fetchMethod = sibAuthDefined.then(() => (sibAuth as any).getFetch()) + storeOptions.session = sibAuthDefined.then(() => (sibAuth as any).session); + storeOptions.fetchMethod = sibAuthDefined.then(() => + (sibAuth as any).getFetch(), + ); } store = new Store(storeOptions); window.sibStore = store; } -export { - store -}; +export { store }; diff --git a/src/locales/en.json b/src/locales/en.json index 723755c3fe341dba83739c491b8fe022d9c5baf2..c75d4106575d6c6038133fa0324bf7e349bcd3b1 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,11 +1,11 @@ { - "autocompletion.placeholder": "Select a value", - "autocompletion.searchPlaceholder": "Search", - "autocompletion.searchText": "No result", - "solid-delete.button": "Delete", - "solid-form.submit-button": "Submit", - "solid-form.validation-error": "A validation error occurred.", - "validation.message": "Please, confirm your choice", - "validation.submit-text": "Yes", - "validation.cancel-text": "Cancel" -} \ No newline at end of file + "autocompletion.placeholder": "Select a value", + "autocompletion.searchPlaceholder": "Search", + "autocompletion.searchText": "No result", + "solid-delete.button": "Delete", + "solid-form.submit-button": "Submit", + "solid-form.validation-error": "A validation error occurred.", + "validation.message": "Please, confirm your choice", + "validation.submit-text": "Yes", + "validation.cancel-text": "Cancel" +} diff --git a/src/locales/fr.json b/src/locales/fr.json index d1c9c5fda9aedce0eb20c3894cdcbe8f418d83c0..e2d66bf1c70628b3e7c3d58a82779fc50aa2505b 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1,11 +1,11 @@ { - "autocompletion.placeholder": "Sélectionner une valeur", - "autocompletion.searchPlaceholder": "Rechercher", - "autocompletion.searchText": "Aucun résultat", - "solid-delete.button": "Supprimer", - "solid-form.submit-button": "Envoyer", - "solid-form.validation-error": "Erreur de validation.", - "validation.message": "Merci de confirmer votre choix", - "validation.submit-text": "Oui", - "validation.cancel-text": "Annuler" -} \ No newline at end of file + "autocompletion.placeholder": "Sélectionner une valeur", + "autocompletion.searchPlaceholder": "Rechercher", + "autocompletion.searchText": "Aucun résultat", + "solid-delete.button": "Supprimer", + "solid-form.submit-button": "Envoyer", + "solid-form.validation-error": "Erreur de validation.", + "validation.message": "Merci de confirmer votre choix", + "validation.submit-text": "Oui", + "validation.cancel-text": "Annuler" +} diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a3f1cdb81336d32e7ab7094aa391b3c324ab45b --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,203 @@ +import log from 'loglevel'; + +const colors = { + reset: '\x1b[0m', + trace: '\x1b[38;2;169;169;169m', // Gray + debug: '\x1b[38;2;0;0;255m', // Blue + info: '\x1b[38;2;0;128;0m', // Green + warn: '\x1b[38;2;218;165;32m', // Yellow + error: '\x1b[38;2;255;0;0m', // Red +}; + +function formatMessage(level: log.LogLevelNames, messages: unknown[]) { + const timestamp = new Date().toISOString(); + const color = colors[level] || colors.reset; + + // Convert each message to a string, including objects + const formattedMessages = messages + .map(msg => { + if (typeof msg === 'object') { + try { + return JSON.stringify(msg, null, 2); + } catch { + return String(msg); + } + } + return String(msg); + }) + .join(' '); + + return `${color}[${timestamp}] ${formattedMessages}${colors.reset}`; +} + +const originalFactory = log.methodFactory; + +log.methodFactory = (methodName, logLevel, loggerName) => { + const rawMethod = originalFactory(methodName, logLevel, loggerName); + return (...messages) => { + rawMethod(formatMessage(methodName, messages)); + }; +}; + +// Manage the DEBUG environment variable +if (import.meta.env?.VITE_DEBUG === 'True') { + log.setLevel('debug'); +} else { + log.setLevel('warn'); +} + +// Async HOF to log render times and time execution +export function trackRenderAsync(fn: Function, context?: string) { + return async function (...args: unknown[]) { + let componentName = context + ? context + : this.name + ? this.name + : this.constructor.name; + if (this.element.id) { + componentName += ` (id: ${this.element.id})`; + } else if (this.dataSrc) { + componentName += ` (data-src: ${this.dataSrc})`; + } else if (this.resourceId) { + componentName += ` (resourceId: ${this.resourceId})`; + } + + const startTime = performance.now(); + const result = await fn.apply(this, args); + const endTime = performance.now(); + const renderTime = endTime - startTime; + + if (this.profiler) { + this.profiler.updateStats(componentName, renderTime); + this.profiler.printStats(); + } else { + log.debug( + `Component ${componentName} rendered in ${renderTime.toFixed(2)} ms`, + ); + } + + return result; + }; +} + +// HOF to log render times and time execution +export function trackRender(fn: Function, context?: string) { + return function (...args: unknown[]) { + let componentName = context + ? context + : this.name + ? this.name + : this.constructor.name; + + if (this.element.id) { + componentName += ` (id: ${this.element.id})`; + } else if (this.dataSrc) { + componentName += ` (data-src: ${this.dataSrc})`; + } else if (this.resourceId) { + componentName += ` (resourceId: ${this.resourceId})`; + } + + const startTime = performance.now(); + const result = fn.apply(this, args); + const endTime = performance.now(); + const renderTime = endTime - startTime; + + if (this.profiler) { + this.profiler.updateStats(componentName, renderTime); + this.profiler.printStats(); + } else { + log.debug( + `Component ${componentName} rendered in ${renderTime.toFixed(2)} ms`, + ); + } + + return result; + }; +} + +export type PerformanceMetrics = { + renderCount: number; // Combien de fois le composant a été rendu + totalExecutionTime: number; // Temps total d'exécution (en ms) + lastExecutionTime: number; // Temps d'exécution lors du dernier rendu + averageExecutionTime: number; + minExecutionTime: number; + maxExecutionTime: number; +}; + +export class Profiler { + private stats: { [componentName: string]: PerformanceMetrics } = {}; + + constructor() { + this.stats = {}; + } + + private getOrCreateStats(componentName: string): PerformanceMetrics { + if (!this.stats[componentName]) { + this.stats[componentName] = { + renderCount: 0, + totalExecutionTime: 0, + lastExecutionTime: 0, + averageExecutionTime: 0, + minExecutionTime: Number.POSITIVE_INFINITY, + maxExecutionTime: 0, + }; + } + return this.stats[componentName]; + } + + public getStats(componentName: string): PerformanceMetrics | undefined { + return this.stats[componentName]; + } + + public updateStats(componentName: string, renderTime: number): void { + const stats = this.getOrCreateStats(componentName); + stats.renderCount++; + stats.lastExecutionTime = renderTime; + stats.totalExecutionTime += renderTime; + stats.averageExecutionTime = stats.totalExecutionTime / stats.renderCount; + stats.minExecutionTime = Math.min(stats.minExecutionTime, renderTime); + stats.maxExecutionTime = Math.max(stats.maxExecutionTime, renderTime); + } + + private formatTime(time: number): string { + if (time >= 1000) { + return `${(time / 1000).toFixed(2)} seconds`; + } + return `${time.toFixed(2)} ms`; + } + + private formatComponentStats( + componentName: string, + stats: PerformanceMetrics, + ): string { + return ( + `\nComponent: ${componentName}\n` + + ` Render Count: ${stats.renderCount}\n` + + ` Total Execution Time: ${this.formatTime(stats.totalExecutionTime)}\n` + + ` Last Execution Time: ${this.formatTime(stats.lastExecutionTime)}\n` + + ` Average Execution Time: ${this.formatTime(stats.averageExecutionTime)}\n` + + ` Min Execution Time: ${this.formatTime(stats.minExecutionTime)}\n` + + ` Max Execution Time: ${this.formatTime(stats.maxExecutionTime)}\n` + ); + } + + public printStats(componentName: string): void { + let output = 'Component Performance Stats:\n'; + + if (componentName) { + const stats = this.stats[componentName]; + if (!stats) { + output += `Component ${componentName} not found.\n`; + } else { + output += this.formatComponentStats(componentName, stats); + } + } else { + for (const [name, stats] of Object.entries(this.stats)) { + output += this.formatComponentStats(name, stats); + } + } + log.debug(output); + } +} + +export { log as logger }; diff --git a/src/mixins/attributeBinderMixin.ts b/src/mixins/attributeBinderMixin.ts index 21c0b3c7f8fdcad527193027e6e62a1676f89932..e7db4d1d354ad6c9606d78eecc0d3f9fadd22448 100644 --- a/src/mixins/attributeBinderMixin.ts +++ b/src/mixins/attributeBinderMixin.ts @@ -1,11 +1,11 @@ -import { base_context, store } from '../libs/store/store'; -import type { Resource } from './interfaces'; +import { base_context, store } from '../libs/store/store.ts'; +import type { Resource } from './interfaces.ts'; const AttributeBinderMixin = { name: 'attribute-binder-mixin', use: [], initialState: { - bindedAttributes: null + bindedAttributes: null, }, created() { this.bindedAttributes = {}; @@ -14,7 +14,7 @@ const AttributeBinderMixin = { * Reset attributes values */ resetAttributesData() { - for (let attr of Object.keys(this.bindedAttributes)) { + for (const attr of Object.keys(this.bindedAttributes)) { this.element.setAttribute(attr, this.bindedAttributes[attr]); } }, @@ -25,25 +25,24 @@ const AttributeBinderMixin = { async replaceAttributesData(reset = true) { if (reset) this.resetAttributesData(); - const oldAttributes: any = Array.from(this.element.attributes) // transform NamedNodeMap in object - .reduce((obj: any, attr: any) => { - - // Keep only attributes starting with `store://...` - if (!attr.value.match(/^store:\/\/(resource|container|user)/)) return { ...obj } + const oldAttributes: Record<string, string> = {}; + for (const attr of (this.element as Element).attributes) { + if (!attr.value.match(/^store:\/\/(resource|container|user)/)) continue; - // Save attr for reset later - if (!this.bindedAttributes[attr.name]) this.bindedAttributes[attr.name] = attr.value; + if (!this.bindedAttributes[attr.name]) + this.bindedAttributes[attr.name] = attr.value; - return { - ...obj, - [attr.name]: attr.value, // add "key: value" - }; - }, {}); + oldAttributes[attr.name] = attr.value; + } - const newAttributes = await this.transformAttributes({ ...oldAttributes }, this.resource); // generate new attributes + const newAttributes = await this.transformAttributes( + { ...oldAttributes }, + this.resource, + ); // generate new attributes - for (let attr of Object.keys(newAttributes)) { // set attributes on element - if (oldAttributes[attr] == newAttributes[attr]) continue; // only if it changed + for (const attr of Object.keys(newAttributes)) { + // set attributes on element + if (oldAttributes[attr] === newAttributes[attr]) continue; // only if it changed this.element.setAttribute(attr, newAttributes[attr]); } }, @@ -55,29 +54,38 @@ const AttributeBinderMixin = { * @returns - object representing attributes of an element with resolved values */ async transformAttributes(attributes: object, resource: Resource) { - const isContainer = resource && resource.isContainer?.(); + const isContainer = resource?.isContainer?.(); - for (let attr of Object.keys(attributes)) { + for (const attr of Object.keys(attributes)) { const value = attributes[attr]; // Avoid error if value is a number if (typeof value === 'string') { // Replace attribute value - if (!isContainer && resource && value.startsWith('store://resource')) { // RESOURCE - let path = value.replace('store://resource.', ''); + if (!isContainer && resource && value.startsWith('store://resource')) { + // RESOURCE + const path = value.replace('store://resource.', ''); attributes[attr] = resource ? await resource[path] : ''; - } else if (isContainer && resource && value.startsWith('store://container')) { // CONTAINER - let path = value.replace('store://container.', ''); + } else if ( + isContainer && + resource && + value.startsWith('store://container') + ) { + // CONTAINER + const path = value.replace('store://container.', ''); attributes[attr] = resource ? await resource[path] : ''; - } else if (value.startsWith('store://user')) { // USER + } else if (value.startsWith('store://user')) { + // USER // retry until sibAuth is defined const userId = await this.retry(this.getUser.bind(this)); // TODO: Using this.context makes no sense here. Use same-attribute-context="context-id" instead? - const user = userId && userId['@id'] ? await store.getData(userId['@id'], this.context || base_context) : null; + const user = userId?.['@id'] + ? await store.getData(userId['@id'], this.context || base_context) + : null; if (!user) { attributes[attr] = ''; continue; } - let path = value.replace('store://user.', ''); + const path = value.replace('store://user.', ''); attributes[attr] = user ? await user[path] : ''; } } @@ -91,7 +99,7 @@ const AttributeBinderMixin = { */ async getUser() { const sibAuth: any = document.querySelector('sib-auth'); - return sibAuth.getUser(); + return await sibAuth.getUser(); }, /** @@ -104,17 +112,17 @@ const AttributeBinderMixin = { async retry(fn: Function, ms = 200, maxRetries = 5) { return new Promise((resolve, reject) => { let retries = 0; - fn().then(resolve).catch(() => { - setTimeout(() => { - ++retries; - if (retries == maxRetries) return reject(); - this.retry(fn, ms).then(resolve); - }, ms); - }); + fn() + .then(resolve) + .catch(() => { + setTimeout(() => { + ++retries; + if (retries >= maxRetries) return reject(); + this.retry(fn, ms).then(resolve); + }, ms); + }); }); - } -} + }, +}; -export { - AttributeBinderMixin -} \ No newline at end of file +export { AttributeBinderMixin }; diff --git a/src/mixins/contextMixin.ts b/src/mixins/contextMixin.ts index 310408a4068425bc7dc65c75308c45e0aef65495..0e071f425999077c81118bb705c9f51a957f5583 100644 --- a/src/mixins/contextMixin.ts +++ b/src/mixins/contextMixin.ts @@ -1,4 +1,4 @@ -import { base_context } from '../libs/store/store'; +import { base_context } from '../libs/store/store.ts'; const ContextMixin = { name: 'store-mixin', @@ -6,22 +6,22 @@ const ContextMixin = { attributes: { extraContext: { type: String, - default: null + default: null, }, }, get context(): object { return { ...base_context, ...this.extra_context }; }, get extra_context(): object { - let extraContextElement = this.extraContext ? - document.getElementById(this.extraContext) : // take element extra context first - document.querySelector('[data-default-context]'); // ... or look for a default extra context + const extraContextElement = this.extraContext + ? document.getElementById(this.extraContext) + : // take element extra context first + document.querySelector('[data-default-context]'); // ... or look for a default extra context - if (extraContextElement) return JSON.parse(extraContextElement.textContent || "{}"); + if (extraContextElement) + return JSON.parse(extraContextElement.textContent || '{}'); return {}; }, }; -export { - ContextMixin -} \ No newline at end of file +export { ContextMixin }; diff --git a/src/mixins/counterMixin.ts b/src/mixins/counterMixin.ts index ab6cc4829342ec5c4d6c72badd6e757dfc9966f3..994ea0e973467a0e86326bad656bdb40ea15e115 100644 --- a/src/mixins/counterMixin.ts +++ b/src/mixins/counterMixin.ts @@ -1,6 +1,7 @@ -import { html } from 'lit-html'; -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; -import { evalTemplateString } from '../libs/helpers'; +import { html } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { evalTemplateString } from '../libs/helpers.ts'; const CounterMixin = { name: 'counter-mixin', @@ -8,7 +9,7 @@ const CounterMixin = { attributes: { counterTemplate: { type: String, - default: null + default: null, }, }, initialState: { @@ -16,19 +17,29 @@ const CounterMixin = { parentCounterDiv: null, }, attached() { - this.listPostProcessors.push(this.countResources.bind(this)); + this.listPostProcessors.attach( + this.countResources.bind(this), + 'CounterMixin:countResources', + ); }, - async countResources(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string) { + async countResources( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ) { if (this.counterTemplate) { this.initParentCounterDiv(div); - this.renderCallbacks.push({ // add counter template to render callback + this.renderCallbacks.push({ + // add counter template to render callback template: await this.renderCounter(resources.length), - parent: this.parentCounterDiv + parent: this.parentCounterDiv, }); } const nextProcessor = listPostProcessors.shift(); - if (nextProcessor) await nextProcessor(resources, listPostProcessors, div, context); + if (nextProcessor) + await nextProcessor(resources, listPostProcessors, div, context); }, /** * Create the parent div of the counter in the component. @@ -50,9 +61,7 @@ const CounterMixin = { throw e; } return html`${unsafeHTML(htmlCounter)}`; - } -} + }, +}; -export { - CounterMixin -} \ No newline at end of file +export { CounterMixin }; diff --git a/src/mixins/federationMixin.ts b/src/mixins/federationMixin.ts index 0a06bcdac51f3560baf04c4efffcb8a041a88175..b4afb9ee18d0960bae3c6e31dcab539283bdffaf 100644 --- a/src/mixins/federationMixin.ts +++ b/src/mixins/federationMixin.ts @@ -1,22 +1,33 @@ -import { store } from '../libs/store/store'; -import type { Resource } from './interfaces'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { store } from '../libs/store/store.ts'; +import type { Resource } from './interfaces.ts'; const FederationMixin = { name: 'federation-mixin', use: [], initialState: { - containerFetched: null + containerFetched: null, }, attached(): void { - this.listPostProcessors.push(this.fetchSources.bind(this)); + this.listPostProcessors.attach( + this.fetchSources.bind(this), + 'FederationMixin:fetchSources', + ); }, - async fetchSources(resources: Resource[], listPostProcessors: Function[], div: HTMLElement, context: string) { + async fetchSources( + resources: Resource[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ) { this.containerFetched = []; let newResources: Resource[] = await this.getResources(resources); newResources = [...new Set(newResources)]; // remove possible duplicates + this.resources = [...newResources]; // Create a new array to avoid unintended reference issues const nextProcessor = listPostProcessors.shift(); - if(nextProcessor) await nextProcessor(newResources, listPostProcessors, div, context); + if (nextProcessor) + await nextProcessor(newResources, listPostProcessors, div, context); }, async getResources(resources: Resource[]): Promise<Resource[]> { if (!resources && this.resources) resources = this.resources; @@ -25,18 +36,21 @@ const FederationMixin = { const getChildResources = async (res: Resource) => { if (!res) return; - if (res.isContainer?.()) { // if this is a container + if (res.isContainer?.()) { + // if this is a container const containerId = res['@id']; - if (!this.containerFetched.includes(containerId)) { // prevent from including twice the same source + if (!this.containerFetched.includes(containerId)) { + // prevent from including twice the same source this.containerFetched.push(containerId); const resourcesFetched = await this.fetchSource(containerId); // fetch the resources of this container - if (resourcesFetched) newResources.push(...(await this.getResources(resourcesFetched))); // Add content of source to array... + if (resourcesFetched) + newResources.push(...(await this.getResources(resourcesFetched))); // Add content of source to array... } } else { newResources.push(res); // Or resource directly if not a container } - } + }; // Special case for list support, if there is only one item it is serialized as an object, not an array if (!Array.isArray(resources)) resources = [resources]; @@ -46,14 +60,13 @@ const FederationMixin = { async fetchSource(containerId: string): Promise<Resource[] | null> { const cachedContainer = store.get(containerId); // find container in cache - if (!cachedContainer || cachedContainer['ldp:contains'] === null) { // if container not fetched + if (!cachedContainer || cachedContainer['ldp:contains'] === null) { + // if container not fetched store.clearCache(containerId); // empty cache } const container = await store.getData(containerId, this.context); // and fetch it return container ? container['ldp:contains'] : null; }, -} +}; -export { - FederationMixin -} \ No newline at end of file +export { FederationMixin }; diff --git a/src/mixins/filterMixin.ts b/src/mixins/filterMixin.ts index 9a8c1cbabc71205a25697c520e271c1a035f7b80..e4b4d4ebe5191d32a0172b4cdab387e7dadedb9f 100644 --- a/src/mixins/filterMixin.ts +++ b/src/mixins/filterMixin.ts @@ -1,6 +1,7 @@ -import type { SearchQuery } from '../libs/interfaces'; -import { searchInResources } from '../libs/filter'; -import type { ServerSearchOptions } from '../libs/store/server-search'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { searchInResources } from '../libs/filter.ts'; +import type { SearchQuery } from '../libs/interfaces.ts'; +import type { ServerSearchOptions } from '../libs/store/server-search.ts'; const FilterMixin = { name: 'filter-mixin', @@ -11,23 +12,27 @@ const FilterMixin = { attributes: { searchFields: { type: String, - default: null + default: null, }, filteredBy: { type: String, default: null, callback(newValue: string) { // if we change search form, re-populate - if (newValue && this.searchForm && newValue !== this.searchForm.getAttribute('id')) { + if ( + newValue && + this.searchForm && + newValue !== this.searchForm.getAttribute('id') + ) { this.searchForm.component.detach(this); this.searchForm = null; this.populate(); } - } + }, }, filteredOn: { type: String, // 'server' | 'client' - default: 'client' + default: 'client', }, }, created() { @@ -35,17 +40,22 @@ const FilterMixin = { this.element.addEventListener('populate', () => { if (!window.document.contains(this.element)) return; this.searchForm?.component.updateAutoRanges(); - }) + }); }, attached(): void { const filteredBy = this.filteredBy; if (this.isFilteredOnServer() && filteredBy) { - this.searchForm = document.getElementById(filteredBy) + this.searchForm = document.getElementById(filteredBy); if (!this.searchForm) throw `#${filteredBy} is not in DOM`; // this.searchForm.component.attach(this); // is it necessary? - this.searchForm.addEventListener('formChange', () => this.onServerSearchChange()); + this.searchForm.addEventListener('formChange', () => + this.onServerSearchChange(), + ); } else { - this.listPostProcessors.push(this.filterCallback.bind(this)); + this.listPostProcessors.attach( + this.filterCallback.bind(this), + 'FilterMixin:filterCallback', + ); } }, get filters(): SearchQuery { @@ -71,15 +81,21 @@ const FilterMixin = { const fields = Object.keys(filters); const value = (Object.values(filters) as { value: string }[]) .map(({ value }) => value) - .filter((value) => !!value) - .join(' ').trim(); + .filter(value => !!value) + .join(' ') + .trim(); if (fields.length > 0 && value) { return { fields, value }; } } return; }, - async filterCallback(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string): Promise<void> { + async filterCallback( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ): Promise<void> { if (this.filteredBy || this.searchFields) { if (!this.searchCount.has(context)) this.searchCount.set(context, 1); if (!this.searchForm) await this.createFilter(context); @@ -87,13 +103,19 @@ const FilterMixin = { resources, this.filters, this.fields, - this.searchForm + this.searchForm, ); - this.resources = resources = resources.filter((_v, index) => filteredResources[index]); + resources = resources.filter((_v, index) => filteredResources[index]); + this.resources = [...resources]; } - const nextProcessor = listPostProcessors.shift(); - if (nextProcessor) await nextProcessor(resources, listPostProcessors, div, context + (this.searchCount.get(context) || '')); + if (nextProcessor) + await nextProcessor( + resources, + listPostProcessors, + div, + context + (this.searchCount.get(context) || ''), + ); }, async filterList(context: string): Promise<void> { this.searchCount.set(context, this.searchCount.get(context) + 1); @@ -109,8 +131,10 @@ const FilterMixin = { const nextArrayOfObjects = await obj[field]; if (!nextArrayOfObjects) continue; - if (typeof nextArrayOfObjects !== "object") { - console.warn(`The format value of ${field} is not suitable with auto-range-[field] attribute`); + if (typeof nextArrayOfObjects !== 'object') { + console.warn( + `The format value of ${field} is not suitable with auto-range-[field] attribute`, + ); continue; } @@ -130,10 +154,10 @@ const FilterMixin = { async createFilter(context: string): Promise<void> { const filteredBy = this.filteredBy; if (filteredBy != null) { - this.searchForm = document.getElementById(filteredBy) + this.searchForm = document.getElementById(filteredBy); if (!this.searchForm) throw `#${filteredBy} is not in DOM`; } else { - this.searchForm = document.createElement(`solid-form-search`); + this.searchForm = document.createElement('solid-form-search'); } this.searchForm.component.attach(this); this.searchForm.addEventListener('formChange', () => { @@ -145,21 +169,19 @@ const FilterMixin = { //pass attributes to search form const searchAttributes = Array.from((this.element as Element).attributes) - .filter(attr => attr['name'].startsWith('search-')) + .filter(attr => attr.name.startsWith('search-')) .map(attr => ({ - name: attr['name'].replace('search-', ''), - value: attr['value'], + name: attr.name.replace('search-', ''), + value: attr.value, })); - searchAttributes.forEach(({ name, value }) => { + for (const { name, value } of searchAttributes) { this.searchForm.setAttribute(name, value); - }); + } this.element.insertBefore(this.searchForm, this.element.firstChild); await this.searchForm.component.populate(); }, -} +}; -export { - FilterMixin -} \ No newline at end of file +export { FilterMixin }; diff --git a/src/mixins/grouperMixin.ts b/src/mixins/grouperMixin.ts index ee8442281a0b8375a05e616579b87b600d5d57c3..85264d1dba7114750ad4583df074413bf61ec619 100644 --- a/src/mixins/grouperMixin.ts +++ b/src/mixins/grouperMixin.ts @@ -1,4 +1,5 @@ -import { generalComparator } from "../libs/helpers"; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { generalComparator } from '../libs/helpers.ts'; const GrouperMixin = { name: 'grouper-mixin', @@ -10,60 +11,68 @@ const GrouperMixin = { }, groupWidget: { type: String, - default: 'solid-group-default' + default: 'solid-group-default', }, groupClass: { type: String, - default: '' + default: '', }, orderGroupAsc: { type: Boolean, - default: null + default: null, }, orderGroupDesc: { type: Boolean, - default: null + default: null, }, }, attached() { - this.listPostProcessors.push(this.groupResources.bind(this)); + this.listPostProcessors.attach( + this.groupResources.bind(this), + 'GrouperMixin:groupResources', + ); }, - async groupResources(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string) { + async groupResources( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ) { const nextProcessor = listPostProcessors.shift(); if (this.groupBy) { - let groups = {}; - for (let resource of resources) { + const groups = {}; + for (const resource of resources) { const valueGroup = await resource[this.groupBy]; if (valueGroup == null) continue; if (!groups[valueGroup]) groups[valueGroup] = { resources: [] }; // if no group yet, we create one... - groups[valueGroup].resources.push(resource) // ...and push corresponding resource into it + groups[valueGroup].resources.push(resource); // ...and push corresponding resource into it } let sortedKeys = Object.keys(groups); if (this.orderGroupAsc !== null || this.orderGroupDesc !== null) { - const order = this.orderGroupDesc !== null ? 'desc' : 'asc' + const order = this.orderGroupDesc !== null ? 'desc' : 'asc'; sortedKeys = Object.keys(groups).sort((a, b) => { - return generalComparator(a, b, order); + return generalComparator(a, b, order); }); } // For each group, get group widget and call next processors - const parents = sortedKeys.map(g => ({ group: g, parent: this.renderGroup(g, div) })); - for (let { group, parent } of parents) { - if (nextProcessor) await nextProcessor( - groups[group].resources, // give only resources from group - [...listPostProcessors], // copy post processors - parent, // parent is group widget - context + "_" + group - ); + const parents = sortedKeys.map(g => ({ + group: g, + parent: this.renderGroup(g, div), + })); + for (const { group, parent } of parents) { + if (nextProcessor) + await nextProcessor( + groups[group].resources, // give only resources from group + listPostProcessors.deepCopy(), // copy post processors + parent, // parent is group widget + `${context}_${group}`, + ); } } else { - if (nextProcessor) await nextProcessor( - resources, - listPostProcessors, - div, - context - ); + if (nextProcessor) + await nextProcessor(resources, listPostProcessors, div, context); } }, /** @@ -71,7 +80,9 @@ const GrouperMixin = { * @param groupName */ renderGroup(groupName: string, div: HTMLElement) { - let groupElt = this.element.querySelector(`${this.groupWidget}[value="${groupName}"]`); + let groupElt = this.element.querySelector( + `${this.groupWidget}[value="${groupName}"]`, + ); if (!groupElt) { groupElt = document.createElement(this.groupWidget); groupElt.setAttribute('value', groupName); @@ -80,9 +91,7 @@ const GrouperMixin = { div.appendChild(groupElt); // and append it to the parent div } return groupElt.querySelector('[data-content]') || groupElt; // return the node where to insert content - } -} + }, +}; -export { - GrouperMixin -} \ No newline at end of file +export { GrouperMixin }; diff --git a/src/mixins/highlighterMixin.ts b/src/mixins/highlighterMixin.ts index fce1050e237bb60262465025f85b3708bc2e2fd2..a01d321ca22460a10db8d22ff7b0c6e13c104b69 100644 --- a/src/mixins/highlighterMixin.ts +++ b/src/mixins/highlighterMixin.ts @@ -1,37 +1,48 @@ +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; + const HighlighterMixin = { name: 'highlighter-mixin', use: [], attached(): void { - this.listPostProcessors.push(this.hightlightCallback.bind(this)); + this.listPostProcessors.attach( + this.hightlightCallback.bind(this), + 'HighlighterMixin:hightlightCallback', + ); }, - async hightlightCallback(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string): Promise<void> { - for (let attr of this.element.attributes) { + async hightlightCallback( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ): Promise<void> { + for (const attr of this.element.attributes) { if (attr.name.startsWith('highlight-')) { const field = attr.name.split('highlight-')[1]; - resources = await Promise.all(resources.map(async (resource) => ({ - sortingKey: await resource[field], // fetch sorting value - proxy: resource // and keep proxy - }))); - resources = this.sortHighlighted(resources, "sortingKey", attr.value); // highlight element + resources = await Promise.all( + resources.map(async resource => ({ + sortingKey: await resource[field], // fetch sorting value + proxy: resource, // and keep proxy + })), + ); + resources = this.sortHighlighted(resources, 'sortingKey', attr.value); // highlight element resources = resources.map(resource => (<any>resource).proxy); // and re-transform in arra of resources } } - + this.resources = [...resources]; const nextProcessor = listPostProcessors.shift(); - if (nextProcessor) await nextProcessor(resources, listPostProcessors, div, context); + if (nextProcessor) + await nextProcessor(resources, listPostProcessors, div, context); }, sortHighlighted(resources, field, value) { - for (let [index, res] of resources.entries()) { - if (res[field] && res[field] == value) { + for (const [index, res] of resources.entries()) { + if (res[field] && res[field] === value) { // put the current element at the beginning of the array resources.splice(0, 0, resources.splice(index, 1)[0]); // TODO : test with sort } } - return resources - } -} + return resources; + }, +}; -export { - HighlighterMixin -} \ No newline at end of file +export { HighlighterMixin }; diff --git a/src/mixins/interfaces.ts b/src/mixins/interfaces.ts index 1ed067a48ab7a47db3ec12924af8eff1a4b11b2b..0fca9342b6e0d2ddc18bc667fdf1d0efa441dfba 100644 --- a/src/mixins/interfaces.ts +++ b/src/mixins/interfaces.ts @@ -1,20 +1,20 @@ export enum WidgetType { - CUSTOM = "custom", - USER = "user", - NATIVE = "native", + CUSTOM = 'custom', + USER = 'user', + NATIVE = 'native', } export interface WidgetInterface { - tagName: String - type: WidgetType + tagName: string; + type: WidgetType; } export interface Resource { - '@id': string - clientContext: object - isContainer: Function - isArray: Function - isFullResource: Function - properties: string[], - serverPagination: object -} \ No newline at end of file + '@id': string; + clientContext: object; + isContainer: Function; + isArray: Function; + isFullResource: Function; + properties: string[]; + serverPagination: object; +} diff --git a/src/mixins/listMixin.ts b/src/mixins/listMixin.ts index 2103a566924d89023819d6dd2d7e2d43837b7bbd..77a309984626990d82a85385cf17fbd8c90ca17d 100644 --- a/src/mixins/listMixin.ts +++ b/src/mixins/listMixin.ts @@ -1,6 +1,7 @@ -import { html, render } from 'lit-html'; -import { preHTML } from '../libs/lit-helpers'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import { preHTML } from '../libs/lit-helpers.ts'; const ListMixin = { name: 'list-mixin', @@ -17,77 +18,95 @@ const ListMixin = { }, initialState: { // Processors functions to execute on the list before rendering - listPostProcessors: [], + listPostProcessors: new PostProcessorRegistry(), // Rendering to execute after all the processors have been executed renderCallbacks: [], }, created() { - this.listPostProcessors = []; + this.listPostProcessors = new PostProcessorRegistry(); this.renderCallbacks = []; }, appendSingleElt(parent: HTMLElement): void { this.appendChildElt(this.resource['@id'], parent); }, setElementAttribute(attr: 'resource' | 'container') { - const containerAttribute = "solid-container"; - const resourceAttribute = "solid-resource"; - if (attr === "resource") { + const containerAttribute = 'solid-container'; + const resourceAttribute = 'solid-resource'; + if (attr === 'resource') { this.element.removeAttribute(containerAttribute); - this.element.setAttribute(resourceAttribute, ""); + this.element.setAttribute(resourceAttribute, ''); } else { this.element.removeAttribute(resourceAttribute); - this.element.setAttribute(containerAttribute, "") + this.element.setAttribute(containerAttribute, ''); } }, async populate(): Promise<void> { + const listPostProcessorsCopy = this.listPostProcessors.deepCopy(); const div = this.div; if (!this.resource) return; // Not a container but a single resource - if (!this.resource.isContainer?.() && !this.arrayField && !this.predicateName) { - this.setElementAttribute("resource"); + if ( + !this.resource.isContainer?.() && + !this.arrayField && + !this.predicateName + ) { + this.setElementAttribute('resource'); this.appendSingleElt(div); return; } if (this.resource.isContainer?.()) { - this.setElementAttribute("container"); - const listPostProcessors = [...this.listPostProcessors]; + this.setElementAttribute('container'); this.renderCallbacks = []; - listPostProcessors.push(this.renderDOM.bind(this)); - listPostProcessors.push(this.handleEmptyWidget.bind(this)); + listPostProcessorsCopy.attach( + this.renderDOM.bind(this), + 'ListMixin:renderDOM', + ); + listPostProcessorsCopy.attach( + this.handleEmptyWidget.bind(this), + 'ListMixin:handleEmptyWidget', + ); // Execute the first post-processor of the list - const nextProcessor = listPostProcessors.shift(); + const nextProcessor = listPostProcessorsCopy.shift(); + await nextProcessor( this.resource['ldp:contains'], - listPostProcessors, + listPostProcessorsCopy, div, this.dataSrc, ); - } else if (this.arrayField && this.predicateName && this.resource[this.predicateName]) { - this.setElementAttribute("container"); - const listPostProcessors = [...this.listPostProcessors]; + } else if ( + this.arrayField && + this.predicateName && + this.resource[this.predicateName] + ) { + this.setElementAttribute('container'); this.renderCallbacks = []; - listPostProcessors.push(this.renderDOM.bind(this)); - listPostProcessors.push(this.handleEmptyWidget.bind(this)); + listPostProcessorsCopy.attach( + this.renderDOM.bind(this), + 'ListMixin:renderDOM', + ); + listPostProcessorsCopy.attach( + this.handleEmptyWidget.bind(this), + 'ListMixin:handleEmptyWidget', + ); // Execute the first post-processor of the list - const nextProcessor = listPostProcessors.shift(); + const nextProcessor = listPostProcessorsCopy.shift(); await nextProcessor( await this.resource[this.predicateName], - listPostProcessors, + listPostProcessorsCopy, div, this.dataSrc, ); - } // Execute the render callbacks for (const renderCallback of this.renderCallbacks) { // Render the template in the given parent element render(renderCallback.template, renderCallback.parent); } - }, /** @@ -99,24 +118,19 @@ const ListMixin = { */ async renderDOM( resources: object[], - listPostProcessors: Function[], + listPostProcessors: PostProcessorRegistry, div: HTMLElement, context: string, ) { // Create child components - for (let resource of resources) { + for (const resource of resources) { if (!resource) continue; this.appendChildElt(resource['@id'], div); } const nextProcessor = listPostProcessors.shift(); if (nextProcessor) - await nextProcessor( - resources, - listPostProcessors, - div, - context - ); + await nextProcessor(resources, listPostProcessors, div, context); }, /** @@ -128,30 +142,26 @@ const ListMixin = { */ async handleEmptyWidget( resources: object[], - listPostProcessors: Function[], + listPostProcessors: PostProcessorRegistry, div: HTMLElement, context: string, ) { if (this.emptyWidget) { - const emptyWidgetTemplate = preHTML` - <${this.emptyWidget} value=${ifDefined(this.emptyValue)}></${this.emptyWidget}> - ` + const emptyWidgetTemplate = preHTML`<${this.emptyWidget} value=${ifDefined(this.emptyValue)}></${this.emptyWidget}>`; if (!this.emptyWrapper) { - this.emptyWrapper = document.createElement('span') - this.element.appendChild(this.emptyWrapper) + this.emptyWrapper = document.createElement('span'); + this.element.appendChild(this.emptyWrapper); } - - render(resources.length > 0 ? html`` : emptyWidgetTemplate, this.emptyWrapper); + + render( + resources.length > 0 ? html`` : emptyWidgetTemplate, + this.emptyWrapper, + ); } const nextProcessor = listPostProcessors.shift(); if (nextProcessor) - await nextProcessor( - resources, - listPostProcessors, - div, - context - ); + await nextProcessor(resources, listPostProcessors, div, context); }, }; diff --git a/src/mixins/nextMixin.ts b/src/mixins/nextMixin.ts index d3663f734c97a664289bdab8753bc00fd1970802..eab388cefae210b8f86cba8b4419f7b8c186acef 100644 --- a/src/mixins/nextMixin.ts +++ b/src/mixins/nextMixin.ts @@ -1,4 +1,4 @@ -import type { Resource } from "./interfaces.js"; +import type { Resource } from './interfaces.js'; const NextMixin = { name: 'next-mixin', @@ -6,7 +6,7 @@ const NextMixin = { attributes: { next: { type: String, - default:'' + default: '', }, }, @@ -20,9 +20,7 @@ const NextMixin = { }), ); } - } -} + }, +}; -export { - NextMixin -} \ No newline at end of file +export { NextMixin }; diff --git a/src/mixins/paginateMixin.ts b/src/mixins/paginateMixin.ts index da421034e0e3dee6d195ca62613c14d4f48bec00..f68be13f2b6f7344d386ecef6d7200b13ebd5e6a 100644 --- a/src/mixins/paginateMixin.ts +++ b/src/mixins/paginateMixin.ts @@ -1,4 +1,5 @@ -import { html, TemplateResult } from "lit-html"; +import { type TemplateResult, html } from 'lit'; +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; const PaginateMixin = { name: 'paginate-mixin', @@ -6,12 +7,12 @@ const PaginateMixin = { attributes: { paginateBy: { type: Number, - default: 0 + default: 0, }, paginateLoop: { type: String, - default: null - } + default: null, + }, }, initialState: { currentPage: [], @@ -20,23 +21,40 @@ const PaginateMixin = { this.currentPage = []; }, attached(): void { - this.listPostProcessors.push(this.paginateCallback.bind(this)); + this.listPostProcessors.attach( + this.paginateCallback.bind(this), + 'PaginateMixin:paginateCallback', + ); }, - async paginateCallback(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string) { + async paginateCallback( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ) { if (this.paginateBy > 0) { if (!this.currentPage[context]) this.currentPage[context] = 1; const parentDiv = this.initParentPaginationDiv(div, context); this.renderCallbacks.push({ - template: this.renderPaginationNav(this.getPageCount(resources.length),context,div), - parent: parentDiv + template: this.renderPaginationNav( + this.getPageCount(resources.length), + context, + div, + ), + parent: parentDiv, }); - const firstElementIndex = (this.getCurrentPage(context) - 1) * this.paginateBy; - resources = resources.slice(firstElementIndex, firstElementIndex + this.paginateBy); + const firstElementIndex = + (this.getCurrentPage(context) - 1) * this.paginateBy; + resources = resources.slice( + firstElementIndex, + firstElementIndex + this.paginateBy, + ); } const nextProcessor = listPostProcessors.shift(); - if (nextProcessor) await nextProcessor(resources, listPostProcessors, div,context); + if (nextProcessor) + await nextProcessor(resources, listPostProcessors, div, context); }, getNavElement(div: HTMLElement) { const insertNode = div.parentNode || div; @@ -78,7 +96,11 @@ const PaginateMixin = { * @param pageCount * @param context */ - renderPaginationNav(pageCount: number, context: string, div: HTMLElement): TemplateResult { + renderPaginationNav( + pageCount: number, + context: string, + div: HTMLElement, + ): TemplateResult { this.getNavElement(div).toggleAttribute('hidden', pageCount <= 1); const currentPage = this.getCurrentPage(context); @@ -91,15 +113,13 @@ const PaginateMixin = { <button data-id="next" ?disabled=${!this.shouldLoop() && currentPage >= pageCount} - @click=${ () => this.setCurrentPage(currentPage + 1, context, pageCount)} + @click=${() => this.setCurrentPage(currentPage + 1, context, pageCount)} >→</button> <span> <span data-id="current">${currentPage}</span> / <span data-id="count">${String(pageCount)}</span> </span> `; }, -} +}; -export { - PaginateMixin -} \ No newline at end of file +export { PaginateMixin }; diff --git a/src/mixins/requiredMixin.ts b/src/mixins/requiredMixin.ts index 819da65b19ba9c3b934a87ae7300d876d8250523..6e648cfa19dd52fba6d7979967b697d4492a1d2e 100644 --- a/src/mixins/requiredMixin.ts +++ b/src/mixins/requiredMixin.ts @@ -1,35 +1,52 @@ +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; + const RequiredMixin = { name: 'required-mixin', use: [], attached(): void { - this.listPostProcessors.push(this.requiredResources.bind(this)); + this.listPostProcessors.attach( + this.requiredResources.bind(this), + 'RequiredMixin:requiredResources', + ); }, - async requiredResources(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string): Promise<void> { + async requiredResources( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ): Promise<void> { const displays: any[] = []; - const requiredFields = Array.from((this.element as Element).attributes).filter(attr => attr.name.startsWith('required-')) + const requiredFields = Array.from((this.element as Element).attributes) + .filter(attr => attr.name.startsWith('required-')) .map(attr => { - return (attr.value !== '' ? attr.value : attr['name'].replace('required-', '')); - }); + return attr.value !== '' + ? attr.value + : attr.name.replace('required-', ''); + }); - if (requiredFields.length) { - for (let resource of resources) { + if (requiredFields.length > 0) { + for (const resource of resources) { let hasProps = true; - for(let field of requiredFields) { + for (const field of requiredFields) { // Retrieve resource from store - let res = await resource[field]; - if (!res || res == null) { + const res = await resource[field]; + if (!res) { hasProps = false; - continue; + break; } } if (hasProps) displays.push(resource); } } const nextProcessor = listPostProcessors.shift(); - if (nextProcessor) await nextProcessor(requiredFields.length ? displays : resources, listPostProcessors, div, context); - } -} + if (nextProcessor) + await nextProcessor( + requiredFields.length > 0 ? displays : resources, + listPostProcessors, + div, + context, + ); + }, +}; -export { - RequiredMixin -} +export { RequiredMixin }; diff --git a/src/mixins/serverPaginationMixin.ts b/src/mixins/serverPaginationMixin.ts index 235fd4222843de2d8f3d3f1f1bfec90323a28188..67391554f01ca5e563d740e887e1f88a216b3835 100644 --- a/src/mixins/serverPaginationMixin.ts +++ b/src/mixins/serverPaginationMixin.ts @@ -1,4 +1,4 @@ -import { html, render } from "lit-html"; +import { html, render } from 'lit'; const ServerPaginationMixin = { name: 'server-pagination-mixin', @@ -6,20 +6,20 @@ const ServerPaginationMixin = { attributes: { limit: { type: Number, - default: undefined + default: undefined, }, offset: { type: Number, - default: undefined + default: undefined, }, pageCount: { type: Number, - default: 1000 + default: 1000, }, pageNumber: { type: Number, - default: 0 - } + default: 0, + }, }, initialState: { currentOffset: [], @@ -29,20 +29,20 @@ const ServerPaginationMixin = { if (this.limit) { this.setCurrentOffset(this.resourceId, 0); const parentDiv = this.initServerPaginationDiv(this.div); - + this.renderCallbacks.push({ template: this.renderServerPaginationNav(this.resourceId, parentDiv), - parent: parentDiv + parent: parentDiv, }); } }, getCurrentOffset(resourceId: string, limit: number) { - return this.currentOffset[resourceId + "#p" + limit]; + return this.currentOffset[`${resourceId}#p${limit}`]; }, async setCurrentOffset(resourceId: string, offset: number): Promise<void> { - let index = resourceId + "#p" + this.limit; + const index = `${resourceId}#p${this.limit}`; this.currentOffset[index] = this.offset = offset; this.pageNumber = Number(this.offset / this.limit); this.currentPage[resourceId] = this.pageNumber; @@ -51,7 +51,7 @@ const ServerPaginationMixin = { }, async decreaseCurrentOffset(resourceId: string): Promise<void> { - let index = resourceId + "#p" + this.limit; + const index = `${resourceId}#p${this.limit}`; this.currentOffset[index] = this.offset = this.offset - this.limit; this.currentPage[index] = this.offset / this.limit; this.pageNumber = this.offset / this.limit; @@ -61,7 +61,7 @@ const ServerPaginationMixin = { }, async increaseCurrentOffset(resourceId: string): Promise<void> { - let index = resourceId + "#p" + this.limit; + const index = `${resourceId}#p${this.limit}`; this.currentOffset[index] = this.offset = this.offset + this.limit; this.currentPage[index] = this.offset / this.limit; @@ -69,15 +69,16 @@ const ServerPaginationMixin = { await this.fetchData(this.dataSrc); }, - async updateNavButtons(resourceId: string, index: string, variance: number) { - this.element.querySelector("[data-id='prev']").disabled = this.currentOffset[index] <= 0; - // this.element.querySelector("[data-id='next']").disabled = await this.resource['ldp:contains'].length == 0; - this.element.querySelector("[data-id='current']").innerText = this.getCurrentServedPage(resourceId, variance); - + updateNavButtons(resourceId: string, index: string, variance: number) { + this.element.querySelector("[data-id='prev']").disabled = + this.currentOffset[index] <= 0; + // this.element.querySelector("[data-id='next']").disabled = await this.resource['ldp:contains'].length === 0; + this.element.querySelector("[data-id='current']").innerText = + this.getCurrentServedPage(resourceId, variance); }, getServerNavElement(div: HTMLElement) { - if(div) { + if (div) { const insertNode = div.parentNode || div; return insertNode.querySelector(`nav[data-id="nav"]`); } @@ -95,7 +96,7 @@ const ServerPaginationMixin = { * Find nav element or create it if not existing * @param div - insert nav next to this div */ - initServerPaginationDiv(div: HTMLElement) { + initServerPaginationDiv(div: HTMLElement) { let nav = this.getServerNavElement(div); if (!nav) { nav = document.createElement('nav'); @@ -112,10 +113,11 @@ const ServerPaginationMixin = { renderServerPaginationNav(resourceId: string, div: HTMLElement): void { if (this.limit) { const currentOffset = this.getCurrentOffset(resourceId, this.limit); - var currentPageNumber = this.getCurrentServedPage(resourceId, 1); + const currentPageNumber = this.getCurrentServedPage(resourceId, 1); const pageCount = Math.ceil(this.pageCount / this.limit); - render(html` + render( + html` <button data-id="prev" ?disabled=${currentOffset <= 0} @@ -127,15 +129,15 @@ const ServerPaginationMixin = { <button data-id="next" ?disabled=${currentOffset >= (pageCount - 1) * this.limit} - @click=${ () => this.increaseCurrentOffset(resourceId)} + @click=${() => this.increaseCurrentOffset(resourceId)} >→</button> <span> </span> - `, div); + `, + div, + ); } }, -} +}; -export { - ServerPaginationMixin -} \ No newline at end of file +export { ServerPaginationMixin }; diff --git a/src/mixins/sorterMixin.ts b/src/mixins/sorterMixin.ts index 0734226d27a33c5b052f57637d215cedbc516c1b..a565739ec95c874a0e593a418e72c9c555a22db1 100644 --- a/src/mixins/sorterMixin.ts +++ b/src/mixins/sorterMixin.ts @@ -1,40 +1,49 @@ +import type { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; + const SorterMixin = { name: 'sorter-mixin', use: [], attributes: { orderBy: { type: String, - default: null + default: null, }, orderAsc: { type: String, - default: null + default: null, }, orderDesc: { type: String, - default: null + default: null, }, orderByRandom: { type: String, - default: null + default: null, }, sortedBy: { - type:String, + type: String, default: null, callback(newValue: string) { // if we change search form, re-populate - if (newValue && this.sortForm && newValue !== this.sortForm.getAttribute('id')) { + if ( + newValue && + this.sortForm && + newValue !== this.sortForm.getAttribute('id') + ) { this.sortForm = null; this.populate(); } - } - } + }, + }, }, initialState: { - randomOrder: null + randomOrder: null, }, attached(): void { - this.listPostProcessors.push(this.orderCallback.bind(this)); + this.listPostProcessors.attach( + this.orderCallback.bind(this), + 'SorterMixin:orderCallback', + ); }, created(): void { this.randomOrder = []; @@ -50,7 +59,12 @@ const SorterMixin = { }); }, - async orderCallback(resources: object[], listPostProcessors: Function[], div: HTMLElement, context: string) { + async orderCallback( + resources: object[], + listPostProcessors: PostProcessorRegistry, + div: HTMLElement, + context: string, + ) { if (this.orderBy) this.orderAsc = this.orderBy; // retrocompatibility. remove in 0.15 let sortingKey = ''; let orderValueToSort = ''; @@ -65,66 +79,75 @@ const SorterMixin = { if (sortedBy != null) { if (!this.sortForm) { this.sortForm = document.getElementById(sortedBy); - if (!this.sortForm) throw `#${sortedBy} is not in DOM`; + if (!this.sortForm) throw `#${sortedBy} is not in DOM`; this.linkSorterForm(); } if (!this.sortForm.component.value.field) { - console.warn('The attribute field does not exist') - } else { - sortingKey = this.sortForm.component.value.field['value']; + console.warn('The attribute field does not exist'); + } else { + sortingKey = this.sortForm.component.value.field.value; } const orderField = this.sortForm.component.value.order; - orderValueToSort = orderField && orderField.value ? orderField.value : 'asc'; + orderValueToSort = orderField?.value ? orderField.value : 'asc'; } } // sorting data according to the defined value of sortingKey if (sortingKey) { let orderToSort = true; // set 'asc' by default - if (this.orderDesc || orderValueToSort == "desc") orderToSort = false; - resources = (await Promise.all(resources.map(async (resource) => ({ - sortingKey: await resource[sortingKey], // fetch sorting value - proxy: resource // and keep proxy - })))) - .sort(this.sortValuesByKey("sortingKey", orderToSort)) // sort this array - .map(r => r.proxy) // re-create array + if (this.orderDesc || orderValueToSort === 'desc') orderToSort = false; + resources = ( + await Promise.all( + resources.map(async resource => ({ + sortingKey: await resource[sortingKey], // fetch sorting value + proxy: resource, // and keep proxy + })), + ) + ) + .sort(this.sortValuesByKey('sortingKey', orderToSort)) // sort this array + .map(r => r.proxy); // re-create array } // if order-by-random attribute else if (this.isRandomSorted()) { resources = this.shuffleResources(resources); // shuffle resources } + this.resources = [...resources]; const nextProcessor = listPostProcessors.shift(); - if(nextProcessor) await nextProcessor(resources, listPostProcessors, div, context); + if (nextProcessor) + await nextProcessor(resources, listPostProcessors, div, context); }, isRandomSorted(): boolean { return this.orderByRandom !== null; }, sortValuesByKey(key: string, asc: boolean): Function { - return function (a: object, b: object): number { - if (!a.hasOwnProperty(key)) return 1; - if (!b.hasOwnProperty(key)) return -1; + return (a: object, b: object): number => { + if (!Object.hasOwn(a, key)) return 1; + if (!Object.hasOwn(b, key)) return -1; const varA = a[key]; const varB = b[key]; let comparison = 0; if (typeof varA === 'string' && typeof varB === 'string') { - comparison = varA.localeCompare(varB, undefined, { sensitivity: 'base' }); + comparison = varA.localeCompare(varB, undefined, { + sensitivity: 'base', + }); comparison = asc ? comparison : -comparison; } else { if (varA > varB) comparison = asc ? 1 : -1; else if (varA < varB) comparison = asc ? -1 : 1; } return comparison; - } + }; }, shuffleResources(array: object[]): object[] { let currentIndex = array.length; let temporaryValue: object; let randomIndex: number; - if (this.randomOrder.length !== array.length) { // if no random order existing - this.randomOrder = [ ...Array(array.length).keys() ]; // generate array of indexes - while (0 !== currentIndex) { + if (this.randomOrder.length !== array.length) { + // if no random order existing + this.randomOrder = [...Array(array.length).keys()]; // generate array of indexes + while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = this.randomOrder[currentIndex]; @@ -133,9 +156,7 @@ const SorterMixin = { } } return this.randomOrder.map((i: number) => array[i]); // rebuild array with random order - } -} + }, +}; -export { - SorterMixin -} \ No newline at end of file +export { SorterMixin }; diff --git a/src/mixins/storeMixin.ts b/src/mixins/storeMixin.ts index 0d8956f58c5dd199185bd2442479bca940468af6..07432fde2f9354270ec812d1c8c1311bcd42c55a 100644 --- a/src/mixins/storeMixin.ts +++ b/src/mixins/storeMixin.ts @@ -1,10 +1,13 @@ -import { store } from '../libs/store/store'; -import { formatAttributesToServerSearchOptions, mergeServerSearchOptions } from '../libs/store/server-search'; -import { AttributeBinderMixin } from './attributeBinderMixin'; -import type { Resource } from './interfaces'; -import { ContextMixin } from './contextMixin'; -import { ServerPaginationMixin } from './serverPaginationMixin'; -import { formatAttributesToServerPaginationOptions } from '../libs/store/server-pagination'; +import { formatAttributesToServerPaginationOptions } from '../libs/store/server-pagination.ts'; +import { + formatAttributesToServerSearchOptions, + mergeServerSearchOptions, +} from '../libs/store/server-search.ts'; +import { store } from '../libs/store/store.ts'; +import { AttributeBinderMixin } from './attributeBinderMixin.ts'; +import { ContextMixin } from './contextMixin.ts'; +import type { Resource } from './interfaces.ts'; +import { ServerPaginationMixin } from './serverPaginationMixin.ts'; const StoreMixin = { name: 'store-mixin', @@ -15,40 +18,45 @@ const StoreMixin = { default: null, callback: function (value: boolean) { if (value === null) this.fetchData(this.dataSrc); - } + }, }, dataSrc: { type: String, default: null, callback: async function (value: string) { - const filteredOnServer = this.element.attributes['filtered-on']?.value === 'server'; - const limited = this.element.attributes['limit']?.value !== undefined; - + const filteredOnServer = + this.element.attributes['filtered-on']?.value === 'server'; + const limited = this.element.attributes.limit?.value !== undefined; + if (this.noRender === null && !filteredOnServer && !limited) { await this.fetchData(value); } else if (this.noRender === null && !filteredOnServer) { - this.resourceId = value + this.resourceId = value; } }, }, loaderId: { type: String, - default: '' + default: '', }, nestedField: { type: String, - default: null + default: null, }, arrayField: { type: String, default: null, callback: function (value: boolean) { - if (value) this.predicateName = store.getExpandedPredicate(this.arrayField, this.context); - } + if (value) + this.predicateName = store.getExpandedPredicate( + this.arrayField, + this.context, + ); + }, }, predicateName: { type: String, - default: null + default: null, }, }, initialState: { @@ -62,12 +70,14 @@ const StoreMixin = { detached() { if (this.subscription) PubSub.unsubscribe(this.subscription); }, - get resource(): Resource|null{ - let id = this.resourceId; - const serverPagination = formatAttributesToServerPaginationOptions(this.element.attributes) + get resource(): Resource | null { + const id = this.resourceId; + const serverPagination = formatAttributesToServerPaginationOptions( + this.element.attributes, + ); const serverSearch = mergeServerSearchOptions( formatAttributesToServerSearchOptions(this.element.attributes), - this.getDynamicServerSearch?.() // from `filterMixin` + this.getDynamicServerSearch?.(), // from `filterMixin` ); return id ? store.get(id, serverPagination, serverSearch) : null; @@ -78,7 +88,7 @@ const StoreMixin = { async fetchData(value: string) { this.empty(); if (this.subscription) PubSub.unsubscribe(this.subscription); - if (!value || value == "undefined") return; + if (!value || value === 'undefined') return; this.resourceId = value; if (this.nestedField) { @@ -100,15 +110,28 @@ const StoreMixin = { this.updateNavigateSubscription(); - this.subscription = PubSub.subscribe(this.resourceId, this.updateDOM.bind(this)); - const serverPagination = formatAttributesToServerPaginationOptions(this.element.attributes); + this.subscription = PubSub.subscribe( + this.resourceId, + this.updateDOM.bind(this), + ); + const serverPagination = formatAttributesToServerPaginationOptions( + this.element.attributes, + ); const dynamicServerSearch = this.getDynamicServerSearch?.(); // from `filterMixin` const serverSearch = mergeServerSearchOptions( formatAttributesToServerSearchOptions(this.element.attributes), - dynamicServerSearch + dynamicServerSearch, ); const forceRefetch = !!dynamicServerSearch; - this.resources = await store.getData(this.resourceId, this.context, undefined, undefined, forceRefetch, serverPagination, serverSearch); + await store.getData( + this.resourceId, + this.context, + undefined, + undefined, + forceRefetch, + serverPagination, + serverSearch, + ); this.updateDOM(); }, @@ -116,24 +139,26 @@ const StoreMixin = { toggleLoaderHidden(toggle: boolean): void { if (this.loader) this.loader.toggleAttribute('hidden', toggle); }, - updateNavigateSubscription() { }, + updateNavigateSubscription() {}, async updateDOM(): Promise<void> { this.toggleLoaderHidden(false); // brings a loader out if the attribute is set this.empty(); await this.replaceAttributesData(); await this.populate(); - setTimeout(() => ( // Brings the dispatchEvent at the end of the queue - this.element.dispatchEvent(new CustomEvent('populate', { detail: { resource: {"@id": this.dataSrc} } }))) + setTimeout(() => + // Brings the dispatchEvent at the end of the queue + this.element.dispatchEvent( + new CustomEvent('populate', { + detail: { resource: { '@id': this.dataSrc } }, + }), + ), ); this.toggleLoaderHidden(true); }, - empty():void { - }, + empty(): void {}, update() { if (this.noRender === null) this.updateDOM(); - } + }, }; -export { - StoreMixin -} \ No newline at end of file +export { StoreMixin }; diff --git a/src/mixins/translationMixin.ts b/src/mixins/translationMixin.ts index c23c1706c1812181db290825ab558791bf58935d..6ba822a2ee649c26697b6c7ae3829fa86b0b57f3 100644 --- a/src/mixins/translationMixin.ts +++ b/src/mixins/translationMixin.ts @@ -1,10 +1,10 @@ -import { store } from "../libs/store/store"; +import { store } from '../libs/store/store.ts'; const TranslationMixin = { name: 'translation-mixin', use: [], initialState: { - translationData:{} + translationData: {}, }, created() { this.getLang(); @@ -15,12 +15,16 @@ const TranslationMixin = { * @returns - object: {key: translation} */ async getTranslationModule(langCode: string) { - const translationsModules = { // define modules in a static way, snowpack does not support dynamic strings here + const translationsModules = { + // define modules in a static way, snowpack does not support dynamic strings here en: () => import('../locales/en.json'), fr: () => import('../locales/fr.json'), }; - if (!translationsModules[langCode]) { // set default to EN if the file does not exist - console.warn(`${langCode}.json translation file may not exist, English is setted by default`); + if (!translationsModules[langCode]) { + // set default to EN if the file does not exist + console.warn( + `${langCode}.json translation file may not exist, English is setted by default`, + ); langCode = 'en'; } const module = await translationsModules[langCode](); @@ -31,16 +35,18 @@ const TranslationMixin = { */ getLang() { const languageStorage = store._getLanguage(); - if(languageStorage) { - if (window.fetchTranslationPromise === undefined) { // if translation data are not already fetched - window.fetchTranslationPromise = this.getTranslationModule(languageStorage); + if (languageStorage) { + if (window.fetchTranslationPromise === undefined) { + // if translation data are not already fetched + window.fetchTranslationPromise = + this.getTranslationModule(languageStorage); } window.fetchTranslationPromise.then(res => { if (res) { this.translationData = res; // stock data in object passed to traduction method below this.update(); // update the rendering in components and widgets } - }) + }); } }, /** @@ -50,9 +56,7 @@ const TranslationMixin = { */ t(tradKey: string) { return this.translationData[tradKey] || ''; - } -} + }, +}; -export { - TranslationMixin -} \ No newline at end of file +export { TranslationMixin }; diff --git a/src/mixins/validationMixin.ts b/src/mixins/validationMixin.ts index cd56edffd3c7c1aec9c29f669a9e52d46925bfb7..770ad3259f8e19ebde5adcd8c114f18b6fe0bf27 100644 --- a/src/mixins/validationMixin.ts +++ b/src/mixins/validationMixin.ts @@ -1,9 +1,9 @@ -import dialogPolyfill from 'dialog-polyfill' -import { html } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; -import { uniqID } from '../libs/helpers'; -import { TranslationMixin } from './translationMixin'; -import { preHTML } from '../libs/lit-helpers'; +import dialogPolyfill from 'dialog-polyfill'; +import { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { uniqID } from '../libs/helpers.ts'; +import { preHTML } from '../libs/lit-helpers.ts'; +import { TranslationMixin } from './translationMixin.ts'; const ValidationMixin = { name: 'validation-mixin', @@ -11,89 +11,95 @@ const ValidationMixin = { attributes: { confirmationMessage: { type: String, - default: null + default: null, }, confirmationType: { type: String, - default: null + default: null, }, confirmationSubmitText: { type: String, - default: null + default: null, }, confirmationCancelText: { type: String, - default: null + default: null, }, confirmationSubmitClass: { type: String, - default: undefined + default: undefined, }, confirmationCancelClass: { type: String, - default: undefined + default: undefined, }, confirmationWidget: { type: String, - default: undefined - } + default: undefined, + }, }, created() { this.dialogID = uniqID(); }, showModal() { - var dialog: any = document.getElementById(this.dialogID); + const dialog: any = document.getElementById(this.dialogID); dialogPolyfill.registerDialog(dialog); return dialog.showModal(); }, performAction() { // Console warning if conf-type attr not filled AND conf-message filled - if (this.element.hasAttribute('confirmation-message') && !this.confirmationType) console.warn('confirmation-type attribute is missing.'); + if ( + this.element.hasAttribute('confirmation-message') && + !this.confirmationType + ) + console.warn('confirmation-type attribute is missing.'); // Data directly submitted OR confirm dialog modal displayed - if ((!this.confirmationType) || (this.confirmationType == "confirm" && confirm(this.confirmationMessage || this.t("validation.message")))) this.validateModal(); + if ( + !this.confirmationType || + (this.confirmationType === 'confirm' && + confirm(this.confirmationMessage || this.t('validation.message'))) + ) + this.validateModal(); // Customisable dialog modal opened - if (this.confirmationType == "dialog") { + if (this.confirmationType === 'dialog') { this.showModal(); } }, getModalDialog() { - if (this.confirmationType == 'dialog') { - const quitDialog = () => { - var dialog: any = document.getElementById(this.dialogID); - if (dialog == null) return; - dialog.close(); - } - const confirmChoice = () => { - this.validateModal(); - quitDialog(); + if (this.confirmationType !== 'dialog') return ''; + const quitDialog = () => { + const dialog: any = document.getElementById(this.dialogID); + if (dialog == null) return; + dialog.close(); + }; + const confirmChoice = () => { + this.validateModal(); + quitDialog(); + }; + return html` + <dialog id="${this.dialogID}"> + ${ + this.confirmationWidget + ? preHTML`<${this.confirmationWidget} value=${this.resourceId}></${this.confirmationWidget}>` + : html`<p>${this.confirmationMessage || this.t('validation.message')}</p>` } - return html` - <dialog id="${this.dialogID}"> - ${this.confirmationWidget ? preHTML` - <${this.confirmationWidget} value=${this.resourceId}></${this.confirmationWidget}> - ` : html` - <p>${this.confirmationMessage || this.t("validation.message")}</p> - `} - <div> - <button - @click=${confirmChoice} - class=${ifDefined(this.confirmationSubmitClass)} - > - ${this.confirmationSubmitText || this.t("validation.submit-text")} - </button> - <button - @click=${quitDialog} - class=${ifDefined(this.confirmationCancelClass)} - > - ${this.confirmationCancelText || this.t("validation.cancel-text")} - </button> - </div> - </dialog> - ` - } else return ''; + <div> + <button + @click=${confirmChoice} + class=${ifDefined(this.confirmationSubmitClass)} + > + ${this.confirmationSubmitText || this.t('validation.submit-text')} + </button> + <button + @click=${quitDialog} + class=${ifDefined(this.confirmationCancelClass)} + > + ${this.confirmationCancelText || this.t('validation.cancel-text')} + </button> + </div> + </dialog> + `; }, -} +}; -export { - ValidationMixin -} \ No newline at end of file +export { ValidationMixin }; diff --git a/src/mixins/widgetMixin.ts b/src/mixins/widgetMixin.ts index 96f0771f8ac689869344dafb9901baa426e5204c..ca46eef7d26f2555ec357dfab94913f606021045 100644 --- a/src/mixins/widgetMixin.ts +++ b/src/mixins/widgetMixin.ts @@ -1,9 +1,16 @@ -import { spread, preHTML } from '../libs/lit-helpers'; -import { parseFieldsString, findClosingBracketMatchIndex } from '../libs/helpers'; -import { newWidgetFactory } from '../new-widgets/new-widget-factory'; -import { WidgetInterface, WidgetType, Resource } from './interfaces'; -import { html, render, TemplateResult } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { type TemplateResult, html, render } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { + findClosingBracketMatchIndex, + parseFieldsString, +} from '../libs/helpers.ts'; +import { preHTML, spread } from '../libs/lit-helpers.ts'; +import { newWidgetFactory } from '../new-widgets/new-widget-factory.ts'; +import { + type Resource, + type WidgetInterface, + WidgetType, +} from './interfaces.ts'; const WidgetMixin = { name: 'widget-mixin', @@ -12,17 +19,18 @@ const WidgetMixin = { fields: { type: String, default: undefined, - } + }, }, initialState: { nameWidgets: null, - _div: null + _div: null, }, created(): void { this.nameWidgets = []; }, attached(): void { - if (!this.dataSrc && !this.resource && this.noRender === null) this.populate(); + if (!this.dataSrc && !this.resource && this.noRender === null) + this.populate(); }, get parentElement(): string { return 'div'; @@ -34,39 +42,45 @@ const WidgetMixin = { return this._div; }, set div(value) { - this._div = value + this._div = value; }, get widgets() { - return this.nameWidgets.map((name: string) => this.element.querySelector(`[name="${name}"]`)); + return this.nameWidgets.map((name: string) => + this.element.querySelector(`[name="${name}"]`), + ); }, /** * Return field list of the component */ - async getFields(): Promise<string[]>{ // TODO : improve code + async getFields(): Promise<string[]> { + // TODO : improve code const attr = this.fields; if (attr === '') return []; if (attr) return parseFieldsString(attr); let resource = this.resource as Resource; - if (resource && resource.isContainer?.()) { // If container, keep the 1rst resource - for (let res of resource['ldp:contains']) { + if (resource?.isContainer?.()) { + // If container, keep the 1rst resource + for (const res of resource['ldp:contains']) { resource = res; break; } - } else if (resource && this.arrayField && this.predicateName) { // if array, keep the 1rst resource - for (let res of resource[this.predicateName]) { + } else if (resource && this.arrayField && this.predicateName) { + // if array, keep the 1rst resource + for (const res of resource[this.predicateName]) { resource = res; break; } } - if (!this.dataSrc) console.error(new Error('You must provide a "fields" attribute')); - if(!resource) return []; + if (!this.dataSrc) + console.error(new Error('You must provide a "fields" attribute')); + if (!resource) return []; - let fields: string[] = []; + const fields: string[] = []; for (const prop of resource.properties) { - if ((!prop.startsWith('@') && !(prop === "permissions"))) { - if (!this.isAlias(prop) && await resource[prop]) fields.push(prop); + if (!prop.startsWith('@') && !(prop === 'permissions')) { + if (!this.isAlias(prop) && (await resource[prop])) fields.push(prop); else if (this.isAlias(prop)) fields.push(prop); } } @@ -77,7 +91,7 @@ const WidgetMixin = { * @param field - string */ getAction(field: string): string { - const action = this.element.getAttribute('action-' + field); + const action = this.element.getAttribute(`action-${field}`); return action; }, /** @@ -85,14 +99,14 @@ const WidgetMixin = { * @param field - string */ editable(field: string): string { - return this.element.hasAttribute('editable-' + field); + return this.element.hasAttribute(`editable-${field}`); }, /** * Return regexp to check if "field" is a set * @param field - string */ getSetRegexp(field: string) { - return new RegExp(`(^|\\,|\\(|\\s)\\s*${field}\\s*\\(`, 'g') + return new RegExp(`(^|\\,|\\(|\\s)\\s*${field}\\s*\\(`, 'g'); }, /** * Return fields contained in set "field" @@ -101,8 +115,12 @@ const WidgetMixin = { getSet(field: string): string[] { const setString = this.fields.match(this.getSetRegexp(field)); if (!setString) return []; - const firstSetBracket = this.fields.indexOf(setString[0]) + (setString[0].length) - 1; - const lastSetBracket = findClosingBracketMatchIndex(this.fields, firstSetBracket); + const firstSetBracket = + this.fields.indexOf(setString[0]) + setString[0].length - 1; + const lastSetBracket = findClosingBracketMatchIndex( + this.fields, + firstSetBracket, + ); const set = this.fields.substring(firstSetBracket + 1, lastSetBracket); return parseFieldsString(set); }, @@ -112,7 +130,7 @@ const WidgetMixin = { */ isSet(field: string): boolean { if (!this.fields) return false; - let foundSets = this.fields.match(this.getSetRegexp(field)); + const foundSets = this.fields.match(this.getSetRegexp(field)); return foundSets ? foundSets.length > 0 : false; }, /** @@ -120,7 +138,7 @@ const WidgetMixin = { * @param field - string */ isString(field: string): boolean { - return field.startsWith('\'') || field.startsWith('\"'); + return field.startsWith("'") || field.startsWith('"'); }, /** * Return true if "field" is an alias (contains " as ") @@ -138,22 +156,35 @@ const WidgetMixin = { async fetchValue(field: string, resource: Resource) { if (resource && !resource.isContainer?.()) { let fieldValue = await resource[field]; - if (fieldValue === null || fieldValue === undefined || fieldValue === '') { - let expandedPredicate = sibStore.getExpandedPredicate(field, this.context); + if ( + fieldValue === null || + fieldValue === undefined || + fieldValue === '' + ) { + const expandedPredicate = sibStore.getExpandedPredicate( + field, + this.context, + ); fieldValue = await resource[expandedPredicate]; } - if (fieldValue === null || fieldValue === undefined || fieldValue === '') return undefined; + if (fieldValue === null || fieldValue === undefined || fieldValue === '') + return undefined; if (Array.isArray(fieldValue) && !fieldValue['ldp:contains']) { return JSON.stringify(fieldValue); - // Dumb edge case because if the array bears only one item, when compacted the array translates into one object - } else if ( + // Dumb edge case because if the array bears only one item, when compacted the array translates into one object + } + if ( typeof fieldValue === 'object' && - fieldValue['@id'] && 1 === Object.keys(fieldValue).length) { + fieldValue['@id'] && + Object.keys(fieldValue).length === 1 + ) { return JSON.stringify([fieldValue]); } } - return resource && !resource.isContainer?.() ? await resource[field] : undefined; + return resource && !resource.isContainer?.() + ? await resource[field] + : undefined; }, /** * Return the value of the field @@ -165,8 +196,8 @@ const WidgetMixin = { return this.getAction(escapedField); } - if (this.element.hasAttribute('value-' + field)) { - return this.element.getAttribute('value-' + field); + if (this.element.hasAttribute(`value-${field}`)) { + return this.element.getAttribute(`value-${field}`); } if (this.isAlias(field)) { @@ -174,11 +205,17 @@ const WidgetMixin = { return await this.fetchValue(alias[0], resource); } - let resourceValue = await this.fetchValue(field, resource); + const resourceValue = await this.fetchValue(field, resource); // Empty value - if (resourceValue === undefined || resourceValue === '' || resourceValue === null) // If null or empty, return field default value - return this.element.hasAttribute('default-' + field) ? - this.element.getAttribute('default-' + field) : ''; + if ( + resourceValue === undefined || + resourceValue === '' || + resourceValue === null + ) + // If null or empty, return field default value + return this.element.hasAttribute(`default-${field}`) + ? this.element.getAttribute(`default-${field}`) + : ''; return resourceValue; }, @@ -188,9 +225,13 @@ const WidgetMixin = { * @param tagName - string */ widgetFromTagName(tagName: string) { - let type = tagName.startsWith('solid') ? WidgetType.CUSTOM : WidgetType.USER; - if (!customElements.get(tagName)) { // component does not exist - if (tagName.startsWith('solid')) newWidgetFactory(tagName); // solid- -> create it + let type = tagName.startsWith('solid') + ? WidgetType.CUSTOM + : WidgetType.USER; + if (!customElements.get(tagName)) { + // component does not exist + if (tagName.startsWith('solid')) + newWidgetFactory(tagName); // solid- -> create it else type = WidgetType.NATIVE; // or use a native tag } return { tagName, type }; // return tagName @@ -200,23 +241,26 @@ const WidgetMixin = { * @param field - string * @param isSet - boolean */ - getWidget(field: string, isSet: boolean = false): WidgetInterface { + getWidget(field: string, isSet = false): WidgetInterface { if (this.isAlias(field)) field = field.split(' as ')[1]; - const widget = this.element.getAttribute('widget-' + field); + const widget = this.element.getAttribute(`widget-${field}`); if (widget) return this.widgetFromTagName(widget); if (this.getAction(field)) return this.widgetFromTagName('solid-action'); - return !isSet ? this.widgetFromTagName(this.defaultWidget) : this.widgetFromTagName(this.defaultSetWidget); + return !isSet + ? this.widgetFromTagName(this.defaultWidget) + : this.widgetFromTagName(this.defaultSetWidget); }, /** * Return multiple widget if "field" is a multiple, false if it's not * @param field - string */ - multiple(field: string): WidgetInterface|null { - const attribute = 'multiple-' + field; + multiple(field: string): WidgetInterface | null { + const attribute = `multiple-${field}`; if (!this.element.hasAttribute(attribute)) return null; - const widget = this.element.getAttribute(attribute) || this.defaultMultipleWidget; + const widget = + this.element.getAttribute(attribute) || this.defaultMultipleWidget; return this.widgetFromTagName(widget); }, /** @@ -236,7 +280,7 @@ const WidgetMixin = { * @param resource - Resource */ widgetAttributes(field: string, resource: Resource): object { - const attrs = { name: field }; + const attrs: Record<string, string> = { name: field }; if (this.isAlias(field)) field = field.split(' as ')[1]; const escapedField = this.getEscapedField(field); @@ -247,12 +291,13 @@ const WidgetMixin = { 'widget', 'add-label', 'remove-label', - 'next', + 'next', 'empty-widget', 'add-class', - 'remove-class' + 'remove-class', ]; - for (let attr of multipleAttributes) this.addToAttributes(`multiple-${escapedField}-${attr}`, attr, attrs) + for (const attr of multipleAttributes) + this.addToAttributes(`multiple-${escapedField}-${attr}`, attr, attrs); // transfer all [attr]-[field] attributes as [attr] attribute for widget [field] const defaultAttributes = [ @@ -261,7 +306,7 @@ const WidgetMixin = { 'label', 'placeholder', 'class', - /* 'widget', */, + /* 'widget', */ 'required', 'editable', 'autocomplete', @@ -286,72 +331,95 @@ const WidgetMixin = { 'search-placeholder', 'link-text', 'target-src', - 'data-label' + 'data-label', ]; - for (let attr of defaultAttributes) this.addToAttributes(`${attr}-${escapedField}`, attr, attrs) + for (const attr of defaultAttributes) + this.addToAttributes(`${attr}-${escapedField}`, attr, attrs); - const addableAttributes: Attr[] = (Array.from(this.element.attributes) as Attr[]).filter((a: Attr) => a.name.startsWith(`addable-${escapedField}`)); - for (let attr of addableAttributes) this.addToAttributes(attr.name, attr.name.replace(`addable-${escapedField}`, 'addable'), attrs) + const addableAttributes: Attr[] = ( + Array.from(this.element.attributes) as Attr[] + ).filter((a: Attr) => a.name.startsWith(`addable-${escapedField}`)); + for (const attr of addableAttributes) + this.addToAttributes( + attr.name, + attr.name.replace(`addable-${escapedField}`, 'addable'), + attrs, + ); - const resourceId = resource ? resource!['@id'] : null; - if (this.multiple(escapedField)) attrs['widget'] = this.getWidget(escapedField).tagName; - if (this.getAction(escapedField) && resourceId) attrs['src'] = this.element.getAttribute('src-' + escapedField) || resourceId; - if (this.editable(escapedField) && resourceId) attrs['value-id'] = resourceId; + const resourceId = resource?.['@id'] ?? null; + if (this.multiple(escapedField)) + attrs.widget = this.getWidget(escapedField).tagName; + if (this.getAction(escapedField) && resourceId) + attrs.src = + this.element.getAttribute(`src-${escapedField}`) || resourceId; + if (this.editable(escapedField) && resourceId) + attrs['value-id'] = resourceId; return attrs; }, /** * Creates and return a widget for field + add it to the widget list * @param field - string */ - async createWidgetTemplate(field: string, resource = null, transformAttributes = false): Promise<TemplateResult> { + async createWidgetTemplate( + field: string, + resource = null, + transformAttributes = false, + ): Promise<TemplateResult> { if (this.isString(field)) return this.createString(field); // field is a static string if (this.isSet(field)) return await this.createSet(field); const currentResource = resource || this.resource; let attributes = this.widgetAttributes(field, currentResource); const escapedField = this.getEscapedField(field); - const widgetMeta = this.multiple(escapedField) || this.getWidget(escapedField); + const widgetMeta = + this.multiple(escapedField) || this.getWidget(escapedField); let tagName = widgetMeta.tagName; - let widgetTemplate = html``; + let widgetTemplate: TemplateResult = html``; // Set attributes - let value = await this.getValue(field, currentResource); - if (widgetMeta.type === WidgetType.NATIVE) { // native widget (ie: h1) - widgetTemplate = preHTML` - <${tagName} - name="${ifDefined(attributes.name)}" - class="${ifDefined(attributes.class)}" - >${value}</${tagName}> - `; - } else { // custom widget (ie: solid-display-value) + const value = await this.getValue(field, currentResource); + if (widgetMeta.type === WidgetType.NATIVE) { + // native widget (ie: h1) + widgetTemplate = preHTML`<${tagName} name="${ifDefined(attributes.name)}" class="${ifDefined(attributes.class)}">${value}</${tagName}>`; + } else { + // custom widget (ie: solid-display-value) // Check if value is defined, and if the default widget is needed - if ((value === null || value === '') && this.element.hasAttribute('default-widget-' + field)) { - tagName = this.element.getAttribute('default-widget-' + field); + if ( + (value === null || value === '') && + this.element.hasAttribute(`default-widget-${field}`) + ) { + tagName = this.element.getAttribute(`default-widget-${field}`); } // Set attributes to the widget // setAttribute set a string. Make sure null values are empty if (value === null || value === undefined) attributes.value = ''; - if (widgetMeta.type === WidgetType.USER) { // if value is a resource and solid-widget used, set data-src + if (widgetMeta.type === WidgetType.USER) { + // if value is a resource and solid-widget used, set data-src if (value['@id']) { attributes['data-src'] = value['@id']; } else { try { - let isUrl = new URL(value); + const isUrl = new URL(value); if (isUrl) attributes['data-src'] = value; - } catch (e) {} + } catch {} // in any case, set value attribute - attributes['value'] = value; + attributes.value = value; } - } else { // otherwise, set value attribute - attributes['value'] = value; + } else { + // otherwise, set value attribute + attributes.value = value; } // Subscribe widgets if they show a resource - if (value && value['@id']) attributes['auto-subscribe'] = value['@id']; + if (value?.['@id']) attributes['auto-subscribe'] = value['@id']; // Transform store://XXX attributes - if (transformAttributes) attributes = await this.transformAttributes(attributes, currentResource); + if (transformAttributes) + attributes = await this.transformAttributes( + attributes, + currentResource, + ); widgetTemplate = preHTML`<${tagName} ...=${spread(attributes)}></${tagName}>`; } @@ -360,7 +428,8 @@ const WidgetMixin = { return widgetTemplate; }, defineAttribute(widget: HTMLElement, attribute: string, value: any) { - if (widget.getAttribute(attribute) !== value) { // if attribute is different than previous one + if (widget.getAttribute(attribute) !== value) { + // if attribute is different than previous one widget.setAttribute(attribute, value); // set it } }, @@ -373,55 +442,59 @@ const WidgetMixin = { // Get set attributes const attrs = { name: field }; - const setAttributes = [ - 'class', - 'label' - ]; - for (let attr of setAttributes) this.addToAttributes(`${attr}-${field}`, attr, attrs); + const setAttributes = ['class', 'label']; + for (const attr of setAttributes) + this.addToAttributes(`${attr}-${field}`, attr, attrs); // Create widget if not already existing - let widget = this.element.querySelector(`${setWidget.tagName}[name="${field}"]`); + let widget = this.element.querySelector( + `${setWidget.tagName}[name="${field}"]`, + ); let initializing = false; // used to render widget only first time if (!widget) { widget = document.createElement(setWidget.tagName); initializing = true; } - for (let name of Object.keys(attrs)) { + for (const name of Object.keys(attrs)) { this.defineAttribute(widget, name, attrs[name], setWidget.type); } if (widget.component && initializing) widget.component.render(); - let setFields = this.getSet(field); + const setFields = this.getSet(field); // Catch widget for the set if all these fields are empty - if (this.element.hasAttribute('empty-' + field)) { + if (this.element.hasAttribute(`empty-${field}`)) { let hasOnlyEmpty = true; - for(let field of setFields) { - let value: string = await this.getValue(field, this.resource); - if (value !== '') { // if one not empty + for (const field of setFields) { + const value: string = await this.getValue(field, this.resource); + if (value !== '') { + // if one not empty hasOnlyEmpty = false; - continue; // break loop + break; } - }; - if(hasOnlyEmpty) { // if only empty values, return empty-widget + } + if (hasOnlyEmpty) { + // if only empty values, return empty-widget const attributes = this.widgetAttributes(field, this.resource); const tagName = this.element.getAttribute(`empty-${field}`); const valueSet = this.element.getAttribute(`empty-${field}-value`); if (valueSet) attributes.value = valueSet; return preHTML`<${tagName} ...=${spread(attributes)}></${tagName}>`; - }; + } } - if (!setFields.length) { - console.warn(`Set with name ${field} has not been generated due to being empty`) + if (setFields.length === 0) { + console.warn( + `Set with name ${field} has not been generated due to being empty`, + ); } // Render template - const widgetsTemplate = await Promise.all(setFields.map((field: string) => this.createWidgetTemplate(field))); + const widgetsTemplate = await Promise.all( + setFields.map((field: string) => this.createWidgetTemplate(field)), + ); const template = html`${widgetsTemplate}`; render(template, widget.querySelector('[data-content]') || widget); return widget; }, createString(value: string): TemplateResult { - return html` - <span>${value.slice(1, -1).replace(/\\(['"])/g, '$1')}</span> - `; + return html`<span>${value.slice(1, -1).replace(/\\(['"])/g, '$1')}</span>`; }, /** * Returns field name without starting "@" @@ -429,9 +502,7 @@ const WidgetMixin = { */ getEscapedField(field: string): string { return field.startsWith('@') ? field.slice(1, field.length) : field; - } -} + }, +}; -export { - WidgetMixin -} \ No newline at end of file +export { WidgetMixin }; diff --git a/src/new-widgets/attributeMixins/actionMixin.ts b/src/new-widgets/attributeMixins/actionMixin.ts index a50058cd0a73fbf572abff5768d85b154c634a91..6a5e25f4c15cf6692e630718101bbb8054ac5258 100644 --- a/src/new-widgets/attributeMixins/actionMixin.ts +++ b/src/new-widgets/attributeMixins/actionMixin.ts @@ -6,18 +6,16 @@ const ActionMixin = { default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'src'); - } + }, }, targetSrc: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'target-src'); - } + }, }, }, -} +}; -export { - ActionMixin -} \ No newline at end of file +export { ActionMixin }; diff --git a/src/new-widgets/attributeMixins/blankMixin.ts b/src/new-widgets/attributeMixins/blankMixin.ts index 0ecac831ca83318dc8cd6ae317d43e7f1591fba7..5e3569cdbbba3d70e2dc0e70105cd343c3bb38d0 100644 --- a/src/new-widgets/attributeMixins/blankMixin.ts +++ b/src/new-widgets/attributeMixins/blankMixin.ts @@ -1,10 +1,8 @@ const BlankMixin = { name: 'blank-mixin', created() { - this.listAttributes['target'] = '_blank'; - } -} + this.listAttributes.target = '_blank'; + }, +}; -export { - BlankMixin -} \ No newline at end of file +export { BlankMixin }; diff --git a/src/new-widgets/attributeMixins/index.ts b/src/new-widgets/attributeMixins/index.ts index 0106ad776d97bbded1f09f6502f678ba121cfbdf..7032f711f9ced0e2f1a8d8f3b3af80a4ae748d1a 100644 --- a/src/new-widgets/attributeMixins/index.ts +++ b/src/new-widgets/attributeMixins/index.ts @@ -1,11 +1,11 @@ -import { MultipleMixin } from './multipleMixin'; -import { ActionMixin } from './actionMixin'; -import { BlankMixin } from './blankMixin'; -import { MailtoMixin } from './mailtoMixin'; -import { TelMixin } from './telMixin'; -import { PlaceholderMixin } from './placeholderMixin'; -import { BooleanMixin } from './booleanMixin'; -import { NumberMixin } from './numberMixin'; +import { ActionMixin } from './actionMixin.ts'; +import { BlankMixin } from './blankMixin.ts'; +import { BooleanMixin } from './booleanMixin.ts'; +import { MailtoMixin } from './mailtoMixin.ts'; +import { MultipleMixin } from './multipleMixin.ts'; +import { NumberMixin } from './numberMixin.ts'; +import { PlaceholderMixin } from './placeholderMixin.ts'; +import { TelMixin } from './telMixin.ts'; const attributeDirectory = { multiple: MultipleMixin, @@ -16,7 +16,7 @@ const attributeDirectory = { placeholder: PlaceholderMixin, bool: BooleanMixin, num: NumberMixin, -} +}; export { attributeDirectory, @@ -26,4 +26,4 @@ export { MailtoMixin, TelMixin, PlaceholderMixin, -} +}; diff --git a/src/new-widgets/attributeMixins/mailtoMixin.ts b/src/new-widgets/attributeMixins/mailtoMixin.ts index 618264e425e8480a11d5235fb0eea374b11e91aa..b500c742fce8327fecaaa6cc638410a57f3e4978 100644 --- a/src/new-widgets/attributeMixins/mailtoMixin.ts +++ b/src/new-widgets/attributeMixins/mailtoMixin.ts @@ -1,10 +1,8 @@ const MailtoMixin = { name: 'mailto-mixin', created() { - this.listAttributes['mailto'] = 'mailto:'; - } -} + this.listAttributes.mailto = 'mailto:'; + }, +}; -export { - MailtoMixin -} \ No newline at end of file +export { MailtoMixin }; diff --git a/src/new-widgets/attributeMixins/multipleMixin.ts b/src/new-widgets/attributeMixins/multipleMixin.ts index 90e0e01fb79dc15a088a0b1f040ce4a446000cd2..45bab1ea4ca60e4084198f892911074d75246af2 100644 --- a/src/new-widgets/attributeMixins/multipleMixin.ts +++ b/src/new-widgets/attributeMixins/multipleMixin.ts @@ -6,25 +6,23 @@ const MultipleMixin = { default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'fields'); - } + }, }, next: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'next'); - } + }, }, emptyWidget: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'emptyWidget'); - } - } + }, + }, }, -} +}; -export { - MultipleMixin -} \ No newline at end of file +export { MultipleMixin }; diff --git a/src/new-widgets/attributeMixins/placeholderMixin.ts b/src/new-widgets/attributeMixins/placeholderMixin.ts index 301bcb7019d058863416c2b46e9a8cd1e70be1c4..aee2ef30ef763f0f1c4b229cd11105866ac0445b 100644 --- a/src/new-widgets/attributeMixins/placeholderMixin.ts +++ b/src/new-widgets/attributeMixins/placeholderMixin.ts @@ -6,14 +6,13 @@ const PlaceholderMixin = { default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'placeholder'); - } + }, }, }, attached() { - this.listAttributes['placeholder'] = this.placeholder || this.label || this.name || ''; - } -} + this.listAttributes.placeholder = + this.placeholder || this.label || this.name || ''; + }, +}; -export { - PlaceholderMixin -} \ No newline at end of file +export { PlaceholderMixin }; diff --git a/src/new-widgets/attributeMixins/telMixin.ts b/src/new-widgets/attributeMixins/telMixin.ts index 26a9a1e02d197cdb1d0317020232003ff3c7e296..3582ace3756de0804b870ab87b0c8cb6ed3b9cd9 100644 --- a/src/new-widgets/attributeMixins/telMixin.ts +++ b/src/new-widgets/attributeMixins/telMixin.ts @@ -1,10 +1,8 @@ const TelMixin = { name: 'tel-mixin', created() { - this.listAttributes['tel'] = 'tel:'; - } -} + this.listAttributes.tel = 'tel:'; + }, +}; -export { - TelMixin -} \ No newline at end of file +export { TelMixin }; diff --git a/src/new-widgets/baseWidgetMixin.ts b/src/new-widgets/baseWidgetMixin.ts index a5cb6195445e93dd029de73247a54f2283237722..b93c369a04c682829bb1cbad5cea4e484e3bb2fa 100644 --- a/src/new-widgets/baseWidgetMixin.ts +++ b/src/new-widgets/baseWidgetMixin.ts @@ -1,6 +1,10 @@ -import type { Template } from './interfaces'; +import type PubSubType from 'pubsub-js'; +import { PostProcessorRegistry } from '../libs/PostProcessorRegistry.ts'; +import type { Template } from './interfaces.ts'; -import {render} from 'lit-html'; +import { render } from 'lit'; + +declare const PubSub: typeof PubSubType; const BaseWidgetMixin = { name: 'widget-mixin', @@ -11,21 +15,21 @@ const BaseWidgetMixin = { default: '', callback: function () { this.planRender(); - } + }, }, name: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'name'); - } + }, }, label: { type: String, default: null, callback: function (newValue: string) { this.addToAttributes(newValue, 'label'); - } + }, }, autoSubscribe: { type: String, @@ -33,24 +37,24 @@ const BaseWidgetMixin = { callback: function (newValue: string) { if (this.subscription) PubSub.unsubscribe(this.subscription); this.subscribe(newValue); - } + }, }, }, initialState: { - listValueTransformations: [], - listTemplateAdditions: [], + listValueTransformations: new PostProcessorRegistry(), + listTemplateAdditions: new PostProcessorRegistry(), listAttributes: {}, - listCallbacks: [], + listCallbacks: new PostProcessorRegistry(), renderPlanned: false, }, get template() { - return null + return null; }, created() { - this.listValueTransformations = []; + this.listValueTransformations = new PostProcessorRegistry(); this.listAttributes = {}; - this.listTemplateAdditions = []; - this.listCallbacks = []; + this.listTemplateAdditions = new PostProcessorRegistry(); + this.listCallbacks = new PostProcessorRegistry(); this.subscription = null; }, attached() { @@ -69,28 +73,36 @@ const BaseWidgetMixin = { } }, render() { - const listValueTransformations = [...this.listValueTransformations]; - listValueTransformations.push(this.renderTemplate.bind(this)); - - const nextProcessor = listValueTransformations.shift(); - nextProcessor(this.value, listValueTransformations); + const listValueTransformationsCopy = + this.listValueTransformations.deepCopy(); + listValueTransformationsCopy.attach( + this.renderTemplate.bind(this), + 'BaseWidgetMixin:renderTemplate', + ); + const nextProcessor = listValueTransformationsCopy.shift(); + nextProcessor(this.value, listValueTransformationsCopy); // Callbacks - const listCallbacks = [...this.listCallbacks]; - if (listCallbacks.length) { - const nextCallback = listCallbacks.shift(); - nextCallback(this.value, listCallbacks); + const listCallbacksCopy = this.listCallbacks.deepCopy(); + const nextCallback = listCallbacksCopy.shift(); + if (nextCallback) { + nextCallback(this.value, listCallbacksCopy); } - this.element.dispatchEvent(new CustomEvent('widgetRendered', { bubbles: true })); + this.element.dispatchEvent( + new CustomEvent('widgetRendered', { bubbles: true }), + ); }, renderTemplate(value: string) { const template: Template = this.template(value, { ...this.listAttributes }); - const listTemplateAdditions = [...this.listTemplateAdditions]; - listTemplateAdditions.push(this.templateToDOM.bind(this)); + const listTemplateAdditionsCopy = this.listTemplateAdditions.deepCopy(); + listTemplateAdditionsCopy.attach( + this.templateToDOM.bind(this), + 'BaseWidgetMixin:templateToDOM', + ); - const nextProcessor = listTemplateAdditions.shift(); - nextProcessor(template, listTemplateAdditions); + const nextProcessor = listTemplateAdditionsCopy.shift(); + nextProcessor(template, listTemplateAdditionsCopy); }, templateToDOM(template: Template) { render(template, this.element); @@ -106,9 +118,7 @@ const BaseWidgetMixin = { }, update() { this.planRender(); - } -} + }, +}; -export { - BaseWidgetMixin -} \ No newline at end of file +export { BaseWidgetMixin }; diff --git a/src/new-widgets/callbackMixins/autocompletionMixin.ts b/src/new-widgets/callbackMixins/autocompletionMixin.ts index 2bf8f68f7ff6f0107d7317964073cef728e0db04..ac7c156a620490a9d02c5b7c924db95877b5498f 100644 --- a/src/new-widgets/callbackMixins/autocompletionMixin.ts +++ b/src/new-widgets/callbackMixins/autocompletionMixin.ts @@ -1,6 +1,11 @@ -import { fuzzyCompare, importInlineCSS } from '../../libs/helpers'; import SlimSelect from 'slim-select'; -import { TranslationMixin } from '../../mixins/translationMixin'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import { + asyncQuerySelector, + fuzzyCompare, + importInlineCSS, +} from '../../libs/helpers.ts'; +import { TranslationMixin } from '../../mixins/translationMixin.ts'; const AutocompletionMixin = { name: 'autocompletion-mixin', @@ -11,83 +16,73 @@ const AutocompletionMixin = { default: null, callback: function (newValue: string) { this.addToAttributes(newValue, 'searchText'); - } + }, }, searchPlaceholder: { type: String, default: null, callback: function (newValue: string) { this.addToAttributes(newValue, 'searchPlaceholder'); - } + }, }, }, initialState: { slimSelect: null, - mutationObserver: null + mutationObserver: null, }, created() { - importInlineCSS('slimselect', () => import('./slimselect.css?inline')) + importInlineCSS( + 'slimselect-base', + () => import('slim-select/styles?inline'), + ); + importInlineCSS( + 'slimselect-local', + () => import('./slimselect.css?inline'), + ); this.slimSelect = null; this.addToAttributes(true, 'autocomplete'); - this.listCallbacks.push(this.addCallback.bind(this)); + this.listCallbacks.attach( + this.addCallback.bind(this), + 'AutocompletionMixin:addCallback', + ); }, detached() { if (this.slimSelect) this.slimSelect.destroy(); if (this.mutationObserver) this.mutationObserver.disconnect(); }, - addCallback(value: string, listCallbacks: Function[]) { + addCallback(value: string, listCallbacks: PostProcessorRegistry) { if (this.slimSelect) return; - let select = this.element.querySelector('select'); - if (select) { + asyncQuerySelector('select:has(option)', this.element).then(select => { this.initSlimSelect(select); - } else { - // if no select available, wait for one and init slimSelect - new MutationObserver((_m, observer) => { - const select = this.element.querySelector('select'); - if (select) { - this.initSlimSelect(select); - observer.disconnect(); // then disconnect mutationObserver - } - }).observe(this.element, { - childList: true, - characterData: true, - subtree: true, - }); - } + }); const nextProcessor = listCallbacks.shift(); if (nextProcessor) nextProcessor(value, listCallbacks); }, - initSlimSelect(select: Element) { - const slimSelect = new SlimSelect({ select }); - this.slimSelect = slimSelect; - select.addEventListener('change', () => { - this.slimSelect.render(); - this.element.dispatchEvent(new Event('input', { bubbles: true })); + async initSlimSelect(select: Element) { + await new Promise(resolve => setTimeout(resolve, 500)); + const slimSelect = new SlimSelect({ + select, + settings: { + placeholderText: + this.placeholder || this.t('autocompletion.placeholder'), + searchText: this.searchText || this.t('autocompletion.searchText'), + searchPlaceholder: + this.searchPlaceholder || this.t('autocompletion.searchPlaceholder'), + contentLocation: this.element, + }, + events: { + searchFilter: (option, filterValue) => + fuzzyCompare(option.text, filterValue), + }, }); - this.element.addEventListener('input', (e:Event) => { - if(e.target !== this.element) { + this.slimSelect = slimSelect; + this.element.addEventListener('input', (e: Event) => { + if (e.target !== this.element) { // avoid update search result when search in slimSelect suggestions e.stopPropagation(); } }); - - // when data changes, re-build slimSelect - if (this.mutationObserver) this.mutationObserver.disconnect(); - this.mutationObserver = new MutationObserver(() => { - this.slimSelect.destroy(); - this.slimSelect = new SlimSelect({ - select, - placeholder: this.placeholder || this.t("autocompletion.placeholder"), - searchText: this.searchText || this.t("autocompletion.searchText"), - searchPlaceholder: this.searchPlaceholder || this.t("autocompletion.searchPlaceholder"), - searchFilter: (option, filterValue) => fuzzyCompare(option.text, filterValue), - }); - }).observe(select, { - childList: true, - characterData: true, - subtree: true, - }); }, }; diff --git a/src/new-widgets/callbackMixins/index.ts b/src/new-widgets/callbackMixins/index.ts index eca6ff7a57ee688c1923592b461143cdb639f423..162a8adaa57c61513a78ec187d3637af45e7848e 100644 --- a/src/new-widgets/callbackMixins/index.ts +++ b/src/new-widgets/callbackMixins/index.ts @@ -1,13 +1,9 @@ -import { AutocompletionMixin } from './autocompletionMixin'; -import { RichtextMixin } from './richtextMixin'; +import { AutocompletionMixin } from './autocompletionMixin.ts'; +import { RichtextMixin } from './richtextMixin.ts'; const callbackDirectory = { autocompletion: AutocompletionMixin, richtext: RichtextMixin, -} +}; -export { - callbackDirectory, - AutocompletionMixin, - RichtextMixin, -} +export { callbackDirectory, AutocompletionMixin, RichtextMixin }; diff --git a/src/new-widgets/callbackMixins/richtextMixin.ts b/src/new-widgets/callbackMixins/richtextMixin.ts index ae044c756c9955463e69429dabb59fb549ff773e..59afdcc1f65d66fd2cdb9799ffefacdd369d70b4 100644 --- a/src/new-widgets/callbackMixins/richtextMixin.ts +++ b/src/new-widgets/callbackMixins/richtextMixin.ts @@ -1,6 +1,7 @@ +import MarkdownIt from 'markdown-it'; import Quill from 'quill'; -import markdownToDelta from "markdown-to-quill-delta"; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.js'; import { importInlineCSS } from '../../libs/helpers.js'; const RichtextMixin = { @@ -10,54 +11,69 @@ const RichtextMixin = { }, created() { - importInlineCSS('quill', () => import('quill/dist/quill.snow.css?inline')) + importInlineCSS('quill', () => import('quill/dist/quill.snow.css?inline')); this.quill = null; - this.listCallbacks.push(this.addCallback.bind(this)); + this.listCallbacks.attach( + this.addCallback.bind(this), + 'RichtextMixin:addCallback', + ); }, getPlaceHolderValue() { - return this.element.hasAttribute('placeholder') ? this.element.getAttribute('placeholder') : ''; + return this.element.hasAttribute('placeholder') + ? this.element.getAttribute('placeholder') + : ''; }, - addCallback(value: string, listCallbacks: Function[]) { + addCallback(value: string, listCallbacks: PostProcessorRegistry) { if (this.quill == null) { - var toolbarOptions = [ + const toolbarOptions = [ ['bold', 'italic'], ['blockquote'], - [{ 'header': [1, 2, 3, 4, 5, 6, false] }], - [{ 'list': 'ordered' }, { 'list': 'bullet' }], + [{ header: [1, 2, 3, 4, 5, 6, false] }], + [{ list: 'ordered' }, { list: 'bullet' }], ['link'], - ['clean'] + ['clean'], ]; - const richtext = this.element.querySelector('[data-richtext]'); - this.quill = new Quill( - richtext, - { - modules: { toolbar: toolbarOptions }, - placeholder: this.getPlaceHolderValue(), - theme: 'snow' - } - ); + const richtext = this.element.querySelector( + '[data-richtext]', + ) as HTMLElement; + this.quill = new Quill(richtext, { + modules: { toolbar: toolbarOptions }, + placeholder: this.getPlaceHolderValue(), + theme: 'snow', + }); } - const ops = markdownToDelta(this.value); - this.quill.setContents(ops); + const mdParser = new MarkdownIt({ + html: true, + }); + + const formattedValue = this.value.replace(/\r\n|\n/g, '<br>'); + const html = mdParser.render(formattedValue); // Convert Markdown to HTML + const delta = this.quill.clipboard.convert({ html }); // Convert HTML to Delta + + this.quill.setContents(delta); if (this.isRequired()) { - this.createHiddenRequiredInput() - this.quill.on('text-change', this.onTextChange.bind(this)) + this.createHiddenRequiredInput(); + this.quill.on('text-change', this.onTextChange.bind(this)); } const nextProcessor = listCallbacks.shift(); if (nextProcessor) nextProcessor(value, listCallbacks); }, isRequired() { - return Array.from(this.element.attributes).some(attr => (attr as Attr).name === 'required') + return Array.from(this.element.attributes).some( + attr => (attr as Attr).name === 'required', + ); }, createHiddenRequiredInput() { const attributeName = this.getAttributeValue('name'); - this.hiddenInput = document.querySelector(`input[name="${attributeName + '-hidden'}"]`) as HTMLInputElement; + this.hiddenInput = document.querySelector( + `input[name="${`${attributeName}-hidden`}"]`, + ) as HTMLInputElement; if (!this.hiddenInput) { - this.hiddenInput = this.createHiddenInput(attributeName + '-hidden'); + this.hiddenInput = this.createHiddenInput(`${attributeName}-hidden`); this.element.appendChild(this.hiddenInput); this.addInvalidEventListener(); } @@ -73,14 +89,18 @@ const RichtextMixin = { return input; }, getAttributeValue(attributeName: string): string { - const attribute = Array.from(this.element.attributes).find(attr => (attr as Attr).name === attributeName) as Attr; + const attribute = Array.from(this.element.attributes).find( + attr => (attr as Attr).name === attributeName, + ) as Attr; return attribute ? attribute.value : ''; }, displayCustomErrorMessage(message: string) { const richtext = this.element.querySelector('[data-richtext]'); if (richtext) { - let errorMessageElement = richtext.querySelector('.required-error-message') as HTMLDivElement; + let errorMessageElement = richtext.querySelector( + '.required-error-message', + ) as HTMLDivElement; if (!errorMessageElement) { errorMessageElement = document.createElement('div'); @@ -93,25 +113,24 @@ const RichtextMixin = { } }, addInvalidEventListener() { - this.hiddenInput.addEventListener("invalid", (e) => { + (this.hiddenInput as HTMLInputElement).addEventListener('invalid', e => { e.preventDefault(); this.displayCustomErrorMessage('Please fill out this field.'); }); }, onTextChange() { - this.hiddenInput.value = this.quill.getText(); + (this.hiddenInput as HTMLInputElement).value = this.quill.getText(); this.removeErrorMessageAndStyling(); }, removeErrorMessageAndStyling() { // Remove any previously displayed error message and error styling const richtext = this.element.querySelector('[data-richtext]'); - let errorMessageElement = richtext.querySelector('.required-error-message') as HTMLDivElement; - if (errorMessageElement) - errorMessageElement.remove() + const errorMessageElement = richtext.querySelector( + '.required-error-message', + ) as HTMLDivElement; + if (errorMessageElement) errorMessageElement.remove(); richtext.classList.remove('error-border-richtext'); }, -} +}; -export { - RichtextMixin -} \ No newline at end of file +export { RichtextMixin }; diff --git a/src/new-widgets/callbackMixins/slimselect.css b/src/new-widgets/callbackMixins/slimselect.css index 3a795bad302fb57f80a51fbe11f0324172997b68..07a93c5308c9c1c7430f11b07b9be2d814ce3a59 100644 --- a/src/new-widgets/callbackMixins/slimselect.css +++ b/src/new-widgets/callbackMixins/slimselect.css @@ -1,2 +1,339 @@ -.ss-main{position:relative;display:inline-block;user-select:none;color:#666;width:100%}.ss-main .ss-single-selected{display:flex;cursor:pointer;width:100%;height:30px;padding:6px;border:1px solid #dcdee2;border-radius:4px;background-color:#fff;outline:0;box-sizing:border-box;transition:background-color .2s}.ss-main .ss-single-selected.ss-disabled{background-color:#dcdee2;cursor:not-allowed}.ss-main .ss-single-selected.ss-open-above{border-top-left-radius:0px;border-top-right-radius:0px}.ss-main .ss-single-selected.ss-open-below{border-bottom-left-radius:0px;border-bottom-right-radius:0px}.ss-main .ss-single-selected .placeholder{display:flex;flex:1 1 100%;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left;width:calc(100% - 30px);line-height:1em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ss-main .ss-single-selected .placeholder *{display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:auto}.ss-main .ss-single-selected .placeholder .ss-disabled{color:#dedede}.ss-main .ss-single-selected .ss-deselect{display:flex;align-items:center;justify-content:flex-end;flex:0 1 auto;margin:0 6px 0 6px;font-weight:bold}.ss-main .ss-single-selected .ss-deselect.ss-hide{display:none}.ss-main .ss-single-selected .ss-arrow{display:flex;align-items:center;justify-content:flex-end;flex:0 1 auto;margin:0 6px 0 6px}.ss-main .ss-single-selected .ss-arrow span{border:solid #666;border-width:0 2px 2px 0;display:inline-block;padding:3px;transition:transform .2s, margin .2s}.ss-main .ss-single-selected .ss-arrow span.arrow-up{transform:rotate(-135deg);margin:3px 0 0 0}.ss-main .ss-single-selected .ss-arrow span.arrow-down{transform:rotate(45deg);margin:-3px 0 0 0}.ss-main .ss-multi-selected{display:flex;flex-direction:row;cursor:pointer;min-height:30px;width:100%;padding:0 0 0 3px;border:1px solid #dcdee2;border-radius:4px;background-color:#fff;outline:0;box-sizing:border-box;transition:background-color .2s}.ss-main .ss-multi-selected.ss-disabled{background-color:#dcdee2;cursor:not-allowed}.ss-main .ss-multi-selected.ss-disabled .ss-values .ss-disabled{color:#666}.ss-main .ss-multi-selected.ss-disabled .ss-values .ss-value .ss-value-delete{cursor:not-allowed}.ss-main .ss-multi-selected.ss-open-above{border-top-left-radius:0px;border-top-right-radius:0px}.ss-main .ss-multi-selected.ss-open-below{border-bottom-left-radius:0px;border-bottom-right-radius:0px}.ss-main .ss-multi-selected .ss-values{display:flex;flex-wrap:wrap;justify-content:flex-start;flex:1 1 100%;width:calc(100% - 30px)}.ss-main .ss-multi-selected .ss-values .ss-disabled{display:flex;padding:4px 5px;margin:2px 0px;line-height:1em;align-items:center;width:100%;color:#dedede;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@keyframes scaleIn{0%{transform:scale(0);opacity:0}100%{transform:scale(1);opacity:1}}@keyframes scaleOut{0%{transform:scale(1);opacity:1}100%{transform:scale(0);opacity:0}}.ss-main .ss-multi-selected .ss-values .ss-value{display:flex;user-select:none;align-items:center;font-size:12px;padding:3px 5px;margin:3px 5px 3px 0px;color:#fff;background-color:#5897fb;border-radius:4px;animation-name:scaleIn;animation-duration:.2s;animation-timing-function:ease-out;animation-fill-mode:both}.ss-main .ss-multi-selected .ss-values .ss-value.ss-out{animation-name:scaleOut;animation-duration:.2s;animation-timing-function:ease-out}.ss-main .ss-multi-selected .ss-values .ss-value .ss-value-delete{margin:0 0 0 5px;cursor:pointer}.ss-main .ss-multi-selected .ss-add{display:flex;flex:0 1 3px;margin:9px 12px 0 5px}.ss-main .ss-multi-selected .ss-add .ss-plus{display:flex;justify-content:center;align-items:center;background:#666;position:relative;height:10px;width:2px;transition:transform .2s}.ss-main .ss-multi-selected .ss-add .ss-plus:after{background:#666;content:"";position:absolute;height:2px;width:10px;left:-4px;top:4px}.ss-main .ss-multi-selected .ss-add .ss-plus.ss-cross{transform:rotate(45deg)}.ss-content{position:absolute;width:100%;margin:-1px 0 0 0;box-sizing:border-box;border:solid 1px #dcdee2;z-index:1010;background-color:#fff;transform-origin:center top;transition:transform .2s, opacity .2s;opacity:0;transform:scaleY(0)}.ss-content.ss-open{display:block;opacity:1;transform:scaleY(1)}.ss-content .ss-search{display:flex;flex-direction:row;padding:8px 8px 6px 8px}.ss-content .ss-search.ss-hide{height:0px;opacity:0;padding:0px 0px 0px 0px;margin:0px 0px 0px 0px}.ss-content .ss-search.ss-hide input{height:0px;opacity:0;padding:0px 0px 0px 0px;margin:0px 0px 0px 0px}.ss-content .ss-search input{display:inline-flex;font-size:inherit;line-height:inherit;flex:1 1 auto;width:100%;min-width:0px;height:30px;padding:6px 8px;margin:0;border:1px solid #dcdee2;border-radius:4px;background-color:#fff;outline:0;text-align:left;box-sizing:border-box;-webkit-box-sizing:border-box;-webkit-appearance:textfield}.ss-content .ss-search input::placeholder{color:#8a8a8a;vertical-align:middle}.ss-content .ss-search input:focus{box-shadow:0 0 5px #5897fb}.ss-content .ss-search .ss-addable{display:inline-flex;justify-content:center;align-items:center;cursor:pointer;font-size:22px;font-weight:bold;flex:0 0 30px;height:30px;margin:0 0 0 8px;border:1px solid #dcdee2;border-radius:4px;box-sizing:border-box}.ss-content .ss-addable{padding-top:0px}.ss-content .ss-list{max-height:200px;overflow-x:hidden;overflow-y:auto;text-align:left}.ss-content .ss-list .ss-optgroup .ss-optgroup-label{padding:6px 10px 6px 10px;font-weight:bold}.ss-content .ss-list .ss-optgroup .ss-option{padding:6px 6px 6px 25px}.ss-content .ss-list .ss-optgroup-label-selectable{cursor:pointer}.ss-content .ss-list .ss-optgroup-label-selectable:hover{color:#fff;background-color:#5897fb}.ss-content .ss-list .ss-option{padding:6px 10px 6px 10px;cursor:pointer;user-select:none}.ss-content .ss-list .ss-option *{display:inline-block}.ss-content .ss-list .ss-option:hover,.ss-content .ss-list .ss-option.ss-highlighted{color:#fff;background-color:#5897fb}.ss-content .ss-list .ss-option.ss-disabled{cursor:not-allowed;color:#dedede;background-color:#fff}.ss-content .ss-list .ss-option:not(.ss-disabled).ss-option-selected{color:#666;background-color:rgba(88,151,251,0.1)}.ss-content .ss-list .ss-option.ss-hide{display:none}.ss-content .ss-list .ss-option .ss-search-highlight{background-color:#fffb8c} - +.ss-main { + position: relative; + display: inline-block; + user-select: none; + color: #666; + width: 100%; +} +.ss-main .ss-single-selected { + display: flex; + cursor: pointer; + width: 100%; + height: 30px; + padding: 6px; + border: 1px solid #dcdee2; + border-radius: 4px; + background-color: #fff; + outline: 0; + box-sizing: border-box; + transition: background-color .2s; +} +.ss-main .ss-single-selected.ss-disabled { + background-color: #dcdee2; + cursor: not-allowed; +} +.ss-main .ss-single-selected.ss-open-above { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} +.ss-main .ss-single-selected.ss-open-below { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; +} +.ss-main .ss-single-selected .placeholder { + display: flex; + flex: 1 1 100%; + align-items: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + text-align: left; + width: calc(100% - 30px); + line-height: 1em; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.ss-main .ss-single-selected .placeholder * { + display: flex; + align-items: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: auto; +} +.ss-main .ss-single-selected .placeholder .ss-disabled { + color: #dedede; +} +.ss-main .ss-single-selected .ss-deselect { + display: flex; + align-items: center; + justify-content: flex-end; + flex: 0 1 auto; + margin: 0 6px 0 6px; + font-weight: bold; +} +.ss-main .ss-single-selected .ss-deselect.ss-hide { + display: none; +} +.ss-main .ss-single-selected .ss-arrow { + display: flex; + align-items: center; + justify-content: flex-end; + flex: 0 1 auto; + margin: 0 6px 0 6px; +} +.ss-main .ss-single-selected .ss-arrow span { + border: solid #666; + border-width: 0 2px 2px 0; + display: inline-block; + padding: 3px; + transition: transform .2s, margin .2s; +} +.ss-main .ss-single-selected .ss-arrow span.arrow-up { + transform: rotate(-135deg); + margin: 3px 0 0 0; +} +.ss-main .ss-single-selected .ss-arrow span.arrow-down { + transform: rotate(45deg); + margin: -3px 0 0 0; +} +.ss-main .ss-multi-selected { + display: flex; + flex-direction: row; + cursor: pointer; + min-height: 30px; + width: 100%; + padding: 0 0 0 3px; + border: 1px solid #dcdee2; + border-radius: 4px; + background-color: #fff; + outline: 0; + box-sizing: border-box; + transition: background-color .2s; +} +.ss-main .ss-multi-selected.ss-disabled { + background-color: #dcdee2; + cursor: not-allowed; +} +.ss-main .ss-multi-selected.ss-disabled .ss-values .ss-disabled { + color: #666; +} +.ss-main .ss-multi-selected.ss-disabled .ss-values .ss-value .ss-value-delete { + cursor: not-allowed; +} +.ss-main .ss-multi-selected.ss-open-above { + border-top-left-radius: 0px; + border-top-right-radius: 0px; +} +.ss-main .ss-multi-selected.ss-open-below { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; +} +.ss-main .ss-multi-selected .ss-values { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + flex: 1 1 100%; + width: calc(100% - 30px); +} +.ss-main .ss-multi-selected .ss-values .ss-disabled { + display: flex; + padding: 4px 5px; + margin: 2px 0px; + line-height: 1em; + align-items: center; + width: 100%; + color: #dedede; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +@keyframes scaleIn { + 0% { + transform: scale(0); + opacity: 0; + } + 100% { + transform: scale(1); + opacity: 1; + } +} +@keyframes scaleOut { + 0% { + transform: scale(1); + opacity: 1; + } + 100% { + transform: scale(0); + opacity: 0; + } +} +.ss-main .ss-multi-selected .ss-values .ss-value { + display: flex; + user-select: none; + align-items: center; + font-size: 12px; + padding: 3px 5px; + margin: 3px 5px 3px 0px; + color: #fff; + background-color: #5897fb; + border-radius: 4px; + animation-name: scaleIn; + animation-duration: .2s; + animation-timing-function: ease-out; + animation-fill-mode: both; +} +.ss-main .ss-multi-selected .ss-values .ss-value.ss-out { + animation-name: scaleOut; + animation-duration: .2s; + animation-timing-function: ease-out; +} +.ss-main .ss-multi-selected .ss-values .ss-value .ss-value-delete { + margin: 0 0 0 5px; + cursor: pointer; +} +.ss-main .ss-multi-selected .ss-add { + display: flex; + flex: 0 1 3px; + margin: 9px 12px 0 5px; +} +.ss-main .ss-multi-selected .ss-add .ss-plus { + display: flex; + justify-content: center; + align-items: center; + background: #666; + position: relative; + height: 10px; + width: 2px; + transition: transform .2s; +} +.ss-main .ss-multi-selected .ss-add .ss-plus:after { + background: #666; + content: ""; + position: absolute; + height: 2px; + width: 10px; + left: -4px; + top: 4px; +} +.ss-main .ss-multi-selected .ss-add .ss-plus.ss-cross { + transform: rotate(45deg); +} +.ss-content { + position: absolute; + width: 100%; + margin: -1px 0 0 0; + box-sizing: border-box; + border: solid 1px #dcdee2; + z-index: 1010; + background-color: #fff; + transform-origin: center top; + transition: transform .2s, opacity .2s; + opacity: 0; + transform: scaleY(0); +} +.ss-content.ss-open { + display: block; + opacity: 1; + transform: scaleY(1); +} +.ss-content .ss-search { + display: flex; + flex-direction: row; + padding: 8px 8px 6px 8px; +} +.ss-content .ss-search.ss-hide { + height: 0px; + opacity: 0; + padding: 0px 0px 0px 0px; + margin: 0px 0px 0px 0px; +} +.ss-content .ss-search.ss-hide input { + height: 0px; + opacity: 0; + padding: 0px 0px 0px 0px; + margin: 0px 0px 0px 0px; +} +.ss-content .ss-search input { + display: inline-flex; + font-size: inherit; + line-height: inherit; + flex: 1 1 auto; + width: 100%; + min-width: 0px; + height: 30px; + padding: 6px 8px; + margin: 0; + border: 1px solid #dcdee2; + border-radius: 4px; + background-color: #fff; + outline: 0; + text-align: left; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -webkit-appearance: textfield; +} +.ss-content .ss-search input::placeholder { + color: #8a8a8a; + vertical-align: middle; +} +.ss-content .ss-search input:focus { + box-shadow: 0 0 5px #5897fb; +} +.ss-content .ss-search .ss-addable { + display: inline-flex; + justify-content: center; + align-items: center; + cursor: pointer; + font-size: 22px; + font-weight: bold; + flex: 0 0 30px; + height: 30px; + margin: 0 0 0 8px; + border: 1px solid #dcdee2; + border-radius: 4px; + box-sizing: border-box; +} +.ss-content .ss-addable { + padding-top: 0px; +} +.ss-content .ss-list { + max-height: 200px; + overflow-x: hidden; + overflow-y: auto; + text-align: left; +} +.ss-content .ss-list .ss-optgroup .ss-optgroup-label { + padding: 6px 10px 6px 10px; + font-weight: bold; +} +.ss-content .ss-list .ss-optgroup .ss-option { + padding: 6px 6px 6px 25px; +} +.ss-content .ss-list .ss-optgroup-label-selectable { + cursor: pointer; +} +.ss-content .ss-list .ss-optgroup-label-selectable:hover { + color: #fff; + background-color: #5897fb; +} +.ss-content .ss-list .ss-option { + padding: 6px 10px 6px 10px; + cursor: pointer; + user-select: none; +} +.ss-content .ss-list .ss-option * { + display: inline-block; +} +.ss-content .ss-list .ss-option:hover, +.ss-content .ss-list .ss-option.ss-highlighted { + color: #fff; + background-color: #5897fb; +} +.ss-content .ss-list .ss-option.ss-disabled { + cursor: not-allowed; + color: #dedede; + background-color: #fff; +} +.ss-content .ss-list .ss-option:not(.ss-disabled).ss-option-selected { + color: #666; + background-color: rgba(88, 151, 251, 0.1); +} +.ss-content .ss-list .ss-option.ss-hide { + display: none; +} +.ss-content .ss-list .ss-option .ss-search-highlight { + background-color: #fffb8c; +} diff --git a/src/new-widgets/interfaces.ts b/src/new-widgets/interfaces.ts index e638fc9a090cb18b4fb4a1eb1da216e183032da1..01e77e40a8c5d63710202e8e68a4b6126c54da5a 100644 --- a/src/new-widgets/interfaces.ts +++ b/src/new-widgets/interfaces.ts @@ -1,11 +1,11 @@ -import type { MixinStaticInterface } from '../libs/interfaces'; +import type { MixinStaticInterface } from '../libs/interfaces.ts'; export interface Template { - template: Function - dependencies: MixinStaticInterface[] + template: Function; + dependencies: MixinStaticInterface[]; } export interface WidgetMixinsInterface { - templateMixin: Template - mixins: MixinStaticInterface[] -} \ No newline at end of file + templateMixin: Template; + mixins: MixinStaticInterface[]; +} diff --git a/src/new-widgets/new-widget-factory.ts b/src/new-widgets/new-widget-factory.ts index a3dda0d0d6a99e2cb865f9d14c3a273efd2bfbf6..4f8a4ac403ed5d9b6b3dd4da8dc6286acce3c09f 100644 --- a/src/new-widgets/new-widget-factory.ts +++ b/src/new-widgets/new-widget-factory.ts @@ -1,12 +1,18 @@ -import { Sib } from '../libs/Sib'; -import { BaseWidgetMixin } from './baseWidgetMixin'; -import type { Template, WidgetMixinsInterface } from './interfaces'; -import type { MixinStaticInterface } from '../libs/interfaces'; -import { defaultTemplates, displayTemplates, formTemplates, setTemplates, groupTemplates } from './templates/index'; -import { valueTransformationDirectory } from './valueTransformationMixins/index'; -import { templateAdditionDirectory } from './templateAdditionMixins/index'; -import { attributeDirectory } from './attributeMixins/index'; -import { callbackDirectory } from './callbackMixins/index'; +import { Sib } from '../libs/Sib.ts'; +import type { MixinStaticInterface } from '../libs/interfaces.ts'; +import { attributeDirectory } from './attributeMixins/index.ts'; +import { BaseWidgetMixin } from './baseWidgetMixin.ts'; +import { callbackDirectory } from './callbackMixins/index.ts'; +import type { Template, WidgetMixinsInterface } from './interfaces.ts'; +import { templateAdditionDirectory } from './templateAdditionMixins/index.ts'; +import { + defaultTemplates, + displayTemplates, + formTemplates, + groupTemplates, + setTemplates, +} from './templates/index.ts'; +import { valueTransformationDirectory } from './valueTransformationMixins/index.ts'; const valueTransformationKeys = Object.keys(valueTransformationDirectory); const attributeKeys = Object.keys(attributeDirectory); @@ -19,13 +25,16 @@ const callbackKeys = Object.keys(callbackDirectory); */ export const newWidgetFactory = (tagName: string) => { let widgetMixins: WidgetMixinsInterface; - try { widgetMixins = getWidgetMixins(tagName) } // get mixins and template - catch (e) { + try { + widgetMixins = getWidgetMixins(tagName); + } catch (e) { + // get mixins and template console.error(e); return; } - const newWidget = { // compose widget + const newWidget = { + // compose widget name: tagName, use: [ ...widgetMixins.mixins, @@ -93,8 +102,8 @@ function getWidgetMixins(tagName: string): WidgetMixinsInterface { ...templateAdditions, ...(template.dependencies || []), ...callbacks, - ] - } + ], + }; } // create default widgets @@ -102,4 +111,4 @@ newWidgetFactory('solid-form-dropdown'); newWidgetFactory('solid-form-multicheckbox'); newWidgetFactory('solid-form-file-label'); newWidgetFactory('solid-action'); -newWidgetFactory('solid-group-default'); \ No newline at end of file +newWidgetFactory('solid-group-default'); diff --git a/src/new-widgets/templateAdditionMixins/addableMixin.ts b/src/new-widgets/templateAdditionMixins/addableMixin.ts index 5c396a8ed9d53f83ed0b458133d781991cbdf9e3..fb1c571d23b9a424ee54adc524eb513a6c5b8091 100644 --- a/src/new-widgets/templateAdditionMixins/addableMixin.ts +++ b/src/new-widgets/templateAdditionMixins/addableMixin.ts @@ -1,20 +1,32 @@ -import { spread } from '../../libs/lit-helpers'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import { spread } from '../../libs/lit-helpers.ts'; -import { html } from 'lit-html'; +import { html } from 'lit'; const AddableMixin = { name: 'addable-mixin', created() { - this.listTemplateAdditions.push(this.addableValue.bind(this)); + this.listTemplateAdditions.attach( + this.addableValue.bind(this), + 'AddableMixin:addableValue', + ); }, getAddableAttributes() { - const addableAttr = (Array.from(this.element.attributes) as Attr[]).filter((a: Attr) => a.name.startsWith('addable-')); + const addableAttr = (Array.from(this.element.attributes) as Attr[]).filter( + (a: Attr) => a.name.startsWith('addable-'), + ); const cleanAddableAttr: { [key: string]: string } = {}; - for (let attr of addableAttr) cleanAddableAttr[attr.name.replace('addable-', '')] = attr.value; - if (!cleanAddableAttr.hasOwnProperty('data-src')) cleanAddableAttr['data-src'] = this.range; + for (const attr of addableAttr) + cleanAddableAttr[attr.name.replace('addable-', '')] = attr.value; + if (!Object.hasOwn(cleanAddableAttr, 'data-src')) + cleanAddableAttr['data-src'] = this.range; return cleanAddableAttr; }, - addableValue(template, listTemplateAdditions: Function[], attributes: object) { + addableValue( + template, + listTemplateAdditions: PostProcessorRegistry, + attributes: object, + ) { const addables = this.getAddableAttributes(attributes); const newTemplate = html` ${template} @@ -24,9 +36,7 @@ const AddableMixin = { const nextProcessor = listTemplateAdditions.shift(); if (nextProcessor) nextProcessor(newTemplate, listTemplateAdditions); - } -} + }, +}; -export { - AddableMixin -} \ No newline at end of file +export { AddableMixin }; diff --git a/src/new-widgets/templateAdditionMixins/index.ts b/src/new-widgets/templateAdditionMixins/index.ts index ad7207675746851f952d07e5c3e97a632e12fa32..8e874eeee853c914432d9932d2c8d34a1c183c7b 100644 --- a/src/new-widgets/templateAdditionMixins/index.ts +++ b/src/new-widgets/templateAdditionMixins/index.ts @@ -1,6 +1,6 @@ -import { LabelMixin } from './labelMixin'; -import { LabelLastMixin } from './labelLastMixin'; -import { AddableMixin } from './addableMixin'; +import { AddableMixin } from './addableMixin.ts'; +import { LabelLastMixin } from './labelLastMixin.ts'; +import { LabelMixin } from './labelMixin.ts'; /** * DOM Additions @@ -9,11 +9,6 @@ const templateAdditionDirectory = { label: LabelMixin, labellast: LabelLastMixin, addable: AddableMixin, -} +}; -export { - templateAdditionDirectory, - LabelMixin, - LabelLastMixin, - AddableMixin, -} +export { templateAdditionDirectory, LabelMixin, LabelLastMixin, AddableMixin }; diff --git a/src/new-widgets/templateAdditionMixins/labelLastMixin.ts b/src/new-widgets/templateAdditionMixins/labelLastMixin.ts index b917a6c5def8609b2c7cd6e31e35857392580b33..aabea616ca3f7d5f34a9b84fb3b77e650c5535a4 100644 --- a/src/new-widgets/templateAdditionMixins/labelLastMixin.ts +++ b/src/new-widgets/templateAdditionMixins/labelLastMixin.ts @@ -1,21 +1,20 @@ -import { html } from 'lit-html'; +import { html } from 'lit'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const LabelLastMixin = { name: 'label-last-mixin', created() { - this.listTemplateAdditions.push(this.addLabelLast.bind(this)); + this.listTemplateAdditions.attach( + this.addLabelLast.bind(this), + 'LabelLastMixin:addLabelLast', + ); }, - addLabelLast(template, listTemplateAdditions: Function[]) { - const newTemplate = html` - ${template} - <label>${this.label || this.name}</label> - `; + addLabelLast(template, listTemplateAdditions: PostProcessorRegistry) { + const newTemplate = html`${template}<label>${this.label || this.name}</label>`; const nextProcessor = listTemplateAdditions.shift(); - if(nextProcessor) nextProcessor(newTemplate, listTemplateAdditions); - } -} + if (nextProcessor) nextProcessor(newTemplate, listTemplateAdditions); + }, +}; -export { - LabelLastMixin -} \ No newline at end of file +export { LabelLastMixin }; diff --git a/src/new-widgets/templateAdditionMixins/labelMixin.ts b/src/new-widgets/templateAdditionMixins/labelMixin.ts index 7230dd454bdcc6427b6875552e52d297cce8e023..d607425b398b5aed2e03d374fe8bf5092f954a90 100644 --- a/src/new-widgets/templateAdditionMixins/labelMixin.ts +++ b/src/new-widgets/templateAdditionMixins/labelMixin.ts @@ -1,23 +1,22 @@ -import { html } from 'lit-html'; -import { uniqID } from '../../libs/helpers'; +import { html } from 'lit'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import { uniqID } from '../../libs/helpers.ts'; const LabelMixin = { name: 'label-mixin', created() { - this.listAttributes['id'] = uniqID(); - this.listTemplateAdditions.push(this.addLabel.bind(this)); + this.listAttributes.id = uniqID(); + this.listTemplateAdditions.attach( + this.addLabel.bind(this), + 'LabelMixin:addLabel', + ); }, - addLabel(template, listTemplateAdditions: Function[]) { - const newTemplate = html` - <label for="${this.listAttributes['id']}">${this.label || this.name}</label> - ${template} - `; + addLabel(template, listTemplateAdditions: PostProcessorRegistry) { + const newTemplate = html`<label for="${this.listAttributes.id}">${this.label || this.name}</label>${template}`; const nextProcessor = listTemplateAdditions.shift(); - if(nextProcessor) nextProcessor(newTemplate, listTemplateAdditions); - } -} + if (nextProcessor) nextProcessor(newTemplate, listTemplateAdditions); + }, +}; -export { - LabelMixin -} \ No newline at end of file +export { LabelMixin }; diff --git a/src/new-widgets/templates/defaultTemplatesDirectory.ts b/src/new-widgets/templates/defaultTemplatesDirectory.ts index 53cd49932724f73edd8c87f28e4ee9b1d0ad5fdc..1bcdbed6db21812f3eef2180d6fb739e95fdbc64 100644 --- a/src/new-widgets/templates/defaultTemplatesDirectory.ts +++ b/src/new-widgets/templates/defaultTemplatesDirectory.ts @@ -1,6 +1,6 @@ -import { html } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; -import { LinkTextMixin } from '../templatesDependencies/linkTextMixin'; +import { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { LinkTextMixin } from '../templatesDependencies/linkTextMixin.ts'; export const defaultTemplates = { action: { @@ -11,10 +11,10 @@ export const defaultTemplates = { id=${ifDefined(attributes.id)} link-text=${ifDefined(attributes.linkText)} > - ${attributes.linkText == null ? (attributes.name || '') : attributes.linkText} + ${attributes.linkText == null ? attributes.name || '' : attributes.linkText} </solid-link> `, - dependencies: [LinkTextMixin] + dependencies: [LinkTextMixin], }, multiple: { template: (value: string, attributes: any) => html` @@ -25,6 +25,6 @@ export const defaultTemplates = { empty-widget=${ifDefined(attributes.emptyWidget)} ></solid-display> `, - dependencies: [] + dependencies: [], }, -} +}; diff --git a/src/new-widgets/templates/displayTemplatesDirectory.ts b/src/new-widgets/templates/displayTemplatesDirectory.ts index f815bb592ea1935dd46a06ef68e9e63366f99ff6..3de48ca356e1f0edd62ecb9f6873e7dd5a0f2954 100644 --- a/src/new-widgets/templates/displayTemplatesDirectory.ts +++ b/src/new-widgets/templates/displayTemplatesDirectory.ts @@ -1,31 +1,25 @@ -import { EditableMixin } from '../templatesDependencies/editableMixin'; -import { AltMixin } from '../templatesDependencies/altMixin'; -import { LinkTextMixin } from '../templatesDependencies/linkTextMixin'; +import { AltMixin } from '../templatesDependencies/altMixin.ts'; +import { EditableMixin } from '../templatesDependencies/editableMixin.ts'; +import { LinkTextMixin } from '../templatesDependencies/linkTextMixin.ts'; -import { html } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; export const displayTemplates = { value: { template: (value: string) => html`${value}`, - dependencies: [] + dependencies: [], }, div: { - template: (value: string, attributes: any) => html` - <div - name=${ifDefined(attributes.name)} - ?data-editable=${attributes.editable} - > - ${value} - </div> - `, - dependencies: [ EditableMixin ] + template: (value: string, attributes: any) => + html`<div name=${ifDefined(attributes.name)} ?data-editable=${attributes.editable}>${value}</div>`, + dependencies: [EditableMixin], }, link: { template: (value: string, attributes: any) => html` <a name=${ifDefined(attributes.name)} - href=${(attributes.mailto || attributes.tel || '')+(value || '#')} + href=${(attributes.mailto || attributes.tel || '') + (value || '#')} target=${ifDefined(attributes.target)} ?data-editable=${attributes.editable} id=${ifDefined(attributes.id)} @@ -34,7 +28,7 @@ export const displayTemplates = { ${attributes.linkText || value || ''} </a> `, - dependencies: [ EditableMixin, LinkTextMixin ] + dependencies: [EditableMixin, LinkTextMixin], }, img: { template: (value: string, attributes: any) => html` @@ -45,12 +39,11 @@ export const displayTemplates = { style="max-width: 100%; max-height: 100%;" /> `, - dependencies: [AltMixin] + dependencies: [AltMixin], }, boolean: { - template: (value: string, attributes: any) => html` - ${value === 'true' ? html`<label>${attributes.label || attributes.name || ''}</label>` : ''} - `, - dependencies: [] + template: (value: string, attributes: any) => + html`${value === 'true' ? html`<label>${attributes.label || attributes.name || ''}</label>` : ''}`, + dependencies: [], }, -} +}; diff --git a/src/new-widgets/templates/formTemplatesDirectory.ts b/src/new-widgets/templates/formTemplatesDirectory.ts index be8d15e7b5846cfc17951d3cb4b260f63a2165cb..599f389d47ad9a463e8a2c2c85fcc0a8173444e0 100644 --- a/src/new-widgets/templates/formTemplatesDirectory.ts +++ b/src/new-widgets/templates/formTemplatesDirectory.ts @@ -1,22 +1,22 @@ -import { FormMixin } from '../templatesDependencies/formMixin'; -import { FormCheckboxMixin } from '../templatesDependencies/formCheckboxMixin'; -import { FormMinMaxMixin } from '../templatesDependencies/formMinMaxMixin'; -import { FormNumberMixin } from '../templatesDependencies/formNumberMixin'; -import { FormDropdownMixin } from '../templatesDependencies/formDropdownMixin'; -import { FormCheckboxesMixin } from '../templatesDependencies/formCheckboxesMixin'; -import { FormRadioMixin } from '../templatesDependencies/formRadioMixin'; -import { FormFileMixin } from '../templatesDependencies/formFileMixin'; -import { MultipleFormMixin } from '../templatesDependencies/multipleFormMixin'; -import { MultipleselectFormMixin } from '../templatesDependencies/multipleselectFormMixin'; -import { RangeMixin } from '../templatesDependencies/rangeMixin'; -import { FilterRangeFormMixin } from '../templatesDependencies/filterRangeFormMixin'; -import { ValueRichtextMixin } from '../templatesDependencies/valueRichtextMixin'; -import { PatternMixin } from '../templatesDependencies/patternMixin'; -import { FormStepMixin } from '../templatesDependencies/formStepMixin'; -import { FormLengthMixin } from '../templatesDependencies/formLengthMixin'; +import { FilterRangeFormMixin } from '../templatesDependencies/filterRangeFormMixin.ts'; +import { FormCheckboxMixin } from '../templatesDependencies/formCheckboxMixin.ts'; +import { FormCheckboxesMixin } from '../templatesDependencies/formCheckboxesMixin.ts'; +import { FormDropdownMixin } from '../templatesDependencies/formDropdownMixin.ts'; +import { FormFileMixin } from '../templatesDependencies/formFileMixin.ts'; +import { FormLengthMixin } from '../templatesDependencies/formLengthMixin.ts'; +import { FormMinMaxMixin } from '../templatesDependencies/formMinMaxMixin.ts'; +import { FormMixin } from '../templatesDependencies/formMixin.ts'; +import { FormNumberMixin } from '../templatesDependencies/formNumberMixin.ts'; +import { FormRadioMixin } from '../templatesDependencies/formRadioMixin.ts'; +import { FormStepMixin } from '../templatesDependencies/formStepMixin.ts'; +import { MultipleFormMixin } from '../templatesDependencies/multipleFormMixin.ts'; +import { MultipleselectFormMixin } from '../templatesDependencies/multipleselectFormMixin.ts'; +import { PatternMixin } from '../templatesDependencies/patternMixin.ts'; +import { RangeMixin } from '../templatesDependencies/rangeMixin.ts'; +import { ValueRichtextMixin } from '../templatesDependencies/valueRichtextMixin.ts'; -import { html } from 'lit-html'; -import { ifDefined } from 'lit-html/directives/if-defined'; +import { html } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; export const formTemplates = { text: { @@ -37,7 +37,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin, PatternMixin, FormLengthMixin ] + dependencies: [FormMixin, PatternMixin, FormLengthMixin], }, textarea: { template: (value: string, attributes: any) => html` @@ -53,7 +53,7 @@ export const formTemplates = { @change=${attributes.onChange} >${value}</textarea> `, - dependencies: [ FormMixin, FormLengthMixin ] + dependencies: [FormMixin, FormLengthMixin], }, checkbox: { template: (value: string, attributes: any) => html` @@ -69,7 +69,7 @@ export const formTemplates = { <div>${attributes.label || attributes.name}</div> </label> `, - dependencies: [ FormCheckboxMixin, FormMixin ] + dependencies: [FormCheckboxMixin, FormMixin], }, date: { template: (_value: string, attributes: any) => html` @@ -84,7 +84,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin ] + dependencies: [FormMixin], }, rangedate: { template: (_value: string, attributes: any) => html` @@ -103,7 +103,7 @@ export const formTemplates = { value=${ifDefined(attributes.endValue)} /> `, - dependencies: [ FilterRangeFormMixin, FormMixin ] + dependencies: [FilterRangeFormMixin, FormMixin], }, number: { template: (value: string, attributes: any) => html` @@ -121,7 +121,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormNumberMixin, FormMinMaxMixin, FormMixin, FormStepMixin ] + dependencies: [FormNumberMixin, FormMinMaxMixin, FormMixin, FormStepMixin], }, rangenumber: { template: (_value: string, attributes: any) => html` @@ -140,7 +140,7 @@ export const formTemplates = { value=${ifDefined(attributes.endValue)} /> `, - dependencies: [ FilterRangeFormMixin, FormNumberMixin, FormMixin ] + dependencies: [FilterRangeFormMixin, FormNumberMixin, FormMixin], }, hidden: { template: (value: string, attributes: any) => html` @@ -152,7 +152,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin ] + dependencies: [FormMixin], }, dropdown: { template: (value: string, attributes: any) => html` @@ -165,37 +165,46 @@ export const formTemplates = { autocomplete=${ifDefined(attributes.autocomplete)} @change=${attributes.onChange} > - ${!(attributes.multiple || attributes.autocomplete) ? html` - <option value="" ?selected=${value === ""}> + ${ + !(attributes.multiple || attributes.autocomplete) + ? html` + <option value="" ?selected=${value === ''}> ${attributes.placeholder || '-'} </option> - ` : ''} - ${(attributes.range || []).map(el => html` + ` + : '' + } + ${(attributes.range || []).map( + el => html` <option value=${el.value} ?selected=${!attributes.multiple ? value === el.selectedValue : attributes.values.includes(el.selectedValue)} > ${el.label} </option> - `)} - ${Object.entries(attributes.enum || []).map(([key, val]) => html` + `, + )} + ${Object.entries(attributes.enum || []).map( + ([key, val]) => html` <option value="${key}" ?selected=${!attributes.multiple ? value === key : attributes.values.includes(key)} > ${val} </option> - `)} + `, + )} </select> `, - dependencies: [ FormDropdownMixin, FormMixin, RangeMixin ] + dependencies: [FormDropdownMixin, FormMixin, RangeMixin], }, radio: { template: (value: string, attributes: any) => html` <div name=${ifDefined(attributes.name)} > - ${(attributes.range || []).map(el => html` + ${(attributes.range || []).map( + el => html` <label> <input type="radio" @@ -205,8 +214,10 @@ export const formTemplates = { ?checked=${value === el.selectedValue} > <span>${el.label}</span> </label> - `)} - ${Object.entries(attributes.enum || []).map(([key, val]) => html` + `, + )} + ${Object.entries(attributes.enum || []).map( + ([key, val]) => html` <label> <input type="radio" @@ -216,16 +227,18 @@ export const formTemplates = { ?checked=${value === key} > <span>${val}</span> </label> - `)} + `, + )} `, - dependencies: [ FormRadioMixin, FormMixin, RangeMixin ] + dependencies: [FormRadioMixin, FormMixin, RangeMixin], }, multicheckbox: { template: (_value: string, attributes: any) => html` <div name=${ifDefined(attributes.name)} > - ${(attributes.range || []).map(el => html` + ${(attributes.range || []).map( + el => html` <label> <input type="checkbox" @@ -233,18 +246,20 @@ export const formTemplates = { ?checked=${attributes.values.includes(el.selectedValue)} /> <span>${el.label}</span> </label> - `)} - ${Object.entries(attributes.enum || []) - .map(([key, val]) => html` + `, + )} + ${Object.entries(attributes.enum || []).map( + ([key, val]) => html` <label> <input type="checkbox" value="${key}" /> <span>${val}</span> </label> - `)} + `, + )} </select> `, - dependencies: [ FormCheckboxesMixin, FormMixin, RangeMixin ] + dependencies: [FormCheckboxesMixin, FormMixin, RangeMixin], }, checkboxes: { template: (_value: string, attributes: any) => html` @@ -261,19 +276,21 @@ export const formTemplates = { ?required=${attributes.required} ></solid-form-multicheckbox> `, - dependencies: [ MultipleselectFormMixin, FormMixin, RangeMixin ] + dependencies: [MultipleselectFormMixin, FormMixin, RangeMixin], }, multiple: { template: (_value: string, attributes: any) => html` - ${(attributes.children || []).map((child, index) => html` + ${(attributes.children || []).map( + (child, index) => html` <div data-index=${attributes.name + index}> ${child} <button type="button" class=${ifDefined(attributes.removeClass)} @click=${() => attributes.removeItem(index)}>${attributes.removeLabel}</button> </div> - `)} + `, + )} <button type="button" class=${ifDefined(attributes.addClass)} @click=${attributes.addItem}>${attributes.addLabel}</button> `, - dependencies: [ MultipleFormMixin, FormMixin ] + dependencies: [MultipleFormMixin, FormMixin], }, multipleselect: { template: (_value: string, attributes: any) => html` @@ -291,7 +308,7 @@ export const formTemplates = { multiple ></solid-form-dropdown> `, - dependencies: [ MultipleselectFormMixin, FormMixin, RangeMixin ] + dependencies: [MultipleselectFormMixin, FormMixin, RangeMixin], }, file: { template: (value: string, attributes: any) => html` @@ -303,6 +320,11 @@ export const formTemplates = { name=${ifDefined(attributes.name)} value=${value || ''} > + <a + href=${value || ''} + ?hidden=${value === ''} + >${value !== '' ? decodeURI(value.split('/').pop() as string) : ''}</a> + <input type="file" id=${ifDefined(attributes.id)} @@ -316,7 +338,7 @@ export const formTemplates = { <span>${attributes.output}</span> </div> `, - dependencies: [ FormFileMixin, FormMixin ] + dependencies: [FormFileMixin, FormMixin], }, image: { template: (value: string, attributes: any) => html` @@ -346,7 +368,7 @@ export const formTemplates = { <span>${attributes.output}</span> </div> `, - dependencies: [ FormFileMixin, FormMixin ] + dependencies: [FormFileMixin, FormMixin], }, richtext: { template: (_value: string, attributes: any) => html` @@ -356,7 +378,7 @@ export const formTemplates = { data-holder ></div> `, - dependencies: [ ValueRichtextMixin, FormMixin ] + dependencies: [ValueRichtextMixin, FormMixin], }, color: { template: (_value: string, attributes: any) => html` @@ -371,7 +393,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin ] + dependencies: [FormMixin], }, email: { template: (value: string, attributes: any) => html` @@ -380,7 +402,7 @@ export const formTemplates = { placeholder=${ifDefined(attributes.placeholder)} id=${ifDefined(attributes.id)} name=${ifDefined(attributes.name)} - value=${value || ''} + value=${value || ''} ?required=${attributes.required} data-holder maxlength=${ifDefined(attributes.maxlength)} @@ -388,7 +410,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin, FormLengthMixin ] + dependencies: [FormMixin, FormLengthMixin], }, password: { template: (value: string, attributes: any) => html` @@ -397,7 +419,7 @@ export const formTemplates = { placeholder=${ifDefined(attributes.placeholder)} id=${ifDefined(attributes.id)} name=${ifDefined(attributes.name)} - value=${value || ''} + value=${value || ''} ?required=${attributes.required} pattern=${ifDefined(attributes.pattern)} title=${ifDefined(attributes.title)} @@ -407,7 +429,7 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin, PatternMixin, FormLengthMixin ] + dependencies: [FormMixin, PatternMixin, FormLengthMixin], }, time: { template: (value: string, attributes: any) => html` @@ -425,6 +447,6 @@ export const formTemplates = { @change=${attributes.onChange} /> `, - dependencies: [ FormMixin, FormMinMaxMixin, FormStepMixin ] + dependencies: [FormMixin, FormMinMaxMixin, FormStepMixin], }, -} +}; diff --git a/src/new-widgets/templates/groupTemplatesDirectory.ts b/src/new-widgets/templates/groupTemplatesDirectory.ts index bb88ebd1a781c1837db7cde5d0de2e6869a3cb2a..77799cb5b76884fa2d7e0f9bfe06158edaacf182 100644 --- a/src/new-widgets/templates/groupTemplatesDirectory.ts +++ b/src/new-widgets/templates/groupTemplatesDirectory.ts @@ -1,12 +1,10 @@ -import { html } from 'lit-html'; -import { SetMixin } from '../templatesDependencies/setMixin'; +import { html } from 'lit'; +import { SetMixin } from '../templatesDependencies/setMixin.ts'; export const groupTemplates = { default: { - template: (value: string) => html` - <span>${value}</span> - <div data-content></div> - `, - dependencies: [SetMixin] + template: (value: string) => + html`<span>${value}</span><div data-content></div>`, + dependencies: [SetMixin], }, -} \ No newline at end of file +}; diff --git a/src/new-widgets/templates/index.ts b/src/new-widgets/templates/index.ts index 288fcd3b6b04a02a7f3c057eee48a022d40d7e97..e05514ebc6351d73cdee60aaee6c7225d372b6a4 100644 --- a/src/new-widgets/templates/index.ts +++ b/src/new-widgets/templates/index.ts @@ -1,13 +1,13 @@ -import { defaultTemplates } from './defaultTemplatesDirectory'; -import { displayTemplates } from './displayTemplatesDirectory'; -import { formTemplates } from './formTemplatesDirectory'; -import { setTemplates } from './setTemplatesDirectory'; +import { defaultTemplates } from './defaultTemplatesDirectory.ts'; +import { displayTemplates } from './displayTemplatesDirectory.ts'; +import { formTemplates } from './formTemplatesDirectory.ts'; import { groupTemplates } from './groupTemplatesDirectory.js'; +import { setTemplates } from './setTemplatesDirectory.ts'; export { defaultTemplates, displayTemplates, formTemplates, setTemplates, - groupTemplates -} + groupTemplates, +}; diff --git a/src/new-widgets/templates/setTemplatesDirectory.ts b/src/new-widgets/templates/setTemplatesDirectory.ts index 61ae761b05427c6b21b64999f3691b42613e006b..155b8d8c94e1f2862da497c638dc65cd9e9e917c 100644 --- a/src/new-widgets/templates/setTemplatesDirectory.ts +++ b/src/new-widgets/templates/setTemplatesDirectory.ts @@ -1,17 +1,17 @@ -import { html } from 'lit-html'; -import { SetMixin } from '../templatesDependencies/setMixin'; +import { html } from 'lit'; +import { SetMixin } from '../templatesDependencies/setMixin.ts'; export const setTemplates = { default: { template: () => html``, - dependencies: [ SetMixin ] + dependencies: [SetMixin], }, div: { template: () => html`<div data-content></div>`, - dependencies: [ SetMixin ] + dependencies: [SetMixin], }, ul: { template: () => html`<ul data-content></ul>`, - dependencies: [ SetMixin ] - } -} \ No newline at end of file + dependencies: [SetMixin], + }, +}; diff --git a/src/new-widgets/templatesDependencies/altMixin.ts b/src/new-widgets/templatesDependencies/altMixin.ts index 3e517c3ce9f60a4775d7c31fd1d5b09f192e3812..1d0a1821ee8ae82da34793e817cce5216390aafe 100644 --- a/src/new-widgets/templatesDependencies/altMixin.ts +++ b/src/new-widgets/templatesDependencies/altMixin.ts @@ -1,15 +1,13 @@ const AltMixin = { name: 'alt-mixin', - attributes : { - alt : { + attributes: { + alt: { type: String, callback: function (newValue: string) { - this.addToAttributes(newValue, 'alt') - } + this.addToAttributes(newValue, 'alt'); + }, }, }, -} +}; -export { - AltMixin -} \ No newline at end of file +export { AltMixin }; diff --git a/src/new-widgets/templatesDependencies/editableMixin.ts b/src/new-widgets/templatesDependencies/editableMixin.ts index 9137d86de8f87428f8b9863920e557631a8f9ff2..1ef096dc17d0a9c54e73541de2a7d21959eb644f 100644 --- a/src/new-widgets/templatesDependencies/editableMixin.ts +++ b/src/new-widgets/templatesDependencies/editableMixin.ts @@ -1,37 +1,43 @@ -import { StoreMixin } from '../../mixins/storeMixin'; -import { store } from '../../libs/store/store'; +import { store } from '../../libs/store/store.ts'; +import { StoreMixin } from '../../mixins/storeMixin.ts'; -import { html } from 'lit-html'; +import { html } from 'lit'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const EditableMixin = { name: 'editable-mixin', - use: [ StoreMixin ], // used to get context + use: [StoreMixin], // used to get context attributes: { editable: { type: Boolean, default: null, callback: function (newValue: boolean) { - if (newValue !== null) this.listAttributes['editable'] = true; - } + if (newValue !== null) this.listAttributes.editable = true; + }, }, valueId: { type: String, - default: '' - } + default: '', + }, + buttonLabel: { + type: String, + default: 'Modifier', + }, }, created() { - this.listTemplateAdditions.push(this.addEditButton.bind(this)); + this.listTemplateAdditions.attach( + this.addEditButton.bind(this), + 'EditableMixin:addEditButton', + ); }, - addEditButton(template, listTemplateAdditions: Function[]) { + addEditButton(template, listTemplateAdditions: PostProcessorRegistry) { let newTemplate: any = null; if (this.editable !== null) { - newTemplate = html` - ${template} - <button @click=${this.activateEditableField.bind(this)}>Modifier</button> - `; + newTemplate = html`${template}<button @click=${this.activateEditableField.bind(this)}>${this.buttonLabel}</button>`; } const nextProcessor = listTemplateAdditions.shift(); - if(nextProcessor) nextProcessor(newTemplate || template, listTemplateAdditions); + if (nextProcessor) + nextProcessor(newTemplate || template, listTemplateAdditions); }, activateEditableField(e: Event): void { const editableField = this.element.querySelector('[data-editable]'); @@ -43,7 +49,9 @@ const EditableMixin = { editButton.toggleAttribute('disabled', true); // Save on focusout - editableField.addEventListener('focusout', () => this.save(editableField, editButton)); + editableField.addEventListener('focusout', () => + this.save(editableField, editButton), + ); }, save(editableField: HTMLElement, editButton: HTMLElement) { editableField.toggleAttribute('contenteditable', false); @@ -59,8 +67,6 @@ const EditableMixin = { store.patch(resource, this.valueId); }, -} +}; -export { - EditableMixin -} \ No newline at end of file +export { EditableMixin }; diff --git a/src/new-widgets/templatesDependencies/filterRangeFormMixin.ts b/src/new-widgets/templatesDependencies/filterRangeFormMixin.ts index 63c4b8683b83f1fb707d963868a0471dd12ff14d..9d03620ffc3bb0887626166cdf958f27009392b4 100644 --- a/src/new-widgets/templatesDependencies/filterRangeFormMixin.ts +++ b/src/new-widgets/templatesDependencies/filterRangeFormMixin.ts @@ -3,36 +3,36 @@ const FilterRangeFormMixin = { attributes: { startValue: { type: String, - default:'', + default: '', callback: function (value: string) { - this.addToAttributes(this.getDefaultValue(value), "startValue") - } + this.addToAttributes(this.getDefaultValue(value), 'startValue'); + }, }, endValue: { type: String, - default:'', + default: '', callback: function (value: string) { - this.addToAttributes(this.getDefaultValue(value), "endValue") - } - } + this.addToAttributes(this.getDefaultValue(value), 'endValue'); + }, + }, }, getDefaultValue(value) { - if (value == "today") return new Date().toISOString().split("T")[0]; + if (value === 'today') return new Date().toISOString().split('T')[0]; return value; }, getValue() { if (!this.dataHolder) return []; - if (this.dataHolder.length !== 2) this.showDataHolderError(2, this.dataHolder.length); - return [ // we expect 2 values, one min and one max + if (this.dataHolder.length !== 2) + this.showDataHolderError(2, this.dataHolder.length); + return [ + // we expect 2 values, one min and one max this.getValueFromElement(this.dataHolder[0]), - this.getValueFromElement(this.dataHolder[1]) - ] + this.getValueFromElement(this.dataHolder[1]), + ]; }, get type() { return 'range'; }, -} +}; -export { - FilterRangeFormMixin -} \ No newline at end of file +export { FilterRangeFormMixin }; diff --git a/src/new-widgets/templatesDependencies/formCheckboxMixin.ts b/src/new-widgets/templatesDependencies/formCheckboxMixin.ts index 0d7d906b91af9fac59c975685ea2ec61f28e84bc..5b6fcb1ae530de26efc95114e4803182b10e39c6 100644 --- a/src/new-widgets/templatesDependencies/formCheckboxMixin.ts +++ b/src/new-widgets/templatesDependencies/formCheckboxMixin.ts @@ -6,8 +6,6 @@ const FormCheckboxMixin = { get type() { return 'boolean'; }, -} +}; -export { - FormCheckboxMixin -} \ No newline at end of file +export { FormCheckboxMixin }; diff --git a/src/new-widgets/templatesDependencies/formCheckboxesMixin.ts b/src/new-widgets/templatesDependencies/formCheckboxesMixin.ts index 76c8d7e5c02c20d893446e4271d7c65b9a4e569b..cd175681010ddd1343c2bf8b665f1461fc71bc91 100644 --- a/src/new-widgets/templatesDependencies/formCheckboxesMixin.ts +++ b/src/new-widgets/templatesDependencies/formCheckboxesMixin.ts @@ -7,38 +7,40 @@ const FormCheckboxesMixin = { callback: function (value: string) { if (!value) return; try { - this.listAttributes['values'] = JSON.parse(value); + this.listAttributes.values = JSON.parse(value); } catch (e) { console.error(e); - this.listAttributes['values'] = []; + this.listAttributes.values = []; } this.render(); this.element.dispatchEvent(new Event('change')); - } + }, }, }, created() { - this.listAttributes['values'] = []; + this.listAttributes.values = []; }, getValue() { - const options = Array.from(this.element.querySelectorAll('input')) as HTMLInputElement[]; + const options = Array.from( + this.element.querySelectorAll('input'), + ) as HTMLInputElement[]; return options .filter(el => el.checked) .map(el => { if (!el.value) return null; let value = el.value; - try { value = JSON.parse(el.value) } catch (e) { } + try { + value = JSON.parse(el.value); + } catch {} return value; - }) + }); }, get type() { - return this.enum === ''? 'resource' : 'string'; + return this.enum === '' ? 'resource' : 'string'; }, get multiple() { return true; - } -} + }, +}; -export { - FormCheckboxesMixin -} \ No newline at end of file +export { FormCheckboxesMixin }; diff --git a/src/new-widgets/templatesDependencies/formDropdownMixin.ts b/src/new-widgets/templatesDependencies/formDropdownMixin.ts index a43b70acdd7387f85a4c57e508c7091933e35d4d..e850778b8b2e41a0c6b75b9a256df6d9ccd984c1 100644 --- a/src/new-widgets/templatesDependencies/formDropdownMixin.ts +++ b/src/new-widgets/templatesDependencies/formDropdownMixin.ts @@ -1,38 +1,41 @@ const FormDropdownMixin = { name: 'form-dropdown-mixin', attributes: { - values: { // used to set more than 1 value, for multiple select + values: { + // used to set more than 1 value, for multiple select type: String, default: '', - callback: function(value) { + callback: function (value) { if (value) { try { - this.listAttributes['values'] = JSON.parse(value); + this.listAttributes.values = JSON.parse(value); } catch (e) { console.error(e); - this.listAttributes['values'] = []; + this.listAttributes.values = []; } this.render(); // use render to make sure the dispatch always happen after this.dispatchChange(); } - } + }, }, dataId: { type: String, default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'id'); - } + }, }, }, created() { - this.listAttributes['values'] = []; - if (this.listAttributes['value'] && - !(JSON.parse(this.listAttributes['value']['@id'])) && Array.isArray(JSON.parse(this.listAttributes['value'])) + this.listAttributes.values = []; + if ( + this.listAttributes.value && + !JSON.parse(this.listAttributes.value['@id']) && + Array.isArray(JSON.parse(this.listAttributes.value)) ) { - this.listAttributes['values'] = this.listAttributes['value']; + this.listAttributes.values = this.listAttributes.value; } - if (this.multiple) this.listAttributes['multiple'] = true; + if (this.multiple) this.listAttributes.multiple = true; }, dispatchChange() { if (!this.element.querySelector('select')) return; @@ -40,23 +43,27 @@ const FormDropdownMixin = { }, getValue() { if (!this.dataHolder) return ''; // no value - if (!this.multiple) { // simple select - if (this.dataHolder.length > 1) this.showDataHolderError(1, this.dataHolder.length); + if (!this.multiple) { + // simple select + if (this.dataHolder.length > 1) + this.showDataHolderError(1, this.dataHolder.length); return this.getValueFromElement(this.dataHolder[0]); } // multiple select - const options = Array.from(this.element.querySelectorAll('option')) as HTMLOptionElement[]; - return options.filter(el => el.selected).map(el => el.value ? JSON.parse(el.value) : null) + const options = Array.from( + this.element.querySelectorAll('option'), + ) as HTMLOptionElement[]; + return options + .filter(el => el.selected) + .map(el => (el.value ? JSON.parse(el.value) : null)); }, get type() { - return this.enum === ''? 'resource' : 'string'; + return this.enum === '' ? 'resource' : 'string'; }, get multiple() { return this.element.hasAttribute('multiple'); - } -} + }, +}; -export { - FormDropdownMixin -} \ No newline at end of file +export { FormDropdownMixin }; diff --git a/src/new-widgets/templatesDependencies/formFileMixin.ts b/src/new-widgets/templatesDependencies/formFileMixin.ts index 7b594b8ba8cfe00872236fb36e7f8bda64f19768..4699689bf6fda708d0f7b69d3c769610e1e73382 100644 --- a/src/new-widgets/templatesDependencies/formFileMixin.ts +++ b/src/new-widgets/templatesDependencies/formFileMixin.ts @@ -1,25 +1,29 @@ -import { store } from "../../libs/store/store"; +import { store } from '../../libs/store/store.ts'; const FormFileMixin = { name: 'form-file-mixin', attributes: { uploadUrl: { type: String, - default: '' + default: '', }, }, initialState: { - initialValue: '' + initialValue: '', }, created() { - this.listAttributes['output'] = ''; - this.listAttributes['resetButtonHidden'] = true; - this.listAttributes['selectFile'] = this.selectFile.bind(this); - this.listAttributes['resetFile'] = this.resetFile.bind(this); + this.listAttributes.output = ''; + this.listAttributes.resetButtonHidden = true; + this.listAttributes.selectFile = this.selectFile.bind(this); + this.listAttributes.resetFile = this.resetFile.bind(this); }, attached() { - this.element.closest('form').addEventListener('reset', this.resetFormFile.bind(this)) - this.element.closest('solid-form').addEventListener('populate', this.onPopulate.bind(this)) + this.element + .closest('form') + .addEventListener('reset', this.resetFormFile.bind(this)); + this.element + .closest('solid-form') + .addEventListener('populate', this.onPopulate.bind(this)); }, onPopulate() { const dataHolder = this.element.querySelector('input[data-holder]'); @@ -28,10 +32,10 @@ const FormFileMixin = { }, resetFormFile(e) { if (e.target && (e.target as HTMLElement).contains(this.element)) { - if (this.initialValue !== "") { + if (this.initialValue !== '') { this.value = this.initialValue; } - this.listAttributes['resetButtonHidden'] = true; + this.listAttributes.resetButtonHidden = true; this.planRender(); const dataHolder = this.element.querySelector('input[data-holder]'); dataHolder.value = this.value; @@ -46,23 +50,24 @@ const FormFileMixin = { } const filePicker = this.element.querySelector('input[type="file"]'); - if (filePicker.files!.length < 1) return; + if (filePicker.files?.length === 0) return; const dataHolder = this.element.querySelector('input[data-holder]'); - this.listAttributes['output'] = 'â³'; + this.listAttributes.output = 'â³'; this.planRender(); - const file = filePicker.files![0]; + const file = filePicker.files?.[0]; const formData = new FormData(); formData.append('file', file); - store.fetchAuthn(this.uploadUrl, { - method: 'POST', - body: formData, - }) - .then(response => this.updateFile(dataHolder, response) ) + store + .fetchAuthn(this.uploadUrl, { + method: 'POST', + body: formData, + }) + .then(response => this.updateFile(dataHolder, response)) .catch(error => { - this.listAttributes['fileValue'] = ''; - this.listAttributes['output'] = 'upload error'; + this.listAttributes.fileValue = ''; + this.listAttributes.output = 'upload error'; this.planRender(); console.error(error); }); @@ -71,11 +76,11 @@ const FormFileMixin = { updateFile(dataHolder: HTMLInputElement, response: Response) { const location = response.headers.get('location'); if (location == null) { - this.listAttributes['output'] = 'header location not found!'; + this.listAttributes.output = 'header location not found!'; } else { this.value = location; - this.listAttributes['output'] = ''; - this.listAttributes['resetButtonHidden'] = false; + this.listAttributes.output = ''; + this.listAttributes.resetButtonHidden = false; dataHolder.value = location; dataHolder.dispatchEvent(new Event('change')); @@ -90,18 +95,16 @@ const FormFileMixin = { const filePicker = this.element.querySelector('input[type="file"]'); const dataHolder = this.element.querySelector('input[data-holder]'); - if (filePicker && dataHolder ) { + if (filePicker && dataHolder) { filePicker.value = dataHolder.value = ''; } - this.listAttributes['fileValue'] = ''; - this.listAttributes['output'] = ''; - this.listAttributes['resetButtonHidden'] = true; + this.listAttributes.fileValue = ''; + this.listAttributes.output = ''; + this.listAttributes.resetButtonHidden = true; dataHolder.dispatchEvent(new Event('change')); this.planRender(); - } -} + }, +}; -export { - FormFileMixin -} +export { FormFileMixin }; diff --git a/src/new-widgets/templatesDependencies/formLengthMixin.ts b/src/new-widgets/templatesDependencies/formLengthMixin.ts index 9121410f526da5bc9e6a0dc16145a2cb6a2d3a9c..628796b68033bbd3bd520d45fcfcff0d301cf0fe 100644 --- a/src/new-widgets/templatesDependencies/formLengthMixin.ts +++ b/src/new-widgets/templatesDependencies/formLengthMixin.ts @@ -5,17 +5,15 @@ const FormLengthMixin = { type: Number, callback: function (newValue: string) { this.addToAttributes(newValue, 'maxlength'); - } + }, }, minlength: { type: Number, callback: function (newValue: string) { this.addToAttributes(newValue, 'minlength'); - } + }, }, }, -} +}; -export { - FormLengthMixin -} \ No newline at end of file +export { FormLengthMixin }; diff --git a/src/new-widgets/templatesDependencies/formMinMaxMixin.ts b/src/new-widgets/templatesDependencies/formMinMaxMixin.ts index f83c8794630d1eb8f7c52a4d412082367b3250ad..fe964c2a11584e61d3fe0c8c20bd87485a356cf2 100644 --- a/src/new-widgets/templatesDependencies/formMinMaxMixin.ts +++ b/src/new-widgets/templatesDependencies/formMinMaxMixin.ts @@ -1,21 +1,19 @@ const FormMinMaxMixin = { name: 'form-min-max-mixin', - attributes : { - min : { + attributes: { + min: { type: Number, callback: function (newValue: number) { this.addToAttributes(newValue, 'min'); - } + }, }, - max : { + max: { type: Number, callback: function (newValue: number) { this.addToAttributes(newValue, 'max'); - } + }, }, - } -} + }, +}; -export { - FormMinMaxMixin -} \ No newline at end of file +export { FormMinMaxMixin }; diff --git a/src/new-widgets/templatesDependencies/formMixin.ts b/src/new-widgets/templatesDependencies/formMixin.ts index 65bbd892b0ce804e00dc4ce04674d1ce8c5c4ea8..5c3dcbb11426dc3b8b5a577e4c82e8062f2f65d6 100644 --- a/src/new-widgets/templatesDependencies/formMixin.ts +++ b/src/new-widgets/templatesDependencies/formMixin.ts @@ -5,19 +5,19 @@ const FormMixin = { type: Boolean, default: false, callback: function () { - this.listAttributes['required'] = true; - } + this.listAttributes.required = true; + }, }, autocomplete: { type: String, default: '', - callback:function (value: string) { - this.addToAttributes(value, "autocomplete"); - } + callback: function (value: string) { + this.addToAttributes(value, 'autocomplete'); + }, }, }, attached() { - this.listAttributes['onChange'] = this.onChange.bind(this); + this.listAttributes.onChange = this.onChange.bind(this); }, onChange(e: Event) { e.preventDefault(); @@ -26,7 +26,8 @@ const FormMixin = { }, getValue() { if (!this.dataHolder || this.dataHolder.length === 0) return this.value; - if (this.dataHolder.length > 1) this.showDataHolderError(1, this.dataHolder.length); + if (this.dataHolder.length > 1) + this.showDataHolderError(1, this.dataHolder.length); return this.getValueFromElement(this.dataHolder[0]); }, get type() { @@ -36,23 +37,31 @@ const FormMixin = { return false; }, get dataHolder(): Element[] | null { - const dataHolders = Array.from((this.element as Element).querySelectorAll('[data-holder]')); + const dataHolders = Array.from( + (this.element as Element).querySelectorAll('[data-holder]'), + ); const widgetDataHolders = dataHolders.filter(element => { - const dataHolderAncestor = element.parentElement ? element.parentElement.closest('[data-holder]') : null; + const dataHolderAncestor = element.parentElement + ? element.parentElement.closest('[data-holder]') + : null; // get the dataHolder of the widget only if no dataHolder ancestor in the current widget - return dataHolderAncestor === this.element || !dataHolderAncestor || !this.element.contains(dataHolderAncestor) + return ( + dataHolderAncestor === this.element || + !dataHolderAncestor || + !this.element.contains(dataHolderAncestor) + ); }); - return widgetDataHolders.length ? widgetDataHolders : null; + return widgetDataHolders.length > 0 ? widgetDataHolders : null; }, getValueFromElement(element: any) { return element.component ? element.component.getValue() : element.value; }, showDataHolderError(expected: number, found: number) { - console.warn(`Expected ${expected} data-holder element in ${this.element.tagName}. Found ${found}`); - } -} + console.warn( + `Expected ${expected} data-holder element in ${this.element.tagName}. Found ${found}`, + ); + }, +}; -export { - FormMixin -} \ No newline at end of file +export { FormMixin }; diff --git a/src/new-widgets/templatesDependencies/formNumberMixin.ts b/src/new-widgets/templatesDependencies/formNumberMixin.ts index b682676712f89377f2ead0b9d656d1c433e6acc3..3949343efa734faff57a9e81c09df9121085d0db 100644 --- a/src/new-widgets/templatesDependencies/formNumberMixin.ts +++ b/src/new-widgets/templatesDependencies/formNumberMixin.ts @@ -3,11 +3,9 @@ const FormNumberMixin = { getValueFromElement(element: any) { return element.value ? Number(element.value) : ''; }, - get type () { - return 'number' + get type() { + return 'number'; }, -} +}; -export { - FormNumberMixin -} \ No newline at end of file +export { FormNumberMixin }; diff --git a/src/new-widgets/templatesDependencies/formRadioMixin.ts b/src/new-widgets/templatesDependencies/formRadioMixin.ts index 29bea1d67580f92d936bf7b4a46af2d212af31b9..d672b80a88a07326926ed68b40b33aa32accfb96 100644 --- a/src/new-widgets/templatesDependencies/formRadioMixin.ts +++ b/src/new-widgets/templatesDependencies/formRadioMixin.ts @@ -1,16 +1,16 @@ -import { uniqID } from '../../libs/helpers'; +import { uniqID } from '../../libs/helpers.ts'; const FormRadioMixin = { name: 'form-radio-mixin', created() { - this.listAttributes['id'] = uniqID(); + this.listAttributes.id = uniqID(); }, getValue() { - const checkedElement = this.element.querySelector('input[type=radio]:checked') as HTMLInputElement; + const checkedElement = this.element.querySelector( + 'input[type=radio]:checked', + ) as HTMLInputElement; return checkedElement ? checkedElement.value : ''; }, -} +}; -export { - FormRadioMixin -} \ No newline at end of file +export { FormRadioMixin }; diff --git a/src/new-widgets/templatesDependencies/formStepMixin.ts b/src/new-widgets/templatesDependencies/formStepMixin.ts index 292d2fc477b0e61694f561f4ec31d19d75d0d962..9ba7f9ea9467edf289fc9dcfd8288917606aaa2b 100644 --- a/src/new-widgets/templatesDependencies/formStepMixin.ts +++ b/src/new-widgets/templatesDependencies/formStepMixin.ts @@ -1,15 +1,13 @@ const FormStepMixin = { name: 'form-time-mixin', - attributes : { - step : { + attributes: { + step: { type: Number, callback: function (newValue: number) { this.addToAttributes(newValue, 'step'); - } + }, }, }, -} +}; -export { - FormStepMixin -} \ No newline at end of file +export { FormStepMixin }; diff --git a/src/new-widgets/templatesDependencies/index.ts b/src/new-widgets/templatesDependencies/index.ts index df477f3057045ab0ad03135a2e8695d5ad4716f5..6f4d7c222559d1a5236e8b5b8e4656ee31aba5eb 100644 --- a/src/new-widgets/templatesDependencies/index.ts +++ b/src/new-widgets/templatesDependencies/index.ts @@ -1,47 +1,46 @@ -import { AltMixin } from './altMixin'; -import { EditableMixin } from './editableMixin'; -import { FilterRangeFormMixin } from './filterRangeFormMixin'; -import { FormCheckboxesMixin } from './formCheckboxesMixin'; -import { FormCheckboxMixin } from './formCheckboxMixin'; -import { FormDropdownMixin } from './formDropdownMixin'; -import { FormFileMixin } from './formFileMixin'; -import { FormLengthMixin } from './formLengthMixin'; -import { FormMinMaxMixin } from './formMinMaxMixin'; -import { FormMixin } from './formMixin'; -import { FormNumberMixin } from './formNumberMixin'; -import { FormRadioMixin } from './formRadioMixin'; -import { FormStepMixin } from './formStepMixin'; -import { LinkTextMixin } from './linkTextMixin'; -import { MultipleFormMixin } from './multipleFormMixin'; -import { MultipleselectFormMixin } from './multipleselectFormMixin'; -import { PatternMixin } from './patternMixin'; -import { RangeMixin } from './rangeMixin'; -import { SetMixin } from './setMixin'; -import { ValueRichtextMixin } from './valueRichtextMixin'; - +import { AltMixin } from './altMixin.ts'; +import { EditableMixin } from './editableMixin.ts'; +import { FilterRangeFormMixin } from './filterRangeFormMixin.ts'; +import { FormCheckboxMixin } from './formCheckboxMixin.ts'; +import { FormCheckboxesMixin } from './formCheckboxesMixin.ts'; +import { FormDropdownMixin } from './formDropdownMixin.ts'; +import { FormFileMixin } from './formFileMixin.ts'; +import { FormLengthMixin } from './formLengthMixin.ts'; +import { FormMinMaxMixin } from './formMinMaxMixin.ts'; +import { FormMixin } from './formMixin.ts'; +import { FormNumberMixin } from './formNumberMixin.ts'; +import { FormRadioMixin } from './formRadioMixin.ts'; +import { FormStepMixin } from './formStepMixin.ts'; +import { LinkTextMixin } from './linkTextMixin.ts'; +import { MultipleFormMixin } from './multipleFormMixin.ts'; +import { MultipleselectFormMixin } from './multipleselectFormMixin.ts'; +import { PatternMixin } from './patternMixin.ts'; +import { RangeMixin } from './rangeMixin.ts'; +import { SetMixin } from './setMixin.ts'; +import { ValueRichtextMixin } from './valueRichtextMixin.ts'; /** * Template Depenedices Additions */ export { - AltMixin, - EditableMixin, - FilterRangeFormMixin, - FormCheckboxesMixin, - FormCheckboxMixin, - FormDropdownMixin, - FormFileMixin, - FormLengthMixin, - FormMinMaxMixin, - FormMixin, - FormNumberMixin, - FormRadioMixin, - FormStepMixin, - LinkTextMixin, - MultipleFormMixin, - MultipleselectFormMixin, - PatternMixin, - RangeMixin, - SetMixin, - ValueRichtextMixin -} + AltMixin, + EditableMixin, + FilterRangeFormMixin, + FormCheckboxesMixin, + FormCheckboxMixin, + FormDropdownMixin, + FormFileMixin, + FormLengthMixin, + FormMinMaxMixin, + FormMixin, + FormNumberMixin, + FormRadioMixin, + FormStepMixin, + LinkTextMixin, + MultipleFormMixin, + MultipleselectFormMixin, + PatternMixin, + RangeMixin, + SetMixin, + ValueRichtextMixin, +}; diff --git a/src/new-widgets/templatesDependencies/linkTextMixin.ts b/src/new-widgets/templatesDependencies/linkTextMixin.ts index dd8ad35624bd63d8ee1bd33185ad3ec424629645..48bb6150a453195e4d719f5110ad984959bc6546 100644 --- a/src/new-widgets/templatesDependencies/linkTextMixin.ts +++ b/src/new-widgets/templatesDependencies/linkTextMixin.ts @@ -6,11 +6,9 @@ const LinkTextMixin = { default: '', callback: function (newValue: string) { this.addToAttributes(newValue, 'linkText'); - } + }, }, }, -} +}; -export { - LinkTextMixin -} \ No newline at end of file +export { LinkTextMixin }; diff --git a/src/new-widgets/templatesDependencies/multipleFormMixin.ts b/src/new-widgets/templatesDependencies/multipleFormMixin.ts index 83e5d27fb135a07deceffe77835523ef84a57b1b..f921743fbb6b2c347c5de65bfd50961b9572092d 100644 --- a/src/new-widgets/templatesDependencies/multipleFormMixin.ts +++ b/src/new-widgets/templatesDependencies/multipleFormMixin.ts @@ -1,111 +1,122 @@ -import { StoreMixin } from '../../mixins/storeMixin'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import { StoreMixin } from '../../mixins/storeMixin.ts'; const MultipleFormMixin = { name: 'multiple-form-mixin', - use: [ StoreMixin ], + use: [StoreMixin], attributes: { widget: { type: String, - default: 'solid-form-text' + default: 'solid-form-text', }, addLabel: { type: String, default: '+', - callback: function(value) { - if (value !== this.listAttributes['addLabel']) this.listAttributes['addLabel'] = value; + callback: function (value) { + if (value !== this.listAttributes.addLabel) + this.listAttributes.addLabel = value; this.planRender(); - } + }, }, removeLabel: { type: String, default: '×', - callback: function(value) { - if (value !== this.listAttributes['removeLabel']) this.listAttributes['removeLabel'] = value; + callback: function (value) { + if (value !== this.listAttributes.removeLabel) + this.listAttributes.removeLabel = value; this.planRender(); - } + }, }, range: { type: String, default: '', - }, addClass: { type: String, default: undefined, - callback: function(value) { - if (value !== this.listAttributes['addClass']) this.listAttributes['addClass'] = value; + callback: function (value) { + if (value !== this.listAttributes.addClass) + this.listAttributes.addClass = value; this.planRender(); - } + }, }, removeClass: { type: String, default: undefined, - callback: function(value) { - if (value !== this.listAttributes['removeClass']) this.listAttributes['removeClass'] = value; + callback: function (value) { + if (value !== this.listAttributes.removeClass) + this.listAttributes.removeClass = value; this.planRender(); - } - } + }, + }, }, created() { - this.listValueTransformations.push(this.setDataSrc.bind(this)); + this.listValueTransformations.attach( + this.setDataSrc.bind(this), + 'MultipleFormMixin:setDataSrc', + ); - this.listAttributes['children'] = []; - this.listAttributes['addLabel'] = this.addLabel; - this.listAttributes['removeLabel'] = this.removeLabel; - this.listAttributes['addClass'] = this.addClass; - this.listAttributes['removeClass'] = this.removeClass; - this.listAttributes['addItem'] = () => { + this.listAttributes.children = []; + this.listAttributes.addLabel = this.addLabel; + this.listAttributes.removeLabel = this.removeLabel; + this.listAttributes.addClass = this.addClass; + this.listAttributes.removeClass = this.removeClass; + this.listAttributes.addItem = () => { this.insertWidget(); this.planRender(); }; - this.listAttributes['removeItem'] = (index) => { - this.element.querySelector(`[data-index="${this.name + index}"]`).remove(); - this.element.dispatchEvent(new Event('change', {bubbles: true})); + this.listAttributes.removeItem = index => { + this.element + .querySelector(`[data-index="${this.name + index}"]`) + .remove(); + this.element.dispatchEvent(new Event('change', { bubbles: true })); }; }, - setDataSrc(value: string, listValueTransformations: Function[]) { + setDataSrc(value: string, listValueTransformations: PostProcessorRegistry) { if (value && value !== this.dataSrc) { try { if (Array.isArray(JSON.parse(value))) { this.setValue(JSON.parse(value)); } - } catch (ex) { + } catch { //FIXME: Awful trick to handle both resource @ids as value and serialized arrays values this.dataSrc = value; } } const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(value, listValueTransformations); + if (nextProcessor) nextProcessor(value, listValueTransformations); }, populate() { if (!this.resource || !this.resource['ldp:contains']) return; - this.listAttributes['children'] = []; // reset list + this.listAttributes.children = []; // reset list // set value in form - for (let resource of this.resource['ldp:contains']) { // for each resource + for (const resource of this.resource['ldp:contains']) { + // for each resource this.insertWidget(resource['@id']); // create a widget } this.planRender(); }, - insertWidget(value: string = '') { + insertWidget(value = '') { if (!this.widget) return; const widget = document.createElement(this.widget); const attributes = { 'data-holder': true, - 'name': this.name, - 'value': value, - 'range': this.range + name: this.name, + value: value, + range: this.range, }; - for (let name of Object.keys(attributes)) { - if (typeof attributes[name] === "boolean") widget.toggleAttribute(name, attributes[name]); + for (const name of Object.keys(attributes)) { + if (typeof attributes[name] === 'boolean') + widget.toggleAttribute(name, attributes[name]); else widget.setAttribute(name, attributes[name]); } - this.listAttributes['children'].push(widget); + this.listAttributes.children.push(widget); }, empty() { - this.listAttributes['children'] = []; + this.listAttributes.children = []; this.planRender(); }, getValue() { @@ -113,7 +124,7 @@ const MultipleFormMixin = { // Was returning an array of functions, now returns an array of values. // Not sure about the tests results in that context return Array.from(this.dataHolder).map((element: any) => { - let elValue = this.getValueFromElement(element); + const elValue = this.getValueFromElement(element); return elValue; }); }, @@ -122,10 +133,7 @@ const MultipleFormMixin = { }, get multiple() { return true; - } - -} + }, +}; -export { - MultipleFormMixin -} \ No newline at end of file +export { MultipleFormMixin }; diff --git a/src/new-widgets/templatesDependencies/multipleselectFormMixin.ts b/src/new-widgets/templatesDependencies/multipleselectFormMixin.ts index 79f3c6261b789dc963073894c05a697c848cf3fb..dce7ad4a92db859ec68c3d7bb4528c2876658d4f 100644 --- a/src/new-widgets/templatesDependencies/multipleselectFormMixin.ts +++ b/src/new-widgets/templatesDependencies/multipleselectFormMixin.ts @@ -1,61 +1,74 @@ -import { StoreMixin } from '../../mixins/storeMixin'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import type { Resource } from '../../mixins/interfaces.ts'; +import { StoreMixin } from '../../mixins/storeMixin.ts'; const MultipleselectFormMixin = { name: 'multipleselect-form-mixin', - use: [ StoreMixin ], + use: [StoreMixin], attributes: { - range: { // range attribute is passed to the solid-dropdown + range: { + // range attribute is passed to the solid-dropdown type: String, default: '', - callback: function(value) { - if (value && value !== this.listAttributes['range']) this.listAttributes['range'] = value; - } + callback: function (value: string) { + if (value && value !== this.listAttributes.range) + this.listAttributes.range = value; + }, }, - enum: { // enum attribute is passed to the solid-dropdown + enum: { + // enum attribute is passed to the solid-dropdown type: String, default: '', - callback: function (value) { - if (value && value !== this.listAttributes['enum']) this.listAttributes['enum'] = value; - } + callback: function (value: string) { + if (value && value !== this.listAttributes.enum) + this.listAttributes.enum = value; + }, }, orderAsc: { type: String, default: 'name', callback: function (newValue: string) { this.addToAttributes(newValue, 'orderAsc'); - } + }, }, orderDesc: { type: String, default: 'name', callback: function (newValue: string) { this.addToAttributes(newValue, 'orderDesc'); - } - } + }, + }, }, created() { - this.listValueTransformations.push(this.setDataSrc.bind(this)); + this.listValueTransformations.attach( + this.setDataSrc.bind(this), + 'MultipleselectFormMixin:setDataSrc', + ); }, - setDataSrc(value: string, listValueTransformations: Function[]) { + setDataSrc(value: string, listValueTransformations: PostProcessorRegistry) { if (value && value !== this.dataSrc) { try { - let values = JSON.parse(value); + const values = JSON.parse(value); if (values && Array.isArray(values)) { this.setValue(values); } else { this.setValue([value]); } - } catch (ex) { + } catch { this.dataSrc = value; - this.setValue([ {"@id": value}]); + this.setValue([{ '@id': value }]); } } const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(value, listValueTransformations); + if (nextProcessor) nextProcessor(value, listValueTransformations); }, populate() { - if (!this.resource || (!this.resource['ldp:contains'] && !Array.isArray(this.resource))) return; + if ( + !this.resource || + (!this.resource['ldp:contains'] && !Array.isArray(this.resource)) + ) + return; this.setValue(this.resource['ldp:contains']); // TODO: Rationalize or clean this commented code @@ -65,11 +78,12 @@ const MultipleselectFormMixin = { this.planRender(); }, - setValue(values: string[]) { // set the values to the dropdown - this.listAttributes['values'] = JSON.stringify(values.map(r => r['@id'])); + setValue(values: Resource[]) { + // set the values to the dropdown + this.listAttributes.values = JSON.stringify(values.map(r => r['@id'])); }, empty() { - this.listAttributes['values'] = []; + this.listAttributes.values = []; this.planRender(); }, get type() { @@ -78,8 +92,6 @@ const MultipleselectFormMixin = { get multiple() { return true; }, -} +}; -export { - MultipleselectFormMixin -} \ No newline at end of file +export { MultipleselectFormMixin }; diff --git a/src/new-widgets/templatesDependencies/patternMixin.ts b/src/new-widgets/templatesDependencies/patternMixin.ts index b2748ff9b0c147e0369f370ee16c9025fb3139a3..e9f4944f8d9f72ae8cf5f23760a6445fb1824206 100644 --- a/src/new-widgets/templatesDependencies/patternMixin.ts +++ b/src/new-widgets/templatesDependencies/patternMixin.ts @@ -1,21 +1,19 @@ const PatternMixin = { name: 'pattern-mixin', - attributes : { - pattern : { + attributes: { + pattern: { type: String, callback: function (newValue: string) { - this.addToAttributes(newValue, 'pattern') - } + this.addToAttributes(newValue, 'pattern'); + }, }, - title : { + title: { type: String, callback: function (newValue: string) { this.addToAttributes(newValue, 'title'); - } + }, }, }, -} +}; -export { - PatternMixin -} \ No newline at end of file +export { PatternMixin }; diff --git a/src/new-widgets/templatesDependencies/rangeMixin.ts b/src/new-widgets/templatesDependencies/rangeMixin.ts index 826765f374669c014f5ddfc070b76e842669f6cc..d7b9a2ab86fa893fe73e3bf3f319ce1709f97497 100644 --- a/src/new-widgets/templatesDependencies/rangeMixin.ts +++ b/src/new-widgets/templatesDependencies/rangeMixin.ts @@ -1,92 +1,86 @@ -import { base_context, store } from '../../libs/store/store'; -import { StoreMixin } from '../../mixins/storeMixin'; -import { SorterMixin } from '../../mixins/sorterMixin'; -import { FederationMixin } from '../../mixins/federationMixin'; -import type { Resource } from '../../mixins/interfaces'; +import { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; +import { base_context, store } from '../../libs/store/store.ts'; +import { FederationMixin } from '../../mixins/federationMixin.ts'; +import type { Resource } from '../../mixins/interfaces.ts'; +import { SorterMixin } from '../../mixins/sorterMixin.ts'; +import { StoreMixin } from '../../mixins/storeMixin.ts'; const RangeMixin = { name: 'range-mixin', - use: [ - StoreMixin, - SorterMixin, - FederationMixin - ], + use: [StoreMixin, SorterMixin, FederationMixin], attributes: { range: { type: String, default: '', callback: function (value: string) { if (value !== this.dataSrc) this.dataSrc = value; - } + }, }, enum: { type: String, default: '', callback: function (value: string) { if (value !== null) { - const optional = value.trim().split(","); - let key; - let keyValue; + const optional = value.trim().split(','); const list = {}; - optional.forEach(element => { - if (element.includes("=")) { - const option = element.trim().split("="); - key = option[1].trim(); - keyValue = option[0].trim(); + for (const element of optional) { + if (element.includes('=')) { + const option = element.trim().split('='); + const key = option[1].trim(); + const keyValue = option[0].trim(); list[key] = keyValue; } else { const elem = element.trim(); list[elem] = elem; } - }); + } this.addToAttributes(list, 'enum'); - }; - } + } + }, }, optionLabel: { type: String, default: 'name', callback: function (newValue: string) { this.addToAttributes(newValue, 'optionLabel'); - } + }, }, optionValue: { type: String, default: '@id', callback: function (newValue: string) { this.addToAttributes(newValue, 'optionValue'); - } - } + }, + }, }, initialState: { - listPostProcessors: [], + listPostProcessors: new PostProcessorRegistry(), }, created() { - this.listPostProcessors = []; - this.listAttributes['optionLabel'] = this.optionLabel; - this.listAttributes['optionValue'] = this.optionValue; + this.listPostProcessors = new PostProcessorRegistry(); + this.listAttributes.optionLabel = this.optionLabel; + this.listAttributes.optionValue = this.optionValue; }, async populate() { const resources = this.resource ? this.resource['ldp:contains'] : []; - const listPostProcessors = [...this.listPostProcessors]; - listPostProcessors.push(this.setRangeAttribute.bind(this)); - - const nextProcessor = listPostProcessors.shift(); - await nextProcessor( - resources, - listPostProcessors, - null, - this.dataSrc, + const listPostProcessorsCopy = this.listPostProcessors.deepCopy(); + listPostProcessorsCopy.attach( + this.setRangeAttribute.bind(this), + 'RangeMixin:setRangeAttribute', ); + + const nextProcessor = listPostProcessorsCopy.shift(); + await nextProcessor(resources, listPostProcessorsCopy, null, this.dataSrc); }, - async setRangeAttribute( - resources: Resource[] - ) { + async setRangeAttribute(resources: Resource[]) { if (resources) { // process resources to create the template const getRangeValue = async (resource: Resource) => { - let res = await store.getData(resource['@id'], this.context || base_context); + let res = await store.getData( + resource['@id'], + this.context || base_context, + ); //TODO: handle properly the fact that the res could be null if (res === null) { res = resource; @@ -94,32 +88,32 @@ const RangeMixin = { //TODO: this splitting and expanding is disgusting, please find another solution !! const selectedValue = await resource[this.optionValue]; // value used for selected options - const value = (this.optionValue.includes('@id') || selectedValue['@id']) ? - `{"@id": "${selectedValue}"}` : // resource - selectedValue; // literal + const value = + this.optionValue.includes('@id') || selectedValue['@id'] + ? `{"@id": "${selectedValue}"}` + : // resource + selectedValue; // literal //TODO: this splitting and expanding is disgusting, please find another solution !! - let labelProperty = this.optionLabel.split(/[.]+/).pop() + const labelProperty = this.optionLabel.split(/[.]+/).pop(); const label = await res[labelProperty]; // label of the option - return { value, label, selectedValue } - } + return { value, label, selectedValue }; + }; - this.listAttributes['range'] = await Promise.all( - resources.filter(el => el !== null).map(r => getRangeValue(r)) + this.listAttributes.range = await Promise.all( + resources.filter(el => el !== null).map(r => getRangeValue(r)), ); } this.planRender(); }, empty() { - this.listAttributes['range'] = []; + this.listAttributes.range = []; this.planRender(); }, get type() { - return this.enum === ''? 'resource' : 'string'; - } -} + return this.enum === '' ? 'resource' : 'string'; + }, +}; -export { - RangeMixin -} \ No newline at end of file +export { RangeMixin }; diff --git a/src/new-widgets/templatesDependencies/setMixin.ts b/src/new-widgets/templatesDependencies/setMixin.ts index 4505df53fc9bff9844c054d8d6838cf1ffc6faee..712472d80f3376cd00a6656bff8ece6e5ab36f1b 100644 --- a/src/new-widgets/templatesDependencies/setMixin.ts +++ b/src/new-widgets/templatesDependencies/setMixin.ts @@ -4,9 +4,7 @@ const SetMixin = { * For sets and group widgets, remove auto rendering * function to allow only manual renders */ - planRender() { }, -} + planRender() {}, +}; -export { - SetMixin -} \ No newline at end of file +export { SetMixin }; diff --git a/src/new-widgets/templatesDependencies/valueRichtextMixin.ts b/src/new-widgets/templatesDependencies/valueRichtextMixin.ts index 740a12ae62bb865861fb260b5ad98d30e94ebf4e..c1389df40de7e97d4485db2f01d29ed953de302d 100644 --- a/src/new-widgets/templatesDependencies/valueRichtextMixin.ts +++ b/src/new-widgets/templatesDependencies/valueRichtextMixin.ts @@ -1,13 +1,11 @@ import qdtm from 'quill-delta-to-markdown'; const ValueRichtextMixin = { name: 'valuerichtext-mixin', - + getValue() { const markdown = qdtm.deltaToMarkdown(this.quill.getContents().ops); return markdown; }, -} +}; -export { - ValueRichtextMixin -} \ No newline at end of file +export { ValueRichtextMixin }; diff --git a/src/new-widgets/valueTransformationMixins/autolinkMixin.ts b/src/new-widgets/valueTransformationMixins/autolinkMixin.ts index 1ffeb16fad862086bc7c2a2afeaf0fcab04c13d5..148d8061ef9afd8b9d8e813e88bc760a393a1152 100644 --- a/src/new-widgets/valueTransformationMixins/autolinkMixin.ts +++ b/src/new-widgets/valueTransformationMixins/autolinkMixin.ts @@ -1,16 +1,24 @@ -import {Autolinker} from 'autolinker'; +import { Autolinker } from 'autolinker'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const AutolinkMixin = { name: 'autolink-mixin', created() { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'AutolinkMixin:transformValue', + ); }, - transformValue(value: string, listValueTransformations: Function[]) { + transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { const template = document.createElement('template'); - template.innerHTML = Autolinker.link(value); + template.innerHTML = Autolinker.link(value); const nextProcessor = listValueTransformations.shift(); - if (nextProcessor) nextProcessor(template.content, listValueTransformations); + if (nextProcessor) + nextProcessor(template.content, listValueTransformations); }, }; diff --git a/src/new-widgets/valueTransformationMixins/dateMixin.ts b/src/new-widgets/valueTransformationMixins/dateMixin.ts index 0ac4961c580569fa47bf802adba9aba76e020177..5150b76db0c5c6863c3fb17e1d5d08c3fe7e2ebb 100644 --- a/src/new-widgets/valueTransformationMixins/dateMixin.ts +++ b/src/new-widgets/valueTransformationMixins/dateMixin.ts @@ -1,35 +1,41 @@ +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; + const DateMixin = { name: 'date-mixin', created() { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'DateMixin:transformValue', + ); }, - transformValue(value: string, listValueTransformations: Function[]) { + transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { try { // workaround for giving a specific-formatted value to the form widget - this.listAttributes['originalValue'] = this.formatDateForInput(value); - } catch (e) { + this.listAttributes.originalValue = this.formatDateForInput(value); + } catch { console.warn('Invalid date format for widget', this.name); - this.listAttributes['originalValue'] = ''; + this.listAttributes.originalValue = ''; } const newValue = value ? new Date(value).toLocaleDateString() : value; const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(newValue, listValueTransformations); + if (nextProcessor) nextProcessor(newValue, listValueTransformations); }, formatDateForInput(date: string) { - let d = new Date(date); - if (isNaN(d.getTime())) throw new Error('Invalid date'); + const d = new Date(date); + if (Number.isNaN(d.getTime())) throw new Error('Invalid date'); let month = `${d.getMonth() + 1}`; let day = `${d.getDate()}`; - let year = d.getFullYear(); + const year = d.getFullYear(); if (month.length < 2) month = `0${month}`; if (day.length < 2) day = `0${day}`; return [year, month, day].join('-'); - } -} + }, +}; -export { - DateMixin -} \ No newline at end of file +export { DateMixin }; diff --git a/src/new-widgets/valueTransformationMixins/dateTimeMixin.ts b/src/new-widgets/valueTransformationMixins/dateTimeMixin.ts index de6872f747ab4f0241eea440a1400e1a893de034..b09c979c7532044a9e6ecea5612313eb433f2675 100644 --- a/src/new-widgets/valueTransformationMixins/dateTimeMixin.ts +++ b/src/new-widgets/valueTransformationMixins/dateTimeMixin.ts @@ -1,16 +1,22 @@ +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; + const DateTimeMixin = { name: 'date-time-mixin', created() { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'DateTimeMixin:transformValue', + ); }, - transformValue(value: string, listValueTransformations: Function[]) { + transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { const newValue = value ? new Date(value).toLocaleString() : value; const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(newValue, listValueTransformations); - } -} + if (nextProcessor) nextProcessor(newValue, listValueTransformations); + }, +}; -export { - DateTimeMixin -} \ No newline at end of file +export { DateTimeMixin }; diff --git a/src/new-widgets/valueTransformationMixins/index.ts b/src/new-widgets/valueTransformationMixins/index.ts index eeabf92aadde10b133e2073d73d2f34ce96d7413..16dba1dfb3213806fcd55df289329c6464527bf0 100644 --- a/src/new-widgets/valueTransformationMixins/index.ts +++ b/src/new-widgets/valueTransformationMixins/index.ts @@ -1,9 +1,9 @@ -import { DateMixin } from './dateMixin'; -import { DateTimeMixin } from './dateTimeMixin'; -import { MultilineMixin } from './multilineMixin'; +import { AutolinkMixin } from './autolinkMixin.ts'; +import { DateMixin } from './dateMixin.ts'; +import { DateTimeMixin } from './dateTimeMixin.ts'; import { MarkdownMixin } from './markdownMixin.js'; -import { OembedMixin } from './oembedMixin'; -import { AutolinkMixin } from './autolinkMixin'; +import { MultilineMixin } from './multilineMixin.ts'; +import { OembedMixin } from './oembedMixin.ts'; const valueTransformationDirectory = { date: DateMixin, @@ -11,8 +11,8 @@ const valueTransformationDirectory = { multiline: MultilineMixin, markdown: MarkdownMixin, oembed: OembedMixin, - autolink: AutolinkMixin -} + autolink: AutolinkMixin, +}; export { valueTransformationDirectory, @@ -21,5 +21,5 @@ export { MultilineMixin, MarkdownMixin, OembedMixin, - AutolinkMixin -} + AutolinkMixin, +}; diff --git a/src/new-widgets/valueTransformationMixins/markdownMixin.ts b/src/new-widgets/valueTransformationMixins/markdownMixin.ts index def05d0a6943c219b6397cff456e405e07371145..7b2382b544277a66c3e6d46ab791bf6f3645b4de 100644 --- a/src/new-widgets/valueTransformationMixins/markdownMixin.ts +++ b/src/new-widgets/valueTransformationMixins/markdownMixin.ts @@ -1,14 +1,21 @@ -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import markdownit from 'markdown-it'; import mila from 'markdown-it-link-attributes'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const MarkdownMixin = { name: 'markdown-mixin', created() { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'MarkdownMixin:transformValue', + ); }, - transformValue(value: string, listValueTransformations: Function[]) { + transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { let newValue: any = ''; if (value) { const md = markdownit({ @@ -21,7 +28,7 @@ const MarkdownMixin = { attrs: { target: '_blank', rel: 'noopener', - } + }, }); const html = md.render(value); @@ -29,10 +36,8 @@ const MarkdownMixin = { } const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(newValue, listValueTransformations); - } -} + if (nextProcessor) nextProcessor(newValue, listValueTransformations); + }, +}; -export { - MarkdownMixin -} \ No newline at end of file +export { MarkdownMixin }; diff --git a/src/new-widgets/valueTransformationMixins/multilineMixin.ts b/src/new-widgets/valueTransformationMixins/multilineMixin.ts index 6c97b4753a85d9dbbe0f832d67e8286a75034a34..c6cee1fb5e3e396e6b703760abeecfb1e2caaed8 100644 --- a/src/new-widgets/valueTransformationMixins/multilineMixin.ts +++ b/src/new-widgets/valueTransformationMixins/multilineMixin.ts @@ -1,18 +1,23 @@ -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const MultilineMixin = { name: 'multiline-mixin', created() { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'MultilineMixin:transformValue', + ); }, - transformValue(value: string, listValueTransformations: Function[]) { - const newValue = value ? unsafeHTML(value.replace(/\n/g, "<br/>")) : value; + transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { + const newValue = value ? unsafeHTML(value.replace(/\n/g, '<br/>')) : value; const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(newValue, listValueTransformations); - } -} + if (nextProcessor) nextProcessor(newValue, listValueTransformations); + }, +}; -export { - MultilineMixin -} \ No newline at end of file +export { MultilineMixin }; diff --git a/src/new-widgets/valueTransformationMixins/oembedMixin.ts b/src/new-widgets/valueTransformationMixins/oembedMixin.ts index 8a8c08fc2b3feea9d36d9277cf73d8180e597fb5..27ad92dba0e893682564ad78c6dfe0889694eec4 100644 --- a/src/new-widgets/valueTransformationMixins/oembedMixin.ts +++ b/src/new-widgets/valueTransformationMixins/oembedMixin.ts @@ -1,26 +1,31 @@ -import { unsafeHTML } from 'lit-html/directives/unsafe-html'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import type { PostProcessorRegistry } from '../../libs/PostProcessorRegistry.ts'; const OembedMixin = { name: 'oembed-mixin', - initialState : { + initialState: { existingOembed: null, }, created(): void { - this.listValueTransformations.push(this.transformValue.bind(this)); + this.listValueTransformations.attach( + this.transformValue.bind(this), + 'OembedMixin:transformValue', + ); }, - async transformValue(value: string, listValueTransformations: Function[]) { + async transformValue( + value: string, + listValueTransformations: PostProcessorRegistry, + ) { if (!value) return; if (this.existingOembed == null) { const response = await fetch(this.value); this.existingOembed = await response.json(); } const newValue = unsafeHTML(this.existingOembed.html); - + const nextProcessor = listValueTransformations.shift(); - if(nextProcessor) nextProcessor(newValue, listValueTransformations); - } -} + if (nextProcessor) nextProcessor(newValue, listValueTransformations); + }, +}; -export { - OembedMixin -} \ No newline at end of file +export { OembedMixin }; diff --git a/src/solid-template-element.ts b/src/solid-template-element.ts index 6130290801a370bf5c3f9aecf4e6896845c35f56..bf9d2560857a15e60a7c41d7cee33004376e4aef 100644 --- a/src/solid-template-element.ts +++ b/src/solid-template-element.ts @@ -5,23 +5,22 @@ export default class SolidTemplateElement extends HTMLElement { strings = {}; translationsPath = null; translationsFetched = false; - props : {[key:string]:any} = {} + props: { [key: string]: unknown } = {}; constructor() { super(); this.initProps(); } static get observedAttributes() { - return Object.values(this.propsDefinition); + return Object.values(SolidTemplateElement.propsDefinition); } - static get propsDefinition():{[key:string]:any} { - return { - }; + static get propsDefinition(): { [key: string]: unknown } { + return {}; } initProps() { - this.props = {} - for(let key in this.constructor.propsDefinition) { + this.props = {}; + for (const key in this.constructor.propsDefinition) { this.props[key] = undefined; } } @@ -30,20 +29,29 @@ export default class SolidTemplateElement extends HTMLElement { const declaredAttributes: string[] = []; // Get props values - for(let key in this.constructor.propsDefinition) { + for (const key in this.constructor.propsDefinition) { const def = this.constructor.propsDefinition[key]; - if (typeof def === "string") { - this.props[key] = this.hasAttribute(def) ? this.getAttribute(def) : undefined; + if (typeof def === 'string') { + this.props[key] = this.hasAttribute(def) + ? this.getAttribute(def) + : undefined; declaredAttributes.push(def); - } else if (typeof def === "object" && def.attribute && typeof def.attribute === "string") { - this.props[key] = this.hasAttribute(def.attribute) ? this.getAttribute(def.attribute) : def.default || undefined; + } else if ( + typeof def === 'object' && + def.attribute && + typeof def.attribute === 'string' + ) { + this.props[key] = this.hasAttribute(def.attribute) + ? this.getAttribute(def.attribute) + : def.default || undefined; declaredAttributes.push(def.attribute); } } // Add attributes to props - for (let attr of this.attributes) { - if (!declaredAttributes.includes(attr.name)) { // if attribute not in propsDefinition + for (const attr of this.attributes) { + if (!declaredAttributes.includes(attr.name)) { + // if attribute not in propsDefinition this.props[this._camelize(attr.name)] = attr.value || undefined; // add it to props } } @@ -62,19 +70,21 @@ export default class SolidTemplateElement extends HTMLElement { */ async fetchLocaleStrings() { if (this.translationsFetched) return; - const filesToFetch:any[] = []; - if (this.translationsPath) // fetch component translations + const filesToFetch: unknown[] = []; + if (this.translationsPath) + // fetch component translations filesToFetch.push(this.fetchTranslationFile(this.translationsPath)); const extraTranslationsPath = this.getAttribute('extra-translations-path'); - if (extraTranslationsPath) // fetch developer translations + if (extraTranslationsPath) + // fetch developer translations filesToFetch.push(this.fetchTranslationFile(extraTranslationsPath)); // merge all translations return Promise.all(filesToFetch).then(res => { this.translationsFetched = true; this.strings = Object.assign({}, ...res); - }) + }); } /** @@ -84,19 +94,31 @@ export default class SolidTemplateElement extends HTMLElement { const ln = this.getLocale(); const fullPath = `${path}/${ln}.json`; return fetch(fullPath) - .then((result) => { + .then(result => { if (result.ok) { - return result.json() // parse content - .catch(e => console.error(`Error while parsing the translation file: ${fullPath}`)); + return result + .json() // parse content + .catch(() => + console.error( + `Error while parsing the translation file: ${fullPath}`, + ), + ); } - }).catch(e => console.error(`Error while retrieving the translation file: ${fullPath}`)); + }) + .catch(() => + console.error( + `Error while retrieving the translation file: ${fullPath}`, + ), + ); } /** * Returns current locale of app */ getLocale() { - return localStorage.getItem('language') || window.navigator.language.slice(0, 2); + return ( + localStorage.getItem('language') || window.navigator.language.slice(0, 2) + ); } /** @@ -107,8 +129,7 @@ export default class SolidTemplateElement extends HTMLElement { return this.strings[key] || key; } - attributeChangedCallback() - { + attributeChangedCallback() { this.updateProps(); this.planRender(); } @@ -131,10 +152,11 @@ export default class SolidTemplateElement extends HTMLElement { } } - renderCallback() { } + renderCallback() {} render() { - this.fetchLocaleStrings().finally(() => { // render even if some errors occurred + this.fetchLocaleStrings().finally(() => { + // render even if some errors occurred this.innerHTML = this.template(this.props); this.renderCallback(); }); @@ -145,6 +167,6 @@ export default class SolidTemplateElement extends HTMLElement { } _camelize(str) { - return str.replace(/\W+(.)/g, (match, chr) => chr.toUpperCase()); + return str.replace(/\W+(.)/g, (_match, chr) => chr.toUpperCase()); } } diff --git a/src/solid.d.ts b/src/solid.d.ts index 78626222dd32568e60ca5eb8be049e0af3010419..fc9ef8f46699264177c4e8e1292eac0d1f18be68 100644 --- a/src/solid.d.ts +++ b/src/solid.d.ts @@ -1 +1 @@ -declare var solid: any; +declare let solid: unknown; diff --git a/src/store.d.ts b/src/store.d.ts index 53e696f57a33b7cf0e62f3c32b47ed5b1c7e3ac5..3190a1f81a6666fdffe77ba5deb530317c1e9a81 100644 --- a/src/store.d.ts +++ b/src/store.d.ts @@ -1,6 +1,6 @@ -declare var sibStore: any; +declare let sibStore: import('./libs/store/store').Store; interface StoreOptions { - fetchMethod?: Promise<any> - session?: Promise<any> + fetchMethod?: Promise<any>; + session?: Promise<any>; } diff --git a/src/style/default-theme.css b/src/style/default-theme.css deleted file mode 100644 index da97c8749d3bd976ff5a7f237ce26fd5648e632d..0000000000000000000000000000000000000000 --- a/src/style/default-theme.css +++ /dev/null @@ -1,24 +0,0 @@ -/*==== SOLID-MAP ====*/ -/* map custom marker */ -.sib-custom-marker { - position: absolute; - top: 40%; - left: 50%; - margin-left: 115px; - border-radius: 50%; - border: 8px solid #1c78c9; - width: 8px; - height: 8px; -} -.sib-custom-marker::after { - position: absolute; - content: ''; - width: 0px; - height: 0px; - bottom: -30px; - left: -6px; - border: 10px solid transparent; - border-top-width: 17px; - border-top-style: solid; - border-top-color: inherit; -} \ No newline at end of file diff --git a/src/widgets/baseWidget.ts b/src/widgets/baseWidget.ts index 1f0a0c030639b855d12b2c2b073e915426faa1e2..50553b821e68d87ca1d6253ac7ecc7bf6c5cb304 100644 --- a/src/widgets/baseWidget.ts +++ b/src/widgets/baseWidget.ts @@ -1,5 +1,5 @@ -import { evalTemplateString } from '../libs/helpers'; -import { store } from '../libs/store/store'; +import { evalTemplateString } from '../libs/helpers.ts'; +import { store } from '../libs/store/store.ts'; export class BaseWidget extends HTMLElement { private src: string | undefined; @@ -16,9 +16,9 @@ export class BaseWidget extends HTMLElement { this.render(); } disconnectedCallback(): void { - this._subscriptions.forEach((subscription) => { + for (const subscription of this._subscriptions.values()) { PubSub.unsubscribe(subscription); - }) + } } async render() { this.innerHTML = await evalTemplateString(this.template, { @@ -27,12 +27,12 @@ export class BaseWidget extends HTMLElement { label: this.label, placeholder: this.placeholder, value: this.value, - id: (this._value && this._value['@id']) || '', + id: this._value?.['@id'] || '', escapedValue: this.escapedValue, range: await this.htmlRange, multiple: this.multiple, - editable: this.editable === '' ? true : false, - required: this.required === '' ? true : false + editable: this.editable === '', + required: this.required === '', }); this.addEditButtons(); @@ -42,27 +42,30 @@ export class BaseWidget extends HTMLElement { return this.hasAttribute('label') ? this.getAttribute('label') : this.name; } set label(label: string | null) { - if(label != null) this.setAttribute('label', label); + if (label != null) this.setAttribute('label', label); this.render(); } get placeholder(): string | null { - return this.hasAttribute('placeholder') ? this.getAttribute('placeholder') : this.label; + return this.hasAttribute('placeholder') + ? this.getAttribute('placeholder') + : this.label; } set placeholder(placeholder: string | null) { - if(placeholder != null) this.setAttribute('placeholder', placeholder); + if (placeholder != null) this.setAttribute('placeholder', placeholder); this.render(); } get name(): string | null { return this.getAttribute('name'); } set name(name: string | null) { - if(name) this.setAttribute('name', name); + if (name) this.setAttribute('name', name); this.render(); } get value() { if (this.dataHolder) { - let values = this.dataHolder.map(element => { - if (element instanceof HTMLInputElement && element.type == "checkbox") return element.checked; + const values = this.dataHolder.map(element => { + if (element instanceof HTMLInputElement && element.type === 'checkbox') + return element.checked; // if value is defined, push it in the array return this.getValueHolder(element).value; }); @@ -73,12 +76,12 @@ export class BaseWidget extends HTMLElement { } set value(value) { this._value = value; // ... store `value` in the widget - if (this._value == null || this._value == undefined) return; + if (this._value == null) return; if (this.dataHolder && this.dataHolder.length === 1) { // if one dataHolder in the widget... const element = this.getValueHolder(this.dataHolder[0]); - if (element.type == "checkbox") { + if (element.type === 'checkbox') { element.checked = value; } else { element.value = value; // ... set `value` to the dataHolder element @@ -87,41 +90,47 @@ export class BaseWidget extends HTMLElement { if (element.dispatchEvent) element.dispatchEvent(new Event('change')); // trigger change manually } else if (this.dataHolder && this.dataHolder.length > 1) { // if multiple dataHolder in the widget ... - this.dataHolder.forEach( - (el, index) => { - const element = this.getValueHolder(el); - if (element.type == "checkbox") { - element.checked = value ? value[index] : '' - } else { - element.value = value ? value[index] : '' - } - element.dispatchEvent(new Event('change')); // trigger change manually - }, - ); // ... set each `value` to each dataHolder element + this.dataHolder.forEach((el, index) => { + const element = this.getValueHolder(el); + if (element.type === 'checkbox') { + element.checked = value ? value[index] : ''; + } else { + element.value = value ? value[index] : ''; + } + element.dispatchEvent(new Event('change')); // trigger change manually + }); // ... set each `value` to each dataHolder element } this.render(); } - get ['each-label'](): string{ + get 'each-label'(): string { return this.getAttribute('each-label') || ''; } - set ['each-label'](label: string) { + set 'each-label'(label: string) { this.setAttribute('each-label', label); } - set ['add-label'](label: string) { + set 'add-label'(label: string) { this.setAttribute('add-label', label); } - set ['remove-label'](label: string) { + set 'remove-label'(label: string) { this.setAttribute('remove-label', label); } get dataHolder(): Element[] | null { - const widgetDataHolders = Array.from(this.querySelectorAll('[data-holder]')).filter(element => { - const dataHolderAncestor = element.parentElement ? element.parentElement.closest('[data-holder]') : null; + const widgetDataHolders = Array.from( + this.querySelectorAll('[data-holder]'), + ).filter(element => { + const dataHolderAncestor = element.parentElement + ? element.parentElement.closest('[data-holder]') + : null; // get the dataHolder of the widget only if no dataHolder ancestor in the current widget - return dataHolderAncestor === this || !dataHolderAncestor || !this.contains(dataHolderAncestor) + return ( + dataHolderAncestor === this || + !dataHolderAncestor || + !this.contains(dataHolderAncestor) + ); }); - return widgetDataHolders.length ? widgetDataHolders : null; + return widgetDataHolders.length > 0 ? widgetDataHolders : null; } get template(): string { return ''; @@ -130,7 +139,7 @@ export class BaseWidget extends HTMLElement { return ''; } get escapedValue(): string { - return ('' + this.value) + return `${this.value}` .replace(/&/g, '&') .replace(/'/g, ''') .replace(/"/g, '"'); @@ -147,26 +156,36 @@ export class BaseWidget extends HTMLElement { } set range(range) { (async () => { - this._listen(range, async () => this._range = await store.getData(range, this.context)); + this._listen(range, async () => { + this._range = await store.getData(range, this.context); + }); this._range = await store.getData(range, this.context); this.render(); })(); } async fetchSources(resource: any) { if (!resource || !resource['ldp:contains']) return null; - let resources: any[] = []; + const resources: any[] = []; let index = 0; for (let res of resource['ldp:contains']) { - if (!res) { // child not in cache yet + if (!res) { + // child not in cache yet try { const resourceId = resource.getChildren('ldp:contains')[index]['@id']; - res = await store.getData(resourceId, this.context) - } catch (e) { continue; } + res = await store.getData(resourceId, this.context); + } catch { + continue; + } } - if (res.isContainer?.()) { // if nested container - let resourcesFromContainer = await store.getData(res['@id'], this.context); // fetch the datas + if (res.isContainer?.()) { + // if nested container + const resourcesFromContainer = await store.getData( + res['@id'], + this.context, + ); // fetch the datas this._listen(res['@id']); - if (resourcesFromContainer) resources.push(...resourcesFromContainer['ldp:contains']); + if (resourcesFromContainer) + resources.push(...resourcesFromContainer['ldp:contains']); } else { resources.push(res); } @@ -175,35 +194,35 @@ export class BaseWidget extends HTMLElement { return resources; } - get htmlRange(): Promise<string | undefined> { - return (async () => { - let htmlRange = ''; - const rangeResources = await this.range; - if (!rangeResources) return; - for await (let element of rangeResources) { - element = await store.getData(element['@id'], this.context); // fetch the resource to display the name - this._listen(element['@id']); + async htmlRange(): Promise<string | undefined> { + let htmlRange = ''; + const rangeResources = await this.range; + if (!rangeResources) return; + for await (let element of rangeResources) { + element = await store.getData(element['@id'], this.context); // fetch the resource to display the name + this._listen(element['@id']); - let selected: boolean; - if (this._value && this._value.isContainer && this._value.isContainer()) { // selected options for multiple select - selected = false; - for await (let value of this._value["ldp:contains"]) { - if (value['@id'] == element['@id']) { - selected = true; - break; - } + let selected: boolean; + if (this._value?.isContainer?.()) { + // selected options for multiple select + selected = false; + for await (const value of this._value['ldp:contains']) { + if (value['@id'] === element['@id']) { + selected = true; + break; } - } else { // selected options for simple dropdowns - selected = this._value ? this._value['@id'] == element['@id'] : false; } - htmlRange += await evalTemplateString(this.childTemplate, { - name: await element.name, - id: element['@id'], - selected: selected - }); + } else { + // selected options for simple dropdowns + selected = this._value ? this._value['@id'] === element['@id'] : false; } - return htmlRange || ''; - })(); + htmlRange += await evalTemplateString(this.childTemplate, { + name: await element.name, + id: element['@id'], + selected: selected, + }); + } + return htmlRange || ''; } getValueHolder(element) { return element.component ? element.component : element; @@ -215,10 +234,13 @@ export class BaseWidget extends HTMLElement { _listen(id: string, callback: Function = () => {}) { if (!this._subscriptions.get(id)) { - this._subscriptions.set(id, PubSub.subscribe(id, async () => { - await callback(); - this.render(); - })) + this._subscriptions.set( + id, + PubSub.subscribe(id, async () => { + await callback(); + this.render(); + }), + ); } } @@ -229,18 +251,24 @@ export class BaseWidget extends HTMLElement { if (editableField) { // Add edit button const editButton = document.createElement('button'); - editButton.innerText = "Modifier"; - editButton.onclick = () => this.activateEditableField(editableField, editButton); + editButton.innerText = 'Modifier'; + editButton.onclick = () => + this.activateEditableField(editableField, editButton); editableField.insertAdjacentElement('afterend', editButton); // Save on focusout - editableField.addEventListener('focusout', () => this.save(editableField, editButton)); + editableField.addEventListener('focusout', () => + this.save(editableField, editButton), + ); } } - activateEditableField(editableField: HTMLElement, editButton: HTMLButtonElement): void { + activateEditableField( + editableField: HTMLElement, + editButton: HTMLButtonElement, + ): void { editableField.setAttribute('contenteditable', 'true'); editableField.focus(); - editButton.setAttribute("disabled", "disabled"); + editButton.setAttribute('disabled', 'disabled'); } /** * Dispatch change events of data holders from the current widget @@ -248,24 +276,24 @@ export class BaseWidget extends HTMLElement { initChangeEvents(): void { if (this.dataHolder) { const event = new Event('change', { bubbles: true }); - this.dataHolder.forEach(element => { + for (const element of this.dataHolder) { element.addEventListener('change', e => { e.preventDefault(); e.stopPropagation(); this.dispatchEvent(event); }); - }); + } } } save(editableField: HTMLElement, editButton: HTMLButtonElement): void { editableField.setAttribute('contenteditable', 'false'); - editButton.removeAttribute("disabled"); + editButton.removeAttribute('disabled'); if (!this.name) return; const resource = {}; resource[this.name] = editableField.innerText; resource['@context'] = this.context; - if(this.resourceId && resource) store.patch(resource, this.resourceId) + if (this.resourceId && resource) store.patch(resource, this.resourceId); } } diff --git a/src/widgets/widget-factory.ts b/src/widgets/widget-factory.ts index 01e4acc9264f2921d2c9c0d475013ae712627ff7..718433ee491dd78e6a4c0ca09262767de719ee4b 100644 --- a/src/widgets/widget-factory.ts +++ b/src/widgets/widget-factory.ts @@ -1,23 +1,23 @@ -import { BaseWidget } from './baseWidget'; -import { defineComponent } from '../libs/helpers'; +import { defineComponent } from '../libs/helpers.ts'; +import { BaseWidget } from './baseWidget.ts'; export const widgetFactory = ( tagName: string, customTemplate: string, - childTemplate: string = '', + childTemplate = '', callback?: (element: Element) => void, ) => { const registered = customElements.get(tagName); if (registered) return registered; const cls = class extends BaseWidget { - async render() { + override async render() { await super.render(); if (callback) callback(this); } - get template(): string { + override get template(): string { return customTemplate; } - get childTemplate(): string { + override get childTemplate(): string { return childTemplate; } }; diff --git a/src/window.d.ts b/src/window.d.ts index cbc4eb286e5ef6837aa447655c6b07e574612db2..3f370e97ef659af2faf1ef4372ae33be08e31cde 100644 --- a/src/window.d.ts +++ b/src/window.d.ts @@ -1,9 +1,11 @@ -declare var PubSub: any; -declare var markdownit: any; -declare var fetchTranslationPromise: Promise; -declare var cachePropsSearchFilter: { - [key: string]: { - setFields: string[] | null - setSearchFields: string[] | null +export declare global { + interface Window { + fetchTranslationPromise: Promise; + cachePropsSearchFilter: { + [key: string]: { + setFields: string[] | null; + setSearchFields: string[] | null; + }; + }; } -}; +} diff --git a/tsconfig.json b/tsconfig.json index 645ec74062d534af6d1c7214eca4859a5c5e1a49..6d6b34a6ca8eb02d62bd2df6e0302d2a586271c9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,26 +1,24 @@ { "compilerOptions": { - "target": "es2018", + "target": "es2022", "module": "ESNext", - "moduleResolution": "node", + "moduleResolution": "Bundler", + "isolatedModules": true, + "moduleDetection": "force", "allowJs": true, - "jsx": "preserve", "noEmit": true, - "declaration": false, - "declarationMap": false, + "allowImportingTsExtensions": true, "esModuleInterop": true, "composite": false, "strict": true, "noImplicitAny": false, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictPropertyInitialization": true, "noImplicitThis": false, - "alwaysStrict": true, + "noImplicitOverride": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, + "verbatimModuleSyntax": true, "resolveJsonModule": true, "baseUrl": "./", "paths": { @@ -29,6 +27,5 @@ "skipLibCheck": true, "types": ["cypress"] }, - "include": ["./src/**/*", "./cypress/**/*"], - "exclude": ["./node_modules/", "./cypress.config.ts"] + "include": ["./src/**/*", "./cypress/**/*"] } diff --git a/vite.config.ts b/vite.config.ts index 3447be027372b75e74f68bfbf0f5d517747aeb67..d6bb5745e9d1a3b2519e73551a0aa9248b1c3ba0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,4 @@ -import { resolve } from 'path'; +import { resolve } from 'node:path'; import { defineConfig } from 'vite'; export default defineConfig({ @@ -12,10 +12,7 @@ export default defineConfig({ }, rollupOptions: { preserveEntrySignatures: 'strict', - input: [ - './src/index.ts', - './src/libs/helpers.ts', - ], + input: ['./src/index.ts', './src/libs/helpers.ts'], output: { dir: 'dist', entryFileNames: '[name].js', @@ -23,5 +20,6 @@ export default defineConfig({ }, outDir: 'dist', minify: false, + reportCompressedSize: false, }, });