diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..9661ca5e8 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,8 @@ +docs/** +.svelte-kit/** +static/** +build/** +node_modules/** +coverage/** +__snapshots__/** +snapshots.js \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs index b9d78c7cc..46ad25472 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -7,7 +7,7 @@ module.exports = { // 'plugin:@typescript-eslint/recommended-requiring-type-checking', 'prettier' ], - plugins: ['svelte3', 'tailwindcss', '@typescript-eslint', 'es'], + plugins: ['svelte3', 'tailwindcss', '@typescript-eslint', 'es', 'vitest'], ignorePatterns: [ 'docs/*', '*.cjs', diff --git a/.github/workflows/cypress.yml b/.github/workflows/tests.yml similarity index 91% rename from .github/workflows/cypress.yml rename to .github/workflows/tests.yml index c8f215285..a69868c09 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: Cypress Tests +name: Tests on: pull_request: @@ -30,17 +30,18 @@ jobs: node-version: 16 cache: 'yarn' - - name: Build & Lint + - name: Lint & Test run: | yarn install - yarn build yarn lint + yarn test:unit # Install NPM dependencies, cache them correctly # and run all Cypress tests - name: Cypress run uses: cypress-io/github-action@v3 with: + build: yarn build start: yarn preview wait-on: 'http://localhost:3000' record: true diff --git a/.github/workflows/update-monaco-editor.yml b/.github/workflows/update-monaco-editor.yml index 646aa98fc..cb1586e6a 100644 --- a/.github/workflows/update-monaco-editor.yml +++ b/.github/workflows/update-monaco-editor.yml @@ -10,7 +10,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - run: ./bin/update-monaco + - uses: actions/setup-node@v2 + with: + node-version: 18 + - name: Update monaco version + run: | + yarn install + node ./bin/update-monaco.js - name: Commit changes uses: EndBug/add-and-commit@v9 with: diff --git a/.prettierignore b/.prettierignore index 1a41f98dd..9661ca5e8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,4 +3,6 @@ docs/** static/** build/** node_modules/** +coverage/** +__snapshots__/** snapshots.js \ No newline at end of file diff --git a/SECURITY.md b/SECURITY.md index 45953550d..dc478729d 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ Live editor only has a single version, which will be maintained. | Version | Supported | | ------- | ------------------ | -| latest | :white_check_mark: | +| latest | :white_check_mark: | ## Reporting a Vulnerability diff --git a/bin/update-monaco b/bin/update-monaco deleted file mode 100755 index dbddd5719..000000000 --- a/bin/update-monaco +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -monacoVersion="$(jq -r '.dependencies."monaco-editor"' package.json)" -monacoVersion="${monacoVersion:1}" - -if [[ $(uname) == "Darwin" ]]; -then - sed -i '' -E "s/monaco-editor\/[^/]*/monaco-editor\/$monacoVersion/g" ./src/app.html -else - sed -i'' -E "s/monaco-editor\/[^/]*/monaco-editor\/$monacoVersion/g" ./src/app.html -fi - diff --git a/bin/update-monaco.js b/bin/update-monaco.js new file mode 100755 index 000000000..3d81bdfc6 --- /dev/null +++ b/bin/update-monaco.js @@ -0,0 +1,45 @@ +import fs from 'fs'; +import path from 'path'; +import { parse } from 'node-html-parser'; +import prettier from 'prettier'; + +// parse monaco version out of package.json +const packageJson = JSON.parse(fs.readFileSync('package.json')); +const monacoVersion = packageJson.dependencies['monaco-editor'].replace('^', ''); + +// fetch monaco sri info from cdnjs api +const cdnjsAPIResp = await fetch( + `https://api.cdnjs.com/libraries/monaco-editor/${monacoVersion}?fields=sri` +); +if (cdnjsAPIResp.ok) { + const respJson = await cdnjsAPIResp.json(); + const htmlPath = path.join('src', 'app.html'); + const appHtml = fs + .readFileSync(htmlPath, 'utf8') + // update monaco version of every asset in app.html + .replaceAll(/[0-9.]+\/min\/vs/g, `${monacoVersion}/min/vs`); + const root = parse(appHtml); + const updateIntegrity = (tag, attr) => { + for (const node of root + .getElementsByTagName(tag) + .filter((node) => node.getAttribute(attr)?.includes('monaco-editor'))) { + const file = node.getAttribute(attr).split(`${monacoVersion}/`)[1]; + node.setAttribute('integrity', respJson.sri[file]); + } + }; + + updateIntegrity('script', 'src'); + updateIntegrity('link', 'href'); + + fs.writeFileSync( + htmlPath, + prettier.format(root.toString(), { + singleQuote: false, + parser: 'html', + bracketSameLine: true, + useTabs: true + }) + ); +} else { + throw Error('Unable to fetch monaco sri data from cdnjs api.'); +} diff --git a/cypress/.eslintrc b/cypress/.eslintrc index 2fc835730..43c008550 100644 --- a/cypress/.eslintrc +++ b/cypress/.eslintrc @@ -1,12 +1,10 @@ { - "plugins": ["cypress", "mocha"], - "extends": ["plugin:cypress/recommended", "plugin:mocha/recommended"], + "plugins": ["cypress"], + "extends": ["plugin:cypress/recommended"], "rules": { - "jest/expect-expect": "off", - "mocha/no-mocha-arrows": "off" + "jest/expect-expect": "off" }, "env": { - "cypress/globals": true, - "mocha": true + "cypress/globals": true } } diff --git a/cypress/e2e/diagramUpdate.spec.ts b/cypress/e2e/diagramUpdate.spec.ts index 2141526e4..36746daf5 100644 --- a/cypress/e2e/diagramUpdate.spec.ts +++ b/cypress/e2e/diagramUpdate.spec.ts @@ -1,4 +1,13 @@ describe('Auto sync tests', () => { + const cmd = Cypress.platform === 'darwin' ? 'meta' : 'ctrl'; + const getEditor = ({ bottom = true, newline = false } = {}) => + cy + .get('#editor textarea:first') + .click() + .focused() + .type(`${bottom ? '{pageDown}' : `{${cmd}}`}`) + .type(`${newline ? '{enter}' : `{${cmd}}`}`); + beforeEach(() => { cy.clearLocalStorage(); cy.visit('/'); @@ -7,7 +16,7 @@ describe('Auto sync tests', () => { it('should dim diagram when code is edited', () => { cy.contains('Auto sync').click(); cy.get('#view').should('not.have.class', 'outOfSync'); - cy.get('#editor').type(' C --> Test'); + getEditor().type(' C --> Test'); cy.get('#view').should('have.class', 'outOfSync'); cy.getLocalStorage('codeStore').snapshot(); }); @@ -19,26 +28,25 @@ describe('Auto sync tests', () => { cy.get('#autoSync').check(); cy.get('[data-cy=sync]').should('not.exist'); }); + it('should not dim diagram when code is in sync', () => { cy.contains('Auto sync').click(); cy.get('#view').should('not.have.class', 'outOfSync'); - cy.get('#editor').type(' C --> Test'); + getEditor().type(' C --> Test'); cy.get('#view').should('have.class', 'outOfSync'); cy.get('[data-cy=sync]').click(); cy.get('#view').should('not.have.class', 'outOfSync'); cy.get('#autoSync').check(); - cy.get('#editor').type('ing'); + getEditor().type('ing'); cy.get('#view').should('not.have.class', 'outOfSync'); cy.getLocalStorage('codeStore').snapshot(); }); it('supports commenting code out/in', () => { - const cmd = Cypress.platform === 'darwin' ? 'meta' : 'ctrl'; - - cy.get('#editor').type(`{uparrow}{${cmd}}/`); + getEditor().type(`{uparrow}{${cmd}}/`); cy.get('#view').contains('Car').should('not.exist'); - cy.get('#editor').type(`{uparrow}{${cmd}}/`); + getEditor().type(`{uparrow}{${cmd}}/`); cy.get('#view').contains('Car').should('exist'); }); @@ -47,7 +55,7 @@ describe('Auto sync tests', () => { '/edit#pako:eNpljjEKwzAMRa8SNOcEnlt6gK5eVFvYJsgOqkwpIXevg9smEE1PnyfxF3DFExgISW-CczQ2D21cYU7a-SGYXRwyvTp9jUhuKlVP-eHy7zA-leQsMEmg_QOM0BLG5FujZVMsaCQmC6ahR5ks2Lw2r84ela4-aREwKpVGwKrl_s7ut3fnkjAIcg_XDzuaUhs' ); cy.get('#errorContainer').should('not.exist'); - cy.get('#editor').type(`{enter}branch test`); + getEditor({ newline: true }).type(`branch test`); cy.get('#editor').contains('branch test').should('exist'); cy.get('#errorContainer') .contains( diff --git a/cypress/e2e/history.spec.ts b/cypress/e2e/history.spec.ts index 93b5f9514..a769a3c90 100644 --- a/cypress/e2e/history.spec.ts +++ b/cypress/e2e/history.spec.ts @@ -47,7 +47,6 @@ describe('Save History', () => { }); // TODO: Fix #639 - // eslint-disable-next-line mocha/no-skipped-tests xit('should auto save history', () => { cy.get('#editor').type(' C --> HistoryTest'); cy.tick(70000); diff --git a/cypress/e2e/themes.spec.ts b/cypress/e2e/themes.spec.ts index fb4e6c522..a5a5c77f0 100644 --- a/cypress/e2e/themes.spec.ts +++ b/cypress/e2e/themes.spec.ts @@ -32,7 +32,6 @@ describe('Test themes', () => { }); describe('Test dark mode', () => { - // eslint-disable-next-line mocha/no-hooks-for-single-case beforeEach(() => { cy.clearLocalStorage(); cy.visit('/edit', { diff --git a/package.json b/package.json index b802046a5..ce7a2fff9 100644 --- a/package.json +++ b/package.json @@ -11,59 +11,69 @@ "lint:fix": "prettier --write --cache --plugin-search-dir=. .;eslint --fix --ignore-path .gitignore .", "format": "prettier --write --cache --plugin-search-dir=. .", "pre-commit": "lint-staged", - "postinstall": "husky install; cypress cache prune", - "test": "cypress run", + "postinstall": "husky install; cypress cache prune; svelte-kit sync", + "test:unit": "vitest", + "test:ui": "vitest --ui", + "test:coverage": "vitest run --coverage", + "test:browser": "cypress run", + "test": "test:unit && test:browser", "cy": "cypress open" }, "devDependencies": { - "@cypress/snapshot": "^2.1.7", + "@cypress/snapshot": "2.1.7", "@sveltejs/adapter-static": "1.0.0-next.34", - "@sveltejs/kit": "1.0.0-next.359", - "@types/mermaid": "^8.2.9", - "@types/pako": "^1.0.3", - "@typescript-eslint/eslint-plugin": "^4.33.0", - "@typescript-eslint/parser": "^4.33.0", - "autoprefixer": "^10.4.7", - "chai": "^4.3.6", - "cssnano": "^5.1.12", - "cy-verify-downloads": "^0.1.8", + "@sveltejs/kit": "1.0.0-next.361", + "@testing-library/jest-dom": "5.16.4", + "@testing-library/svelte": "3.1.3", + "@types/mermaid": "8.2.9", + "@types/pako": "1.0.3", + "@typescript-eslint/eslint-plugin": "5.30.5", + "@typescript-eslint/parser": "5.30.5", + "@vitest/ui": "0.17.1", + "autoprefixer": "10.4.7", + "c8": "7.11.3", + "chai": "4.3.6", + "cssnano": "5.1.12", + "cy-verify-downloads": "0.1.8", "cypress": "10.3.0", - "cypress-localstorage-commands": "^2.1.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-cypress": "^2.12.1", - "eslint-plugin-es": "^4.1.0", - "eslint-plugin-mocha": "^10.0.5", - "eslint-plugin-postcss-modules": "^2.0.0", - "eslint-plugin-svelte3": "^3.4.1", - "eslint-plugin-tailwindcss": "^3.6.0", - "husky": "^8.0.1", + "cypress-localstorage-commands": "2.1.0", + "eslint": "8.19.0", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-cypress": "2.12.1", + "eslint-plugin-es": "4.1.0", + "eslint-plugin-postcss-modules": "2.0.0", + "eslint-plugin-svelte3": "4.0.0", + "eslint-plugin-tailwindcss": "3.6.0", + "eslint-plugin-vitest": "0.0.8", + "husky": "8.0.1", + "jsdom": "20.0.0", "lint-staged": "13.0.3", - "mocha": "^10.0.0", - "node-html-parser": "^5.3.3", - "postcss": "^8.4.14", - "postcss-load-config": "^4.0.1", - "prettier": "~2.7.1", - "prettier-plugin-svelte": "^2.7.0", - "svelte": "^3.48.0", + "node-html-parser": "5.3.3", + "postcss": "8.4.14", + "postcss-load-config": "4.0.1", + "prettier": "2.7.1", + "prettier-plugin-svelte": "2.7.0", + "svelte": "3.49.0", "svelte-preprocess": "4.10.7", - "tailwindcss": "^3.1.4", - "tslib": "^2.4.0", - "typescript": "^4.7.4", - "vite": "^2.9.13" + "tailwindcss": "3.1.5", + "tslib": "2.4.0", + "typescript": "4.7.4", + "vite": "2.9.13", + "vitest": "0.17.1", + "vitest-svelte-kit": "0.0.6" }, "dependencies": { - "@analytics/google-analytics": "^0.5.3", - "@macfja/svelte-persistent-store": "^1.3.0", - "analytics": "^0.8.1", + "@analytics/google-analytics": "0.5.3", + "@macfja/svelte-persistent-store": "1.3.0", + "analytics": "0.8.1", "daisyui": "2.17.0", - "js-base64": "^3.7.2", + "js-base64": "3.7.2", "mermaid": "9.1.3", - "moment": "^2.29.3", - "monaco-editor": "^0.33.0", - "monaco-mermaid": "^1.0.6", + "moment": "2.29.4", + "monaco-editor": "0.33.0", + "monaco-mermaid": "1.0.6", "pako": "2.0.4", - "random-word-slugs": "^0.1.6" + "random-word-slugs": "0.1.6" }, "lint-staged": { "*.{ts,svelte,js,css,md,json}": [ @@ -72,7 +82,7 @@ ] }, "volta": { - "node": "16.15.0", + "node": "18.5.0", "yarn": "1.22.10" }, "engines": { diff --git a/src/app.html b/src/app.html index e6054088a..38b8fb45d 100644 --- a/src/app.html +++ b/src/app.html @@ -15,30 +15,38 @@ + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" + integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" + crossorigin="anonymous" + referrerpolicy="no-referrer" /> - %sveltekit.head% diff --git a/src/global.d.ts b/src/global.d.ts index 63908c66c..17fa2e249 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1 +1,15 @@ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/no-unused-vars */ + /// +import type { TestingLibraryMatchers } from '@testing-library/jest-dom/matchers'; + +declare global { + namespace jest { + interface Matchers + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + extends TestingLibraryMatchers {} + } +} diff --git a/src/hooks.ts b/src/hooks.ts index 6eba0ddab..916b2c818 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -1,4 +1,4 @@ -import type { Handle } from '@sveltejs/kit/types/hooks'; +import type { Handle } from '@sveltejs/kit'; export const handle: Handle = async ({ event, resolve }) => { const response = await resolve(event, { diff --git a/src/lib/components/card/__snapshots__/card.test.ts.snap b/src/lib/components/card/__snapshots__/card.test.ts.snap new file mode 100644 index 000000000..eb662c95f --- /dev/null +++ b/src/lib/components/card/__snapshots__/card.test.ts.snap @@ -0,0 +1,3 @@ +// Vitest Snapshot v1 + +exports[`card.svelte > mounts 1`] = `"
TabTest
    title1
    title2
"`; diff --git a/src/lib/components/card/card.test.ts b/src/lib/components/card/card.test.ts new file mode 100644 index 000000000..98ffccd3d --- /dev/null +++ b/src/lib/components/card/card.test.ts @@ -0,0 +1,24 @@ +import { cleanup, render } from '@testing-library/svelte'; +import { describe, expect, it, afterEach } from 'vitest'; +import Card from './card.svelte'; + +describe('card.svelte', () => { + // TODO: @testing-library/svelte claims to add this automatically but it doesn't work without explicit afterEach + afterEach(() => cleanup()); + + it('mounts', () => { + const { container } = render(Card, { + title: 'TabTest', + tabs: [ + { id: 't1', title: 'title1' }, + { id: 't2', title: 'title2' } + ] + }); + expect(container).toBeTruthy(); + expect(container).toHaveTextContent('TabTest'); + expect(container).toHaveTextContent('title1'); + expect(container).toHaveTextContent('title2'); + expect(container).not.toHaveTextContent('title3'); + expect(container.innerHTML).toMatchSnapshot(); + }); +}); diff --git a/src/lib/types.d.ts b/src/lib/types.d.ts index 0f750f9e7..8e6643232 100644 --- a/src/lib/types.d.ts +++ b/src/lib/types.d.ts @@ -43,7 +43,7 @@ export interface State { } export interface ValidatedState extends State { - error: any; + error: unknown; errorMarkers: MarkerData[]; serialized: string; } diff --git a/src/lib/util/fileLoaders/gist.ts b/src/lib/util/fileLoaders/gist.ts index cd9a2a757..6304f9c51 100644 --- a/src/lib/util/fileLoaders/gist.ts +++ b/src/lib/util/fileLoaders/gist.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -43,6 +44,7 @@ const getGistData = async (gistURL: string): Promise => { } const currentItem = history[0]; return { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions url: `${html_url}/${currentItem.version}`, code, config, diff --git a/src/lib/util/fileLoaders/loader.ts b/src/lib/util/fileLoaders/loader.ts index 2f8b48e15..5ae528268 100644 --- a/src/lib/util/fileLoaders/loader.ts +++ b/src/lib/util/fileLoaders/loader.ts @@ -23,6 +23,9 @@ export const loadDataFromUrl = async (): Promise => { config = defaultState.mermaid; } if (!code) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call for (const [key, value] of searchParams.entries()) { if (key in loaders) { try { diff --git a/src/lib/util/serde.test.ts b/src/lib/util/serde.test.ts new file mode 100644 index 000000000..51171e8fb --- /dev/null +++ b/src/lib/util/serde.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest'; +import { serializeState, deserializeState, type SerdeType } from './serde'; +import { defaultState } from './state'; +import type { State } from '$lib/types'; + +describe('Serde tests', () => { + const verifySerde = (state: State, serde?: SerdeType): string => { + const serialized = serializeState(state, serde); + const deserialized = deserializeState(serialized); + expect(deserialized).to.deep.equal(state); + return serialized; + }; + + it('should serialize and deserialize with default serde', () => { + expect(verifySerde(defaultState)).toMatchInlineSnapshot( + '"pako:eNpVkM1qw0AMhF9F6JRC_AI-FBo7ySXQQnPz5iC8cnZp9oe1TAm2373rmEKik5j5ZhAasQ2ascRromjgXCsPeT6ayiTbi6P-AkXxPh1ZwAXP9wl2m2OA3oQYrb--rfxugaAaTwvGIMb6n3m1qkf-0_MEdXOiKCFenp3zb5hg39gvk-tfHZM4pw5NR2VHRUsJKkoPBLfoODmyOp8-LopCMexYYZlXzR0NN1Go_JzRIWoS3msrIWGuuvW8RRokfN99i6Wkgf-h2lL-hFvF-Q9-YFyS"' + ); + }); + + it('should serialize and deserialize with base64 serde', () => { + expect(verifySerde(defaultState, 'base64')).toMatchInlineSnapshot( + '"base64:eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0NocmlzdG1hc10gLS0-fEdldCBtb25leXwgQihHbyBzaG9wcGluZylcbiAgICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgICBDIC0tPnxPbmV8IERbTGFwdG9wXVxuICAgIEMgLS0-fFR3b3wgRVtpUGhvbmVdXG4gICAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cbiAgIiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjp0cnVlfQ"' + ); + }); + + it('should serialize and deserialize with pako serde', () => { + expect(verifySerde(defaultState, 'pako')).toMatchInlineSnapshot( + '"pako:eNpVkM1qw0AMhF9F6JRC_AI-FBo7ySXQQnPz5iC8cnZp9oe1TAm2373rmEKik5j5ZhAasQ2ascRromjgXCsPeT6ayiTbi6P-AkXxPh1ZwAXP9wl2m2OA3oQYrb--rfxugaAaTwvGIMb6n3m1qkf-0_MEdXOiKCFenp3zb5hg39gvk-tfHZM4pw5NR2VHRUsJKkoPBLfoODmyOp8-LopCMexYYZlXzR0NN1Go_JzRIWoS3msrIWGuuvW8RRokfN99i6Wkgf-h2lL-hFvF-Q9-YFyS"' + ); + }); + + it('should throw error for unrecognized serde', () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + expect(() => serializeState(defaultState, 'unknown')).toThrowError( + 'Unknown serde type: unknown' + ); + expect(() => deserializeState('unknown:hello')).toThrowError('Unknown serde type: unknown'); + }); +}); diff --git a/src/lib/util/serde.ts b/src/lib/util/serde.ts index 1f7540fc8..643401ff5 100644 --- a/src/lib/util/serde.ts +++ b/src/lib/util/serde.ts @@ -28,18 +28,20 @@ export const pakoSerde: Serde = { } }; -const serdes: { [key: string]: Serde } = { +export type SerdeType = 'base64' | 'pako'; + +const serdes: { [key in SerdeType]: Serde } = { base64: base64Serde, pako: pakoSerde }; -type SerdeType = keyof typeof serdes; - -export const serializeState = (state: State): string => { +export const serializeState = (state: State, serde: SerdeType = 'pako'): string => { + if (serdes[serde] === undefined) { + throw new Error(`Unknown serde type: ${serde}`); + } const json = JSON.stringify(state); - const defaultSerde: SerdeType = 'pako'; - const serialized = serdes[defaultSerde].serialize(json); - return `${defaultSerde}:${serialized}`; + const serialized = serdes[serde].serialize(json); + return `${serde}:${serialized}`; }; export const deserializeState = (state: string): State => { @@ -48,7 +50,7 @@ export const deserializeState = (state: string): State => { let tempType: string; [tempType, serialized] = state.split(':'); if (tempType in serdes) { - type = tempType; + type = tempType as SerdeType; } else { throw new Error(`Unknown serde type: ${tempType}`); } diff --git a/src/routes/edit.svelte b/src/routes/edit.svelte index 3ec957f41..dfe45d077 100644 --- a/src/routes/edit.svelte +++ b/src/routes/edit.svelte @@ -111,10 +111,6 @@ } }; - const viewDiagram = () => { - window.open(`${base}/view#${$stateStore.serialized}`, '_blank').focus(); - }; - onMount(async () => { await initHandler(); const resizer = document.getElementById('resizeHandler'); @@ -181,11 +177,13 @@