From 9135fb94ad89710292fe5edee1f975dc4b177fb4 Mon Sep 17 00:00:00 2001 From: "Kilu.He" <108015703+qinluhe@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:32:14 +0800 Subject: [PATCH] feat: support web document and cypress test (#5116) * feat: support web document and cypress test * fix: support blocks * fix: support table and outline * fix: update nginx --- .github/workflows/tauri2_ci.yaml | 2 +- .github/workflows/tauri_ci.yaml | 9 +- .github/workflows/web2_ci.yaml | 7 +- .github/workflows/web_cypress_ci.yaml | 48 + .../src/appflowy_app/views/DatabasePage.tsx | 6 +- frontend/appflowy_web_app/.eslintignore | 4 +- frontend/appflowy_web_app/README.md | 18 +- frontend/appflowy_web_app/cypress.config.ts | 18 + .../cypress/fixtures/full_doc.json | 1 + .../cypress/fixtures/sign_in_success.json | 66 + .../cypress/fixtures/simple_doc.json | 1 + .../cypress/fixtures/user.json | 17 + .../cypress/fixtures/verify_token.json | 6 + .../cypress/support/commands.ts | 46 + .../cypress/support/component-index.html | 12 + .../cypress/support/component.ts | 42 + .../cypress/support/document.ts | 88 ++ frontend/appflowy_web_app/index.html | 11 +- frontend/appflowy_web_app/jest.config.cjs | 20 + frontend/appflowy_web_app/nginx.conf | 13 + frontend/appflowy_web_app/package.json | 28 +- frontend/appflowy_web_app/pnpm-lock.yaml | 1101 +++++++++++++++-- frontend/appflowy_web_app/src/App.tsx | 35 - frontend/appflowy_web_app/src/AppTheme.tsx | 178 --- .../src/application/collab.type.ts | 14 + .../src/application/constants.ts | 2 + .../src/application/document.type.ts | 176 +++ .../src/application/services/index.ts | 3 +- .../services/js-services/auth.service.ts | 48 +- .../services/js-services/db/index.ts | 68 + .../services/js-services/db/tables/users.ts | 10 + .../services/js-services/decorator.ts | 60 + .../services/js-services/document.service.ts | 47 +- .../services/js-services/http/client.ts | 86 -- .../services/js-services/http/const.ts | 26 - .../services/js-services/http/http.type.ts | 40 - .../services/js-services/http/utils.ts | 110 -- .../application/services/js-services/index.ts | 28 +- .../services/js-services/storage/auth.ts | 11 + .../services/js-services/storage/document.ts | 21 + .../services/js-services/storage/index.ts | 2 + .../services/js-services/storage/token.ts | 36 + .../services/js-services/storage/user.ts | 18 + .../services/js-services/user.service.ts | 34 +- .../services/js-services/wasm/client_api.ts | 77 ++ .../services/js-services/wasm/index.ts | 1 + .../src/application/services/services.type.ts | 14 +- .../services/tauri-services/auth.service.ts | 23 +- .../tauri-services/document.service.ts | 66 +- .../services/tauri-services/index.ts | 6 +- .../services/tauri-services/user.service.ts | 10 +- .../services/wasm-services/cloud.service.ts | 36 - .../services/wasm-services/cloud.type.ts | 7 - .../services/wasm-services/index.ts | 20 - .../src/application/slate-yjs/index.ts | 1 + .../application/slate-yjs/plugins/withYjs.ts | 147 +++ .../slate-yjs/utils/applySlateOpts.ts | 6 + .../application/slate-yjs/utils/convert.ts | 240 ++++ .../utils/translateYjsEvent/arrayEvent.ts | 12 + .../utils/translateYjsEvent/index.ts | 34 + .../utils/translateYjsEvent/mapEvent.ts | 12 + .../utils/translateYjsEvent/textEvent.ts | 8 + .../application/{services => }/user.type.ts | 9 +- .../ydoc/apply/__tests__/document.test.ts | 18 + .../src/application/ydoc/apply/document.ts | 18 + .../src/application/ydoc/apply/index.ts | 1 + .../_shared/context-provider/IdProvider.tsx | 18 + .../_shared/katex-math/KatexMath.tsx | 24 + .../components/_shared/katex-math/index.css | 4 + .../_shared/scroller/AFScroller.tsx | 55 + .../src/components/_shared/scroller/index.ts | 1 + .../src/components/app/App.tsx | 27 + .../src/{ => components/app}/AppConfig.tsx | 9 +- .../src/components/app/AppTheme.tsx | 181 +++ .../src/components/app/withAppWrapper.tsx | 27 + .../src/components/auth/LoginButtonGroup.tsx | 13 +- .../src/components/auth/ProtectedRoutes.tsx | 30 +- .../src/components/auth/SignInWithEmail.tsx | 17 +- .../src/components/auth/SplashScreen.tsx | 22 +- .../src/components/auth/Welcome.cy.tsx | 34 + .../src/components/auth/Welcome.tsx | 42 +- .../src/components/auth/auth.hooks.ts | 34 +- .../src/components/document/Document.tsx | 19 + .../src/components/document/index.ts | 1 + .../components/editor/CollaborativeEditor.tsx | 33 + .../src/components/editor/Editable.tsx | 35 + .../src/components/editor/Editor.cy.tsx | 37 + .../src/components/editor/Editor.tsx | 48 + .../src/components/editor/EditorContext.tsx | 17 + .../blocks/bulleted_list/BulletedList.tsx | 16 + .../blocks/bulleted_list/BulletedListIcon.tsx | 49 + .../components/blocks/bulleted_list/index.ts | 2 + .../components/blocks/callout/Callout.tsx | 22 + .../components/blocks/callout/CalloutIcon.tsx | 17 + .../editor/components/blocks/callout/index.ts | 1 + .../components/blocks/code/Code.hooks.ts | 27 + .../editor/components/blocks/code/Code.tsx | 26 + .../components/blocks/code/SelectLanguage.tsx | 43 + .../components/blocks/code/constants.ts | 154 +++ .../editor/components/blocks/code/index.ts | 1 + .../components/blocks/code/useDecorate.ts | 33 + .../editor/components/blocks/code/utils.ts | 137 ++ .../components/blocks/divider/DividerNode.tsx | 30 + .../editor/components/blocks/divider/index.ts | 1 + .../components/blocks/heading/Heading.tsx | 20 + .../editor/components/blocks/heading/index.ts | 2 + .../editor/components/blocks/heading/utils.ts | 18 + .../components/blocks/image/ImageBlock.tsx | 56 + .../components/blocks/image/ImageEmpty.tsx | 23 + .../components/blocks/image/ImageRender.tsx | 77 ++ .../editor/components/blocks/image/index.ts | 1 + .../blocks/math_equation/MathEquation.tsx | 44 + .../components/blocks/math_equation/index.ts | 5 + .../blocks/numbered_list/NumberListIcon.tsx | 84 ++ .../blocks/numbered_list/NumberedList.tsx | 16 + .../components/blocks/numbered_list/index.ts | 2 + .../components/blocks/outline/Outline.tsx | 59 + .../editor/components/blocks/outline/index.ts | 1 + .../editor/components/blocks/outline/utils.ts | 54 + .../editor/components/blocks/page/Page.tsx | 18 + .../editor/components/blocks/page/index.ts | 1 + .../components/blocks/paragraph/Paragraph.tsx | 14 + .../components/blocks/paragraph/index.ts | 1 + .../editor/components/blocks/quote/Quote.tsx | 18 + .../editor/components/blocks/quote/index.ts | 1 + .../editor/components/blocks/table/Table.tsx | 56 + .../components/blocks/table/TableCell.tsx | 16 + .../editor/components/blocks/table/index.ts | 3 + .../editor/components/blocks/table/table.scss | 10 + .../components/blocks/text/Placeholder.tsx | 133 ++ .../blocks/text/StartIcon.hooks.tsx | 47 + .../editor/components/blocks/text/Text.tsx | 31 + .../editor/components/blocks/text/index.ts | 1 + .../blocks/todo_list/CheckboxIcon.tsx | 24 + .../components/blocks/todo_list/TodoList.tsx | 17 + .../components/blocks/todo_list/index.ts | 1 + .../blocks/toggle_list/ToggleIcon.tsx | 22 + .../blocks/toggle_list/ToggleList.tsx | 19 + .../components/blocks/toggle_list/index.ts | 1 + .../editor/components/element/Element.tsx | 122 ++ .../components/element/UnSupportedBlock.tsx | 13 + .../editor/components/element/index.ts | 1 + .../editor/components/leaf/Leaf.tsx | 57 + .../components/leaf/formula/Formula.tsx | 30 + .../editor/components/leaf/formula/index.ts | 5 + .../editor/components/leaf/href/Href.tsx | 6 + .../editor/components/leaf/href/index.ts | 1 + .../editor/components/leaf/index.ts | 1 + .../components/leaf/mention/Mention.tsx | 25 + .../components/leaf/mention/MentionDate.tsx | 18 + .../components/leaf/mention/MentionLeaf.tsx | 19 + .../components/leaf/mention/MentionPage.tsx | 52 + .../editor/components/leaf/mention/index.ts | 1 + .../src/components/editor/editor.scss | 277 +++++ .../src/components/editor/editor.type.ts | 137 ++ .../src/components/editor/index.ts | 3 + .../src/components/editor/plugins/index.ts | 6 + .../editor/plugins/withInlineElement.ts | 31 + .../src/components/editor/utils/list.ts | 73 ++ .../src/components/layout/Header.tsx | 38 + .../src/components/layout/Layout.tsx | 26 +- .../components/tauri/SignInAsAnonymous.tsx | 30 + frontend/appflowy_web_app/src/main.tsx | 5 +- .../src/pages/DocumentPage.tsx | 8 + .../appflowy_web_app/src/pages/LoginPage.tsx | 22 + .../src/pages/ProductPage.tsx | 38 + .../appflowy_web_app/src/slate-editor.d.ts | 45 + .../src/stores/currentUser/slice.ts | 3 +- frontend/appflowy_web_app/src/styles/font.css | 107 -- .../appflowy_web_app/src/styles/template.css | 3 - frontend/appflowy_web_app/src/utils/color.ts | 50 + frontend/appflowy_web_app/src/utils/font.ts | 3 + .../appflowy_web_app/src/utils/platform.ts | 2 +- frontend/appflowy_web_app/src/vite-env.d.ts | 9 + frontend/appflowy_web_app/tsconfig.json | 8 +- frontend/appflowy_web_app/tsconfig.web.json | 3 +- frontend/appflowy_web_app/vite.config.ts | 117 +- 177 files changed, 5872 insertions(+), 1089 deletions(-) create mode 100644 .github/workflows/web_cypress_ci.yaml create mode 100644 frontend/appflowy_web_app/cypress.config.ts create mode 100644 frontend/appflowy_web_app/cypress/fixtures/full_doc.json create mode 100644 frontend/appflowy_web_app/cypress/fixtures/sign_in_success.json create mode 100644 frontend/appflowy_web_app/cypress/fixtures/simple_doc.json create mode 100644 frontend/appflowy_web_app/cypress/fixtures/user.json create mode 100644 frontend/appflowy_web_app/cypress/fixtures/verify_token.json create mode 100644 frontend/appflowy_web_app/cypress/support/commands.ts create mode 100644 frontend/appflowy_web_app/cypress/support/component-index.html create mode 100644 frontend/appflowy_web_app/cypress/support/component.ts create mode 100644 frontend/appflowy_web_app/cypress/support/document.ts create mode 100644 frontend/appflowy_web_app/jest.config.cjs delete mode 100644 frontend/appflowy_web_app/src/App.tsx delete mode 100644 frontend/appflowy_web_app/src/AppTheme.tsx create mode 100644 frontend/appflowy_web_app/src/application/collab.type.ts create mode 100644 frontend/appflowy_web_app/src/application/constants.ts create mode 100644 frontend/appflowy_web_app/src/application/document.type.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/db/index.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/db/tables/users.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/decorator.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/js-services/http/client.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/js-services/http/const.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/js-services/http/http.type.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/js-services/http/utils.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/storage/auth.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/storage/document.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/storage/index.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/storage/token.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/storage/user.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/wasm/client_api.ts create mode 100644 frontend/appflowy_web_app/src/application/services/js-services/wasm/index.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/wasm-services/cloud.service.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/wasm-services/cloud.type.ts delete mode 100644 frontend/appflowy_web_app/src/application/services/wasm-services/index.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/index.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/plugins/withYjs.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/applySlateOpts.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/convert.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/arrayEvent.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/index.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/mapEvent.ts create mode 100644 frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/textEvent.ts rename frontend/appflowy_web_app/src/application/{services => }/user.type.ts (84%) create mode 100644 frontend/appflowy_web_app/src/application/ydoc/apply/__tests__/document.test.ts create mode 100644 frontend/appflowy_web_app/src/application/ydoc/apply/document.ts create mode 100644 frontend/appflowy_web_app/src/application/ydoc/apply/index.ts create mode 100644 frontend/appflowy_web_app/src/components/_shared/context-provider/IdProvider.tsx create mode 100644 frontend/appflowy_web_app/src/components/_shared/katex-math/KatexMath.tsx create mode 100644 frontend/appflowy_web_app/src/components/_shared/katex-math/index.css create mode 100644 frontend/appflowy_web_app/src/components/_shared/scroller/AFScroller.tsx create mode 100644 frontend/appflowy_web_app/src/components/_shared/scroller/index.ts create mode 100644 frontend/appflowy_web_app/src/components/app/App.tsx rename frontend/appflowy_web_app/src/{ => components/app}/AppConfig.tsx (86%) create mode 100644 frontend/appflowy_web_app/src/components/app/AppTheme.tsx create mode 100644 frontend/appflowy_web_app/src/components/app/withAppWrapper.tsx create mode 100644 frontend/appflowy_web_app/src/components/auth/Welcome.cy.tsx create mode 100644 frontend/appflowy_web_app/src/components/document/Document.tsx create mode 100644 frontend/appflowy_web_app/src/components/document/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/CollaborativeEditor.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/Editable.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/Editor.cy.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/Editor.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/EditorContext.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedList.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedListIcon.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/callout/Callout.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/callout/CalloutIcon.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/callout/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.hooks.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/SelectLanguage.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/constants.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/useDecorate.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/code/utils.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/divider/DividerNode.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/divider/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/heading/Heading.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/heading/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/heading/utils.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageBlock.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageEmpty.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageRender.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/image/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/MathEquation.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberListIcon.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberedList.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/outline/Outline.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/outline/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/outline/utils.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/page/Page.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/page/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/Paragraph.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/quote/Quote.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/quote/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/table/Table.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/table/TableCell.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/table/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/table/table.scss create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/text/Placeholder.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/text/StartIcon.hooks.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/text/Text.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/text/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/CheckboxIcon.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/TodoList.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleIcon.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleList.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/element/Element.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/element/UnSupportedBlock.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/element/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/Leaf.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/formula/Formula.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/formula/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/href/Href.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/href/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/mention/Mention.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionDate.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionLeaf.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionPage.tsx create mode 100644 frontend/appflowy_web_app/src/components/editor/components/leaf/mention/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/editor.scss create mode 100644 frontend/appflowy_web_app/src/components/editor/editor.type.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/plugins/index.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/plugins/withInlineElement.ts create mode 100644 frontend/appflowy_web_app/src/components/editor/utils/list.ts create mode 100644 frontend/appflowy_web_app/src/components/layout/Header.tsx create mode 100644 frontend/appflowy_web_app/src/components/tauri/SignInAsAnonymous.tsx create mode 100644 frontend/appflowy_web_app/src/pages/DocumentPage.tsx create mode 100644 frontend/appflowy_web_app/src/pages/LoginPage.tsx create mode 100644 frontend/appflowy_web_app/src/pages/ProductPage.tsx create mode 100644 frontend/appflowy_web_app/src/slate-editor.d.ts delete mode 100644 frontend/appflowy_web_app/src/styles/font.css create mode 100644 frontend/appflowy_web_app/src/utils/color.ts create mode 100644 frontend/appflowy_web_app/src/utils/font.ts diff --git a/.github/workflows/tauri2_ci.yaml b/.github/workflows/tauri2_ci.yaml index 7ad7fdd4aa..28414f0997 100644 --- a/.github/workflows/tauri2_ci.yaml +++ b/.github/workflows/tauri2_ci.yaml @@ -1,4 +1,4 @@ -name: Tauri2-CI +name: Tauri-CI on: pull_request: paths: diff --git a/.github/workflows/tauri_ci.yaml b/.github/workflows/tauri_ci.yaml index c9472fc6dc..70ad621451 100644 --- a/.github/workflows/tauri_ci.yaml +++ b/.github/workflows/tauri_ci.yaml @@ -1,11 +1,8 @@ name: Tauri-CI on: - pull_request: - paths: - - ".github/workflows/tauri_ci.yaml" - - "frontend/rust-lib/**" - - "frontend/appflowy_tauri/**" - - "frontend/resources/**" + push: + branches: + - build/tauri env: NODE_VERSION: "18.16.0" diff --git a/.github/workflows/web2_ci.yaml b/.github/workflows/web2_ci.yaml index d134cd712f..68df8d805f 100644 --- a/.github/workflows/web2_ci.yaml +++ b/.github/workflows/web2_ci.yaml @@ -1,4 +1,4 @@ -name: Web2-CI +name: Web-CI on: pull_request: paths: @@ -17,14 +17,14 @@ jobs: strategy: fail-fast: false matrix: - platform: [ ubuntu-latest ] + platform: [ ubuntu-20.04 ] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - name: Maximize build space (ubuntu only) - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-20.04' run: | sudo rm -rf /usr/share/dotnet sudo rm -rf /opt/ghc @@ -56,6 +56,7 @@ jobs: working-directory: frontend/appflowy_web_app run: | pnpm run lint + pnpm run test:unit - name: build and analyze working-directory: frontend/appflowy_web_app run: | diff --git a/.github/workflows/web_cypress_ci.yaml b/.github/workflows/web_cypress_ci.yaml new file mode 100644 index 0000000000..15e52d3e8d --- /dev/null +++ b/.github/workflows/web_cypress_ci.yaml @@ -0,0 +1,48 @@ +name: Cypress Tests + +on: + pull_request: + paths: + - ".github/workflows/web2_ci.yaml" + - "frontend/appflowy_web_app/**" + - "frontend/resources/**" +env: + NODE_VERSION: "18.16.0" + PNPM_VERSION: "8.5.0" +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true +jobs: + cypress-run: + if: github.event.pull_request.draft != true + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - name: Maximize build space (ubuntu only) + run: | + sudo rm -rf /usr/share/dotnet + sudo rm -rf /opt/ghc + sudo rm -rf "/usr/local/share/boost" + sudo rm -rf "$AGENT_TOOLSDIRECTORY" + sudo docker image prune --all --force + sudo rm -rf /opt/hostedtoolcache/codeQL + sudo rm -rf ${GITHUB_WORKSPACE}/.git + sudo rm -rf $ANDROID_HOME/ndk + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + - name: setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + # Install pnpm dependencies, cache them correctly + # and run all Cypress tests + - name: Cypress run + uses: cypress-io/github-action@v6 + with: + working-directory: frontend/appflowy_web_app + component: true + build: pnpm run build + start: pnpm run start + browser: chrome \ No newline at end of file diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/DatabasePage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/DatabasePage.tsx index 1a68b70237..004fc4355b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/views/DatabasePage.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/views/DatabasePage.tsx @@ -14,10 +14,10 @@ export const DatabasePage = () => { } return ( -
+
- - + +
); diff --git a/frontend/appflowy_web_app/.eslintignore b/frontend/appflowy_web_app/.eslintignore index 6061ede6d5..8b900e497c 100644 --- a/frontend/appflowy_web_app/.eslintignore +++ b/frontend/appflowy_web_app/.eslintignore @@ -4,4 +4,6 @@ src-tauri/ .eslintrc.cjs tsconfig.json **/backend/** -vite.config.ts \ No newline at end of file +vite.config.ts +**/*.cy.tsx +*.config.ts \ No newline at end of file diff --git a/frontend/appflowy_web_app/README.md b/frontend/appflowy_web_app/README.md index f5ac3e4832..c5c8ebf51f 100644 --- a/frontend/appflowy_web_app/README.md +++ b/frontend/appflowy_web_app/README.md @@ -186,7 +186,7 @@ Don't modify the theme file in `frontend/appflowy_web_app/src/styles/variables` // ... { find: '$client-services', - replacement: process.env.TAURI_MODE + replacement: !!process.env.TAURI_PLATFORM ? `${__dirname}/src/application/services/tauri-services` : `${__dirname}/src/application/services/js-services`, }, @@ -207,7 +207,7 @@ Use the AppFlowy CI/CD pipeline to deploy the application to the test and produc - Enter the options - Click on the Run workflow button -#### 📦 Deployment (Self-Hosted) +#### 📦 Deployment (Self-Hosted EC2) ##### Pre-requisites @@ -267,6 +267,18 @@ And then follow the steps below: ### 🧪 Testing -> To be Continued... +> We use Cypress for end-to-end testing and component testing - [Cypress](https://www.cypress.io/) + +#### 🧪 End-to-End Testing + +> to be continued + +#### 🧪 Component Testing + +Run the following command to run the component tests + +```bash +pnpm run test:components +``` diff --git a/frontend/appflowy_web_app/cypress.config.ts b/frontend/appflowy_web_app/cypress.config.ts new file mode 100644 index 0000000000..c8f9f6972f --- /dev/null +++ b/frontend/appflowy_web_app/cypress.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from 'cypress'; + +export default defineConfig({ + component: { + devServer: { + framework: 'react', + bundler: 'vite', + }, + }, + retries: { + // Configure retry attempts for `cypress run` + // Default is 0 + runMode: 2, + // Configure retry attempts for `cypress open` + // Default is 0 + openMode: 0, + }, +}); diff --git a/frontend/appflowy_web_app/cypress/fixtures/full_doc.json b/frontend/appflowy_web_app/cypress/fixtures/full_doc.json new file mode 100644 index 0000000000..e47a6c6fc0 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/fixtures/full_doc.json @@ -0,0 +1 @@ +{"data":{"state_vector":[43,192,246,139,213,2,35,131,182,180,202,12,53,132,236,218,251,9,14,197,205,192,233,12,9,198,223,206,159,1,145,2,199,130,209,189,2,141,8,136,172,186,168,4,182,6,131,128,202,229,9,1,204,195,206,156,1,153,9,141,178,210,127,3,140,167,201,161,14,10,207,231,154,196,9,3,142,211,188,164,13,15,206,214,243,86,178,1,146,216,250,133,2,180,1,150,152,188,203,6,20,151,234,142,238,11,27,150,216,171,142,3,188,8,217,168,198,159,4,7,218,255,204,32,21,155,213,159,176,1,10,219,200,174,197,9,25,224,159,166,178,15,30,161,234,157,145,5,7,226,167,254,250,5,13,228,242,134,215,15,12,165,131,171,211,15,20,229,154,194,35,178,1,164,202,219,213,10,122,168,215,223,235,2,56,171,236,222,251,5,252,4,172,254,181,239,1,15,236,158,128,159,2,4,239,239,208,251,10,17,176,238,158,139,14,175,2,241,147,239,232,6,4,178,187,245,161,14,11,243,138,171,183,10,252,1,245,181,155,135,2,23,181,156,253,158,6,5,247,212,219,208,10,46,184,146,243,216,14,7,190,183,139,210,2,110],"doc_state":[43,9,228,242,134,215,15,0,39,0,204,195,206,156,1,4,6,109,86,80,71,80,99,2,4,0,228,242,134,215,15,0,4,104,106,107,100,161,172,254,181,239,1,14,1,132,228,242,134,215,15,4,1,56,161,228,242,134,215,15,5,1,132,228,242,134,215,15,6,1,56,161,228,242,134,215,15,7,1,132,228,242,134,215,15,8,1,56,161,228,242,134,215,15,9,1,18,165,131,171,211,15,0,129,155,213,159,176,1,6,2,161,155,213,159,176,1,7,1,161,155,213,159,176,1,8,1,161,155,213,159,176,1,9,1,161,165,131,171,211,15,2,1,161,165,131,171,211,15,3,1,161,165,131,171,211,15,4,1,161,165,131,171,211,15,5,1,161,165,131,171,211,15,6,1,161,165,131,171,211,15,7,1,129,165,131,171,211,15,1,2,161,165,131,171,211,15,8,1,161,165,131,171,211,15,9,1,161,165,131,171,211,15,10,1,129,165,131,171,211,15,12,1,161,165,131,171,211,15,13,1,161,165,131,171,211,15,14,1,161,165,131,171,211,15,15,1,28,224,159,166,178,15,0,129,165,131,171,211,15,16,1,161,197,205,192,233,12,6,1,161,197,205,192,233,12,7,1,161,197,205,192,233,12,8,1,161,224,159,166,178,15,1,1,161,224,159,166,178,15,2,1,161,224,159,166,178,15,3,1,129,224,159,166,178,15,0,1,161,224,159,166,178,15,4,1,161,224,159,166,178,15,5,1,161,224,159,166,178,15,6,1,129,224,159,166,178,15,7,2,161,224,159,166,178,15,8,1,161,224,159,166,178,15,9,1,161,224,159,166,178,15,10,1,161,224,159,166,178,15,13,1,161,224,159,166,178,15,14,1,161,224,159,166,178,15,15,1,161,224,159,166,178,15,16,1,161,224,159,166,178,15,17,1,161,224,159,166,178,15,18,1,161,224,159,166,178,15,19,1,161,224,159,166,178,15,20,1,161,224,159,166,178,15,21,1,129,224,159,166,178,15,12,2,161,224,159,166,178,15,22,1,161,224,159,166,178,15,23,1,161,224,159,166,178,15,24,1,7,184,146,243,216,14,0,129,217,168,198,159,4,3,1,161,142,211,188,164,13,12,1,161,142,211,188,164,13,13,1,161,142,211,188,164,13,14,1,161,184,146,243,216,14,1,1,161,184,146,243,216,14,2,1,161,184,146,243,216,14,3,1,5,178,187,245,161,14,0,39,0,204,195,206,156,1,4,6,95,104,88,73,115,119,2,4,0,178,187,245,161,14,0,13,229,144,140,228,184,128,228,184,170,106,106,106,57,161,198,223,206,159,1,124,1,132,178,187,245,161,14,7,1,57,161,178,187,245,161,14,8,1,5,140,167,201,161,14,0,0,4,132,204,195,206,156,1,245,5,9,229,176,177,229,135,160,229,174,182,168,198,223,206,159,1,89,1,119,96,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,97,110,121,119,104,101,114,101,32,97,110,100,32,106,117,115,116,32,115,116,97,114,116,32,116,121,112,105,110,103,229,147,136,229,147,136,229,147,136,46,229,176,177,229,135,160,229,174,182,34,125,93,125,168,198,223,206,159,1,90,1,119,10,119,79,108,117,99,85,55,51,73,76,168,198,223,206,159,1,91,1,119,4,116,101,120,116,1,176,238,158,139,14,0,161,206,214,243,86,177,1,175,2,15,142,211,188,164,13,0,161,217,168,198,159,4,4,1,161,217,168,198,159,4,5,1,161,217,168,198,159,4,6,1,161,142,211,188,164,13,0,1,161,142,211,188,164,13,1,1,161,142,211,188,164,13,2,1,161,142,211,188,164,13,3,1,161,142,211,188,164,13,4,1,161,142,211,188,164,13,5,1,161,142,211,188,164,13,6,1,161,142,211,188,164,13,7,1,161,142,211,188,164,13,8,1,161,142,211,188,164,13,9,1,161,142,211,188,164,13,10,1,161,142,211,188,164,13,11,1,9,197,205,192,233,12,0,161,165,131,171,211,15,17,1,161,165,131,171,211,15,18,1,161,165,131,171,211,15,19,1,161,197,205,192,233,12,0,1,161,197,205,192,233,12,1,1,161,197,205,192,233,12,2,1,161,197,205,192,233,12,3,1,161,197,205,192,233,12,4,1,161,197,205,192,233,12,5,1,47,131,182,180,202,12,0,129,184,146,243,216,14,0,1,161,184,146,243,216,14,4,1,161,184,146,243,216,14,5,1,161,184,146,243,216,14,6,1,129,131,182,180,202,12,0,2,161,131,182,180,202,12,1,1,161,131,182,180,202,12,2,1,161,131,182,180,202,12,3,1,161,131,182,180,202,12,6,1,161,131,182,180,202,12,7,1,161,131,182,180,202,12,8,1,161,131,182,180,202,12,9,1,161,131,182,180,202,12,10,1,161,131,182,180,202,12,11,1,161,131,182,180,202,12,12,1,161,131,182,180,202,12,13,1,161,131,182,180,202,12,14,1,129,131,182,180,202,12,5,3,161,131,182,180,202,12,15,1,161,131,182,180,202,12,16,1,161,131,182,180,202,12,17,1,161,131,182,180,202,12,21,1,161,131,182,180,202,12,22,1,161,131,182,180,202,12,23,1,161,131,182,180,202,12,24,1,161,131,182,180,202,12,25,1,161,131,182,180,202,12,26,1,161,131,182,180,202,12,27,1,161,131,182,180,202,12,28,1,161,131,182,180,202,12,29,1,129,131,182,180,202,12,20,4,161,131,182,180,202,12,30,1,161,131,182,180,202,12,31,1,161,131,182,180,202,12,32,1,161,131,182,180,202,12,37,1,161,131,182,180,202,12,38,1,161,131,182,180,202,12,39,1,129,131,182,180,202,12,36,1,161,131,182,180,202,12,40,1,161,131,182,180,202,12,41,1,161,131,182,180,202,12,42,1,161,131,182,180,202,12,44,1,161,131,182,180,202,12,45,1,161,131,182,180,202,12,46,1,161,131,182,180,202,12,47,1,161,131,182,180,202,12,48,1,161,131,182,180,202,12,49,1,1,151,234,142,238,11,0,161,229,154,194,35,177,1,27,1,239,239,208,251,10,0,33,1,4,109,101,116,97,12,108,97,115,116,95,115,121,110,99,95,97,116,17,81,164,202,219,213,10,0,39,0,204,195,206,156,1,4,6,103,67,116,99,89,115,2,39,0,204,195,206,156,1,4,6,102,105,108,83,57,100,2,4,0,164,202,219,213,10,1,10,116,111,100,111,32,108,105,115,116,32,134,164,202,219,213,10,11,7,109,101,110,116,105,111,110,51,123,34,116,121,112,101,34,58,34,100,97,116,101,34,44,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,56,84,49,52,58,50,53,58,51,50,46,52,53,55,50,55,55,34,125,132,164,202,219,213,10,12,1,36,134,164,202,219,213,10,13,7,109,101,110,116,105,111,110,4,110,117,108,108,132,164,202,219,213,10,14,4,109,101,110,116,33,0,204,195,206,156,1,1,6,88,55,78,102,76,50,1,0,7,33,0,204,195,206,156,1,3,6,112,56,66,76,122,103,1,193,198,223,206,159,1,135,1,199,130,209,189,2,60,1,168,199,130,209,189,2,140,8,1,119,161,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,116,111,100,111,32,108,105,115,116,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,109,101,110,116,105,111,110,34,58,123,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,56,84,49,52,58,50,53,58,51,50,46,52,53,55,50,55,55,34,44,34,116,121,112,101,34,58,34,100,97,116,101,34,125,125,44,34,105,110,115,101,114,116,34,58,34,36,34,125,44,123,34,105,110,115,101,114,116,34,58,34,109,101,110,116,34,125,93,44,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,39,0,204,195,206,156,1,4,6,66,120,115,95,114,76,2,33,0,204,195,206,156,1,1,6,111,56,54,77,119,121,1,0,7,33,0,204,195,206,156,1,3,6,67,89,84,109,67,89,1,193,198,223,206,159,1,135,1,164,202,219,213,10,28,1,4,0,164,202,219,213,10,30,1,35,0,1,39,0,204,195,206,156,1,4,6,109,113,102,117,86,95,2,33,0,204,195,206,156,1,1,6,84,100,115,87,90,75,1,0,7,33,0,204,195,206,156,1,3,6,49,115,106,52,120,74,1,193,198,223,206,159,1,135,1,164,202,219,213,10,40,1,4,0,164,202,219,213,10,43,1,49,0,1,132,164,202,219,213,10,54,1,50,0,1,132,164,202,219,213,10,56,1,51,0,1,132,164,202,219,213,10,58,1,32,0,1,129,164,202,219,213,10,60,1,0,1,134,164,202,219,213,10,62,7,109,101,110,116,105,111,110,51,123,34,116,121,112,101,34,58,34,100,97,116,101,34,44,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,57,84,49,54,58,49,51,58,52,57,46,52,49,49,49,54,53,34,125,132,164,202,219,213,10,64,1,36,134,164,202,219,213,10,65,7,109,101,110,116,105,111,110,4,110,117,108,108,0,1,39,0,204,195,206,156,1,4,6,103,83,52,80,113,73,2,4,0,164,202,219,213,10,68,4,49,50,51,32,134,164,202,219,213,10,72,7,109,101,110,116,105,111,110,51,123,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,57,84,49,54,58,49,51,58,52,57,46,52,49,49,49,54,53,34,44,34,116,121,112,101,34,58,34,100,97,116,101,34,125,132,164,202,219,213,10,73,1,36,134,164,202,219,213,10,74,7,109,101,110,116,105,111,110,4,110,117,108,108,132,164,202,219,213,10,75,1,32,0,1,129,164,202,219,213,10,76,1,0,1,161,204,195,206,156,1,155,1,1,161,204,195,206,156,1,156,1,1,161,204,195,206,156,1,157,1,1,0,1,132,164,202,219,213,10,78,1,32,0,1,132,164,202,219,213,10,84,1,101,0,1,132,164,202,219,213,10,86,1,114,0,1,132,164,202,219,213,10,88,1,32,0,1,132,164,202,219,213,10,90,1,32,0,1,68,164,202,219,213,10,69,1,35,0,1,68,164,202,219,213,10,94,1,35,0,1,39,0,204,195,206,156,1,4,6,120,115,71,80,56,122,2,4,0,164,202,219,213,10,98,4,49,50,51,32,134,164,202,219,213,10,102,7,109,101,110,116,105,111,110,51,123,34,116,121,112,101,34,58,34,100,97,116,101,34,44,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,57,84,49,54,58,49,51,58,52,57,46,52,49,49,49,54,53,34,125,132,164,202,219,213,10,103,1,36,134,164,202,219,213,10,104,7,109,101,110,116,105,111,110,4,110,117,108,108,132,164,202,219,213,10,105,6,32,32,101,114,32,32,39,0,204,195,206,156,1,1,6,106,97,80,87,115,68,1,40,0,164,202,219,213,10,112,2,105,100,1,119,6,106,97,80,87,115,68,40,0,164,202,219,213,10,112,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,164,202,219,213,10,112,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,164,202,219,213,10,112,8,99,104,105,108,100,114,101,110,1,119,6,106,75,88,90,122,73,33,0,164,202,219,213,10,112,4,100,97,116,97,1,40,0,164,202,219,213,10,112,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,164,202,219,213,10,112,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,106,75,88,90,122,73,0,200,198,223,206,159,1,135,1,164,202,219,213,10,53,1,119,6,106,97,80,87,115,68,1,247,212,219,208,10,0,161,132,236,218,251,9,13,46,240,1,243,138,171,183,10,0,161,150,216,171,142,3,178,5,1,161,150,216,171,142,3,190,5,1,161,150,216,171,142,3,200,5,1,161,150,216,171,142,3,187,6,1,161,150,216,171,142,3,188,6,1,161,150,216,171,142,3,189,6,1,161,150,216,171,142,3,190,6,2,161,150,216,171,142,3,251,5,1,161,150,216,171,142,3,144,6,1,161,150,216,171,142,3,164,6,1,161,243,138,171,183,10,7,1,161,243,138,171,183,10,0,1,161,243,138,171,183,10,1,1,161,243,138,171,183,10,2,1,161,243,138,171,183,10,8,1,161,243,138,171,183,10,9,1,161,243,138,171,183,10,10,1,161,243,138,171,183,10,11,1,161,243,138,171,183,10,3,1,161,243,138,171,183,10,4,1,161,243,138,171,183,10,5,1,161,243,138,171,183,10,18,2,161,243,138,171,183,10,12,1,161,243,138,171,183,10,13,1,161,243,138,171,183,10,14,1,161,243,138,171,183,10,19,1,161,243,138,171,183,10,20,1,161,243,138,171,183,10,21,1,161,243,138,171,183,10,23,1,161,243,138,171,183,10,15,1,161,243,138,171,183,10,16,1,161,243,138,171,183,10,17,1,161,243,138,171,183,10,30,2,161,243,138,171,183,10,24,1,161,243,138,171,183,10,25,1,161,243,138,171,183,10,26,1,161,243,138,171,183,10,27,1,161,243,138,171,183,10,28,1,161,243,138,171,183,10,29,1,161,243,138,171,183,10,35,1,161,243,138,171,183,10,31,1,161,243,138,171,183,10,32,1,161,243,138,171,183,10,33,1,161,243,138,171,183,10,42,2,161,243,138,171,183,10,36,1,161,243,138,171,183,10,37,1,161,243,138,171,183,10,38,1,161,243,138,171,183,10,43,1,161,243,138,171,183,10,44,1,161,243,138,171,183,10,45,1,161,243,138,171,183,10,47,1,161,243,138,171,183,10,39,1,161,243,138,171,183,10,40,1,161,243,138,171,183,10,41,1,161,243,138,171,183,10,54,2,161,243,138,171,183,10,48,1,161,243,138,171,183,10,49,1,161,243,138,171,183,10,50,1,161,243,138,171,183,10,55,1,161,243,138,171,183,10,56,1,161,243,138,171,183,10,57,1,161,243,138,171,183,10,59,1,161,243,138,171,183,10,51,1,161,243,138,171,183,10,52,1,161,243,138,171,183,10,53,1,161,243,138,171,183,10,66,2,161,243,138,171,183,10,60,1,161,243,138,171,183,10,61,1,161,243,138,171,183,10,62,1,161,243,138,171,183,10,63,1,161,243,138,171,183,10,64,1,161,243,138,171,183,10,65,1,161,243,138,171,183,10,71,2,161,243,138,171,183,10,67,1,161,243,138,171,183,10,68,1,161,243,138,171,183,10,69,1,161,243,138,171,183,10,79,1,161,243,138,171,183,10,72,1,161,243,138,171,183,10,73,1,161,243,138,171,183,10,74,1,161,243,138,171,183,10,75,1,161,243,138,171,183,10,76,1,161,243,138,171,183,10,77,1,161,243,138,171,183,10,83,1,161,243,138,171,183,10,80,1,161,243,138,171,183,10,81,1,161,243,138,171,183,10,82,1,161,243,138,171,183,10,90,2,161,146,216,250,133,2,12,1,161,146,216,250,133,2,13,1,161,146,216,250,133,2,14,1,161,146,216,250,133,2,17,1,161,146,216,250,133,2,21,1,161,146,216,250,133,2,22,1,161,146,216,250,133,2,23,1,161,243,138,171,183,10,99,1,161,146,216,250,133,2,18,1,161,146,216,250,133,2,19,1,161,146,216,250,133,2,20,1,161,243,138,171,183,10,103,1,161,146,216,250,133,2,24,1,161,146,216,250,133,2,25,1,161,146,216,250,133,2,26,1,161,146,216,250,133,2,35,1,161,146,216,250,133,2,28,1,161,146,216,250,133,2,29,1,161,146,216,250,133,2,30,1,161,243,138,171,183,10,111,1,161,146,216,250,133,2,32,1,161,146,216,250,133,2,33,1,161,146,216,250,133,2,34,1,161,243,138,171,183,10,115,1,161,146,216,250,133,2,36,1,161,146,216,250,133,2,37,1,161,146,216,250,133,2,38,1,161,146,216,250,133,2,40,1,161,146,216,250,133,2,41,1,161,146,216,250,133,2,42,1,161,146,216,250,133,2,47,1,161,146,216,250,133,2,44,1,161,146,216,250,133,2,45,1,161,146,216,250,133,2,46,1,161,243,138,171,183,10,126,2,161,146,216,250,133,2,48,1,161,146,216,250,133,2,49,1,161,146,216,250,133,2,50,1,161,146,216,250,133,2,59,1,161,146,216,250,133,2,51,1,161,146,216,250,133,2,52,1,161,146,216,250,133,2,53,1,161,243,138,171,183,10,135,1,1,161,146,216,250,133,2,56,1,161,146,216,250,133,2,57,1,161,146,216,250,133,2,58,1,161,243,138,171,183,10,139,1,1,161,146,216,250,133,2,60,1,161,146,216,250,133,2,61,1,161,146,216,250,133,2,62,1,161,146,216,250,133,2,71,1,161,146,216,250,133,2,64,1,161,146,216,250,133,2,65,1,161,146,216,250,133,2,66,1,161,243,138,171,183,10,147,1,1,161,146,216,250,133,2,68,1,161,146,216,250,133,2,69,1,161,146,216,250,133,2,70,1,161,243,138,171,183,10,151,1,1,161,146,216,250,133,2,72,1,161,146,216,250,133,2,73,1,161,146,216,250,133,2,74,1,161,146,216,250,133,2,83,1,161,146,216,250,133,2,76,1,161,146,216,250,133,2,77,1,161,146,216,250,133,2,78,1,161,243,138,171,183,10,159,1,1,161,146,216,250,133,2,80,1,161,146,216,250,133,2,81,1,161,146,216,250,133,2,82,1,161,243,138,171,183,10,163,1,1,161,146,216,250,133,2,84,1,161,146,216,250,133,2,85,1,161,146,216,250,133,2,86,1,161,146,216,250,133,2,95,1,161,146,216,250,133,2,92,1,161,146,216,250,133,2,93,1,161,146,216,250,133,2,94,1,161,243,138,171,183,10,171,1,1,161,146,216,250,133,2,88,1,161,146,216,250,133,2,89,1,161,146,216,250,133,2,90,1,161,243,138,171,183,10,175,1,1,161,146,216,250,133,2,96,1,161,146,216,250,133,2,97,1,161,146,216,250,133,2,98,1,161,146,216,250,133,2,107,1,161,146,216,250,133,2,104,1,161,146,216,250,133,2,105,1,161,146,216,250,133,2,106,1,161,243,138,171,183,10,183,1,1,161,146,216,250,133,2,100,1,161,146,216,250,133,2,101,1,161,146,216,250,133,2,102,1,161,243,138,171,183,10,187,1,1,161,146,216,250,133,2,108,1,161,146,216,250,133,2,109,1,161,146,216,250,133,2,110,1,161,146,216,250,133,2,119,1,161,146,216,250,133,2,112,1,161,146,216,250,133,2,113,1,161,146,216,250,133,2,114,1,161,243,138,171,183,10,195,1,1,161,146,216,250,133,2,116,1,161,146,216,250,133,2,117,1,161,146,216,250,133,2,118,1,161,243,138,171,183,10,199,1,1,161,146,216,250,133,2,120,1,161,146,216,250,133,2,121,1,161,146,216,250,133,2,122,1,161,146,216,250,133,2,131,1,2,161,146,216,250,133,2,124,1,161,146,216,250,133,2,125,1,161,146,216,250,133,2,126,1,161,146,216,250,133,2,128,1,1,161,146,216,250,133,2,129,1,1,161,146,216,250,133,2,130,1,1,161,243,138,171,183,10,208,1,1,161,146,216,250,133,2,132,1,1,161,146,216,250,133,2,133,1,1,161,146,216,250,133,2,134,1,1,161,146,216,250,133,2,143,1,1,161,146,216,250,133,2,136,1,1,161,146,216,250,133,2,137,1,1,161,146,216,250,133,2,138,1,1,161,243,138,171,183,10,219,1,1,161,146,216,250,133,2,140,1,1,161,146,216,250,133,2,141,1,1,161,146,216,250,133,2,142,1,1,161,243,138,171,183,10,223,1,1,161,146,216,250,133,2,144,1,1,161,146,216,250,133,2,145,1,1,161,146,216,250,133,2,146,1,1,161,146,216,250,133,2,155,1,1,161,146,216,250,133,2,148,1,1,161,146,216,250,133,2,149,1,1,161,146,216,250,133,2,150,1,1,161,243,138,171,183,10,231,1,1,161,146,216,250,133,2,152,1,1,161,146,216,250,133,2,153,1,1,161,146,216,250,133,2,154,1,1,161,243,138,171,183,10,235,1,1,168,146,216,250,133,2,156,1,1,119,68,123,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,48,44,34,119,105,100,116,104,34,58,49,53,48,46,56,53,53,52,54,56,55,53,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,48,125,168,146,216,250,133,2,157,1,1,119,68,123,34,99,111,108,80,111,115,105,116,105,111,110,34,58,49,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,48,44,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,119,105,100,116,104,34,58,49,48,53,46,48,53,48,55,56,49,50,53,125,168,146,216,250,133,2,158,1,1,119,60,123,34,119,105,100,116,104,34,58,56,48,46,48,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,48,44,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,50,125,161,146,216,250,133,2,167,1,3,168,146,216,250,133,2,160,1,1,119,68,123,34,119,105,100,116,104,34,58,49,53,48,46,56,53,53,52,54,56,55,53,44,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,48,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,49,125,168,146,216,250,133,2,161,1,1,119,68,123,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,119,105,100,116,104,34,58,49,48,53,46,48,53,48,55,56,49,50,53,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,49,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,49,125,168,146,216,250,133,2,162,1,1,119,60,123,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,50,44,34,119,105,100,116,104,34,58,56,48,46,48,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,49,125,168,146,216,250,133,2,164,1,1,119,68,123,34,99,111,108,80,111,115,105,116,105,111,110,34,58,48,44,34,114,111,119,80,111,115,105,116,105,111,110,34,58,50,44,34,119,105,100,116,104,34,58,49,53,48,46,56,53,53,52,54,56,55,53,44,34,104,101,105,103,104,116,34,58,52,48,46,48,125,168,146,216,250,133,2,165,1,1,119,68,123,34,114,111,119,80,111,115,105,116,105,111,110,34,58,50,44,34,119,105,100,116,104,34,58,49,48,53,46,48,53,48,55,56,49,50,53,44,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,49,125,168,146,216,250,133,2,166,1,1,119,60,123,34,114,111,119,80,111,115,105,116,105,111,110,34,58,50,44,34,104,101,105,103,104,116,34,58,52,48,46,48,44,34,99,111,108,80,111,115,105,116,105,111,110,34,58,50,44,34,119,105,100,116,104,34,58,56,48,46,48,125,1,132,236,218,251,9,0,161,218,255,204,32,20,14,1,131,128,202,229,9,0,168,243,138,171,183,10,245,1,1,119,114,123,34,99,111,108,68,101,102,97,117,108,116,87,105,100,116,104,34,58,56,48,46,48,44,34,99,111,108,115,72,101,105,103,104,116,34,58,49,50,56,46,48,44,34,99,111,108,115,76,101,110,34,58,51,44,34,99,111,108,77,105,110,105,109,117,109,87,105,100,116,104,34,58,52,48,46,48,44,34,114,111,119,68,101,102,97,117,108,116,72,101,105,103,104,116,34,58,52,48,46,48,44,34,114,111,119,115,76,101,110,34,58,51,125,1,219,200,174,197,9,0,161,161,234,157,145,5,6,25,3,207,231,154,196,9,0,168,204,195,206,156,1,209,1,1,119,101,123,34,105,109,97,103,101,95,116,121,112,101,34,58,34,49,34,44,34,99,111,118,101,114,95,115,101,108,101,99,116,105,111,110,95,116,121,112,101,34,58,34,67,111,118,101,114,84,121,112,101,46,99,111,108,111,114,34,44,34,100,101,108,116,97,34,58,91,93,44,34,99,111,118,101,114,95,115,101,108,101,99,116,105,111,110,34,58,34,48,120,102,102,101,56,101,48,102,102,34,125,168,204,195,206,156,1,210,1,1,119,10,112,70,113,76,55,45,79,83,121,86,168,204,195,206,156,1,211,1,1,119,4,116,101,120,116,1,241,147,239,232,6,0,161,245,181,155,135,2,22,4,1,150,152,188,203,6,0,161,192,246,139,213,2,34,20,2,181,156,253,158,6,0,161,198,223,206,159,1,175,1,4,168,181,156,253,158,6,3,1,119,231,1,123,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,105,109,97,103,101,115,46,117,110,115,112,108,97,115,104,46,99,111,109,47,112,104,111,116,111,45,49,55,49,50,51,48,51,55,48,48,56,51,50,45,53,55,100,50,98,50,98,57,49,54,98,56,63,99,114,111,112,61,101,110,116,114,111,112,121,38,99,115,61,116,105,110,121,115,114,103,98,38,102,105,116,61,109,97,120,38,102,109,61,106,112,103,38,105,120,105,100,61,77,51,119,49,77,84,69,49,77,122,100,56,77,72,119,120,102,72,74,104,98,109,82,118,98,88,120,56,102,72,120,56,102,72,120,56,102,68,69,51,77,84,77,121,78,84,107,122,78,84,100,56,38,105,120,108,105,98,61,114,98,45,52,46,48,46,51,38,113,61,56,48,38,119,61,49,48,56,48,34,44,34,119,105,100,116,104,34,58,52,50,56,46,49,57,53,51,49,50,53,44,34,97,108,105,103,110,34,58,34,114,105,103,104,116,34,125,220,2,171,236,222,251,5,0,198,204,195,206,156,1,205,4,204,195,206,156,1,206,4,4,98,111,108,100,4,116,114,117,101,196,171,236,222,251,5,0,204,195,206,156,1,206,4,4,112,97,103,101,198,171,236,222,251,5,4,204,195,206,156,1,206,4,4,98,111,108,100,4,110,117,108,108,168,204,195,206,156,1,119,1,119,222,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,43,32,78,101,119,32,80,97,103,101,32,34,125,44,123,34,105,110,115,101,114,116,34,58,34,98,117,116,116,111,110,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,111,102,32,121,111,117,114,32,115,105,100,101,98,97,114,32,116,111,32,97,100,100,32,97,32,110,101,119,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,111,108,100,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,112,97,103,101,34,125,44,123,34,105,110,115,101,114,116,34,58,34,46,34,125,93,44,34,99,104,101,99,107,101,100,34,58,116,114,117,101,125,168,204,195,206,156,1,120,1,119,10,122,77,121,109,67,97,118,83,107,102,168,204,195,206,156,1,121,1,119,4,116,101,120,116,193,204,195,206,156,1,129,6,204,195,206,156,1,130,6,5,198,171,236,222,251,5,13,204,195,206,156,1,130,6,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,204,195,206,156,1,11,1,161,204,195,206,156,1,12,1,161,204,195,206,156,1,13,1,161,171,236,222,251,5,15,1,161,171,236,222,251,5,16,1,161,171,236,222,251,5,17,1,193,204,195,206,156,1,129,6,171,236,222,251,5,9,5,198,171,236,222,251,5,25,171,236,222,251,5,9,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,18,1,161,171,236,222,251,5,19,1,161,171,236,222,251,5,20,1,193,204,195,206,156,1,129,6,171,236,222,251,5,21,5,198,171,236,222,251,5,34,171,236,222,251,5,21,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,27,1,161,171,236,222,251,5,28,1,161,171,236,222,251,5,29,1,198,204,195,206,156,1,129,6,171,236,222,251,5,30,10,102,111,110,116,95,99,111,108,111,114,12,34,48,120,102,102,100,98,51,54,51,54,34,193,171,236,222,251,5,39,171,236,222,251,5,30,4,198,171,236,222,251,5,43,171,236,222,251,5,30,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,36,1,161,171,236,222,251,5,37,1,161,171,236,222,251,5,38,1,193,171,236,222,251,5,39,171,236,222,251,5,40,5,198,171,236,222,251,5,52,171,236,222,251,5,40,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,45,1,161,171,236,222,251,5,46,1,161,171,236,222,251,5,47,1,193,171,236,222,251,5,39,171,236,222,251,5,48,5,198,171,236,222,251,5,61,171,236,222,251,5,48,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,54,1,161,171,236,222,251,5,55,1,161,171,236,222,251,5,56,1,198,171,236,222,251,5,39,171,236,222,251,5,57,8,98,103,95,99,111,108,111,114,12,34,48,120,102,102,102,102,100,97,101,54,34,196,171,236,222,251,5,66,171,236,222,251,5,57,4,110,101,120,116,198,171,236,222,251,5,70,171,236,222,251,5,57,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,63,1,161,171,236,222,251,5,64,1,161,171,236,222,251,5,65,1,198,204,195,206,156,1,180,6,204,195,206,156,1,181,6,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,193,171,236,222,251,5,75,204,195,206,156,1,181,6,3,198,171,236,222,251,5,78,204,195,206,156,1,181,6,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,161,171,236,222,251,5,72,1,161,171,236,222,251,5,73,1,161,171,236,222,251,5,74,1,198,171,236,222,251,5,75,171,236,222,251,5,76,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,193,171,236,222,251,5,83,171,236,222,251,5,76,3,198,171,236,222,251,5,86,171,236,222,251,5,76,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,161,171,236,222,251,5,80,1,161,171,236,222,251,5,81,1,161,171,236,222,251,5,82,1,198,171,236,222,251,5,83,171,236,222,251,5,84,6,105,116,97,108,105,99,4,116,114,117,101,193,171,236,222,251,5,91,171,236,222,251,5,84,3,198,171,236,222,251,5,94,171,236,222,251,5,84,6,105,116,97,108,105,99,4,110,117,108,108,161,171,236,222,251,5,88,1,161,171,236,222,251,5,89,1,161,171,236,222,251,5,90,1,196,171,236,222,251,5,94,171,236,222,251,5,95,9,230,140,168,233,161,191,230,137,147,161,171,236,222,251,5,96,1,161,171,236,222,251,5,97,1,161,171,236,222,251,5,98,1,39,0,204,195,206,156,1,4,6,68,89,98,118,73,66,2,33,0,204,195,206,156,1,1,6,109,57,74,107,49,75,1,0,7,33,0,204,195,206,156,1,3,6,78,76,50,70,103,95,1,193,204,195,206,156,1,238,1,204,195,206,156,1,239,1,1,168,171,236,222,251,5,102,1,119,204,5,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,43,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,102,102,102,102,100,97,101,54,34,44,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,102,102,100,98,51,54,51,54,34,125,44,34,105,110,115,101,114,116,34,58,34,110,101,120,116,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,116,111,32,97,110,121,32,112,97,103,101,32,116,105,116,108,101,32,105,110,32,116,104,101,32,115,105,100,101,98,97,114,32,116,111,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,102,102,56,52,50,55,101,48,34,125,44,34,105,110,115,101,114,116,34,58,34,113,117,105,99,107,108,121,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,105,116,97,108,105,99,34,58,116,114,117,101,44,34,115,116,114,105,107,101,116,104,114,111,117,103,104,34,58,116,114,117,101,44,34,117,110,100,101,114,108,105,110,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,230,140,168,233,161,191,230,137,147,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,97,32,110,101,119,32,115,117,98,112,97,103,101,44,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,68,111,99,117,109,101,110,116,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,102,97,108,115,101,125,44,34,105,110,115,101,114,116,34,58,34,44,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,71,114,105,100,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,102,97,108,115,101,125,44,34,105,110,115,101,114,116,34,58,34,44,32,111,114,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,75,97,110,98,97,110,32,66,111,97,114,100,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,102,97,108,115,101,125,44,34,105,110,115,101,114,116,34,58,34,46,34,125,93,44,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,168,171,236,222,251,5,103,1,119,10,98,113,76,109,98,57,111,45,109,109,168,171,236,222,251,5,104,1,119,4,116,101,120,116,39,0,204,195,206,156,1,4,6,68,53,45,65,82,65,2,33,0,204,195,206,156,1,1,6,89,87,119,55,87,53,1,0,7,33,0,204,195,206,156,1,3,6,85,68,79,77,112,98,1,1,0,204,195,206,156,1,14,1,39,0,204,195,206,156,1,4,6,107,90,52,97,119,69,2,33,0,204,195,206,156,1,1,6,108,79,120,55,95,83,1,0,7,33,0,204,195,206,156,1,3,6,50,109,115,116,117,104,1,193,171,236,222,251,5,115,204,195,206,156,1,239,1,1,39,0,204,195,206,156,1,4,6,52,98,104,66,88,113,2,33,0,204,195,206,156,1,1,6,121,105,115,116,115,72,1,0,7,33,0,204,195,206,156,1,3,6,53,67,71,119,50,122,1,129,171,236,222,251,5,129,1,1,39,0,204,195,206,156,1,4,6,87,105,113,49,48,95,2,33,0,204,195,206,156,1,1,6,71,121,98,79,49,81,1,0,7,33,0,204,195,206,156,1,3,6,66,90,69,117,90,106,1,193,171,236,222,251,5,129,1,171,236,222,251,5,151,1,1,39,0,204,195,206,156,1,4,6,106,101,65,53,90,85,2,39,0,204,195,206,156,1,1,6,102,67,65,65,81,117,1,40,0,171,236,222,251,5,164,1,2,105,100,1,119,6,102,67,65,65,81,117,40,0,171,236,222,251,5,164,1,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,171,236,222,251,5,164,1,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,171,236,222,251,5,164,1,8,99,104,105,108,100,114,101,110,1,119,6,52,74,88,112,120,108,33,0,171,236,222,251,5,164,1,4,100,97,116,97,1,40,0,171,236,222,251,5,164,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,164,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,52,74,88,112,120,108,0,200,171,236,222,251,5,129,1,171,236,222,251,5,162,1,1,119,6,102,67,65,65,81,117,4,0,171,236,222,251,5,163,1,6,228,189,147,233,170,140,129,171,236,222,251,5,175,1,1,161,171,236,222,251,5,169,1,1,198,171,236,222,251,5,175,1,171,236,222,251,5,176,1,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,193,171,236,222,251,5,178,1,171,236,222,251,5,176,1,1,198,171,236,222,251,5,179,1,171,236,222,251,5,176,1,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,161,171,236,222,251,5,177,1,1,198,171,236,222,251,5,178,1,171,236,222,251,5,179,1,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,196,171,236,222,251,5,182,1,171,236,222,251,5,179,1,3,228,184,128,198,171,236,222,251,5,183,1,171,236,222,251,5,179,1,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,168,171,236,222,251,5,181,1,1,119,101,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,228,189,147,233,170,140,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,115,116,114,105,107,101,116,104,114,111,117,103,104,34,58,116,114,117,101,44,34,117,110,100,101,114,108,105,110,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,228,184,128,34,125,93,125,39,0,204,195,206,156,1,4,6,82,74,108,100,72,67,2,33,0,204,195,206,156,1,1,6,53,106,100,78,87,117,1,0,7,33,0,204,195,206,156,1,3,6,67,106,107,76,57,108,1,129,171,236,222,251,5,151,1,1,4,0,171,236,222,251,5,186,1,4,103,104,104,104,0,1,39,0,204,195,206,156,1,4,6,70,117,117,52,113,66,2,4,0,171,236,222,251,5,202,1,4,103,104,104,104,33,0,204,195,206,156,1,1,6,121,112,70,119,50,69,1,0,7,33,0,204,195,206,156,1,3,6,71,77,54,72,55,119,1,193,171,236,222,251,5,151,1,171,236,222,251,5,196,1,1,39,0,204,195,206,156,1,4,6,118,113,76,104,110,70,2,4,0,171,236,222,251,5,217,1,4,103,104,104,104,33,0,204,195,206,156,1,1,6,73,57,73,75,116,115,1,0,7,33,0,204,195,206,156,1,3,6,77,114,102,81,106,87,1,193,171,236,222,251,5,140,1,204,195,206,156,1,239,1,1,39,0,204,195,206,156,1,4,6,89,50,52,104,77,55,2,4,0,171,236,222,251,5,232,1,4,103,104,104,104,33,0,204,195,206,156,1,1,6,107,110,74,87,104,48,1,0,7,33,0,204,195,206,156,1,3,6,55,99,67,68,120,77,1,129,171,236,222,251,5,196,1,1,0,7,39,0,204,195,206,156,1,4,6,109,98,56,104,95,45,2,4,0,171,236,222,251,5,254,1,4,103,104,104,104,33,0,204,195,206,156,1,1,6,103,75,73,116,90,101,1,0,7,33,0,204,195,206,156,1,3,6,118,115,54,50,82,105,1,193,171,236,222,251,5,196,1,171,236,222,251,5,246,1,1,39,0,204,195,206,156,1,4,6,105,67,98,56,102,56,2,4,0,171,236,222,251,5,141,2,4,103,104,104,104,33,0,204,195,206,156,1,1,6,88,113,72,53,122,82,1,0,7,33,0,204,195,206,156,1,3,6,73,111,48,108,119,67,1,193,171,236,222,251,5,196,1,171,236,222,251,5,140,2,1,39,0,204,195,206,156,1,4,6,82,89,116,67,111,86,2,4,0,171,236,222,251,5,156,2,4,103,104,104,104,39,0,204,195,206,156,1,1,6,49,120,78,111,50,76,1,40,0,171,236,222,251,5,161,2,2,105,100,1,119,6,49,120,78,111,50,76,40,0,171,236,222,251,5,161,2,2,116,121,1,119,5,113,117,111,116,101,40,0,171,236,222,251,5,161,2,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,171,236,222,251,5,161,2,8,99,104,105,108,100,114,101,110,1,119,6,67,85,68,115,45,70,33,0,171,236,222,251,5,161,2,4,100,97,116,97,1,40,0,171,236,222,251,5,161,2,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,161,2,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,67,85,68,115,45,70,0,200,171,236,222,251,5,196,1,171,236,222,251,5,155,2,1,119,6,49,120,78,111,50,76,39,0,204,195,206,156,1,4,6,122,112,90,112,49,101,2,33,0,204,195,206,156,1,1,6,109,65,112,48,84,75,1,0,7,33,0,204,195,206,156,1,3,6,117,95,113,85,121,95,1,129,171,236,222,251,5,246,1,1,4,0,171,236,222,251,5,171,2,4,104,106,106,106,0,1,39,0,204,195,206,156,1,4,6,79,88,120,110,65,84,2,4,0,171,236,222,251,5,187,2,4,104,106,106,106,33,0,204,195,206,156,1,1,6,109,70,99,75,110,81,1,0,7,33,0,204,195,206,156,1,3,6,72,52,122,104,56,95,1,193,171,236,222,251,5,246,1,171,236,222,251,5,181,2,1,39,0,204,195,206,156,1,4,6,90,97,54,99,87,113,2,4,0,171,236,222,251,5,202,2,4,104,106,106,106,33,0,204,195,206,156,1,1,6,50,110,113,71,98,75,1,0,7,33,0,204,195,206,156,1,3,6,95,69,69,76,53,109,1,193,171,236,222,251,5,246,1,171,236,222,251,5,201,2,1,39,0,204,195,206,156,1,4,6,95,88,107,52,56,116,2,4,0,171,236,222,251,5,217,2,4,104,106,106,106,33,0,204,195,206,156,1,1,6,68,99,97,85,109,79,1,0,7,33,0,204,195,206,156,1,3,6,120,69,54,111,108,48,1,193,171,236,222,251,5,231,1,204,195,206,156,1,239,1,1,39,0,204,195,206,156,1,4,6,82,106,87,98,56,111,2,4,0,171,236,222,251,5,232,2,4,104,106,106,106,33,0,204,195,206,156,1,1,6,87,98,82,107,87,69,1,0,7,33,0,204,195,206,156,1,3,6,89,103,114,112,81,55,1,129,171,236,222,251,5,181,2,1,39,0,204,195,206,156,1,4,6,112,107,78,57,112,83,2,4,0,171,236,222,251,5,247,2,4,104,106,106,106,33,0,204,195,206,156,1,1,6,79,98,74,118,76,57,1,0,7,33,0,204,195,206,156,1,3,6,97,79,100,49,121,82,1,193,171,236,222,251,5,181,2,171,236,222,251,5,246,2,1,39,0,204,195,206,156,1,4,6,99,51,100,115,103,56,2,4,0,171,236,222,251,5,134,3,4,104,106,106,106,33,0,204,195,206,156,1,1,6,109,119,79,85,85,87,1,0,7,33,0,204,195,206,156,1,3,6,98,70,74,53,121,122,1,193,171,236,222,251,5,181,2,171,236,222,251,5,133,3,1,39,0,204,195,206,156,1,4,6,104,82,53,106,71,79,2,1,0,171,236,222,251,5,149,3,4,33,0,204,195,206,156,1,1,6,73,77,51,71,72,50,1,0,7,33,0,204,195,206,156,1,3,6,119,85,111,112,97,102,1,193,171,236,222,251,5,181,2,171,236,222,251,5,148,3,1,0,4,39,0,204,195,206,156,1,4,6,74,66,108,114,84,51,2,33,0,204,195,206,156,1,1,6,76,105,86,56,56,104,1,0,7,33,0,204,195,206,156,1,3,6,112,106,107,107,53,97,1,193,171,236,222,251,5,181,2,171,236,222,251,5,163,3,1,1,0,171,236,222,251,5,168,3,1,0,2,129,171,236,222,251,5,179,3,1,0,1,196,171,236,222,251,5,179,3,171,236,222,251,5,182,3,3,226,128,148,0,1,39,0,204,195,206,156,1,4,6,89,108,67,77,99,111,2,39,0,204,195,206,156,1,1,6,112,69,80,105,117,115,1,40,0,171,236,222,251,5,187,3,2,105,100,1,119,6,112,69,80,105,117,115,40,0,171,236,222,251,5,187,3,2,116,121,1,119,7,100,105,118,105,100,101,114,40,0,171,236,222,251,5,187,3,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,171,236,222,251,5,187,3,8,99,104,105,108,100,114,101,110,1,119,6,49,45,49,107,111,85,40,0,171,236,222,251,5,187,3,4,100,97,116,97,1,119,2,123,125,40,0,171,236,222,251,5,187,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,187,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,49,45,49,107,111,85,0,200,171,236,222,251,5,181,2,171,236,222,251,5,178,3,1,119,6,112,69,80,105,117,115,39,0,204,195,206,156,1,1,6,95,65,78,99,110,51,1,40,0,171,236,222,251,5,197,3,2,105,100,1,119,6,95,65,78,99,110,51,40,0,171,236,222,251,5,197,3,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,171,236,222,251,5,197,3,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,171,236,222,251,5,197,3,8,99,104,105,108,100,114,101,110,1,119,6,84,45,117,87,109,83,33,0,171,236,222,251,5,197,3,4,100,97,116,97,1,40,0,171,236,222,251,5,197,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,197,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,84,45,117,87,109,83,0,136,171,236,222,251,5,246,2,1,119,6,95,65,78,99,110,51,4,0,171,236,222,251,5,186,3,1,54,161,171,236,222,251,5,202,3,1,132,171,236,222,251,5,207,3,1,54,161,171,236,222,251,5,208,3,1,132,171,236,222,251,5,209,3,1,54,161,171,236,222,251,5,210,3,1,132,171,236,222,251,5,211,3,1,57,168,171,236,222,251,5,212,3,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,54,54,54,57,34,125,93,125,39,0,204,195,206,156,1,1,6,79,77,79,95,52,106,1,40,0,171,236,222,251,5,215,3,2,105,100,1,119,6,79,77,79,95,52,106,40,0,171,236,222,251,5,215,3,2,116,121,1,119,7,100,105,118,105,100,101,114,40,0,171,236,222,251,5,215,3,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,171,236,222,251,5,215,3,8,99,104,105,108,100,114,101,110,1,119,6,99,107,78,65,119,105,40,0,171,236,222,251,5,215,3,4,100,97,116,97,1,119,2,123,125,40,0,171,236,222,251,5,215,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,215,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,99,107,78,65,119,105,0,200,171,236,222,251,5,246,2,171,236,222,251,5,206,3,1,119,6,79,77,79,95,52,106,39,0,204,195,206,156,1,4,6,45,80,118,95,90,87,2,4,0,171,236,222,251,5,225,3,4,103,104,104,104,39,0,204,195,206,156,1,4,6,87,105,54,69,77,70,2,4,0,171,236,222,251,5,230,3,4,54,54,54,57,39,0,204,195,206,156,1,1,6,122,78,116,118,66,84,1,40,0,171,236,222,251,5,235,3,2,105,100,1,119,6,122,78,116,118,66,84,40,0,171,236,222,251,5,235,3,2,116,121,1,119,5,113,117,111,116,101,40,0,171,236,222,251,5,235,3,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,171,236,222,251,5,235,3,8,99,104,105,108,100,114,101,110,1,119,6,105,85,75,111,98,79,33,0,171,236,222,251,5,235,3,4,100,97,116,97,1,40,0,171,236,222,251,5,235,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,235,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,105,85,75,111,98,79,0,200,171,236,222,251,5,231,2,204,195,206,156,1,239,1,1,119,6,122,78,116,118,66,84,33,0,204,195,206,156,1,1,6,57,104,76,90,119,104,1,0,7,33,0,204,195,206,156,1,3,6,120,113,118,100,85,73,1,193,171,236,222,251,5,244,3,204,195,206,156,1,239,1,1,39,0,204,195,206,156,1,4,6,75,122,88,45,65,53,2,1,0,171,236,222,251,5,255,3,4,39,0,204,195,206,156,1,1,6,49,51,100,105,49,69,1,40,0,171,236,222,251,5,132,4,2,105,100,1,119,6,49,51,100,105,49,69,40,0,171,236,222,251,5,132,4,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,171,236,222,251,5,132,4,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,171,236,222,251,5,132,4,8,99,104,105,108,100,114,101,110,1,119,6,106,54,115,52,103,109,33,0,171,236,222,251,5,132,4,4,100,97,116,97,1,40,0,171,236,222,251,5,132,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,171,236,222,251,5,132,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,106,54,115,52,103,109,0,200,171,236,222,251,5,244,3,171,236,222,251,5,254,3,1,119,6,49,51,100,105,49,69,161,171,236,222,251,5,137,4,2,65,171,236,222,251,5,128,4,5,198,171,236,222,251,5,148,4,171,236,222,251,5,128,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,143,4,1,65,171,236,222,251,5,144,4,5,198,171,236,222,251,5,155,4,171,236,222,251,5,144,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,150,4,1,65,171,236,222,251,5,151,4,5,198,171,236,222,251,5,162,4,171,236,222,251,5,151,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,157,4,1,65,171,236,222,251,5,158,4,5,198,171,236,222,251,5,169,4,171,236,222,251,5,158,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,164,4,1,65,171,236,222,251,5,165,4,5,198,171,236,222,251,5,176,4,171,236,222,251,5,165,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,171,4,1,65,171,236,222,251,5,172,4,5,198,171,236,222,251,5,183,4,171,236,222,251,5,172,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,178,4,1,65,171,236,222,251,5,179,4,5,198,171,236,222,251,5,190,4,171,236,222,251,5,179,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,185,4,1,65,171,236,222,251,5,186,4,5,198,171,236,222,251,5,197,4,171,236,222,251,5,186,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,192,4,1,70,171,236,222,251,5,193,4,8,98,103,95,99,111,108,111,114,12,34,48,120,102,102,102,102,100,97,101,54,34,193,171,236,222,251,5,200,4,171,236,222,251,5,193,4,4,198,171,236,222,251,5,204,4,171,236,222,251,5,193,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,199,4,2,193,171,236,222,251,5,200,4,171,236,222,251,5,201,4,5,198,171,236,222,251,5,212,4,171,236,222,251,5,201,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,207,4,1,193,171,236,222,251,5,200,4,171,236,222,251,5,208,4,5,198,171,236,222,251,5,219,4,171,236,222,251,5,208,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,214,4,1,193,171,236,222,251,5,200,4,171,236,222,251,5,215,4,5,198,171,236,222,251,5,226,4,171,236,222,251,5,215,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,221,4,1,193,171,236,222,251,5,200,4,171,236,222,251,5,222,4,5,198,171,236,222,251,5,233,4,171,236,222,251,5,222,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,228,4,1,193,171,236,222,251,5,200,4,171,236,222,251,5,229,4,5,198,171,236,222,251,5,240,4,171,236,222,251,5,229,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,161,171,236,222,251,5,235,4,1,70,171,236,222,251,5,200,4,10,102,111,110,116,95,99,111,108,111,114,12,34,48,120,102,102,101,97,56,102,48,54,34,198,171,236,222,251,5,243,4,171,236,222,251,5,200,4,8,98,103,95,99,111,108,111,114,12,34,48,120,102,102,97,55,100,102,52,97,34,196,171,236,222,251,5,244,4,171,236,222,251,5,200,4,4,54,54,54,57,193,171,236,222,251,5,248,4,171,236,222,251,5,200,4,1,198,171,236,222,251,5,249,4,171,236,222,251,5,200,4,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,168,171,236,222,251,5,242,4,1,119,110,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,102,102,97,55,100,102,52,97,34,44,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,102,102,101,97,56,102,48,54,34,125,44,34,105,110,115,101,114,116,34,58,34,54,54,54,57,34,125,93,125,7,226,167,254,250,5,0,39,0,204,195,206,156,1,4,6,72,97,87,55,95,104,2,4,0,226,167,254,250,5,0,13,229,144,140,228,184,128,228,184,170,106,106,106,56,161,198,223,206,159,1,124,1,132,226,167,254,250,5,7,1,56,161,226,167,254,250,5,8,1,132,226,167,254,250,5,9,1,56,161,226,167,254,250,5,10,1,1,161,234,157,145,5,0,161,247,212,219,208,10,45,7,1,136,172,186,168,4,0,161,176,238,158,139,14,174,2,182,6,4,217,168,198,159,4,0,129,204,195,206,156,1,154,7,4,161,204,195,206,156,1,227,1,1,161,204,195,206,156,1,228,1,1,161,204,195,206,156,1,229,1,1,215,6,150,216,171,142,3,0,161,199,130,209,189,2,177,3,6,161,164,202,219,213,10,80,1,161,164,202,219,213,10,81,1,161,164,202,219,213,10,82,1,161,150,216,171,142,3,6,1,161,150,216,171,142,3,7,1,161,150,216,171,142,3,8,1,129,204,195,206,156,1,207,5,1,161,150,216,171,142,3,9,1,161,150,216,171,142,3,10,1,161,150,216,171,142,3,11,1,129,150,216,171,142,3,12,1,161,150,216,171,142,3,13,1,161,150,216,171,142,3,14,1,161,150,216,171,142,3,15,1,161,150,216,171,142,3,17,1,161,150,216,171,142,3,18,1,161,150,216,171,142,3,19,1,161,150,216,171,142,3,20,1,161,150,216,171,142,3,21,1,161,150,216,171,142,3,22,1,129,150,216,171,142,3,16,1,161,150,216,171,142,3,23,1,161,150,216,171,142,3,24,1,161,150,216,171,142,3,25,1,129,150,216,171,142,3,26,1,161,150,216,171,142,3,27,1,161,150,216,171,142,3,28,1,161,150,216,171,142,3,29,1,129,150,216,171,142,3,30,1,161,150,216,171,142,3,31,1,161,150,216,171,142,3,32,1,161,150,216,171,142,3,33,1,129,150,216,171,142,3,34,1,161,150,216,171,142,3,35,1,161,150,216,171,142,3,36,1,161,150,216,171,142,3,37,1,129,150,216,171,142,3,38,1,161,150,216,171,142,3,39,1,161,150,216,171,142,3,40,1,161,150,216,171,142,3,41,1,129,150,216,171,142,3,42,1,161,150,216,171,142,3,43,1,161,150,216,171,142,3,44,1,161,150,216,171,142,3,45,1,129,150,216,171,142,3,46,1,161,150,216,171,142,3,47,1,161,150,216,171,142,3,48,1,161,150,216,171,142,3,49,1,129,150,216,171,142,3,50,1,161,150,216,171,142,3,51,1,161,150,216,171,142,3,52,1,161,150,216,171,142,3,53,1,129,150,216,171,142,3,54,1,161,150,216,171,142,3,55,1,161,150,216,171,142,3,56,1,161,150,216,171,142,3,57,1,129,150,216,171,142,3,58,1,161,150,216,171,142,3,59,1,161,150,216,171,142,3,60,1,161,150,216,171,142,3,61,1,129,150,216,171,142,3,62,1,161,150,216,171,142,3,63,1,161,150,216,171,142,3,64,1,161,150,216,171,142,3,65,1,129,150,216,171,142,3,66,1,161,150,216,171,142,3,67,1,161,150,216,171,142,3,68,1,161,150,216,171,142,3,69,1,129,150,216,171,142,3,70,1,161,150,216,171,142,3,71,1,161,150,216,171,142,3,72,1,161,150,216,171,142,3,73,1,129,150,216,171,142,3,74,1,161,150,216,171,142,3,75,1,161,150,216,171,142,3,76,1,161,150,216,171,142,3,77,1,129,150,216,171,142,3,78,1,161,150,216,171,142,3,79,1,161,150,216,171,142,3,80,1,161,150,216,171,142,3,81,1,129,150,216,171,142,3,82,1,161,150,216,171,142,3,83,1,161,150,216,171,142,3,84,1,161,150,216,171,142,3,85,1,129,150,216,171,142,3,86,1,161,150,216,171,142,3,87,1,161,150,216,171,142,3,88,1,161,150,216,171,142,3,89,1,129,150,216,171,142,3,90,1,161,150,216,171,142,3,91,1,161,150,216,171,142,3,92,1,161,150,216,171,142,3,93,1,129,150,216,171,142,3,94,1,161,150,216,171,142,3,95,1,161,150,216,171,142,3,96,1,161,150,216,171,142,3,97,1,129,150,216,171,142,3,98,1,161,150,216,171,142,3,99,1,161,150,216,171,142,3,100,1,161,150,216,171,142,3,101,1,129,150,216,171,142,3,102,1,161,150,216,171,142,3,103,1,161,150,216,171,142,3,104,1,161,150,216,171,142,3,105,1,129,150,216,171,142,3,106,1,161,150,216,171,142,3,107,1,161,150,216,171,142,3,108,1,161,150,216,171,142,3,109,1,129,150,216,171,142,3,110,1,161,150,216,171,142,3,111,1,161,150,216,171,142,3,112,1,161,150,216,171,142,3,113,1,129,150,216,171,142,3,114,1,161,150,216,171,142,3,115,1,161,150,216,171,142,3,116,1,161,150,216,171,142,3,117,1,129,150,216,171,142,3,118,1,161,150,216,171,142,3,119,1,161,150,216,171,142,3,120,1,161,150,216,171,142,3,121,1,129,150,216,171,142,3,122,1,161,150,216,171,142,3,123,1,161,150,216,171,142,3,124,1,161,150,216,171,142,3,125,1,129,150,216,171,142,3,126,1,161,150,216,171,142,3,127,1,161,150,216,171,142,3,128,1,1,161,150,216,171,142,3,129,1,1,129,150,216,171,142,3,130,1,1,161,150,216,171,142,3,131,1,1,161,150,216,171,142,3,132,1,1,161,150,216,171,142,3,133,1,1,129,150,216,171,142,3,134,1,1,161,150,216,171,142,3,135,1,1,161,150,216,171,142,3,136,1,1,161,150,216,171,142,3,137,1,1,193,150,216,171,142,3,134,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,139,1,1,161,150,216,171,142,3,140,1,1,161,150,216,171,142,3,141,1,1,193,150,216,171,142,3,142,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,143,1,1,161,150,216,171,142,3,144,1,1,161,150,216,171,142,3,145,1,1,193,150,216,171,142,3,146,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,147,1,1,161,150,216,171,142,3,148,1,1,161,150,216,171,142,3,149,1,1,193,150,216,171,142,3,150,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,151,1,1,161,150,216,171,142,3,152,1,1,161,150,216,171,142,3,153,1,1,193,150,216,171,142,3,154,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,155,1,1,161,150,216,171,142,3,156,1,1,161,150,216,171,142,3,157,1,1,193,150,216,171,142,3,158,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,159,1,1,161,150,216,171,142,3,160,1,1,161,150,216,171,142,3,161,1,1,193,150,216,171,142,3,162,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,163,1,1,161,150,216,171,142,3,164,1,1,161,150,216,171,142,3,165,1,1,193,150,216,171,142,3,166,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,167,1,1,161,150,216,171,142,3,168,1,1,161,150,216,171,142,3,169,1,1,193,150,216,171,142,3,170,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,171,1,1,161,150,216,171,142,3,172,1,1,161,150,216,171,142,3,173,1,1,193,150,216,171,142,3,174,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,175,1,1,161,150,216,171,142,3,176,1,1,161,150,216,171,142,3,177,1,1,193,150,216,171,142,3,178,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,179,1,1,161,150,216,171,142,3,180,1,1,161,150,216,171,142,3,181,1,1,193,150,216,171,142,3,182,1,150,216,171,142,3,138,1,1,161,150,216,171,142,3,183,1,1,161,150,216,171,142,3,184,1,1,161,150,216,171,142,3,185,1,1,129,150,216,171,142,3,138,1,4,161,150,216,171,142,3,187,1,1,161,150,216,171,142,3,188,1,1,161,150,216,171,142,3,189,1,1,129,150,216,171,142,3,193,1,1,161,150,216,171,142,3,194,1,1,161,150,216,171,142,3,195,1,1,161,150,216,171,142,3,196,1,1,161,150,216,171,142,3,198,1,1,161,150,216,171,142,3,199,1,1,161,150,216,171,142,3,200,1,1,161,150,216,171,142,3,201,1,1,161,150,216,171,142,3,202,1,1,161,150,216,171,142,3,203,1,1,161,150,216,171,142,3,204,1,1,161,150,216,171,142,3,205,1,1,161,150,216,171,142,3,206,1,1,129,150,216,171,142,3,197,1,1,161,150,216,171,142,3,207,1,1,161,150,216,171,142,3,208,1,1,161,150,216,171,142,3,209,1,1,129,150,216,171,142,3,210,1,1,161,150,216,171,142,3,211,1,1,161,150,216,171,142,3,212,1,1,161,150,216,171,142,3,213,1,1,129,150,216,171,142,3,214,1,1,161,150,216,171,142,3,215,1,1,161,150,216,171,142,3,216,1,1,161,150,216,171,142,3,217,1,1,129,150,216,171,142,3,218,1,1,161,150,216,171,142,3,219,1,1,161,150,216,171,142,3,220,1,1,161,150,216,171,142,3,221,1,1,129,150,216,171,142,3,222,1,1,161,150,216,171,142,3,223,1,1,161,150,216,171,142,3,224,1,1,161,150,216,171,142,3,225,1,1,129,150,216,171,142,3,226,1,1,161,150,216,171,142,3,227,1,1,161,150,216,171,142,3,228,1,1,161,150,216,171,142,3,229,1,1,129,150,216,171,142,3,230,1,1,161,150,216,171,142,3,231,1,1,161,150,216,171,142,3,232,1,1,161,150,216,171,142,3,233,1,1,129,150,216,171,142,3,234,1,1,161,150,216,171,142,3,235,1,1,161,150,216,171,142,3,236,1,1,161,150,216,171,142,3,237,1,1,129,150,216,171,142,3,238,1,1,161,150,216,171,142,3,239,1,1,161,150,216,171,142,3,240,1,1,161,150,216,171,142,3,241,1,1,129,150,216,171,142,3,242,1,1,161,150,216,171,142,3,243,1,1,161,150,216,171,142,3,244,1,1,161,150,216,171,142,3,245,1,1,129,150,216,171,142,3,246,1,1,161,150,216,171,142,3,247,1,1,161,150,216,171,142,3,248,1,1,161,150,216,171,142,3,249,1,1,129,150,216,171,142,3,250,1,1,161,150,216,171,142,3,251,1,1,161,150,216,171,142,3,252,1,1,161,150,216,171,142,3,253,1,1,129,150,216,171,142,3,254,1,1,161,150,216,171,142,3,255,1,1,161,150,216,171,142,3,128,2,1,161,150,216,171,142,3,129,2,1,129,150,216,171,142,3,130,2,1,161,150,216,171,142,3,131,2,1,161,150,216,171,142,3,132,2,1,161,150,216,171,142,3,133,2,1,129,150,216,171,142,3,134,2,1,161,150,216,171,142,3,135,2,1,161,150,216,171,142,3,136,2,1,161,150,216,171,142,3,137,2,1,129,150,216,171,142,3,138,2,1,161,150,216,171,142,3,139,2,1,161,150,216,171,142,3,140,2,1,161,150,216,171,142,3,141,2,1,161,150,216,171,142,3,143,2,1,161,150,216,171,142,3,144,2,1,161,150,216,171,142,3,145,2,1,129,150,216,171,142,3,142,2,1,161,150,216,171,142,3,146,2,1,161,150,216,171,142,3,147,2,1,161,150,216,171,142,3,148,2,1,161,150,216,171,142,3,150,2,1,161,150,216,171,142,3,151,2,1,161,150,216,171,142,3,152,2,1,161,150,216,171,142,3,153,2,1,161,150,216,171,142,3,154,2,1,161,150,216,171,142,3,155,2,1,161,150,216,171,142,3,156,2,1,161,150,216,171,142,3,157,2,1,161,150,216,171,142,3,158,2,1,129,150,216,171,142,3,149,2,1,161,150,216,171,142,3,159,2,1,161,150,216,171,142,3,160,2,1,161,150,216,171,142,3,161,2,1,129,150,216,171,142,3,162,2,1,161,150,216,171,142,3,163,2,1,161,150,216,171,142,3,164,2,1,161,150,216,171,142,3,165,2,1,129,150,216,171,142,3,166,2,1,161,150,216,171,142,3,167,2,1,161,150,216,171,142,3,168,2,1,161,150,216,171,142,3,169,2,1,129,150,216,171,142,3,170,2,1,161,150,216,171,142,3,171,2,1,161,150,216,171,142,3,172,2,1,161,150,216,171,142,3,173,2,1,129,150,216,171,142,3,174,2,1,161,150,216,171,142,3,175,2,1,161,150,216,171,142,3,176,2,1,161,150,216,171,142,3,177,2,1,129,150,216,171,142,3,178,2,1,161,150,216,171,142,3,179,2,1,161,150,216,171,142,3,180,2,1,161,150,216,171,142,3,181,2,1,129,150,216,171,142,3,182,2,1,161,150,216,171,142,3,183,2,1,161,150,216,171,142,3,184,2,1,161,150,216,171,142,3,185,2,1,129,150,216,171,142,3,186,2,1,161,150,216,171,142,3,187,2,1,161,150,216,171,142,3,188,2,1,161,150,216,171,142,3,189,2,1,129,150,216,171,142,3,190,2,1,161,150,216,171,142,3,191,2,1,161,150,216,171,142,3,192,2,1,161,150,216,171,142,3,193,2,1,129,150,216,171,142,3,194,2,1,161,150,216,171,142,3,195,2,1,161,150,216,171,142,3,196,2,1,161,150,216,171,142,3,197,2,1,129,150,216,171,142,3,198,2,1,161,150,216,171,142,3,199,2,1,161,150,216,171,142,3,200,2,1,161,150,216,171,142,3,201,2,1,193,150,216,171,142,3,198,2,150,216,171,142,3,202,2,1,161,150,216,171,142,3,203,2,1,161,150,216,171,142,3,204,2,1,161,150,216,171,142,3,205,2,1,193,150,216,171,142,3,206,2,150,216,171,142,3,202,2,1,161,150,216,171,142,3,207,2,1,161,150,216,171,142,3,208,2,1,161,150,216,171,142,3,209,2,1,193,150,216,171,142,3,206,2,150,216,171,142,3,210,2,2,161,150,216,171,142,3,211,2,1,161,150,216,171,142,3,212,2,1,161,150,216,171,142,3,213,2,1,193,150,216,171,142,3,215,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,216,2,1,161,150,216,171,142,3,217,2,1,161,150,216,171,142,3,218,2,1,193,150,216,171,142,3,219,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,220,2,1,161,150,216,171,142,3,221,2,1,161,150,216,171,142,3,222,2,1,193,150,216,171,142,3,223,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,224,2,1,161,150,216,171,142,3,225,2,1,161,150,216,171,142,3,226,2,1,193,150,216,171,142,3,227,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,228,2,1,161,150,216,171,142,3,229,2,1,161,150,216,171,142,3,230,2,1,193,150,216,171,142,3,231,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,232,2,1,161,150,216,171,142,3,233,2,1,161,150,216,171,142,3,234,2,1,193,150,216,171,142,3,235,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,236,2,1,161,150,216,171,142,3,237,2,1,161,150,216,171,142,3,238,2,1,193,150,216,171,142,3,239,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,240,2,1,161,150,216,171,142,3,241,2,1,161,150,216,171,142,3,242,2,1,193,150,216,171,142,3,243,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,244,2,1,161,150,216,171,142,3,245,2,1,161,150,216,171,142,3,246,2,1,193,150,216,171,142,3,247,2,150,216,171,142,3,210,2,1,161,150,216,171,142,3,248,2,1,161,150,216,171,142,3,249,2,1,161,150,216,171,142,3,250,2,1,193,150,216,171,142,3,247,2,150,216,171,142,3,251,2,1,161,150,216,171,142,3,252,2,1,161,150,216,171,142,3,253,2,1,161,150,216,171,142,3,254,2,1,193,150,216,171,142,3,255,2,150,216,171,142,3,251,2,1,161,150,216,171,142,3,128,3,1,161,150,216,171,142,3,129,3,1,161,150,216,171,142,3,130,3,1,193,150,216,171,142,3,255,2,150,216,171,142,3,131,3,1,161,150,216,171,142,3,132,3,1,161,150,216,171,142,3,133,3,1,161,150,216,171,142,3,134,3,1,193,150,216,171,142,3,135,3,150,216,171,142,3,131,3,1,161,150,216,171,142,3,136,3,1,161,150,216,171,142,3,137,3,1,161,150,216,171,142,3,138,3,1,193,150,216,171,142,3,139,3,150,216,171,142,3,131,3,1,161,150,216,171,142,3,140,3,1,161,150,216,171,142,3,141,3,1,161,150,216,171,142,3,142,3,1,161,150,216,171,142,3,144,3,1,161,150,216,171,142,3,145,3,1,161,150,216,171,142,3,146,3,1,193,204,195,206,156,1,130,5,204,195,206,156,1,131,5,1,161,150,216,171,142,3,147,3,1,161,150,216,171,142,3,148,3,1,161,150,216,171,142,3,149,3,1,129,150,216,171,142,3,202,2,1,161,150,216,171,142,3,151,3,1,161,150,216,171,142,3,152,3,1,161,150,216,171,142,3,153,3,1,129,150,216,171,142,3,154,3,1,161,150,216,171,142,3,155,3,1,161,150,216,171,142,3,156,3,1,161,150,216,171,142,3,157,3,1,161,150,216,171,142,3,159,3,1,161,150,216,171,142,3,160,3,1,161,150,216,171,142,3,161,3,1,161,150,216,171,142,3,162,3,1,161,150,216,171,142,3,163,3,1,161,150,216,171,142,3,164,3,1,161,150,216,171,142,3,165,3,1,161,150,216,171,142,3,166,3,1,161,150,216,171,142,3,167,3,1,132,150,216,171,142,3,158,3,1,102,161,150,216,171,142,3,168,3,1,161,150,216,171,142,3,169,3,1,161,150,216,171,142,3,170,3,1,132,150,216,171,142,3,171,3,1,117,161,150,216,171,142,3,172,3,1,161,150,216,171,142,3,173,3,1,161,150,216,171,142,3,174,3,1,132,150,216,171,142,3,175,3,1,110,161,150,216,171,142,3,176,3,1,161,150,216,171,142,3,177,3,1,161,150,216,171,142,3,178,3,1,132,150,216,171,142,3,179,3,1,99,161,150,216,171,142,3,180,3,1,161,150,216,171,142,3,181,3,1,161,150,216,171,142,3,182,3,1,132,150,216,171,142,3,183,3,1,116,161,150,216,171,142,3,184,3,1,161,150,216,171,142,3,185,3,1,161,150,216,171,142,3,186,3,1,132,150,216,171,142,3,187,3,1,105,161,150,216,171,142,3,188,3,1,161,150,216,171,142,3,189,3,1,161,150,216,171,142,3,190,3,1,132,150,216,171,142,3,191,3,1,111,161,150,216,171,142,3,192,3,1,161,150,216,171,142,3,193,3,1,161,150,216,171,142,3,194,3,1,132,150,216,171,142,3,195,3,1,110,161,150,216,171,142,3,196,3,1,161,150,216,171,142,3,197,3,1,161,150,216,171,142,3,198,3,1,132,150,216,171,142,3,199,3,1,32,161,150,216,171,142,3,200,3,1,161,150,216,171,142,3,201,3,1,161,150,216,171,142,3,202,3,1,132,150,216,171,142,3,203,3,1,109,161,150,216,171,142,3,204,3,1,161,150,216,171,142,3,205,3,1,161,150,216,171,142,3,206,3,1,132,150,216,171,142,3,207,3,1,97,161,150,216,171,142,3,208,3,1,161,150,216,171,142,3,209,3,1,161,150,216,171,142,3,210,3,1,132,150,216,171,142,3,211,3,1,105,161,150,216,171,142,3,212,3,1,161,150,216,171,142,3,213,3,1,161,150,216,171,142,3,214,3,1,132,150,216,171,142,3,215,3,1,110,161,150,216,171,142,3,216,3,1,161,150,216,171,142,3,217,3,1,161,150,216,171,142,3,218,3,1,132,150,216,171,142,3,219,3,1,40,161,150,216,171,142,3,220,3,1,161,150,216,171,142,3,221,3,1,161,150,216,171,142,3,222,3,1,132,150,216,171,142,3,223,3,1,41,161,150,216,171,142,3,224,3,1,161,150,216,171,142,3,225,3,1,161,150,216,171,142,3,226,3,1,132,150,216,171,142,3,227,3,1,32,161,150,216,171,142,3,228,3,1,161,150,216,171,142,3,229,3,1,161,150,216,171,142,3,230,3,1,132,150,216,171,142,3,231,3,1,123,161,150,216,171,142,3,232,3,1,161,150,216,171,142,3,233,3,1,161,150,216,171,142,3,234,3,1,132,150,216,171,142,3,235,3,1,125,161,150,216,171,142,3,236,3,1,161,150,216,171,142,3,237,3,1,161,150,216,171,142,3,238,3,1,196,150,216,171,142,3,235,3,150,216,171,142,3,239,3,1,10,161,150,216,171,142,3,240,3,1,161,150,216,171,142,3,241,3,1,161,150,216,171,142,3,242,3,1,196,150,216,171,142,3,243,3,150,216,171,142,3,239,3,1,10,161,150,216,171,142,3,244,3,1,161,150,216,171,142,3,245,3,1,161,150,216,171,142,3,246,3,1,196,150,216,171,142,3,243,3,150,216,171,142,3,247,3,2,32,32,161,150,216,171,142,3,248,3,1,161,150,216,171,142,3,249,3,1,161,150,216,171,142,3,250,3,1,196,150,216,171,142,3,252,3,150,216,171,142,3,247,3,1,99,161,150,216,171,142,3,253,3,1,161,150,216,171,142,3,254,3,1,161,150,216,171,142,3,255,3,1,196,150,216,171,142,3,128,4,150,216,171,142,3,247,3,1,111,161,150,216,171,142,3,129,4,1,161,150,216,171,142,3,130,4,1,161,150,216,171,142,3,131,4,1,196,150,216,171,142,3,132,4,150,216,171,142,3,247,3,1,110,161,150,216,171,142,3,133,4,1,161,150,216,171,142,3,134,4,1,161,150,216,171,142,3,135,4,1,196,150,216,171,142,3,136,4,150,216,171,142,3,247,3,1,115,161,150,216,171,142,3,137,4,1,161,150,216,171,142,3,138,4,1,161,150,216,171,142,3,139,4,1,196,150,216,171,142,3,140,4,150,216,171,142,3,247,3,1,111,161,150,216,171,142,3,141,4,1,161,150,216,171,142,3,142,4,1,161,150,216,171,142,3,143,4,1,196,150,216,171,142,3,144,4,150,216,171,142,3,247,3,1,108,161,150,216,171,142,3,145,4,1,161,150,216,171,142,3,146,4,1,161,150,216,171,142,3,147,4,1,196,150,216,171,142,3,148,4,150,216,171,142,3,247,3,1,101,161,150,216,171,142,3,149,4,1,161,150,216,171,142,3,150,4,1,161,150,216,171,142,3,151,4,1,196,150,216,171,142,3,152,4,150,216,171,142,3,247,3,1,46,161,150,216,171,142,3,153,4,1,161,150,216,171,142,3,154,4,1,161,150,216,171,142,3,155,4,1,196,150,216,171,142,3,156,4,150,216,171,142,3,247,3,1,108,161,150,216,171,142,3,157,4,1,161,150,216,171,142,3,158,4,1,161,150,216,171,142,3,159,4,1,196,150,216,171,142,3,160,4,150,216,171,142,3,247,3,1,111,161,150,216,171,142,3,161,4,1,161,150,216,171,142,3,162,4,1,161,150,216,171,142,3,163,4,1,196,150,216,171,142,3,164,4,150,216,171,142,3,247,3,1,103,161,150,216,171,142,3,165,4,1,161,150,216,171,142,3,166,4,1,161,150,216,171,142,3,167,4,1,196,150,216,171,142,3,168,4,150,216,171,142,3,247,3,1,40,161,150,216,171,142,3,169,4,1,161,150,216,171,142,3,170,4,1,161,150,216,171,142,3,171,4,1,196,150,216,171,142,3,172,4,150,216,171,142,3,247,3,1,41,161,150,216,171,142,3,173,4,1,161,150,216,171,142,3,174,4,1,161,150,216,171,142,3,175,4,1,196,150,216,171,142,3,172,4,150,216,171,142,3,176,4,1,34,161,150,216,171,142,3,177,4,1,161,150,216,171,142,3,178,4,1,161,150,216,171,142,3,179,4,1,196,150,216,171,142,3,180,4,150,216,171,142,3,176,4,1,34,161,150,216,171,142,3,181,4,1,161,150,216,171,142,3,182,4,1,161,150,216,171,142,3,183,4,1,196,150,216,171,142,3,180,4,150,216,171,142,3,184,4,1,72,161,150,216,171,142,3,185,4,1,161,150,216,171,142,3,186,4,1,161,150,216,171,142,3,187,4,1,196,150,216,171,142,3,188,4,150,216,171,142,3,184,4,1,101,161,150,216,171,142,3,189,4,1,161,150,216,171,142,3,190,4,1,161,150,216,171,142,3,191,4,1,196,150,216,171,142,3,192,4,150,216,171,142,3,184,4,1,108,161,150,216,171,142,3,193,4,1,161,150,216,171,142,3,194,4,1,161,150,216,171,142,3,195,4,1,196,150,216,171,142,3,196,4,150,216,171,142,3,184,4,1,108,161,150,216,171,142,3,197,4,1,161,150,216,171,142,3,198,4,1,161,150,216,171,142,3,199,4,1,196,150,216,171,142,3,200,4,150,216,171,142,3,184,4,1,111,161,150,216,171,142,3,201,4,1,161,150,216,171,142,3,202,4,1,161,150,216,171,142,3,203,4,1,196,150,216,171,142,3,204,4,150,216,171,142,3,184,4,1,32,161,150,216,171,142,3,205,4,1,161,150,216,171,142,3,206,4,1,161,150,216,171,142,3,207,4,1,196,150,216,171,142,3,208,4,150,216,171,142,3,184,4,1,87,161,150,216,171,142,3,209,4,1,161,150,216,171,142,3,210,4,1,161,150,216,171,142,3,211,4,1,196,150,216,171,142,3,212,4,150,216,171,142,3,184,4,1,111,161,150,216,171,142,3,213,4,1,161,150,216,171,142,3,214,4,1,161,150,216,171,142,3,215,4,1,196,150,216,171,142,3,216,4,150,216,171,142,3,184,4,1,114,161,150,216,171,142,3,217,4,1,161,150,216,171,142,3,218,4,1,161,150,216,171,142,3,219,4,1,196,150,216,171,142,3,220,4,150,216,171,142,3,184,4,1,108,161,150,216,171,142,3,221,4,1,161,150,216,171,142,3,222,4,1,161,150,216,171,142,3,223,4,1,196,150,216,171,142,3,224,4,150,216,171,142,3,184,4,1,100,161,150,216,171,142,3,225,4,1,161,150,216,171,142,3,226,4,1,161,150,216,171,142,3,227,4,1,193,150,216,171,142,3,228,4,150,216,171,142,3,184,4,1,161,150,216,171,142,3,229,4,1,161,150,216,171,142,3,230,4,1,161,150,216,171,142,3,231,4,1,168,150,216,171,142,3,233,4,1,119,132,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,47,47,32,84,104,105,115,32,105,115,32,116,104,101,32,109,97,105,110,32,102,117,110,99,116,105,111,110,46,92,110,102,117,110,99,116,105,111,110,32,109,97,105,110,40,41,32,123,92,110,32,32,99,111,110,115,111,108,101,46,108,111,103,40,92,34,72,101,108,108,111,32,87,111,114,108,100,92,34,41,92,110,125,34,125,93,44,34,108,97,110,103,117,97,103,101,34,58,34,74,97,118,97,115,99,114,105,112,116,34,125,168,150,216,171,142,3,234,4,1,119,10,49,112,115,100,67,122,97,87,104,49,168,150,216,171,142,3,235,4,1,119,4,116,101,120,116,39,0,204,195,206,156,1,4,6,48,100,51,52,82,50,2,39,0,204,195,206,156,1,4,6,45,71,115,81,49,95,2,4,0,150,216,171,142,3,240,4,4,49,50,51,32,134,150,216,171,142,3,244,4,7,109,101,110,116,105,111,110,51,123,34,116,121,112,101,34,58,34,100,97,116,101,34,44,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,57,84,49,54,58,49,51,58,52,57,46,52,49,49,49,54,53,34,125,132,150,216,171,142,3,245,4,1,36,134,150,216,171,142,3,246,4,7,109,101,110,116,105,111,110,4,110,117,108,108,132,150,216,171,142,3,247,4,6,32,32,101,114,32,32,33,0,204,195,206,156,1,1,6,49,71,114,87,76,99,1,0,7,33,0,204,195,206,156,1,3,6,72,105,104,101,52,114,1,193,164,202,219,213,10,28,199,130,209,189,2,60,1,168,164,202,219,213,10,117,1,119,151,1,123,34,108,101,118,101,108,34,58,50,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,51,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,109,101,110,116,105,111,110,34,58,123,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,57,84,49,54,58,49,51,58,52,57,46,52,49,49,49,54,53,34,44,34,116,121,112,101,34,58,34,100,97,116,101,34,125,125,44,34,105,110,115,101,114,116,34,58,34,36,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,32,101,114,32,32,34,125,93,125,4,0,150,216,171,142,3,239,4,1,35,0,1,132,150,216,171,142,3,137,5,1,35,0,1,132,150,216,171,142,3,139,5,1,35,0,1,39,0,204,195,206,156,1,4,6,115,99,68,45,119,114,2,39,0,204,195,206,156,1,1,6,67,72,115,77,79,98,1,40,0,150,216,171,142,3,144,5,2,105,100,1,119,6,67,72,115,77,79,98,40,0,150,216,171,142,3,144,5,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,150,216,171,142,3,144,5,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,150,216,171,142,3,144,5,8,99,104,105,108,100,114,101,110,1,119,6,97,107,121,80,104,45,33,0,150,216,171,142,3,144,5,4,100,97,116,97,1,40,0,150,216,171,142,3,144,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,144,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,97,107,121,80,104,45,0,200,164,202,219,213,10,28,150,216,171,142,3,135,5,1,119,6,67,72,115,77,79,98,4,0,150,216,171,142,3,143,5,1,49,161,150,216,171,142,3,149,5,1,132,150,216,171,142,3,154,5,1,50,161,150,216,171,142,3,155,5,1,132,150,216,171,142,3,156,5,1,51,161,150,216,171,142,3,157,5,1,168,150,216,171,142,3,5,1,119,11,123,34,100,101,112,116,104,34,58,54,125,39,0,204,195,206,156,1,4,6,112,79,69,118,75,110,2,39,0,204,195,206,156,1,4,6,80,49,49,121,116,108,2,4,0,150,216,171,142,3,162,5,3,49,50,51,33,0,204,195,206,156,1,1,6,97,79,72,54,79,66,1,0,7,33,0,204,195,206,156,1,3,6,105,89,77,80,45,116,1,193,150,216,171,142,3,135,5,199,130,209,189,2,60,1,161,150,216,171,142,3,159,5,1,168,150,216,171,142,3,176,5,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,51,34,125,93,44,34,108,101,118,101,108,34,58,51,125,161,199,130,209,189,2,212,3,1,161,199,130,209,189,2,232,3,1,161,199,130,209,189,2,159,4,1,161,150,216,171,142,3,179,5,1,161,199,130,209,189,2,144,4,1,161,150,216,171,142,3,181,5,1,161,150,216,171,142,3,182,5,1,161,150,216,171,142,3,180,5,2,161,150,216,171,142,3,183,5,1,161,150,216,171,142,3,184,5,1,161,150,216,171,142,3,186,5,1,161,199,130,209,189,2,252,3,1,161,150,216,171,142,3,188,5,1,161,150,216,171,142,3,189,5,1,39,0,204,195,206,156,1,4,6,70,76,85,90,75,54,2,39,0,204,195,206,156,1,4,6,69,53,84,66,120,118,2,39,0,204,195,206,156,1,1,6,103,79,106,51,90,68,1,40,0,150,216,171,142,3,195,5,2,105,100,1,119,6,103,79,106,51,90,68,40,0,150,216,171,142,3,195,5,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,150,216,171,142,3,195,5,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,150,216,171,142,3,195,5,8,99,104,105,108,100,114,101,110,1,119,6,116,51,112,87,101,56,33,0,150,216,171,142,3,195,5,4,100,97,116,97,1,40,0,150,216,171,142,3,195,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,195,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,116,51,112,87,101,56,0,136,199,130,209,189,2,148,4,1,119,6,103,79,106,51,90,68,39,0,204,195,206,156,1,1,6,88,56,80,113,67,120,1,40,0,150,216,171,142,3,205,5,2,105,100,1,119,6,88,56,80,113,67,120,40,0,150,216,171,142,3,205,5,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,150,216,171,142,3,205,5,6,112,97,114,101,110,116,1,119,6,103,79,106,51,90,68,40,0,150,216,171,142,3,205,5,8,99,104,105,108,100,114,101,110,1,119,6,76,55,82,84,78,106,33,0,150,216,171,142,3,205,5,4,100,97,116,97,1,40,0,150,216,171,142,3,205,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,205,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,76,55,82,84,78,106,0,8,0,150,216,171,142,3,203,5,1,119,6,88,56,80,113,67,120,39,0,204,195,206,156,1,1,6,74,48,69,48,67,66,1,40,0,150,216,171,142,3,215,5,2,105,100,1,119,6,74,48,69,48,67,66,40,0,150,216,171,142,3,215,5,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,150,216,171,142,3,215,5,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,150,216,171,142,3,215,5,8,99,104,105,108,100,114,101,110,1,119,6,73,120,120,49,82,88,33,0,150,216,171,142,3,215,5,4,100,97,116,97,1,40,0,150,216,171,142,3,215,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,215,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,73,120,120,49,82,88,0,136,150,216,171,142,3,204,5,1,119,6,74,48,69,48,67,66,39,0,204,195,206,156,1,1,6,75,78,45,115,87,88,1,40,0,150,216,171,142,3,225,5,2,105,100,1,119,6,75,78,45,115,87,88,40,0,150,216,171,142,3,225,5,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,150,216,171,142,3,225,5,6,112,97,114,101,110,116,1,119,6,74,48,69,48,67,66,40,0,150,216,171,142,3,225,5,8,99,104,105,108,100,114,101,110,1,119,6,75,115,100,83,116,74,33,0,150,216,171,142,3,225,5,4,100,97,116,97,1,40,0,150,216,171,142,3,225,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,225,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,75,115,100,83,116,74,0,8,0,150,216,171,142,3,223,5,1,119,6,75,78,45,115,87,88,161,150,216,171,142,3,192,5,1,4,0,150,216,171,142,3,193,5,1,55,161,150,216,171,142,3,210,5,1,132,150,216,171,142,3,236,5,1,55,161,150,216,171,142,3,237,5,1,132,150,216,171,142,3,238,5,1,55,161,150,216,171,142,3,239,5,1,39,0,204,195,206,156,1,4,6,71,52,107,110,49,95,2,39,0,204,195,206,156,1,4,6,98,52,97,80,80,53,2,39,0,204,195,206,156,1,4,6,80,111,114,82,81,79,2,161,150,216,171,142,3,235,5,1,39,0,204,195,206,156,1,1,6,80,53,88,89,98,115,1,40,0,150,216,171,142,3,246,5,2,105,100,1,119,6,80,53,88,89,98,115,40,0,150,216,171,142,3,246,5,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,150,216,171,142,3,246,5,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,150,216,171,142,3,246,5,8,99,104,105,108,100,114,101,110,1,119,6,89,55,81,88,109,84,33,0,150,216,171,142,3,246,5,4,100,97,116,97,1,40,0,150,216,171,142,3,246,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,246,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,89,55,81,88,109,84,0,200,199,130,209,189,2,236,3,199,130,209,189,2,128,4,1,119,6,80,53,88,89,98,115,39,0,204,195,206,156,1,1,6,57,49,85,122,51,51,1,40,0,150,216,171,142,3,128,6,2,105,100,1,119,6,57,49,85,122,51,51,40,0,150,216,171,142,3,128,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,150,216,171,142,3,128,6,6,112,97,114,101,110,116,1,119,6,80,53,88,89,98,115,40,0,150,216,171,142,3,128,6,8,99,104,105,108,100,114,101,110,1,119,6,88,73,86,101,114,105,33,0,150,216,171,142,3,128,6,4,100,97,116,97,1,40,0,150,216,171,142,3,128,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,128,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,88,73,86,101,114,105,0,8,0,150,216,171,142,3,254,5,1,119,6,57,49,85,122,51,51,161,150,216,171,142,3,245,5,1,39,0,204,195,206,156,1,1,6,97,105,73,55,114,78,1,40,0,150,216,171,142,3,139,6,2,105,100,1,119,6,97,105,73,55,114,78,40,0,150,216,171,142,3,139,6,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,150,216,171,142,3,139,6,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,150,216,171,142,3,139,6,8,99,104,105,108,100,114,101,110,1,119,6,70,83,77,57,101,119,33,0,150,216,171,142,3,139,6,4,100,97,116,97,1,40,0,150,216,171,142,3,139,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,139,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,70,83,77,57,101,119,0,200,199,130,209,189,2,148,4,150,216,171,142,3,204,5,1,119,6,97,105,73,55,114,78,39,0,204,195,206,156,1,1,6,48,117,114,80,56,120,1,40,0,150,216,171,142,3,149,6,2,105,100,1,119,6,48,117,114,80,56,120,40,0,150,216,171,142,3,149,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,150,216,171,142,3,149,6,6,112,97,114,101,110,116,1,119,6,97,105,73,55,114,78,40,0,150,216,171,142,3,149,6,8,99,104,105,108,100,114,101,110,1,119,6,98,90,114,57,106,101,33,0,150,216,171,142,3,149,6,4,100,97,116,97,1,40,0,150,216,171,142,3,149,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,149,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,98,90,114,57,106,101,0,8,0,150,216,171,142,3,147,6,1,119,6,48,117,114,80,56,120,39,0,204,195,206,156,1,1,6,100,114,110,97,115,68,1,40,0,150,216,171,142,3,159,6,2,105,100,1,119,6,100,114,110,97,115,68,40,0,150,216,171,142,3,159,6,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,150,216,171,142,3,159,6,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,150,216,171,142,3,159,6,8,99,104,105,108,100,114,101,110,1,119,6,76,114,45,49,81,54,33,0,150,216,171,142,3,159,6,4,100,97,116,97,1,40,0,150,216,171,142,3,159,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,159,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,76,114,45,49,81,54,0,136,150,216,171,142,3,224,5,1,119,6,100,114,110,97,115,68,39,0,204,195,206,156,1,1,6,72,69,79,54,86,72,1,40,0,150,216,171,142,3,169,6,2,105,100,1,119,6,72,69,79,54,86,72,40,0,150,216,171,142,3,169,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,150,216,171,142,3,169,6,6,112,97,114,101,110,116,1,119,6,100,114,110,97,115,68,40,0,150,216,171,142,3,169,6,8,99,104,105,108,100,114,101,110,1,119,6,71,118,57,87,108,76,33,0,150,216,171,142,3,169,6,4,100,97,116,97,1,40,0,150,216,171,142,3,169,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,150,216,171,142,3,169,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,71,118,57,87,108,76,0,8,0,150,216,171,142,3,167,6,1,119,6,72,69,79,54,86,72,4,0,150,216,171,142,3,242,5,1,49,161,150,216,171,142,3,133,6,1,132,150,216,171,142,3,179,6,1,48,161,150,216,171,142,3,180,6,1,132,150,216,171,142,3,181,6,1,49,161,150,216,171,142,3,182,6,1,132,150,216,171,142,3,183,6,1,48,161,150,216,171,142,3,184,6,1,161,150,216,171,142,3,187,5,1,161,150,216,171,142,3,191,5,1,161,150,216,171,142,3,220,5,1,161,150,216,171,142,3,138,6,1,39,0,204,195,206,156,1,4,6,54,73,68,55,103,118,2,4,0,150,216,171,142,3,191,6,1,49,168,199,130,209,189,2,169,4,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,34,125,93,125,39,0,204,195,206,156,1,4,6,77,84,68,68,110,107,2,4,0,150,216,171,142,3,194,6,1,50,168,199,130,209,189,2,242,3,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,50,34,125,93,125,39,0,204,195,206,156,1,4,6,88,108,87,102,45,70,2,4,0,150,216,171,142,3,197,6,1,51,168,150,216,171,142,3,186,6,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,51,34,125,93,125,39,0,204,195,206,156,1,4,6,57,98,65,107,106,109,2,4,0,150,216,171,142,3,200,6,1,52,168,199,130,209,189,2,134,4,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,52,34,125,93,125,39,0,204,195,206,156,1,4,6,99,112,85,122,107,121,2,4,0,150,216,171,142,3,203,6,1,53,168,199,130,209,189,2,177,4,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,53,34,125,93,125,39,0,204,195,206,156,1,4,6,81,102,72,107,77,77,2,4,0,150,216,171,142,3,206,6,1,54,168,150,216,171,142,3,154,6,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,54,34,125,93,125,39,0,204,195,206,156,1,4,6,119,113,82,74,112,76,2,4,0,150,216,171,142,3,209,6,1,55,168,150,216,171,142,3,241,5,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,55,34,125,93,125,39,0,204,195,206,156,1,4,6,69,70,82,71,121,80,2,4,0,150,216,171,142,3,212,6,1,56,168,150,216,171,142,3,230,5,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,56,34,125,93,125,39,0,204,195,206,156,1,4,6,104,109,90,99,72,101,2,1,0,150,216,171,142,3,215,6,1,161,150,216,171,142,3,174,6,2,132,150,216,171,142,3,216,6,1,57,168,150,216,171,142,3,218,6,1,119,26,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,57,34,125,93,125,39,0,204,195,206,156,1,4,6,56,117,111,87,49,119,2,4,0,150,216,171,142,3,221,6,4,119,105,116,104,168,199,130,209,189,2,146,3,1,119,61,123,34,97,108,105,103,110,34,58,34,114,105,103,104,116,34,44,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,119,105,116,104,34,125,93,125,39,0,204,195,206,156,1,4,6,109,55,80,110,81,54,2,4,0,150,216,171,142,3,227,6,3,108,111,110,129,150,216,171,142,3,230,6,14,132,150,216,171,142,3,244,6,44,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,134,150,216,171,142,3,160,7,11,102,111,110,116,95,102,97,109,105,108,121,22,34,65,68,76,97,77,68,105,115,112,108,97,121,95,114,101,103,117,108,97,114,34,132,150,216,171,142,3,161,7,9,116,101,120,116,110,103,32,116,101,134,150,216,171,142,3,170,7,11,102,111,110,116,95,102,97,109,105,108,121,4,110,117,108,108,132,150,216,171,142,3,171,7,16,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,129,150,216,171,142,3,187,7,6,132,150,216,171,142,3,193,7,92,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,161,199,130,209,189,2,213,2,1,196,150,216,171,142,3,187,7,150,216,171,142,3,188,7,1,76,161,150,216,171,142,3,158,8,1,196,150,216,171,142,3,193,7,150,216,171,142,3,194,7,1,101,161,150,216,171,142,3,160,8,1,70,204,195,206,156,1,135,7,11,102,111,110,116,95,102,97,109,105,108,121,22,34,65,98,114,105,108,70,97,116,102,97,99,101,95,114,101,103,117,108,97,114,34,193,150,216,171,142,3,163,8,204,195,206,156,1,135,7,3,198,150,216,171,142,3,166,8,204,195,206,156,1,135,7,11,102,111,110,116,95,102,97,109,105,108,121,4,110,117,108,108,161,199,130,209,189,2,25,1,161,199,130,209,189,2,26,1,161,199,130,209,189,2,27,1,198,150,216,171,142,3,230,6,150,216,171,142,3,231,6,11,102,111,110,116,95,102,97,109,105,108,121,22,34,65,68,76,97,77,68,105,115,112,108,97,121,95,114,101,103,117,108,97,114,34,196,150,216,171,142,3,171,8,150,216,171,142,3,231,6,14,103,32,116,101,120,116,110,103,32,116,101,120,116,110,198,150,216,171,142,3,185,8,150,216,171,142,3,231,6,11,102,111,110,116,95,102,97,109,105,108,121,4,110,117,108,108,168,150,216,171,142,3,162,8,1,119,253,2,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,108,111,110,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,102,97,109,105,108,121,34,58,34,65,68,76,97,77,68,105,115,112,108,97,121,95,114,101,103,117,108,97,114,34,125,44,34,105,110,115,101,114,116,34,58,34,103,32,116,101,120,116,110,103,32,116,101,120,116,110,34,125,44,123,34,105,110,115,101,114,116,34,58,34,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,102,97,109,105,108,121,34,58,34,65,68,76,97,77,68,105,115,112,108,97,121,95,114,101,103,117,108,97,114,34,125,44,34,105,110,115,101,114,116,34,58,34,116,101,120,116,110,103,32,116,101,34,125,44,123,34,105,110,115,101,114,116,34,58,34,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,76,101,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,34,125,93,125,20,168,215,223,235,2,0,161,150,216,171,142,3,168,8,1,161,150,216,171,142,3,169,8,1,161,150,216,171,142,3,170,8,1,196,150,216,171,142,3,166,8,150,216,171,142,3,167,8,3,87,101,108,132,224,159,166,178,15,26,16,99,111,109,101,32,116,111,32,65,112,112,70,108,111,119,121,39,0,204,195,206,156,1,4,6,74,98,104,77,53,50,2,4,0,168,215,223,235,2,22,20,72,101,114,101,32,97,114,101,32,116,104,101,32,98,97,115,105,99,115,32,168,168,215,223,235,2,0,1,119,120,123,34,100,101,108,116,97,34,58,91,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,102,97,109,105,108,121,34,58,34,65,98,114,105,108,70,97,116,102,97,99,101,95,114,101,103,117,108,97,114,34,125,44,34,105,110,115,101,114,116,34,58,34,87,101,108,34,125,44,123,34,105,110,115,101,114,116,34,58,34,99,111,109,101,32,116,111,32,65,112,112,70,108,111,119,121,34,125,93,44,34,108,101,118,101,108,34,58,49,125,168,168,215,223,235,2,1,1,119,10,119,88,107,79,72,81,49,50,99,111,168,168,215,223,235,2,2,1,119,4,116,101,120,116,167,204,195,206,156,1,213,1,1,40,0,168,215,223,235,2,46,2,105,100,1,119,10,97,115,74,118,54,70,114,65,82,97,40,0,168,215,223,235,2,46,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,168,215,223,235,2,46,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,168,215,223,235,2,46,8,99,104,105,108,100,114,101,110,1,119,6,51,107,67,87,106,70,40,0,168,215,223,235,2,46,4,100,97,116,97,1,119,55,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,72,101,114,101,32,97,114,101,32,116,104,101,32,98,97,115,105,99,115,32,34,125,93,44,34,108,101,118,101,108,34,58,50,125,40,0,168,215,223,235,2,46,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,168,215,223,235,2,46,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,51,107,67,87,106,70,0,200,204,195,206,156,1,232,1,199,130,209,189,2,181,3,1,119,10,97,115,74,118,54,70,114,65,82,97,1,192,246,139,213,2,0,161,239,239,208,251,10,16,35,2,190,183,139,210,2,0,161,241,147,239,232,6,3,109,168,190,183,139,210,2,108,1,122,0,0,0,0,102,35,115,218,143,6,199,130,209,189,2,0,39,0,204,195,206,156,1,4,6,88,116,53,112,118,55,2,4,0,199,130,209,189,2,0,9,229,144,140,228,184,128,228,184,170,129,199,130,209,189,2,3,5,161,178,187,245,161,14,10,6,132,199,130,209,189,2,8,1,110,161,199,130,209,189,2,14,1,132,199,130,209,189,2,15,1,105,168,199,130,209,189,2,16,1,119,36,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,144,140,228,184,128,228,184,170,110,105,34,125,93,125,161,224,159,166,178,15,27,1,161,224,159,166,178,15,28,1,161,224,159,166,178,15,29,1,161,199,130,209,189,2,19,1,161,199,130,209,189,2,20,1,161,199,130,209,189,2,21,1,161,199,130,209,189,2,22,1,161,199,130,209,189,2,23,1,161,199,130,209,189,2,24,1,0,3,39,0,204,195,206,156,1,4,6,82,74,97,73,54,107,2,4,0,199,130,209,189,2,31,1,116,161,228,242,134,215,15,11,1,132,199,130,209,189,2,32,1,111,161,199,130,209,189,2,33,1,132,199,130,209,189,2,34,1,100,161,199,130,209,189,2,35,1,132,199,130,209,189,2,36,1,111,161,199,130,209,189,2,37,1,132,199,130,209,189,2,38,1,32,161,199,130,209,189,2,39,1,132,199,130,209,189,2,40,1,108,161,199,130,209,189,2,41,1,132,199,130,209,189,2,42,1,105,161,199,130,209,189,2,43,1,132,199,130,209,189,2,44,1,115,161,199,130,209,189,2,45,1,132,199,130,209,189,2,46,1,116,161,199,130,209,189,2,47,1,39,0,204,195,206,156,1,4,6,55,80,118,106,121,81,2,39,0,204,195,206,156,1,1,6,71,118,88,50,102,110,1,40,0,199,130,209,189,2,51,2,105,100,1,119,6,71,118,88,50,102,110,40,0,199,130,209,189,2,51,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,199,130,209,189,2,51,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,51,8,99,104,105,108,100,114,101,110,1,119,6,111,112,68,102,54,95,33,0,199,130,209,189,2,51,4,100,97,116,97,1,40,0,199,130,209,189,2,51,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,51,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,111,112,68,102,54,95,0,200,198,223,206,159,1,135,1,198,223,206,159,1,116,1,119,6,71,118,88,50,102,110,161,199,130,209,189,2,49,1,4,0,199,130,209,189,2,50,1,99,161,199,130,209,189,2,56,1,132,199,130,209,189,2,62,1,104,161,199,130,209,189,2,63,1,132,199,130,209,189,2,64,1,101,161,199,130,209,189,2,65,1,132,199,130,209,189,2,66,1,99,161,199,130,209,189,2,67,1,132,199,130,209,189,2,68,1,107,161,199,130,209,189,2,69,1,132,199,130,209,189,2,70,1,101,161,199,130,209,189,2,71,1,132,199,130,209,189,2,72,1,100,161,199,130,209,189,2,73,1,132,199,130,209,189,2,74,1,32,161,199,130,209,189,2,75,1,132,199,130,209,189,2,76,1,116,161,199,130,209,189,2,77,1,132,199,130,209,189,2,78,1,111,161,199,130,209,189,2,79,1,132,199,130,209,189,2,80,1,100,161,199,130,209,189,2,81,1,132,199,130,209,189,2,82,1,111,161,199,130,209,189,2,83,1,132,199,130,209,189,2,84,1,32,161,199,130,209,189,2,85,1,132,199,130,209,189,2,86,1,108,161,199,130,209,189,2,87,1,132,199,130,209,189,2,88,1,105,161,199,130,209,189,2,89,1,132,199,130,209,189,2,90,1,115,161,199,130,209,189,2,91,1,132,199,130,209,189,2,92,1,116,161,199,130,209,189,2,93,1,39,0,204,195,206,156,1,4,6,117,115,117,45,118,111,2,39,0,204,195,206,156,1,1,6,86,90,80,95,77,113,1,40,0,199,130,209,189,2,97,2,105,100,1,119,6,86,90,80,95,77,113,40,0,199,130,209,189,2,97,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,199,130,209,189,2,97,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,97,8,99,104,105,108,100,114,101,110,1,119,6,54,55,76,56,102,50,33,0,199,130,209,189,2,97,4,100,97,116,97,1,40,0,199,130,209,189,2,97,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,97,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,54,55,76,56,102,50,0,200,199,130,209,189,2,60,198,223,206,159,1,116,1,119,6,86,90,80,95,77,113,161,199,130,209,189,2,95,1,4,0,199,130,209,189,2,96,1,108,161,199,130,209,189,2,102,1,132,199,130,209,189,2,108,1,111,161,199,130,209,189,2,109,1,132,199,130,209,189,2,110,1,110,161,199,130,209,189,2,111,1,132,199,130,209,189,2,112,1,103,161,199,130,209,189,2,113,1,132,199,130,209,189,2,114,1,32,161,199,130,209,189,2,115,1,132,199,130,209,189,2,116,1,116,161,199,130,209,189,2,117,1,132,199,130,209,189,2,118,1,101,161,199,130,209,189,2,119,1,132,199,130,209,189,2,120,1,120,161,199,130,209,189,2,121,1,132,199,130,209,189,2,122,1,116,161,199,130,209,189,2,123,1,129,199,130,209,189,2,124,1,161,199,130,209,189,2,125,2,132,199,130,209,189,2,126,7,110,103,32,116,101,120,116,161,199,130,209,189,2,128,1,1,132,199,130,209,189,2,135,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,136,1,1,132,199,130,209,189,2,143,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,144,1,1,132,199,130,209,189,2,151,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,152,1,1,132,199,130,209,189,2,159,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,160,1,1,132,199,130,209,189,2,167,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,168,1,1,132,199,130,209,189,2,175,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,176,1,1,132,199,130,209,189,2,183,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,184,1,1,132,199,130,209,189,2,191,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,192,1,1,132,199,130,209,189,2,199,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,200,1,1,132,199,130,209,189,2,207,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,208,1,1,132,199,130,209,189,2,215,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,216,1,1,132,199,130,209,189,2,223,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,224,1,1,132,199,130,209,189,2,231,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,232,1,1,132,199,130,209,189,2,239,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,240,1,1,132,199,130,209,189,2,247,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,248,1,1,132,199,130,209,189,2,255,1,7,110,103,32,116,101,120,116,161,199,130,209,189,2,128,2,1,132,199,130,209,189,2,135,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,136,2,1,132,199,130,209,189,2,143,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,144,2,1,132,199,130,209,189,2,151,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,152,2,1,132,199,130,209,189,2,159,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,160,2,1,132,199,130,209,189,2,167,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,168,2,1,132,199,130,209,189,2,175,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,176,2,1,132,199,130,209,189,2,183,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,184,2,1,132,199,130,209,189,2,191,2,7,110,103,32,116,101,120,116,161,199,130,209,189,2,192,2,1,161,199,130,209,189,2,107,1,39,0,204,195,206,156,1,4,6,55,74,97,87,111,56,2,39,0,204,195,206,156,1,1,6,54,87,56,99,101,88,1,40,0,199,130,209,189,2,203,2,2,105,100,1,119,6,54,87,56,99,101,88,40,0,199,130,209,189,2,203,2,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,199,130,209,189,2,203,2,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,203,2,8,99,104,105,108,100,114,101,110,1,119,6,105,55,111,99,51,56,33,0,199,130,209,189,2,203,2,4,100,97,116,97,1,40,0,199,130,209,189,2,203,2,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,203,2,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,105,55,111,99,51,56,0,200,199,130,209,189,2,106,198,223,206,159,1,116,1,119,6,54,87,56,99,101,88,161,199,130,209,189,2,200,2,1,132,199,130,209,189,2,94,1,32,161,199,130,209,189,2,201,2,1,129,199,130,209,189,2,214,2,1,161,199,130,209,189,2,215,2,1,129,199,130,209,189,2,216,2,1,161,199,130,209,189,2,217,2,1,129,199,130,209,189,2,218,2,1,161,199,130,209,189,2,219,2,1,129,199,130,209,189,2,220,2,1,161,199,130,209,189,2,221,2,5,129,199,130,209,189,2,222,2,1,161,199,130,209,189,2,227,2,1,129,199,130,209,189,2,228,2,1,161,199,130,209,189,2,229,2,1,129,199,130,209,189,2,230,2,1,161,199,130,209,189,2,231,2,1,129,199,130,209,189,2,232,2,1,161,199,130,209,189,2,233,2,1,129,199,130,209,189,2,234,2,1,161,199,130,209,189,2,235,2,1,129,199,130,209,189,2,236,2,1,161,199,130,209,189,2,237,2,1,129,199,130,209,189,2,238,2,1,161,199,130,209,189,2,239,2,1,134,199,130,209,189,2,240,2,7,102,111,114,109,117,108,97,9,34,102,111,114,109,117,108,97,34,132,199,130,209,189,2,242,2,1,36,134,199,130,209,189,2,243,2,7,102,111,114,109,117,108,97,4,110,117,108,108,168,199,130,209,189,2,241,2,1,119,108,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,101,99,107,101,100,32,116,111,100,111,32,108,105,115,116,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,114,109,117,108,97,34,58,34,102,111,114,109,117,108,97,34,125,44,34,105,110,115,101,114,116,34,58,34,36,34,125,93,44,34,99,104,101,99,107,101,100,34,58,116,114,117,101,125,1,0,199,130,209,189,2,202,2,1,161,199,130,209,189,2,208,2,1,129,199,130,209,189,2,246,2,1,161,199,130,209,189,2,247,2,1,129,199,130,209,189,2,248,2,1,161,199,130,209,189,2,249,2,1,129,199,130,209,189,2,250,2,1,161,199,130,209,189,2,251,2,1,129,199,130,209,189,2,252,2,1,161,199,130,209,189,2,253,2,1,129,199,130,209,189,2,254,2,1,161,199,130,209,189,2,255,2,1,129,199,130,209,189,2,128,3,1,161,199,130,209,189,2,129,3,8,132,199,130,209,189,2,130,3,1,119,161,199,130,209,189,2,138,3,1,132,199,130,209,189,2,139,3,1,105,161,199,130,209,189,2,140,3,1,132,199,130,209,189,2,141,3,1,116,161,199,130,209,189,2,142,3,1,132,199,130,209,189,2,143,3,1,104,161,199,130,209,189,2,144,3,1,39,0,204,195,206,156,1,4,6,55,99,74,88,114,112,2,39,0,204,195,206,156,1,1,6,86,111,54,70,109,81,1,40,0,199,130,209,189,2,148,3,2,105,100,1,119,6,86,111,54,70,109,81,40,0,199,130,209,189,2,148,3,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,148,3,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,199,130,209,189,2,148,3,8,99,104,105,108,100,114,101,110,1,119,6,106,82,78,118,55,111,33,0,199,130,209,189,2,148,3,4,100,97,116,97,1,40,0,199,130,209,189,2,148,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,148,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,106,82,78,118,55,111,0,136,171,236,222,251,5,206,3,1,119,6,86,111,54,70,109,81,4,0,199,130,209,189,2,147,3,4,240,159,152,131,168,199,130,209,189,2,153,3,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,240,159,152,131,34,125,93,125,39,0,204,195,206,156,1,4,6,103,89,121,119,78,121,2,33,0,204,195,206,156,1,1,6,84,67,99,110,98,71,1,0,7,33,0,204,195,206,156,1,3,6,82,117,68,55,67,100,1,193,204,195,206,156,1,232,1,198,223,206,159,1,149,1,1,39,0,204,195,206,156,1,1,6,101,77,66,121,99,80,1,40,0,199,130,209,189,2,172,3,2,105,100,1,119,6,101,77,66,121,99,80,40,0,199,130,209,189,2,172,3,2,116,121,1,119,7,111,117,116,108,105,110,101,40,0,199,130,209,189,2,172,3,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,172,3,8,99,104,105,108,100,114,101,110,1,119,6,112,72,116,98,67,52,33,0,199,130,209,189,2,172,3,4,100,97,116,97,1,40,0,199,130,209,189,2,172,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,172,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,112,72,116,98,67,52,0,200,204,195,206,156,1,232,1,199,130,209,189,2,171,3,1,119,6,101,77,66,121,99,80,39,0,204,195,206,156,1,4,6,95,97,88,90,88,80,2,33,0,204,195,206,156,1,1,6,81,89,119,70,83,48,1,0,7,33,0,204,195,206,156,1,3,6,88,110,80,104,117,89,1,193,199,130,209,189,2,171,3,198,223,206,159,1,149,1,1,39,0,204,195,206,156,1,4,6,110,90,88,77,89,67,2,39,0,204,195,206,156,1,4,6,85,99,120,53,52,69,2,39,0,204,195,206,156,1,4,6,69,82,71,102,107,88,2,39,0,204,195,206,156,1,4,6,71,108,50,57,116,102,2,39,0,204,195,206,156,1,1,6,120,49,100,100,111,87,1,40,0,199,130,209,189,2,197,3,2,105,100,1,119,6,120,49,100,100,111,87,40,0,199,130,209,189,2,197,3,2,116,121,1,119,5,116,97,98,108,101,40,0,199,130,209,189,2,197,3,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,197,3,8,99,104,105,108,100,114,101,110,1,119,6,100,49,110,86,107,119,33,0,199,130,209,189,2,197,3,4,100,97,116,97,1,40,0,199,130,209,189,2,197,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,197,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,100,49,110,86,107,119,0,200,199,130,209,189,2,171,3,199,130,209,189,2,192,3,1,119,6,120,49,100,100,111,87,39,0,204,195,206,156,1,1,6,121,57,72,73,118,95,1,40,0,199,130,209,189,2,207,3,2,105,100,1,119,6,121,57,72,73,118,95,40,0,199,130,209,189,2,207,3,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,199,130,209,189,2,207,3,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,199,130,209,189,2,207,3,8,99,104,105,108,100,114,101,110,1,119,6,78,104,69,49,119,116,33,0,199,130,209,189,2,207,3,4,100,97,116,97,1,40,0,199,130,209,189,2,207,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,207,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,78,104,69,49,119,116,0,8,0,199,130,209,189,2,205,3,1,119,6,121,57,72,73,118,95,39,0,204,195,206,156,1,1,6,48,83,82,103,66,118,1,40,0,199,130,209,189,2,217,3,2,105,100,1,119,6,48,83,82,103,66,118,40,0,199,130,209,189,2,217,3,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,217,3,6,112,97,114,101,110,116,1,119,6,121,57,72,73,118,95,40,0,199,130,209,189,2,217,3,8,99,104,105,108,100,114,101,110,1,119,6,107,108,100,67,117,111,33,0,199,130,209,189,2,217,3,4,100,97,116,97,1,40,0,199,130,209,189,2,217,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,217,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,107,108,100,67,117,111,0,8,0,199,130,209,189,2,215,3,1,119,6,48,83,82,103,66,118,39,0,204,195,206,156,1,1,6,95,90,90,78,53,99,1,40,0,199,130,209,189,2,227,3,2,105,100,1,119,6,95,90,90,78,53,99,40,0,199,130,209,189,2,227,3,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,199,130,209,189,2,227,3,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,199,130,209,189,2,227,3,8,99,104,105,108,100,114,101,110,1,119,6,103,89,69,98,121,107,33,0,199,130,209,189,2,227,3,4,100,97,116,97,1,40,0,199,130,209,189,2,227,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,227,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,103,89,69,98,121,107,0,136,199,130,209,189,2,216,3,1,119,6,95,90,90,78,53,99,39,0,204,195,206,156,1,1,6,77,106,74,57,74,76,1,40,0,199,130,209,189,2,237,3,2,105,100,1,119,6,77,106,74,57,74,76,40,0,199,130,209,189,2,237,3,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,237,3,6,112,97,114,101,110,116,1,119,6,95,90,90,78,53,99,40,0,199,130,209,189,2,237,3,8,99,104,105,108,100,114,101,110,1,119,6,95,102,81,84,95,110,33,0,199,130,209,189,2,237,3,4,100,97,116,97,1,40,0,199,130,209,189,2,237,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,237,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,95,102,81,84,95,110,0,8,0,199,130,209,189,2,235,3,1,119,6,77,106,74,57,74,76,39,0,204,195,206,156,1,1,6,78,77,45,104,67,70,1,40,0,199,130,209,189,2,247,3,2,105,100,1,119,6,78,77,45,104,67,70,40,0,199,130,209,189,2,247,3,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,199,130,209,189,2,247,3,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,199,130,209,189,2,247,3,8,99,104,105,108,100,114,101,110,1,119,6,117,118,68,83,80,101,33,0,199,130,209,189,2,247,3,4,100,97,116,97,1,40,0,199,130,209,189,2,247,3,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,247,3,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,117,118,68,83,80,101,0,136,199,130,209,189,2,236,3,1,119,6,78,77,45,104,67,70,39,0,204,195,206,156,1,1,6,69,70,66,45,52,82,1,40,0,199,130,209,189,2,129,4,2,105,100,1,119,6,69,70,66,45,52,82,40,0,199,130,209,189,2,129,4,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,129,4,6,112,97,114,101,110,116,1,119,6,78,77,45,104,67,70,40,0,199,130,209,189,2,129,4,8,99,104,105,108,100,114,101,110,1,119,6,81,81,77,50,48,66,33,0,199,130,209,189,2,129,4,4,100,97,116,97,1,40,0,199,130,209,189,2,129,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,129,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,81,81,77,50,48,66,0,8,0,199,130,209,189,2,255,3,1,119,6,69,70,66,45,52,82,39,0,204,195,206,156,1,1,6,98,100,95,105,68,101,1,40,0,199,130,209,189,2,139,4,2,105,100,1,119,6,98,100,95,105,68,101,40,0,199,130,209,189,2,139,4,2,116,121,1,119,10,116,97,98,108,101,47,99,101,108,108,40,0,199,130,209,189,2,139,4,6,112,97,114,101,110,116,1,119,6,120,49,100,100,111,87,40,0,199,130,209,189,2,139,4,8,99,104,105,108,100,114,101,110,1,119,6,105,80,89,69,52,56,33,0,199,130,209,189,2,139,4,4,100,97,116,97,1,40,0,199,130,209,189,2,139,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,139,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,105,80,89,69,52,56,0,136,199,130,209,189,2,128,4,1,119,6,98,100,95,105,68,101,39,0,204,195,206,156,1,1,6,55,51,88,69,103,80,1,40,0,199,130,209,189,2,149,4,2,105,100,1,119,6,55,51,88,69,103,80,40,0,199,130,209,189,2,149,4,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,149,4,6,112,97,114,101,110,116,1,119,6,98,100,95,105,68,101,40,0,199,130,209,189,2,149,4,8,99,104,105,108,100,114,101,110,1,119,6,115,45,80,102,105,89,33,0,199,130,209,189,2,149,4,4,100,97,116,97,1,40,0,199,130,209,189,2,149,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,149,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,115,45,80,102,105,89,0,8,0,199,130,209,189,2,147,4,1,119,6,55,51,88,69,103,80,161,199,130,209,189,2,202,3,1,4,0,199,130,209,189,2,193,3,1,56,161,199,130,209,189,2,222,3,1,132,199,130,209,189,2,160,4,1,56,161,199,130,209,189,2,161,4,1,132,199,130,209,189,2,162,4,1,56,161,199,130,209,189,2,163,4,1,132,199,130,209,189,2,164,4,1,56,161,199,130,209,189,2,165,4,1,132,199,130,209,189,2,166,4,1,56,161,199,130,209,189,2,167,4,1,4,0,199,130,209,189,2,196,3,1,57,161,199,130,209,189,2,154,4,1,132,199,130,209,189,2,170,4,1,57,161,199,130,209,189,2,171,4,1,132,199,130,209,189,2,172,4,1,57,161,199,130,209,189,2,173,4,1,132,199,130,209,189,2,174,4,1,57,161,199,130,209,189,2,175,4,1,0,4,39,0,204,195,206,156,1,4,6,56,85,53,118,100,78,2,39,0,204,195,206,156,1,1,6,78,99,104,45,81,78,1,40,0,199,130,209,189,2,183,4,2,105,100,1,119,6,78,99,104,45,81,78,40,0,199,130,209,189,2,183,4,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,199,130,209,189,2,183,4,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,183,4,8,99,104,105,108,100,114,101,110,1,119,6,122,97,90,84,55,68,33,0,199,130,209,189,2,183,4,4,100,97,116,97,1,40,0,199,130,209,189,2,183,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,183,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,122,97,90,84,55,68,0,200,204,195,206,156,1,246,1,204,195,206,156,1,247,1,1,119,6,78,99,104,45,81,78,1,0,199,130,209,189,2,182,4,1,161,199,130,209,189,2,188,4,1,129,199,130,209,189,2,193,4,1,161,199,130,209,189,2,194,4,1,129,199,130,209,189,2,195,4,1,161,199,130,209,189,2,196,4,1,39,0,204,195,206,156,1,4,6,75,102,57,98,106,87,2,33,0,204,195,206,156,1,1,6,119,73,53,75,113,116,1,0,7,33,0,204,195,206,156,1,3,6,115,76,56,78,88,117,1,193,204,195,206,156,1,247,1,204,195,206,156,1,248,1,1,39,0,204,195,206,156,1,4,6,48,72,111,66,111,70,2,39,0,204,195,206,156,1,1,6,84,67,90,121,70,52,1,40,0,199,130,209,189,2,211,4,2,105,100,1,119,6,84,67,90,121,70,52,40,0,199,130,209,189,2,211,4,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,199,130,209,189,2,211,4,6,112,97,114,101,110,116,1,119,6,78,99,104,45,81,78,40,0,199,130,209,189,2,211,4,8,99,104,105,108,100,114,101,110,1,119,6,108,99,89,77,103,95,33,0,199,130,209,189,2,211,4,4,100,97,116,97,1,40,0,199,130,209,189,2,211,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,211,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,108,99,89,77,103,95,0,8,0,199,130,209,189,2,191,4,1,119,6,84,67,90,121,70,52,1,0,199,130,209,189,2,210,4,1,161,199,130,209,189,2,216,4,1,129,199,130,209,189,2,221,4,1,161,199,130,209,189,2,222,4,1,129,199,130,209,189,2,223,4,1,161,199,130,209,189,2,224,4,1,39,0,204,195,206,156,1,4,6,108,73,54,101,68,85,2,33,0,204,195,206,156,1,1,6,67,118,56,72,55,83,1,0,7,33,0,204,195,206,156,1,3,6,107,119,71,100,66,65,1,129,199,130,209,189,2,220,4,1,39,0,204,195,206,156,1,4,6,57,83,80,71,121,88,2,39,0,204,195,206,156,1,1,6,52,119,120,102,90,72,1,40,0,199,130,209,189,2,239,4,2,105,100,1,119,6,52,119,120,102,90,72,40,0,199,130,209,189,2,239,4,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,199,130,209,189,2,239,4,6,112,97,114,101,110,116,1,119,6,84,67,90,121,70,52,40,0,199,130,209,189,2,239,4,8,99,104,105,108,100,114,101,110,1,119,6,118,103,105,70,69,106,33,0,199,130,209,189,2,239,4,4,100,97,116,97,1,40,0,199,130,209,189,2,239,4,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,239,4,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,118,103,105,70,69,106,0,8,0,199,130,209,189,2,219,4,1,119,6,52,119,120,102,90,72,1,0,199,130,209,189,2,238,4,1,161,199,130,209,189,2,244,4,1,129,199,130,209,189,2,249,4,1,161,199,130,209,189,2,250,4,1,129,199,130,209,189,2,251,4,1,161,199,130,209,189,2,252,4,1,39,0,204,195,206,156,1,4,6,106,81,55,52,49,100,2,39,0,204,195,206,156,1,1,6,109,102,89,53,57,121,1,40,0,199,130,209,189,2,128,5,2,105,100,1,119,6,109,102,89,53,57,121,40,0,199,130,209,189,2,128,5,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,199,130,209,189,2,128,5,6,112,97,114,101,110,116,1,119,6,84,67,90,121,70,52,40,0,199,130,209,189,2,128,5,8,99,104,105,108,100,114,101,110,1,119,6,71,116,121,76,66,108,33,0,199,130,209,189,2,128,5,4,100,97,116,97,1,40,0,199,130,209,189,2,128,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,128,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,71,116,121,76,66,108,0,136,199,130,209,189,2,248,4,1,119,6,109,102,89,53,57,121,1,0,199,130,209,189,2,255,4,1,161,199,130,209,189,2,133,5,1,129,199,130,209,189,2,138,5,1,161,199,130,209,189,2,139,5,1,129,199,130,209,189,2,140,5,1,161,199,130,209,189,2,141,5,1,39,0,204,195,206,156,1,4,6,99,82,52,54,74,83,2,33,0,204,195,206,156,1,1,6,95,95,82,90,106,107,1,0,7,33,0,204,195,206,156,1,3,6,117,113,87,99,122,50,1,129,199,130,209,189,2,137,5,1,4,0,199,130,209,189,2,144,5,1,49,0,1,132,199,130,209,189,2,155,5,1,50,0,1,132,199,130,209,189,2,157,5,1,51,0,1,39,0,204,195,206,156,1,4,6,84,108,76,116,78,119,2,1,0,199,130,209,189,2,161,5,3,39,0,204,195,206,156,1,1,6,87,57,68,108,99,56,1,40,0,199,130,209,189,2,165,5,2,105,100,1,119,6,87,57,68,108,99,56,40,0,199,130,209,189,2,165,5,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,199,130,209,189,2,165,5,6,112,97,114,101,110,116,1,119,6,78,99,104,45,81,78,40,0,199,130,209,189,2,165,5,8,99,104,105,108,100,114,101,110,1,119,6,71,113,89,119,74,81,33,0,199,130,209,189,2,165,5,4,100,97,116,97,1,40,0,199,130,209,189,2,165,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,165,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,71,113,89,119,74,81,0,136,199,130,209,189,2,237,4,1,119,6,87,57,68,108,99,56,129,199,130,209,189,2,164,5,1,161,199,130,209,189,2,170,5,1,129,199,130,209,189,2,175,5,1,161,199,130,209,189,2,176,5,1,129,199,130,209,189,2,177,5,1,161,199,130,209,189,2,178,5,1,39,0,204,195,206,156,1,4,6,105,45,118,52,52,66,2,33,0,204,195,206,156,1,1,6,116,72,104,110,105,69,1,0,7,33,0,204,195,206,156,1,3,6,79,69,107,76,69,106,1,129,199,130,209,189,2,174,5,1,1,0,199,130,209,189,2,181,5,1,0,1,129,199,130,209,189,2,192,5,1,0,3,132,199,130,209,189,2,194,5,1,62,0,1,39,0,204,195,206,156,1,4,6,76,115,116,55,78,103,2,39,0,204,195,206,156,1,1,6,113,90,76,56,88,88,1,40,0,199,130,209,189,2,201,5,2,105,100,1,119,6,113,90,76,56,88,88,40,0,199,130,209,189,2,201,5,2,116,121,1,119,11,116,111,103,103,108,101,95,108,105,115,116,40,0,199,130,209,189,2,201,5,6,112,97,114,101,110,116,1,119,6,78,99,104,45,81,78,40,0,199,130,209,189,2,201,5,8,99,104,105,108,100,114,101,110,1,119,6,49,98,68,104,69,101,33,0,199,130,209,189,2,201,5,4,100,97,116,97,1,40,0,199,130,209,189,2,201,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,201,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,49,98,68,104,69,101,0,200,199,130,209,189,2,174,5,199,130,209,189,2,191,5,1,119,6,113,90,76,56,88,88,1,0,199,130,209,189,2,200,5,1,161,199,130,209,189,2,206,5,1,129,199,130,209,189,2,211,5,1,161,199,130,209,189,2,212,5,1,129,199,130,209,189,2,213,5,1,161,199,130,209,189,2,214,5,1,39,0,204,195,206,156,1,4,6,88,103,107,99,56,110,2,39,0,204,195,206,156,1,1,6,105,66,98,109,87,48,1,40,0,199,130,209,189,2,218,5,2,105,100,1,119,6,105,66,98,109,87,48,40,0,199,130,209,189,2,218,5,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,218,5,6,112,97,114,101,110,116,1,119,6,113,90,76,56,88,88,40,0,199,130,209,189,2,218,5,8,99,104,105,108,100,114,101,110,1,119,6,72,95,104,114,75,71,33,0,199,130,209,189,2,218,5,4,100,97,116,97,1,40,0,199,130,209,189,2,218,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,218,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,72,95,104,114,75,71,0,8,0,199,130,209,189,2,209,5,1,119,6,105,66,98,109,87,48,161,199,130,209,189,2,216,5,1,1,0,199,130,209,189,2,217,5,1,161,199,130,209,189,2,223,5,1,129,199,130,209,189,2,229,5,1,161,199,130,209,189,2,230,5,1,129,199,130,209,189,2,231,5,1,161,199,130,209,189,2,232,5,1,39,0,204,195,206,156,1,4,6,52,90,104,112,86,73,2,33,0,204,195,206,156,1,1,6,78,79,116,108,71,74,1,0,7,33,0,204,195,206,156,1,3,6,52,107,104,115,81,48,1,129,199,130,209,189,2,227,5,1,39,0,204,195,206,156,1,4,6,74,98,106,103,98,105,2,39,0,204,195,206,156,1,1,6,55,71,119,105,74,83,1,40,0,199,130,209,189,2,247,5,2,105,100,1,119,6,55,71,119,105,74,83,40,0,199,130,209,189,2,247,5,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,247,5,6,112,97,114,101,110,116,1,119,6,105,66,98,109,87,48,40,0,199,130,209,189,2,247,5,8,99,104,105,108,100,114,101,110,1,119,6,99,53,87,50,53,102,33,0,199,130,209,189,2,247,5,4,100,97,116,97,1,40,0,199,130,209,189,2,247,5,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,247,5,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,99,53,87,50,53,102,0,8,0,199,130,209,189,2,226,5,1,119,6,55,71,119,105,74,83,1,0,199,130,209,189,2,246,5,1,161,199,130,209,189,2,252,5,1,129,199,130,209,189,2,129,6,1,161,199,130,209,189,2,130,6,1,129,199,130,209,189,2,131,6,1,161,199,130,209,189,2,132,6,1,39,0,204,195,206,156,1,4,6,118,87,56,68,45,102,2,33,0,204,195,206,156,1,1,6,99,88,73,114,105,45,1,0,7,33,0,204,195,206,156,1,3,6,122,70,104,98,74,88,1,129,199,130,209,189,2,128,6,1,39,0,204,195,206,156,1,4,6,86,65,80,82,86,55,2,33,0,204,195,206,156,1,1,6,99,72,102,57,114,111,1,0,7,33,0,204,195,206,156,1,3,6,70,112,56,103,98,56,1,129,199,130,209,189,2,245,5,1,4,0,199,130,209,189,2,146,6,1,49,0,1,132,199,130,209,189,2,157,6,1,50,0,1,132,199,130,209,189,2,159,6,1,51,0,1,39,0,204,195,206,156,1,4,6,95,70,68,79,103,89,2,4,0,199,130,209,189,2,163,6,3,49,50,51,39,0,204,195,206,156,1,1,6,84,69,81,71,120,89,1,40,0,199,130,209,189,2,167,6,2,105,100,1,119,6,84,69,81,71,120,89,40,0,199,130,209,189,2,167,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,167,6,6,112,97,114,101,110,116,1,119,6,78,99,104,45,81,78,40,0,199,130,209,189,2,167,6,8,99,104,105,108,100,114,101,110,1,119,6,72,120,102,70,78,49,40,0,199,130,209,189,2,167,6,4,100,97,116,97,1,119,28,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,51,34,125,93,125,40,0,199,130,209,189,2,167,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,167,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,72,120,102,70,78,49,0,136,199,130,209,189,2,191,5,1,119,6,84,69,81,71,120,89,68,199,130,209,189,2,193,4,1,98,161,199,130,209,189,2,198,4,1,132,199,130,209,189,2,197,4,1,117,161,199,130,209,189,2,178,6,1,129,199,130,209,189,2,179,6,1,132,199,130,209,189,2,181,6,1,108,161,199,130,209,189,2,180,6,2,132,199,130,209,189,2,182,6,1,108,161,199,130,209,189,2,184,6,1,132,199,130,209,189,2,185,6,1,101,161,199,130,209,189,2,186,6,1,132,199,130,209,189,2,187,6,1,116,161,199,130,209,189,2,188,6,1,132,199,130,209,189,2,189,6,1,101,161,199,130,209,189,2,190,6,1,132,199,130,209,189,2,191,6,1,100,161,199,130,209,189,2,192,6,1,132,199,130,209,189,2,193,6,1,32,161,199,130,209,189,2,194,6,1,132,199,130,209,189,2,195,6,1,108,161,199,130,209,189,2,196,6,1,132,199,130,209,189,2,197,6,1,105,161,199,130,209,189,2,198,6,1,132,199,130,209,189,2,199,6,1,115,161,199,130,209,189,2,200,6,1,132,199,130,209,189,2,201,6,1,116,168,199,130,209,189,2,202,6,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,98,117,108,108,101,116,101,100,32,108,105,115,116,34,125,93,125,68,199,130,209,189,2,221,4,1,99,161,199,130,209,189,2,226,4,1,132,199,130,209,189,2,225,4,1,104,161,199,130,209,189,2,206,6,1,132,199,130,209,189,2,207,6,1,105,161,199,130,209,189,2,208,6,1,132,199,130,209,189,2,209,6,1,108,161,199,130,209,189,2,210,6,1,132,199,130,209,189,2,211,6,1,100,161,199,130,209,189,2,212,6,1,129,199,130,209,189,2,213,6,1,161,199,130,209,189,2,214,6,2,132,199,130,209,189,2,215,6,1,45,161,199,130,209,189,2,217,6,1,132,199,130,209,189,2,218,6,1,49,168,199,130,209,189,2,219,6,1,119,32,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,34,125,93,125,68,199,130,209,189,2,249,4,1,99,161,199,130,209,189,2,254,4,1,132,199,130,209,189,2,253,4,1,104,161,199,130,209,189,2,223,6,1,132,199,130,209,189,2,224,6,1,105,161,199,130,209,189,2,225,6,1,132,199,130,209,189,2,226,6,1,108,161,199,130,209,189,2,227,6,1,132,199,130,209,189,2,228,6,1,100,161,199,130,209,189,2,229,6,1,132,199,130,209,189,2,230,6,1,45,161,199,130,209,189,2,231,6,1,132,199,130,209,189,2,232,6,1,49,161,199,130,209,189,2,233,6,1,132,199,130,209,189,2,234,6,1,45,161,199,130,209,189,2,235,6,1,132,199,130,209,189,2,236,6,1,49,168,199,130,209,189,2,237,6,1,119,34,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,45,49,34,125,93,125,68,199,130,209,189,2,138,5,1,99,161,199,130,209,189,2,143,5,1,132,199,130,209,189,2,142,5,1,104,161,199,130,209,189,2,241,6,1,132,199,130,209,189,2,242,6,1,105,161,199,130,209,189,2,243,6,1,132,199,130,209,189,2,244,6,1,108,161,199,130,209,189,2,245,6,1,132,199,130,209,189,2,246,6,1,100,161,199,130,209,189,2,247,6,1,132,199,130,209,189,2,248,6,1,45,161,199,130,209,189,2,249,6,1,132,199,130,209,189,2,250,6,1,49,161,199,130,209,189,2,251,6,1,132,199,130,209,189,2,252,6,1,45,161,199,130,209,189,2,253,6,1,132,199,130,209,189,2,254,6,1,50,168,199,130,209,189,2,255,6,1,119,34,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,45,50,34,125,93,125,68,199,130,209,189,2,162,5,1,99,161,199,130,209,189,2,180,5,1,132,199,130,209,189,2,179,5,1,104,161,199,130,209,189,2,131,7,1,132,199,130,209,189,2,132,7,1,105,161,199,130,209,189,2,133,7,1,132,199,130,209,189,2,134,7,1,108,161,199,130,209,189,2,135,7,1,132,199,130,209,189,2,136,7,1,100,161,199,130,209,189,2,137,7,1,132,199,130,209,189,2,138,7,1,45,161,199,130,209,189,2,139,7,1,132,199,130,209,189,2,140,7,1,50,168,199,130,209,189,2,141,7,1,119,32,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,50,34,125,93,125,65,199,130,209,189,2,211,5,1,161,199,130,209,189,2,228,5,1,129,199,130,209,189,2,215,5,1,161,199,130,209,189,2,145,7,1,129,199,130,209,189,2,146,7,1,161,199,130,209,189,2,147,7,1,129,199,130,209,189,2,148,7,1,161,199,130,209,189,2,149,7,1,129,199,130,209,189,2,150,7,1,161,199,130,209,189,2,151,7,1,129,199,130,209,189,2,152,7,1,161,199,130,209,189,2,153,7,1,129,199,130,209,189,2,154,7,1,161,199,130,209,189,2,155,7,8,132,199,130,209,189,2,156,7,1,116,161,199,130,209,189,2,164,7,1,132,199,130,209,189,2,165,7,1,111,161,199,130,209,189,2,166,7,1,132,199,130,209,189,2,167,7,1,103,161,199,130,209,189,2,168,7,1,132,199,130,209,189,2,169,7,1,103,161,199,130,209,189,2,170,7,1,132,199,130,209,189,2,171,7,1,108,161,199,130,209,189,2,172,7,1,132,199,130,209,189,2,173,7,1,101,161,199,130,209,189,2,174,7,1,132,199,130,209,189,2,175,7,1,32,161,199,130,209,189,2,176,7,1,132,199,130,209,189,2,177,7,1,108,161,199,130,209,189,2,178,7,1,132,199,130,209,189,2,179,7,1,105,161,199,130,209,189,2,180,7,1,132,199,130,209,189,2,181,7,1,115,161,199,130,209,189,2,182,7,1,132,199,130,209,189,2,183,7,1,116,168,199,130,209,189,2,184,7,1,119,54,123,34,99,111,108,108,97,112,115,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,116,111,103,103,108,101,32,108,105,115,116,34,125,93,125,68,199,130,209,189,2,229,5,1,99,161,199,130,209,189,2,234,5,1,132,199,130,209,189,2,233,5,1,104,161,199,130,209,189,2,188,7,1,132,199,130,209,189,2,189,7,1,105,161,199,130,209,189,2,190,7,1,132,199,130,209,189,2,191,7,1,108,161,199,130,209,189,2,192,7,1,132,199,130,209,189,2,193,7,1,100,161,199,130,209,189,2,194,7,1,132,199,130,209,189,2,195,7,1,45,161,199,130,209,189,2,196,7,1,129,199,130,209,189,2,197,7,1,161,199,130,209,189,2,198,7,2,132,199,130,209,189,2,199,7,1,49,168,199,130,209,189,2,201,7,1,119,32,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,34,125,93,125,68,199,130,209,189,2,129,6,1,99,161,199,130,209,189,2,134,6,1,132,199,130,209,189,2,133,6,1,104,161,199,130,209,189,2,205,7,1,132,199,130,209,189,2,206,7,1,105,161,199,130,209,189,2,207,7,1,132,199,130,209,189,2,208,7,1,108,161,199,130,209,189,2,209,7,1,132,199,130,209,189,2,210,7,1,100,161,199,130,209,189,2,211,7,1,132,199,130,209,189,2,212,7,1,45,161,199,130,209,189,2,213,7,1,132,199,130,209,189,2,214,7,1,49,161,199,130,209,189,2,215,7,1,129,199,130,209,189,2,216,7,1,161,199,130,209,189,2,217,7,1,129,199,130,209,189,2,218,7,1,161,199,130,209,189,2,219,7,3,129,199,130,209,189,2,220,7,1,161,199,130,209,189,2,223,7,1,129,199,130,209,189,2,224,7,1,161,199,130,209,189,2,225,7,3,132,199,130,209,189,2,226,7,1,45,161,199,130,209,189,2,229,7,1,132,199,130,209,189,2,230,7,1,49,168,199,130,209,189,2,231,7,1,119,34,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,45,49,34,125,93,125,39,0,204,195,206,156,1,4,6,55,88,55,105,70,103,2,39,0,204,195,206,156,1,1,6,101,79,68,109,108,65,1,40,0,199,130,209,189,2,235,7,2,105,100,1,119,6,101,79,68,109,108,65,40,0,199,130,209,189,2,235,7,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,199,130,209,189,2,235,7,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,199,130,209,189,2,235,7,8,99,104,105,108,100,114,101,110,1,119,6,109,112,74,69,74,90,33,0,199,130,209,189,2,235,7,4,100,97,116,97,1,40,0,199,130,209,189,2,235,7,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,199,130,209,189,2,235,7,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,109,112,74,69,74,90,0,200,204,195,206,156,1,242,1,204,195,206,156,1,243,1,1,119,6,101,79,68,109,108,65,168,204,195,206,156,1,164,1,1,119,79,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,44,32,109,97,114,107,100,111,119,110,44,32,97,110,100,32,99,111,100,101,32,98,108,111,99,107,34,125,93,44,34,108,101,118,101,108,34,58,50,125,168,204,195,206,156,1,165,1,1,119,10,97,98,100,49,105,117,71,81,109,68,168,204,195,206,156,1,166,1,1,119,4,116,101,120,116,1,0,199,130,209,189,2,234,7,1,161,199,130,209,189,2,240,7,1,168,199,130,209,189,2,249,7,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,132,199,130,209,189,2,48,1,32,161,199,130,209,189,2,61,1,129,199,130,209,189,2,251,7,1,161,199,130,209,189,2,252,7,1,134,199,130,209,189,2,253,7,7,109,101,110,116,105,111,110,51,123,34,116,121,112,101,34,58,34,100,97,116,101,34,44,34,100,97,116,101,34,58,34,50,48,50,52,45,48,52,45,49,56,84,49,52,58,50,53,58,51,50,46,52,53,55,50,55,55,34,125,132,199,130,209,189,2,255,7,1,36,134,199,130,209,189,2,128,8,7,109,101,110,116,105,111,110,4,110,117,108,108,161,199,130,209,189,2,254,7,1,132,199,130,209,189,2,129,8,1,109,161,199,130,209,189,2,130,8,1,132,199,130,209,189,2,131,8,1,101,161,199,130,209,189,2,132,8,1,132,199,130,209,189,2,133,8,1,110,161,199,130,209,189,2,134,8,1,129,199,130,209,189,2,135,8,1,132,199,130,209,189,2,137,8,1,116,161,199,130,209,189,2,136,8,2,1,236,158,128,159,2,0,161,219,200,174,197,9,24,4,1,245,181,155,135,2,0,161,151,234,142,238,11,26,23,176,1,146,216,250,133,2,0,161,243,138,171,183,10,60,1,161,243,138,171,183,10,61,1,161,243,138,171,183,10,62,1,161,243,138,171,183,10,71,1,161,243,138,171,183,10,63,1,161,243,138,171,183,10,64,1,161,243,138,171,183,10,65,1,161,146,216,250,133,2,3,1,161,243,138,171,183,10,67,1,161,243,138,171,183,10,68,1,161,243,138,171,183,10,69,1,161,146,216,250,133,2,7,1,161,243,138,171,183,10,84,1,161,243,138,171,183,10,85,1,161,243,138,171,183,10,86,1,161,243,138,171,183,10,95,3,161,243,138,171,183,10,91,1,161,243,138,171,183,10,92,1,161,243,138,171,183,10,93,1,161,243,138,171,183,10,87,1,161,243,138,171,183,10,88,1,161,243,138,171,183,10,89,1,161,243,138,171,183,10,96,1,161,243,138,171,183,10,97,1,161,243,138,171,183,10,98,1,161,243,138,171,183,10,107,1,161,243,138,171,183,10,100,1,161,243,138,171,183,10,101,1,161,243,138,171,183,10,102,1,161,146,216,250,133,2,27,1,161,243,138,171,183,10,104,1,161,243,138,171,183,10,105,1,161,243,138,171,183,10,106,1,161,146,216,250,133,2,31,1,161,243,138,171,183,10,108,1,161,243,138,171,183,10,109,1,161,243,138,171,183,10,110,1,161,243,138,171,183,10,119,1,161,243,138,171,183,10,112,1,161,243,138,171,183,10,113,1,161,243,138,171,183,10,114,1,161,146,216,250,133,2,39,1,161,243,138,171,183,10,116,1,161,243,138,171,183,10,117,1,161,243,138,171,183,10,118,1,161,146,216,250,133,2,43,1,161,243,138,171,183,10,120,1,161,243,138,171,183,10,121,1,161,243,138,171,183,10,122,1,161,243,138,171,183,10,123,1,161,243,138,171,183,10,124,1,161,243,138,171,183,10,125,1,161,243,138,171,183,10,131,1,2,161,243,138,171,183,10,127,1,161,243,138,171,183,10,128,1,1,161,243,138,171,183,10,129,1,1,161,146,216,250,133,2,55,1,161,243,138,171,183,10,132,1,1,161,243,138,171,183,10,133,1,1,161,243,138,171,183,10,134,1,1,161,243,138,171,183,10,143,1,1,161,243,138,171,183,10,136,1,1,161,243,138,171,183,10,137,1,1,161,243,138,171,183,10,138,1,1,161,146,216,250,133,2,63,1,161,243,138,171,183,10,140,1,1,161,243,138,171,183,10,141,1,1,161,243,138,171,183,10,142,1,1,161,146,216,250,133,2,67,1,161,243,138,171,183,10,144,1,1,161,243,138,171,183,10,145,1,1,161,243,138,171,183,10,146,1,1,161,243,138,171,183,10,155,1,1,161,243,138,171,183,10,148,1,1,161,243,138,171,183,10,149,1,1,161,243,138,171,183,10,150,1,1,161,146,216,250,133,2,75,1,161,243,138,171,183,10,152,1,1,161,243,138,171,183,10,153,1,1,161,243,138,171,183,10,154,1,1,161,146,216,250,133,2,79,1,161,243,138,171,183,10,156,1,1,161,243,138,171,183,10,157,1,1,161,243,138,171,183,10,158,1,1,161,243,138,171,183,10,167,1,1,161,243,138,171,183,10,160,1,1,161,243,138,171,183,10,161,1,1,161,243,138,171,183,10,162,1,1,161,146,216,250,133,2,87,1,161,243,138,171,183,10,164,1,1,161,243,138,171,183,10,165,1,1,161,243,138,171,183,10,166,1,1,161,146,216,250,133,2,91,1,161,243,138,171,183,10,168,1,1,161,243,138,171,183,10,169,1,1,161,243,138,171,183,10,170,1,1,161,243,138,171,183,10,179,1,1,161,243,138,171,183,10,176,1,1,161,243,138,171,183,10,177,1,1,161,243,138,171,183,10,178,1,1,161,146,216,250,133,2,99,1,161,243,138,171,183,10,172,1,1,161,243,138,171,183,10,173,1,1,161,243,138,171,183,10,174,1,1,161,146,216,250,133,2,103,1,161,243,138,171,183,10,180,1,1,161,243,138,171,183,10,181,1,1,161,243,138,171,183,10,182,1,1,161,243,138,171,183,10,191,1,1,161,243,138,171,183,10,188,1,1,161,243,138,171,183,10,189,1,1,161,243,138,171,183,10,190,1,1,161,146,216,250,133,2,111,1,161,243,138,171,183,10,184,1,1,161,243,138,171,183,10,185,1,1,161,243,138,171,183,10,186,1,1,161,146,216,250,133,2,115,1,161,243,138,171,183,10,192,1,1,161,243,138,171,183,10,193,1,1,161,243,138,171,183,10,194,1,1,161,243,138,171,183,10,203,1,1,161,243,138,171,183,10,196,1,1,161,243,138,171,183,10,197,1,1,161,243,138,171,183,10,198,1,1,161,146,216,250,133,2,123,1,161,243,138,171,183,10,200,1,1,161,243,138,171,183,10,201,1,1,161,243,138,171,183,10,202,1,1,161,146,216,250,133,2,127,1,161,243,138,171,183,10,204,1,1,161,243,138,171,183,10,205,1,1,161,243,138,171,183,10,206,1,1,161,243,138,171,183,10,215,1,1,161,243,138,171,183,10,209,1,1,161,243,138,171,183,10,210,1,1,161,243,138,171,183,10,211,1,1,161,146,216,250,133,2,135,1,1,161,243,138,171,183,10,212,1,1,161,243,138,171,183,10,213,1,1,161,243,138,171,183,10,214,1,1,161,146,216,250,133,2,139,1,1,161,243,138,171,183,10,216,1,1,161,243,138,171,183,10,217,1,1,161,243,138,171,183,10,218,1,1,161,243,138,171,183,10,227,1,1,161,243,138,171,183,10,220,1,1,161,243,138,171,183,10,221,1,1,161,243,138,171,183,10,222,1,1,161,146,216,250,133,2,147,1,1,161,243,138,171,183,10,224,1,1,161,243,138,171,183,10,225,1,1,161,243,138,171,183,10,226,1,1,161,146,216,250,133,2,151,1,1,161,243,138,171,183,10,228,1,1,161,243,138,171,183,10,229,1,1,161,243,138,171,183,10,230,1,1,161,243,138,171,183,10,239,1,1,161,243,138,171,183,10,232,1,1,161,243,138,171,183,10,233,1,1,161,243,138,171,183,10,234,1,1,161,146,216,250,133,2,159,1,1,161,243,138,171,183,10,236,1,1,161,243,138,171,183,10,237,1,1,161,243,138,171,183,10,238,1,1,161,146,216,250,133,2,163,1,1,161,146,216,250,133,2,156,1,1,161,146,216,250,133,2,157,1,1,161,146,216,250,133,2,158,1,1,161,146,216,250,133,2,160,1,1,161,146,216,250,133,2,161,1,1,161,146,216,250,133,2,162,1,1,161,146,216,250,133,2,167,1,1,161,146,216,250,133,2,164,1,1,161,146,216,250,133,2,165,1,1,161,146,216,250,133,2,166,1,1,161,146,216,250,133,2,174,1,2,9,172,254,181,239,1,0,39,0,204,195,206,156,1,4,6,108,45,56,109,101,45,2,4,0,172,254,181,239,1,0,4,104,106,107,100,161,198,223,206,159,1,153,1,1,132,172,254,181,239,1,4,2,39,100,161,172,254,181,239,1,5,1,132,172,254,181,239,1,7,2,39,100,161,172,254,181,239,1,8,1,132,172,254,181,239,1,10,2,39,100,161,172,254,181,239,1,11,1,10,155,213,159,176,1,0,161,131,182,180,202,12,50,1,161,131,182,180,202,12,51,1,161,131,182,180,202,12,52,1,161,155,213,159,176,1,0,1,161,155,213,159,176,1,1,1,161,155,213,159,176,1,2,1,129,131,182,180,202,12,43,1,161,155,213,159,176,1,3,1,161,155,213,159,176,1,4,1,161,155,213,159,176,1,5,1,179,1,198,223,206,159,1,0,39,0,204,195,206,156,1,4,6,57,70,53,89,108,75,2,4,0,198,223,206,159,1,0,13,103,104,104,104,229,143,145,230,140,165,229,165,189,168,171,236,222,251,5,166,2,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,103,104,104,104,229,143,145,230,140,165,229,165,189,34,125,93,125,39,0,204,195,206,156,1,4,6,89,50,51,82,99,105,2,4,0,198,223,206,159,1,9,12,229,185,178,230,180,187,229,147,136,229,147,136,168,171,236,222,251,5,240,3,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,185,178,230,180,187,229,147,136,229,147,136,34,125,93,125,0,3,39,0,204,195,206,156,1,4,6,72,90,117,111,112,102,2,33,0,204,195,206,156,1,1,6,67,102,80,66,48,85,1,0,7,33,0,204,195,206,156,1,3,6,81,117,121,48,102,66,1,193,171,236,222,251,5,196,1,171,236,222,251,5,170,2,1,1,0,198,223,206,159,1,18,3,0,2,129,198,223,206,159,1,31,1,0,4,39,0,204,195,206,156,1,4,6,48,82,103,55,103,55,2,33,0,204,195,206,156,1,1,6,72,51,76,88,97,79,1,0,7,33,0,204,195,206,156,1,3,6,75,83,56,80,116,80,1,193,171,236,222,251,5,196,1,198,223,206,159,1,28,1,39,0,204,195,206,156,1,4,6,105,90,51,118,76,100,2,33,0,204,195,206,156,1,1,6,121,102,76,72,69,119,1,0,7,33,0,204,195,206,156,1,3,6,48,80,108,53,77,98,1,193,171,236,222,251,5,196,1,198,223,206,159,1,49,1,39,0,204,195,206,156,1,4,6,72,97,76,66,45,86,2,33,0,204,195,206,156,1,1,6,98,65,77,76,51,82,1,0,7,33,0,204,195,206,156,1,3,6,81,83,99,52,51,111,1,193,171,236,222,251,5,196,1,198,223,206,159,1,60,1,39,0,204,195,206,156,1,4,6,98,86,122,115,102,101,2,39,0,204,195,206,156,1,1,6,52,90,113,105,51,76,1,40,0,198,223,206,159,1,73,2,105,100,1,119,6,52,90,113,105,51,76,40,0,198,223,206,159,1,73,2,116,121,1,119,5,113,117,111,116,101,40,0,198,223,206,159,1,73,6,112,97,114,101,110,116,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,198,223,206,159,1,73,8,99,104,105,108,100,114,101,110,1,119,6,98,50,103,102,70,95,33,0,198,223,206,159,1,73,4,100,97,116,97,1,40,0,198,223,206,159,1,73,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,73,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,98,50,103,102,70,95,0,200,171,236,222,251,5,196,1,198,223,206,159,1,71,1,119,6,52,90,113,105,51,76,4,0,198,223,206,159,1,72,6,231,155,145,230,142,167,168,198,223,206,159,1,78,1,119,31,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,231,155,145,230,142,167,34,125,93,125,196,204,195,206,156,1,244,5,204,195,206,156,1,245,5,9,229,147,136,229,147,136,229,147,136,161,204,195,206,156,1,137,1,1,161,204,195,206,156,1,138,1,1,161,204,195,206,156,1,139,1,1,39,0,204,195,206,156,1,4,6,50,101,101,116,51,53,2,33,0,204,195,206,156,1,1,6,77,103,77,119,109,49,1,0,7,33,0,204,195,206,156,1,3,6,52,76,51,66,86,49,1,193,204,195,206,156,1,232,1,204,195,206,156,1,233,1,1,0,3,39,0,204,195,206,156,1,4,6,100,87,119,54,116,114,2,39,0,204,195,206,156,1,1,6,77,89,55,45,90,70,1,40,0,198,223,206,159,1,107,2,105,100,1,119,6,77,89,55,45,90,70,40,0,198,223,206,159,1,107,2,116,121,1,119,5,113,117,111,116,101,40,0,198,223,206,159,1,107,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,198,223,206,159,1,107,8,99,104,105,108,100,114,101,110,1,119,6,112,88,122,66,110,100,33,0,198,223,206,159,1,107,4,100,97,116,97,1,40,0,198,223,206,159,1,107,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,107,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,112,88,122,66,110,100,0,200,204,195,206,156,1,232,1,198,223,206,159,1,102,1,119,6,77,89,55,45,90,70,4,0,198,223,206,159,1,106,9,229,144,140,228,184,128,228,184,170,161,198,223,206,159,1,112,1,132,198,223,206,159,1,119,3,106,106,106,161,198,223,206,159,1,120,1,39,0,204,195,206,156,1,4,6,71,121,120,95,72,54,2,33,0,204,195,206,156,1,1,6,83,101,74,81,114,75,1,0,7,33,0,204,195,206,156,1,3,6,122,116,99,78,71,87,1,193,204,195,206,156,1,232,1,198,223,206,159,1,116,1,0,3,39,0,204,195,206,156,1,4,6,51,107,108,102,97,80,2,39,0,204,195,206,156,1,1,6,85,72,48,53,51,70,1,40,0,198,223,206,159,1,140,1,2,105,100,1,119,6,85,72,48,53,51,70,40,0,198,223,206,159,1,140,1,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,198,223,206,159,1,140,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,198,223,206,159,1,140,1,8,99,104,105,108,100,114,101,110,1,119,6,52,75,90,73,113,76,33,0,198,223,206,159,1,140,1,4,100,97,116,97,1,40,0,198,223,206,159,1,140,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,140,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,52,75,90,73,113,76,0,200,204,195,206,156,1,232,1,198,223,206,159,1,135,1,1,119,6,85,72,48,53,51,70,4,0,198,223,206,159,1,139,1,3,104,106,107,161,198,223,206,159,1,145,1,1,39,0,204,195,206,156,1,1,6,114,78,78,65,105,82,1,40,0,198,223,206,159,1,154,1,2,105,100,1,119,6,114,78,78,65,105,82,40,0,198,223,206,159,1,154,1,2,116,121,1,119,13,109,97,116,104,95,101,113,117,97,116,105,111,110,40,0,198,223,206,159,1,154,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,198,223,206,159,1,154,1,8,99,104,105,108,100,114,101,110,1,119,6,69,82,69,45,78,66,33,0,198,223,206,159,1,154,1,4,100,97,116,97,1,40,0,198,223,206,159,1,154,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,154,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,69,82,69,45,78,66,0,200,204,195,206,156,1,240,1,204,195,206,156,1,241,1,1,119,6,114,78,78,65,105,82,168,198,223,206,159,1,159,1,1,119,24,123,34,102,111,114,109,117,108,97,34,58,34,105,231,156,139,231,187,143,230,181,142,34,125,39,0,204,195,206,156,1,1,6,68,114,122,68,111,83,1,40,0,198,223,206,159,1,165,1,2,105,100,1,119,6,68,114,122,68,111,83,40,0,198,223,206,159,1,165,1,2,116,121,1,119,5,105,109,97,103,101,40,0,198,223,206,159,1,165,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,198,223,206,159,1,165,1,8,99,104,105,108,100,114,101,110,1,119,6,57,68,97,108,108,97,33,0,198,223,206,159,1,165,1,4,100,97,116,97,1,40,0,198,223,206,159,1,165,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,165,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,57,68,97,108,108,97,0,200,204,195,206,156,1,251,1,204,195,206,156,1,252,1,1,119,6,68,114,122,68,111,83,161,198,223,206,159,1,170,1,1,39,0,204,195,206,156,1,4,6,102,80,55,52,75,113,2,33,0,204,195,206,156,1,1,6,84,120,69,107,78,52,1,0,7,33,0,204,195,206,156,1,3,6,104,109,65,56,45,115,1,193,204,195,206,156,1,244,1,204,195,206,156,1,245,1,1,39,0,204,195,206,156,1,4,6,118,105,52,104,122,104,2,39,0,204,195,206,156,1,1,6,95,98,119,81,76,101,1,40,0,198,223,206,159,1,188,1,2,105,100,1,119,6,95,98,119,81,76,101,40,0,198,223,206,159,1,188,1,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,198,223,206,159,1,188,1,6,112,97,114,101,110,116,1,119,10,101,110,68,45,73,83,100,100,99,55,40,0,198,223,206,159,1,188,1,8,99,104,105,108,100,114,101,110,1,119,6,104,102,109,108,88,52,33,0,198,223,206,159,1,188,1,4,100,97,116,97,1,40,0,198,223,206,159,1,188,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,188,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,104,102,109,108,88,52,0,8,0,204,195,206,156,1,23,1,119,6,95,98,119,81,76,101,4,0,198,223,206,159,1,187,1,3,105,106,106,168,198,223,206,159,1,193,1,1,119,28,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,105,106,106,34,125,93,125,39,0,204,195,206,156,1,4,6,55,83,79,113,80,69,2,33,0,204,195,206,156,1,1,6,75,119,55,52,104,73,1,0,7,33,0,204,195,206,156,1,3,6,80,82,74,72,65,95,1,129,198,223,206,159,1,197,1,1,39,0,204,195,206,156,1,4,6,78,97,78,121,113,76,2,39,0,204,195,206,156,1,1,6,72,90,88,98,113,104,1,40,0,198,223,206,159,1,214,1,2,105,100,1,119,6,72,90,88,98,113,104,40,0,198,223,206,159,1,214,1,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,198,223,206,159,1,214,1,6,112,97,114,101,110,116,1,119,6,95,98,119,81,76,101,40,0,198,223,206,159,1,214,1,8,99,104,105,108,100,114,101,110,1,119,6,110,98,72,85,90,106,33,0,198,223,206,159,1,214,1,4,100,97,116,97,1,40,0,198,223,206,159,1,214,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,214,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,110,98,72,85,90,106,0,8,0,198,223,206,159,1,196,1,1,119,6,72,90,88,98,113,104,4,0,198,223,206,159,1,213,1,4,106,107,110,98,168,198,223,206,159,1,219,1,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,106,107,110,98,34,125,93,125,39,0,204,195,206,156,1,4,6,57,56,55,97,106,50,2,33,0,204,195,206,156,1,1,6,110,117,56,75,122,68,1,0,7,33,0,204,195,206,156,1,3,6,85,56,79,113,105,78,1,129,198,223,206,159,1,223,1,1,39,0,204,195,206,156,1,4,6,88,116,82,99,45,53,2,39,0,204,195,206,156,1,1,6,88,52,88,118,49,84,1,40,0,198,223,206,159,1,241,1,2,105,100,1,119,6,88,52,88,118,49,84,40,0,198,223,206,159,1,241,1,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,198,223,206,159,1,241,1,6,112,97,114,101,110,116,1,119,6,72,90,88,98,113,104,40,0,198,223,206,159,1,241,1,8,99,104,105,108,100,114,101,110,1,119,6,119,77,90,48,100,71,33,0,198,223,206,159,1,241,1,4,100,97,116,97,1,40,0,198,223,206,159,1,241,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,241,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,119,77,90,48,100,71,0,8,0,198,223,206,159,1,222,1,1,119,6,88,52,88,118,49,84,4,0,198,223,206,159,1,240,1,6,232,191,155,230,173,165,161,198,223,206,159,1,246,1,1,132,198,223,206,159,1,252,1,6,230,156,186,228,188,154,168,198,223,206,159,1,253,1,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,232,191,155,230,173,165,230,156,186,228,188,154,34,125,93,125,39,0,204,195,206,156,1,4,6,121,85,99,121,82,100,2,39,0,204,195,206,156,1,1,6,100,121,76,82,53,100,1,40,0,198,223,206,159,1,130,2,2,105,100,1,119,6,100,121,76,82,53,100,40,0,198,223,206,159,1,130,2,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,198,223,206,159,1,130,2,6,112,97,114,101,110,116,1,119,6,72,90,88,98,113,104,40,0,198,223,206,159,1,130,2,8,99,104,105,108,100,114,101,110,1,119,6,55,89,79,70,48,116,33,0,198,223,206,159,1,130,2,4,100,97,116,97,1,40,0,198,223,206,159,1,130,2,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,198,223,206,159,1,130,2,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,6,55,89,79,70,48,116,0,136,198,223,206,159,1,250,1,1,119,6,100,121,76,82,53,100,4,0,198,223,206,159,1,129,2,12,230,150,164,230,150,164,232,174,161,232,190,131,168,198,223,206,159,1,135,2,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,230,150,164,230,150,164,232,174,161,232,190,131,34,125,93,125,230,2,204,195,206,156,1,0,39,1,4,100,97,116,97,8,100,111,99,117,109,101,110,116,1,39,0,204,195,206,156,1,0,6,98,108,111,99,107,115,1,39,0,204,195,206,156,1,0,4,109,101,116,97,1,39,0,204,195,206,156,1,2,12,99,104,105,108,100,114,101,110,95,109,97,112,1,39,0,204,195,206,156,1,2,8,116,101,120,116,95,109,97,112,1,40,0,204,195,206,156,1,0,7,112,97,103,101,95,105,100,1,119,10,109,54,120,76,118,72,89,48,76,107,39,0,204,195,206,156,1,1,10,77,48,104,84,99,67,120,66,88,82,1,40,0,204,195,206,156,1,6,2,105,100,1,119,10,77,48,104,84,99,67,120,66,88,82,40,0,204,195,206,156,1,6,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,6,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,6,8,99,104,105,108,100,114,101,110,1,119,10,49,87,78,107,89,75,118,109,105,50,33,0,204,195,206,156,1,6,4,100,97,116,97,1,33,0,204,195,206,156,1,6,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,49,87,78,107,89,75,118,109,105,50,0,39,0,204,195,206,156,1,1,10,101,110,68,45,73,83,100,100,99,55,1,40,0,204,195,206,156,1,15,2,105,100,1,119,10,101,110,68,45,73,83,100,100,99,55,40,0,204,195,206,156,1,15,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,204,195,206,156,1,15,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,15,8,99,104,105,108,100,114,101,110,1,119,10,103,106,110,76,109,66,89,118,68,65,40,0,204,195,206,156,1,15,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,15,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,102,56,54,108,88,117,88,74,101,54,40,0,204,195,206,156,1,15,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,103,106,110,76,109,66,89,118,68,65,0,39,0,204,195,206,156,1,1,10,113,115,110,89,82,48,74,72,74,56,1,40,0,204,195,206,156,1,24,2,105,100,1,119,10,113,115,110,89,82,48,74,72,74,56,40,0,204,195,206,156,1,24,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,24,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,24,8,99,104,105,108,100,114,101,110,1,119,10,116,79,53,122,78,78,73,82,69,100,40,0,204,195,206,156,1,24,4,100,97,116,97,1,119,17,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,40,0,204,195,206,156,1,24,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,51,72,115,115,121,121,66,84,57,50,40,0,204,195,206,156,1,24,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,116,79,53,122,78,78,73,82,69,100,0,39,0,204,195,206,156,1,1,10,75,54,50,76,100,101,119,53,95,121,1,40,0,204,195,206,156,1,33,2,105,100,1,119,10,75,54,50,76,100,101,119,53,95,121,40,0,204,195,206,156,1,33,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,204,195,206,156,1,33,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,33,8,99,104,105,108,100,114,101,110,1,119,10,57,118,109,120,98,73,71,120,109,73,40,0,204,195,206,156,1,33,4,100,97,116,97,1,119,11,123,34,108,101,118,101,108,34,58,50,125,40,0,204,195,206,156,1,33,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,72,116,114,88,117,57,102,65,95,107,40,0,204,195,206,156,1,33,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,57,118,109,120,98,73,71,120,109,73,0,39,0,204,195,206,156,1,1,10,117,51,120,66,95,83,69,116,53,68,1,40,0,204,195,206,156,1,42,2,105,100,1,119,10,117,51,120,66,95,83,69,116,53,68,40,0,204,195,206,156,1,42,2,116,121,1,119,7,99,97,108,108,111,117,116,40,0,204,195,206,156,1,42,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,42,8,99,104,105,108,100,114,101,110,1,119,10,50,88,118,55,52,84,105,73,70,108,40,0,204,195,206,156,1,42,4,100,97,116,97,1,119,15,123,34,105,99,111,110,34,58,34,240,159,165,176,34,125,40,0,204,195,206,156,1,42,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,108,119,101,104,75,79,117,78,68,67,40,0,204,195,206,156,1,42,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,50,88,118,55,52,84,105,73,70,108,0,39,0,204,195,206,156,1,1,10,78,73,76,105,97,84,121,72,108,112,1,40,0,204,195,206,156,1,51,2,105,100,1,119,10,78,73,76,105,97,84,121,72,108,112,40,0,204,195,206,156,1,51,2,116,121,1,119,5,113,117,111,116,101,40,0,204,195,206,156,1,51,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,51,8,99,104,105,108,100,114,101,110,1,119,10,109,82,95,75,65,57,45,108,110,78,40,0,204,195,206,156,1,51,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,51,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,119,86,82,81,117,71,111,121,116,48,40,0,204,195,206,156,1,51,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,109,82,95,75,65,57,45,108,110,78,0,33,0,204,195,206,156,1,1,10,99,108,78,111,66,75,99,119,73,82,1,0,7,33,0,204,195,206,156,1,3,10,117,117,65,100,55,95,119,72,72,106,1,39,0,204,195,206,156,1,1,10,78,89,54,108,121,101,57,108,88,51,1,40,0,204,195,206,156,1,69,2,105,100,1,119,10,78,89,54,108,121,101,57,108,88,51,40,0,204,195,206,156,1,69,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,69,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,69,8,99,104,105,108,100,114,101,110,1,119,10,108,77,72,53,73,113,54,77,68,78,40,0,204,195,206,156,1,69,4,100,97,116,97,1,119,17,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,40,0,204,195,206,156,1,69,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,109,69,119,56,90,66,102,95,100,68,40,0,204,195,206,156,1,69,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,108,77,72,53,73,113,54,77,68,78,0,39,0,204,195,206,156,1,1,10,101,104,73,115,79,74,69,114,55,73,1,40,0,204,195,206,156,1,78,2,105,100,1,119,10,101,104,73,115,79,74,69,114,55,73,40,0,204,195,206,156,1,78,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,204,195,206,156,1,78,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,78,8,99,104,105,108,100,114,101,110,1,119,10,56,116,67,52,100,103,121,98,57,55,40,0,204,195,206,156,1,78,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,78,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,107,106,48,68,49,121,121,88,78,119,40,0,204,195,206,156,1,78,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,56,116,67,52,100,103,121,98,57,55,0,39,0,204,195,206,156,1,1,10,68,90,114,95,72,118,106,65,78,107,1,40,0,204,195,206,156,1,87,2,105,100,1,119,10,68,90,114,95,72,118,106,65,78,107,40,0,204,195,206,156,1,87,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,87,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,87,8,99,104,105,108,100,114,101,110,1,119,10,119,95,65,55,90,114,77,89,86,122,40,0,204,195,206,156,1,87,4,100,97,116,97,1,119,17,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,40,0,204,195,206,156,1,87,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,54,74,108,118,72,71,53,111,120,90,40,0,204,195,206,156,1,87,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,119,95,65,55,90,114,77,89,86,122,0,33,0,204,195,206,156,1,1,10,105,90,113,50,95,68,72,49,50,69,1,0,7,33,0,204,195,206,156,1,3,10,119,54,53,71,114,77,54,109,119,69,1,39,0,204,195,206,156,1,1,10,48,105,122,109,122,95,86,65,55,70,1,40,0,204,195,206,156,1,105,2,105,100,1,119,10,48,105,122,109,122,95,86,65,55,70,40,0,204,195,206,156,1,105,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,204,195,206,156,1,105,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,105,8,99,104,105,108,100,114,101,110,1,119,10,65,90,49,50,53,79,88,51,65,97,40,0,204,195,206,156,1,105,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,105,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,109,73,73,113,81,111,118,74,105,101,40,0,204,195,206,156,1,105,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,65,90,49,50,53,79,88,51,65,97,0,39,0,204,195,206,156,1,1,10,55,107,121,57,118,72,100,98,90,90,1,40,0,204,195,206,156,1,114,2,105,100,1,119,10,55,107,121,57,118,72,100,98,90,90,40,0,204,195,206,156,1,114,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,114,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,114,8,99,104,105,108,100,114,101,110,1,119,10,118,122,73,48,69,73,102,97,111,55,33,0,204,195,206,156,1,114,4,100,97,116,97,1,33,0,204,195,206,156,1,114,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,114,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,118,122,73,48,69,73,102,97,111,55,0,39,0,204,195,206,156,1,1,10,76,77,51,100,74,90,103,105,119,106,1,40,0,204,195,206,156,1,123,2,105,100,1,119,10,76,77,51,100,74,90,103,105,119,106,40,0,204,195,206,156,1,123,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,204,195,206,156,1,123,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,123,8,99,104,105,108,100,114,101,110,1,119,10,65,49,72,80,70,85,72,104,51,86,40,0,204,195,206,156,1,123,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,123,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,120,116,103,85,69,74,52,104,81,95,40,0,204,195,206,156,1,123,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,65,49,72,80,70,85,72,104,51,86,0,39,0,204,195,206,156,1,1,10,109,73,66,54,73,106,49,57,52,77,1,40,0,204,195,206,156,1,132,1,2,105,100,1,119,10,109,73,66,54,73,106,49,57,52,77,40,0,204,195,206,156,1,132,1,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,204,195,206,156,1,132,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,132,1,8,99,104,105,108,100,114,101,110,1,119,10,121,56,100,54,52,108,75,54,81,109,33,0,204,195,206,156,1,132,1,4,100,97,116,97,1,33,0,204,195,206,156,1,132,1,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,132,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,121,56,100,54,52,108,75,54,81,109,0,39,0,204,195,206,156,1,1,10,109,79,82,56,99,51,71,108,104,101,1,40,0,204,195,206,156,1,141,1,2,105,100,1,119,10,109,79,82,56,99,51,71,108,104,101,40,0,204,195,206,156,1,141,1,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,204,195,206,156,1,141,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,141,1,8,99,104,105,108,100,114,101,110,1,119,10,75,50,75,54,117,121,80,56,108,65,40,0,204,195,206,156,1,141,1,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,141,1,11,101,120,116,101,114,110,97,108,95,105,100,1,119,10,52,97,84,122,117,113,66,107,110,70,40,0,204,195,206,156,1,141,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,119,4,116,101,120,116,39,0,204,195,206,156,1,3,10,75,50,75,54,117,121,80,56,108,65,0,39,0,204,195,206,156,1,1,10,118,110,69,86,85,50,114,57,65,88,1,40,0,204,195,206,156,1,150,1,2,105,100,1,119,10,118,110,69,86,85,50,114,57,65,88,40,0,204,195,206,156,1,150,1,2,116,121,1,119,4,99,111,100,101,40,0,204,195,206,156,1,150,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,150,1,8,99,104,105,108,100,114,101,110,1,119,10,75,119,115,101,107,79,85,115,115,57,33,0,204,195,206,156,1,150,1,4,100,97,116,97,1,33,0,204,195,206,156,1,150,1,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,150,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,75,119,115,101,107,79,85,115,115,57,0,39,0,204,195,206,156,1,1,10,104,87,121,95,110,110,79,73,101,108,1,40,0,204,195,206,156,1,159,1,2,105,100,1,119,10,104,87,121,95,110,110,79,73,101,108,40,0,204,195,206,156,1,159,1,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,204,195,206,156,1,159,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,159,1,8,99,104,105,108,100,114,101,110,1,119,10,95,74,97,104,108,70,88,117,82,109,33,0,204,195,206,156,1,159,1,4,100,97,116,97,1,33,0,204,195,206,156,1,159,1,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,159,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,95,74,97,104,108,70,88,117,82,109,0,33,0,204,195,206,156,1,1,10,71,45,117,115,79,56,75,107,81,81,1,0,7,33,0,204,195,206,156,1,3,10,56,112,113,84,95,112,120,118,65,78,1,33,0,204,195,206,156,1,1,10,87,114,65,73,121,89,90,76,79,110,1,0,7,33,0,204,195,206,156,1,3,10,89,100,82,106,88,106,109,55,118,114,1,33,0,204,195,206,156,1,1,10,95,90,102,110,119,90,114,87,68,105,1,0,7,33,0,204,195,206,156,1,3,10,49,86,117,68,73,110,45,56,100,114,1,39,0,204,195,206,156,1,1,10,82,50,56,82,106,69,66,70,99,71,1,40,0,204,195,206,156,1,195,1,2,105,100,1,119,10,82,50,56,82,106,69,66,70,99,71,40,0,204,195,206,156,1,195,1,2,116,121,1,119,7,100,105,118,105,100,101,114,40,0,204,195,206,156,1,195,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,195,1,8,99,104,105,108,100,114,101,110,1,119,10,119,115,98,50,74,101,113,52,87,71,40,0,204,195,206,156,1,195,1,4,100,97,116,97,1,119,2,123,125,40,0,204,195,206,156,1,195,1,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,204,195,206,156,1,195,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,204,195,206,156,1,3,10,119,115,98,50,74,101,113,52,87,71,0,39,0,204,195,206,156,1,1,10,109,54,120,76,118,72,89,48,76,107,1,40,0,204,195,206,156,1,204,1,2,105,100,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,204,1,2,116,121,1,119,4,112,97,103,101,40,0,204,195,206,156,1,204,1,6,112,97,114,101,110,116,1,119,0,40,0,204,195,206,156,1,204,1,8,99,104,105,108,100,114,101,110,1,119,10,120,68,48,121,90,73,118,109,51,115,33,0,204,195,206,156,1,204,1,4,100,97,116,97,1,33,0,204,195,206,156,1,204,1,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,204,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,120,68,48,121,90,73,118,109,51,115,0,33,0,204,195,206,156,1,1,10,97,115,74,118,54,70,114,65,82,97,1,0,7,33,0,204,195,206,156,1,3,10,68,75,70,79,99,81,75,54,52,72,1,39,0,204,195,206,156,1,1,10,119,70,86,108,107,88,117,108,104,74,1,40,0,204,195,206,156,1,222,1,2,105,100,1,119,10,119,70,86,108,107,88,117,108,104,74,40,0,204,195,206,156,1,222,1,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,204,195,206,156,1,222,1,6,112,97,114,101,110,116,1,119,10,109,54,120,76,118,72,89,48,76,107,40,0,204,195,206,156,1,222,1,8,99,104,105,108,100,114,101,110,1,119,10,69,113,72,71,75,105,54,115,68,53,33,0,204,195,206,156,1,222,1,4,100,97,116,97,1,33,0,204,195,206,156,1,222,1,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,204,195,206,156,1,222,1,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,204,195,206,156,1,3,10,69,113,72,71,75,105,54,115,68,53,0,8,0,204,195,206,156,1,212,1,1,119,10,119,70,86,108,107,88,117,108,104,74,129,204,195,206,156,1,231,1,1,136,204,195,206,156,1,232,1,6,119,10,109,73,66,54,73,106,49,57,52,77,119,10,78,89,54,108,121,101,57,108,88,51,119,10,68,90,114,95,72,118,106,65,78,107,119,10,113,115,110,89,82,48,74,72,74,56,119,10,55,107,121,57,118,72,100,98,90,90,119,10,77,48,104,84,99,67,120,66,88,82,129,204,195,206,156,1,238,1,1,136,204,195,206,156,1,239,1,1,119,10,82,50,56,82,106,69,66,70,99,71,129,204,195,206,156,1,240,1,1,136,204,195,206,156,1,241,1,1,119,10,104,87,121,95,110,110,79,73,101,108,136,204,195,206,156,1,242,1,2,119,10,48,105,122,109,122,95,86,65,55,70,119,10,101,110,68,45,73,83,100,100,99,55,136,204,195,206,156,1,244,1,2,119,10,109,79,82,56,99,51,71,108,104,101,119,10,118,110,69,86,85,50,114,57,65,88,129,204,195,206,156,1,246,1,1,136,204,195,206,156,1,247,1,4,119,10,75,54,50,76,100,101,119,53,95,121,119,10,78,73,76,105,97,84,121,72,108,112,119,10,101,104,73,115,79,74,69,114,55,73,119,10,117,51,120,66,95,83,69,116,53,68,129,204,195,206,156,1,251,1,1,136,204,195,206,156,1,252,1,1,119,10,76,77,51,100,74,90,103,105,119,106,129,204,195,206,156,1,253,1,1,39,0,204,195,206,156,1,4,10,97,98,100,49,105,117,71,81,109,68,2,4,0,204,195,206,156,1,255,1,44,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,44,32,109,97,114,107,100,111,119,110,44,32,97,110,100,32,99,111,100,101,32,98,108,111,99,107,39,0,204,195,206,156,1,4,10,54,74,108,118,72,71,53,111,120,90,2,4,0,204,195,206,156,1,172,2,20,65,115,32,115,111,111,110,32,97,115,32,121,111,117,32,116,121,112,101,32,134,204,195,206,156,1,192,2,10,102,111,110,116,95,99,111,108,111,114,12,34,48,120,102,102,48,48,98,53,102,102,34,134,204,195,206,156,1,193,2,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,194,2,1,47,134,204,195,206,156,1,195,2,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,134,204,195,206,156,1,196,2,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,197,2,28,32,97,32,109,101,110,117,32,119,105,108,108,32,112,111,112,32,117,112,46,32,83,101,108,101,99,116,32,134,204,195,206,156,1,225,2,8,98,103,95,99,111,108,111,114,12,34,48,120,52,100,57,99,50,55,98,48,34,132,204,195,206,156,1,226,2,15,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,134,204,195,206,156,1,241,2,8,98,103,95,99,111,108,111,114,4,110,117,108,108,132,204,195,206,156,1,242,2,31,32,111,102,32,99,111,110,116,101,110,116,32,98,108,111,99,107,115,32,121,111,117,32,99,97,110,32,97,100,100,46,39,0,204,195,206,156,1,4,10,51,72,115,115,121,121,66,84,57,50,2,4,0,204,195,206,156,1,146,3,5,84,121,112,101,32,134,204,195,206,156,1,151,3,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,152,3,1,47,134,204,195,206,156,1,153,3,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,154,3,13,32,102,111,108,108,111,119,101,100,32,98,121,32,134,204,195,206,156,1,167,3,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,168,3,7,47,98,117,108,108,101,116,134,204,195,206,156,1,175,3,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,176,3,4,32,111,114,32,134,204,195,206,156,1,180,3,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,181,3,4,47,110,117,109,134,204,195,206,156,1,185,3,4,99,111,100,101,4,110,117,108,108,198,204,195,206,156,1,185,3,204,195,206,156,1,186,3,4,99,111,100,101,5,102,97,108,115,101,196,204,195,206,156,1,187,3,204,195,206,156,1,186,3,18,32,116,111,32,99,114,101,97,116,101,32,97,32,108,105,115,116,46,198,204,195,206,156,1,205,3,204,195,206,156,1,186,3,4,99,111,100,101,4,116,114,117,101,33,0,204,195,206,156,1,4,10,84,82,53,102,106,82,122,115,114,105,1,39,0,204,195,206,156,1,4,10,119,86,82,81,117,71,111,121,116,48,2,4,0,204,195,206,156,1,208,3,6,67,108,105,99,107,32,134,204,195,206,156,1,214,3,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,215,3,1,63,134,204,195,206,156,1,216,3,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,217,3,42,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,114,105,103,104,116,32,102,111,114,32,104,101,108,112,32,97,110,100,32,115,117,112,112,111,114,116,46,39,0,204,195,206,156,1,4,10,107,106,48,68,49,121,121,88,78,119,2,39,0,204,195,206,156,1,4,10,120,116,103,85,69,74,52,104,81,95,2,39,0,204,195,206,156,1,4,10,112,70,113,76,55,45,79,83,121,86,2,4,0,204,195,206,156,1,134,4,0,33,0,204,195,206,156,1,4,10,102,114,97,74,99,70,55,54,70,99,1,39,0,204,195,206,156,1,4,10,122,77,121,109,67,97,118,83,107,102,2,4,0,204,195,206,156,1,136,4,6,67,108,105,99,107,32,134,204,195,206,156,1,142,4,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,143,4,11,43,32,78,101,119,32,80,97,103,101,32,134,204,195,206,156,1,154,4,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,155,4,50,98,117,116,116,111,110,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,111,102,32,121,111,117,114,32,115,105,100,101,98,97,114,32,116,111,32,97,100,100,32,97,32,110,101,119,32,129,204,195,206,156,1,205,4,4,132,204,195,206,156,1,209,4,1,46,39,0,204,195,206,156,1,4,10,72,116,114,88,117,57,102,65,95,107,2,4,0,204,195,206,156,1,211,4,18,72,97,118,101,32,97,32,113,117,101,115,116,105,111,110,226,157,147,39,0,204,195,206,156,1,4,10,49,112,115,100,67,122,97,87,104,49,2,4,0,204,195,206,156,1,228,4,30,47,47,32,84,104,105,115,32,105,115,32,116,104,101,32,109,97,105,110,32,102,117,110,99,116,105,111,110,46,10,129,204,195,206,156,1,130,5,77,39,0,204,195,206,156,1,4,10,119,79,108,117,99,85,55,51,73,76,2,4,0,204,195,206,156,1,208,5,36,67,108,105,99,107,32,97,110,121,119,104,101,114,101,32,97,110,100,32,106,117,115,116,32,115,116,97,114,116,32,116,121,112,105,110,103,132,204,195,206,156,1,244,5,1,46,33,0,204,195,206,156,1,4,10,69,72,117,95,67,112,120,53,67,103,1,39,0,204,195,206,156,1,4,10,98,113,76,109,98,57,111,45,109,109,2,4,0,204,195,206,156,1,247,5,6,67,108,105,99,107,32,134,204,195,206,156,1,253,5,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,254,5,1,43,134,204,195,206,156,1,255,5,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,128,6,1,32,129,204,195,206,156,1,129,6,4,132,204,195,206,156,1,133,6,37,32,116,111,32,97,110,121,32,112,97,103,101,32,116,105,116,108,101,32,105,110,32,116,104,101,32,115,105,100,101,98,97,114,32,116,111,32,134,204,195,206,156,1,170,6,10,102,111,110,116,95,99,111,108,111,114,12,34,48,120,102,102,56,52,50,55,101,48,34,132,204,195,206,156,1,171,6,7,113,117,105,99,107,108,121,134,204,195,206,156,1,178,6,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,132,204,195,206,156,1,179,6,1,32,129,204,195,206,156,1,180,6,3,132,204,195,206,156,1,183,6,16,32,97,32,110,101,119,32,115,117,98,112,97,103,101,44,32,134,204,195,206,156,1,199,6,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,200,6,8,68,111,99,117,109,101,110,116,134,204,195,206,156,1,208,6,4,99,111,100,101,4,110,117,108,108,198,204,195,206,156,1,208,6,204,195,206,156,1,209,6,4,99,111,100,101,5,102,97,108,115,101,196,204,195,206,156,1,210,6,204,195,206,156,1,209,6,2,44,32,198,204,195,206,156,1,212,6,204,195,206,156,1,209,6,4,99,111,100,101,4,116,114,117,101,196,204,195,206,156,1,213,6,204,195,206,156,1,209,6,4,71,114,105,100,198,204,195,206,156,1,217,6,204,195,206,156,1,209,6,4,99,111,100,101,5,102,97,108,115,101,196,204,195,206,156,1,218,6,204,195,206,156,1,209,6,5,44,32,111,114,32,198,204,195,206,156,1,223,6,204,195,206,156,1,209,6,4,99,111,100,101,4,116,114,117,101,196,204,195,206,156,1,224,6,204,195,206,156,1,209,6,12,75,97,110,98,97,110,32,66,111,97,114,100,198,204,195,206,156,1,236,6,204,195,206,156,1,209,6,4,99,111,100,101,5,102,97,108,115,101,196,204,195,206,156,1,237,6,204,195,206,156,1,209,6,1,46,198,204,195,206,156,1,238,6,204,195,206,156,1,209,6,4,99,111,100,101,4,116,114,117,101,39,0,204,195,206,156,1,4,10,102,56,54,108,88,117,88,74,101,54,2,4,0,204,195,206,156,1,240,6,9,77,97,114,107,100,111,119,110,32,134,204,195,206,156,1,249,6,4,104,114,101,102,67,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,109,97,114,107,100,111,119,110,34,132,204,195,206,156,1,250,6,9,114,101,102,101,114,101,110,99,101,134,204,195,206,156,1,131,7,4,104,114,101,102,4,110,117,108,108,33,0,204,195,206,156,1,4,10,89,74,119,52,70,81,88,106,110,84,1,39,0,204,195,206,156,1,4,10,119,88,107,79,72,81,49,50,99,111,2,1,0,204,195,206,156,1,134,7,20,33,0,204,195,206,156,1,4,10,65,108,73,86,97,121,54,119,80,104,1,0,19,39,0,204,195,206,156,1,4,10,109,69,119,56,90,66,102,95,100,68,2,6,0,204,195,206,156,1,175,7,8,98,103,95,99,111,108,111,114,12,34,48,120,52,100,102,102,101,98,51,98,34,132,204,195,206,156,1,176,7,10,72,105,103,104,108,105,103,104,116,32,134,204,195,206,156,1,186,7,8,98,103,95,99,111,108,111,114,4,110,117,108,108,132,204,195,206,156,1,187,7,38,97,110,121,32,116,101,120,116,44,32,97,110,100,32,117,115,101,32,116,104,101,32,101,100,105,116,105,110,103,32,109,101,110,117,32,116,111,32,134,204,195,206,156,1,225,7,6,105,116,97,108,105,99,4,116,114,117,101,132,204,195,206,156,1,226,7,5,115,116,121,108,101,134,204,195,206,156,1,231,7,6,105,116,97,108,105,99,4,110,117,108,108,132,204,195,206,156,1,232,7,1,32,134,204,195,206,156,1,233,7,4,98,111,108,100,4,116,114,117,101,132,204,195,206,156,1,234,7,4,121,111,117,114,134,204,195,206,156,1,238,7,4,98,111,108,100,4,110,117,108,108,132,204,195,206,156,1,239,7,1,32,134,204,195,206,156,1,240,7,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,132,204,195,206,156,1,241,7,7,119,114,105,116,105,110,103,134,204,195,206,156,1,248,7,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,132,204,195,206,156,1,249,7,1,32,134,204,195,206,156,1,250,7,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,251,7,7,104,111,119,101,118,101,114,134,204,195,206,156,1,130,8,4,99,111,100,101,4,110,117,108,108,132,204,195,206,156,1,131,8,5,32,121,111,117,32,134,204,195,206,156,1,136,8,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,132,204,195,206,156,1,137,8,5,108,105,107,101,46,134,204,195,206,156,1,142,8,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,33,0,204,195,206,156,1,4,10,98,122,103,70,79,75,118,99,117,89,1,39,0,204,195,206,156,1,4,10,52,97,84,122,117,113,66,107,110,70,2,4,0,204,195,206,156,1,145,8,5,84,121,112,101,32,134,204,195,206,156,1,150,8,4,99,111,100,101,4,116,114,117,101,132,204,195,206,156,1,151,8,5,47,99,111,100,101,134,204,195,206,156,1,156,8,4,99,111,100,101,4,110,117,108,108,198,204,195,206,156,1,156,8,204,195,206,156,1,157,8,4,99,111,100,101,5,102,97,108,115,101,196,204,195,206,156,1,158,8,204,195,206,156,1,157,8,23,32,116,111,32,105,110,115,101,114,116,32,97,32,99,111,100,101,32,98,108,111,99,107,198,204,195,206,156,1,181,8,204,195,206,156,1,157,8,4,99,111,100,101,4,116,114,117,101,39,0,204,195,206,156,1,4,10,108,119,101,104,75,79,117,78,68,67,2,4,0,204,195,206,156,1,183,8,27,10,76,105,107,101,32,65,112,112,70,108,111,119,121,63,32,70,111,108,108,111,119,32,117,115,58,10,134,204,195,206,156,1,210,8,4,104,114,101,102,41,34,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,65,112,112,70,108,111,119,121,45,73,79,47,65,112,112,70,108,111,119,121,34,132,204,195,206,156,1,211,8,6,71,105,116,72,117,98,134,204,195,206,156,1,217,8,4,104,114,101,102,4,110,117,108,108,132,204,195,206,156,1,218,8,1,10,134,204,195,206,156,1,219,8,4,104,114,101,102,30,34,104,116,116,112,115,58,47,47,116,119,105,116,116,101,114,46,99,111,109,47,97,112,112,102,108,111,119,121,34,132,204,195,206,156,1,220,8,7,84,119,105,116,116,101,114,134,204,195,206,156,1,227,8,4,104,114,101,102,4,110,117,108,108,132,204,195,206,156,1,228,8,12,58,32,64,97,112,112,102,108,111,119,121,10,134,204,195,206,156,1,240,8,4,104,114,101,102,33,34,104,116,116,112,115,58,47,47,98,108,111,103,45,97,112,112,102,108,111,119,121,46,103,104,111,115,116,46,105,111,47,34,132,204,195,206,156,1,241,8,10,78,101,119,115,108,101,116,116,101,114,134,204,195,206,156,1,251,8,4,104,114,101,102,4,110,117,108,108,132,204,195,206,156,1,252,8,1,10,39,0,204,195,206,156,1,4,10,109,73,73,113,81,111,118,74,105,101,2,4,0,204,195,206,156,1,254,8,19,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,32,134,204,195,206,156,1,145,9,4,104,114,101,102,68,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,115,104,111,114,116,99,117,116,115,34,132,204,195,206,156,1,146,9,5,103,117,105,100,101,134,204,195,206,156,1,151,9,4,104,114,101,102,4,110,117,108,108,1,141,178,210,127,0,0,3,1,206,214,243,86,0,161,236,158,128,159,2,3,178,1,1,229,154,194,35,0,161,136,172,186,168,4,181,6,178,1,1,218,255,204,32,0,161,150,152,188,203,6,19,21,41,192,246,139,213,2,1,0,35,131,182,180,202,12,1,0,53,132,236,218,251,9,1,0,14,197,205,192,233,12,1,0,9,198,223,206,159,1,25,15,3,19,20,40,10,51,10,62,10,78,1,89,3,93,13,112,1,120,1,124,1,126,13,145,1,1,153,1,1,159,1,1,170,1,1,175,1,1,177,1,10,193,1,1,203,1,10,219,1,1,230,1,10,246,1,1,253,1,1,135,2,1,199,130,209,189,2,202,1,4,11,16,1,19,12,33,1,35,1,37,1,39,1,41,1,43,1,45,1,47,1,49,1,56,1,61,1,63,1,65,1,67,1,69,1,71,1,73,1,75,1,77,1,79,1,81,1,83,1,85,1,87,1,89,1,91,1,93,1,95,1,102,1,107,1,109,1,111,1,113,1,115,1,117,1,119,1,121,1,123,1,125,4,136,1,1,144,1,1,152,1,1,160,1,1,168,1,1,176,1,1,184,1,1,192,1,1,200,1,1,208,1,1,216,1,1,224,1,1,232,1,1,240,1,1,248,1,1,128,2,1,136,2,1,144,2,1,152,2,1,160,2,1,168,2,1,176,2,1,184,2,1,192,2,1,200,2,2,208,2,1,213,2,1,215,2,27,246,2,21,140,3,1,142,3,1,144,3,1,146,3,1,153,3,1,162,3,10,177,3,1,183,3,10,202,3,1,212,3,1,222,3,1,232,3,1,242,3,1,252,3,1,134,4,1,144,4,1,154,4,1,159,4,1,161,4,1,163,4,1,165,4,1,167,4,1,169,4,1,171,4,1,173,4,1,175,4,1,177,4,5,188,4,1,193,4,6,200,4,10,216,4,1,221,4,6,228,4,10,244,4,1,249,4,6,133,5,1,138,5,6,145,5,10,156,5,1,158,5,1,160,5,1,162,5,3,170,5,1,175,5,6,182,5,16,199,5,1,206,5,1,211,5,6,223,5,1,228,5,7,236,5,10,252,5,1,129,6,6,136,6,10,147,6,10,158,6,1,160,6,1,162,6,1,178,6,1,180,6,2,183,6,2,186,6,1,188,6,1,190,6,1,192,6,1,194,6,1,196,6,1,198,6,1,200,6,1,202,6,1,206,6,1,208,6,1,210,6,1,212,6,1,214,6,4,219,6,1,223,6,1,225,6,1,227,6,1,229,6,1,231,6,1,233,6,1,235,6,1,237,6,1,241,6,1,243,6,1,245,6,1,247,6,1,249,6,1,251,6,1,253,6,1,255,6,1,131,7,1,133,7,1,135,7,1,137,7,1,139,7,1,141,7,1,144,7,21,166,7,1,168,7,1,170,7,1,172,7,1,174,7,1,176,7,1,178,7,1,180,7,1,182,7,1,184,7,1,188,7,1,190,7,1,192,7,1,194,7,1,196,7,1,198,7,4,205,7,1,207,7,1,209,7,1,211,7,1,213,7,1,215,7,1,217,7,13,231,7,1,240,7,1,248,7,2,252,7,3,130,8,1,132,8,1,134,8,1,136,8,2,139,8,2,136,172,186,168,4,1,0,182,6,204,195,206,156,1,27,11,3,60,9,96,9,119,3,137,1,3,155,1,3,164,1,3,168,1,27,209,1,3,213,1,9,227,1,3,232,1,1,239,1,1,241,1,1,247,1,1,252,1,1,254,1,1,207,3,1,135,4,1,206,4,4,131,5,77,246,5,1,130,6,4,181,6,3,133,7,1,135,7,40,144,8,1,141,178,210,127,1,0,3,140,167,201,161,14,1,0,4,142,211,188,164,13,1,0,15,206,214,243,86,1,0,178,1,146,216,250,133,2,1,0,180,1,150,152,188,203,6,1,0,20,151,234,142,238,11,1,0,27,150,216,171,142,3,86,0,171,3,172,3,3,176,3,3,180,3,3,184,3,3,188,3,3,192,3,3,196,3,3,200,3,3,204,3,3,208,3,3,212,3,3,216,3,3,220,3,3,224,3,3,228,3,3,232,3,3,236,3,3,240,3,3,244,3,3,248,3,3,253,3,3,129,4,3,133,4,3,137,4,3,141,4,3,145,4,3,149,4,3,153,4,3,157,4,3,161,4,3,165,4,3,169,4,3,173,4,3,177,4,3,181,4,3,185,4,3,189,4,3,193,4,3,197,4,3,201,4,3,205,4,3,209,4,3,213,4,3,217,4,3,221,4,3,225,4,3,229,4,7,254,4,10,138,5,1,140,5,1,142,5,1,149,5,1,155,5,1,157,5,1,159,5,1,166,5,11,178,5,15,200,5,1,210,5,1,220,5,1,230,5,1,235,5,1,237,5,1,239,5,1,241,5,1,245,5,1,251,5,1,133,6,1,138,6,1,144,6,1,154,6,1,164,6,1,174,6,1,180,6,1,182,6,1,184,6,1,186,6,5,216,6,3,231,6,14,188,7,6,158,8,1,160,8,1,162,8,1,164,8,3,168,8,3,217,168,198,159,4,1,0,7,218,255,204,32,1,0,21,155,213,159,176,1,1,0,10,219,200,174,197,9,1,0,25,224,159,166,178,15,1,0,30,161,234,157,145,5,1,0,7,226,167,254,250,5,3,8,1,10,1,12,1,228,242,134,215,15,4,5,1,7,1,9,1,11,1,165,131,171,211,15,1,0,20,229,154,194,35,1,0,178,1,164,202,219,213,10,18,19,10,31,10,42,1,44,10,55,1,57,1,59,1,61,3,67,1,77,7,85,1,87,1,89,1,91,1,93,1,95,1,97,1,117,1,168,215,223,235,2,1,0,3,171,236,222,251,5,69,9,5,15,11,27,8,36,3,40,4,45,8,54,8,63,3,72,3,76,3,80,3,84,3,88,3,92,3,96,3,102,3,106,10,120,10,131,1,10,142,1,10,153,1,10,169,1,1,176,1,2,179,1,1,181,1,1,187,1,10,201,1,1,207,1,10,222,1,10,237,1,17,131,2,10,146,2,10,166,2,1,172,2,10,186,2,1,192,2,10,207,2,10,222,2,10,237,2,10,252,2,10,139,3,10,150,3,18,169,3,15,185,3,1,202,3,1,208,3,1,210,3,1,212,3,1,240,3,1,245,3,10,128,4,4,137,4,1,142,4,7,150,4,6,157,4,6,164,4,6,171,4,6,178,4,6,185,4,6,192,4,6,199,4,1,201,4,4,206,4,7,214,4,6,221,4,6,228,4,6,235,4,6,242,4,1,249,4,1,172,254,181,239,1,4,5,1,8,1,11,1,14,1,236,158,128,159,2,1,0,4,239,239,208,251,10,1,0,17,176,238,158,139,14,1,0,175,2,241,147,239,232,6,1,0,4,178,187,245,161,14,2,8,1,10,1,243,138,171,183,10,2,0,240,1,243,1,3,245,181,155,135,2,1,0,23,181,156,253,158,6,1,0,4,247,212,219,208,10,1,0,46,184,146,243,216,14,1,0,7,190,183,139,210,2,1,0,109],"version":0},"code":0,"message":"Operation completed successfully."} \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/fixtures/sign_in_success.json b/frontend/appflowy_web_app/cypress/fixtures/sign_in_success.json new file mode 100644 index 0000000000..0679311668 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/fixtures/sign_in_success.json @@ -0,0 +1,66 @@ +{ + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTI4Mjk2MjAsImlhdCI6MTcxMjgyNjAyMCwic3ViIjoiY2JmZjA2MGEtMTk2ZC00MTVhLWFhODAtNzU5YzAxODg2NDY2IiwiZW1haWwiOiJsdUBhcHBmbG93eS5pbyIsInBob25lIjoiIiwiYXBwX21ldGFkYXRhIjp7InByb3ZpZGVyIjoiZ29vZ2xlIiwicHJvdmlkZXJzIjpbImdvb2dsZSJdfSwidXNlcl9tZXRhZGF0YSI6eyJhdmF0YXJfdXJsIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvQUNnOG9jTEhabVZBczRTb0ZlVFFuWG5CU2JiNTBBVXF0YktHNWx5MGllVHZCSklYZ1o3UmdRPXM5Ni1jIiwiY3VzdG9tX2NsYWltcyI6eyJoZCI6ImFwcGZsb3d5LmlvIn0sImVtYWlsIjoibHVAYXBwZmxvd3kuaW8iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZnVsbF9uYW1lIjoiTHUgSGUiLCJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYW1lIjoiTHUgSGUiLCJwaG9uZV92ZXJpZmllZCI6ZmFsc2UsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NMSFptVkFzNFNvRmVUUW5YbkJTYmI1MEFVcXRiS0c1bHkwaWVUdkJKSVhnWjdSZ1E9czk2LWMiLCJwcm92aWRlcl9pZCI6IjEwMTE2OTI1MDgyOTU1NDAyODM4MSIsInN1YiI6IjEwMTE2OTI1MDgyOTU1NDAyODM4MSJ9LCJyb2xlIjoiIiwiYWFsIjoiYWFsMSIsImFtciI6W3sibWV0aG9kIjoicGFzc3dvcmQiLCJ0aW1lc3RhbXAiOjE3MTI4MjYwMjB9XSwic2Vzc2lvbl9pZCI6ImJmMzE5OTRlLTQwMTgtNDhjMS05Yzc0LWVmYzkyMGNjOWQ0NSJ9.QeTrRhsnBjBL1GUS3TIWOgU1SPM6RcaWwxZdMVfcFBU", + "token_type": "bearer", + "expires_in": 3600, + "expires_at": 4869016461, + "refresh_token": "71vp1jJnSAVluZKaXkhG1A", + "user": { + "id": "cbff060a-196d-415a-aa80-759c01886466", + "aud": "", + "role": "", + "email": "lu@appflowy.io", + "email_confirmed_at": "2024-03-13T10:49:53.165361Z", + "phone": "", + "confirmed_at": "2024-03-13T10:49:53.165361Z", + "last_sign_in_at": "2024-04-11T09:00:20.547468985Z", + "app_metadata": { + "provider": "google", + "providers": [ + "google" + ] + }, + "user_metadata": { + "avatar_url": "https://lh3.googleusercontent.com/a/ACg8ocLHZmVAs4SoFeTQnXnBSbb50AUqtbKG5ly0ieTvBJIXgZ7RgQ=s96-c", + "custom_claims": { + "hd": "appflowy.io" + }, + "email": "lu@appflowy.io", + "email_verified": true, + "full_name": "Lu He", + "iss": "https://accounts.google.com", + "name": "Lu He", + "phone_verified": false, + "picture": "https://lh3.googleusercontent.com/a/ACg8ocLHZmVAs4SoFeTQnXnBSbb50AUqtbKG5ly0ieTvBJIXgZ7RgQ=s96-c", + "provider_id": "101169250829554028381", + "sub": "101169250829554028381" + }, + "identities": [ + { + "identity_id": "e4cf8b69-7f80-42e9-aed2-e25132ad0178", + "id": "101169250829554028381", + "user_id": "cbff060a-196d-415a-aa80-759c01886466", + "identity_data": { + "avatar_url": "https://lh3.googleusercontent.com/a/ACg8ocLHZmVAs4SoFeTQnXnBSbb50AUqtbKG5ly0ieTvBJIXgZ7RgQ=s96-c", + "custom_claims": { + "hd": "appflowy.io" + }, + "email": "lu@appflowy.io", + "email_verified": true, + "full_name": "Lu He", + "iss": "https://accounts.google.com", + "name": "Lu He", + "phone_verified": false, + "picture": "https://lh3.googleusercontent.com/a/ACg8ocLHZmVAs4SoFeTQnXnBSbb50AUqtbKG5ly0ieTvBJIXgZ7RgQ=s96-c", + "provider_id": "101169250829554028381", + "sub": "101169250829554028381" + }, + "provider": "google", + "last_sign_in_at": "2024-03-13T07:22:43.110504Z", + "created_at": "2024-03-13T07:22:43.110543Z", + "updated_at": "2024-04-04T06:15:14.03093Z" + } + ], + "created_at": "2024-03-13T07:22:43.102586Z", + "updated_at": "2024-04-11T09:00:20.551485Z" + } +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/fixtures/simple_doc.json b/frontend/appflowy_web_app/cypress/fixtures/simple_doc.json new file mode 100644 index 0000000000..97bd9c99b5 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/fixtures/simple_doc.json @@ -0,0 +1 @@ +{"data":{"state_vector":[5,200,244,136,224,7,3,178,246,186,209,6,72,147,128,159,145,14,26,195,133,217,18,167,13,156,139,194,87,4],"doc_state":[5,26,147,128,159,145,14,0,39,1,4,100,97,116,97,8,100,111,99,117,109,101,110,116,1,39,0,147,128,159,145,14,0,6,98,108,111,99,107,115,1,39,0,147,128,159,145,14,0,4,109,101,116,97,1,39,0,147,128,159,145,14,2,12,99,104,105,108,100,114,101,110,95,109,97,112,1,39,0,147,128,159,145,14,2,8,116,101,120,116,95,109,97,112,1,40,0,147,128,159,145,14,0,7,112,97,103,101,95,105,100,1,119,10,85,86,79,107,81,88,110,117,86,114,39,0,147,128,159,145,14,1,10,51,77,108,48,104,78,110,102,79,82,1,40,0,147,128,159,145,14,6,2,105,100,1,119,10,51,77,108,48,104,78,110,102,79,82,40,0,147,128,159,145,14,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,147,128,159,145,14,6,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,147,128,159,145,14,6,8,99,104,105,108,100,114,101,110,1,119,10,73,121,84,67,107,48,105,52,113,114,33,0,147,128,159,145,14,6,4,100,97,116,97,1,33,0,147,128,159,145,14,6,11,101,120,116,101,114,110,97,108,95,105,100,1,33,0,147,128,159,145,14,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,39,0,147,128,159,145,14,3,10,73,121,84,67,107,48,105,52,113,114,0,39,0,147,128,159,145,14,1,10,85,86,79,107,81,88,110,117,86,114,1,40,0,147,128,159,145,14,15,2,105,100,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,147,128,159,145,14,15,2,116,121,1,119,4,112,97,103,101,40,0,147,128,159,145,14,15,6,112,97,114,101,110,116,1,119,0,40,0,147,128,159,145,14,15,8,99,104,105,108,100,114,101,110,1,119,10,67,102,118,66,115,66,84,122,83,105,40,0,147,128,159,145,14,15,4,100,97,116,97,1,119,2,123,125,40,0,147,128,159,145,14,15,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,147,128,159,145,14,15,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,10,67,102,118,66,115,66,84,122,83,105,0,8,0,147,128,159,145,14,23,1,119,10,51,77,108,48,104,78,110,102,79,82,39,0,147,128,159,145,14,4,10,84,97,119,48,120,69,66,121,65,83,2,1,200,244,136,224,7,0,33,1,4,109,101,116,97,12,108,97,115,116,95,115,121,110,99,95,97,116,3,1,178,246,186,209,6,0,161,200,244,136,224,7,2,72,2,156,139,194,87,0,161,178,246,186,209,6,71,3,168,156,139,194,87,2,1,122,0,0,0,0,102,34,168,95,251,5,195,133,217,18,0,4,0,147,128,159,145,14,25,2,85,73,168,147,128,159,145,14,11,1,119,27,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,85,73,34,125,93,125,168,147,128,159,145,14,12,1,119,10,84,97,119,48,120,69,66,121,65,83,168,147,128,159,145,14,13,1,119,4,116,101,120,116,39,0,147,128,159,145,14,4,6,120,52,56,106,57,65,2,39,0,147,128,159,145,14,1,6,53,77,89,104,51,105,1,40,0,195,133,217,18,6,2,105,100,1,119,6,53,77,89,104,51,105,40,0,195,133,217,18,6,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,6,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,6,8,99,104,105,108,100,114,101,110,1,119,6,75,79,49,111,105,114,33,0,195,133,217,18,6,4,100,97,116,97,1,40,0,195,133,217,18,6,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,6,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,75,79,49,111,105,114,0,136,147,128,159,145,14,24,1,119,6,53,77,89,104,51,105,4,0,195,133,217,18,5,3,111,111,111,168,195,133,217,18,11,1,119,28,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,111,111,111,34,125,93,125,39,0,147,128,159,145,14,4,6,73,72,56,87,97,118,2,33,0,147,128,159,145,14,1,6,85,81,88,116,105,65,1,0,7,33,0,147,128,159,145,14,3,6,65,122,48,88,110,77,1,129,195,133,217,18,15,1,39,0,147,128,159,145,14,4,6,82,122,107,73,79,49,2,39,0,147,128,159,145,14,1,6,69,79,113,57,79,119,1,40,0,195,133,217,18,32,2,105,100,1,119,6,69,79,113,57,79,119,40,0,195,133,217,18,32,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,195,133,217,18,32,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,32,8,99,104,105,108,100,114,101,110,1,119,6,105,80,115,106,50,65,33,0,195,133,217,18,32,4,100,97,116,97,1,40,0,195,133,217,18,32,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,32,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,105,80,115,106,50,65,0,200,195,133,217,18,15,195,133,217,18,30,1,119,6,69,79,113,57,79,119,4,0,195,133,217,18,31,6,232,191,155,233,151,168,161,195,133,217,18,37,1,39,0,147,128,159,145,14,4,6,95,56,78,114,97,97,2,39,0,147,128,159,145,14,1,6,86,73,50,122,54,78,1,40,0,195,133,217,18,46,2,105,100,1,119,6,86,73,50,122,54,78,40,0,195,133,217,18,46,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,195,133,217,18,46,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,46,8,99,104,105,108,100,114,101,110,1,119,6,56,118,75,112,112,71,33,0,195,133,217,18,46,4,100,97,116,97,1,40,0,195,133,217,18,46,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,46,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,56,118,75,112,112,71,0,136,195,133,217,18,30,1,119,6,86,73,50,122,54,78,168,195,133,217,18,44,1,119,47,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,232,191,155,233,151,168,34,125,93,44,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,4,0,195,133,217,18,45,9,229,147,136,229,147,136,229,147,136,161,195,133,217,18,51,1,39,0,147,128,159,145,14,4,6,82,119,103,79,71,104,2,33,0,147,128,159,145,14,1,6,57,82,83,84,76,77,1,0,7,33,0,147,128,159,145,14,3,6,51,85,73,116,84,78,1,129,195,133,217,18,55,1,168,195,133,217,18,60,1,119,50,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,147,136,229,147,136,229,147,136,34,125,93,44,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,125,39,0,147,128,159,145,14,4,6,114,77,45,67,67,70,2,39,0,147,128,159,145,14,1,6,112,116,116,106,121,52,1,40,0,195,133,217,18,74,2,105,100,1,119,6,112,116,116,106,121,52,40,0,195,133,217,18,74,2,116,121,1,119,9,116,111,100,111,95,108,105,115,116,40,0,195,133,217,18,74,6,112,97,114,101,110,116,1,119,6,86,73,50,122,54,78,40,0,195,133,217,18,74,8,99,104,105,108,100,114,101,110,1,119,6,110,57,101,88,110,75,33,0,195,133,217,18,74,4,100,97,116,97,1,40,0,195,133,217,18,74,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,74,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,110,57,101,88,110,75,0,8,0,195,133,217,18,54,1,119,6,112,116,116,106,121,52,4,0,195,133,217,18,73,12,229,129,165,229,186,183,233,130,163,232,190,185,161,195,133,217,18,79,1,39,0,147,128,159,145,14,4,6,79,86,73,85,113,85,2,33,0,147,128,159,145,14,1,6,55,90,111,73,74,109,1,0,7,33,0,147,128,159,145,14,3,6,117,57,107,50,68,78,1,129,195,133,217,18,71,1,39,0,147,128,159,145,14,4,6,85,111,95,84,114,107,2,4,0,195,133,217,18,100,11,49,50,51,32,36,32,32,101,114,32,32,39,0,147,128,159,145,14,4,6,99,102,56,95,106,100,2,4,0,195,133,217,18,112,3,49,50,51,39,0,147,128,159,145,14,4,6,53,87,72,110,88,75,2,4,0,195,133,217,18,116,19,99,104,101,99,107,101,100,32,116,111,100,111,32,108,105,115,116,32,36,39,0,147,128,159,145,14,4,6,45,107,95,95,66,113,2,39,0,147,128,159,145,14,4,6,95,67,82,55,75,53,2,4,0,195,133,217,18,137,1,180,1,108,111,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,76,101,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,39,0,147,128,159,145,14,4,6,122,79,53,86,113,78,2,39,0,147,128,159,145,14,4,6,50,51,68,78,97,74,2,4,0,195,133,217,18,191,2,4,119,105,116,104,39,0,147,128,159,145,14,4,6,95,56,114,66,75,71,2,39,0,147,128,159,145,14,4,6,67,54,45,78,116,106,2,4,0,195,133,217,18,197,2,11,229,144,140,228,184,128,228,184,170,110,105,39,0,147,128,159,145,14,4,6,120,83,103,122,75,55,2,4,0,195,133,217,18,203,2,55,67,108,105,99,107,32,97,110,121,119,104,101,114,101,32,97,110,100,32,106,117,115,116,32,115,116,97,114,116,32,116,121,112,105,110,103,229,147,136,229,147,136,229,147,136,46,229,176,177,229,135,160,229,174,182,39,0,147,128,159,145,14,4,6,53,118,101,50,119,103,2,39,0,147,128,159,145,14,4,6,84,86,66,74,86,72,2,6,0,195,133,217,18,248,2,8,98,103,95,99,111,108,111,114,12,34,48,120,98,51,102,102,101,98,51,98,34,132,195,133,217,18,249,2,10,72,105,103,104,108,105,103,104,116,32,134,195,133,217,18,131,3,8,98,103,95,99,111,108,111,114,4,110,117,108,108,132,195,133,217,18,132,3,38,97,110,121,32,116,101,120,116,44,32,97,110,100,32,117,115,101,32,116,104,101,32,101,100,105,116,105,110,103,32,109,101,110,117,32,116,111,32,134,195,133,217,18,170,3,6,105,116,97,108,105,99,4,116,114,117,101,132,195,133,217,18,171,3,5,115,116,121,108,101,134,195,133,217,18,176,3,6,105,116,97,108,105,99,4,110,117,108,108,132,195,133,217,18,177,3,1,32,134,195,133,217,18,178,3,4,98,111,108,100,4,116,114,117,101,132,195,133,217,18,179,3,4,121,111,117,114,134,195,133,217,18,183,3,4,98,111,108,100,4,110,117,108,108,132,195,133,217,18,184,3,1,32,134,195,133,217,18,185,3,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,132,195,133,217,18,186,3,7,119,114,105,116,105,110,103,134,195,133,217,18,193,3,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,132,195,133,217,18,194,3,1,32,134,195,133,217,18,195,3,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,196,3,7,104,111,119,101,118,101,114,134,195,133,217,18,203,3,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,204,3,5,32,121,111,117,32,134,195,133,217,18,209,3,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,132,195,133,217,18,210,3,5,108,105,107,101,46,134,195,133,217,18,215,3,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,39,0,147,128,159,145,14,4,6,109,119,113,108,50,67,2,39,0,147,128,159,145,14,4,6,67,82,79,71,73,119,2,4,0,195,133,217,18,218,3,20,65,115,32,115,111,111,110,32,97,115,32,121,111,117,32,116,121,112,101,32,134,195,133,217,18,238,3,10,102,111,110,116,95,99,111,108,111,114,11,34,48,120,49,48,48,98,53,102,102,34,132,195,133,217,18,239,3,1,47,134,195,133,217,18,240,3,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,132,195,133,217,18,241,3,28,32,97,32,109,101,110,117,32,119,105,108,108,32,112,111,112,32,117,112,46,32,83,101,108,101,99,116,32,134,195,133,217,18,141,4,8,98,103,95,99,111,108,111,114,12,34,48,120,98,51,57,99,50,55,98,48,34,132,195,133,217,18,142,4,15,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,134,195,133,217,18,157,4,8,98,103,95,99,111,108,111,114,4,110,117,108,108,132,195,133,217,18,158,4,31,32,111,102,32,99,111,110,116,101,110,116,32,98,108,111,99,107,115,32,121,111,117,32,99,97,110,32,97,100,100,46,39,0,147,128,159,145,14,4,6,53,72,118,84,75,51,2,39,0,147,128,159,145,14,4,6,90,79,118,81,105,51,2,4,0,195,133,217,18,191,4,5,84,121,112,101,32,134,195,133,217,18,196,4,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,197,4,1,47,134,195,133,217,18,198,4,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,199,4,13,32,102,111,108,108,111,119,101,100,32,98,121,32,134,195,133,217,18,212,4,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,213,4,7,47,98,117,108,108,101,116,134,195,133,217,18,220,4,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,221,4,4,32,111,114,32,134,195,133,217,18,225,4,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,226,4,22,47,110,117,109,32,116,111,32,99,114,101,97,116,101,32,97,32,108,105,115,116,46,134,195,133,217,18,248,4,4,99,111,100,101,4,110,117,108,108,39,0,147,128,159,145,14,4,6,79,90,115,66,78,49,2,39,0,147,128,159,145,14,4,6,81,116,69,74,118,51,2,4,0,195,133,217,18,251,4,6,67,108,105,99,107,32,134,195,133,217,18,129,5,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,130,5,11,43,32,78,101,119,32,80,97,103,101,32,134,195,133,217,18,141,5,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,142,5,50,98,117,116,116,111,110,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,111,102,32,121,111,117,114,32,115,105,100,101,98,97,114,32,116,111,32,97,100,100,32,97,32,110,101,119,32,134,195,133,217,18,192,5,4,98,111,108,100,4,116,114,117,101,132,195,133,217,18,193,5,4,112,97,103,101,134,195,133,217,18,197,5,4,98,111,108,100,4,110,117,108,108,132,195,133,217,18,198,5,1,46,39,0,147,128,159,145,14,4,6,84,100,107,119,102,104,2,39,0,147,128,159,145,14,4,6,90,70,108,73,71,121,2,4,0,195,133,217,18,201,5,6,67,108,105,99,107,32,134,195,133,217,18,207,5,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,208,5,1,43,134,195,133,217,18,209,5,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,210,5,1,32,134,195,133,217,18,211,5,10,102,111,110,116,95,99,111,108,111,114,11,34,48,120,49,100,98,51,54,51,54,34,134,195,133,217,18,212,5,8,98,103,95,99,111,108,111,114,11,34,48,120,49,102,102,100,97,101,54,34,132,195,133,217,18,213,5,4,110,101,120,116,134,195,133,217,18,217,5,8,98,103,95,99,111,108,111,114,4,110,117,108,108,134,195,133,217,18,218,5,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,132,195,133,217,18,219,5,37,32,116,111,32,97,110,121,32,112,97,103,101,32,116,105,116,108,101,32,105,110,32,116,104,101,32,115,105,100,101,98,97,114,32,116,111,32,134,195,133,217,18,128,6,10,102,111,110,116,95,99,111,108,111,114,11,34,48,120,49,56,52,50,55,101,48,34,132,195,133,217,18,129,6,7,113,117,105,99,107,108,121,134,195,133,217,18,136,6,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,132,195,133,217,18,137,6,1,32,134,195,133,217,18,138,6,6,105,116,97,108,105,99,4,116,114,117,101,134,195,133,217,18,139,6,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,134,195,133,217,18,140,6,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,132,195,133,217,18,141,6,9,230,140,168,233,161,191,230,137,147,134,195,133,217,18,144,6,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,134,195,133,217,18,145,6,6,105,116,97,108,105,99,4,110,117,108,108,134,195,133,217,18,146,6,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,132,195,133,217,18,147,6,16,32,97,32,110,101,119,32,115,117,98,112,97,103,101,44,32,134,195,133,217,18,163,6,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,164,6,32,68,111,99,117,109,101,110,116,44,32,71,114,105,100,44,32,111,114,32,75,97,110,98,97,110,32,66,111,97,114,100,46,134,195,133,217,18,196,6,4,99,111,100,101,4,110,117,108,108,39,0,147,128,159,145,14,4,6,51,55,75,112,109,74,2,39,0,147,128,159,145,14,4,6,114,49,67,51,121,66,2,4,0,195,133,217,18,199,6,6,228,189,147,233,170,140,134,195,133,217,18,201,6,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,116,114,117,101,134,195,133,217,18,202,6,9,117,110,100,101,114,108,105,110,101,4,116,114,117,101,132,195,133,217,18,203,6,3,228,184,128,134,195,133,217,18,204,6,9,117,110,100,101,114,108,105,110,101,4,110,117,108,108,134,195,133,217,18,205,6,13,115,116,114,105,107,101,116,104,114,111,117,103,104,4,110,117,108,108,39,0,147,128,159,145,14,4,6,104,48,112,77,45,68,2,4,0,195,133,217,18,207,6,6,231,155,145,230,142,167,39,0,147,128,159,145,14,4,6,88,85,57,77,122,75,2,4,0,195,133,217,18,210,6,13,103,104,104,104,229,143,145,230,140,165,229,165,189,39,0,147,128,159,145,14,4,6,88,101,101,105,77,89,2,4,0,195,133,217,18,218,6,4,54,54,54,57,39,0,147,128,159,145,14,4,6,111,121,69,56,121,53,2,4,0,195,133,217,18,223,6,4,240,159,152,131,39,0,147,128,159,145,14,4,6,80,69,50,72,56,68,2,4,0,195,133,217,18,226,6,12,229,185,178,230,180,187,229,147,136,229,147,136,39,0,147,128,159,145,14,4,6,72,80,78,114,99,102,2,6,0,195,133,217,18,231,6,8,98,103,95,99,111,108,111,114,11,34,48,120,49,97,55,100,102,52,97,34,134,195,133,217,18,232,6,10,102,111,110,116,95,99,111,108,111,114,11,34,48,120,49,101,97,56,102,48,54,34,132,195,133,217,18,233,6,4,54,54,54,57,134,195,133,217,18,237,6,10,102,111,110,116,95,99,111,108,111,114,4,110,117,108,108,134,195,133,217,18,238,6,8,98,103,95,99,111,108,111,114,4,110,117,108,108,39,0,147,128,159,145,14,4,6,55,81,111,111,73,112,2,39,0,147,128,159,145,14,4,6,120,117,78,48,102,83,2,4,0,195,133,217,18,241,6,44,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,44,32,109,97,114,107,100,111,119,110,44,32,97,110,100,32,99,111,100,101,32,98,108,111,99,107,39,0,147,128,159,145,14,4,6,108,107,118,90,121,113,2,4,0,195,133,217,18,158,7,19,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,32,134,195,133,217,18,177,7,4,104,114,101,102,68,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,115,104,111,114,116,99,117,116,115,34,132,195,133,217,18,178,7,5,103,117,105,100,101,134,195,133,217,18,183,7,4,104,114,101,102,4,110,117,108,108,39,0,147,128,159,145,14,4,6,97,50,90,104,55,55,2,4,0,195,133,217,18,185,7,9,77,97,114,107,100,111,119,110,32,134,195,133,217,18,194,7,4,104,114,101,102,67,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,109,97,114,107,100,111,119,110,34,132,195,133,217,18,195,7,9,114,101,102,101,114,101,110,99,101,134,195,133,217,18,204,7,4,104,114,101,102,4,110,117,108,108,39,0,147,128,159,145,14,4,6,122,122,70,106,54,119,2,4,0,195,133,217,18,206,7,3,105,106,106,39,0,147,128,159,145,14,4,6,72,85,89,49,86,115,2,4,0,195,133,217,18,210,7,4,106,107,110,98,39,0,147,128,159,145,14,4,6,102,79,45,120,115,55,2,4,0,195,133,217,18,215,7,12,232,191,155,230,173,165,230,156,186,228,188,154,39,0,147,128,159,145,14,4,6,51,110,110,101,106,112,2,4,0,195,133,217,18,220,7,12,230,150,164,230,150,164,232,174,161,232,190,131,39,0,147,128,159,145,14,4,6,109,54,68,111,117,70,2,4,0,195,133,217,18,225,7,5,84,121,112,101,32,134,195,133,217,18,230,7,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,231,7,28,47,99,111,100,101,32,116,111,32,105,110,115,101,114,116,32,97,32,99,111,100,101,32,98,108,111,99,107,134,195,133,217,18,131,8,4,99,111,100,101,4,110,117,108,108,39,0,147,128,159,145,14,4,6,51,119,76,72,119,80,2,4,0,195,133,217,18,133,8,13,98,117,108,108,101,116,101,100,32,108,105,115,116,39,0,147,128,159,145,14,4,6,73,57,55,106,83,103,2,4,0,195,133,217,18,147,8,7,99,104,105,108,100,45,49,39,0,147,128,159,145,14,4,6,114,55,104,73,74,95,2,4,0,195,133,217,18,155,8,9,99,104,105,108,100,45,49,45,49,39,0,147,128,159,145,14,4,6,53,74,52,110,52,56,2,4,0,195,133,217,18,165,8,9,99,104,105,108,100,45,49,45,50,39,0,147,128,159,145,14,4,6,82,105,78,75,118,55,2,4,0,195,133,217,18,175,8,7,99,104,105,108,100,45,50,39,0,147,128,159,145,14,4,6,57,119,57,113,66,45,2,4,0,195,133,217,18,183,8,3,49,50,51,39,0,147,128,159,145,14,4,6,84,81,109,75,119,97,2,4,0,195,133,217,18,187,8,18,72,97,118,101,32,97,32,113,117,101,115,116,105,111,110,226,157,147,39,0,147,128,159,145,14,4,6,50,83,115,67,101,65,2,4,0,195,133,217,18,204,8,6,67,108,105,99,107,32,134,195,133,217,18,210,8,4,99,111,100,101,4,116,114,117,101,132,195,133,217,18,211,8,1,63,134,195,133,217,18,212,8,4,99,111,100,101,4,110,117,108,108,132,195,133,217,18,213,8,42,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,114,105,103,104,116,32,102,111,114,32,104,101,108,112,32,97,110,100,32,115,117,112,112,111,114,116,46,39,0,147,128,159,145,14,1,6,118,71,89,57,89,100,1,40,0,195,133,217,18,128,9,2,105,100,1,119,6,118,71,89,57,89,100,40,0,195,133,217,18,128,9,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,195,133,217,18,128,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,128,9,8,99,104,105,108,100,114,101,110,1,119,6,122,55,68,52,54,115,40,0,195,133,217,18,128,9,4,100,97,116,97,1,119,46,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,51,32,36,32,32,101,114,32,32,34,125,93,44,34,108,101,118,101,108,34,58,50,125,40,0,195,133,217,18,128,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,128,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,122,55,68,52,54,115,0,200,195,133,217,18,71,195,133,217,18,99,1,119,6,118,71,89,57,89,100,39,0,147,128,159,145,14,1,6,115,45,78,113,116,119,1,40,0,195,133,217,18,138,9,2,105,100,1,119,6,115,45,78,113,116,119,40,0,195,133,217,18,138,9,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,195,133,217,18,138,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,138,9,8,99,104,105,108,100,114,101,110,1,119,6,85,65,51,119,110,54,40,0,195,133,217,18,138,9,4,100,97,116,97,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,51,34,125,93,44,34,108,101,118,101,108,34,58,51,125,40,0,195,133,217,18,138,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,138,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,85,65,51,119,110,54,0,200,195,133,217,18,137,9,195,133,217,18,99,1,119,6,115,45,78,113,116,119,39,0,147,128,159,145,14,1,6,75,55,102,84,65,65,1,40,0,195,133,217,18,148,9,2,105,100,1,119,6,75,55,102,84,65,65,40,0,195,133,217,18,148,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,148,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,148,9,8,99,104,105,108,100,114,101,110,1,119,6,88,112,113,70,83,99,40,0,195,133,217,18,148,9,4,100,97,116,97,1,119,44,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,101,99,107,101,100,32,116,111,100,111,32,108,105,115,116,32,36,34,125,93,125,40,0,195,133,217,18,148,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,148,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,88,112,113,70,83,99,0,200,195,133,217,18,147,9,195,133,217,18,99,1,119,6,75,55,102,84,65,65,39,0,147,128,159,145,14,1,6,113,84,87,120,77,103,1,40,0,195,133,217,18,158,9,2,105,100,1,119,6,113,84,87,120,77,103,40,0,195,133,217,18,158,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,158,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,158,9,8,99,104,105,108,100,114,101,110,1,119,6,115,116,70,77,88,66,40,0,195,133,217,18,158,9,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,158,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,158,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,115,116,70,77,88,66,0,200,195,133,217,18,157,9,195,133,217,18,99,1,119,6,113,84,87,120,77,103,39,0,147,128,159,145,14,1,6,79,116,113,105,98,55,1,40,0,195,133,217,18,168,9,2,105,100,1,119,6,79,116,113,105,98,55,40,0,195,133,217,18,168,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,168,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,168,9,8,99,104,105,108,100,114,101,110,1,119,6,53,56,45,56,70,76,40,0,195,133,217,18,168,9,4,100,97,116,97,1,119,205,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,108,111,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,76,101,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,110,103,32,116,101,120,116,34,125,93,125,40,0,195,133,217,18,168,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,168,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,53,56,45,56,70,76,0,200,195,133,217,18,167,9,195,133,217,18,99,1,119,6,79,116,113,105,98,55,39,0,147,128,159,145,14,1,6,120,87,45,65,56,86,1,40,0,195,133,217,18,178,9,2,105,100,1,119,6,120,87,45,65,56,86,40,0,195,133,217,18,178,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,178,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,178,9,8,99,104,105,108,100,114,101,110,1,119,6,103,84,78,70,76,73,40,0,195,133,217,18,178,9,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,178,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,178,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,103,84,78,70,76,73,0,200,195,133,217,18,177,9,195,133,217,18,99,1,119,6,120,87,45,65,56,86,39,0,147,128,159,145,14,1,6,112,109,117,76,121,114,1,40,0,195,133,217,18,188,9,2,105,100,1,119,6,112,109,117,76,121,114,40,0,195,133,217,18,188,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,188,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,188,9,8,99,104,105,108,100,114,101,110,1,119,6,100,121,111,70,45,65,40,0,195,133,217,18,188,9,4,100,97,116,97,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,119,105,116,104,34,125,93,125,40,0,195,133,217,18,188,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,188,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,100,121,111,70,45,65,0,200,195,133,217,18,187,9,195,133,217,18,99,1,119,6,112,109,117,76,121,114,39,0,147,128,159,145,14,1,6,88,87,120,55,57,115,1,40,0,195,133,217,18,198,9,2,105,100,1,119,6,88,87,120,55,57,115,40,0,195,133,217,18,198,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,198,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,198,9,8,99,104,105,108,100,114,101,110,1,119,6,88,67,102,53,75,117,40,0,195,133,217,18,198,9,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,198,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,198,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,88,67,102,53,75,117,0,200,195,133,217,18,197,9,195,133,217,18,99,1,119,6,88,87,120,55,57,115,39,0,147,128,159,145,14,1,6,87,50,72,99,77,83,1,40,0,195,133,217,18,208,9,2,105,100,1,119,6,87,50,72,99,77,83,40,0,195,133,217,18,208,9,2,116,121,1,119,5,113,117,111,116,101,40,0,195,133,217,18,208,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,208,9,8,99,104,105,108,100,114,101,110,1,119,6,76,82,68,50,65,86,40,0,195,133,217,18,208,9,4,100,97,116,97,1,119,36,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,144,140,228,184,128,228,184,170,110,105,34,125,93,125,40,0,195,133,217,18,208,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,208,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,76,82,68,50,65,86,0,200,195,133,217,18,207,9,195,133,217,18,99,1,119,6,87,50,72,99,77,83,39,0,147,128,159,145,14,1,6,114,45,105,49,57,106,1,40,0,195,133,217,18,218,9,2,105,100,1,119,6,114,45,105,49,57,106,40,0,195,133,217,18,218,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,218,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,218,9,8,99,104,105,108,100,114,101,110,1,119,6,76,97,68,83,112,65,40,0,195,133,217,18,218,9,4,100,97,116,97,1,119,80,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,97,110,121,119,104,101,114,101,32,97,110,100,32,106,117,115,116,32,115,116,97,114,116,32,116,121,112,105,110,103,229,147,136,229,147,136,229,147,136,46,229,176,177,229,135,160,229,174,182,34,125,93,125,40,0,195,133,217,18,218,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,218,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,76,97,68,83,112,65,0,200,195,133,217,18,217,9,195,133,217,18,99,1,119,6,114,45,105,49,57,106,39,0,147,128,159,145,14,1,6,45,77,89,115,65,114,1,40,0,195,133,217,18,228,9,2,105,100,1,119,6,45,77,89,115,65,114,40,0,195,133,217,18,228,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,228,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,228,9,8,99,104,105,108,100,114,101,110,1,119,6,70,122,111,65,105,114,40,0,195,133,217,18,228,9,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,228,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,228,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,70,122,111,65,105,114,0,200,195,133,217,18,227,9,195,133,217,18,99,1,119,6,45,77,89,115,65,114,39,0,147,128,159,145,14,1,6,53,99,99,77,84,71,1,40,0,195,133,217,18,238,9,2,105,100,1,119,6,53,99,99,77,84,71,40,0,195,133,217,18,238,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,238,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,238,9,8,99,104,105,108,100,114,101,110,1,119,6,105,85,97,67,74,107,40,0,195,133,217,18,238,9,4,100,97,116,97,1,119,183,3,123,34,100,101,108,116,97,34,58,91,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,98,51,102,102,101,98,51,98,34,125,44,34,105,110,115,101,114,116,34,58,34,72,105,103,104,108,105,103,104,116,32,34,125,44,123,34,105,110,115,101,114,116,34,58,34,97,110,121,32,116,101,120,116,44,32,97,110,100,32,117,115,101,32,116,104,101,32,101,100,105,116,105,110,103,32,109,101,110,117,32,116,111,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,105,116,97,108,105,99,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,115,116,121,108,101,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,111,108,100,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,121,111,117,114,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,117,110,100,101,114,108,105,110,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,119,114,105,116,105,110,103,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,104,111,119,101,118,101,114,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,121,111,117,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,115,116,114,105,107,101,116,104,114,111,117,103,104,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,108,105,107,101,46,34,125,93,125,40,0,195,133,217,18,238,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,238,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,105,85,97,67,74,107,0,200,195,133,217,18,237,9,195,133,217,18,99,1,119,6,53,99,99,77,84,71,39,0,147,128,159,145,14,1,6,57,88,75,76,69,115,1,40,0,195,133,217,18,248,9,2,105,100,1,119,6,57,88,75,76,69,115,40,0,195,133,217,18,248,9,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,248,9,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,248,9,8,99,104,105,108,100,114,101,110,1,119,6,82,116,101,71,70,116,40,0,195,133,217,18,248,9,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,248,9,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,248,9,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,82,116,101,71,70,116,0,200,195,133,217,18,247,9,195,133,217,18,99,1,119,6,57,88,75,76,69,115,39,0,147,128,159,145,14,1,6,45,99,53,69,50,113,1,40,0,195,133,217,18,130,10,2,105,100,1,119,6,45,99,53,69,50,113,40,0,195,133,217,18,130,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,130,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,130,10,8,99,104,105,108,100,114,101,110,1,119,6,90,52,77,78,84,95,40,0,195,133,217,18,130,10,4,100,97,116,97,1,119,255,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,65,115,32,115,111,111,110,32,97,115,32,121,111,117,32,116,121,112,101,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,49,48,48,98,53,102,102,34,125,44,34,105,110,115,101,114,116,34,58,34,47,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,97,32,109,101,110,117,32,119,105,108,108,32,112,111,112,32,117,112,46,32,83,101,108,101,99,116,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,98,51,57,99,50,55,98,48,34,125,44,34,105,110,115,101,114,116,34,58,34,100,105,102,102,101,114,101,110,116,32,116,121,112,101,115,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,111,102,32,99,111,110,116,101,110,116,32,98,108,111,99,107,115,32,121,111,117,32,99,97,110,32,97,100,100,46,34,125,93,125,40,0,195,133,217,18,130,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,130,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,90,52,77,78,84,95,0,200,195,133,217,18,129,10,195,133,217,18,99,1,119,6,45,99,53,69,50,113,39,0,147,128,159,145,14,1,6,108,73,53,65,67,48,1,40,0,195,133,217,18,140,10,2,105,100,1,119,6,108,73,53,65,67,48,40,0,195,133,217,18,140,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,140,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,140,10,8,99,104,105,108,100,114,101,110,1,119,6,57,86,108,107,82,87,40,0,195,133,217,18,140,10,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,140,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,140,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,57,86,108,107,82,87,0,200,195,133,217,18,139,10,195,133,217,18,99,1,119,6,108,73,53,65,67,48,39,0,147,128,159,145,14,1,6,115,98,73,99,106,103,1,40,0,195,133,217,18,150,10,2,105,100,1,119,6,115,98,73,99,106,103,40,0,195,133,217,18,150,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,150,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,150,10,8,99,104,105,108,100,114,101,110,1,119,6,56,119,111,119,68,50,40,0,195,133,217,18,150,10,4,100,97,116,97,1,119,228,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,84,121,112,101,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,47,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,102,111,108,108,111,119,101,100,32,98,121,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,47,98,117,108,108,101,116,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,111,114,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,47,110,117,109,32,116,111,32,99,114,101,97,116,101,32,97,32,108,105,115,116,46,34,125,93,125,40,0,195,133,217,18,150,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,150,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,56,119,111,119,68,50,0,200,195,133,217,18,149,10,195,133,217,18,99,1,119,6,115,98,73,99,106,103,39,0,147,128,159,145,14,1,6,65,72,89,121,80,85,1,40,0,195,133,217,18,160,10,2,105,100,1,119,6,65,72,89,121,80,85,40,0,195,133,217,18,160,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,160,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,160,10,8,99,104,105,108,100,114,101,110,1,119,6,70,68,79,70,76,77,40,0,195,133,217,18,160,10,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,160,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,160,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,70,68,79,70,76,77,0,200,195,133,217,18,159,10,195,133,217,18,99,1,119,6,65,72,89,121,80,85,39,0,147,128,159,145,14,1,6,72,110,55,49,119,97,1,40,0,195,133,217,18,170,10,2,105,100,1,119,6,72,110,55,49,119,97,40,0,195,133,217,18,170,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,170,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,170,10,8,99,104,105,108,100,114,101,110,1,119,6,80,55,68,49,81,54,40,0,195,133,217,18,170,10,4,100,97,116,97,1,119,207,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,43,32,78,101,119,32,80,97,103,101,32,34,125,44,123,34,105,110,115,101,114,116,34,58,34,98,117,116,116,111,110,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,111,102,32,121,111,117,114,32,115,105,100,101,98,97,114,32,116,111,32,97,100,100,32,97,32,110,101,119,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,111,108,100,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,112,97,103,101,34,125,44,123,34,105,110,115,101,114,116,34,58,34,46,34,125,93,125,40,0,195,133,217,18,170,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,170,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,80,55,68,49,81,54,0,200,195,133,217,18,169,10,195,133,217,18,99,1,119,6,72,110,55,49,119,97,39,0,147,128,159,145,14,1,6,56,120,67,119,110,83,1,40,0,195,133,217,18,180,10,2,105,100,1,119,6,56,120,67,119,110,83,40,0,195,133,217,18,180,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,180,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,180,10,8,99,104,105,108,100,114,101,110,1,119,6,114,116,113,68,113,100,40,0,195,133,217,18,180,10,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,180,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,180,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,114,116,113,68,113,100,0,200,195,133,217,18,179,10,195,133,217,18,99,1,119,6,56,120,67,119,110,83,39,0,147,128,159,145,14,1,6,67,79,113,95,50,67,1,40,0,195,133,217,18,190,10,2,105,100,1,119,6,67,79,113,95,50,67,40,0,195,133,217,18,190,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,190,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,190,10,8,99,104,105,108,100,114,101,110,1,119,6,109,54,56,82,52,55,40,0,195,133,217,18,190,10,4,100,97,116,97,1,119,233,3,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,43,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,49,102,102,100,97,101,54,34,44,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,49,100,98,51,54,51,54,34,125,44,34,105,110,115,101,114,116,34,58,34,110,101,120,116,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,116,111,32,97,110,121,32,112,97,103,101,32,116,105,116,108,101,32,105,110,32,116,104,101,32,115,105,100,101,98,97,114,32,116,111,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,49,56,52,50,55,101,48,34,125,44,34,105,110,115,101,114,116,34,58,34,113,117,105,99,107,108,121,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,105,116,97,108,105,99,34,58,116,114,117,101,44,34,115,116,114,105,107,101,116,104,114,111,117,103,104,34,58,116,114,117,101,44,34,117,110,100,101,114,108,105,110,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,230,140,168,233,161,191,230,137,147,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,97,32,110,101,119,32,115,117,98,112,97,103,101,44,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,68,111,99,117,109,101,110,116,44,32,71,114,105,100,44,32,111,114,32,75,97,110,98,97,110,32,66,111,97,114,100,46,34,125,93,125,40,0,195,133,217,18,190,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,190,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,109,54,56,82,52,55,0,200,195,133,217,18,189,10,195,133,217,18,99,1,119,6,67,79,113,95,50,67,39,0,147,128,159,145,14,1,6,114,71,120,87,45,114,1,40,0,195,133,217,18,200,10,2,105,100,1,119,6,114,71,120,87,45,114,40,0,195,133,217,18,200,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,200,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,200,10,8,99,104,105,108,100,114,101,110,1,119,6,112,82,70,53,54,68,40,0,195,133,217,18,200,10,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,200,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,200,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,112,82,70,53,54,68,0,200,195,133,217,18,199,10,195,133,217,18,99,1,119,6,114,71,120,87,45,114,39,0,147,128,159,145,14,1,6,102,48,55,89,71,81,1,40,0,195,133,217,18,210,10,2,105,100,1,119,6,102,48,55,89,71,81,40,0,195,133,217,18,210,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,210,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,210,10,8,99,104,105,108,100,114,101,110,1,119,6,78,56,98,56,111,65,40,0,195,133,217,18,210,10,4,100,97,116,97,1,119,101,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,228,189,147,233,170,140,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,115,116,114,105,107,101,116,104,114,111,117,103,104,34,58,116,114,117,101,44,34,117,110,100,101,114,108,105,110,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,228,184,128,34,125,93,125,40,0,195,133,217,18,210,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,210,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,78,56,98,56,111,65,0,200,195,133,217,18,209,10,195,133,217,18,99,1,119,6,102,48,55,89,71,81,39,0,147,128,159,145,14,1,6,68,73,122,109,100,87,1,40,0,195,133,217,18,220,10,2,105,100,1,119,6,68,73,122,109,100,87,40,0,195,133,217,18,220,10,2,116,121,1,119,5,113,117,111,116,101,40,0,195,133,217,18,220,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,220,10,8,99,104,105,108,100,114,101,110,1,119,6,55,114,82,118,114,89,40,0,195,133,217,18,220,10,4,100,97,116,97,1,119,31,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,231,155,145,230,142,167,34,125,93,125,40,0,195,133,217,18,220,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,220,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,55,114,82,118,114,89,0,200,195,133,217,18,219,10,195,133,217,18,99,1,119,6,68,73,122,109,100,87,39,0,147,128,159,145,14,1,6,88,104,87,98,66,48,1,40,0,195,133,217,18,230,10,2,105,100,1,119,6,88,104,87,98,66,48,40,0,195,133,217,18,230,10,2,116,121,1,119,5,113,117,111,116,101,40,0,195,133,217,18,230,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,230,10,8,99,104,105,108,100,114,101,110,1,119,6,69,110,114,122,69,100,40,0,195,133,217,18,230,10,4,100,97,116,97,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,103,104,104,104,229,143,145,230,140,165,229,165,189,34,125,93,125,40,0,195,133,217,18,230,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,230,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,69,110,114,122,69,100,0,200,195,133,217,18,229,10,195,133,217,18,99,1,119,6,88,104,87,98,66,48,39,0,147,128,159,145,14,1,6,117,122,54,88,89,118,1,40,0,195,133,217,18,240,10,2,105,100,1,119,6,117,122,54,88,89,118,40,0,195,133,217,18,240,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,240,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,240,10,8,99,104,105,108,100,114,101,110,1,119,6,80,72,76,53,98,110,40,0,195,133,217,18,240,10,4,100,97,116,97,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,54,54,54,57,34,125,93,125,40,0,195,133,217,18,240,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,240,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,80,72,76,53,98,110,0,200,195,133,217,18,239,10,195,133,217,18,99,1,119,6,117,122,54,88,89,118,39,0,147,128,159,145,14,1,6,51,110,100,90,103,51,1,40,0,195,133,217,18,250,10,2,105,100,1,119,6,51,110,100,90,103,51,40,0,195,133,217,18,250,10,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,250,10,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,250,10,8,99,104,105,108,100,114,101,110,1,119,6,79,120,115,115,72,77,40,0,195,133,217,18,250,10,4,100,97,116,97,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,240,159,152,131,34,125,93,125,40,0,195,133,217,18,250,10,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,250,10,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,79,120,115,115,72,77,0,200,195,133,217,18,249,10,195,133,217,18,99,1,119,6,51,110,100,90,103,51,39,0,147,128,159,145,14,1,6,110,103,95,69,109,50,1,40,0,195,133,217,18,132,11,2,105,100,1,119,6,110,103,95,69,109,50,40,0,195,133,217,18,132,11,2,116,121,1,119,5,113,117,111,116,101,40,0,195,133,217,18,132,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,132,11,8,99,104,105,108,100,114,101,110,1,119,6,102,107,66,48,107,107,40,0,195,133,217,18,132,11,4,100,97,116,97,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,185,178,230,180,187,229,147,136,229,147,136,34,125,93,125,40,0,195,133,217,18,132,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,132,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,102,107,66,48,107,107,0,200,195,133,217,18,131,11,195,133,217,18,99,1,119,6,110,103,95,69,109,50,39,0,147,128,159,145,14,1,6,102,84,86,120,101,99,1,40,0,195,133,217,18,142,11,2,105,100,1,119,6,102,84,86,120,101,99,40,0,195,133,217,18,142,11,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,142,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,142,11,8,99,104,105,108,100,114,101,110,1,119,6,99,107,80,105,100,83,40,0,195,133,217,18,142,11,4,100,97,116,97,1,119,92,123,34,100,101,108,116,97,34,58,91,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,98,103,95,99,111,108,111,114,34,58,34,48,120,49,97,55,100,102,52,97,34,44,34,102,111,110,116,95,99,111,108,111,114,34,58,34,48,120,49,101,97,56,102,48,54,34,125,44,34,105,110,115,101,114,116,34,58,34,54,54,54,57,34,125,93,125,40,0,195,133,217,18,142,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,142,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,99,107,80,105,100,83,0,200,195,133,217,18,141,11,195,133,217,18,99,1,119,6,102,84,86,120,101,99,39,0,147,128,159,145,14,1,6,111,56,70,84,77,117,1,40,0,195,133,217,18,152,11,2,105,100,1,119,6,111,56,70,84,77,117,40,0,195,133,217,18,152,11,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,152,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,152,11,8,99,104,105,108,100,114,101,110,1,119,6,108,119,100,112,111,55,40,0,195,133,217,18,152,11,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,152,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,152,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,108,119,100,112,111,55,0,200,195,133,217,18,151,11,195,133,217,18,99,1,119,6,111,56,70,84,77,117,39,0,147,128,159,145,14,1,6,82,74,81,67,50,82,1,40,0,195,133,217,18,162,11,2,105,100,1,119,6,82,74,81,67,50,82,40,0,195,133,217,18,162,11,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,195,133,217,18,162,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,162,11,8,99,104,105,108,100,114,101,110,1,119,6,119,97,87,79,66,52,40,0,195,133,217,18,162,11,4,100,97,116,97,1,119,79,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,44,32,109,97,114,107,100,111,119,110,44,32,97,110,100,32,99,111,100,101,32,98,108,111,99,107,34,125,93,44,34,108,101,118,101,108,34,58,50,125,40,0,195,133,217,18,162,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,162,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,119,97,87,79,66,52,0,200,195,133,217,18,161,11,195,133,217,18,99,1,119,6,82,74,81,67,50,82,39,0,147,128,159,145,14,1,6,117,70,54,49,55,109,1,40,0,195,133,217,18,172,11,2,105,100,1,119,6,117,70,54,49,55,109,40,0,195,133,217,18,172,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,172,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,172,11,8,99,104,105,108,100,114,101,110,1,119,6,55,118,110,77,69,78,40,0,195,133,217,18,172,11,4,100,97,116,97,1,119,154,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,75,101,121,98,111,97,114,100,32,115,104,111,114,116,99,117,116,115,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,104,114,101,102,34,58,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,115,104,111,114,116,99,117,116,115,34,125,44,34,105,110,115,101,114,116,34,58,34,103,117,105,100,101,34,125,93,125,40,0,195,133,217,18,172,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,172,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,55,118,110,77,69,78,0,200,195,133,217,18,171,11,195,133,217,18,99,1,119,6,117,70,54,49,55,109,39,0,147,128,159,145,14,1,6,76,87,83,67,73,57,1,40,0,195,133,217,18,182,11,2,105,100,1,119,6,76,87,83,67,73,57,40,0,195,133,217,18,182,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,182,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,182,11,8,99,104,105,108,100,114,101,110,1,119,6,111,67,89,117,74,57,40,0,195,133,217,18,182,11,4,100,97,116,97,1,119,147,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,77,97,114,107,100,111,119,110,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,104,114,101,102,34,58,34,104,116,116,112,115,58,47,47,97,112,112,102,108,111,119,121,46,103,105,116,98,111,111,107,46,105,111,47,100,111,99,115,47,101,115,115,101,110,116,105,97,108,45,100,111,99,117,109,101,110,116,97,116,105,111,110,47,109,97,114,107,100,111,119,110,34,125,44,34,105,110,115,101,114,116,34,58,34,114,101,102,101,114,101,110,99,101,34,125,93,125,40,0,195,133,217,18,182,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,182,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,111,67,89,117,74,57,0,200,195,133,217,18,181,11,195,133,217,18,99,1,119,6,76,87,83,67,73,57,39,0,147,128,159,145,14,1,6,110,98,54,83,103,101,1,40,0,195,133,217,18,192,11,2,105,100,1,119,6,110,98,54,83,103,101,40,0,195,133,217,18,192,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,192,11,6,112,97,114,101,110,116,1,119,6,76,87,83,67,73,57,40,0,195,133,217,18,192,11,8,99,104,105,108,100,114,101,110,1,119,6,105,87,100,115,72,89,40,0,195,133,217,18,192,11,4,100,97,116,97,1,119,28,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,105,106,106,34,125,93,125,40,0,195,133,217,18,192,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,192,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,105,87,100,115,72,89,0,8,0,195,133,217,18,190,11,1,119,6,110,98,54,83,103,101,39,0,147,128,159,145,14,1,6,77,73,113,111,117,90,1,40,0,195,133,217,18,202,11,2,105,100,1,119,6,77,73,113,111,117,90,40,0,195,133,217,18,202,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,202,11,6,112,97,114,101,110,116,1,119,6,110,98,54,83,103,101,40,0,195,133,217,18,202,11,8,99,104,105,108,100,114,101,110,1,119,6,88,65,95,122,90,115,40,0,195,133,217,18,202,11,4,100,97,116,97,1,119,29,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,106,107,110,98,34,125,93,125,40,0,195,133,217,18,202,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,202,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,88,65,95,122,90,115,0,8,0,195,133,217,18,200,11,1,119,6,77,73,113,111,117,90,39,0,147,128,159,145,14,1,6,98,112,45,97,121,53,1,40,0,195,133,217,18,212,11,2,105,100,1,119,6,98,112,45,97,121,53,40,0,195,133,217,18,212,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,212,11,6,112,97,114,101,110,116,1,119,6,77,73,113,111,117,90,40,0,195,133,217,18,212,11,8,99,104,105,108,100,114,101,110,1,119,6,73,84,120,118,112,57,40,0,195,133,217,18,212,11,4,100,97,116,97,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,232,191,155,230,173,165,230,156,186,228,188,154,34,125,93,125,40,0,195,133,217,18,212,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,212,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,73,84,120,118,112,57,0,8,0,195,133,217,18,210,11,1,119,6,98,112,45,97,121,53,39,0,147,128,159,145,14,1,6,56,121,102,112,65,112,1,40,0,195,133,217,18,222,11,2,105,100,1,119,6,56,121,102,112,65,112,40,0,195,133,217,18,222,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,222,11,6,112,97,114,101,110,116,1,119,6,77,73,113,111,117,90,40,0,195,133,217,18,222,11,8,99,104,105,108,100,114,101,110,1,119,6,45,109,54,99,76,105,40,0,195,133,217,18,222,11,4,100,97,116,97,1,119,37,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,230,150,164,230,150,164,232,174,161,232,190,131,34,125,93,125,40,0,195,133,217,18,222,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,222,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,45,109,54,99,76,105,0,136,195,133,217,18,221,11,1,119,6,56,121,102,112,65,112,39,0,147,128,159,145,14,1,6,111,109,54,99,122,66,1,40,0,195,133,217,18,232,11,2,105,100,1,119,6,111,109,54,99,122,66,40,0,195,133,217,18,232,11,2,116,121,1,119,13,110,117,109,98,101,114,101,100,95,108,105,115,116,40,0,195,133,217,18,232,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,232,11,8,99,104,105,108,100,114,101,110,1,119,6,68,82,102,101,121,118,40,0,195,133,217,18,232,11,4,100,97,116,97,1,119,99,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,84,121,112,101,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,47,99,111,100,101,32,116,111,32,105,110,115,101,114,116,32,97,32,99,111,100,101,32,98,108,111,99,107,34,125,93,125,40,0,195,133,217,18,232,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,232,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,68,82,102,101,121,118,0,200,195,133,217,18,191,11,195,133,217,18,99,1,119,6,111,109,54,99,122,66,39,0,147,128,159,145,14,1,6,65,120,74,79,67,97,1,40,0,195,133,217,18,242,11,2,105,100,1,119,6,65,120,74,79,67,97,40,0,195,133,217,18,242,11,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,195,133,217,18,242,11,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,242,11,8,99,104,105,108,100,114,101,110,1,119,6,49,52,84,74,100,51,40,0,195,133,217,18,242,11,4,100,97,116,97,1,119,38,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,98,117,108,108,101,116,101,100,32,108,105,115,116,34,125,93,125,40,0,195,133,217,18,242,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,242,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,49,52,84,74,100,51,0,200,195,133,217,18,241,11,195,133,217,18,99,1,119,6,65,120,74,79,67,97,39,0,147,128,159,145,14,1,6,48,55,67,110,83,97,1,40,0,195,133,217,18,252,11,2,105,100,1,119,6,48,55,67,110,83,97,40,0,195,133,217,18,252,11,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,195,133,217,18,252,11,6,112,97,114,101,110,116,1,119,6,65,120,74,79,67,97,40,0,195,133,217,18,252,11,8,99,104,105,108,100,114,101,110,1,119,6,89,108,74,119,83,49,40,0,195,133,217,18,252,11,4,100,97,116,97,1,119,32,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,34,125,93,125,40,0,195,133,217,18,252,11,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,252,11,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,89,108,74,119,83,49,0,8,0,195,133,217,18,250,11,1,119,6,48,55,67,110,83,97,39,0,147,128,159,145,14,1,6,95,57,76,55,68,108,1,40,0,195,133,217,18,134,12,2,105,100,1,119,6,95,57,76,55,68,108,40,0,195,133,217,18,134,12,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,195,133,217,18,134,12,6,112,97,114,101,110,116,1,119,6,48,55,67,110,83,97,40,0,195,133,217,18,134,12,8,99,104,105,108,100,114,101,110,1,119,6,68,90,49,112,114,48,40,0,195,133,217,18,134,12,4,100,97,116,97,1,119,34,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,45,49,34,125,93,125,40,0,195,133,217,18,134,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,134,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,68,90,49,112,114,48,0,8,0,195,133,217,18,132,12,1,119,6,95,57,76,55,68,108,39,0,147,128,159,145,14,1,6,118,109,65,70,53,76,1,40,0,195,133,217,18,144,12,2,105,100,1,119,6,118,109,65,70,53,76,40,0,195,133,217,18,144,12,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,195,133,217,18,144,12,6,112,97,114,101,110,116,1,119,6,48,55,67,110,83,97,40,0,195,133,217,18,144,12,8,99,104,105,108,100,114,101,110,1,119,6,118,87,53,73,57,111,40,0,195,133,217,18,144,12,4,100,97,116,97,1,119,34,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,49,45,50,34,125,93,125,40,0,195,133,217,18,144,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,144,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,118,87,53,73,57,111,0,136,195,133,217,18,143,12,1,119,6,118,109,65,70,53,76,39,0,147,128,159,145,14,1,6,121,55,78,87,55,99,1,40,0,195,133,217,18,154,12,2,105,100,1,119,6,121,55,78,87,55,99,40,0,195,133,217,18,154,12,2,116,121,1,119,13,98,117,108,108,101,116,101,100,95,108,105,115,116,40,0,195,133,217,18,154,12,6,112,97,114,101,110,116,1,119,6,65,120,74,79,67,97,40,0,195,133,217,18,154,12,8,99,104,105,108,100,114,101,110,1,119,6,79,51,103,80,85,76,40,0,195,133,217,18,154,12,4,100,97,116,97,1,119,32,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,99,104,105,108,100,45,50,34,125,93,125,40,0,195,133,217,18,154,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,154,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,79,51,103,80,85,76,0,136,195,133,217,18,133,12,1,119,6,121,55,78,87,55,99,39,0,147,128,159,145,14,1,6,83,102,48,120,100,54,1,40,0,195,133,217,18,164,12,2,105,100,1,119,6,83,102,48,120,100,54,40,0,195,133,217,18,164,12,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,164,12,6,112,97,114,101,110,116,1,119,6,65,120,74,79,67,97,40,0,195,133,217,18,164,12,8,99,104,105,108,100,114,101,110,1,119,6,78,76,97,67,89,115,33,0,195,133,217,18,164,12,4,100,97,116,97,1,40,0,195,133,217,18,164,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,164,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,78,76,97,67,89,115,0,136,195,133,217,18,163,12,1,119,6,83,102,48,120,100,54,39,0,147,128,159,145,14,1,6,54,104,67,112,68,80,1,40,0,195,133,217,18,174,12,2,105,100,1,119,6,54,104,67,112,68,80,40,0,195,133,217,18,174,12,2,116,121,1,119,7,104,101,97,100,105,110,103,40,0,195,133,217,18,174,12,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,174,12,8,99,104,105,108,100,114,101,110,1,119,6,57,77,71,74,107,73,40,0,195,133,217,18,174,12,4,100,97,116,97,1,119,53,123,34,108,101,118,101,108,34,58,50,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,72,97,118,101,32,97,32,113,117,101,115,116,105,111,110,226,157,147,34,125,93,125,40,0,195,133,217,18,174,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,174,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,57,77,71,74,107,73,0,200,195,133,217,18,251,11,195,133,217,18,99,1,119,6,54,104,67,112,68,80,39,0,147,128,159,145,14,1,6,90,68,65,45,49,122,1,40,0,195,133,217,18,184,12,2,105,100,1,119,6,90,68,65,45,49,122,40,0,195,133,217,18,184,12,2,116,121,1,119,5,113,117,111,116,101,40,0,195,133,217,18,184,12,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,184,12,8,99,104,105,108,100,114,101,110,1,119,6,122,50,122,106,95,53,40,0,195,133,217,18,184,12,4,100,97,116,97,1,119,129,1,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,67,108,105,99,107,32,34,125,44,123,34,97,116,116,114,105,98,117,116,101,115,34,58,123,34,99,111,100,101,34,58,116,114,117,101,125,44,34,105,110,115,101,114,116,34,58,34,63,34,125,44,123,34,105,110,115,101,114,116,34,58,34,32,97,116,32,116,104,101,32,98,111,116,116,111,109,32,114,105,103,104,116,32,102,111,114,32,104,101,108,112,32,97,110,100,32,115,117,112,112,111,114,116,46,34,125,93,125,40,0,195,133,217,18,184,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,184,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,122,50,122,106,95,53,0,200,195,133,217,18,183,12,195,133,217,18,99,1,119,6,90,68,65,45,49,122,39,0,147,128,159,145,14,4,6,110,66,48,103,72,72,2,4,0,195,133,217,18,194,12,15,229,129,165,229,186,183,233,130,163,232,190,185,85,73,105,168,195,133,217,18,88,1,119,56,123,34,99,104,101,99,107,101,100,34,58,102,97,108,115,101,44,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,229,129,165,229,186,183,233,130,163,232,190,185,85,73,105,34,125,93,125,39,0,147,128,159,145,14,4,6,112,119,95,118,45,79,2,33,0,147,128,159,145,14,1,6,102,77,98,109,66,116,1,0,7,33,0,147,128,159,145,14,3,6,122,104,84,113,87,83,1,129,195,133,217,18,99,1,39,0,147,128,159,145,14,1,6,69,120,118,84,102,57,1,40,0,195,133,217,18,214,12,2,105,100,1,119,6,69,120,118,84,102,57,40,0,195,133,217,18,214,12,2,116,121,1,119,5,105,109,97,103,101,40,0,195,133,217,18,214,12,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,214,12,8,99,104,105,108,100,114,101,110,1,119,6,57,87,71,65,49,95,33,0,195,133,217,18,214,12,4,100,97,116,97,1,40,0,195,133,217,18,214,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,214,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,57,87,71,65,49,95,0,200,195,133,217,18,99,195,133,217,18,213,12,1,119,6,69,120,118,84,102,57,39,0,147,128,159,145,14,4,6,119,48,80,67,108,103,2,39,0,147,128,159,145,14,1,6,102,100,85,89,106,108,1,40,0,195,133,217,18,225,12,2,105,100,1,119,6,102,100,85,89,106,108,40,0,195,133,217,18,225,12,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,225,12,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,225,12,8,99,104,105,108,100,114,101,110,1,119,6,68,107,98,56,50,87,40,0,195,133,217,18,225,12,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,225,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,225,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,68,107,98,56,50,87,0,136,195,133,217,18,213,12,1,119,6,102,100,85,89,106,108,168,195,133,217,18,219,12,1,119,212,1,123,34,117,114,108,34,58,34,104,116,116,112,115,58,47,47,105,109,97,103,101,115,46,117,110,115,112,108,97,115,104,46,99,111,109,47,112,104,111,116,111,45,49,55,49,51,48,57,56,48,57,56,56,51,51,45,102,52,53,100,49,56,48,99,97,57,97,50,63,99,114,111,112,61,101,110,116,114,111,112,121,38,99,115,61,116,105,110,121,115,114,103,98,38,102,105,116,61,109,97,120,38,102,109,61,106,112,103,38,105,120,105,100,61,77,51,119,49,77,84,69,49,77,122,100,56,77,72,119,120,102,72,74,104,98,109,82,118,98,88,120,56,102,72,120,56,102,72,120,56,102,68,69,51,77,84,77,49,78,68,73,51,78,84,74,56,38,105,120,108,105,98,61,114,98,45,52,46,48,46,51,38,113,61,56,48,38,119,61,49,48,56,48,34,44,34,97,108,105,103,110,34,58,34,99,101,110,116,101,114,34,125,39,0,147,128,159,145,14,4,6,70,80,88,99,109,117,2,39,0,147,128,159,145,14,1,6,109,99,66,107,98,115,1,40,0,195,133,217,18,237,12,2,105,100,1,119,6,109,99,66,107,98,115,40,0,195,133,217,18,237,12,2,116,121,1,119,9,112,97,114,97,103,114,97,112,104,40,0,195,133,217,18,237,12,6,112,97,114,101,110,116,1,119,10,85,86,79,107,81,88,110,117,86,114,40,0,195,133,217,18,237,12,8,99,104,105,108,100,114,101,110,1,119,6,113,49,74,97,114,53,40,0,195,133,217,18,237,12,4,100,97,116,97,1,119,12,123,34,100,101,108,116,97,34,58,91,93,125,40,0,195,133,217,18,237,12,11,101,120,116,101,114,110,97,108,95,105,100,1,126,40,0,195,133,217,18,237,12,13,101,120,116,101,114,110,97,108,95,116,121,112,101,1,126,39,0,147,128,159,145,14,3,6,113,49,74,97,114,53,0,136,195,133,217,18,234,12,1,119,6,109,99,66,107,98,115,39,0,147,128,159,145,14,4,6,66,87,74,50,81,114,2,4,0,195,133,217,18,247,12,2,49,50,168,195,133,217,18,169,12,1,119,27,123,34,100,101,108,116,97,34,58,91,123,34,105,110,115,101,114,116,34,58,34,49,50,34,125,93,125,39,0,147,128,159,145,14,4,6,116,83,114,83,65,45,2,33,0,147,128,159,145,14,1,6,118,71,79,68,118,57,1,0,7,33,0,147,128,159,145,14,3,6,66,122,109,101,85,67,1,129,195,133,217,18,173,12,1,39,0,147,128,159,145,14,4,6,56,82,84,70,84,106,2,33,0,147,128,159,145,14,1,6,100,48,101,105,48,99,1,0,7,33,0,147,128,159,145,14,3,6,55,103,88,67,83,76,1,193,195,133,217,18,251,11,195,133,217,18,183,12,1,39,0,147,128,159,145,14,4,6,86,49,69,99,77,120,2,33,0,147,128,159,145,14,1,6,57,82,76,118,75,83,1,0,7,33,0,147,128,159,145,14,3,6,100,84,102,75,114,54,1,129,195,133,217,18,133,13,1,39,0,147,128,159,145,14,4,6,95,90,85,102,102,106,2,33,0,147,128,159,145,14,1,6,78,102,79,67,79,76,1,0,7,33,0,147,128,159,145,14,3,6,66,52,111,107,80,118,1,193,195,133,217,18,144,13,195,133,217,18,183,12,1,5,200,244,136,224,7,1,0,3,178,246,186,209,6,1,0,72,147,128,159,145,14,1,11,3,195,133,217,18,17,11,1,21,10,37,1,44,1,51,1,60,1,62,10,79,1,88,1,90,10,169,12,1,204,12,10,219,12,1,252,12,10,135,13,10,146,13,10,157,13,10,156,139,194,87,1,0,3],"version":0},"code":0,"message":"Operation completed successfully."} \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/fixtures/user.json b/frontend/appflowy_web_app/cypress/fixtures/user.json new file mode 100644 index 0000000000..5b429dcd59 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/fixtures/user.json @@ -0,0 +1,17 @@ +{ + "data": { + "uid": 304120109071339520, + "uuid": "cbff060a-196d-415a-aa80-759c01886466", + "email": "lu@appflowy.io", + "password": "", + "name": "Kilu", + "metadata": { + "icon_url": "🇽🇰" + }, + "encryption_sign": null, + "latest_workspace_id": "fcb503f9-9287-4de4-8de0-ea191e680968", + "updated_at": 1710421586 + }, + "code": 0, + "message": "Operation completed successfully." +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/fixtures/verify_token.json b/frontend/appflowy_web_app/cypress/fixtures/verify_token.json new file mode 100644 index 0000000000..503838f0a6 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/fixtures/verify_token.json @@ -0,0 +1,6 @@ +{ + "code": 0, + "data": { + "is_new": false + } +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/support/commands.ts b/frontend/appflowy_web_app/cypress/support/commands.ts new file mode 100644 index 0000000000..6146bd1c01 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/support/commands.ts @@ -0,0 +1,46 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +Cypress.Commands.add('mockAPI', () => { + cy.fixture('sign_in_success').then((json) => { + cy.intercept('GET', `/api/user/verify/${json.access_token}`, { + fixture: 'verify_token', + }).as('verifyToken'); + cy.intercept('POST', '/gotrue/token?grant_type=password', json).as('loginSuccess'); + cy.intercept('POST', '/gotrue/token?grant_type=refresh_token', json).as('refreshToken'); + }); + cy.intercept('GET', '/api/user/profile', { fixture: 'user' }).as('getUserProfile'); +}); + +// Example use: +// beforeEach(() => { +// cy.mockAPI(); +// }); + diff --git a/frontend/appflowy_web_app/cypress/support/component-index.html b/frontend/appflowy_web_app/cypress/support/component-index.html new file mode 100644 index 0000000000..b8b58ae50c --- /dev/null +++ b/frontend/appflowy_web_app/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/frontend/appflowy_web_app/cypress/support/component.ts b/frontend/appflowy_web_app/cypress/support/component.ts new file mode 100644 index 0000000000..ad7f96afeb --- /dev/null +++ b/frontend/appflowy_web_app/cypress/support/component.ts @@ -0,0 +1,42 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; +import './document'; +// Alternatively you can use CommonJS syntax: +// require('./commands') + +import { mount } from 'cypress/react18'; + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + interface Chainable { + mount: typeof mount; + mockAPI: () => void; + mockFullDocument: () => void; + } + } +} + +Cypress.Commands.add('mount', mount); + +// Example use: +// cy.mount() diff --git a/frontend/appflowy_web_app/cypress/support/document.ts b/frontend/appflowy_web_app/cypress/support/document.ts new file mode 100644 index 0000000000..35a5b4ae11 --- /dev/null +++ b/frontend/appflowy_web_app/cypress/support/document.ts @@ -0,0 +1,88 @@ +import { BlockId, BlockType, YBlocks, YChildrenMap, YjsEditorKey, YTextMap } from '@/application/document.type'; +import { applyDocument } from 'src/application/ydoc/apply'; +import { JSDocumentService } from '@/application/services/js-services/document.service'; +import { nanoid } from 'nanoid'; +import * as Y from 'yjs'; + +Cypress.Commands.add('mockFullDocument', () => { + cy.fixture('full_doc').then((docJson) => { + const collab = new Y.Doc(); + const state = new Uint8Array(docJson.data.doc_state); + + applyDocument(collab, state); + + cy.stub(JSDocumentService.prototype, 'openDocument').returns(Promise.resolve(collab)); + }); +}); + +export class DocumentTest { + public doc: Y.Doc; + + private blocks: YBlocks; + + private childrenMap: YChildrenMap; + + private textMap: YTextMap; + + private pageId: string; + + constructor() { + const doc = new Y.Doc(); + + this.doc = doc; + const collab = doc.getMap(YjsEditorKey.data_section); + const document = new Y.Map(); + const blocks = new Y.Map() as YBlocks; + const pageId = nanoid(8); + const meta = new Y.Map(); + const childrenMap = new Y.Map() as YChildrenMap; + const textMap = new Y.Map() as YTextMap; + + const block = new Y.Map(); + + block.set(YjsEditorKey.block_id, pageId); + block.set(YjsEditorKey.block_type, BlockType.Page); + block.set(YjsEditorKey.block_children, pageId); + block.set(YjsEditorKey.block_external_id, pageId); + block.set(YjsEditorKey.block_external_type, YjsEditorKey.text); + block.set(YjsEditorKey.block_data, ''); + blocks.set(pageId, block); + + document.set(YjsEditorKey.page_id, pageId); + document.set(YjsEditorKey.blocks, blocks); + document.set(YjsEditorKey.meta, meta); + meta.set(YjsEditorKey.children_map, childrenMap); + meta.set(YjsEditorKey.text_map, textMap); + collab.set(YjsEditorKey.document, document); + + this.blocks = blocks; + this.childrenMap = childrenMap; + this.textMap = textMap; + this.pageId = pageId; + } + + insertParagraph(text: string) { + const blockId = nanoid(8); + const block = new Y.Map(); + + block.set(YjsEditorKey.block_id, blockId); + block.set(YjsEditorKey.block_type, BlockType.Paragraph); + block.set(YjsEditorKey.block_children, blockId); + block.set(YjsEditorKey.block_external_id, blockId); + block.set(YjsEditorKey.block_external_type, YjsEditorKey.text); + block.set(YjsEditorKey.block_parent, this.pageId); + block.set(YjsEditorKey.block_data, ''); + this.blocks.set(blockId, block); + const pageChildren = this.childrenMap.get(this.pageId) ?? new Y.Array(); + + pageChildren.push([blockId]); + this.childrenMap.set(this.pageId, pageChildren); + + const blockText = new Y.Text(); + + blockText.insert(0, text); + this.textMap.set(blockId, blockText); + + return blockText; + } +} diff --git a/frontend/appflowy_web_app/index.html b/frontend/appflowy_web_app/index.html index 5d36aaa0a1..3548e9b85d 100644 --- a/frontend/appflowy_web_app/index.html +++ b/frontend/appflowy_web_app/index.html @@ -1,16 +1,15 @@ - - - - + + + AppFlowy
+ + diff --git a/frontend/appflowy_web_app/jest.config.cjs b/frontend/appflowy_web_app/jest.config.cjs new file mode 100644 index 0000000000..0d20a53241 --- /dev/null +++ b/frontend/appflowy_web_app/jest.config.cjs @@ -0,0 +1,20 @@ +const { compilerOptions } = require('./tsconfig.json'); +const { pathsToModuleNameMapper } = require('ts-jest'); +const esModules = ['lodash-es', 'nanoid'].join('|'); + +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + roots: [''], + modulePaths: [compilerOptions.baseUrl], + moduleNameMapper: { + ...pathsToModuleNameMapper(compilerOptions.paths), + '^lodash-es(/(.*)|$)': 'lodash$1', + '^nanoid(/(.*)|$)': 'nanoid$1', + }, + 'transform': { + '(.*)/node_modules/nanoid/.+\\.(j|t)sx?$': 'ts-jest', + }, + 'transformIgnorePatterns': [`/node_modules/(?!${esModules})`], +}; \ No newline at end of file diff --git a/frontend/appflowy_web_app/nginx.conf b/frontend/appflowy_web_app/nginx.conf index a426f7faa2..56529cca1a 100644 --- a/frontend/appflowy_web_app/nginx.conf +++ b/frontend/appflowy_web_app/nginx.conf @@ -63,6 +63,19 @@ http { location / { root /usr/share/nginx/html; index index.html index.htm; + try_files $uri $uri/ /index.html; + } + + location /static/ { + root /usr/share/nginx/html; + expires 30d; + access_log off; + } + + location /appflowy.svg { + root /usr/share/nginx/html; + expires 30d; + access_log off; } error_page 404 /404.html; diff --git a/frontend/appflowy_web_app/package.json b/frontend/appflowy_web_app/package.json index 3ab82541d5..397fb90f52 100644 --- a/frontend/appflowy_web_app/package.json +++ b/frontend/appflowy_web_app/package.json @@ -5,27 +5,31 @@ "type": "module", "scripts": { "dev": "pnpm run sync:i18n && vite", - "dev:tauri": "TAURI_MODE=true pnpm run sync:i18n && vite", - "build": "vite build", - "build:tauri": "TAURI_MODE=true vite build", - "lint:tauri": "TAURI_MODE=true pnpm run sync:i18n && tsc --noEmit && eslint --ext .js,.ts,.tsx . --ignore-path .eslintignore", + "dev:tauri": "pnpm run sync:i18n && vite", + "build": "pnpm run sync:i18n && vite build", + "build:tauri": "vite build", + "lint:tauri": "pnpm run sync:i18n && tsc --noEmit && eslint --ext .js,.ts,.tsx . --ignore-path .eslintignore", "lint": "pnpm run sync:i18n && tsc --noEmit --project tsconfig.web.json && eslint --ext .js,.ts,.tsx . --ignore-path .eslintignore.web", - "preview": "vite preview --port 8080", + "start": "vite preview --port 3000", "tauri:dev": "tauri dev", "css:variables": "node style-dictionary/config.cjs", "sync:i18n": "node scripts/i18n.cjs", "link:client-api": "rm -rf node_modules/.vite && node scripts/create-symlink.cjs", - "analyze": "ANALYZE_MODE=true vite build" + "analyze": "cross-env ANALYZE_MODE=true vite build", + "cypress:open": "cypress open", + "test": "pnpm run test:unit && pnpm run test:components", + "test:components": "cypress run --component --browser chrome --headless", + "test:unit": "jest" }, "dependencies": { - "@appflowyinc/client-api-wasm": "^0.0.2", + "@appflowyinc/client-api-wasm": "0.0.2-alpha.2", + "@atlaskit/primitives": "^5.5.3", "@emoji-mart/data": "^1.1.2", "@emoji-mart/react": "^1.1.1", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@mui/icons-material": "^5.11.11", - "@mui/material": "^5.11.12", - "@mui/system": "^5.14.4", + "@mui/material": "6.0.0-alpha.2", "@mui/x-date-pickers-pro": "^6.18.2", "@reduxjs/toolkit": "2.0.0", "@slate-yjs/core": "^1.0.2", @@ -33,6 +37,7 @@ "@types/react-swipeable-views": "^0.13.4", "axios": "^1.6.8", "dayjs": "^1.11.9", + "dexie": "^4.0.1", "emoji-mart": "^5.5.2", "emoji-regex": "^10.2.1", "events": "^3.3.0", @@ -80,7 +85,8 @@ "utf8": "^3.0.0", "valtio": "^1.12.1", "vite-plugin-wasm": "^3.3.0", - "yjs": "^13.5.51" + "y-indexeddb": "9.0.12", + "yjs": "^13.6.14" }, "devDependencies": { "@svgr/plugin-svgo": "^8.0.1", @@ -110,6 +116,8 @@ "autoprefixer": "^10.4.13", "babel-jest": "^29.6.2", "chalk": "^4.1.2", + "cross-env": "^7.0.3", + "cypress": "^13.7.2", "eslint": "^8.57.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/frontend/appflowy_web_app/pnpm-lock.yaml b/frontend/appflowy_web_app/pnpm-lock.yaml index f1cc2195ee..0da4a7e4ed 100644 --- a/frontend/appflowy_web_app/pnpm-lock.yaml +++ b/frontend/appflowy_web_app/pnpm-lock.yaml @@ -1,9 +1,16 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + dependencies: '@appflowyinc/client-api-wasm': - specifier: ^0.0.2 - version: 0.0.2 + specifier: 0.0.2-alpha.2 + version: 0.0.2-alpha.2 + '@atlaskit/primitives': + specifier: ^5.5.3 + version: 5.5.3(@types/react@18.2.66)(react@18.2.0) '@emoji-mart/data': specifier: ^1.1.2 version: 1.1.2 @@ -18,22 +25,19 @@ dependencies: version: 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/icons-material': specifier: ^5.11.11 - version: 5.11.11(@mui/material@5.11.12)(@types/react@18.2.66)(react@18.2.0) + version: 5.11.11(@mui/material@6.0.0-alpha.2)(@types/react@18.2.66)(react@18.2.0) '@mui/material': - specifier: ^5.11.12 - version: 5.11.12(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': - specifier: ^5.14.4 - version: 5.14.4(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0) + specifier: 6.0.0-alpha.2 + version: 6.0.0-alpha.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) '@mui/x-date-pickers-pro': specifier: ^6.18.2 - version: 6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.12)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) + version: 6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@6.0.0-alpha.2)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) '@reduxjs/toolkit': specifier: 2.0.0 version: 2.0.0(react-redux@8.0.5)(react@18.2.0) '@slate-yjs/core': specifier: ^1.0.2 - version: 1.0.2(slate@0.101.4)(yjs@13.5.51) + version: 1.0.2(slate@0.101.4)(yjs@13.6.14) '@tauri-apps/api': specifier: ^1.5.3 version: 1.5.3 @@ -46,6 +50,9 @@ dependencies: dayjs: specifier: ^1.11.9 version: 1.11.9 + dexie: + specifier: ^4.0.1 + version: 4.0.1 emoji-mart: specifier: ^5.5.2 version: 5.5.2 @@ -187,9 +194,12 @@ dependencies: vite-plugin-wasm: specifier: ^3.3.0 version: 3.3.0(vite@5.2.0) + y-indexeddb: + specifier: 9.0.12 + version: 9.0.12(yjs@13.6.14) yjs: - specifier: ^13.5.51 - version: 13.5.51 + specifier: ^13.6.14 + version: 13.6.14 devDependencies: '@svgr/plugin-svgo': @@ -273,6 +283,12 @@ devDependencies: chalk: specifier: ^4.1.2 version: 4.1.2 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + cypress: + specifier: ^13.7.2 + version: 13.7.2 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -354,8 +370,132 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - /@appflowyinc/client-api-wasm@0.0.2: - resolution: {integrity: sha512-Y8YkH+5ZT1sVJRXpMB5eMFt5SWUeRxgIV3FEXZjl0CjWjqSAwr5wIqEX0uHdOSrLU5fTzWoolRK9oIIiHvG2SA==} + /@appflowyinc/client-api-wasm@0.0.2-alpha.2: + resolution: {integrity: sha512-BcRK06zHHJdaGNYohYxGaR2xPfQ1RwU48jMzdMZDf2HXVLU2WWQ6cYfuM4lrsK+O3QEfJdeEL2fntnQDaaeQng==} + dev: false + + /@atlaskit/analytics-next-stable-react-context@1.0.1(react@18.2.0): + resolution: {integrity: sha512-iO6+hIp09dF4iAZQarVz3vKY1kM5Ij5CExYcK9jgc2q+OH8nv8n+BPFeJTdzGOGopmbUZn5Opj9pYQvge1Gr4Q==} + peerDependencies: + react: ^16.8.0 + dependencies: + react: 18.2.0 + tslib: 2.6.2 + dev: false + + /@atlaskit/analytics-next@9.2.3(react@18.2.0): + resolution: {integrity: sha512-zTtM6xHTNNMO0dxiPrsxMko6BawEh4wN0wWSvMdQXdnusvvWNEE8rnpjn23kS4M08bYWIEstRbgoPLx6VQisug==} + peerDependencies: + react: ^16.8.0 + dependencies: + '@atlaskit/analytics-next-stable-react-context': 1.0.1(react@18.2.0) + '@atlaskit/platform-feature-flags': 0.2.5 + '@babel/runtime': 7.24.4 + prop-types: 15.8.1 + react: 18.2.0 + use-memo-one: 1.1.3(react@18.2.0) + dev: false + + /@atlaskit/app-provider@1.3.0(react@18.2.0): + resolution: {integrity: sha512-0bHfIbXyCbYjuv0zMyHPyuCcyW5IIVCBsNbYEbEl9w5P9hChPyewNrz1VkNPRQBg18DF1zxIIsNyZOEuQjvs7Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ~18.2.0 + dependencies: + '@atlaskit/tokens': 1.43.0(react@18.2.0) + '@babel/runtime': 7.24.4 + bind-event-listener: 2.1.1 + react: 18.2.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@atlaskit/css@0.1.0(react@18.2.0): + resolution: {integrity: sha512-FQfiLoYJrwTYhjSpa+RA8omPAPlJ5rl0OCJ0NAkMXRGx1o8ItNBW5EcRBwW0wUHaBOZ4oFS5EUshk185E/G/zQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ~18.2.0 + dependencies: + '@atlaskit/tokens': 1.43.0(react@18.2.0) + '@babel/runtime': 7.24.4 + '@compiled/react': 0.17.1(react@18.2.0) + react: 18.2.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@atlaskit/ds-lib@2.3.0(react@18.2.0): + resolution: {integrity: sha512-ULU9ZTVBvlQ9QUwKXhCju3/fUWT79zdX5omNYOIL3nUrAtBCPX7inNpIJ/D4Lx35O6XSWJRKuNFL5tR75FEYKQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ~18.2.0 + dependencies: + '@babel/runtime': 7.24.4 + bind-event-listener: 2.1.1 + react: 18.2.0 + dev: false + + /@atlaskit/interaction-context@2.1.4(react@18.2.0): + resolution: {integrity: sha512-MTuHN8wLYBPADE83Q+9KF5BcKyMW9/FkmA+lB/XnHwYIL86sMPzMSTM0DPG7crq/JI0JM0jlyY3Xzz0Aba7G+A==} + peerDependencies: + react: ^16.8.0 + dependencies: + '@babel/runtime': 7.24.4 + react: 18.2.0 + dev: false + + /@atlaskit/platform-feature-flags@0.2.5: + resolution: {integrity: sha512-0fD2aDxn2mE59D4acUhVib+YF2HDYuuPH50aYwpQdcV/CsVkAaJsMKy8WhWSulcRFeMYp72kfIfdy0qGdRB7Uw==} + dependencies: + '@babel/runtime': 7.24.4 + dev: false + + /@atlaskit/primitives@5.5.3(@types/react@18.2.66)(react@18.2.0): + resolution: {integrity: sha512-UnKx0N/Jeo5Z61wFm5U2OkJM3bcb1qpKUHYrxzmSVe+QfQvBbJ/U5882WMnwQYq9rqYR2NcFvRNyT8Lf/L4FRQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@atlaskit/analytics-next': 9.2.3(react@18.2.0) + '@atlaskit/app-provider': 1.3.0(react@18.2.0) + '@atlaskit/css': 0.1.0(react@18.2.0) + '@atlaskit/ds-lib': 2.3.0(react@18.2.0) + '@atlaskit/interaction-context': 2.1.4(react@18.2.0) + '@atlaskit/tokens': 1.43.0(react@18.2.0) + '@atlaskit/visually-hidden': 1.2.5(@types/react@18.2.66)(react@18.2.0) + '@babel/runtime': 7.24.4 + '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) + '@emotion/serialize': 1.1.4 + bind-event-listener: 2.1.1 + react: 18.2.0 + tiny-invariant: 1.3.3 + transitivePeerDependencies: + - '@types/react' + - supports-color + dev: false + + /@atlaskit/tokens@1.43.0(react@18.2.0): + resolution: {integrity: sha512-3rRxGRnJGQBVKGqNqy+Zuad3xuDZ7uD+aFGRcU2OpLuIpiFLX95agDZ9w0HGzNiDw9eWi2f1j8Uzq06AyaRqTw==} + peerDependencies: + react: ^16.8.0 + dependencies: + '@atlaskit/ds-lib': 2.3.0(react@18.2.0) + '@atlaskit/platform-feature-flags': 0.2.5 + '@babel/runtime': 7.24.4 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + bind-event-listener: 2.1.1 + react: 18.2.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@atlaskit/visually-hidden@1.2.5(@types/react@18.2.66)(react@18.2.0): + resolution: {integrity: sha512-khxJB6456uMS1IkwnsH0ZTYGVAnE83aoGarz388I0zPydOZdNeeEdwsRPFOn9mua88Ez+rL0OEWV22k6XRUf6A==} + peerDependencies: + react: ^16.8.0 + dependencies: + '@babel/runtime': 7.24.4 + '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) + react: 18.2.0 + transitivePeerDependencies: + - '@types/react' dev: false /@babel/code-frame@7.24.2: @@ -384,7 +524,7 @@ packages: '@babel/traverse': 7.24.1 '@babel/types': 7.24.0 convert-source-map: 2.0.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -647,6 +787,13 @@ packages: dependencies: regenerator-runtime: 0.14.1 + /@babel/runtime@7.24.4: + resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: false + /@babel/template@7.24.0: resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} engines: {node: '>=6.9.0'} @@ -667,7 +814,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.1 '@babel/types': 7.24.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -683,6 +830,22 @@ packages: /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + + /@compiled/react@0.17.1(react@18.2.0): + resolution: {integrity: sha512-1CzTOrwNHOUmz9QGYHv8R8J6ejUyaNYiaUN6/dIM0Wu3G5CIam0KgsqvRikfGPrTtBfAQYMmdI9ytzxUKYwJrg==} + peerDependencies: + react: '>= 16.12.0' + dependencies: + csstype: 3.1.3 + react: 18.2.0 + dev: false + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -690,6 +853,39 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@cypress/request@3.0.1: + resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} + engines: {node: '>= 6'} + dependencies: + aws-sign2: 0.7.0 + aws4: 1.12.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + http-signature: 1.3.6 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + performance-now: 2.1.0 + qs: 6.10.4 + safe-buffer: 5.1.2 + tough-cookie: 4.1.3 + tunnel-agent: 0.6.0 + uuid: 8.3.2 + dev: true + + /@cypress/xvfb@1.2.4(supports-color@8.1.1): + resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} + dependencies: + debug: 3.2.7(supports-color@8.1.1) + lodash.once: 4.1.1 + transitivePeerDependencies: + - supports-color + dev: true + /@emoji-mart/data@1.1.2: resolution: {integrity: sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg==} dev: false @@ -1024,7 +1220,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -1074,7 +1270,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -1359,30 +1555,6 @@ packages: resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} dev: false - /@mui/base@5.0.0-alpha.119(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-XA5zhlYfXi67u613eIF0xRmktkatx6ERy3h+PwrMN5IcWFbgiL1guz8VpdXON+GWb8+G7B8t5oqTFIaCqaSAeA==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.1 - '@emotion/is-prop-valid': 1.2.2 - '@mui/types': 7.2.14(@types/react@18.2.66) - '@mui/utils': 5.15.14(@types/react@18.2.66)(react@18.2.0) - '@popperjs/core': 2.11.8 - '@types/react': 18.2.66 - clsx: 1.2.1 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 - dev: false - /@mui/base@5.0.0-beta.40(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} engines: {node: '>=12.0.0'} @@ -1406,11 +1578,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/core-downloads-tracker@5.15.14: - resolution: {integrity: sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==} + /@mui/base@5.0.0-beta.42(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fWRiUJVCHCPF+mxd5drn08bY2qRw3jj5f1SSQdUXmaJ/yKpk23ys8MgLO2KGVTRtbks/+ctRfgffGPbXifj0Ug==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@mui/types': 7.2.14(@types/react@18.2.66) + '@mui/utils': 6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0) + '@popperjs/core': 2.11.8 + '@types/react': 18.2.66 + clsx: 2.1.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/icons-material@5.11.11(@mui/material@5.11.12)(@types/react@18.2.66)(react@18.2.0): + /@mui/core-downloads-tracker@6.0.0-alpha.2: + resolution: {integrity: sha512-6JSNsfMePoLZ0tKZzQ2i+W8mcZCbP9snFNf/pQGOsMK2igkPGqOfqgdsda2OJrD5tP9VGjEDrrmYGHuX3ir29g==} + dev: false + + /@mui/icons-material@5.11.11(@mui/material@6.0.0-alpha.2)(@types/react@18.2.66)(react@18.2.0): resolution: {integrity: sha512-Eell3ADmQVE8HOpt/LZ3zIma8JSvPh3XgnhwZLT0k5HRqZcd6F/QDHc7xsWtgz09t+UEFvOYJXjtrwKmLdwwpw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1422,13 +1617,13 @@ packages: optional: true dependencies: '@babel/runtime': 7.24.1 - '@mui/material': 5.11.12(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 6.0.0-alpha.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) '@types/react': 18.2.66 react: 18.2.0 dev: false - /@mui/material@5.11.12(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-M6BiIeJjySeEzWeiFJQ9pIjJy6mx5mHPWeMT99wjQdAmA2GxCQhE9A0fh6jQP4jMmYzxhOIhjsGcp0vSdpseXg==} + /@mui/material@6.0.0-alpha.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-p1GpE1a7dQTns0yp0anSNX/Bh1xafTdUCt0roTyqEuL/3hCBKTURE/9/CDttwwQ+Q8oDm5KcsdtXJXJh1ts6Kw==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -1444,17 +1639,17 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.24.1 + '@babel/runtime': 7.24.4 '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) - '@mui/base': 5.0.0-alpha.119(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.15.14 - '@mui/system': 5.14.4(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0) + '@mui/base': 5.0.0-beta.42(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 6.0.0-alpha.2 + '@mui/system': 6.0.0-alpha.1(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/types': 7.2.14(@types/react@18.2.66) - '@mui/utils': 5.15.14(@types/react@18.2.66)(react@18.2.0) + '@mui/utils': 6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0) '@types/react': 18.2.66 - '@types/react-transition-group': 4.4.6 - clsx: 1.2.1 + '@types/react-transition-group': 4.4.10 + clsx: 2.1.0 csstype: 3.1.3 prop-types: 15.8.1 react: 18.2.0 @@ -1473,13 +1668,30 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.24.1 + '@babel/runtime': 7.24.4 '@mui/utils': 5.15.14(@types/react@18.2.66)(react@18.2.0) '@types/react': 18.2.66 prop-types: 15.8.1 react: 18.2.0 dev: false + /@mui/private-theming@6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0): + resolution: {integrity: sha512-S+vlRxja0ncLT1KK+Qkqy6ZNpIsw5ZxoTd70KR8foLtPQXs0XGWQkq9IotbcZnYyKUUhM/5Cqo3w8Q/zNNVzBQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@mui/utils': 6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0) + '@types/react': 18.2.66 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /@mui/styled-engine@5.15.14(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(react@18.2.0): resolution: {integrity: sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==} engines: {node: '>=12.0.0'} @@ -1493,7 +1705,29 @@ packages: '@emotion/styled': optional: true dependencies: - '@babel/runtime': 7.24.1 + '@babel/runtime': 7.24.4 + '@emotion/cache': 11.11.0 + '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) + '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + + /@mui/styled-engine@6.0.0-alpha.1(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(react@18.2.0): + resolution: {integrity: sha512-lJmMF1D3SD9unSh5gjXYU3ChiCrNGrpT36cPOmGv7wiH2qLMov5Wo23nK7UfuaQVA4c4/JAS43SLT2O2z6hx4Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + dependencies: + '@babel/runtime': 7.24.4 '@emotion/cache': 11.11.0 '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) @@ -1518,7 +1752,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.24.1 + '@babel/runtime': 7.24.4 '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/private-theming': 5.15.14(@types/react@18.2.66)(react@18.2.0) @@ -1532,6 +1766,36 @@ packages: react: 18.2.0 dev: false + /@mui/system@6.0.0-alpha.1(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0): + resolution: {integrity: sha512-NqOFHCT/lvi4v696b0pEEz2Jc3MgjjGRsbFNN+IW5EuIInHr/JEznnPw0GpEU8tgU544MdfMTlFpDgR1LmvmLA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) + '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) + '@mui/private-theming': 6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0) + '@mui/styled-engine': 6.0.0-alpha.1(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(react@18.2.0) + '@mui/types': 7.2.14(@types/react@18.2.66) + '@mui/utils': 6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0) + '@types/react': 18.2.66 + clsx: 2.1.0 + csstype: 3.1.3 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /@mui/types@7.2.14(@types/react@18.2.66): resolution: {integrity: sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==} peerDependencies: @@ -1561,7 +1825,25 @@ packages: react-is: 18.2.0 dev: false - /@mui/x-date-pickers-pro@6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.12)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): + /@mui/utils@6.0.0-alpha.1(@types/react@18.2.66)(react@18.2.0): + resolution: {integrity: sha512-BvTVWvW6JDxMjDfEfTTEb6/CLgj87HyS3hYA4hbk0LdFsXeRnFSK6yDj8Dw3gxvXBymQ26kHDyFK3pEoAFlurw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@types/prop-types': 15.7.12 + '@types/react': 18.2.66 + prop-types: 15.8.1 + react: 18.2.0 + react-is: 18.2.0 + dev: false + + /@mui/x-date-pickers-pro@6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@6.0.0-alpha.2)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-8lEVEOtCQssKWel4Ey1pRulGPXUQ73TnkHKzHWsjdv03FjiUs3eYB+Ej0Uk5yWPmsqlShWhOzOlOGDpzsYJsUg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1602,10 +1884,10 @@ packages: '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/base': 5.0.0-beta.40(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) - '@mui/material': 5.11.12(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 6.0.0-alpha.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) '@mui/system': 5.14.4(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/utils': 5.15.14(@types/react@18.2.66)(react@18.2.0) - '@mui/x-date-pickers': 6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.12)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) + '@mui/x-date-pickers': 6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@6.0.0-alpha.2)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0) '@mui/x-license-pro': 6.10.2(@types/react@18.2.66)(react@18.2.0) clsx: 2.1.0 dayjs: 1.11.9 @@ -1617,7 +1899,7 @@ packages: - '@types/react' dev: false - /@mui/x-date-pickers@6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@5.11.12)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): + /@mui/x-date-pickers@6.18.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@mui/material@6.0.0-alpha.2)(@mui/system@5.14.4)(@types/react@18.2.66)(dayjs@1.11.9)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-HJq4uoFQSu5isa/mesWw2BKh8KBRYUQb+KaSlVlWfJNgP3YhPvWZ6yqCNYyxOAiPMxb0n3nBjS9ErO27OHjFMA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1658,7 +1940,7 @@ packages: '@emotion/react': 11.10.6(@types/react@18.2.66)(react@18.2.0) '@emotion/styled': 11.10.6(@emotion/react@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/base': 5.0.0-beta.40(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) - '@mui/material': 5.11.12(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 6.0.0-alpha.2(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react-dom@18.2.0)(react@18.2.0) '@mui/system': 5.14.4(@emotion/react@11.10.6)(@emotion/styled@11.10.6)(@types/react@18.2.66)(react@18.2.0) '@mui/utils': 5.15.14(@types/react@18.2.66)(react@18.2.0) '@types/react-transition-group': 4.4.10 @@ -1899,15 +2181,15 @@ packages: dependencies: '@sinonjs/commons': 3.0.1 - /@slate-yjs/core@1.0.2(slate@0.101.4)(yjs@13.5.51): + /@slate-yjs/core@1.0.2(slate@0.101.4)(yjs@13.6.14): resolution: {integrity: sha512-X0hLFJbQu9c1ItWBaNuEn0pqcXYK76KCp8C4Gvy/VaTQVMo1VgAb2WiiJ0Je/AyuIYEPPSTNVOcyrGHwgA7e6Q==} peerDependencies: slate: '>=0.70.0' yjs: ^13.5.29 dependencies: slate: 0.101.4 - y-protocols: 1.0.6(yjs@13.5.51) - yjs: 13.5.51 + y-protocols: 1.0.6(yjs@13.6.14) + yjs: 13.6.14 dev: false /@svgr/babel-plugin-add-jsx-attribute@7.0.0(@babel/core@7.24.3): @@ -2474,6 +2756,7 @@ packages: resolution: {integrity: sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==} dependencies: '@types/react': 18.2.66 + dev: true /@types/react-window@1.8.8: resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==} @@ -2500,6 +2783,14 @@ packages: resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} dev: true + /@types/sinonjs__fake-timers@8.1.1: + resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} + dev: true + + /@types/sizzle@2.3.8: + resolution: {integrity: sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==} + dev: true + /@types/stack-utils@2.0.3: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -2539,6 +2830,14 @@ packages: dependencies: '@types/yargs-parser': 21.0.3 + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 20.11.30 + dev: true + optional: true + /@typescript-eslint/eslint-plugin@7.2.0(@typescript-eslint/parser@7.2.0)(eslint@8.57.0)(typescript@4.9.5): resolution: {integrity: sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -2556,7 +2855,7 @@ packages: '@typescript-eslint/type-utils': 7.2.0(eslint@8.57.0)(typescript@4.9.5) '@typescript-eslint/utils': 7.2.0(eslint@8.57.0)(typescript@4.9.5) '@typescript-eslint/visitor-keys': 7.2.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -2582,7 +2881,7 @@ packages: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/typescript-estree': 7.2.0(typescript@4.9.5) '@typescript-eslint/visitor-keys': 7.2.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 4.9.5 transitivePeerDependencies: @@ -2609,7 +2908,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.2.0(typescript@4.9.5) '@typescript-eslint/utils': 7.2.0(eslint@8.57.0)(typescript@4.9.5) - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@4.9.5) typescript: 4.9.5 @@ -2633,7 +2932,7 @@ packages: dependencies: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/visitor-keys': 7.2.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -2749,11 +3048,19 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -2763,6 +3070,11 @@ packages: uri-js: 4.4.1 dev: true + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + /ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -2806,6 +3118,10 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: true + /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -2892,9 +3208,34 @@ packages: is-shared-array-buffer: 1.0.3 dev: true + /asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: true + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: true + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + /at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + dev: true + /autoprefixer@10.4.13(postcss@8.4.21): resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==} engines: {node: ^10 || ^12 || >=14} @@ -2918,6 +3259,14 @@ packages: possible-typed-array-names: 1.0.0 dev: true + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: true + + /aws4@1.12.0: + resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + dev: true + /axios@1.6.8: resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} dependencies: @@ -3041,10 +3390,32 @@ packages: dev: true optional: true + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: true + /binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + /bind-event-listener@2.1.1: + resolution: {integrity: sha512-O+a5c0D2se/u2VlBJmPRn45IB6R4mYMh1ok3dWxrIZ2pmLqzggBhb875mbq73508ylzofc0+hT9W41x4Y2s8lg==} + dev: false + + /blob-util@2.0.2: + resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: true @@ -3095,9 +3466,25 @@ packages: dependencies: node-int64: 0.4.0 + /buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + dev: true + /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /cachedir@2.4.0: + resolution: {integrity: sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==} + engines: {node: '>=6'} + dev: true + /call-bind@1.0.7: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} @@ -3143,6 +3530,10 @@ packages: upper-case-first: 2.0.2 dev: true + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: true + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -3184,6 +3575,11 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + /check-more-types@2.24.0: + resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} + engines: {node: '>= 0.8.0'} + dev: true + /chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -3209,6 +3605,35 @@ packages: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} dev: false + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-table3@0.6.4: + resolution: {integrity: sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: true + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -3256,12 +3681,21 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 + /commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + dev: true + /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} @@ -3271,6 +3705,11 @@ packages: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: true + /compute-scroll-into-view@3.1.0: resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} dev: false @@ -3293,6 +3732,10 @@ packages: /convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: true + /core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true @@ -3346,6 +3789,14 @@ packages: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true + /cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -3422,6 +3873,63 @@ packages: /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + /cypress@13.7.2: + resolution: {integrity: sha512-FF5hFI5wlRIHY8urLZjJjj/YvfCBrRpglbZCLr/cYcL9MdDe0+5usa8kTIrDHthlEc9lwihbkb5dmwqBDNS2yw==} + engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} + hasBin: true + requiresBuild: true + dependencies: + '@cypress/request': 3.0.1 + '@cypress/xvfb': 1.2.4(supports-color@8.1.1) + '@types/sinonjs__fake-timers': 8.1.1 + '@types/sizzle': 2.3.8 + arch: 2.2.0 + blob-util: 2.0.2 + bluebird: 3.7.2 + buffer: 5.7.1 + cachedir: 2.4.0 + chalk: 4.1.2 + check-more-types: 2.24.0 + cli-cursor: 3.1.0 + cli-table3: 0.6.4 + commander: 6.2.1 + common-tags: 1.8.2 + dayjs: 1.11.9 + debug: 4.3.4(supports-color@8.1.1) + enquirer: 2.4.1 + eventemitter2: 6.4.7 + execa: 4.1.0 + executable: 4.1.1 + extract-zip: 2.0.1(supports-color@8.1.1) + figures: 3.2.0 + fs-extra: 9.1.0 + getos: 3.2.1 + is-ci: 3.0.1 + is-installed-globally: 0.4.0 + lazy-ass: 1.6.0 + listr2: 3.14.0(enquirer@2.4.1) + lodash: 4.17.21 + log-symbols: 4.1.0 + minimist: 1.2.8 + ospath: 1.2.2 + pretty-bytes: 5.6.0 + process: 0.11.10 + proxy-from-env: 1.0.0 + request-progress: 3.0.0 + semver: 7.6.0 + supports-color: 8.1.1 + tmp: 0.2.3 + untildify: 4.0.0 + yauzl: 2.10.0 + dev: true + + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} @@ -3470,9 +3978,20 @@ packages: /dayjs@1.11.9: resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} - dev: false - /debug@4.3.4: + /debug@3.2.7(supports-color@8.1.1): + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 8.1.1 + dev: true + + /debug@4.3.4(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -3482,6 +4001,7 @@ packages: optional: true dependencies: ms: 2.1.2 + supports-color: 8.1.1 /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} @@ -3571,6 +4091,10 @@ packages: minimist: 1.2.8 dev: true + /dexie@4.0.1: + resolution: {integrity: sha512-wSNn+TcCh+DuE2pdg058K3MhxA4g+IiZlW7yGz4cMd/t3z2rJXZcV3HDxZljbrICU2Iq0qY4UHnbolTMK/+bcA==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: true @@ -3690,6 +4214,13 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true + /ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: true + /electron-to-chromium@1.4.722: resolution: {integrity: sha512-5nLE0TWFFpZ80Crhtp4pIp8LXCztjYX41yUcV6b+bKR2PqzjskTMOOlBi1VjBHlvHwS+4gar7kNKOrsbsewEZQ==} @@ -3718,6 +4249,14 @@ packages: once: 1.4.0 dev: true + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -3949,7 +4488,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -4022,6 +4561,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /eventemitter2@6.4.7: + resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} + dev: true + /eventemitter3@2.0.3: resolution: {integrity: sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==} dev: false @@ -4031,6 +4574,21 @@ packages: engines: {node: '>=0.8.x'} dev: false + /execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + /execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -4045,6 +4603,13 @@ packages: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + /executable@4.1.1: + resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} + engines: {node: '>=4'} + dependencies: + pify: 2.3.0 + dev: true + /exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -4061,7 +4626,25 @@ packages: /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false + + /extract-zip@2.0.1(supports-color@8.1.1): + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4(supports-color@8.1.1) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: true + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: true /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -4112,6 +4695,19 @@ packages: dependencies: bser: 2.1.1 + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -4181,6 +4777,19 @@ packages: signal-exit: 4.1.0 dev: true + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: true + + /form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -4202,6 +4811,16 @@ packages: universalify: 2.0.1 dev: true + /fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -4250,6 +4869,13 @@ packages: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -4263,6 +4889,18 @@ packages: get-intrinsic: 1.2.4 dev: true + /getos@3.2.1: + resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} + dependencies: + async: 3.2.5 + dev: true + + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4298,6 +4936,13 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + dependencies: + ini: 2.0.0 + dev: true + /globalize@0.1.1: resolution: {integrity: sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==} dev: false @@ -4440,21 +5085,35 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /http-signature@1.3.6: + resolution: {integrity: sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + jsprim: 2.0.2 + sshpk: 1.18.0 + dev: true + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true + /human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + dev: true + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -4484,6 +5143,10 @@ packages: safer-buffer: 2.1.2 dev: true + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -4515,6 +5178,11 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: @@ -4524,6 +5192,11 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + dev: true + /internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -4583,6 +5256,13 @@ packages: engines: {node: '>= 0.4'} dev: true + /is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + dependencies: + ci-info: 3.9.0 + dev: true + /is-core-module@2.13.1: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: @@ -4638,6 +5318,14 @@ packages: resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==} dev: false + /is-installed-globally@0.4.0: + resolution: {integrity: sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==} + engines: {node: '>=10'} + dependencies: + global-dirs: 3.0.1 + is-path-inside: 3.0.3 + dev: true + /is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -4707,6 +5395,15 @@ packages: which-typed-array: 1.1.15 dev: true + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: @@ -4735,6 +5432,10 @@ packages: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} dev: false + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: true + /istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -4775,7 +5476,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -5225,6 +5926,10 @@ packages: argparse: 2.0.1 dev: true + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: true + /jsdom@20.0.3: resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} engines: {node: '>=14'} @@ -5282,10 +5987,18 @@ packages: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: true + /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -5303,6 +6016,16 @@ packages: graceful-fs: 4.2.11 dev: true + /jsprim@2.0.2: + resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: true + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -5338,6 +6061,11 @@ packages: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true + /lazy-ass@1.6.0: + resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} + engines: {node: '> 0.8'} + dev: true + /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -5366,6 +6094,26 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + /listr2@3.14.0(enquirer@2.4.1): + resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} + engines: {node: '>=10.0.0'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + enquirer: 2.4.1 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.1 + rxjs: 7.8.0 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -5397,9 +6145,31 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -5712,6 +6482,10 @@ packages: type-check: 0.4.0 dev: true + /ospath@1.2.2: + resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} + dev: true + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -5737,6 +6511,13 @@ packages: p-limit: 3.1.0 dev: true + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -5825,9 +6606,12 @@ packages: through2: 2.0.5 dev: true + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: true + /performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - dev: false /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -6001,6 +6785,11 @@ packages: hasBin: true dev: true + /pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: true + /pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6018,6 +6807,11 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: true + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} @@ -6041,6 +6835,10 @@ packages: resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==} dev: false + /proxy-from-env@1.0.0: + resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} + dev: true + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false @@ -6056,6 +6854,13 @@ packages: once: 1.4.0 dev: true + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + /pumpify@1.5.1: resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} dependencies: @@ -6072,6 +6877,13 @@ packages: /pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + /qs@6.10.4: + resolution: {integrity: sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.6 + dev: true + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: true @@ -6612,6 +7424,12 @@ packages: es-errors: 1.3.0 set-function-name: 2.0.2 + /request-progress@3.0.0: + resolution: {integrity: sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==} + dependencies: + throttleit: 1.0.1 + dev: true + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -6659,11 +7477,23 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true + /rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} + dev: true + /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -6728,7 +7558,6 @@ packages: resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} dependencies: tslib: 2.6.2 - dev: false /safe-array-concat@1.1.2: resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} @@ -6909,6 +7738,24 @@ packages: tiny-warning: 1.0.3 dev: false + /slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + /snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} dependencies: @@ -6950,6 +7797,22 @@ packages: /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + /sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: true + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -7197,6 +8060,10 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true + /throttleit@1.0.1: + resolution: {integrity: sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==} + dev: true + /through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} dependencies: @@ -7204,6 +8071,10 @@ packages: xtend: 4.0.2 dev: true + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + /tiny-invariant@1.3.1: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} dev: false @@ -7219,6 +8090,11 @@ packages: /tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + /tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + dev: true + /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -7398,6 +8274,16 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: true + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -7511,6 +8397,11 @@ packages: engines: {node: '>=10'} dev: false + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: true + /update-browserslist-db@1.0.13(browserslist@4.23.0): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -7570,6 +8461,11 @@ packages: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: true + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true @@ -7606,6 +8502,15 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + /vite-plugin-compression2@1.0.0: resolution: {integrity: sha512-42XNp6FjxE0JIecxj1fdi770pLhYm3MJhBUAod9EszTgDg9C4LDOgBzWcj/0K52KfJrpRXwUsWV6kqTDuoCfLA==} dependencies: @@ -7648,7 +8553,7 @@ packages: vite: ^2.0.0||^3.0.0||^4.0.0||^5.0.0 dependencies: '@rollup/plugin-strip': 3.0.4 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) kolorist: 1.8.0 sirv: 2.0.4 ufo: 1.5.3 @@ -7786,6 +8691,15 @@ packages: dependencies: isexe: 2.0.0 + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -7840,14 +8754,24 @@ packages: engines: {node: '>=0.4'} dev: true - /y-protocols@1.0.6(yjs@13.5.51): + /y-indexeddb@9.0.12(yjs@13.6.14): + resolution: {integrity: sha512-9oCFRSPPzBK7/w5vOkJBaVCQZKHXB/v6SIT+WYhnJxlEC61juqG0hBrAf+y3gmSMLFLwICNH9nQ53uscuse6Hg==} + engines: {node: '>=16.0.0', npm: '>=8.0.0'} + peerDependencies: + yjs: ^13.0.0 + dependencies: + lib0: 0.2.93 + yjs: 13.6.14 + dev: false + + /y-protocols@1.0.6(yjs@13.6.14): resolution: {integrity: sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} peerDependencies: yjs: ^13.0.0 dependencies: lib0: 0.2.93 - yjs: 13.5.51 + yjs: 13.6.14 dev: false /y18n@5.0.8: @@ -7880,8 +8804,15 @@ packages: y18n: 5.0.8 yargs-parser: 21.1.1 - /yjs@13.5.51: - resolution: {integrity: sha512-F1Nb3z3TdandD80IAeQqgqy/2n9AhDLcXoBhZvCUX1dNVe0ef7fIwi6MjSYaGAYF2Ev8VcLcsGnmuGGOl7AWbw==} + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: true + + /yjs@13.6.14: + resolution: {integrity: sha512-D+7KcUr0j+vBCUSKXXEWfA+bG4UQBviAwP3gYBhkstkgwy5+8diOPMx0iqLIOxNo/HxaREUimZRxqHGAHCL2BQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} dependencies: lib0: 0.2.93 diff --git a/frontend/appflowy_web_app/src/App.tsx b/frontend/appflowy_web_app/src/App.tsx deleted file mode 100644 index 8959868616..0000000000 --- a/frontend/appflowy_web_app/src/App.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { BrowserRouter, Route, Routes } from 'react-router-dom'; -import { Provider } from 'react-redux'; -import { store } from './stores/store'; -import { ErrorBoundary } from 'react-error-boundary'; -import { ErrorHandlerPage } from './components/error/ErrorHandlerPage'; -import '@/i18n/config'; -import AppTheme from '@/AppTheme'; -import { Toaster } from 'react-hot-toast'; -import ProtectedRoutes from '@/components/auth/ProtectedRoutes'; -import AppConfig from '@/AppConfig'; - -function App() { - return ( - - - - - - - }> - {/*} />*/} - {/*} />*/} - {/*} />*/} - - - - - - - - - ); -} - -export default App; diff --git a/frontend/appflowy_web_app/src/AppTheme.tsx b/frontend/appflowy_web_app/src/AppTheme.tsx deleted file mode 100644 index 3e3259b86d..0000000000 --- a/frontend/appflowy_web_app/src/AppTheme.tsx +++ /dev/null @@ -1,178 +0,0 @@ -import React, { useMemo } from 'react'; -import createTheme from '@mui/material/styles/createTheme'; -import ThemeProvider from '@mui/material/styles/ThemeProvider'; - -function AppTheme ({ children }: { - children: React.ReactNode; -}) { - const isDark = false; - const theme = useMemo(() => createTheme({ - typography: { - fontFamily: ['Poppins'].join(','), - fontSize: 12, - button: { - textTransform: 'none', - }, - }, - components: { - MuiMenuItem: { - defaultProps: { - sx: { - '&.Mui-selected.Mui-focusVisible': { - backgroundColor: 'var(--fill-list-hover)', - }, - '&.Mui-focusVisible': { - backgroundColor: 'unset', - }, - }, - }, - }, - MuiIconButton: { - styleOverrides: { - root: { - '&:hover': { - backgroundColor: 'var(--fill-list-hover)', - }, - borderRadius: '4px', - padding: '2px', - }, - }, - }, - MuiButton: { - styleOverrides: { - contained: { - color: 'var(--content-on-fill)', - boxShadow: 'var(--shadow)', - }, - containedPrimary: { - '&:hover': { - backgroundColor: 'var(--fill-default)', - }, - }, - containedInherit: { - color: 'var(--text-title)', - backgroundColor: isDark ? 'rgba(0, 0, 0, 0.4)' : 'rgba(255, 255, 255, 0.4)', - '&:hover': { - backgroundColor: 'var(--bg-body)', - boxShadow: 'var(--shadow)', - }, - }, - outlinedInherit: { - color: 'var(--text-title)', - borderColor: 'var(--line-border)', - '&:hover': { - boxShadow: 'var(--shadow)', - }, - }, - }, - }, - MuiButtonBase: { - defaultProps: { - sx: { - '&.Mui-selected:hover': { - backgroundColor: 'var(--fill-list-hover)', - }, - }, - }, - styleOverrides: { - root: { - '&:hover': { - backgroundColor: 'var(--fill-list-hover)', - }, - '&:active': { - backgroundColor: 'var(--fill-list-hover)', - }, - borderRadius: '4px', - padding: '2px', - boxShadow: 'none', - }, - }, - }, - MuiPaper: { - styleOverrides: { - root: { - backgroundImage: 'none', - }, - }, - }, - MuiDialog: { - defaultProps: { - sx: { - '& .MuiBackdrop-root': { - backgroundColor: 'var(--bg-mask)', - }, - }, - }, - }, - - MuiTooltip: { - styleOverrides: { - arrow: { - color: 'var(--bg-tips)', - }, - tooltip: { - backgroundColor: 'var(--bg-tips)', - color: 'var(--text-title)', - fontSize: '0.85rem', - borderRadius: '8px', - fontWeight: 400, - }, - }, - }, - MuiInputBase: { - styleOverrides: { - input: { - backgroundColor: 'transparent !important', - }, - }, - }, - MuiDivider: { - styleOverrides: { - root: { - borderColor: 'var(--line-divider)', - }, - }, - }, - }, - palette: { - mode: isDark ? 'dark' : 'light', - primary: { - main: '#00BCF0', - dark: '#00BCF0', - }, - error: { - main: '#FB006D', - dark: '#D32772', - }, - warning: { - main: '#FFC107', - dark: '#E9B320', - }, - info: { - main: '#00BCF0', - dark: '#2E9DBB', - }, - success: { - main: '#66CF80', - dark: '#3BA856', - }, - text: { - primary: isDark ? '#E2E9F2' : '#333333', - secondary: isDark ? '#7B8A9D' : '#828282', - disabled: isDark ? '#363D49' : '#F2F2F2', - }, - divider: isDark ? '#59647A' : '#BDBDBD', - background: { - default: isDark ? '#1A202C' : '#FFFFFF', - paper: isDark ? '#1A202C' : '#FFFFFF', - }, - }, - - }), [isDark]); - - return ( - {children} - ); -} - -export default AppTheme; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/collab.type.ts b/frontend/appflowy_web_app/src/application/collab.type.ts new file mode 100644 index 0000000000..2459c8b3a7 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/collab.type.ts @@ -0,0 +1,14 @@ +export enum CollabType { + Document = 0, + Database = 1, + WorkspaceDatabase = 2, + Folder = 3, + DatabaseRow = 4, + UserAwareness = 5, + Empty = 6, +} + +export enum CollabOrigin { + Local = 'local', + Remote = 'remote', +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/constants.ts b/frontend/appflowy_web_app/src/application/constants.ts new file mode 100644 index 0000000000..36e31606ff --- /dev/null +++ b/frontend/appflowy_web_app/src/application/constants.ts @@ -0,0 +1,2 @@ +export const databasePrefix = 'af_database'; + diff --git a/frontend/appflowy_web_app/src/application/document.type.ts b/frontend/appflowy_web_app/src/application/document.type.ts new file mode 100644 index 0000000000..da559c5bde --- /dev/null +++ b/frontend/appflowy_web_app/src/application/document.type.ts @@ -0,0 +1,176 @@ +import Y from 'yjs'; + +export type BlockId = string; + +export type ExternalId = string; + +export type ChildrenId = string; + +export enum BlockType { + Paragraph = 'paragraph', + Page = 'page', + HeadingBlock = 'heading', + TodoListBlock = 'todo_list', + BulletedListBlock = 'bulleted_list', + NumberedListBlock = 'numbered_list', + ToggleListBlock = 'toggle_list', + CodeBlock = 'code', + EquationBlock = 'math_equation', + QuoteBlock = 'quote', + CalloutBlock = 'callout', + DividerBlock = 'divider', + ImageBlock = 'image', + GridBlock = 'grid', + OutlineBlock = 'outline', + TableBlock = 'table', + TableCell = 'table/cell', +} + +export enum InlineBlockType { + Formula = 'formula', + Mention = 'mention', +} + +export enum AlignType { + Left = 'left', + Center = 'center', + Right = 'right', +} + +export interface BlockData { + bg_color?: string; + font_color?: string; + align?: AlignType; +} + +export interface HeadingBlockData extends BlockData { + level: number; +} + +export interface NumberedListBlockData extends BlockData { + number: number; +} + +export interface TodoListBlockData extends BlockData { + checked: boolean; +} + +export interface ToggleListBlockData extends BlockData { + collapsed: boolean; +} + +export interface CodeBlockData extends BlockData { + language: string; +} + +export interface CalloutBlockData extends BlockData { + icon: string; +} + +export interface MathEquationBlockData extends BlockData { + formula?: string; +} + +export enum ImageType { + Local = 0, + Internal = 1, + External = 2, +} + +export interface ImageBlockData extends BlockData { + url?: string; + width?: number; + align?: AlignType; + image_type?: ImageType; + height?: number; +} + +export interface OutlineBlockData extends BlockData { + depth?: number; +} + +export interface TableBlockData extends BlockData { + colDefaultWidth: number; + colMinimumWidth: number; + colsHeight: number; + colsLen: number; + rowDefaultHeight: number; + rowsLen: number; +} + +export interface TableCellBlockData extends BlockData { + colPosition: number; + height: number; + rowPosition: number; + width: number; +} + +export enum MentionType { + PageRef = 'page', + Date = 'date', +} + +export interface Mention { + // inline page ref id + page_id?: string; + // reminder date ref id + date?: string; + + type: MentionType; +} + +export enum YjsEditorKey { + data_section = 'data', + document = 'document', + database = 'database', + workspace_database = 'databases', + folder = 'folder', + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values + database_row = 'data', + user_awareness = 'user_awareness', + blocks = 'blocks', + page_id = 'page_id', + meta = 'meta', + children_map = 'children_map', + text_map = 'text_map', + text = 'text', + delta = 'delta', + + block_id = 'id', + block_type = 'ty', + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values + block_data = 'data', + block_parent = 'parent', + block_children = 'children', + block_external_id = 'external_id', + block_external_type = 'external_type', +} + +export interface YDoc extends Y.Doc { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get(key: YjsEditorKey.data_section | string): YSharedRoot | any; +} + +export interface YSharedRoot extends Y.Map { + get(key: YjsEditorKey.document): YDocument; +} + +export interface YDocument extends Y.Map { + get(key: YjsEditorKey.blocks | YjsEditorKey.page_id | YjsEditorKey.meta): YBlocks | YMeta | string; +} + +export interface YBlocks extends Y.Map { + get(key: BlockId): Y.Map; +} + +export interface YMeta extends Y.Map { + get(key: YjsEditorKey.children_map | YjsEditorKey.text_map): YChildrenMap | YTextMap; +} + +export interface YChildrenMap extends Y.Map { + get(key: ChildrenId): Y.Array; +} + +export interface YTextMap extends Y.Map { + get(key: ExternalId): Y.Text; +} diff --git a/frontend/appflowy_web_app/src/application/services/index.ts b/frontend/appflowy_web_app/src/application/services/index.ts index c8c14c8e78..21d401d0da 100644 --- a/frontend/appflowy_web_app/src/application/services/index.ts +++ b/frontend/appflowy_web_app/src/application/services/index.ts @@ -3,10 +3,9 @@ import { AFClientService } from '$client-services'; let service: AFService; -export async function getService(config: AFServiceConfig) { +export async function getService (config: AFServiceConfig) { if (service) return service; service = new AFClientService(config); - await service.load(); return service; } diff --git a/frontend/appflowy_web_app/src/application/services/js-services/auth.service.ts b/frontend/appflowy_web_app/src/application/services/js-services/auth.service.ts index 032c2b5b80..7119497775 100644 --- a/frontend/appflowy_web_app/src/application/services/js-services/auth.service.ts +++ b/frontend/appflowy_web_app/src/application/services/js-services/auth.service.ts @@ -1,12 +1,12 @@ import { AuthService } from '@/application/services/services.type'; -import { ProviderType, SignUpWithEmailPasswordParams, UserProfile } from '@/application/services/user.type'; -import { HttpClient } from '@/application/services/js-services/http/client'; -import { ACCESS_TOKEN_NAME, REFRESH_TOKEN_NAME, TOKEN_TYPE_NAME } from '@/application/services/js-services/http/const'; -import { AFWasmService } from '@/application/services/wasm-services'; +import { ProviderType, SignUpWithEmailPasswordParams } from '@/application/user.type'; +import { APIService } from 'src/application/services/js-services/wasm'; +import { signInSuccess } from '@/application/services/js-services/storage/auth'; +import { invalidToken } from '@/application/services/js-services/storage'; +import { afterSignInDecorator } from '@/application/services/js-services/decorator'; export class JSAuthService implements AuthService { - - constructor (private httpClient: HttpClient, private wasmService: AFWasmService) { + constructor() { // Do nothing } @@ -14,32 +14,26 @@ export class JSAuthService implements AuthService { return Promise.reject('Not implemented'); }; - signInWithOAuth = async ({ uri }: { uri: string }): Promise => { - const params = uri.split('#')[1].split('&'); - const data: Record = {}; + @afterSignInDecorator(signInSuccess) + async signInWithOAuth(_: { uri: string }): Promise { + return Promise.reject('Not implemented'); + } - params.forEach((param) => { - const [key, value] = param.split('='); - - data[key] = value; - }); - - sessionStorage.setItem(TOKEN_TYPE_NAME, data.token_type); - sessionStorage.setItem(ACCESS_TOKEN_NAME, data.access_token); - sessionStorage.setItem(REFRESH_TOKEN_NAME, data.refresh_token); - return this.httpClient.getUser(); - }; - signupWithEmailPassword = async (_params: SignUpWithEmailPasswordParams): Promise => { + signupWithEmailPassword = async (_params: SignUpWithEmailPasswordParams): Promise => { return Promise.reject('Not implemented'); }; - signinWithEmailPassword = async (email: string, password: string): Promise => { - // await this.wasmService.cloudService.signIn(email, password); - // return Promise.reject('Not implemented'); - return this.httpClient.signInWithEmailPassword(email, password); - }; + @afterSignInDecorator(signInSuccess) + async signinWithEmailPassword(email: string, password: string): Promise { + try { + return APIService.signIn(email, password); + } catch (e) { + return Promise.reject(e); + } + } signOut = async (): Promise => { - return this.httpClient.logout(); + invalidToken(); + return APIService.logout(); }; } diff --git a/frontend/appflowy_web_app/src/application/services/js-services/db/index.ts b/frontend/appflowy_web_app/src/application/services/js-services/db/index.ts new file mode 100644 index 0000000000..f923aa528d --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/db/index.ts @@ -0,0 +1,68 @@ +import { YDoc } from '@/application/document.type'; +import { getAuthInfo } from '@/application/services/js-services/storage'; +import * as Y from 'yjs'; +import { IndexeddbPersistence } from 'y-indexeddb'; +import { databasePrefix } from '@/application/constants'; +import BaseDexie from 'dexie'; +import { usersSchema, UsersTable } from './tables/users'; + +const version = 1; + +type DexieTables = UsersTable; +export type Dexie = BaseDexie & T; + +let db: Dexie | undefined; + +export function getDB() { + const authInfo = getAuthInfo(); + + if (!db && authInfo?.uuid) { + return openDB(authInfo?.uuid); + } + + return db; +} + +export function openDB(uuid: string) { + const dbName = `${databasePrefix}_${uuid}`; + + if (db && db.name === dbName) { + return db; + } + + db = new BaseDexie(dbName) as Dexie; + const schema = Object.assign({}, usersSchema); + + db.version(version).stores(schema); + return db; +} + +/** + * Open the collaboration database, and return a function to close it + */ +export async function openCollabDB(docName: string): Promise { + const name = `${databasePrefix}_${docName}`; + const doc = new Y.Doc(); + const provider = new IndexeddbPersistence(name, doc); + + let resolve: (value: unknown) => void; + const promise = new Promise((resolveFn) => { + resolve = resolveFn; + }); + + provider.on('synced', () => { + resolve(true); + }); + + await promise; + + return doc as YDoc; +} + +export async function deleteCollabDB(docName: string) { + const name = `${databasePrefix}_${docName}`; + const doc = new Y.Doc(); + const provider = new IndexeddbPersistence(name, doc); + + await provider.destroy(); +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/db/tables/users.ts b/frontend/appflowy_web_app/src/application/services/js-services/db/tables/users.ts new file mode 100644 index 0000000000..1da8f20b0c --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/db/tables/users.ts @@ -0,0 +1,10 @@ +import { Table } from 'dexie'; +import { UserProfile } from '@/application/user.type'; + +export type UsersTable = { + users: Table; +}; + +export const usersSchema = { + users: 'uuid, uid, email, name, workspaceId, iconUrl', +}; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/services/js-services/decorator.ts b/frontend/appflowy_web_app/src/application/services/js-services/decorator.ts new file mode 100644 index 0000000000..a6f9cf9ee4 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/decorator.ts @@ -0,0 +1,60 @@ +/** + * @description: + * * This is a decorator that can be used to read data from storage and fetch data from the server. + * * If the data is already in storage, it will return the data from storage and fetch the data from the server in the background. + * + * @param getStorage A function that returns the data from storage. eg. `() => Promise` + * + * @param setStorage A function that saves the data to storage. eg. `(data: T) => Promise` + * + * @param fetchFunction A function that fetches the data from the server. eg. `(params: P) => Promise` + * + * @returns: A function that returns the data from storage and fetches the data from the server in the background. + */ +export function asyncDataDecorator( + getStorage: () => Promise, + setStorage: (data: T) => Promise, + fetchFunction: (params: P) => Promise +) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { + async function fetchData(params: P) { + const data = await fetchFunction(params); + + if (!data) return; + await setStorage(data); + return data; + } + + const originalMethod = descriptor.value; + + descriptor.value = async function (params: P) { + const data = await getStorage(); + + await originalMethod.apply(this, [params]); + if (data) { + void fetchData(params); + return data; + } else { + return fetchData(params); + } + }; + + return descriptor; + }; +} + +export function afterSignInDecorator(successCallback: () => Promise) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { + const originalMethod = descriptor.value; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + descriptor.value = async function (...args: any[]) { + await originalMethod.apply(this, args); + await successCallback(); + }; + + return descriptor; + }; +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/document.service.ts b/frontend/appflowy_web_app/src/application/services/js-services/document.service.ts index d55ad1771e..2eb35138e8 100644 --- a/frontend/appflowy_web_app/src/application/services/js-services/document.service.ts +++ b/frontend/appflowy_web_app/src/application/services/js-services/document.service.ts @@ -1,17 +1,46 @@ +import { YDoc } from '@/application/document.type'; +import { getDocumentStorage } from '@/application/services/js-services/storage/document'; import { DocumentService } from '@/application/services/services.type'; -import { HttpClient } from '@/application/services/js-services/http/client'; -import { CollabType } from '@/application/services/js-services/http/http.type'; +import { APIService } from 'src/application/services/js-services/wasm'; +import { CollabOrigin, CollabType } from '@/application/collab.type'; +import { applyDocument } from 'src/application/ydoc/apply'; export class JSDocumentService implements DocumentService { - constructor(private httpClient: HttpClient) {} + constructor() { + // + } - async openDocument(docID: string): Promise { - const workspaceId = '9eebea03-3ed5-4298-86b2-a7f77856d48b'; - const docId = '26d5c8c1-1c66-459c-bc6c-f4da1a663348'; - const data = await this.httpClient.getObject(workspaceId, docId, CollabType.Document); + fetchDocument(workspaceId: string, docId: string) { + return APIService.getCollab(workspaceId, docId, CollabType.Document); + } - console.log(docID, data); + async openDocument(workspaceId: string, docId: string): Promise { + const { doc, localExist } = await getDocumentStorage(docId); + const asyncApply = async () => { + const res = await this.fetchDocument(workspaceId, docId); - return; + applyDocument(doc, res.state); + }; + + // If the document exists locally, apply the state asynchronously, + // otherwise, apply the state synchronously + if (localExist) { + void asyncApply(); + } else { + await asyncApply(); + } + + const handleUpdate = (update: Uint8Array, origin: CollabOrigin) => { + if (origin === CollabOrigin.Remote) { + return; + } + + // Send the update to the server + console.log('update', update); + }; + + doc.on('update', handleUpdate); + + return doc; } } diff --git a/frontend/appflowy_web_app/src/application/services/js-services/http/client.ts b/frontend/appflowy_web_app/src/application/services/js-services/http/client.ts deleted file mode 100644 index fc5b99d4b2..0000000000 --- a/frontend/appflowy_web_app/src/application/services/js-services/http/client.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { AxiosInstance } from 'axios'; -import { UserProfile, Workspace } from '@/application/services/user.type'; -import { - CollabType, - EncodedCollab, - UserProfilePB, - WorkspacePB, -} from '@/application/services/js-services/http/http.type'; -import { - parseUserPBToUserProfile, - getAxiosInstances, - parseWorkspacePBToWorkspace, -} from '@/application/services/js-services/http/utils'; -import { - ACCESS_TOKEN_NAME, - baseHttpUrls, - gotrueHttpUrls, - REFRESH_TOKEN_NAME, - URL_NAME, -} from '@/application/services/js-services/http/const'; - -export class HttpClient { - private gotrueAPI: AxiosInstance; - private baseAPI: AxiosInstance; - - constructor(private config: { baseURL: string; gotrueURL: string }) { - const { baseInstance, gotrueInstance } = getAxiosInstances(config.baseURL, config.gotrueURL); - - this.gotrueAPI = gotrueInstance; - this.baseAPI = baseInstance; - } - - async signInWithEmailPassword(email: string, password: string): Promise { - const { data } = await this.gotrueAPI.post<{ - access_token: string; - refresh_token: string; - }>(gotrueHttpUrls[URL_NAME.SIGN_IN_WITH_EMAIL], { - email, - password, - }); - - sessionStorage.setItem(ACCESS_TOKEN_NAME, data.access_token); - sessionStorage.setItem(REFRESH_TOKEN_NAME, data.refresh_token); - - return this.getUser(); - } - - async getUser(): Promise { - const { data } = await this.gotrueAPI.get(gotrueHttpUrls[URL_NAME.GET_USER]); - - return parseUserPBToUserProfile(data); - } - - async logout() { - await this.gotrueAPI.post(gotrueHttpUrls[URL_NAME.LOGOUT]); - sessionStorage.removeItem(REFRESH_TOKEN_NAME); - sessionStorage.removeItem(ACCESS_TOKEN_NAME); - } - - async getWorkspaces(): Promise { - const { data } = await this.baseAPI.get(baseHttpUrls[URL_NAME.GET_WORKSPACES]); - - return data.map(parseWorkspacePBToWorkspace); - } - - /** - * Get object(document/database/view) from workspace - * @param workspaceId - workspace id - * @param objectId - document id or database id or view id - * @param objectType - type of object [CollabType] - */ - async getObject(workspaceId: string, objectId: string, objectType: CollabType): Promise { - // const workspaces = await this.getWorkspaces(); - // - // console.log(workspaces); - const { data } = await this.baseAPI.get(baseHttpUrls[URL_NAME.GET_OBJECT](workspaceId, objectId), { - data: JSON.stringify({ - workspace_id: workspaceId, - object_id: objectId, - collab_type: objectType, - }), - }); - - return data; - } -} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/http/const.ts b/frontend/appflowy_web_app/src/application/services/js-services/http/const.ts deleted file mode 100644 index 13977219c3..0000000000 --- a/frontend/appflowy_web_app/src/application/services/js-services/http/const.ts +++ /dev/null @@ -1,26 +0,0 @@ -export enum URL_NAME { - SIGN_IN_WITH_EMAIL, - GET_USER, - LOGOUT, - REFRESH_TOKEN, - GET_WORKSPACES, - GET_OBJECT, -} - -export const gotrueHttpUrls = { - [URL_NAME.SIGN_IN_WITH_EMAIL]: '/token?grant_type=password', - [URL_NAME.GET_USER]: '/user', - [URL_NAME.LOGOUT]: '/logout', - [URL_NAME.REFRESH_TOKEN]: '/token?grant_type=refresh_token', -}; - -export const baseHttpUrls = { - [URL_NAME.GET_WORKSPACES]: '/api/workspace', - [URL_NAME.GET_OBJECT]: (workspaceId: string, objectId: string) => `/api/workspace/${workspaceId}/collab/${objectId}`, -}; - -export const ACCESS_TOKEN_NAME = 'access_token'; -export const REFRESH_TOKEN_NAME = 'refresh_token'; -export const TOKEN_TYPE_NAME = 'token_type'; - -export const AUTHORIZATION_NAME = 'Authorization'; diff --git a/frontend/appflowy_web_app/src/application/services/js-services/http/http.type.ts b/frontend/appflowy_web_app/src/application/services/js-services/http/http.type.ts deleted file mode 100644 index d062c7d0e2..0000000000 --- a/frontend/appflowy_web_app/src/application/services/js-services/http/http.type.ts +++ /dev/null @@ -1,40 +0,0 @@ -export interface UserProfilePB { - id: string; - name: string; - email: string; - user_metadata: { - avatar_url: string; - full_name: string; - }; -} - -export interface WorkspacePB { - workspace_id: string; - database_storage_id: string; - owner_uid: number; - owner_name: string; - workspace_type: number; - workspace_name: string; - created_at: string; - icon: string; -} - -export enum EncoderVersion { - V1 = 0, - V2 = 1, -} - -export enum CollabType { - Document = 0, - Database = 1, - WorkspaceDatabase = 2, - Folder = 3, - DatabaseRow = 4, - UserAwareness = 5, -} - -export interface EncodedCollab { - state_vector: Uint8Array; - doc_state: Uint8Array; - version: EncoderVersion; -} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/http/utils.ts b/frontend/appflowy_web_app/src/application/services/js-services/http/utils.ts deleted file mode 100644 index 7c420a11e6..0000000000 --- a/frontend/appflowy_web_app/src/application/services/js-services/http/utils.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { UserProfilePB, WorkspacePB } from '@/application/services/js-services/http/http.type'; -import { Authenticator, UserProfile, Workspace } from '@/application/services/user.type'; -import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig } from 'axios'; -import { - ACCESS_TOKEN_NAME, - AUTHORIZATION_NAME, - gotrueHttpUrls, - REFRESH_TOKEN_NAME, - TOKEN_TYPE_NAME, - URL_NAME, -} from '@/application/services/js-services/http/const'; - -async function refreshToken(instance: AxiosInstance) { - const refreshToken = sessionStorage.getItem(REFRESH_TOKEN_NAME); - - if (!refreshToken) { - throw new Error('Refresh token not found'); - } - - const { data } = await instance.post(gotrueHttpUrls[URL_NAME.REFRESH_TOKEN], { - refresh_token: refreshToken, - }); - - sessionStorage.setItem(ACCESS_TOKEN_NAME, data.access_token); - sessionStorage.setItem(REFRESH_TOKEN_NAME, data.refresh_token); - - return data.access_token; -} - -export function getAxiosInstances(baseURL: string, gotrueURL: string) { - const gotrueInstance = axios.create({ - baseURL: gotrueURL, - headers: { - 'Content-Type': 'application/json', - Accept: '*/*', - }, - }); - const baseInstance = axios.create({ - baseURL, - headers: { - 'Content-Type': 'application/json', - Accept: '*/*', - }, - }); - - const requestInterceptor = async (config: InternalAxiosRequestConfig) => { - const accessToken = sessionStorage.getItem(ACCESS_TOKEN_NAME); - const tokenType = sessionStorage.getItem(TOKEN_TYPE_NAME) || 'Bearer'; - - if (accessToken) { - config.headers[AUTHORIZATION_NAME] = `${tokenType} ${accessToken}`; - } - - return config; - }; - - const errorInterceptor = async (error: { - response?: AxiosResponse; - config: AxiosRequestConfig; - }) => { - if (error.response?.status === 401 && !error.config.url?.includes(gotrueHttpUrls[URL_NAME.LOGOUT])) { - try { - const tokenType = sessionStorage.getItem(TOKEN_TYPE_NAME) || 'Bearer'; - const accessToken = await refreshToken(gotrueInstance); - - const config = { - ...error.config, - [AUTHORIZATION_NAME]: `${tokenType} ${accessToken}`, - } - - return gotrueInstance.request(config); - } catch (e) { - // do nothing - } - } - - return Promise.reject(error); - }; - - gotrueInstance.interceptors.request.use(requestInterceptor); - gotrueInstance.interceptors.response.use((response) => response, errorInterceptor); - - baseInstance.interceptors.request.use(requestInterceptor); - baseInstance.interceptors.response.use((response) => response, errorInterceptor); - return { - baseInstance, - gotrueInstance, - }; -} - -export function parseUserPBToUserProfile(userPB: UserProfilePB): UserProfile { - return { - id: userPB.id, - email: userPB.email, - authenticator: Authenticator.AppFlowyCloud, - iconUrl: userPB.user_metadata.avatar_url, - }; -} - -export function parseWorkspacePBToWorkspace(workspacePB: WorkspacePB): Workspace { - return { - id: workspacePB.workspace_id, - name: workspacePB.workspace_name, - icon: workspacePB.icon, - owner: { - id: workspacePB.owner_uid, - name: workspacePB.owner_name, - }, - }; -} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/index.ts b/frontend/appflowy_web_app/src/application/services/js-services/index.ts index d81f2188fb..4f08b44bdf 100644 --- a/frontend/appflowy_web_app/src/application/services/js-services/index.ts +++ b/frontend/appflowy_web_app/src/application/services/js-services/index.ts @@ -7,19 +7,21 @@ import { } from '@/application/services/services.type'; import { JSUserService } from '@/application/services/js-services/user.service'; import { JSAuthService } from '@/application/services/js-services/auth.service'; -import { AFWasmService } from '@/application/services/wasm-services'; -import { HttpClient } from '@/application/services/js-services/http/client'; import { JSDocumentService } from '@/application/services/js-services/document.service'; import { nanoid } from 'nanoid'; +import { initAPIService } from '@/application/services/js-services/wasm/client_api'; export class AFClientService implements AFService { authService: AuthService; + userService: UserService; - wasmService: AFWasmService; - httpClient: HttpClient; + documentService: DocumentService; + private deviceId: string = nanoid(8); + private clientId: string = 'web'; + getDeviceID = (): string => { return this.deviceId; }; @@ -28,21 +30,15 @@ export class AFClientService implements AFService { return this.clientId; }; - constructor(private config: AFServiceConfig) { - this.wasmService = new AFWasmService(config, { + constructor(config: AFServiceConfig) { + initAPIService({ + ...config.cloudConfig, deviceId: this.deviceId, clientId: this.clientId, }); - this.httpClient = new HttpClient({ - baseURL: config.cloudConfig.baseURL, - gotrueURL: config.cloudConfig.gotrueURL, - }); - this.authService = new JSAuthService(this.httpClient, this.wasmService); - this.userService = new JSUserService(this.httpClient); - this.documentService = new JSDocumentService(this.httpClient); - } - async load() { - await this.wasmService.load(); + this.authService = new JSAuthService(); + this.userService = new JSUserService(); + this.documentService = new JSDocumentService(); } } diff --git a/frontend/appflowy_web_app/src/application/services/js-services/storage/auth.ts b/frontend/appflowy_web_app/src/application/services/js-services/storage/auth.ts new file mode 100644 index 0000000000..bb19f590bc --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/storage/auth.ts @@ -0,0 +1,11 @@ +import { getAuthInfo } from '@/application/services/js-services/storage/token'; +import { openDB } from '@/application/services/js-services/db'; + +export async function signInSuccess() { + const authInfo = getAuthInfo(); + + if (authInfo) { + // Open the database + openDB(authInfo.uuid); + } +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/storage/document.ts b/frontend/appflowy_web_app/src/application/services/js-services/storage/document.ts new file mode 100644 index 0000000000..de839314f2 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/storage/document.ts @@ -0,0 +1,21 @@ +import { YjsEditorKey } from '@/application/document.type'; +import { openCollabDB } from '@/application/services/js-services/db'; +import { getAuthInfo } from '@/application/services/js-services/storage/token'; + +export async function getDocumentStorage(docId: string) { + const docName = getDocName(docId); + const doc = await openCollabDB(docName); + const localExist = doc.share.has(YjsEditorKey.data_section); + + return { + doc, + localExist, + }; +} + +export function getDocName(docId: string) { + const { uuid } = getAuthInfo() || {}; + + if (!uuid) throw new Error('No user found'); + return `${uuid}_document_${docId}`; +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/storage/index.ts b/frontend/appflowy_web_app/src/application/services/js-services/storage/index.ts new file mode 100644 index 0000000000..d983c71b07 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/storage/index.ts @@ -0,0 +1,2 @@ +export * from './token'; +export * from './user'; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/services/js-services/storage/token.ts b/frontend/appflowy_web_app/src/application/services/js-services/storage/token.ts new file mode 100644 index 0000000000..d6fcfe8644 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/storage/token.ts @@ -0,0 +1,36 @@ +const tokenKey = 'token'; + +export function readTokenStr () { + return sessionStorage.getItem(tokenKey); +} + +export function getAuthInfo () { + const token = readTokenStr() || ''; + + try { + const info = JSON.parse(token); + + return { + uuid: info.user.id, + access_token: info.access_token, + email: info.user.email, + }; + } catch (e) { + return; + } +} + +export function writeToken (token: string) { + if (!token) { + invalidToken(); + return; + } + + sessionStorage.setItem(tokenKey, token); +} + +export function invalidToken () { + sessionStorage.removeItem(tokenKey); + window.location.reload(); +} + diff --git a/frontend/appflowy_web_app/src/application/services/js-services/storage/user.ts b/frontend/appflowy_web_app/src/application/services/js-services/storage/user.ts new file mode 100644 index 0000000000..0194bb8e0f --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/storage/user.ts @@ -0,0 +1,18 @@ +import { UserProfile } from '@/application/user.type'; +import { getDB } from '@/application/services/js-services/db'; +import { getAuthInfo } from '@/application/services/js-services/storage/token'; + +const primaryKeyName = 'uid'; + +export async function getSignInUser(): Promise { + const db = getDB(); + const authInfo = getAuthInfo(); + + return db?.users.get(authInfo?.uuid); +} + +export async function setSignInUser(profile: UserProfile) { + const db = getDB(); + + return db?.users.put(profile, primaryKeyName); +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/user.service.ts b/frontend/appflowy_web_app/src/application/services/js-services/user.service.ts index fc54da9500..4b2f69c6af 100644 --- a/frontend/appflowy_web_app/src/application/services/js-services/user.service.ts +++ b/frontend/appflowy_web_app/src/application/services/js-services/user.service.ts @@ -1,11 +1,33 @@ import { UserService } from '@/application/services/services.type'; -import { UserProfile } from '@/application/services/user.type'; -import { HttpClient } from '@/application/services/js-services/http/client'; +import { UserProfile } from '@/application/user.type'; +import { notify } from '@/components/_shared/notify'; +import { APIService } from 'src/application/services/js-services/wasm'; +import { getAuthInfo, getSignInUser, setSignInUser } from '@/application/services/js-services/storage'; +import { asyncDataDecorator } from '@/application/services/js-services/decorator'; -export class JSUserService implements UserService { - constructor(private httpClient: HttpClient) {} +async function getUser() { + try { + const user = await APIService.getUser(); - async getUserProfile(): Promise { - return this.httpClient.getUser(); + return user; + } catch (e) { + console.error(e); + notify.error('Failed to get user profile, please try refreshing the page'); + // invalidToken(); + } +} + +export class JSUserService implements UserService { + @asyncDataDecorator(getSignInUser, setSignInUser, getUser) + async getUserProfile(): Promise { + if (!getAuthInfo()) { + return Promise.reject('Not authenticated'); + } + + return null!; + } + + async checkUser(): Promise { + return (await getSignInUser()) !== undefined; } } diff --git a/frontend/appflowy_web_app/src/application/services/js-services/wasm/client_api.ts b/frontend/appflowy_web_app/src/application/services/js-services/wasm/client_api.ts new file mode 100644 index 0000000000..ff9f50ebb7 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/wasm/client_api.ts @@ -0,0 +1,77 @@ +import { ClientAPI } from '@appflowyinc/client-api-wasm'; +import { UserProfile } from '@/application/user.type'; +import { AFCloudConfig } from '@/application/services/services.type'; +import { invalidToken, readTokenStr, writeToken } from '@/application/services/js-services/storage'; +import { CollabType } from '@/application/collab.type'; + +let client: ClientAPI; + +export function initAPIService (config: AFCloudConfig & { + deviceId: string; + clientId: string; +}) { + window.refresh_token = writeToken; + window.invalid_token = invalidToken; + client = ClientAPI.new({ + base_url: config.baseURL, + ws_addr: config.wsURL, + gotrue_url: config.gotrueURL, + device_id: config.deviceId, + client_id: config.clientId, + configuration: { + compression_quality: 8, + compression_buffer_size: 10240, + }, + }); + + const token = readTokenStr(); + + if (token) { + client.restore_token(token); + } + + client.subscribe(); +} + +export function signIn (email: string, password: string) { + return client.login(email, password); +} + +export function logout () { + return client.logout(); +} + +export async function getUser (): Promise { + try { + const user = await client.get_user(); + + if (!user) { + throw new Error('No user found'); + } + + return { + uid: parseInt(user.uid), + uuid: user.uuid || undefined, + email: user.email || undefined, + name: user.name || undefined, + workspaceId: user.latest_workspace_id, + iconUrl: user.icon_url || undefined, + }; + } catch (e) { + return Promise.reject(e); + } +} + +export async function getCollab (workspaceId: string, object_id: string, collabType: CollabType) { + const res = await client.get_collab({ + workspace_id: workspaceId, + object_id: object_id, + collab_type: Number(collabType) as 0 | 1 | 2 | 3 | 4 | 5, + }); + + const state = new Uint8Array(res.doc_state); + + return { + state, + }; +} diff --git a/frontend/appflowy_web_app/src/application/services/js-services/wasm/index.ts b/frontend/appflowy_web_app/src/application/services/js-services/wasm/index.ts new file mode 100644 index 0000000000..b4f0b4f4cc --- /dev/null +++ b/frontend/appflowy_web_app/src/application/services/js-services/wasm/index.ts @@ -0,0 +1 @@ +export * as APIService from './client_api'; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/services/services.type.ts b/frontend/appflowy_web_app/src/application/services/services.type.ts index ab54d9e97f..bbeb1b39b8 100644 --- a/frontend/appflowy_web_app/src/application/services/services.type.ts +++ b/frontend/appflowy_web_app/src/application/services/services.type.ts @@ -1,4 +1,5 @@ -import { ProviderType, SignUpWithEmailPasswordParams, UserProfile } from '@/application/services/user.type'; +import { YDoc } from '@/application/document.type'; +import { ProviderType, SignUpWithEmailPasswordParams, UserProfile } from '@/application/user.type'; export interface AFService { getDeviceID: () => string; @@ -6,7 +7,6 @@ export interface AFService { authService: AuthService; userService: UserService; documentService: DocumentService; - load: () => Promise; } export interface AFServiceConfig { @@ -20,18 +20,18 @@ export interface AFCloudConfig { } export interface AuthService { - getOAuthURL: (provider: ProviderType) => Promise; - signInWithOAuth: (params: { uri: string }) => Promise; - signupWithEmailPassword: (params: SignUpWithEmailPasswordParams) => Promise; - signinWithEmailPassword: (email: string, password: string) => Promise; + signInWithOAuth: (params: { uri: string }) => Promise; + signupWithEmailPassword: (params: SignUpWithEmailPasswordParams) => Promise; + signinWithEmailPassword: (email: string, password: string) => Promise; signOut: () => Promise; } export interface DocumentService { - openDocument: (docID: string) => Promise; + openDocument: (workspaceId: string, docId: string) => Promise; } export interface UserService { getUserProfile: () => Promise; + checkUser: () => Promise; } diff --git a/frontend/appflowy_web_app/src/application/services/tauri-services/auth.service.ts b/frontend/appflowy_web_app/src/application/services/tauri-services/auth.service.ts index 9a97b5fb9b..f039782058 100644 --- a/frontend/appflowy_web_app/src/application/services/tauri-services/auth.service.ts +++ b/frontend/appflowy_web_app/src/application/services/tauri-services/auth.service.ts @@ -12,7 +12,7 @@ import { UserEventSignUp, UserProfilePB, } from './backend/events/flowy-user'; -import { ProviderType, SignUpWithEmailPasswordParams, UserProfile } from '@/application/services/user.type'; +import { ProviderType, SignUpWithEmailPasswordParams, UserProfile } from '@/application/user.type'; export class TauriAuthService implements AuthService { @@ -41,7 +41,7 @@ export class TauriAuthService implements AuthService { return providerData.oauth_url; }; - signInWithOAuth = async ({ uri }: { uri: string }): Promise => { + signInWithOAuth = async ({ uri }: { uri: string }): Promise => { const payload = OauthSignInPB.fromObject({ authenticator: AuthenticatorPB.AppFlowyCloud, map: { @@ -56,9 +56,9 @@ export class TauriAuthService implements AuthService { throw new Error(res.val.msg); } - return parseUserProfileFrom(res.val); + return; }; - signinWithEmailPassword = async (email: string, password: string): Promise => { + signinWithEmailPassword = async (email: string, password: string): Promise => { const payload = SignInPayloadPB.fromObject({ email, password, @@ -70,10 +70,10 @@ export class TauriAuthService implements AuthService { return Promise.reject(res.val.msg); } - return parseUserProfileFrom(res.val); + return; }; - signupWithEmailPassword = async (params: SignUpWithEmailPasswordParams): Promise => { + signupWithEmailPassword = async (params: SignUpWithEmailPasswordParams): Promise => { const payload = SignUpPayloadPB.fromObject({ name: params.name, email: params.email, @@ -84,11 +84,10 @@ export class TauriAuthService implements AuthService { const res = await UserEventSignUp(payload); if (!res.ok) { - console.error(res.val.msg); return Promise.reject(res.val.msg); } - return parseUserProfileFrom(res.val); + return; }; signOut = async () => { @@ -106,16 +105,10 @@ export function parseUserProfileFrom (userPB: UserProfilePB): UserProfile { const user = userPB.toObject(); return { - id: String(user.id), + uid: user.id as number, email: user.email, name: user.name, - token: user.token, iconUrl: user.icon_url, - openaiKey: user.openai_key, - authenticator: user.authenticator as number, - encryptionSign: user.encryption_sign, - encryptionType: user.encryption_type as number, workspaceId: user.workspace_id, - stabilityAiKey: user.stability_ai_key, }; } diff --git a/frontend/appflowy_web_app/src/application/services/tauri-services/document.service.ts b/frontend/appflowy_web_app/src/application/services/tauri-services/document.service.ts index 8e7cc8438a..8bcede6523 100644 --- a/frontend/appflowy_web_app/src/application/services/tauri-services/document.service.ts +++ b/frontend/appflowy_web_app/src/application/services/tauri-services/document.service.ts @@ -1,68 +1,8 @@ import { DocumentService } from '@/application/services/services.type'; -import { OpenDocumentPayloadPB } from './backend'; -import { DocumentEventOpenDocument } from './backend/events/flowy-document'; +import Y from 'yjs'; export class TauriDocumentService implements DocumentService { - async openDocument(docId: string): Promise { - const payload = OpenDocumentPayloadPB.fromObject({ - document_id: docId, - }); - - const result = await DocumentEventOpenDocument(payload); - - if (!result.ok) { - return Promise.reject(result.val); - } - - return; - - // const documentDataPB = result.val; - // - // if (!documentDataPB) { - // return Promise.reject('documentDataPB is null'); - // } - // - // const data: { - // viewId: string; - // rootId: string; - // nodeMap: Record; - // childrenMap: Record; - // relativeMap: Record; - // deltaMap: Record; - // externalIdMap: Record; - // } = { - // viewId: docId, - // rootId: documentDataPB.page_id, - // nodeMap: {}, - // childrenMap: {}, - // relativeMap: {}, - // deltaMap: {}, - // externalIdMap: {}, - // }; - // - // get(documentDataPB, BLOCK_MAP_NAME).forEach((block) => { - // Object.assign(data.nodeMap, { - // [block.id]: blockPB2Node(block), - // }); - // data.relativeMap[block.children_id] = block.id; - // if (block.external_id) { - // data.externalIdMap[block.external_id] = block.id; - // } - // }); - // - // get(documentDataPB, [META_NAME, CHILDREN_MAP_NAME]).forEach((child, key) => { - // const blockId = data.relativeMap[key]; - // - // data.childrenMap[blockId] = child.children; - // }); - // - // get(documentDataPB, [META_NAME, TEXT_MAP_NAME]).forEach((delta, key) => { - // const blockId = data.externalIdMap[key]; - // - // data.deltaMap[blockId] = delta ? JSON.parse(delta) : []; - // }); - // - // // return data; - // return; + async openDocument(_id: string): Promise { + return Promise.reject('Not implemented'); } } diff --git a/frontend/appflowy_web_app/src/application/services/tauri-services/index.ts b/frontend/appflowy_web_app/src/application/services/tauri-services/index.ts index b012f272ce..2f91ab4b13 100644 --- a/frontend/appflowy_web_app/src/application/services/tauri-services/index.ts +++ b/frontend/appflowy_web_app/src/application/services/tauri-services/index.ts @@ -24,7 +24,7 @@ export class AFClientService implements AFService { return this.clientId; }; - constructor(config: AFServiceConfig) { + constructor (config: AFServiceConfig) { this.authService = new TauriAuthService(config.cloudConfig, { deviceId: this.deviceId, clientId: this.clientId, @@ -32,8 +32,4 @@ export class AFClientService implements AFService { this.userService = new TauriUserService(); this.documentService = new TauriDocumentService(); } - - async load() { - // Do nothing - } } diff --git a/frontend/appflowy_web_app/src/application/services/tauri-services/user.service.ts b/frontend/appflowy_web_app/src/application/services/tauri-services/user.service.ts index 0f76fde6c1..383e648052 100644 --- a/frontend/appflowy_web_app/src/application/services/tauri-services/user.service.ts +++ b/frontend/appflowy_web_app/src/application/services/tauri-services/user.service.ts @@ -1,10 +1,10 @@ import { UserService } from '@/application/services/services.type'; -import { UserProfile } from '@/application/services/user.type'; +import { UserProfile } from '@/application/user.type'; import { UserEventGetUserProfile } from './backend/events/flowy-user'; import { parseUserProfileFrom } from '@/application/services/tauri-services/auth.service'; export class TauriUserService implements UserService { - async getUserProfile (): Promise { + async getUserProfile(): Promise { const res = await UserEventGetUserProfile(); if (res.ok) { @@ -13,4 +13,8 @@ export class TauriUserService implements UserService { return null; } -} \ No newline at end of file + + async checkUser(): Promise { + return Promise.resolve(false); + } +} diff --git a/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.service.ts b/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.service.ts deleted file mode 100644 index aa8855391e..0000000000 --- a/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.service.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { CloudServiceConfig } from '@/application/services/wasm-services/cloud.type'; - -// import { ClientAPI } from '@appflowyinc/client-api-wasm'; - -export class CloudService { - // private client?: ClientAPI; - - constructor (private config: CloudServiceConfig) { - // Do nothing - } - - async init () { - // this.client = ClientAPI.new({ - // base_url: this.config.baseURL, - // ws_addr: this.config.wsURL, - // gotrue_url: this.config.gotrueURL, - // device_id: this.config.deviceId, - // client_id: this.config.clientId, - // configuration: { - // compression_quality: 8, - // compression_buffer_size: 10240, - // }, - // }); - - } - - // async signIn (email: string, password: string) { - // try { - // const res = await this.client?.sign_in_password(email, password); - // - // console.log(res); - // } catch (error) { - // console.error(error); - // } - // } -} diff --git a/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.type.ts b/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.type.ts deleted file mode 100644 index 1eff10225d..0000000000 --- a/frontend/appflowy_web_app/src/application/services/wasm-services/cloud.type.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { AFCloudConfig } from '@/application/services/services.type'; - -export type CloudServiceEventPayload = Record; -export type CloudServiceConfig = AFCloudConfig & { - deviceId: string; - clientId: string; -} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/services/wasm-services/index.ts b/frontend/appflowy_web_app/src/application/services/wasm-services/index.ts deleted file mode 100644 index 59bb5425cd..0000000000 --- a/frontend/appflowy_web_app/src/application/services/wasm-services/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { AFServiceConfig } from '@/application/services/services.type'; -import { CloudService } from '@/application/services/wasm-services/cloud.service'; - -export class AFWasmService { - cloudService: CloudService; - - constructor (private config: AFServiceConfig, clientConfig: { - deviceId: string; - clientId: string; - }) { - this.cloudService = new CloudService({ - ...config.cloudConfig, - ...clientConfig, - }); - } - - async load () { - await this.cloudService.init(); - } -} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/index.ts b/frontend/appflowy_web_app/src/application/slate-yjs/index.ts new file mode 100644 index 0000000000..715957a727 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/index.ts @@ -0,0 +1 @@ +export * from './plugins/withYjs'; diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/plugins/withYjs.ts b/frontend/appflowy_web_app/src/application/slate-yjs/plugins/withYjs.ts new file mode 100644 index 0000000000..881a8e2e07 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/plugins/withYjs.ts @@ -0,0 +1,147 @@ +import { YjsEditorKey, YSharedRoot } from '@/application/document.type'; +import { applySlateOp } from '@/application/slate-yjs/utils/applySlateOpts'; +import { translateYjsEvent } from 'src/application/slate-yjs/utils/translateYjsEvent'; +import { Editor, Operation, Descendant } from 'slate'; +import Y, { YEvent, Transaction } from 'yjs'; +import { yDocToSlateContent } from '@/application/slate-yjs/utils/convert'; +import { CollabOrigin } from '@/application/collab.type'; + +type LocalChange = { + op: Operation; + slateContent: Descendant[]; +}; + +export interface YjsEditor extends Editor { + connect: () => void; + disconnect: () => void; + sharedRoot: YSharedRoot; + applyRemoteEvents: (events: Array>, transaction: Transaction) => void; + flushLocalChanges: () => void; + storeLocalChange: (op: Operation) => void; +} + +const connectSet = new WeakSet(); + +const localChanges = new WeakMap(); + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const YjsEditor = { + connected(editor: YjsEditor): boolean { + return connectSet.has(editor); + }, + + connect(editor: YjsEditor): void { + editor.connect(); + }, + + disconnect(editor: YjsEditor): void { + editor.disconnect(); + }, + + applyRemoteEvents(editor: YjsEditor, events: Array>, transaction: Transaction): void { + editor.applyRemoteEvents(events, transaction); + }, + + localChanges(editor: YjsEditor): LocalChange[] { + return localChanges.get(editor) ?? []; + }, + + storeLocalChange(editor: YjsEditor, op: Operation): void { + editor.storeLocalChange(op); + }, + + flushLocalChanges(editor: YjsEditor): void { + editor.flushLocalChanges(); + }, +}; + +export function withYjs(editor: T, doc: Y.Doc): T & YjsEditor { + const e = editor as T & YjsEditor; + const { apply, onChange } = e; + + e.sharedRoot = doc.getMap(YjsEditorKey.data_section) as YSharedRoot; + e.applyRemoteEvents = (events: Array>, _: Transaction) => { + YjsEditor.flushLocalChanges(e); + + Editor.withoutNormalizing(editor, () => { + events.forEach((event) => { + translateYjsEvent(e.sharedRoot, editor, event).forEach((op) => { + // apply remote events to slate, don't call e.apply here because e.apply has been overridden. + apply(op); + }); + }); + }); + }; + + const handleYEvents = (events: Array>, transaction: Transaction) => { + if (transaction.origin === CollabOrigin.Local) { + return; + } + + YjsEditor.applyRemoteEvents(e, events, transaction); + }; + + e.connect = () => { + if (YjsEditor.connected(e)) { + throw new Error('Already connected'); + } + + const content = yDocToSlateContent(doc, true); + + if (!content) { + return; + } + + console.log(content); + + e.sharedRoot.observeDeep(handleYEvents); + e.children = content.children; + Editor.normalize(editor, { force: true }); + connectSet.add(e); + }; + + e.disconnect = () => { + if (!YjsEditor.connected(e)) { + throw new Error('Not connected'); + } + + e.sharedRoot.unobserveDeep(handleYEvents); + connectSet.delete(e); + }; + + e.storeLocalChange = (op) => { + const changes = localChanges.get(e) ?? []; + + localChanges.set(e, [...changes, { op, slateContent: e.children }]); + }; + + e.flushLocalChanges = () => { + const changes = YjsEditor.localChanges(e); + + localChanges.delete(e); + // parse changes and apply to ydoc + doc.transact(() => { + changes.forEach((change) => { + applySlateOp(doc, { children: change.slateContent }, change.op); + }); + }, CollabOrigin.Local); + }; + + e.apply = (op) => { + if (YjsEditor.connected(e)) { + YjsEditor.storeLocalChange(e, op); + } + + apply(op); + }; + + e.onChange = () => { + if (YjsEditor.connected(e)) { + YjsEditor.flushLocalChanges(e); + } + + onChange(); + }; + + return e; +} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/applySlateOpts.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/applySlateOpts.ts new file mode 100644 index 0000000000..edb14cfa0a --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/applySlateOpts.ts @@ -0,0 +1,6 @@ +import { Operation, Node } from 'slate'; +import Y from 'yjs'; + +export function applySlateOp (ydoc: Y.Doc, slateRoot: Node, op: Operation) { + console.log('applySlateOp', op); +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/convert.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/convert.ts new file mode 100644 index 0000000000..44565fa89a --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/convert.ts @@ -0,0 +1,240 @@ +import { + InlineBlockType, + YBlocks, + YChildrenMap, + YSharedRoot, + YDoc, + YjsEditorKey, + YMeta, + YTextMap, + BlockData, + BlockType, +} from '@/application/document.type'; +import { getFontFamily } from '@/utils/font'; +import { uniq } from 'lodash-es'; +import { Element, Text } from 'slate'; + +interface BlockJson { + id: string; + ty: string; + data?: string; + children?: string; + external_id?: string; +} + +export function yDocToSlateContent(doc: YDoc, includeRoot?: boolean): Element | undefined { + console.log(doc); + const sharedRoot = doc.getMap(YjsEditorKey.data_section) as YSharedRoot; + + console.log(sharedRoot.toJSON()); + const document = sharedRoot.get(YjsEditorKey.document); + const pageId = document.get(YjsEditorKey.page_id) as string; + const blocks = document.get(YjsEditorKey.blocks) as YBlocks; + const meta = document.get(YjsEditorKey.meta) as YMeta; + const childrenMap = meta.get(YjsEditorKey.children_map) as YChildrenMap; + const textMap = meta.get(YjsEditorKey.text_map) as YTextMap; + const fontFamilys: string[] = []; + + function traverse(id: string) { + const block = blocks.get(id).toJSON() as BlockJson; + const childrenId = block.children as string; + + const children = (childrenMap.get(childrenId)?.toJSON() ?? []).map(traverse) as (Element | Text)[]; + + const slateNode = blockToSlateNode(block); + + slateNode.children = children; + + if (slateNode.type === BlockType.Page) { + return slateNode; + } + + let textId = block.external_id as string; + + let delta; + + if (!textId) { + if (children.length === 0) { + children.push({ + text: '', + }); + } + + // Compatible data + // The old version of delta data is fully covered through the data field + if (slateNode.data) { + const data = slateNode.data as BlockData; + + if (YjsEditorKey.delta in data) { + textId = block.id; + delta = data.delta; + } else { + return slateNode; + } + } + } else { + delta = textMap.get(textId)?.toDelta(); + } + + try { + const slateDelta = delta.flatMap(deltaInsertToSlateNode); + + // collect font family + slateDelta.forEach((node: Text) => { + if (node.font_family) { + fontFamilys.push(getFontFamily(node.font_family)); + } + }); + const textNode: Element = { + textId, + type: YjsEditorKey.text, + children: slateDelta, + }; + + children.unshift(textNode); + return slateNode; + } catch (e) { + console.error(e); + return; + } + } + + const root = blocks.get(pageId); + + if (!root) return; + + const result = traverse(pageId); + + if (!result) return; + + if (!includeRoot) { + return result; + } + + const { children, ...rootNode } = result; + + // load font family + if (fontFamilys.length > 0) { + window.WebFont?.load({ + google: { + families: uniq(fontFamilys), + }, + }); + } + + return { + children: [ + { + ...rootNode, + children: [ + { + textId: root.toJSON().external_id, + type: YjsEditorKey.text, + children: [{ text: '' }], + }, + ], + }, + ...children, + ], + }; +} + +export function blockToSlateNode(block: BlockJson): Element { + const data = block.data; + let blockData; + + try { + blockData = data ? JSON.parse(data) : {}; + } catch (e) { + blockData = {}; + } + + return { + blockId: block.id, + data: blockData, + type: block.ty, + children: [], + }; +} + +export function deltaInsertToSlateNode({ + attributes, + insert, +}: { + insert: string; + attributes: Record; +}): Element | Text | Element[] { + const matchInlines = transformToInlineElement({ + insert, + attributes, + }); + + if (matchInlines.length > 0) { + return matchInlines; + } + + if (attributes) { + if ('font_color' in attributes && attributes['font_color'] === '') { + delete attributes['font_color']; + } + + if ('bg_color' in attributes && attributes['bg_color'] === '') { + delete attributes['bg_color']; + } + + if ('code' in attributes && !attributes['code']) { + delete attributes['code']; + } + } + + return { + ...attributes, + text: insert, + }; +} + +export function transformToInlineElement(op: { + insert: string; + attributes: Record; +}): Element[] { + const attributes = op.attributes; + + if (!attributes) return []; + const { formula, mention, ...attrs } = attributes; + + if (formula) { + const texts = op.insert.split(''); + + return texts.map((text) => { + return { + type: InlineBlockType.Formula, + data: formula, + children: [ + { + text, + ...attrs, + }, + ], + }; + }); + } + + if (mention) { + const texts = op.insert.split(''); + + return texts.map((text) => { + return { + type: InlineBlockType.Mention, + data: mention, + children: [ + { + text, + ...attrs, + }, + ], + }; + }); + } + + return []; +} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/arrayEvent.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/arrayEvent.ts new file mode 100644 index 0000000000..4524c442f1 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/arrayEvent.ts @@ -0,0 +1,12 @@ +import { YSharedRoot } from '@/application/document.type'; +import * as Y from 'yjs'; +import { Editor, Operation } from 'slate'; + +export function translateYArrayEvent( + sharedRoot: YSharedRoot, + editor: Editor, + event: Y.YEvent> +): Operation[] { + console.log('translateYArrayEvent', sharedRoot, editor, event); + return []; +} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/index.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/index.ts new file mode 100644 index 0000000000..12014a3ff0 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/index.ts @@ -0,0 +1,34 @@ +import { YSharedRoot } from '@/application/document.type'; +import { translateYArrayEvent } from '@/application/slate-yjs/utils/translateYjsEvent/arrayEvent'; +import { translateYMapEvent } from '@/application/slate-yjs/utils/translateYjsEvent/mapEvent'; +import { Editor, Operation } from 'slate'; +import * as Y from 'yjs'; +import { translateYTextEvent } from 'src/application/slate-yjs/utils/translateYjsEvent/textEvent'; + +/** + * Translate a yjs event into slate operations. The editor state has to match the + * yText state before the event occurred. + * + * @param sharedType + * @param op + */ +export function translateYjsEvent ( + sharedRoot: YSharedRoot, + editor: Editor, + event: Y.YEvent, +): Operation[] { + console.log('translateYjsEvent', event); + if (event instanceof Y.YMapEvent) { + return translateYMapEvent(sharedRoot, editor, event); + } + + if (event instanceof Y.YTextEvent) { + return translateYTextEvent(sharedRoot, editor, event); + } + + if (event instanceof Y.YArrayEvent) { + return translateYArrayEvent(sharedRoot, editor, event); + } + + throw new Error('Unexpected Y event type'); +} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/mapEvent.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/mapEvent.ts new file mode 100644 index 0000000000..d79c7d6d77 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/mapEvent.ts @@ -0,0 +1,12 @@ +import { YSharedRoot } from '@/application/document.type'; +import * as Y from 'yjs'; +import { Editor, Operation } from 'slate'; + +export function translateYMapEvent( + sharedRoot: YSharedRoot, + editor: Editor, + event: Y.YEvent> +): Operation[] { + console.log('translateYMapEvent', sharedRoot, editor, event); + return []; +} diff --git a/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/textEvent.ts b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/textEvent.ts new file mode 100644 index 0000000000..3dce8a3d59 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/slate-yjs/utils/translateYjsEvent/textEvent.ts @@ -0,0 +1,8 @@ +import { YSharedRoot } from '@/application/document.type'; +import * as Y from 'yjs'; +import { Editor, Operation } from 'slate'; + +export function translateYTextEvent(sharedRoot: YSharedRoot, editor: Editor, event: Y.YEvent): Operation[] { + console.log('translateYTextEvent', sharedRoot, editor, event); + return []; +} diff --git a/frontend/appflowy_web_app/src/application/services/user.type.ts b/frontend/appflowy_web_app/src/application/user.type.ts similarity index 84% rename from frontend/appflowy_web_app/src/application/services/user.type.ts rename to frontend/appflowy_web_app/src/application/user.type.ts index cda8647761..be64d574b4 100644 --- a/frontend/appflowy_web_app/src/application/services/user.type.ts +++ b/frontend/appflowy_web_app/src/application/user.type.ts @@ -10,17 +10,12 @@ export enum EncryptionType { } export interface UserProfile { - id?: string; + uid: number; + uuid?: string; email?: string; name?: string; - token?: string; iconUrl?: string; - openaiKey?: string; - authenticator?: Authenticator; - encryptionSign?: string; - encryptionType?: EncryptionType; workspaceId?: string; - stabilityAiKey?: string; } export interface Workspace { diff --git a/frontend/appflowy_web_app/src/application/ydoc/apply/__tests__/document.test.ts b/frontend/appflowy_web_app/src/application/ydoc/apply/__tests__/document.test.ts new file mode 100644 index 0000000000..13ff8fe6db --- /dev/null +++ b/frontend/appflowy_web_app/src/application/ydoc/apply/__tests__/document.test.ts @@ -0,0 +1,18 @@ +import { YjsEditorKey } from '@/application/document.type'; +import { applyDocument } from '@/application/ydoc/apply'; +import * as Y from 'yjs'; +import * as docJson from '../../../../../cypress/fixtures/simple_doc.json'; + +describe('apply document', () => { + it('should apply document', () => { + const collab = new Y.Doc(); + const data = collab.getMap(YjsEditorKey.data_section); + const document = new Y.Map(); + data.set(YjsEditorKey.document, document); + + const state = new Uint8Array(docJson.data.doc_state); + applyDocument(collab, state); + }); +}); + +export {}; diff --git a/frontend/appflowy_web_app/src/application/ydoc/apply/document.ts b/frontend/appflowy_web_app/src/application/ydoc/apply/document.ts new file mode 100644 index 0000000000..f79c08d68e --- /dev/null +++ b/frontend/appflowy_web_app/src/application/ydoc/apply/document.ts @@ -0,0 +1,18 @@ +import * as Y from 'yjs'; +import { CollabOrigin } from '@/application/collab.type'; + +/** + * Apply doc state from server to client + * Note: origin is always remote + * @param doc local Y.Doc + * @param state state from server + */ +export function applyDocument(doc: Y.Doc, state: Uint8Array) { + Y.transact( + doc, + () => { + Y.applyUpdate(doc, state); + }, + CollabOrigin.Remote + ); +} diff --git a/frontend/appflowy_web_app/src/application/ydoc/apply/index.ts b/frontend/appflowy_web_app/src/application/ydoc/apply/index.ts new file mode 100644 index 0000000000..8147823035 --- /dev/null +++ b/frontend/appflowy_web_app/src/application/ydoc/apply/index.ts @@ -0,0 +1 @@ +export * from 'src/application/ydoc/apply/document'; diff --git a/frontend/appflowy_web_app/src/components/_shared/context-provider/IdProvider.tsx b/frontend/appflowy_web_app/src/components/_shared/context-provider/IdProvider.tsx new file mode 100644 index 0000000000..98cbd4e2c5 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/_shared/context-provider/IdProvider.tsx @@ -0,0 +1,18 @@ +import { CollabType } from '@/application/collab.type'; +import { useContext, createContext } from 'react'; + +export const IdContext = createContext(null); + +interface IdProviderProps { + workspaceId: string; + objectId: string; + collabType: CollabType; +} + +export const IdProvider = ({ children, ...props }: IdProviderProps & { children: React.ReactNode }) => { + return {children}; +}; + +export function useId() { + return useContext(IdContext); +} diff --git a/frontend/appflowy_web_app/src/components/_shared/katex-math/KatexMath.tsx b/frontend/appflowy_web_app/src/components/_shared/katex-math/KatexMath.tsx new file mode 100644 index 0000000000..e6c7cac5ed --- /dev/null +++ b/frontend/appflowy_web_app/src/components/_shared/katex-math/KatexMath.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import 'katex/dist/katex.min.css'; +import { BlockMath, InlineMath } from 'react-katex'; +import './index.css'; + +function KatexMath({ latex, isInline = false }: { latex: string; isInline?: boolean }) { + return isInline ? ( + + ) : ( + { + return ( +
+ {error.name}: {error.message} +
+ ); + }} + > + {latex} +
+ ); +} + +export default KatexMath; diff --git a/frontend/appflowy_web_app/src/components/_shared/katex-math/index.css b/frontend/appflowy_web_app/src/components/_shared/katex-math/index.css new file mode 100644 index 0000000000..d127dc343b --- /dev/null +++ b/frontend/appflowy_web_app/src/components/_shared/katex-math/index.css @@ -0,0 +1,4 @@ + +.katex-html { + white-space: normal; +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/components/_shared/scroller/AFScroller.tsx b/frontend/appflowy_web_app/src/components/_shared/scroller/AFScroller.tsx new file mode 100644 index 0000000000..0527b6cc26 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/_shared/scroller/AFScroller.tsx @@ -0,0 +1,55 @@ +import { Scrollbars } from 'react-custom-scrollbars'; +import React from 'react'; + +export interface AFScrollerProps { + children: React.ReactNode; + overflowXHidden?: boolean; + overflowYHidden?: boolean; + className?: string; + style?: React.CSSProperties; +} +export const AFScroller = ({ style, children, overflowXHidden, overflowYHidden, className }: AFScrollerProps) => { + return ( +
} + renderThumbVertical={(props) =>
} + {...(overflowXHidden && { + renderTrackHorizontal: (props) => ( +
+ ), + })} + {...(overflowYHidden && { + renderTrackVertical: (props) => ( +
+ ), + })} + style={style} + renderView={(props) => ( +
+ )} + > + {children} + + ); +}; diff --git a/frontend/appflowy_web_app/src/components/_shared/scroller/index.ts b/frontend/appflowy_web_app/src/components/_shared/scroller/index.ts new file mode 100644 index 0000000000..7a740a5bb0 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/_shared/scroller/index.ts @@ -0,0 +1 @@ +export * from './AFScroller'; diff --git a/frontend/appflowy_web_app/src/components/app/App.tsx b/frontend/appflowy_web_app/src/components/app/App.tsx new file mode 100644 index 0000000000..e56499079f --- /dev/null +++ b/frontend/appflowy_web_app/src/components/app/App.tsx @@ -0,0 +1,27 @@ +import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import ProtectedRoutes from '@/components/auth/ProtectedRoutes'; +import LoginPage from '@/pages/LoginPage'; +import ProductPage from '@/pages/ProductPage'; +import withAppWrapper from '@/components/app/withAppWrapper'; + +const AppMain = withAppWrapper(() => { + return ( + + }> + } /> + + } /> + + ); +}); + +function App () { + return ( + + + + ); +} + +export default App; + diff --git a/frontend/appflowy_web_app/src/AppConfig.tsx b/frontend/appflowy_web_app/src/components/app/AppConfig.tsx similarity index 86% rename from frontend/appflowy_web_app/src/AppConfig.tsx rename to frontend/appflowy_web_app/src/components/app/AppConfig.tsx index 452d88e593..1308855bbc 100644 --- a/frontend/appflowy_web_app/src/AppConfig.tsx +++ b/frontend/appflowy_web_app/src/components/app/AppConfig.tsx @@ -5,13 +5,12 @@ import { useAppSelector } from '@/stores/store'; export const AFConfigContext = createContext< | { - service: AFService | undefined; - } + service: AFService | undefined; +} | undefined >(undefined); - -function AppConfig({ children }: { children: React.ReactNode }) { +function AppConfig ({ children }: { children: React.ReactNode }) { const appConfig = useAppSelector((state) => state.app.appConfig); const [service, setService] = useState(); @@ -26,7 +25,7 @@ function AppConfig({ children }: { children: React.ReactNode }) { () => ({ service, }), - [service] + [service], ); return {children}; diff --git a/frontend/appflowy_web_app/src/components/app/AppTheme.tsx b/frontend/appflowy_web_app/src/components/app/AppTheme.tsx new file mode 100644 index 0000000000..176adf539e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/app/AppTheme.tsx @@ -0,0 +1,181 @@ +import React, { useMemo } from 'react'; +import createTheme from '@mui/material/styles/createTheme'; +import ThemeProvider from '@mui/material/styles/ThemeProvider'; +import '@/i18n/config'; + +import 'src/styles/tailwind.css'; +import 'src/styles/template.css'; + +function AppTheme({ children }: { children: React.ReactNode }) { + const isDark = false; + const theme = useMemo( + () => + createTheme({ + typography: { + fontFamily: ['inherit'].join(','), + fontSize: 12, + button: { + textTransform: 'none', + }, + }, + components: { + MuiMenuItem: { + defaultProps: { + sx: { + '&.Mui-selected.Mui-focusVisible': { + backgroundColor: 'var(--fill-list-hover)', + }, + '&.Mui-focusVisible': { + backgroundColor: 'unset', + }, + }, + }, + }, + MuiIconButton: { + styleOverrides: { + root: { + '&:hover': { + backgroundColor: 'var(--fill-list-hover)', + }, + borderRadius: '4px', + padding: '2px', + }, + }, + }, + MuiButton: { + styleOverrides: { + contained: { + color: 'var(--content-on-fill)', + boxShadow: 'var(--shadow)', + }, + containedPrimary: { + '&:hover': { + backgroundColor: 'var(--fill-default)', + }, + }, + containedInherit: { + color: 'var(--text-title)', + backgroundColor: isDark ? 'rgba(0, 0, 0, 0.4)' : 'rgba(255, 255, 255, 0.4)', + '&:hover': { + backgroundColor: 'var(--bg-body)', + boxShadow: 'var(--shadow)', + }, + }, + outlinedInherit: { + color: 'var(--text-title)', + borderColor: 'var(--line-border)', + '&:hover': { + boxShadow: 'var(--shadow)', + }, + }, + }, + }, + MuiButtonBase: { + defaultProps: { + sx: { + '&.Mui-selected:hover': { + backgroundColor: 'var(--fill-list-hover)', + }, + }, + }, + styleOverrides: { + root: { + '&:hover': { + backgroundColor: 'var(--fill-list-hover)', + }, + '&:active': { + backgroundColor: 'var(--fill-list-hover)', + }, + borderRadius: '4px', + padding: '2px', + boxShadow: 'none', + }, + }, + }, + MuiPaper: { + styleOverrides: { + root: { + backgroundImage: 'none', + }, + }, + }, + MuiDialog: { + defaultProps: { + sx: { + '& .MuiBackdrop-root': { + backgroundColor: 'var(--bg-mask)', + }, + }, + }, + }, + + MuiTooltip: { + styleOverrides: { + arrow: { + color: 'var(--bg-tips)', + }, + tooltip: { + backgroundColor: 'var(--bg-tips)', + color: 'var(--text-title)', + fontSize: '0.85rem', + borderRadius: '8px', + fontWeight: 400, + }, + }, + }, + MuiInputBase: { + styleOverrides: { + input: { + backgroundColor: 'transparent !important', + }, + }, + }, + MuiDivider: { + styleOverrides: { + root: { + borderColor: 'var(--line-divider)', + }, + }, + }, + }, + palette: { + mode: isDark ? 'dark' : 'light', + primary: { + main: '#00BCF0', + dark: '#00BCF0', + }, + error: { + main: '#FB006D', + dark: '#D32772', + }, + warning: { + main: '#FFC107', + dark: '#E9B320', + }, + info: { + main: '#00BCF0', + dark: '#2E9DBB', + }, + success: { + main: '#66CF80', + dark: '#3BA856', + }, + text: { + primary: isDark ? '#E2E9F2' : '#333333', + secondary: isDark ? '#7B8A9D' : '#828282', + disabled: isDark ? '#363D49' : '#F2F2F2', + }, + divider: isDark ? '#59647A' : '#BDBDBD', + background: { + default: isDark ? '#1A202C' : '#FFFFFF', + paper: isDark ? '#1A202C' : '#FFFFFF', + }, + }, + }), + [isDark] + ); + + return {children}; +} + +export default AppTheme; diff --git a/frontend/appflowy_web_app/src/components/app/withAppWrapper.tsx b/frontend/appflowy_web_app/src/components/app/withAppWrapper.tsx new file mode 100644 index 0000000000..ca5bdcd100 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/app/withAppWrapper.tsx @@ -0,0 +1,27 @@ +import { Provider } from 'react-redux'; +import { store } from 'src/stores/store'; +import { ErrorBoundary } from 'react-error-boundary'; +import { ErrorHandlerPage } from 'src/components/error/ErrorHandlerPage'; +import AppTheme from '@/components/app/AppTheme'; +import { Toaster } from 'react-hot-toast'; +import AppConfig from '@/components/app/AppConfig'; +import { Suspense } from 'react'; + +export default function withAppWrapper (Component: React.FC): React.FC { + return function AppWrapper (): JSX.Element { + return ( + + + + + + + + + + + + + ); + }; +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/components/auth/LoginButtonGroup.tsx b/frontend/appflowy_web_app/src/components/auth/LoginButtonGroup.tsx index 27cdf746e1..cdc42611f0 100644 --- a/frontend/appflowy_web_app/src/components/auth/LoginButtonGroup.tsx +++ b/frontend/appflowy_web_app/src/components/auth/LoginButtonGroup.tsx @@ -4,7 +4,7 @@ import GithubIcon from '@/assets/settings/github.png'; import DiscordIcon from '@/assets/settings/discord.png'; import { useTranslation } from 'react-i18next'; import { useAuth } from './auth.hooks'; -import { ProviderType } from '@/application/services/user.type'; +import { ProviderType } from '@/application/user.type'; import { useState } from 'react'; import EmailOutlined from '@mui/icons-material/EmailOutlined'; import SignInWithEmail from './SignInWithEmail'; @@ -17,6 +17,7 @@ export const LoginButtonGroup = () => { return (
- setOpenSignInWithEmail(false)}/> + setOpenSignInWithEmail(false)} />
); }; diff --git a/frontend/appflowy_web_app/src/components/auth/ProtectedRoutes.tsx b/frontend/appflowy_web_app/src/components/auth/ProtectedRoutes.tsx index 33782e9724..0bb1c1abcf 100644 --- a/frontend/appflowy_web_app/src/components/auth/ProtectedRoutes.tsx +++ b/frontend/appflowy_web_app/src/components/auth/ProtectedRoutes.tsx @@ -7,22 +7,28 @@ import SplashScreen from '@/components/auth/SplashScreen'; import CircularProgress from '@mui/material/CircularProgress'; import Portal from '@mui/material/Portal'; import { ReactComponent as Logo } from '@/assets/logo.svg'; +import { useNavigate } from 'react-router-dom'; const TauriAuth = lazy(() => import('@/components/tauri/TauriAuth')); function ProtectedRoutes () { - const { currentUser, checkUser } = useAuth(); + const { currentUser, checkUser, isReady } = useAuth(); const isLoading = currentUser?.loginState === LoginState.LOADING; const [checked, setChecked] = useState(false); const checkUserStatus = useCallback(async () => { + if (!isReady) return; + setChecked(false); try { - await checkUser(); + if (!currentUser.isAuthenticated) { + await checkUser(); + } + } finally { setChecked(true); } - }, [checkUser]); + }, [checkUser, isReady, currentUser.isAuthenticated]); useEffect(() => { void checkUserStatus(); @@ -30,18 +36,26 @@ function ProtectedRoutes () { const platform = useMemo(() => getPlatform(), []); + const navigate = useNavigate(); + + console.log('ProtectedRoutes', currentUser, checked); + if (checked && !currentUser.isAuthenticated && window.location.pathname !== '/login') { + navigate(`/login?redirect=${encodeURIComponent(window.location.pathname)}`); + return null; + } + return (
{checked ? ( - + ) : (
- +
)} - {isLoading && } - {platform.isTauri && } + {isLoading && } + {platform.isTauri && }
); } @@ -68,7 +82,7 @@ const StartLoading = () => { return (
- +
); diff --git a/frontend/appflowy_web_app/src/components/auth/SignInWithEmail.tsx b/frontend/appflowy_web_app/src/components/auth/SignInWithEmail.tsx index 020af731ac..06d36c2594 100644 --- a/frontend/appflowy_web_app/src/components/auth/SignInWithEmail.tsx +++ b/frontend/appflowy_web_app/src/components/auth/SignInWithEmail.tsx @@ -9,10 +9,12 @@ function SignInWithEmail({ open, onClose }: { open: boolean; onClose: () => void const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const { signInWithEmailPassword } = useAuth(); + const handleSignIn = async () => { setLoading(true); try { await signInWithEmailPassword(email, password); + onClose(); } catch (e) { // Handle error } @@ -27,9 +29,11 @@ function SignInWithEmail({ open, onClose }: { open: boolean; onClose: () => void sx={{ zIndex: 1500, }} + data-cy={'signInWithEmailDialog'} PaperProps={{ className: 'w-[400px]', }} + keepMounted={false} onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); @@ -41,6 +45,7 @@ function SignInWithEmail({ open, onClose }: { open: boolean; onClose: () => void void /> void - diff --git a/frontend/appflowy_web_app/src/components/auth/SplashScreen.tsx b/frontend/appflowy_web_app/src/components/auth/SplashScreen.tsx index 4757ecdd5d..bf5a5a854d 100644 --- a/frontend/appflowy_web_app/src/components/auth/SplashScreen.tsx +++ b/frontend/appflowy_web_app/src/components/auth/SplashScreen.tsx @@ -1,22 +1,14 @@ import React from 'react'; import { Outlet } from 'react-router-dom'; import Layout from '@/components/layout/Layout'; -import Welcome from './Welcome'; -function SplashScreen({ - isAuthenticated, -}: { - isAuthenticated: boolean; -}) { - if (isAuthenticated) { - return ( - - - - ); - } else { - return ; - } +function SplashScreen () { + + return ( + + + + ); } export default SplashScreen; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/components/auth/Welcome.cy.tsx b/frontend/appflowy_web_app/src/components/auth/Welcome.cy.tsx new file mode 100644 index 0000000000..f0f83d366a --- /dev/null +++ b/frontend/appflowy_web_app/src/components/auth/Welcome.cy.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import Welcome from './Welcome'; +import withAppWrapper from '@/components/app/withAppWrapper'; + +describe('', () => { + beforeEach(() => { + cy.mockAPI(); + }); + + it('renders', () => { + const AppWrapper = withAppWrapper(Welcome); + + cy.mount(); + }); + + it('should handle login success', () => { + const AppWrapper = withAppWrapper(Welcome); + + cy.mount(); + + cy.get('[data-cy=signInWithEmail]').click(); + + cy.wait(100); + + cy.get('[data-cy=signInWithEmailDialog]').as('dialog').should('be.visible'); + cy.get('[data-cy=email]').type('fakeEmail123'); + cy.get('[data-cy=password]').type('fakePassword123'); + cy.get('[data-cy=submit]').click(); + cy.wait('@loginSuccess'); + cy.wait('@verifyToken'); + cy.wait('@getUserProfile'); + cy.get('@dialog').should('not.exist'); + }); +}); diff --git a/frontend/appflowy_web_app/src/components/auth/Welcome.tsx b/frontend/appflowy_web_app/src/components/auth/Welcome.tsx index b40bd25ded..1281c3336f 100644 --- a/frontend/appflowy_web_app/src/components/auth/Welcome.tsx +++ b/frontend/appflowy_web_app/src/components/auth/Welcome.tsx @@ -1,51 +1,39 @@ import { ReactComponent as AppflowyLogo } from '@/assets/logo.svg'; -import Button from '@mui/material/Button'; +import { Stack } from '@mui/material'; import { useTranslation } from 'react-i18next'; -import { useAuth } from './auth.hooks'; import { LoginButtonGroup } from './LoginButtonGroup'; +import { getPlatform } from '@/utils/platform'; +import { lazy } from 'react'; + +const SignInAsAnonymous = lazy(() => import('@/components/tauri/SignInAsAnonymous')); export const Welcome = () => { - const { signInAsAnonymous } = useAuth(); const { t } = useTranslation(); return ( <> -
e.preventDefault()} method="POST"> -
-
- + e.preventDefault()} method='POST'> + +
+
- + {t('welcomeTo')} {t('appName')}
-
- -
-
- {t('signIn.or')} -
-
+
+ {getPlatform().isTauri && }
- +
-
+ ); }; -export default Welcome; \ No newline at end of file +export default Welcome; diff --git a/frontend/appflowy_web_app/src/components/auth/auth.hooks.ts b/frontend/appflowy_web_app/src/components/auth/auth.hooks.ts index b21e7f881a..cb972283bf 100644 --- a/frontend/appflowy_web_app/src/components/auth/auth.hooks.ts +++ b/frontend/appflowy_web_app/src/components/auth/auth.hooks.ts @@ -2,22 +2,24 @@ import { useAppDispatch, useAppSelector } from '@/stores/store'; import { useCallback, useContext } from 'react'; import { nanoid } from 'nanoid'; import { open } from '@tauri-apps/api/shell'; -import { ProviderType, UserProfile } from '@/application/services/user.type'; +import { ProviderType, UserProfile } from '@/application/user.type'; import { currentUserActions } from '@/stores/currentUser/slice'; -import { AFConfigContext } from '@/AppConfig'; +import { AFConfigContext } from '@/components/app/AppConfig'; import { notify } from '@/components/_shared/notify'; export const useAuth = () => { const dispatch = useAppDispatch(); const AFConfig = useContext(AFConfigContext); const currentUser = useAppSelector((state) => state.currentUser); + const isReady = !!AFConfig?.service; const handleSuccess = useCallback(() => { notify.clear(); dispatch(currentUserActions.loginSuccess()); }, [dispatch]); + const setUser = useCallback( - async (userProfile: Partial) => { + async (userProfile: UserProfile) => { handleSuccess(); dispatch(currentUserActions.updateUser(userProfile)); }, @@ -41,8 +43,13 @@ export const useAuth = () => { // Check if the user is authenticated const checkUser = useCallback(async () => { - handleStart(); try { + const userHasSignIn = await AFConfig?.service?.userService.checkUser(); + + if (!userHasSignIn) { + throw new Error('Failed to check user'); + } + const userProfile = await AFConfig?.service?.userService.getUserProfile(); if (!userProfile) { @@ -53,13 +60,9 @@ export const useAuth = () => { return userProfile; } catch (e) { - handleError({ - message: 'Failed to check user', - }); - return Promise.reject('Failed to check user'); } - }, [AFConfig?.service?.userService, handleError, handleStart, setUser]); + }, [AFConfig?.service?.userService, setUser]); const register = useCallback( async (email: string, password: string, name: string): Promise => { @@ -114,7 +117,7 @@ export const useAuth = () => { const url = await AFConfig?.service?.authService.getOAuthURL(provider); if (!url) { - throw new Error('Failed to sign in'); + throw new Error(); } await open(url); @@ -135,7 +138,7 @@ export const useAuth = () => { const userProfile = await AFConfig?.service?.userService.getUserProfile(); if (!userProfile) { - throw new Error('Failed to sign in'); + throw new Error(); } await setUser(userProfile); @@ -154,10 +157,12 @@ export const useAuth = () => { async (email: string, password: string) => { handleStart(); try { - const userProfile = await AFConfig?.service?.authService.signinWithEmailPassword(email, password); + await AFConfig?.service?.authService.signinWithEmailPassword(email, password); + + const userProfile = await AFConfig?.service?.userService.getUserProfile(); if (!userProfile) { - throw new Error('Failed to sign in'); + throw new Error(); } await setUser(userProfile); @@ -169,10 +174,11 @@ export const useAuth = () => { }); } }, - [AFConfig?.service?.authService, handleError, handleStart, setUser] + [AFConfig?.service?.authService, AFConfig?.service?.userService, handleError, handleStart, setUser] ); return { + isReady, currentUser, checkUser, register, diff --git a/frontend/appflowy_web_app/src/components/document/Document.tsx b/frontend/appflowy_web_app/src/components/document/Document.tsx new file mode 100644 index 0000000000..43020886e1 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/document/Document.tsx @@ -0,0 +1,19 @@ +import { useId } from '@/components/_shared/context-provider/IdProvider'; +import { Editor } from '@/components/editor'; +import React from 'react'; + +export const Document = () => { + const { objectId: documentId, workspaceId } = useId() || {}; + + if (!documentId || !workspaceId) return null; + + return ( +
+
+
+ +
+
+
+ ); +}; diff --git a/frontend/appflowy_web_app/src/components/document/index.ts b/frontend/appflowy_web_app/src/components/document/index.ts new file mode 100644 index 0000000000..a844aa51ad --- /dev/null +++ b/frontend/appflowy_web_app/src/components/document/index.ts @@ -0,0 +1 @@ +export * from './Document'; diff --git a/frontend/appflowy_web_app/src/components/editor/CollaborativeEditor.tsx b/frontend/appflowy_web_app/src/components/editor/CollaborativeEditor.tsx new file mode 100644 index 0000000000..4d251701b7 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/CollaborativeEditor.tsx @@ -0,0 +1,33 @@ +import { withYjs, YjsEditor } from '@/application/slate-yjs/plugins/withYjs'; +import EditorEditable from '@/components/editor/Editable'; +import { withPlugins } from '@/components/editor/plugins'; +import React, { useEffect, useMemo, useState } from 'react'; +import { createEditor, Descendant } from 'slate'; +import { Slate, withReact } from 'slate-react'; +import * as Y from 'yjs'; + +const defaultInitialValue: Descendant[] = []; + +function CollaborativeEditor({ doc }: { doc: Y.Doc }) { + const editor = useMemo(() => doc && (withPlugins(withReact(withYjs(createEditor(), doc))) as YjsEditor), [doc]); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_, setIsConnected] = useState(false); + + useEffect(() => { + if (!editor) return; + editor.connect(); + setIsConnected(true); + + return () => { + editor.disconnect(); + }; + }, [editor]); + + return ( + + + + ); +} + +export default CollaborativeEditor; diff --git a/frontend/appflowy_web_app/src/components/editor/Editable.tsx b/frontend/appflowy_web_app/src/components/editor/Editable.tsx new file mode 100644 index 0000000000..e712fc88fd --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/Editable.tsx @@ -0,0 +1,35 @@ +import { useDecorate } from '@/components/editor/components/blocks/code/useDecorate'; +import { Leaf } from '@/components/editor/components/leaf'; +import { useEditorContext } from '@/components/editor/EditorContext'; +import React, { useCallback } from 'react'; +import { NodeEntry } from 'slate'; +import { Editable, ReactEditor } from 'slate-react'; +import { Element } from './components/element'; + +const EditorEditable = ({ editor }: { editor: ReactEditor }) => { + const { readOnly } = useEditorContext(); + const codeDecorate = useDecorate(editor); + + const decorate = useCallback( + (entry: NodeEntry) => { + return [...codeDecorate(entry)]; + }, + [codeDecorate] + ); + + return ( + + ); +}; + +export default EditorEditable; diff --git a/frontend/appflowy_web_app/src/components/editor/Editor.cy.tsx b/frontend/appflowy_web_app/src/components/editor/Editor.cy.tsx new file mode 100644 index 0000000000..dd007fbb97 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/Editor.cy.tsx @@ -0,0 +1,37 @@ +import { JSDocumentService } from '@/application/services/js-services/document.service'; +import { DocumentTest } from '@/../cypress/support/document'; +import { nanoid } from 'nanoid'; +import React from 'react'; +import { Editor } from './Editor'; +import withAppWrapper from '@/components/app/withAppWrapper'; + +describe('', () => { + it('renders with a paragraph', () => { + const documentTest = new DocumentTest(); + + documentTest.insertParagraph('Hello, world!'); + cy.stub(JSDocumentService.prototype, 'openDocument').returns(Promise.resolve(documentTest.doc)); + renderEditor(); + cy.get('[role="textbox"]').should('contain', 'Hello, world!'); + }); + + it('renders with a full document', () => { + cy.mockFullDocument(); + renderEditor(); + }); +}); + +function renderEditor() { + const documentId = nanoid(8); + const workspaceId = nanoid(8); + + const AppWrapper = withAppWrapper(() => { + return ( +
+ +
+ ); + }); + + cy.mount(); +} diff --git a/frontend/appflowy_web_app/src/components/editor/Editor.tsx b/frontend/appflowy_web_app/src/components/editor/Editor.tsx new file mode 100644 index 0000000000..713f5b3371 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/Editor.tsx @@ -0,0 +1,48 @@ +import { AFConfigContext } from '@/components/app/AppConfig'; +import CollaborativeEditor from '@/components/editor/CollaborativeEditor'; +import { EditorContextProvider } from '@/components/editor/EditorContext'; +import { CircularProgress } from '@mui/material'; +import React, { useCallback, useContext, useEffect, useState } from 'react'; +import * as Y from 'yjs'; +import './editor.scss'; + +export const Editor = ({ + workspaceId, + documentId, + readOnly, +}: { + documentId: string; + workspaceId: string; + readOnly: boolean; +}) => { + const [doc, setDoc] = useState(); + + const documentService = useContext(AFConfigContext)?.service?.documentService; + + const handleOpenDocument = useCallback(async () => { + if (!documentService) return; + const doc = await documentService.openDocument(workspaceId, documentId); + + setDoc(doc); + }, [documentService, workspaceId, documentId]); + + useEffect(() => { + void handleOpenDocument(); + }, [handleOpenDocument]); + + if (!doc) { + return ( +
+ +
+ ); + } + + return ( + + + + ); +}; + +export default Editor; diff --git a/frontend/appflowy_web_app/src/components/editor/EditorContext.tsx b/frontend/appflowy_web_app/src/components/editor/EditorContext.tsx new file mode 100644 index 0000000000..7b4162891e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/EditorContext.tsx @@ -0,0 +1,17 @@ +import { createContext, useContext } from 'react'; + +interface EditorContextState { + readOnly: boolean; +} + +export const EditorContext = createContext({ + readOnly: true, +}); + +export const EditorContextProvider = ({ children, ...props }: EditorContextState & { children: React.ReactNode }) => { + return {children}; +}; + +export function useEditorContext() { + return useContext(EditorContext); +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedList.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedList.tsx new file mode 100644 index 0000000000..53552336d2 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedList.tsx @@ -0,0 +1,16 @@ +import { BulletedListNode, EditorElementProps } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; + +export const BulletedList = memo( + forwardRef>( + ({ node: _, children, className, ...attributes }, ref) => { + return ( +
+ {children} +
+ ); + } + ) +); + +export default BulletedList; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedListIcon.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedListIcon.tsx new file mode 100644 index 0000000000..62e06b6ba9 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/BulletedListIcon.tsx @@ -0,0 +1,49 @@ +import { BulletedListNode } from '@/components/editor/editor.type'; +import { getListLevel } from '@/components/editor/utils/list'; +import React, { useMemo } from 'react'; +import { ReactEditor, useSlateStatic } from 'slate-react'; + +enum Letter { + Disc, + Circle, + Square, +} + +export function BulletedListIcon({ block, className }: { block: BulletedListNode; className: string }) { + const staticEditor = useSlateStatic(); + const path = ReactEditor.findPath(staticEditor, block); + + const letter = useMemo(() => { + const level = getListLevel(staticEditor, block.type, path); + + if (level % 3 === 0) { + return Letter.Disc; + } else if (level % 3 === 1) { + return Letter.Circle; + } else { + return Letter.Square; + } + }, [block.type, staticEditor, path]); + + const dataLetter = useMemo(() => { + switch (letter) { + case Letter.Disc: + return '•'; + case Letter.Circle: + return '◦'; + case Letter.Square: + return '▪'; + } + }, [letter]); + + return ( + { + e.preventDefault(); + }} + data-letter={dataLetter} + contentEditable={false} + className={`${className} bulleted-icon flex min-w-[24px] justify-center pr-1 font-medium`} + /> + ); +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/index.ts new file mode 100644 index 0000000000..393f4a03aa --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/bulleted_list/index.ts @@ -0,0 +1,2 @@ +export * from './BulletedList'; +export * from './BulletedListIcon'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/Callout.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/Callout.tsx new file mode 100644 index 0000000000..a60255f951 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/Callout.tsx @@ -0,0 +1,22 @@ +import { EditorElementProps, CalloutNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; +import CalloutIcon from './CalloutIcon'; + +export const Callout = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + return ( + <> +
+ +
+
+
+ {children} +
+
+ + ); + }) +); + +export default Callout; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/CalloutIcon.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/CalloutIcon.tsx new file mode 100644 index 0000000000..f8e570e2cf --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/CalloutIcon.tsx @@ -0,0 +1,17 @@ +import { CalloutNode } from '@/components/editor/editor.type'; +import React, { useRef } from 'react'; +import { IconButton } from '@mui/material'; + +function CalloutIcon({ node }: { node: CalloutNode }) { + const ref = useRef(null); + + return ( + <> + + {node.data.icon} + + + ); +} + +export default React.memo(CalloutIcon); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/index.ts new file mode 100644 index 0000000000..4ca74e4be8 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/callout/index.ts @@ -0,0 +1 @@ +export * from './Callout'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.hooks.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.hooks.ts new file mode 100644 index 0000000000..b7bb3500af --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.hooks.ts @@ -0,0 +1,27 @@ +import { CodeNode } from '@/components/editor/editor.type'; +import { useCallback } from 'react'; +import { ReactEditor, useSlateStatic } from 'slate-react'; +import { Element as SlateElement, Transforms } from 'slate'; + +export function useCodeBlock(node: CodeNode) { + const language = node.data.language; + const editor = useSlateStatic() as ReactEditor; + const handleChangeLanguage = useCallback( + (newLang: string) => { + const path = ReactEditor.findPath(editor, node); + const newProperties = { + data: { + language: newLang, + }, + } as Partial; + + Transforms.setNodes(editor, newProperties, { at: path }); + }, + [editor, node] + ); + + return { + language, + handleChangeLanguage, + }; +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.tsx new file mode 100644 index 0000000000..4a3b0be961 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/Code.tsx @@ -0,0 +1,26 @@ +import { useCodeBlock } from '@/components/editor/components/blocks/code/Code.hooks'; +import { CodeNode, EditorElementProps } from '@/components/editor/editor.type'; +import { forwardRef, memo } from 'react'; +import LanguageSelect from './SelectLanguage'; + +export const CodeBlock = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const { language, handleChangeLanguage } = useCodeBlock(node); + + return ( + <> +
+ +
+
+
+            {children}
+          
+
+ + ); + }) +); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/SelectLanguage.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/SelectLanguage.tsx new file mode 100644 index 0000000000..f249a19951 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/SelectLanguage.tsx @@ -0,0 +1,43 @@ +import React, { useRef } from 'react'; +import { TextField } from '@mui/material'; +import { useTranslation } from 'react-i18next'; + +function SelectLanguage({ + readOnly, + language = 'json', +}: { + readOnly?: boolean; + language: string; + onChangeLanguage: (language: string) => void; + onBlur?: () => void; +}) { + const { t } = useTranslation(); + const ref = useRef(null); + + return ( + <> + { + if (readOnly) return; + }} + InputProps={{ + readOnly: true, + }} + placeholder={t('document.codeBlock.language.placeholder')} + label={t('document.codeBlock.language.label')} + /> + + ); +} + +export default SelectLanguage; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/constants.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/constants.ts new file mode 100644 index 0000000000..dee71624db --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/constants.ts @@ -0,0 +1,154 @@ +export const supportLanguage = [ + { + id: 'bash', + title: 'Bash', + }, + { + id: 'basic', + title: 'Basic', + }, + { + id: 'c', + title: 'C', + }, + { + id: 'clojure', + title: 'Clojure', + }, + { + id: 'cpp', + title: 'C++', + }, + { + id: 'cs', + title: 'CS', + }, + { + id: 'css', + title: 'CSS', + }, + { + id: 'dart', + title: 'Dart', + }, + { + id: 'elixir', + title: 'Elixir', + }, + { + id: 'elm', + title: 'Elm', + }, + { + id: 'erlang', + title: 'Erlang', + }, + { + id: 'fortran', + title: 'Fortran', + }, + { + id: 'go', + title: 'Go', + }, + { + id: 'graphql', + title: 'GraphQL', + }, + { + id: 'haskell', + title: 'Haskell', + }, + { + id: 'java', + title: 'Java', + }, + { + id: 'javascript', + title: 'JavaScript', + }, + { + id: 'json', + title: 'JSON', + }, + { + id: 'kotlin', + title: 'Kotlin', + }, + { + id: 'lisp', + title: 'Lisp', + }, + { + id: 'lua', + title: 'Lua', + }, + { + id: 'markdown', + title: 'Markdown', + }, + { + id: 'matlab', + title: 'Matlab', + }, + { + id: 'ocaml', + title: 'OCaml', + }, + { + id: 'perl', + title: 'Perl', + }, + { + id: 'php', + title: 'PHP', + }, + { + id: 'powershell', + title: 'Powershell', + }, + { + id: 'python', + title: 'Python', + }, + { + id: 'r', + title: 'R', + }, + { + id: 'ruby', + title: 'Ruby', + }, + { + id: 'rust', + title: 'Rust', + }, + { + id: 'scala', + title: 'Scala', + }, + { + id: 'shell', + title: 'Shell', + }, + { + id: 'sql', + title: 'SQL', + }, + { + id: 'swift', + title: 'Swift', + }, + { + id: 'typescript', + title: 'TypeScript', + }, + { + id: 'xml', + title: 'XML', + }, + { + id: 'yaml', + title: 'YAML', + }, +]; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/index.ts new file mode 100644 index 0000000000..c3aa9443d1 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/index.ts @@ -0,0 +1 @@ +export * from './Code'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/useDecorate.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/useDecorate.ts new file mode 100644 index 0000000000..deac180c42 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/useDecorate.ts @@ -0,0 +1,33 @@ +import { BlockType } from '@/application/document.type'; +import { decorateCode } from '@/components/editor/components/blocks/code/utils'; +import { CodeNode } from '@/components/editor/editor.type'; +import { useCallback } from 'react'; +import { BaseRange, Editor, NodeEntry, Element } from 'slate'; +import { ReactEditor } from 'slate-react'; + +export function useDecorate(editor: ReactEditor) { + return useCallback( + (entry: NodeEntry): BaseRange[] => { + const path = entry[1]; + + const blockEntry = editor.above({ + at: path, + match: (n) => + !Editor.isEditor(n) && Element.isElement(n) && n.blockId !== undefined && n.type === BlockType.CodeBlock, + }); + + if (!blockEntry) return []; + + const block = blockEntry[0] as CodeNode; + + if (block.type === BlockType.CodeBlock) { + const language = block.data.language; + + return decorateCode(entry, language, false); + } + + return []; + }, + [editor] + ); +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/code/utils.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/utils.ts new file mode 100644 index 0000000000..458d9e8d7b --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/code/utils.ts @@ -0,0 +1,137 @@ +import Prism from 'prismjs'; + +import 'prismjs/components/prism-bash'; +import 'prismjs/components/prism-basic'; +import 'prismjs/components/prism-c'; +import 'prismjs/components/prism-clojure'; +import 'prismjs/components/prism-cpp'; +import 'prismjs/components/prism-csp'; +import 'prismjs/components/prism-css'; +import 'prismjs/components/prism-dart'; +import 'prismjs/components/prism-elixir'; +import 'prismjs/components/prism-elm'; +import 'prismjs/components/prism-erlang'; +import 'prismjs/components/prism-fortran'; +import 'prismjs/components/prism-go'; +import 'prismjs/components/prism-graphql'; +import 'prismjs/components/prism-haskell'; +import 'prismjs/components/prism-java'; +import 'prismjs/components/prism-javascript'; +import 'prismjs/components/prism-json'; +import 'prismjs/components/prism-kotlin'; +import 'prismjs/components/prism-lisp'; +import 'prismjs/components/prism-lua'; +import 'prismjs/components/prism-markdown'; +import 'prismjs/components/prism-matlab'; +import 'prismjs/components/prism-ocaml'; +import 'prismjs/components/prism-perl'; +import 'prismjs/components/prism-php'; +import 'prismjs/components/prism-powershell'; +import 'prismjs/components/prism-python'; +import 'prismjs/components/prism-r'; +import 'prismjs/components/prism-ruby'; +import 'prismjs/components/prism-rust'; +import 'prismjs/components/prism-scala'; +import 'prismjs/components/prism-shell-session'; +import 'prismjs/components/prism-sql'; +import 'prismjs/components/prism-swift'; +import 'prismjs/components/prism-typescript'; +import 'prismjs/components/prism-xml-doc'; +import 'prismjs/components/prism-yaml'; + +import { BaseRange, NodeEntry, Text, Path } from 'slate'; + +const push_string = ( + token: string | Prism.Token, + path: Path, + start: number, + ranges: BaseRange[], + token_type = 'text' +) => { + let newStart = start; + + ranges.push({ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + prism_token: token_type, + anchor: { path, offset: newStart }, + focus: { path, offset: newStart + token.length }, + }); + newStart += token.length; + return newStart; +}; + +// This recurses through the Prism.tokenizes result and creates stylized ranges based on the token type +const recurseTokenize = ( + token: string | Prism.Token, + path: Path, + ranges: BaseRange[], + start: number, + parent_tag?: string +) => { + // Uses the parent's token type if a Token only has a string as its content + if (typeof token === 'string') { + return push_string(token, path, start, ranges, parent_tag); + } + + if ('content' in token) { + if (token.content instanceof Array) { + // Calls recurseTokenize on nested Tokens in content + let newStart = start; + + for (const subToken of token.content) { + newStart = recurseTokenize(subToken, path, ranges, newStart, token.type) || 0; + } + + return newStart; + } + + return push_string(token.content, path, start, ranges, token.type); + } +}; + +function switchCodeTheme(isDark: boolean) { + const link = document.getElementById('prism-css'); + + if (link && link.classList.contains('dark') === isDark) { + return; + } + + if (link) { + document.head.removeChild(link); + } + + const newLink = document.createElement('link'); + + newLink.rel = 'stylesheet'; + newLink.href = isDark + ? 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism-dark.min.css' + : 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.24.1/themes/prism.min.css'; + newLink.id = 'prism-css'; + newLink.classList.add(isDark ? 'dark' : 'light'); + document.head.appendChild(newLink); +} + +export const decorateCode = ([node, path]: NodeEntry, language: string, isDark: boolean) => { + switchCodeTheme(isDark); + + const ranges: BaseRange[] = []; + + if (!Text.isText(node)) { + return ranges; + } + + try { + const tokens = Prism.tokenize(node.text, Prism.languages[language.toLowerCase()]); + + let start = 0; + + for (const token of tokens) { + start = recurseTokenize(token, path, ranges, start) || 0; + } + + return ranges; + } catch { + return ranges; + } +}; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/DividerNode.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/DividerNode.tsx new file mode 100644 index 0000000000..450f865b79 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/DividerNode.tsx @@ -0,0 +1,30 @@ +import { EditorElementProps, DividerNode as DividerBlock } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useMemo } from 'react'; +import { useSelected } from 'slate-react'; + +export const DividerNode = memo( + forwardRef>( + ({ node: _node, children: children, ...attributes }, ref) => { + const selected = useSelected(); + + const className = useMemo(() => { + return `${attributes.className ?? ''} divider-node relative w-full rounded ${ + selected ? 'bg-content-blue-100' : '' + }`; + }, [attributes.className, selected]); + + return ( +
+
+
+
+
+ {children} +
+
+ ); + } + ) +); + +export default DividerNode; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/index.ts new file mode 100644 index 0000000000..8f6141749a --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/divider/index.ts @@ -0,0 +1 @@ +export * from './DividerNode'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/Heading.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/Heading.tsx new file mode 100644 index 0000000000..8d4351a2d0 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/Heading.tsx @@ -0,0 +1,20 @@ +import { getHeadingCssProperty } from './utils'; +import { EditorElementProps, HeadingNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; + +export const Heading = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const level = node.data.level; + const fontSizeCssProperty = getHeadingCssProperty(level); + + const className = `${attributes.className ?? ''} ${fontSizeCssProperty} level-${level}`; + + return ( +
+ {children} +
+ ); + }) +); + +export default Heading; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/index.ts new file mode 100644 index 0000000000..a202e12acd --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/index.ts @@ -0,0 +1,2 @@ +export * from './utils'; +export * from './Heading'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/utils.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/utils.ts new file mode 100644 index 0000000000..bab542fc84 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/heading/utils.ts @@ -0,0 +1,18 @@ +export function getHeadingCssProperty(level: number) { + switch (level) { + case 1: + return 'text-3xl pt-[10px] pb-[8px] font-bold'; + case 2: + return 'text-2xl pt-[8px] pb-[6px] font-bold'; + case 3: + return 'text-xl pt-[4px] font-bold'; + case 4: + return 'text-lg pt-[4px] font-bold'; + case 5: + return 'text-base pt-[4px] font-bold'; + case 6: + return 'text-sm pt-[4px] font-bold'; + default: + return ''; + } +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageBlock.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageBlock.tsx new file mode 100644 index 0000000000..9adaf3f4c1 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageBlock.tsx @@ -0,0 +1,56 @@ +import { AlignType } from '@/application/document.type'; +import { EditorElementProps, ImageBlockNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useCallback, useMemo, useRef } from 'react'; +import { ReactEditor, useSelected, useSlateStatic } from 'slate-react'; +import ImageEmpty from './ImageEmpty'; +import ImageRender from './ImageRender'; + +export const ImageBlock = memo( + forwardRef>(({ node, children, className, ...attributes }, ref) => { + const selected = useSelected(); + const { url, align } = useMemo(() => node.data || {}, [node.data]); + const containerRef = useRef(null); + const editor = useSlateStatic(); + const onFocusNode = useCallback(() => { + ReactEditor.focus(editor); + const path = ReactEditor.findPath(editor, node); + + editor.select(path); + }, [editor, node]); + + const alignCss = useMemo(() => { + if (!align) return ''; + + return align === AlignType.Center ? 'justify-center' : align === AlignType.Right ? 'justify-end' : 'justify-start'; + }, [align]); + + return ( +
{ + if (!selected) onFocusNode(); + }} + className={`${className || ''} image-block relative w-full cursor-pointer py-1`} + > +
+ {children} +
+
+ {url ? ( + + ) : ( + + )} +
+
+ ); + }) +); + +export default ImageBlock; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageEmpty.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageEmpty.tsx new file mode 100644 index 0000000000..ab95cbe37d --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageEmpty.tsx @@ -0,0 +1,23 @@ +import { ImageBlockNode } from '@/components/editor/editor.type'; +import React from 'react'; +import { ReactComponent as ImageIcon } from '@/assets/image.svg'; +import { useTranslation } from 'react-i18next'; + +function ImageEmpty(_: { containerRef: React.RefObject; onEscape: () => void; node: ImageBlockNode }) { + const { t } = useTranslation(); + + return ( + <> +
+ + {t('document.plugins.image.addAnImage')} +
+ + ); +} + +export default ImageEmpty; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageRender.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageRender.tsx new file mode 100644 index 0000000000..55677506b3 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/ImageRender.tsx @@ -0,0 +1,77 @@ +import { ImageBlockNode } from '@/components/editor/editor.type'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { CircularProgress } from '@mui/material'; +import { ErrorOutline } from '@mui/icons-material'; + +const MIN_WIDTH = 100; + +function ImageRender({ selected, node }: { selected: boolean; node: ImageBlockNode }) { + const [loading, setLoading] = useState(true); + const [hasError, setHasError] = useState(false); + + const imgRef = useRef(null); + const { url = '', width: imageWidth } = useMemo(() => node.data || {}, [node.data]); + const { t } = useTranslation(); + const blockId = node.blockId; + const [initialWidth, setInitialWidth] = useState(null); + const [newWidth] = useState(imageWidth ?? null); + + useEffect(() => { + if (!loading && !hasError && initialWidth === null && imgRef.current) { + setInitialWidth(imgRef.current.offsetWidth); + } + }, [hasError, initialWidth, loading]); + const imageProps: React.ImgHTMLAttributes = useMemo(() => { + return { + style: { width: loading || hasError ? '0' : newWidth ?? '100%', opacity: selected ? 0.8 : 1 }, + className: 'object-cover', + ref: imgRef, + src: url, + draggable: false, + onLoad: () => { + setHasError(false); + setLoading(false); + }, + onError: () => { + setHasError(true); + setLoading(false); + }, + }; + }, [url, newWidth, loading, hasError, selected]); + + const renderErrorNode = useCallback(() => { + return ( +
+ +
{t('editor.imageLoadFailed')}
+
+ ); + }, [t]); + + if (!url) return null; + + return ( +
+ {`image-${blockId}`} + {hasError ? ( + renderErrorNode() + ) : loading ? ( +
+ +
{t('editor.loading')}
+
+ ) : null} +
+ ); +} + +export default ImageRender; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/image/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/index.ts new file mode 100644 index 0000000000..73c3003a92 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/image/index.ts @@ -0,0 +1 @@ +export * from './ImageBlock'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/MathEquation.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/MathEquation.tsx new file mode 100644 index 0000000000..db00aeb777 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/MathEquation.tsx @@ -0,0 +1,44 @@ +import KatexMath from '@/components/_shared/katex-math/KatexMath'; +import { EditorElementProps, MathEquationNode } from '@/components/editor/editor.type'; +import { FunctionsOutlined } from '@mui/icons-material'; +import { forwardRef, memo, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; + +export const MathEquation = memo( + forwardRef>( + ({ node, children, className, ...attributes }, ref) => { + const formula = node.data.formula; + const { t } = useTranslation(); + const containerRef = useRef(null); + + return ( + <> +
+
+ {formula ? ( + + ) : ( +
+ + {t('document.plugins.mathEquation.addMathEquation')} +
+ )} +
+
+ {children} +
+
+ + ); + } + ) +); + +export default MathEquation; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/index.ts new file mode 100644 index 0000000000..27b52f50f2 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/math_equation/index.ts @@ -0,0 +1,5 @@ +import { lazy } from 'react'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error +export const MathEquation = lazy(() => import('./MathEquation?chunkName=formula')); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberListIcon.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberListIcon.tsx new file mode 100644 index 0000000000..12b4c5d0e2 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberListIcon.tsx @@ -0,0 +1,84 @@ +import { NumberedListNode } from '@/components/editor/editor.type'; +import { getListLevel, letterize, romanize } from '@/components/editor/utils/list'; +import React, { useMemo } from 'react'; +import { ReactEditor, useSlate, useSlateStatic } from 'slate-react'; +import { Element, Path } from 'slate'; + +enum Letter { + Number = 'number', + Letter = 'letter', + Roman = 'roman', +} + +function getLetterNumber(index: number, letter: Letter) { + if (letter === Letter.Number) { + return index; + } else if (letter === Letter.Letter) { + return letterize(index); + } else { + return romanize(index); + } +} + +export function NumberListIcon({ block, className }: { block: NumberedListNode; className: string }) { + const editor = useSlate(); + const staticEditor = useSlateStatic(); + + const path = ReactEditor.findPath(editor, block); + const index = useMemo(() => { + let index = 1; + + let topNode; + let prevPath = Path.previous(path); + + while (prevPath) { + const prev = editor.node(prevPath); + + const prevNode = prev[0] as Element; + + if (prevNode.type === block.type) { + index += 1; + topNode = prevNode; + } else { + break; + } + + prevPath = Path.previous(prevPath); + } + + if (!topNode) { + return Number(block.data?.number ?? 1); + } + + const startIndex = (topNode as NumberedListNode).data?.number ?? 1; + + return index + Number(startIndex) - 1; + }, [editor, block, path]); + + const letter = useMemo(() => { + const level = getListLevel(staticEditor, block.type, path); + + if (level % 3 === 0) { + return Letter.Number; + } else if (level % 3 === 1) { + return Letter.Letter; + } else { + return Letter.Roman; + } + }, [block.type, staticEditor, path]); + + const dataNumber = useMemo(() => { + return getLetterNumber(index, letter); + }, [index, letter]); + + return ( + { + e.preventDefault(); + }} + contentEditable={false} + data-number={dataNumber} + className={`${className} numbered-icon flex w-[24px] min-w-[24px] justify-center pr-1 font-medium`} + /> + ); +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberedList.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberedList.tsx new file mode 100644 index 0000000000..9b10389944 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/NumberedList.tsx @@ -0,0 +1,16 @@ +import { EditorElementProps, NumberedListNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; + +export const NumberedList = memo( + forwardRef>( + ({ node: _, children, className, ...attributes }, ref) => { + return ( +
+ {children} +
+ ); + } + ) +); + +export default NumberedList; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/index.ts new file mode 100644 index 0000000000..df030e8e83 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/numbered_list/index.ts @@ -0,0 +1,2 @@ +export * from './NumberedList'; +export * from './NumberListIcon'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/Outline.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/Outline.tsx new file mode 100644 index 0000000000..d28e872425 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/Outline.tsx @@ -0,0 +1,59 @@ +import { extractHeadings, nestHeadings } from '@/components/editor/components/blocks/outline/utils'; +import { EditorElementProps, HeadingNode, OutlineNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useCallback, useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useSlate } from 'slate-react'; + +export const Outline = memo( + forwardRef>(({ node, children, className, ...attributes }, ref) => { + const editor = useSlate(); + const [root, setRoot] = useState([]); + const { t } = useTranslation(); + + useEffect(() => { + const root = nestHeadings(extractHeadings(editor.children, node.data.depth || 6)); + + setRoot(root); + }, [editor, node.data.depth]); + + const jumpToHeading = useCallback((heading: HeadingNode) => { + const id = `heading-${heading.blockId}`; + + const element = document.getElementById(id); + + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + }, []); + + const renderHeading = useCallback( + (heading: HeadingNode, index: number) => { + const children = (heading.children as HeadingNode[]).map(renderHeading); + const { text, level } = heading.data as { text: string; level: number }; + + return ( +
jumpToHeading(heading)} className={`my-1 ml-4 `} key={`${level}-${index}`}> +
{text}
+ +
{children}
+
+ ); + }, + [jumpToHeading] + ); + + return ( +
+
+ {children} +
+
+
{t('document.outlineBlock.placeholder')}
+ {root.map(renderHeading)} +
+
+ ); + }) +); + +export default Outline; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/index.ts new file mode 100644 index 0000000000..739fdf04f6 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/index.ts @@ -0,0 +1 @@ +export * from './Outline'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/utils.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/utils.ts new file mode 100644 index 0000000000..d5c61d1f0e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/outline/utils.ts @@ -0,0 +1,54 @@ +import { BlockType } from '@/application/document.type'; +import { HeadingNode } from '@/components/editor/editor.type'; +import { Element, Text } from 'slate'; + +export function extractHeadings(blocks: (Element | Text)[], maxDepth: number): HeadingNode[] { + const headings: HeadingNode[] = []; + + function traverse(children: (Element | Text)[]) { + for (const block of children) { + if (Text.isText(block)) continue; + if (block.type === BlockType.HeadingBlock && (block as HeadingNode).data?.level <= maxDepth) { + const texts = (block.children[0] as Element).children as Text[]; + + headings.push({ + ...block, + data: { + level: (block as HeadingNode).data.level, + text: texts.map((node) => node.text).join(''), + }, + children: [], + } as HeadingNode); + } else { + traverse(block.children); + } + } + + return headings; + } + + return traverse(blocks); +} + +export function nestHeadings(headings: HeadingNode[]): HeadingNode[] { + const root: HeadingNode[] = []; + const stack: HeadingNode[] = []; + + headings.forEach((heading) => { + const node = { ...heading, children: [] }; + + while (stack.length > 0 && stack[stack.length - 1].data.level >= node.data.level) { + stack.pop(); + } + + if (stack.length === 0) { + root.push(node); + } else { + stack[stack.length - 1].children.push(node); + } + + stack.push(node); + }); + + return root; +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/page/Page.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/page/Page.tsx new file mode 100644 index 0000000000..e0d3b4e293 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/page/Page.tsx @@ -0,0 +1,18 @@ +import { EditorElementProps, PageNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useMemo } from 'react'; + +export const Page = memo( + forwardRef>(({ node: _, children, ...attributes }, ref) => { + const className = useMemo(() => { + return `${attributes.className ?? ''} document-title pb-3 text-5xl font-bold`; + }, [attributes.className]); + + return ( +
+ {children} +
+ ); + }) +); + +export default Page; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/page/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/page/index.ts new file mode 100644 index 0000000000..d9925d7520 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/page/index.ts @@ -0,0 +1 @@ +export * from './Page'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/Paragraph.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/Paragraph.tsx new file mode 100644 index 0000000000..ad6737510e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/Paragraph.tsx @@ -0,0 +1,14 @@ +import { EditorElementProps, ParagraphNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; + +export const Paragraph = memo( + forwardRef>(({ node: _, children, ...attributes }, ref) => { + { + return ( +
+ {children} +
+ ); + } + }) +); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/index.ts new file mode 100644 index 0000000000..01752c914c --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/paragraph/index.ts @@ -0,0 +1 @@ +export * from './Paragraph'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/Quote.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/Quote.tsx new file mode 100644 index 0000000000..0ddc0af985 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/Quote.tsx @@ -0,0 +1,18 @@ +import { EditorElementProps, QuoteNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useMemo } from 'react'; + +export const Quote = memo( + forwardRef>(({ node: _, children, ...attributes }, ref) => { + const className = useMemo(() => { + return `flex w-full flex-col ml-3 border-l-[4px] border-fill-default pl-2 ${attributes.className ?? ''}`; + }, [attributes.className]); + + return ( +
+ {children} +
+ ); + }) +); + +export default Quote; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/index.ts new file mode 100644 index 0000000000..c88e677a53 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/quote/index.ts @@ -0,0 +1 @@ +export * from './Quote'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/table/Table.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/Table.tsx new file mode 100644 index 0000000000..e56b6f4ba7 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/Table.tsx @@ -0,0 +1,56 @@ +import { EditorElementProps, TableCellNode, TableNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useMemo } from 'react'; +import { Grid } from '@atlaskit/primitives'; +import './table.scss'; + +const Table = memo( + forwardRef>(({ node, children, className, ...attributes }, ref) => { + const { rowsLen, colsLen, rowDefaultHeight, colsHeight } = node.data; + const cells = node.children as TableCellNode[]; + + const columnGroup = useMemo(() => { + return Array.from({ length: colsLen }, (_, index) => { + return cells.filter((cell) => cell.data.colPosition === index); + }); + }, [cells, colsLen]); + + const rowGroup = useMemo(() => { + return Array.from({ length: rowsLen }, (_, index) => { + return cells.filter((cell) => cell.data.rowPosition === index); + }); + }, [cells, rowsLen]); + + const templateColumns = useMemo(() => { + return columnGroup + .map((group) => { + return `${group[0].data.width || colsHeight}px`; + }) + .join(' '); + }, [colsHeight, columnGroup]); + + const templateRows = useMemo(() => { + return rowGroup + .map((group) => { + return `${group[0].data.height || rowDefaultHeight}px`; + }) + .join(' '); + }, [rowGroup, rowDefaultHeight]); + + return ( +
+ + {children} + +
+ ); + }) +); + +export default Table; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/table/TableCell.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/TableCell.tsx new file mode 100644 index 0000000000..b2a01d5c8c --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/TableCell.tsx @@ -0,0 +1,16 @@ +import { EditorElementProps, TableCellNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; + +const TableCell = memo( + forwardRef>( + ({ node: _, children, className, ...attributes }, ref) => { + return ( +
+ {children} +
+ ); + } + ) +); + +export default TableCell; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/table/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/index.ts new file mode 100644 index 0000000000..99a5478645 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/index.ts @@ -0,0 +1,3 @@ +export { default as TableBlock } from './Table'; + +export { default as TableCellBlock } from './TableCell'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/table/table.scss b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/table.scss new file mode 100644 index 0000000000..1aa812f6c5 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/table/table.scss @@ -0,0 +1,10 @@ +.table-block { + [id^=table-] { + width: fit-content; + @apply border-t border-l border-line-border; + } + + .table-cell { + @apply border-b border-r border-line-border; + } +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Placeholder.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Placeholder.tsx new file mode 100644 index 0000000000..574a0ba847 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Placeholder.tsx @@ -0,0 +1,133 @@ +import { BlockType } from '@/application/document.type'; +import { HeadingNode } from '@/components/editor/editor.type'; +import { useEditorContext } from '@/components/editor/EditorContext'; +import React, { CSSProperties, useEffect, useMemo, useState } from 'react'; +import { ReactEditor, useSelected, useSlate } from 'slate-react'; +import { Editor, Element, Range } from 'slate'; +import { useTranslation } from 'react-i18next'; + +function Placeholder({ node, ...attributes }: { node: Element; className?: string; style?: CSSProperties }) { + const { t } = useTranslation(); + const { readOnly } = useEditorContext(); + const editor = useSlate(); + const selected = useSelected() && !readOnly && !!editor.selection && Range.isCollapsed(editor.selection); + const [isComposing, setIsComposing] = useState(false); + const block = useMemo(() => { + const path = ReactEditor.findPath(editor, node); + const match = Editor.above(editor, { + match: (n) => { + return !Editor.isEditor(n) && Element.isElement(n) && n.blockId !== undefined && n.type !== undefined; + }, + at: path, + }); + + if (!match) return null; + + return match[0] as Element; + }, [editor, node]); + + const className = useMemo(() => { + return `text-placeholder select-none ${attributes.className ?? ''}`; + }, [attributes.className]); + + const unSelectedPlaceholder = useMemo(() => { + switch (block?.type) { + case BlockType.Paragraph: { + if (editor.children.length === 1) { + return t('editor.slashPlaceHolder'); + } + + return ''; + } + + case BlockType.ToggleListBlock: + return t('blockPlaceholders.bulletList'); + case BlockType.QuoteBlock: + return t('blockPlaceholders.quote'); + case BlockType.TodoListBlock: + return t('blockPlaceholders.todoList'); + case BlockType.NumberedListBlock: + return t('blockPlaceholders.numberList'); + case BlockType.BulletedListBlock: + return t('blockPlaceholders.bulletList'); + case BlockType.HeadingBlock: { + const level = (block as HeadingNode).data.level; + + switch (level) { + case 1: + return t('editor.mobileHeading1'); + case 2: + return t('editor.mobileHeading2'); + case 3: + return t('editor.mobileHeading3'); + default: + return ''; + } + } + + case BlockType.Page: + return t('document.title.placeholder'); + case BlockType.CalloutBlock: + case BlockType.CodeBlock: + return t('editor.typeSomething'); + default: + return ''; + } + }, [block, t, editor.children.length]); + + const selectedPlaceholder = useMemo(() => { + switch (block?.type) { + case BlockType.HeadingBlock: + return unSelectedPlaceholder; + case BlockType.Page: + return t('document.title.placeholder'); + case BlockType.GridBlock: + case BlockType.EquationBlock: + case BlockType.CodeBlock: + case BlockType.DividerBlock: + return ''; + + default: + return t('editor.slashPlaceHolder'); + } + }, [block?.type, t, unSelectedPlaceholder]); + + useEffect(() => { + if (!selected) return; + + const handleCompositionStart = () => { + setIsComposing(true); + }; + + const handleCompositionEnd = () => { + setIsComposing(false); + }; + + const editorDom = ReactEditor.toDOMNode(editor, editor); + + // placeholder should be hidden when composing + editorDom.addEventListener('compositionstart', handleCompositionStart); + editorDom.addEventListener('compositionend', handleCompositionEnd); + editorDom.addEventListener('compositionupdate', handleCompositionStart); + return () => { + editorDom.removeEventListener('compositionstart', handleCompositionStart); + editorDom.removeEventListener('compositionend', handleCompositionEnd); + editorDom.removeEventListener('compositionupdate', handleCompositionStart); + }; + }, [editor, selected]); + + if (isComposing) { + return null; + } + + return ( + + ); +} + +export default Placeholder; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/text/StartIcon.hooks.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/StartIcon.hooks.tsx new file mode 100644 index 0000000000..50ca473fb0 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/StartIcon.hooks.tsx @@ -0,0 +1,47 @@ +import { BlockType } from '@/application/document.type'; +import { BulletedListIcon } from '@/components/editor/components/blocks/bulleted_list'; +import { NumberListIcon } from '@/components/editor/components/blocks/numbered_list'; +import ToggleIcon from '@/components/editor/components/blocks/toggle_list/ToggleIcon'; +import { TextNode } from '@/components/editor/editor.type'; +import React, { FC, useCallback, useMemo } from 'react'; +import { ReactEditor, useSlate } from 'slate-react'; +import { Editor, Element } from 'slate'; +import CheckboxIcon from '../todo_list/CheckboxIcon'; + +export function useStartIcon(node: TextNode) { + const editor = useSlate(); + const path = ReactEditor.findPath(editor, node); + const block = Editor.parent(editor, path)?.[0] as Element | null; + + const Component = useMemo(() => { + if (!Element.isElement(block)) { + return null; + } + + switch (block.type) { + case BlockType.TodoListBlock: + return CheckboxIcon; + case BlockType.ToggleListBlock: + return ToggleIcon; + case BlockType.NumberedListBlock: + return NumberListIcon; + case BlockType.BulletedListBlock: + return BulletedListIcon; + default: + return null; + } + }, [block]) as FC<{ block: Element; className: string }> | null; + + const renderIcon = useCallback(() => { + if (!Component || !block) { + return null; + } + + return ; + }, [Component, block]); + + return { + hasStartIcon: !!Component, + renderIcon, + }; +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Text.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Text.tsx new file mode 100644 index 0000000000..fad8e65060 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/Text.tsx @@ -0,0 +1,31 @@ +import Placeholder from '@/components/editor/components/blocks/text/Placeholder'; +import { useSlateStatic } from 'slate-react'; +import { useStartIcon } from './StartIcon.hooks'; +import { EditorElementProps, TextNode } from '@/components/editor/editor.type'; + +import React, { forwardRef, memo, useMemo } from 'react'; + +export const Text = memo( + forwardRef>( + ({ node, children, className: classNameProp, ...attributes }, ref) => { + const { hasStartIcon, renderIcon } = useStartIcon(node); + const editor = useSlateStatic(); + const isEmpty = editor.isEmpty(node); + const className = useMemo( + () => + `text-element relative my-1 flex w-full whitespace-pre-wrap break-words px-1 ${classNameProp ?? ''} ${ + hasStartIcon ? 'has-start-icon' : '' + }`, + [classNameProp, hasStartIcon] + ); + + return ( + + {renderIcon()} + {isEmpty && } + {children} + + ); + } + ) +); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/text/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/index.ts new file mode 100644 index 0000000000..b0c76af0b0 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/text/index.ts @@ -0,0 +1 @@ +export * from './Text'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/CheckboxIcon.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/CheckboxIcon.tsx new file mode 100644 index 0000000000..aad5969e86 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/CheckboxIcon.tsx @@ -0,0 +1,24 @@ +import { TodoListNode } from '@/components/editor/editor.type'; +import React from 'react'; +import { ReactComponent as CheckboxCheckSvg } from '@/assets/database/checkbox-check.svg'; +import { ReactComponent as CheckboxUncheckSvg } from '@/assets/database/checkbox-uncheck.svg'; + +function CheckboxIcon({ block, className }: { block: TodoListNode; className: string }) { + const { checked } = block.data; + + return ( + { + e.preventDefault(); + }} + className={`${className} cursor-pointer pr-1 text-xl text-fill-default`} + > + {checked ? : } + + ); +} + +export default CheckboxIcon; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/TodoList.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/TodoList.tsx new file mode 100644 index 0000000000..ab3a437b78 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/TodoList.tsx @@ -0,0 +1,17 @@ +import { EditorElementProps, TodoListNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo, useMemo } from 'react'; + +export const TodoList = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const { checked = false } = useMemo(() => node.data || {}, [node.data]); + const className = useMemo(() => { + return `flex w-full flex-col ${checked ? 'checked' : ''} ${attributes.className ?? ''}`; + }, [attributes.className, checked]); + + return ( +
+ {children} +
+ ); + }) +); diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/index.ts new file mode 100644 index 0000000000..f239f43459 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/todo_list/index.ts @@ -0,0 +1 @@ +export * from './TodoList'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleIcon.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleIcon.tsx new file mode 100644 index 0000000000..4e2735d128 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleIcon.tsx @@ -0,0 +1,22 @@ +import { ToggleListNode } from '@/components/editor/editor.type'; +import React from 'react'; +import { ReactComponent as RightSvg } from '@/assets/more.svg'; + +function ToggleIcon({ block, className }: { block: ToggleListNode; className: string }) { + const { collapsed } = block.data; + + return ( + { + e.preventDefault(); + }} + className={`${className} cursor-pointer pr-1 text-xl hover:text-fill-default`} + > + {collapsed ? : } + + ); +} + +export default ToggleIcon; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleList.tsx b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleList.tsx new file mode 100644 index 0000000000..6ccc38f757 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/ToggleList.tsx @@ -0,0 +1,19 @@ +import React, { forwardRef, memo, useMemo } from 'react'; +import { EditorElementProps, ToggleListNode } from '@/components/editor/editor.type'; + +export const ToggleList = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const { collapsed } = useMemo(() => node.data || {}, [node.data]); + const className = `${attributes.className ?? ''} flex w-full flex-col ${collapsed ? 'collapsed' : ''}`; + + return ( + <> +
+ {children} +
+ + ); + }) +); + +export default ToggleList; diff --git a/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/index.ts b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/index.ts new file mode 100644 index 0000000000..833bdb5210 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/blocks/toggle_list/index.ts @@ -0,0 +1 @@ +export * from './ToggleList'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/element/Element.tsx b/frontend/appflowy_web_app/src/components/editor/components/element/Element.tsx new file mode 100644 index 0000000000..57b588bf8a --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/element/Element.tsx @@ -0,0 +1,122 @@ +import { BlockData, BlockType, InlineBlockType, YjsEditorKey } from '@/application/document.type'; +import { BulletedList } from '@/components/editor/components/blocks/bulleted_list'; +import { Callout } from '@/components/editor/components/blocks/callout'; +import { CodeBlock } from '@/components/editor/components/blocks/code'; +import { DividerNode } from '@/components/editor/components/blocks/divider'; +import { Heading } from '@/components/editor/components/blocks/heading'; +import { ImageBlock } from '@/components/editor/components/blocks/image'; +import { MathEquation } from '@/components/editor/components/blocks/math_equation'; +import { NumberedList } from '@/components/editor/components/blocks/numbered_list'; +import { Outline } from '@/components/editor/components/blocks/outline'; +import { Page } from '@/components/editor/components/blocks/page'; +import { Paragraph } from '@/components/editor/components/blocks/paragraph'; +import { Quote } from '@/components/editor/components/blocks/quote'; +import { TableBlock, TableCellBlock } from '@/components/editor/components/blocks/table'; +import { Text } from '@/components/editor/components/blocks/text'; +import { TodoList } from '@/components/editor/components/blocks/todo_list'; +import { ToggleList } from '@/components/editor/components/blocks/toggle_list'; +import { UnSupportedBlock } from '@/components/editor/components/element/UnSupportedBlock'; +import { Formula } from '@/components/editor/components/leaf/formula'; +import { Mention } from '@/components/editor/components/leaf/mention'; +import { EditorElementProps, TextNode } from '@/components/editor/editor.type'; +import { renderColor } from '@/utils/color'; +import React, { FC, useMemo } from 'react'; +import { RenderElementProps } from 'slate-react'; + +export const Element = ({ + element: node, + attributes, + children, +}: RenderElementProps & { + element: EditorElementProps['node']; +}) => { + const Component = useMemo(() => { + switch (node.type) { + case BlockType.HeadingBlock: + return Heading; + case BlockType.TodoListBlock: + return TodoList; + case BlockType.ToggleListBlock: + return ToggleList; + case BlockType.Paragraph: + return Paragraph; + case BlockType.DividerBlock: + return DividerNode; + case BlockType.Page: + return Page; + case BlockType.QuoteBlock: + return Quote; + case BlockType.BulletedListBlock: + return BulletedList; + case BlockType.NumberedListBlock: + return NumberedList; + case BlockType.CodeBlock: + return CodeBlock; + case BlockType.CalloutBlock: + return Callout; + case BlockType.EquationBlock: + return MathEquation; + case BlockType.ImageBlock: + return ImageBlock; + case BlockType.OutlineBlock: + return Outline; + case BlockType.TableBlock: + return TableBlock; + case BlockType.TableCell: + return TableCellBlock; + default: + return UnSupportedBlock; + } + }, [node.type]) as FC; + + const InlineComponent = useMemo(() => { + switch (node.type) { + case InlineBlockType.Formula: + return Formula; + case InlineBlockType.Mention: + return Mention; + default: + return null; + } + }, [node.type]) as FC; + + const className = useMemo(() => { + const data = (node.data as BlockData) || {}; + const align = data.align; + + return `block-element flex rounded ${align ? `block-align-${align}` : ''}`; + }, [node.data]); + + const style = useMemo(() => { + const data = (node.data as BlockData) || {}; + + return { + backgroundColor: data.bg_color ? renderColor(data.bg_color) : undefined, + color: data.font_color ? renderColor(data.font_color) : undefined, + }; + }, [node.data]); + + if (InlineComponent) { + return ( + + {children} + + ); + } + + if (node.type === YjsEditorKey.text) { + return ( + + {children} + + ); + } + + return ( +
+ + {children} + +
+ ); +}; diff --git a/frontend/appflowy_web_app/src/components/editor/components/element/UnSupportedBlock.tsx b/frontend/appflowy_web_app/src/components/editor/components/element/UnSupportedBlock.tsx new file mode 100644 index 0000000000..99c299bc64 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/element/UnSupportedBlock.tsx @@ -0,0 +1,13 @@ +import { EditorElementProps } from '@/components/editor/editor.type'; +import React, { forwardRef } from 'react'; +import { Alert } from '@mui/material'; + +export const UnSupportedBlock = forwardRef(({ node }, ref) => { + return ( +
+ + {`Unsupported block: ${node.type}`} + +
+ ); +}); diff --git a/frontend/appflowy_web_app/src/components/editor/components/element/index.ts b/frontend/appflowy_web_app/src/components/editor/components/element/index.ts new file mode 100644 index 0000000000..b5347c4fe9 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/element/index.ts @@ -0,0 +1 @@ +export * from './Element'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/Leaf.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/Leaf.tsx new file mode 100644 index 0000000000..714b41db97 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/Leaf.tsx @@ -0,0 +1,57 @@ +import { Href } from '@/components/editor/components/leaf/href'; +import { getFontFamily } from '@/utils/font'; +import React, { CSSProperties } from 'react'; +import { RenderLeafProps } from 'slate-react'; +import { renderColor } from '@/utils/color'; + +export function Leaf({ attributes, children, leaf }: RenderLeafProps) { + let newChildren = children; + + const classList = [leaf.prism_token, leaf.prism_token && 'token', leaf.class_name].filter(Boolean); + + if (leaf.code) { + newChildren = ( + {newChildren} + ); + } + + if (leaf.underline) { + newChildren = {newChildren}; + } + + if (leaf.strikethrough) { + newChildren = {newChildren}; + } + + if (leaf.italic) { + newChildren = {newChildren}; + } + + if (leaf.bold) { + newChildren = {newChildren}; + } + + const style: CSSProperties = {}; + + if (leaf.font_color) { + style['color'] = renderColor(leaf.font_color); + } + + if (leaf.bg_color) { + style['backgroundColor'] = renderColor(leaf.bg_color); + } + + if (leaf.href) { + newChildren = {newChildren}; + } + + if (leaf.font_family) { + style['fontFamily'] = getFontFamily(leaf.font_family); + } + + return ( + + {newChildren} + + ); +} diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/Formula.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/Formula.tsx new file mode 100644 index 0000000000..dd8809ff68 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/Formula.tsx @@ -0,0 +1,30 @@ +import KatexMath from '@/components/_shared/katex-math/KatexMath'; +import { EditorElementProps, FormulaNode } from '@/components/editor/editor.type'; +import React, { memo, forwardRef } from 'react'; +import { useSelected } from 'slate-react'; + +export const Formula = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const formula = node.data; + const selected = useSelected(); + + return ( + + + + + + {children} + + ); + }) +); + +export default Formula; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/index.ts b/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/index.ts new file mode 100644 index 0000000000..1c01fca07e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/formula/index.ts @@ -0,0 +1,5 @@ +import { lazy } from 'react'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error +export const Formula = lazy(() => import('./Formula?chunkName=formula')); diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/href/Href.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/href/Href.tsx new file mode 100644 index 0000000000..7ad81a5171 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/href/Href.tsx @@ -0,0 +1,6 @@ +import React, { memo } from 'react'; +import { Text } from 'slate'; + +export const Href = memo(({ children }: { leaf: Text; children: React.ReactNode }) => { + return {children}; +}); diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/href/index.ts b/frontend/appflowy_web_app/src/components/editor/components/leaf/href/index.ts new file mode 100644 index 0000000000..758b3b39d3 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/href/index.ts @@ -0,0 +1 @@ +export * from './Href'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/index.ts b/frontend/appflowy_web_app/src/components/editor/components/leaf/index.ts new file mode 100644 index 0000000000..711768ed28 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/index.ts @@ -0,0 +1 @@ +export * from './Leaf'; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/Mention.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/Mention.tsx new file mode 100644 index 0000000000..eba846b9c1 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/Mention.tsx @@ -0,0 +1,25 @@ +import { EditorElementProps, MentionNode } from '@/components/editor/editor.type'; +import React, { forwardRef, memo } from 'react'; +import { useSelected } from 'slate-react'; + +import MentionLeaf from './MentionLeaf'; + +export const Mention = memo( + forwardRef>(({ node, children, ...attributes }, ref) => { + const selected = useSelected(); + + return ( + + {children} + + + ); + }) +); + +export default Mention; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionDate.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionDate.tsx new file mode 100644 index 0000000000..2e7d56308d --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionDate.tsx @@ -0,0 +1,18 @@ +import dayjs from 'dayjs'; +import React, { useMemo } from 'react'; +import { ReactComponent as DateSvg } from '@/assets/date.svg'; + +function MentionDate({ date }: { date: string }) { + const dateFormat = useMemo(() => { + return dayjs(date).format('MMM D, YYYY'); + }, [date]); + + return ( + + + {dateFormat} + + ); +} + +export default MentionDate; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionLeaf.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionLeaf.tsx new file mode 100644 index 0000000000..851f54f998 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionLeaf.tsx @@ -0,0 +1,19 @@ +import { Mention, MentionType } from '@/application/document.type'; +import MentionDate from '@/components/editor/components/leaf/mention/MentionDate'; +import MentionPage from '@/components/editor/components/leaf/mention/MentionPage'; + +export function MentionLeaf({ mention }: { mention: Mention }) { + const { type, date, page_id } = mention; + + if (type === MentionType.PageRef && page_id) { + return ; + } + + if (type === MentionType.Date && date) { + return ; + } + + return null; +} + +export default MentionLeaf; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionPage.tsx b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionPage.tsx new file mode 100644 index 0000000000..aafe40b1af --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/MentionPage.tsx @@ -0,0 +1,52 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { ReactComponent as DocumentSvg } from '@/assets/document.svg'; +import { useTranslation } from 'react-i18next'; +import { useSelected } from 'slate-react'; +import { ReactComponent as EyeClose } from '@/assets/eye_close.svg'; + +function MentionPage({ pageId }: { pageId: string }) { + const { t } = useTranslation(); + + const selected = useSelected(); + const [page, setPage] = useState<{ + icon?: { + value: string | null; + }; + name: string; + } | null>(null); + const [error, setError] = useState(false); + const loadPage = useCallback(async () => { + setError(false); + setPage(null); + console.log(pageId); + }, [pageId]); + + useEffect(() => { + void loadPage(); + }, [loadPage]); + return ( + + {error ? ( + <> + + {t('document.mention.deleted')} + + ) : ( + page && ( + <> + {page.icon?.value || } + {page.name.trim() || t('menuAppHeader.defaultNewPageName')} + + ) + )} + + ); +} + +export default MentionPage; diff --git a/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/index.ts b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/index.ts new file mode 100644 index 0000000000..d3ee18034d --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/components/leaf/mention/index.ts @@ -0,0 +1 @@ +export * from './Mention'; diff --git a/frontend/appflowy_web_app/src/components/editor/editor.scss b/frontend/appflowy_web_app/src/components/editor/editor.scss new file mode 100644 index 0000000000..6f8bd196ce --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/editor.scss @@ -0,0 +1,277 @@ + +.block-element:not([data-block-type="table/cell"]) { + @apply my-[4px]; + +} + +.block-element .block-element:not([data-block-type="table/cell"]) { + @apply mb-0; + margin-left: 24px; +} + +.block-element[data-block-type="table/cell"] { + margin-left: 0 !important; + + .block-element { + margin-left: 0 !important; + height: 100%; + } +} + +.block-element.block-align-left { + > div > .text-element { + text-align: left; + justify-content: flex-start; + } +} + +.block-element.block-align-right { + > div > .text-element { + text-align: right; + justify-content: flex-end; + } +} + +.block-element.block-align-center { + > div > .text-element { + text-align: center; + justify-content: center; + } + +} + + +.block-element[data-block-type="todo_list"] .checked > .text-element .text-content { + text-decoration: line-through; + color: var(--text-caption); +} + +.block-element .collapsed .block-element { + display: none !important; +} + +[role=textbox] { + .text-element { + &::selection { + @apply bg-transparent; + } + } +} + + +span[data-slate-placeholder="true"]:not(.inline-block-content) { + @apply text-text-placeholder; + opacity: 1 !important; +} + + +[role="textbox"] { + ::selection { + @apply bg-content-blue-100; + } + + .text-content { + &::selection { + @apply bg-transparent; + } + + &.selected { + @apply bg-content-blue-100; + } + + span { + &::selection { + @apply bg-content-blue-100; + } + } + } +} + + +[data-dark-mode="true"] [role="textbox"] { + ::selection { + background-color: #1e79a2; + } + + .text-content { + &::selection { + @apply bg-transparent; + } + + &.selected { + background-color: #1e79a2; + } + + span { + &::selection { + background-color: #1e79a2; + } + } + } +} + + +.text-content, [data-dark-mode="true"] .text-content { + @apply min-w-[1px]; + &.empty-text { + span { + &::selection { + @apply bg-transparent; + } + } + } +} + +.text-element:has(.text-placeholder), .divider-node, [data-dark-mode="true"] .text-element:has(.text-placeholder), [data-dark-mode="true"] .divider-node { + ::selection { + @apply bg-transparent; + } +} + +.text-placeholder { + @apply absolute left-[5px] transform -translate-y-1/2 pointer-events-none select-none whitespace-nowrap; + &:after { + @apply text-text-placeholder absolute top-0; + content: (attr(data-placeholder)); + } +} + +.block-align-center { + .text-placeholder { + @apply left-[calc(50%+1px)]; + &:after { + @apply left-0; + } + } + + .has-start-icon .text-placeholder { + @apply left-[calc(50%+13px)]; + &:after { + @apply left-0; + } + } + +} + +.block-align-left { + .text-placeholder { + &:after { + @apply left-0; + } + } + + .has-start-icon .text-placeholder { + &:after { + @apply left-[24px]; + } + } +} + +.text-block-icon { + @apply top-[2px]; +} + +.block-align-right { + + .text-placeholder { + + @apply relative w-fit h-0 order-2; + &:after { + @apply relative w-fit top-1/2 left-[-6px]; + } + } + + .text-content { + @apply order-1; + } + + .has-start-icon .text-placeholder { + &:after { + @apply left-[-6px]; + } + } +} + + +.formula-inline, .mention { + &.selected { + @apply rounded bg-content-blue-100; + } +} + +.bulleted-icon { + &:after { + content: attr(data-letter); + } +} + +.numbered-icon { + &:after { + content: attr(data-number) "."; + } +} + + +.grid-block .grid-scroll-container::-webkit-scrollbar { + width: 0; + height: 0; +} + +.image-render { + .image-resizer { + @apply absolute w-[10px] top-0 z-10 flex h-full cursor-col-resize items-center justify-end; + .resize-handle { + @apply h-1/4 w-1/2 transform transition-all duration-500 select-none rounded-full border border-white opacity-0; + background: var(--fill-toolbar); + } + } + + &:hover { + .image-resizer { + .resize-handle { + @apply opacity-90; + } + } + } +} + + +.image-block, .math-equation-block, [data-dark-mode="true"] .image-block, [data-dark-mode="true"] .math-equation-block { + ::selection { + @apply bg-transparent; + } + + &:hover { + .container-bg { + background: var(--content-blue-100) !important; + } + } +} + +[data-block-type='heading'] { + .mention-inline .mention-content { + @apply ml-6; + } + + .level-1, .level-2 { + .mention-inline .mention-content { + @apply ml-8; + } + } + +} + +.mention-inline { + height: inherit; + overflow: hidden; + @apply px-1 inline-flex select-none gap-1 relative; + + .mention-icon { + @apply absolute top-1/2 transform -translate-y-1/2; + } + + .mention-content { + @apply ml-5; + } + +} \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/components/editor/editor.type.ts b/frontend/appflowy_web_app/src/components/editor/editor.type.ts new file mode 100644 index 0000000000..2b7e9ef41f --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/editor.type.ts @@ -0,0 +1,137 @@ +import { + BlockType, + CalloutBlockData, + CodeBlockData, + HeadingBlockData, + ImageBlockData, + MathEquationBlockData, + NumberedListBlockData, + TodoListBlockData, + ToggleListBlockData, + YjsEditorKey, + InlineBlockType, + Mention, + OutlineBlockData, + TableBlockData, + TableCellBlockData, + BlockId, + BlockData, +} from '@/application/document.type'; +import { HTMLAttributes } from 'react'; +import { Element } from 'slate'; + +export interface BlockNode extends Element { + blockId: BlockId; + type: BlockType; + data?: BlockData; +} + +export interface TextNode extends Element { + type: YjsEditorKey.text; + textId: string; +} + +export interface PageNode extends BlockNode { + type: BlockType.Page; +} + +export interface ParagraphNode extends BlockNode { + type: BlockType.Paragraph; +} + +export interface HeadingNode extends BlockNode { + blockId: string; + type: BlockType.HeadingBlock; + data: HeadingBlockData; +} + +export interface DividerNode extends BlockNode { + type: BlockType.DividerBlock; + blockId: string; +} + +export interface TodoListNode extends BlockNode { + type: BlockType.TodoListBlock; + blockId: string; + data: TodoListBlockData; +} + +export interface ToggleListNode extends BlockNode { + type: BlockType.ToggleListBlock; + blockId: string; + data: ToggleListBlockData; +} + +export interface BulletedListNode extends BlockNode { + type: BlockType.BulletedListBlock; + blockId: string; +} + +export interface NumberedListNode extends BlockNode { + type: BlockType.NumberedListBlock; + blockId: string; + data: NumberedListBlockData; +} + +export interface QuoteNode extends BlockNode { + type: BlockType.QuoteBlock; + blockId: string; +} + +export interface CodeNode extends BlockNode { + type: BlockType.CodeBlock; + blockId: string; + data: CodeBlockData; +} + +export interface CalloutNode extends BlockNode { + type: BlockType.CalloutBlock; + blockId: string; + data: CalloutBlockData; +} + +export interface MathEquationNode extends BlockNode { + type: BlockType.EquationBlock; + blockId: string; + data: MathEquationBlockData; +} + +export interface ImageBlockNode extends BlockNode { + type: BlockType.ImageBlock; + blockId: string; + data: ImageBlockData; +} + +export interface OutlineNode extends BlockNode { + type: BlockType.OutlineBlock; + blockId: string; + data: OutlineBlockData; +} + +export interface TableNode extends BlockNode { + type: BlockType.TableBlock; + blockId: string; + data: TableBlockData; +} + +export interface TableCellNode extends BlockNode { + type: BlockType.TableCell; + blockId: string; + data: TableCellBlockData; +} + +export interface EditorElementProps extends HTMLAttributes { + node: T; +} + +type FormulaValue = string; + +export interface FormulaNode extends Element { + type: InlineBlockType.Formula; + data: FormulaValue; +} + +export interface MentionNode extends Element { + type: InlineBlockType.Mention; + data: Mention; +} diff --git a/frontend/appflowy_web_app/src/components/editor/index.ts b/frontend/appflowy_web_app/src/components/editor/index.ts new file mode 100644 index 0000000000..59a50adf9b --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/index.ts @@ -0,0 +1,3 @@ +import { lazy } from 'react'; + +export const Editor = lazy(() => import('./Editor')); diff --git a/frontend/appflowy_web_app/src/components/editor/plugins/index.ts b/frontend/appflowy_web_app/src/components/editor/plugins/index.ts new file mode 100644 index 0000000000..4a87275330 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/plugins/index.ts @@ -0,0 +1,6 @@ +import { withInlines } from '@/components/editor/plugins/withInlineElement'; +import { ReactEditor } from 'slate-react'; + +export function withPlugins(editor: ReactEditor) { + return withInlines(editor); +} diff --git a/frontend/appflowy_web_app/src/components/editor/plugins/withInlineElement.ts b/frontend/appflowy_web_app/src/components/editor/plugins/withInlineElement.ts new file mode 100644 index 0000000000..85a13cd69f --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/plugins/withInlineElement.ts @@ -0,0 +1,31 @@ +import { InlineBlockType } from '@/application/document.type'; +import { ReactEditor } from 'slate-react'; +import { Element } from 'slate'; + +export function withInlines(editor: ReactEditor) { + const { isInline, isElementReadOnly, isSelectable, isVoid, markableVoid } = editor; + + const matchInlineType = (element: Element) => { + return Object.values(InlineBlockType).includes(element.type as InlineBlockType); + }; + + editor.isInline = (element) => { + return matchInlineType(element) || isInline(element); + }; + + editor.isVoid = (element) => { + return matchInlineType(element) || isVoid(element); + }; + + editor.markableVoid = (element) => { + return matchInlineType(element) || markableVoid(element); + }; + + editor.isElementReadOnly = (element) => + Object.values(InlineBlockType).includes(element.type as InlineBlockType) || isElementReadOnly(element); + + editor.isSelectable = (element) => + !Object.values(InlineBlockType).includes(element.type as InlineBlockType) && isSelectable(element); + + return editor; +} diff --git a/frontend/appflowy_web_app/src/components/editor/utils/list.ts b/frontend/appflowy_web_app/src/components/editor/utils/list.ts new file mode 100644 index 0000000000..cc62e8d6a2 --- /dev/null +++ b/frontend/appflowy_web_app/src/components/editor/utils/list.ts @@ -0,0 +1,73 @@ +import { BlockType } from '@/application/document.type'; +import { Element, NodeEntry, Path } from 'slate'; +import { ReactEditor } from 'slate-react'; + +const romanMap: [number, string][] = [ + [1000, 'M'], + [900, 'CM'], + [500, 'D'], + [400, 'CD'], + [100, 'C'], + [90, 'XC'], + [50, 'L'], + [40, 'XL'], + [10, 'X'], + [9, 'IX'], + [5, 'V'], + [4, 'IV'], + [1, 'I'], +]; + +export function romanize(num: number): string { + let result = ''; + let nextNum = num; + + for (const [value, symbol] of romanMap) { + const count = Math.floor(nextNum / value); + + nextNum -= value * count; + result += symbol.repeat(count); + if (nextNum === 0) break; + } + + return result; +} + +export function letterize(num: number): string { + let nextNum = num; + let letters = ''; + + while (nextNum > 0) { + nextNum--; + const letter = String.fromCharCode((nextNum % 26) + 'a'.charCodeAt(0)); + + letters = letter + letters; + nextNum = Math.floor(nextNum / 26); + } + + return letters; +} + +export function getListLevel(editor: ReactEditor, type: BlockType, path: Path) { + let level = 0; + let currentPath = path; + + while (currentPath.length > 0) { + const parent = editor.parent(currentPath); + + if (!parent) { + break; + } + + const [parentNode, parentPath] = parent as NodeEntry; + + if (parentNode.type !== type) { + break; + } + + level += 1; + currentPath = parentPath; + } + + return level; +} diff --git a/frontend/appflowy_web_app/src/components/layout/Header.tsx b/frontend/appflowy_web_app/src/components/layout/Header.tsx new file mode 100644 index 0000000000..d8a4fc3b9e --- /dev/null +++ b/frontend/appflowy_web_app/src/components/layout/Header.tsx @@ -0,0 +1,38 @@ +import { useAuth } from '@/components/auth/auth.hooks'; +import { Button } from '@mui/material'; +import Avatar from '@mui/material/Avatar'; +import React, { useMemo } from 'react'; +import LogoutOutlined from '@mui/icons-material/LogoutOutlined'; + +function Header() { + const { logout, currentUser } = useAuth(); + + const user = useMemo(() => currentUser?.user, [currentUser]); + + return ( +
+
+
+ AppFlowy + Page Name +
+
+ +
+ {user ? ( +
+ + {user.email} + +
+ ) : ( + + )} +
+
+ ); +} + +export default Header; diff --git a/frontend/appflowy_web_app/src/components/layout/Layout.tsx b/frontend/appflowy_web_app/src/components/layout/Layout.tsx index ebc9bcba56..ce92f37934 100644 --- a/frontend/appflowy_web_app/src/components/layout/Layout.tsx +++ b/frontend/appflowy_web_app/src/components/layout/Layout.tsx @@ -1,24 +1,20 @@ -import React, { useContext } from 'react'; -import { Button } from '@mui/material'; -import { useAuth } from '@/components/auth/auth.hooks'; -import { AFConfigContext } from '@/AppConfig'; +import Header from '@/components/layout/Header'; +import { AFScroller } from '@/components/_shared/scroller'; +import React from 'react'; function Layout({ children }: { children: React.ReactNode }) { - const { logout } = useAuth(); - const AFConfig = useContext(AFConfigContext); - return (
-
hello world
- - - {children} + {children} +
); } diff --git a/frontend/appflowy_web_app/src/components/tauri/SignInAsAnonymous.tsx b/frontend/appflowy_web_app/src/components/tauri/SignInAsAnonymous.tsx new file mode 100644 index 0000000000..ff241f728b --- /dev/null +++ b/frontend/appflowy_web_app/src/components/tauri/SignInAsAnonymous.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Button } from '@mui/material'; +import { useAuth } from '@/components/auth/auth.hooks'; +import { useTranslation } from 'react-i18next'; + +function SignInAsAnonymous() { + const { signInAsAnonymous } = useAuth(); + const { t } = useTranslation(); + + return ( + <> + +
+
+ {t('signIn.or')} +
+
+ + ); +} + +export default SignInAsAnonymous; diff --git a/frontend/appflowy_web_app/src/main.tsx b/frontend/appflowy_web_app/src/main.tsx index f1236efb5f..d964a40e3d 100644 --- a/frontend/appflowy_web_app/src/main.tsx +++ b/frontend/appflowy_web_app/src/main.tsx @@ -1,7 +1,4 @@ import ReactDOM from 'react-dom/client'; -import App from './App'; -import './styles/tailwind.css'; -import './styles/font.css'; -import './styles/template.css'; +import App from 'src/components/app/App'; ReactDOM.createRoot(document.getElementById('root')!).render(); diff --git a/frontend/appflowy_web_app/src/pages/DocumentPage.tsx b/frontend/appflowy_web_app/src/pages/DocumentPage.tsx new file mode 100644 index 0000000000..0a9a359afc --- /dev/null +++ b/frontend/appflowy_web_app/src/pages/DocumentPage.tsx @@ -0,0 +1,8 @@ +import { Document } from '@/components/document'; +import React from 'react'; + +function DocumentPage() { + return ; +} + +export default DocumentPage; diff --git a/frontend/appflowy_web_app/src/pages/LoginPage.tsx b/frontend/appflowy_web_app/src/pages/LoginPage.tsx new file mode 100644 index 0000000000..c81669a245 --- /dev/null +++ b/frontend/appflowy_web_app/src/pages/LoginPage.tsx @@ -0,0 +1,22 @@ +import React, { useEffect } from 'react'; +import Welcome from '@/components/auth/Welcome'; +import { useNavigate } from 'react-router-dom'; +import { useAppSelector } from '@/stores/store'; + +function LoginPage () { + const currentUser = useAppSelector((state) => state.currentUser); + const navigate = useNavigate(); + + useEffect(() => { + if (currentUser.isAuthenticated) { + const redirect = new URLSearchParams(window.location.search).get('redirect'); + + navigate(`${redirect || ''}`); + } + }, [currentUser, navigate]); + return ( + + ); +} + +export default LoginPage; \ No newline at end of file diff --git a/frontend/appflowy_web_app/src/pages/ProductPage.tsx b/frontend/appflowy_web_app/src/pages/ProductPage.tsx new file mode 100644 index 0000000000..3783a327ae --- /dev/null +++ b/frontend/appflowy_web_app/src/pages/ProductPage.tsx @@ -0,0 +1,38 @@ +import { CollabType } from '@/application/collab.type'; +import { IdProvider } from '@/components/_shared/context-provider/IdProvider'; +import React, { useMemo } from 'react'; +import { useParams } from 'react-router-dom'; +import DocumentPage from '@/pages/DocumentPage'; + +enum URL_COLLAB_TYPE { + DOCUMENT = 'document', + DATABASE = 'database', +} + +const collabTypeMap: Record = { + [URL_COLLAB_TYPE.DOCUMENT]: CollabType.Document, + [URL_COLLAB_TYPE.DATABASE]: CollabType.Database, +}; + +function ProductPage() { + const { workspaceId, collabType, objectId } = useParams(); + + const PageComponent = useMemo(() => { + switch (collabType) { + case URL_COLLAB_TYPE.DOCUMENT: + return DocumentPage; + default: + return null; + } + }, [collabType]); + + if (!workspaceId || !collabType || !objectId) return null; + + return ( + + {PageComponent && } + + ); +} + +export default ProductPage; diff --git a/frontend/appflowy_web_app/src/slate-editor.d.ts b/frontend/appflowy_web_app/src/slate-editor.d.ts new file mode 100644 index 0000000000..2ebcf7a88d --- /dev/null +++ b/frontend/appflowy_web_app/src/slate-editor.d.ts @@ -0,0 +1,45 @@ +import { ReactEditor } from 'slate-react'; + +interface EditorInlineAttributes { + bold?: boolean; + italic?: boolean; + underline?: boolean; + strikethrough?: boolean; + font_color?: string; + bg_color?: string; + href?: string; + code?: boolean; + font_family?: string; + formula?: string; + prism_token?: string; + class_name?: string; + mention?: { + type: string; + // inline page ref id + page?: string; + // reminder date ref id + date?: string; + }; +} + +type CustomElement = { + children: (CustomText | CustomElement)[]; + type?: string; + data?: unknown; + blockId?: string; + textId?: string; +}; + +type CustomText = { text: string } & EditorInlineAttributes; + +declare module 'slate' { + interface CustomTypes { + Editor: BaseEditor & ReactEditor; + Element: CustomElement; + Text: CustomText; + } + + interface BaseEditor { + isEmbed: (element: CustomElement) => boolean; + } +} diff --git a/frontend/appflowy_web_app/src/stores/currentUser/slice.ts b/frontend/appflowy_web_app/src/stores/currentUser/slice.ts index 40ba1300a8..ecd40a433e 100644 --- a/frontend/appflowy_web_app/src/stores/currentUser/slice.ts +++ b/frontend/appflowy_web_app/src/stores/currentUser/slice.ts @@ -1,5 +1,5 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { UserProfile, UserSetting } from '@/application/services/user.type'; +import { UserProfile, UserSetting } from '@/application/user.type'; export enum LoginState { IDLE = 'idle', @@ -46,6 +46,7 @@ export const currentUserSlice = createSlice({ resetLoginState: (state) => { state.loginState = LoginState.IDLE; }, + }, }); diff --git a/frontend/appflowy_web_app/src/styles/font.css b/frontend/appflowy_web_app/src/styles/font.css deleted file mode 100644 index 84f9f90d09..0000000000 --- a/frontend/appflowy_web_app/src/styles/font.css +++ /dev/null @@ -1,107 +0,0 @@ -.poppins-thin { - font-family: "Poppins", sans-serif; - font-weight: 100; - font-style: normal; -} - -.poppins-extralight { - font-family: "Poppins", sans-serif; - font-weight: 200; - font-style: normal; -} - -.poppins-light { - font-family: "Poppins", sans-serif; - font-weight: 300; - font-style: normal; -} - -.poppins-regular { - font-family: "Poppins", sans-serif; - font-weight: 400; - font-style: normal; -} - -.poppins-medium { - font-family: "Poppins", sans-serif; - font-weight: 500; - font-style: normal; -} - -.poppins-semibold { - font-family: "Poppins", sans-serif; - font-weight: 600; - font-style: normal; -} - -.poppins-bold { - font-family: "Poppins", sans-serif; - font-weight: 700; - font-style: normal; -} - -.poppins-extrabold { - font-family: "Poppins", sans-serif; - font-weight: 800; - font-style: normal; -} - -.poppins-black { - font-family: "Poppins", sans-serif; - font-weight: 900; - font-style: normal; -} - -.poppins-thin-italic { - font-family: "Poppins", sans-serif; - font-weight: 100; - font-style: italic; -} - -.poppins-extralight-italic { - font-family: "Poppins", sans-serif; - font-weight: 200; - font-style: italic; -} - -.poppins-light-italic { - font-family: "Poppins", sans-serif; - font-weight: 300; - font-style: italic; -} - -.poppins-regular-italic { - font-family: "Poppins", sans-serif; - font-weight: 400; - font-style: italic; -} - -.poppins-medium-italic { - font-family: "Poppins", sans-serif; - font-weight: 500; - font-style: italic; -} - -.poppins-semibold-italic { - font-family: "Poppins", sans-serif; - font-weight: 600; - font-style: italic; -} - -.poppins-bold-italic { - font-family: "Poppins", sans-serif; - font-weight: 700; - font-style: italic; -} - -.poppins-extrabold-italic { - font-family: "Poppins", sans-serif; - font-weight: 800; - font-style: italic; -} - -.poppins-black-italic { - font-family: "Poppins", sans-serif; - font-weight: 900; - font-style: italic; -} diff --git a/frontend/appflowy_web_app/src/styles/template.css b/frontend/appflowy_web_app/src/styles/template.css index ebad0ce253..b255483f4e 100644 --- a/frontend/appflowy_web_app/src/styles/template.css +++ b/frontend/appflowy_web_app/src/styles/template.css @@ -30,9 +30,6 @@ textarea { background: transparent; } -body { - font-family: Poppins, Roboto, serif; -} ::-webkit-scrollbar { width: 8px; diff --git a/frontend/appflowy_web_app/src/utils/color.ts b/frontend/appflowy_web_app/src/utils/color.ts new file mode 100644 index 0000000000..025c8c45ed --- /dev/null +++ b/frontend/appflowy_web_app/src/utils/color.ts @@ -0,0 +1,50 @@ +export enum ColorEnum { + Purple = 'appflowy_them_color_tint1', + Pink = 'appflowy_them_color_tint2', + LightPink = 'appflowy_them_color_tint3', + Orange = 'appflowy_them_color_tint4', + Yellow = 'appflowy_them_color_tint5', + Lime = 'appflowy_them_color_tint6', + Green = 'appflowy_them_color_tint7', + Aqua = 'appflowy_them_color_tint8', + Blue = 'appflowy_them_color_tint9', +} + +export const colorMap = { + [ColorEnum.Purple]: 'var(--tint-purple)', + [ColorEnum.Pink]: 'var(--tint-pink)', + [ColorEnum.LightPink]: 'var(--tint-red)', + [ColorEnum.Orange]: 'var(--tint-orange)', + [ColorEnum.Yellow]: 'var(--tint-yellow)', + [ColorEnum.Lime]: 'var(--tint-lime)', + [ColorEnum.Green]: 'var(--tint-green)', + [ColorEnum.Aqua]: 'var(--tint-aqua)', + [ColorEnum.Blue]: 'var(--tint-blue)', +}; + +// Convert ARGB to RGBA +// Flutter uses ARGB, but CSS uses RGBA +function argbToRgba(color: string): string { + const hex = color.replace(/^#|0x/, ''); + + const hasAlpha = hex.length === 8; + + if (!hasAlpha) { + return color.replace('0x', '#'); + } + + const r = parseInt(hex.slice(2, 4), 16); + const g = parseInt(hex.slice(4, 6), 16); + const b = parseInt(hex.slice(6, 8), 16); + const a = hasAlpha ? parseInt(hex.slice(0, 2), 16) / 255 : 1; + + return `rgba(${r}, ${g}, ${b}, ${a})`; +} + +export function renderColor(color: string) { + if (colorMap[color as ColorEnum]) { + return colorMap[color as ColorEnum]; + } + + return argbToRgba(color); +} diff --git a/frontend/appflowy_web_app/src/utils/font.ts b/frontend/appflowy_web_app/src/utils/font.ts new file mode 100644 index 0000000000..765ebf5f00 --- /dev/null +++ b/frontend/appflowy_web_app/src/utils/font.ts @@ -0,0 +1,3 @@ +export function getFontFamily(attribute: string) { + return attribute.split('_')[0]; +} diff --git a/frontend/appflowy_web_app/src/utils/platform.ts b/frontend/appflowy_web_app/src/utils/platform.ts index 2196237aff..285e38bc73 100644 --- a/frontend/appflowy_web_app/src/utils/platform.ts +++ b/frontend/appflowy_web_app/src/utils/platform.ts @@ -1,5 +1,5 @@ export function getPlatform() { return { - isTauri: import.meta.env.TAURI_MODE, + isTauri: !!import.meta.env.TAURI_PLATFORM, }; } diff --git a/frontend/appflowy_web_app/src/vite-env.d.ts b/frontend/appflowy_web_app/src/vite-env.d.ts index 561122aa17..5748ee1aed 100644 --- a/frontend/appflowy_web_app/src/vite-env.d.ts +++ b/frontend/appflowy_web_app/src/vite-env.d.ts @@ -1,3 +1,12 @@ /// /// /// +/// +/// +interface Window { + refresh_token: (token: string) => void; + invalid_token: () => void; + WebFont?: { + load: (options: { google: { families: string[] } }) => void; + }; +} diff --git a/frontend/appflowy_web_app/tsconfig.json b/frontend/appflowy_web_app/tsconfig.json index 39e1d62e66..de30c24901 100644 --- a/frontend/appflowy_web_app/tsconfig.json +++ b/frontend/appflowy_web_app/tsconfig.json @@ -10,6 +10,8 @@ "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, @@ -17,9 +19,11 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, + "preserveValueImports": false, "noEmit": true, "jsx": "react-jsx", "types": [ + "cypress", "node", "jest" ], @@ -38,7 +42,9 @@ }, "include": [ "src", - "vite.config.ts" + "vite.config.ts", + "cypress.config.ts", + "cypress" ], "exclude": [ "node_modules" diff --git a/frontend/appflowy_web_app/tsconfig.web.json b/frontend/appflowy_web_app/tsconfig.web.json index f6c24c1512..5e0cdd176d 100644 --- a/frontend/appflowy_web_app/tsconfig.web.json +++ b/frontend/appflowy_web_app/tsconfig.web.json @@ -2,7 +2,8 @@ "extends": "./tsconfig.json", "exclude": [ "node_modules", - "src/application/services/tauri-services" + "src/application/services/tauri-services", + "**/*.cy.tsx" ], "references": [ { diff --git a/frontend/appflowy_web_app/vite.config.ts b/frontend/appflowy_web_app/vite.config.ts index 457db5df6e..b2621799ed 100644 --- a/frontend/appflowy_web_app/vite.config.ts +++ b/frontend/appflowy_web_app/vite.config.ts @@ -3,7 +3,6 @@ import react from '@vitejs/plugin-react'; import svgr from 'vite-plugin-svgr'; import wasm from 'vite-plugin-wasm'; import { visualizer } from 'rollup-plugin-visualizer'; -import { compression } from 'vite-plugin-compression2'; import usePluginImport from 'vite-plugin-importer'; import { totalBundleSize } from 'vite-plugin-total-bundle-size'; @@ -39,39 +38,30 @@ export default defineConfig({ }, }, }), - usePluginImport({ - libraryName: '@mui/material', - libraryDirectory: '', - camel2DashComponentName: false, - style: false, - }), usePluginImport({ libraryName: '@mui/icons-material', libraryDirectory: '', camel2DashComponentName: false, style: false, }), - process.env.ANALYZE_MODE ? - visualizer({ - emitFile: true, - }) : undefined, - process.env.ANALYZE_MODE ? totalBundleSize({ - fileNameRegex: /\.(js|css)$/, - calculateGzip: false, - }) : undefined, - !process.env.ANALYZE_MODE ? - compression({ - threshold: 1024, - deleteOriginalAssets: true, - }) : undefined, - + process.env.ANALYZE_MODE + ? visualizer({ + emitFile: true, + }) + : undefined, + process.env.ANALYZE_MODE + ? totalBundleSize({ + fileNameRegex: /\.(js|css)$/, + calculateGzip: false, + }) + : undefined, ], // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // prevent vite from obscuring rust errors clearScreen: false, // tauri expects a fixed port, fail if that port is not available server: { - port: process.env.TAURI_MODE ? 5173 : process.env.PORT ? parseInt(process.env.PORT) : 3000, + port: !!process.env.TAURI_PLATFORM ? 5173 : process.env.PORT ? parseInt(process.env.PORT) : 3000, strictPort: true, watch: { ignored: ['**/__tests__/**'], @@ -79,57 +69,58 @@ export default defineConfig({ cors: false, }, envPrefix: ['AF', 'TAURI_'], - build: process.env.TAURI_MODE + build: !!process.env.TAURI_PLATFORM ? { - // Tauri supports es2021 - target: process.env.TAURI_PLATFORM === 'windows' ? 'chrome105' : 'safari13', - // don't minify for debug builds - minify: !process.env.TAURI_DEBUG ? 'esbuild' : false, - // produce sourcemaps for debug builds - sourcemap: !!process.env.TAURI_DEBUG, - } + // Tauri supports es2021 + target: process.env.TAURI_PLATFORM === 'windows' ? 'chrome105' : 'safari13', + // don't minify for debug builds + minify: !process.env.TAURI_DEBUG ? 'esbuild' : false, + // produce sourcemaps for debug builds + sourcemap: !!process.env.TAURI_DEBUG, + } : { - target: `esnext`, - terserOptions: !isDev ? { - compress: { - keep_infinity: true, - drop_console: true, - drop_debugger: true, - }, - } : {}, - reportCompressedSize: false, - sourcemap: isDev, - rollupOptions: !isDev ? { - output: { - chunkFileNames: 'js/[name]-[hash].js', - entryFileNames: 'js/[name]-[hash].js', - assetFileNames: '[ext]/[name]-[hash].[ext]', - manualChunks (id) { - if (id.includes(('@mui'))) { - return 'mui'; + target: `esnext`, + terserOptions: !isDev + ? { + compress: { + keep_infinity: true, + drop_console: true, + drop_debugger: true, + }, } - if (id.includes('react-dom') || id.includes('react-is') || id.includes('react')) { - return 'react-framework'; + : {}, + reportCompressedSize: true, + sourcemap: isDev, + rollupOptions: !isDev + ? { + output: { + chunkFileNames: 'static/js/[name]-[hash].js', + entryFileNames: 'static/js/[name]-[hash].js', + assetFileNames: 'static/[ext]/[name]-[hash].[ext]', + manualChunks(id) { + if ( + id.includes('/react@') || + id.includes('/react-dom@') || + id.includes('/react-is@') || + id.includes('/yjs@') || + id.includes('/y-indexeddb@') || + id.includes('/dexie@') || + id.includes('/redux') + ) { + return 'common'; + } + }, + }, } - if (id.includes('@tauri-apps')) { - return 'tauri-api'; - } - - if (id.includes('node_modules')) { - return id.toString().split('node_modules/')[1].split('/')[0].toString(); - } - - }, - }, - } : {}, - }, + : {}, + }, resolve: { alias: [ { find: 'src/', replacement: `${__dirname}/src/` }, { find: '@/', replacement: `${__dirname}/src/` }, { find: '$client-services', - replacement: process.env.TAURI_MODE + replacement: !!process.env.TAURI_PLATFORM ? `${__dirname}/src/application/services/tauri-services` : `${__dirname}/src/application/services/js-services`, },