build: migrate to Vite 🚀 (#6818)
* init * add: vite dev build working * fix: href serving from public * feat: add ejs plugin * feat: migrated env files and ejs templating * chore: add types related to envs * chore: add vite-env types * feat: support vite pwa * chore: upgrade vite pwa * chore: pin node version to 16.18.1 * chore: preserve use of nodejs 14 * refactor: preserve REACT_APP as env prefix * chore: support esm environment variables * fix ts config * use VITE prefix and remove vite-plugin-env-compatible * introduce import-meta-loader for building pacakge as webpack isn't compatible with import.meta syntax * lint * remove import.meta.env in main.js * set debug flag to false * migrate to vitest and use jest-canvas-mock 2.4.0 so its comp atible with vite * integrate vitest-ui * fix most of teh test * snaps * Add script for testing with vite ui * fix all tests related to mocking * fix more test * fix more * fix flip.test.tsx * fix contentxmenu snaps * fix regression snaps * fix excalidraw.test.tsx and this makes all tests finally pass :) * use node 16 * specify node version * use node 16 in lint as well * fix mobile.test.tsx * use node 16 * add style-loader * upgrade to node 18 * fix lint package.json * support eslint with vite * fix lint * fix lint * fix ts * remove pwa/sw stuff * use env vars in EJS the vite way * fix lint * move remainig jest mock/spy to vite * don't cache locales * fix regex * add fonts cache * tweak * add custom service worker * upgrade vite and create font cache again * cache fonts.css and locales * tweak * use manifestTransforms for filtering locales * use assets js pattern for locales * add font.css to globIgnore so its pushed to fonts cache * create a separate chunk for locales with rollup * remove manifestTransforms and fix glob pattern for locales to filter from workbox pre-cache * push sourcemaps in production * add comments in config * lint * use node 18 * disable pwa in dev * fix * fix * increase limit of bundle * upgrade vite-pwa to latest * remove public/workbox so workbox assets are not precached * fon't club en.json and percentages.json with manual locales chunk to fix first load+offline mode * tweak regex * remove happy-dom as its not used * add comment * use any instead of ts-ignore * cleanup * remove jest-canvas-mock resolution as vite-canvas-mock was patched locking deps at 2.4.0 * use same theme color present in entry point * remove vite-plugin-eslint as it improves DX significantly * integrate vite-plugin-checker for ts errors * add nabla/vite-plugin-eslint * use eslint from checker only * add env variable VITE_APP_COLLAPSE_OVERLAY for collapsing the checker overlay * tweak vite checker overlay badge position * Enable eslint behind flag as its not working well with windows with non WSL * make port configurable * open the browser when server ready * enable eslint by default --------- Co-authored-by: Weslley Braga <weslley@bambee.com> Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
8af9ea3cf3
commit
48924688c7
@ -1,30 +1,39 @@
|
|||||||
REACT_APP_BACKEND_V2_GET_URL=https://json-dev.excalidraw.com/api/v2/
|
VITE_APP_BACKEND_V2_GET_URL=https://json-dev.excalidraw.com/api/v2/
|
||||||
REACT_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
|
VITE_APP_BACKEND_V2_POST_URL=https://json-dev.excalidraw.com/api/v2/post/
|
||||||
|
|
||||||
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
||||||
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
||||||
|
|
||||||
# collaboration WebSocket server (https://github.com/excalidraw/excalidraw-room)
|
# collaboration WebSocket server (https://github.com/excalidraw/excalidraw-room)
|
||||||
REACT_APP_WS_SERVER_URL=http://localhost:3002
|
VITE_APP_WS_SERVER_URL=http://localhost:3002
|
||||||
|
|
||||||
# set this only if using the collaboration workflow we use on excalidraw.com
|
# set this only if using the collaboration workflow we use on excalidraw.com
|
||||||
REACT_APP_PORTAL_URL=
|
VITE_APP_PORTAL_URL=
|
||||||
|
|
||||||
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
|
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyCMkxA60XIW8KbqMYL7edC4qT5l4qHX2h8","authDomain":"excalidraw-oss-dev.firebaseapp.com","projectId":"excalidraw-oss-dev","storageBucket":"excalidraw-oss-dev.appspot.com","messagingSenderId":"664559512677","appId":"1:664559512677:web:a385181f2928d328a7aa8c"}'
|
||||||
|
|
||||||
# put these in your .env.local, or make sure you don't commit!
|
# put these in your .env.local, or make sure you don't commit!
|
||||||
# must be lowercase `true` when turned on
|
# must be lowercase `true` when turned on
|
||||||
#
|
#
|
||||||
# whether to enable Service Workers in development
|
# whether to enable Service Workers in development
|
||||||
REACT_APP_DEV_ENABLE_SW=
|
VITE_APP_DEV_ENABLE_SW=
|
||||||
# whether to disable live reload / HMR. Usuaully what you want to do when
|
# whether to disable live reload / HMR. Usuaully what you want to do when
|
||||||
# debugging Service Workers.
|
# debugging Service Workers.
|
||||||
REACT_APP_DEV_DISABLE_LIVE_RELOAD=
|
VITE_APP_DEV_DISABLE_LIVE_RELOAD=
|
||||||
REACT_APP_DISABLE_TRACKING=true
|
VITE_APP_DISABLE_TRACKING=true
|
||||||
|
|
||||||
FAST_REFRESH=false
|
FAST_REFRESH=false
|
||||||
|
|
||||||
|
# The port the run the dev server
|
||||||
|
VITE_APP_PORT=3000
|
||||||
|
|
||||||
#Debug flags
|
#Debug flags
|
||||||
|
|
||||||
# To enable bounding box for text containers
|
# To enable bounding box for text containers
|
||||||
REACT_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX=
|
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX=
|
||||||
|
|
||||||
|
# Set this flag to false if you want to open the overlay by default
|
||||||
|
VITE_APP_COLLAPSE_OVERLAY=true
|
||||||
|
|
||||||
|
# Set this flag to false to disable eslint
|
||||||
|
VITE_APP_ENABLE_ESLINT=true
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
REACT_APP_BACKEND_V2_GET_URL=https://json.excalidraw.com/api/v2/
|
REACT_APP_BACKEND_V2_GET_URL=https://json.excalidraw.com/api/v2/
|
||||||
REACT_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
|
REACT_APP_BACKEND_V2_POST_URL=https://json.excalidraw.com/api/v2/post/
|
||||||
|
|
||||||
REACT_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
VITE_APP_LIBRARY_URL=https://libraries.excalidraw.com
|
||||||
REACT_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
VITE_APP_LIBRARY_BACKEND=https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries
|
||||||
|
|
||||||
REACT_APP_PORTAL_URL=https://portal.excalidraw.com
|
VITE_APP_PORTAL_URL=https://portal.excalidraw.com
|
||||||
# Fill to set socket server URL used for collaboration.
|
# Fill to set socket server URL used for collaboration.
|
||||||
# Meant for forks only: excalidraw.com uses custom REACT_APP_PORTAL_URL flow
|
# Meant for forks only: excalidraw.com uses custom VITE_APP_PORTAL_URL flow
|
||||||
REACT_APP_WS_SERVER_URL=
|
VITE_APP_WS_SERVER_URL=
|
||||||
|
|
||||||
REACT_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
|
VITE_APP_FIREBASE_CONFIG='{"apiKey":"AIzaSyAd15pYlMci_xIp9ko6wkEsDzAAA0Dn0RU","authDomain":"excalidraw-room-persistence.firebaseapp.com","databaseURL":"https://excalidraw-room-persistence.firebaseio.com","projectId":"excalidraw-room-persistence","storageBucket":"excalidraw-room-persistence.appspot.com","messagingSenderId":"654800341332","appId":"1:654800341332:web:4a692de832b55bd57ce0c1"}'
|
||||||
|
|
||||||
REACT_APP_PLUS_APP=https://app.excalidraw.com
|
VITE_APP_PLUS_APP=https://app.excalidraw.com
|
||||||
REACT_APP_DISABLE_TRACKING=
|
VITE_APP_DISABLE_TRACKING=
|
||||||
|
4
.github/workflows/autorelease-excalidraw.yml
vendored
4
.github/workflows/autorelease-excalidraw.yml
vendored
@ -12,10 +12,10 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Set up publish access
|
- name: Set up publish access
|
||||||
run: |
|
run: |
|
||||||
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
||||||
|
4
.github/workflows/autorelease-preview.yml
vendored
4
.github/workflows/autorelease-preview.yml
vendored
@ -32,10 +32,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ steps.sha.outputs.result }}
|
ref: ${{ steps.sha.outputs.result }}
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Set up publish access
|
- name: Set up publish access
|
||||||
run: |
|
run: |
|
||||||
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
|
||||||
|
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@ -9,10 +9,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
|
|
||||||
- name: Install and lint
|
- name: Install and lint
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/locales-coverage.yml
vendored
4
.github/workflows/locales-coverage.yml
vendored
@ -14,10 +14,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
token: ${{ secrets.PUSH_TRANSLATIONS_COVERAGE_PAT }}
|
||||||
|
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
|
|
||||||
- name: Create report file
|
- name: Create report file
|
||||||
run: |
|
run: |
|
||||||
|
4
.github/workflows/sentry-production.yml
vendored
4
.github/workflows/sentry-production.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Install and build
|
- name: Install and build
|
||||||
run: |
|
run: |
|
||||||
yarn --frozen-lockfile
|
yarn --frozen-lockfile
|
||||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -7,10 +7,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Setup Node.js 14.x
|
- name: Setup Node.js 18.x
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 14.x
|
node-version: 18.x
|
||||||
- name: Install and test
|
- name: Install and test
|
||||||
run: |
|
run: |
|
||||||
yarn --frozen-lockfile
|
yarn --frozen-lockfile
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -26,3 +26,5 @@ src/packages/excalidraw/example/public/bundle.js
|
|||||||
src/packages/excalidraw/example/public/excalidraw-assets-dev
|
src/packages/excalidraw/example/public/excalidraw-assets-dev
|
||||||
src/packages/excalidraw/example/public/excalidraw.development.js
|
src/packages/excalidraw/example/public/excalidraw.development.js
|
||||||
coverage
|
coverage
|
||||||
|
dev-dist
|
||||||
|
html
|
||||||
|
@ -78,8 +78,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<!------------------------------------------------------------------------->
|
<!------------------------------------------------------------------------->
|
||||||
|
<% if ("%PROD%" === "true") { %>
|
||||||
<% if (process.env.NODE_ENV === "production") { %>
|
|
||||||
<script>
|
<script>
|
||||||
// Redirect Excalidraw+ users which have auto-redirect enabled.
|
// Redirect Excalidraw+ users which have auto-redirect enabled.
|
||||||
//
|
//
|
||||||
@ -100,41 +99,35 @@
|
|||||||
</script>
|
</script>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
|
||||||
|
|
||||||
<!-- Excalidraw version -->
|
<!-- Excalidraw version -->
|
||||||
<meta name="version" content="{version}" />
|
<meta name="version" content="{version}" />
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="preload"
|
rel="preload"
|
||||||
href="Virgil.woff2"
|
href="/Virgil.woff2"
|
||||||
as="font"
|
as="font"
|
||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
rel="preload"
|
rel="preload"
|
||||||
href="Cascadia.woff2"
|
href="/Cascadia.woff2"
|
||||||
as="font"
|
as="font"
|
||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<link
|
<link rel="stylesheet" href="/fonts.css" type="text/css" />
|
||||||
rel="manifest"
|
<% if ("%VITE_APP_DEV_DISABLE_LIVE_RELOAD%"==="true" ) { %>
|
||||||
href="manifest.json"
|
|
||||||
style="--pwacompat-splash-font: 24px Virgil"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="fonts.css" type="text/css" />
|
|
||||||
<% if (process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD==="true" ) { %>
|
|
||||||
<script>
|
<script>
|
||||||
{
|
{
|
||||||
const _WebSocket = window.WebSocket;
|
const _WebSocket = window.WebSocket;
|
||||||
window.WebSocket = function (url) {
|
window.WebSocket = function (url) {
|
||||||
if (/ws:\/\/localhost:.+?\/sockjs-node/.test(url)) {
|
if (/ws:\/\/localhost:.+?\/sockjs-node/.test(url)) {
|
||||||
console.info(
|
console.info(
|
||||||
"[!!!] Live reload is disabled via process.env.REACT_APP_DEV_DISABLE_LIVE_RELOAD [!!!]",
|
"[!!!] Live reload is disabled via VITE_APP_DEV_DISABLE_LIVE_RELOAD [!!!]",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return new _WebSocket(url);
|
return new _WebSocket(url);
|
||||||
@ -200,7 +193,8 @@
|
|||||||
<h1 class="visually-hidden">Excalidraw</h1>
|
<h1 class="visually-hidden">Excalidraw</h1>
|
||||||
</header>
|
</header>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<% if (process.env.REACT_APP_DISABLE_TRACKING !== 'true') { %>
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
<% if ("%VITE_APP_DEV_DISABLE_LIVE_RELOAD%" !== 'true') { %>
|
||||||
<!-- 100% privacy friendly analytics -->
|
<!-- 100% privacy friendly analytics -->
|
||||||
<script>
|
<script>
|
||||||
// need to load this script dynamically bcs. of iframe embed tracking
|
// need to load this script dynamically bcs. of iframe embed tracking
|
65
package.json
65
package.json
@ -32,6 +32,7 @@
|
|||||||
"canvas-roundrect-polyfill": "0.0.1",
|
"canvas-roundrect-polyfill": "0.0.1",
|
||||||
"clsx": "1.1.1",
|
"clsx": "1.1.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
|
"eslint-plugin-react": "7.32.2",
|
||||||
"fake-indexeddb": "3.1.7",
|
"fake-indexeddb": "3.1.7",
|
||||||
"firebase": "8.3.3",
|
"firebase": "8.3.3",
|
||||||
"i18next-browser-languagedetector": "6.1.4",
|
"i18next-browser-languagedetector": "6.1.4",
|
||||||
@ -51,26 +52,13 @@
|
|||||||
"pwacompat": "2.0.17",
|
"pwacompat": "2.0.17",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-scripts": "5.0.1",
|
|
||||||
"roughjs": "4.5.2",
|
"roughjs": "4.5.2",
|
||||||
"sass": "1.51.0",
|
"sass": "1.51.0",
|
||||||
"socket.io-client": "2.3.1",
|
"socket.io-client": "2.3.1",
|
||||||
"tunnel-rat": "0.1.2",
|
"tunnel-rat": "0.1.2"
|
||||||
"workbox-background-sync": "^6.5.4",
|
|
||||||
"workbox-broadcast-update": "^6.5.4",
|
|
||||||
"workbox-cacheable-response": "^6.5.4",
|
|
||||||
"workbox-core": "^6.5.4",
|
|
||||||
"workbox-expiration": "^6.5.4",
|
|
||||||
"workbox-google-analytics": "^6.5.4",
|
|
||||||
"workbox-navigation-preload": "^6.5.4",
|
|
||||||
"workbox-precaching": "^6.5.4",
|
|
||||||
"workbox-range-requests": "^6.5.4",
|
|
||||||
"workbox-routing": "^6.5.4",
|
|
||||||
"workbox-strategies": "^6.5.4",
|
|
||||||
"workbox-streams": "^6.5.4"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@excalidraw/eslint-config": "1.0.0",
|
"@excalidraw/eslint-config": "1.0.3",
|
||||||
"@excalidraw/prettier-config": "1.0.2",
|
"@excalidraw/prettier-config": "1.0.2",
|
||||||
"@types/chai": "4.3.0",
|
"@types/chai": "4.3.0",
|
||||||
"@types/jest": "27.4.0",
|
"@types/jest": "27.4.0",
|
||||||
@ -81,48 +69,42 @@
|
|||||||
"@types/react-dom": "18.0.6",
|
"@types/react-dom": "18.0.6",
|
||||||
"@types/resize-observer-browser": "0.1.7",
|
"@types/resize-observer-browser": "0.1.7",
|
||||||
"@types/socket.io-client": "1.4.36",
|
"@types/socket.io-client": "1.4.36",
|
||||||
|
"@vitejs/plugin-react": "3.1.0",
|
||||||
|
"@vitest/ui": "0.32.2",
|
||||||
"chai": "4.3.6",
|
"chai": "4.3.6",
|
||||||
"dotenv": "16.0.1",
|
"dotenv": "16.0.1",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
|
"eslint-config-react-app": "7.0.1",
|
||||||
"eslint-plugin-prettier": "3.3.1",
|
"eslint-plugin-prettier": "3.3.1",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"husky": "7.0.4",
|
"husky": "7.0.4",
|
||||||
"jest-canvas-mock": "2.4.0",
|
"jsdom": "22.1.0",
|
||||||
"lint-staged": "12.3.7",
|
"lint-staged": "12.3.7",
|
||||||
"pepjs": "0.5.3",
|
"pepjs": "0.5.3",
|
||||||
"prettier": "2.6.2",
|
"prettier": "2.6.2",
|
||||||
"rewire": "6.0.0",
|
"rewire": "6.0.0",
|
||||||
"typescript": "4.9.4"
|
"typescript": "4.9.4",
|
||||||
|
"vite": "4.4.2",
|
||||||
|
"vite-plugin-checker": "0.6.1",
|
||||||
|
"vite-plugin-ejs": "1.6.4",
|
||||||
|
"vite-plugin-pwa": "0.16.4",
|
||||||
|
"vite-plugin-svgr": "2.4.0",
|
||||||
|
"vitest": "0.32.2",
|
||||||
|
"vitest-canvas-mock": "0.3.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=18.0.0"
|
||||||
},
|
},
|
||||||
"homepage": ".",
|
"homepage": ".",
|
||||||
"jest": {
|
|
||||||
"collectCoverageFrom": [
|
|
||||||
"src/**/*.{js,jsx,ts,tsx}"
|
|
||||||
],
|
|
||||||
"coveragePathIgnorePatterns": [
|
|
||||||
"<rootDir>/locales",
|
|
||||||
"<rootDir>/src/packages/excalidraw/dist/",
|
|
||||||
"<rootDir>/src/packages/excalidraw/types",
|
|
||||||
"<rootDir>/src/packages/excalidraw/example"
|
|
||||||
],
|
|
||||||
"transformIgnorePatterns": [
|
|
||||||
"node_modules/(?!(roughjs|points-on-curve|path-data-parser|points-on-path|browser-fs-access|canvas-roundrect-polyfill)/)"
|
|
||||||
],
|
|
||||||
"resetMocks": false
|
|
||||||
},
|
|
||||||
"name": "excalidraw",
|
"name": "excalidraw",
|
||||||
"prettier": "@excalidraw/prettier-config",
|
"prettier": "@excalidraw/prettier-config",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-node": "node ./scripts/build-node.js",
|
"build-node": "node ./scripts/build-node.js",
|
||||||
"build:app:docker": "cross-env REACT_APP_DISABLE_SENTRY=true REACT_APP_DISABLE_TRACKING=true react-scripts build",
|
"build:app:docker": "cross-env REACT_APP_DISABLE_SENTRY=true REACT_APP_DISABLE_TRACKING=true vite build",
|
||||||
"build:app": "cross-env REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA react-scripts build",
|
"build:app": "cross-env REACT_APP_GIT_SHA=$VERCEL_GIT_COMMIT_SHA vite build",
|
||||||
"build:version": "node ./scripts/build-version.js",
|
"build:version": "node ./scripts/build-version.js",
|
||||||
"build": "yarn build:app && yarn build:version",
|
"build": "yarn build:app && yarn build:version",
|
||||||
"eject": "react-scripts eject",
|
|
||||||
"fix:code": "yarn test:code --fix",
|
"fix:code": "yarn test:code --fix",
|
||||||
"fix:other": "yarn prettier --write",
|
"fix:other": "yarn prettier --write",
|
||||||
"fix": "yarn fix:other && yarn fix:code",
|
"fix": "yarn fix:other && yarn fix:code",
|
||||||
@ -130,19 +112,20 @@
|
|||||||
"locales-coverage:description": "node scripts/locales-coverage-description.js",
|
"locales-coverage:description": "node scripts/locales-coverage-description.js",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore",
|
"prettier": "prettier \"**/*.{css,scss,json,md,html,yml}\" --ignore-path=.eslintignore",
|
||||||
"start": "react-scripts start",
|
"start": "vite",
|
||||||
"start:production": "npm run build && npx http-server build -a localhost -p 5001 -o",
|
"start:production": "npm run build && npx http-server build -a localhost -p 5001 -o",
|
||||||
"test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false",
|
"test:all": "yarn test:typecheck && yarn test:code && yarn test:other && yarn test:app --watchAll=false",
|
||||||
"test:app": "react-scripts test --passWithNoTests",
|
"test:app": "vitest --config vitest.config.ts",
|
||||||
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .",
|
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .",
|
||||||
"test:debug": "react-scripts --inspect-brk test --runInBand --no-cache",
|
|
||||||
"test:other": "yarn prettier --list-different",
|
"test:other": "yarn prettier --list-different",
|
||||||
"test:typecheck": "tsc",
|
"test:typecheck": "tsc",
|
||||||
"test:update": "yarn test:app --updateSnapshot --watchAll=false",
|
"test:update": "yarn test:app --update --watch=false",
|
||||||
"test": "yarn test:app",
|
"test": "yarn test:app",
|
||||||
"test:coverage": "react-scripts test --passWithNoTests --coverage --watchAll",
|
"test:coverage": "vitest --coverage --watchAll",
|
||||||
|
"test:ui": "yarn test --ui",
|
||||||
"autorelease": "node scripts/autorelease.js",
|
"autorelease": "node scripts/autorelease.js",
|
||||||
"prerelease": "node scripts/prerelease.js",
|
"prerelease": "node scripts/prerelease.js",
|
||||||
|
"build:preview": "yarn build && vite preview --port 5000",
|
||||||
"release": "node scripts/release.js"
|
"release": "node scripts/release.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.backgroundSync=function(t,e,s){"use strict";try{self["workbox:background-sync:4.3.1"]&&_()}catch(t){}const i=3,n="workbox-background-sync",a="requests",r="queueName";class c{constructor(t){this.t=t,this.s=new s.DBWrapper(n,i,{onupgradeneeded:this.i})}async pushEntry(t){delete t.id,t.queueName=this.t,await this.s.add(a,t)}async unshiftEntry(t){const[e]=await this.s.getAllMatching(a,{count:1});e?t.id=e.id-1:delete t.id,t.queueName=this.t,await this.s.add(a,t)}async popEntry(){return this.h({direction:"prev"})}async shiftEntry(){return this.h({direction:"next"})}async getAll(){return await this.s.getAllMatching(a,{index:r,query:IDBKeyRange.only(this.t)})}async deleteEntry(t){await this.s.delete(a,t)}async h({direction:t}){const[e]=await this.s.getAllMatching(a,{direction:t,index:r,query:IDBKeyRange.only(this.t),count:1});if(e)return await this.deleteEntry(e.id),e}i(t){const e=t.target.result;t.oldVersion>0&&t.oldVersion<i&&e.objectStoreNames.contains(a)&&e.deleteObjectStore(a),e.createObjectStore(a,{autoIncrement:!0,keyPath:"id"}).createIndex(r,r,{unique:!1})}}const h=["method","referrer","referrerPolicy","mode","credentials","cache","redirect","integrity","keepalive"];class o{static async fromRequest(t){const e={url:t.url,headers:{}};"GET"!==t.method&&(e.body=await t.clone().arrayBuffer());for(const[s,i]of t.headers.entries())e.headers[s]=i;for(const s of h)void 0!==t[s]&&(e[s]=t[s]);return new o(e)}constructor(t){"navigate"===t.mode&&(t.mode="same-origin"),this.o=t}toObject(){const t=Object.assign({},this.o);return t.headers=Object.assign({},this.o.headers),t.body&&(t.body=t.body.slice(0)),t}toRequest(){return new Request(this.o.url,this.o)}clone(){return new o(this.toObject())}}const u="workbox-background-sync",y=10080,w=new Set;class d{constructor(t,{onSync:s,maxRetentionTime:i}={}){if(w.has(t))throw new e.WorkboxError("duplicate-queue-name",{name:t});w.add(t),this.u=t,this.l=s||this.replayRequests,this.q=i||y,this.m=new c(this.u),this.p()}get name(){return this.u}async pushRequest(t){await this.g(t,"push")}async unshiftRequest(t){await this.g(t,"unshift")}async popRequest(){return this.R("pop")}async shiftRequest(){return this.R("shift")}async getAll(){const t=await this.m.getAll(),e=Date.now(),s=[];for(const i of t){const t=60*this.q*1e3;e-i.timestamp>t?await this.m.deleteEntry(i.id):s.push(f(i))}return s}async g({request:t,metadata:e,timestamp:s=Date.now()},i){const n={requestData:(await o.fromRequest(t.clone())).toObject(),timestamp:s};e&&(n.metadata=e),await this.m[`${i}Entry`](n),this.k?this.D=!0:await this.registerSync()}async R(t){const e=Date.now(),s=await this.m[`${t}Entry`]();if(s){const i=60*this.q*1e3;return e-s.timestamp>i?this.R(t):f(s)}}async replayRequests(){let t;for(;t=await this.shiftRequest();)try{await fetch(t.request.clone())}catch(s){throw await this.unshiftRequest(t),new e.WorkboxError("queue-replay-failed",{name:this.u})}}async registerSync(){if("sync"in registration)try{await registration.sync.register(`${u}:${this.u}`)}catch(t){}}p(){"sync"in registration?self.addEventListener("sync",t=>{if(t.tag===`${u}:${this.u}`){const e=async()=>{let e;this.k=!0;try{await this.l({queue:this})}catch(t){throw e=t}finally{!this.D||e&&!t.lastChance||await this.registerSync(),this.k=!1,this.D=!1}};t.waitUntil(e())}}):this.l({queue:this})}static get _(){return w}}const f=t=>{const e={request:new o(t.requestData).toRequest(),timestamp:t.timestamp};return t.metadata&&(e.metadata=t.metadata),e};return t.Queue=d,t.Plugin=class{constructor(...t){this.v=new d(...t),this.fetchDidFail=this.fetchDidFail.bind(this)}async fetchDidFail({request:t}){await this.v.pushRequest({request:t})}},t}({},workbox.core._private,workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-background-sync.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.broadcastUpdate=function(e,t){"use strict";try{self["workbox:broadcast-update:4.3.1"]&&_()}catch(e){}const s=(e,t,s)=>{return!s.some(s=>e.headers.has(s)&&t.headers.has(s))||s.every(s=>{const n=e.headers.has(s)===t.headers.has(s),a=e.headers.get(s)===t.headers.get(s);return n&&a})},n="workbox",a=1e4,i=["content-length","etag","last-modified"],o=async({channel:e,cacheName:t,url:s})=>{const n={type:"CACHE_UPDATED",meta:"workbox-broadcast-update",payload:{cacheName:t,updatedURL:s}};if(e)e.postMessage(n);else{const e=await clients.matchAll({type:"window"});for(const t of e)t.postMessage(n)}};class c{constructor({headersToCheck:e,channelName:t,deferNoticationTimeout:s}={}){this.t=e||i,this.s=t||n,this.i=s||a,this.o()}notifyIfUpdated({oldResponse:e,newResponse:t,url:n,cacheName:a,event:i}){if(!s(e,t,this.t)){const e=(async()=>{i&&i.request&&"navigate"===i.request.mode&&await this.h(i),await this.l({channel:this.u(),cacheName:a,url:n})})();if(i)try{i.waitUntil(e)}catch(e){}return e}}async l(e){await o(e)}u(){return"BroadcastChannel"in self&&!this.p&&(this.p=new BroadcastChannel(this.s)),this.p}h(e){if(!this.m.has(e)){const s=new t.Deferred;this.m.set(e,s);const n=setTimeout(()=>{s.resolve()},this.i);s.promise.then(()=>clearTimeout(n))}return this.m.get(e).promise}o(){this.m=new Map,self.addEventListener("message",e=>{if("WINDOW_READY"===e.data.type&&"workbox-window"===e.data.meta&&this.m.size>0){for(const e of this.m.values())e.resolve();this.m.clear()}})}}return e.BroadcastCacheUpdate=c,e.Plugin=class{constructor(e){this.l=new c(e)}cacheDidUpdate({cacheName:e,oldResponse:t,newResponse:s,request:n,event:a}){t&&this.l.notifyIfUpdated({cacheName:e,oldResponse:t,newResponse:s,event:a,url:n.url})}},e.broadcastUpdate=o,e.responsesAreSame=s,e}({},workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-broadcast-update.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.cacheableResponse=function(t){"use strict";try{self["workbox:cacheable-response:4.3.1"]&&_()}catch(t){}class s{constructor(t={}){this.t=t.statuses,this.s=t.headers}isResponseCacheable(t){let s=!0;return this.t&&(s=this.t.includes(t.status)),this.s&&s&&(s=Object.keys(this.s).some(s=>t.headers.get(s)===this.s[s])),s}}return t.CacheableResponse=s,t.Plugin=class{constructor(t){this.i=new s(t)}cacheWillUpdate({response:t}){return this.i.isResponseCacheable(t)?t:null}},t}({});
|
|
||||||
//# sourceMappingURL=workbox-cacheable-response.prod.js.map
|
|
File diff suppressed because one or more lines are too long
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.expiration=function(t,e,s,i,a,n){"use strict";try{self["workbox:expiration:4.3.1"]&&_()}catch(t){}const h="workbox-expiration",c="cache-entries",r=t=>{const e=new URL(t,location);return e.hash="",e.href};class o{constructor(t){this.t=t,this.s=new e.DBWrapper(h,1,{onupgradeneeded:t=>this.i(t)})}i(t){const e=t.target.result.createObjectStore(c,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1}),s.deleteDatabase(this.t)}async setTimestamp(t,e){t=r(t),await this.s.put(c,{url:t,timestamp:e,cacheName:this.t,id:this.h(t)})}async getTimestamp(t){return(await this.s.get(c,this.h(t))).timestamp}async expireEntries(t,e){const s=await this.s.transaction(c,"readwrite",(s,i)=>{const a=s.objectStore(c),n=[];let h=0;a.index("timestamp").openCursor(null,"prev").onsuccess=(({target:s})=>{const a=s.result;if(a){const s=a.value;s.cacheName===this.t&&(t&&s.timestamp<t||e&&h>=e?n.push(a.value):h++),a.continue()}else i(n)})}),i=[];for(const t of s)await this.s.delete(c,t.id),i.push(t.url);return i}h(t){return this.t+"|"+r(t)}}class u{constructor(t,e={}){this.o=!1,this.u=!1,this.l=e.maxEntries,this.p=e.maxAgeSeconds,this.t=t,this.m=new o(t)}async expireEntries(){if(this.o)return void(this.u=!0);this.o=!0;const t=this.p?Date.now()-1e3*this.p:void 0,e=await this.m.expireEntries(t,this.l),s=await caches.open(this.t);for(const t of e)await s.delete(t);this.o=!1,this.u&&(this.u=!1,this.expireEntries())}async updateTimestamp(t){await this.m.setTimestamp(t,Date.now())}async isURLExpired(t){return await this.m.getTimestamp(t)<Date.now()-1e3*this.p}async delete(){this.u=!1,await this.m.expireEntries(1/0)}}return t.CacheExpiration=u,t.Plugin=class{constructor(t={}){this.D=t,this.p=t.maxAgeSeconds,this.g=new Map,t.purgeOnQuotaError&&n.registerQuotaErrorCallback(()=>this.deleteCacheAndMetadata())}k(t){if(t===a.cacheNames.getRuntimeName())throw new i.WorkboxError("expire-custom-caches-only");let e=this.g.get(t);return e||(e=new u(t,this.D),this.g.set(t,e)),e}cachedResponseWillBeUsed({event:t,request:e,cacheName:s,cachedResponse:i}){if(!i)return null;let a=this.N(i);const n=this.k(s);n.expireEntries();const h=n.updateTimestamp(e.url);if(t)try{t.waitUntil(h)}catch(t){}return a?i:null}N(t){if(!this.p)return!0;const e=this._(t);return null===e||e>=Date.now()-1e3*this.p}_(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async cacheDidUpdate({cacheName:t,request:e}){const s=this.k(t);await s.updateTimestamp(e.url),await s.expireEntries()}async deleteCacheAndMetadata(){for(const[t,e]of this.g)await caches.delete(t),await e.delete();this.g=new Map}},t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private,workbox.core);
|
|
||||||
//# sourceMappingURL=workbox-expiration.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.navigationPreload=function(t){"use strict";try{self["workbox:navigation-preload:4.3.1"]&&_()}catch(t){}function e(){return Boolean(self.registration&&self.registration.navigationPreload)}return t.disable=function(){e()&&self.addEventListener("activate",t=>{t.waitUntil(self.registration.navigationPreload.disable().then(()=>{}))})},t.enable=function(t){e()&&self.addEventListener("activate",e=>{e.waitUntil(self.registration.navigationPreload.enable().then(()=>{t&&self.registration.navigationPreload.setHeaderValue(t)}))})},t.isSupported=e,t}({});
|
|
||||||
//# sourceMappingURL=workbox-navigation-preload.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.googleAnalytics=function(e,t,o,n,a,c,w){"use strict";try{self["workbox:google-analytics:4.3.1"]&&_()}catch(e){}const r=/^\/(\w+\/)?collect/,s=e=>async({queue:t})=>{let o;for(;o=await t.shiftRequest();){const{request:n,timestamp:a}=o,c=new URL(n.url);try{const w="POST"===n.method?new URLSearchParams(await n.clone().text()):c.searchParams,r=a-(Number(w.get("qt"))||0),s=Date.now()-r;if(w.set("qt",s),e.parameterOverrides)for(const t of Object.keys(e.parameterOverrides)){const o=e.parameterOverrides[t];w.set(t,o)}"function"==typeof e.hitFilter&&e.hitFilter.call(null,w),await fetch(new Request(c.origin+c.pathname,{body:w.toString(),method:"POST",mode:"cors",credentials:"omit",headers:{"Content-Type":"text/plain"}}))}catch(e){throw await t.unshiftRequest(o),e}}},i=e=>{const t=({url:e})=>"www.google-analytics.com"===e.hostname&&r.test(e.pathname),o=new w.NetworkOnly({plugins:[e]});return[new n.Route(t,o,"GET"),new n.Route(t,o,"POST")]},l=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.google-analytics.com"===e.hostname&&"/analytics.js"===e.pathname,t,"GET")},m=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.googletagmanager.com"===e.hostname&&"/gtag/js"===e.pathname,t,"GET")},u=e=>{const t=new c.NetworkFirst({cacheName:e});return new n.Route(({url:e})=>"www.googletagmanager.com"===e.hostname&&"/gtm.js"===e.pathname,t,"GET")};return e.initialize=((e={})=>{const n=o.cacheNames.getGoogleAnalyticsName(e.cacheName),c=new t.Plugin("workbox-google-analytics",{maxRetentionTime:2880,onSync:s(e)}),w=[u(n),l(n),m(n),...i(c)],r=new a.Router;for(const e of w)r.registerRoute(e);r.addFetchListener()}),e}({},workbox.backgroundSync,workbox.core._private,workbox.routing,workbox.routing,workbox.strategies,workbox.strategies);
|
|
||||||
//# sourceMappingURL=workbox-offline-ga.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.precaching=function(t,e,n,s,c){"use strict";try{self["workbox:precaching:4.3.1"]&&_()}catch(t){}const o=[],i={get:()=>o,add(t){o.push(...t)}};const a="__WB_REVISION__";function r(t){if(!t)throw new c.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new c.WorkboxError("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location);return{cacheKey:t.href,url:t.href}}const s=new URL(n,location),o=new URL(n,location);return o.searchParams.set(a,e),{cacheKey:o.href,url:s.href}}class l{constructor(t){this.t=e.cacheNames.getPrecacheName(t),this.s=new Map}addToCacheList(t){for(const e of t){const{cacheKey:t,url:n}=r(e);if(this.s.has(n)&&this.s.get(n)!==t)throw new c.WorkboxError("add-to-cache-list-conflicting-entries",{firstEntry:this.s.get(n),secondEntry:t});this.s.set(n,t)}}async install({event:t,plugins:e}={}){const n=[],s=[],c=await caches.open(this.t),o=await c.keys(),i=new Set(o.map(t=>t.url));for(const t of this.s.values())i.has(t)?s.push(t):n.push(t);const a=n.map(n=>this.o({event:t,plugins:e,url:n}));return await Promise.all(a),{updatedURLs:n,notUpdatedURLs:s}}async activate(){const t=await caches.open(this.t),e=await t.keys(),n=new Set(this.s.values()),s=[];for(const c of e)n.has(c.url)||(await t.delete(c),s.push(c.url));return{deletedURLs:s}}async o({url:t,event:e,plugins:o}){const i=new Request(t,{credentials:"same-origin"});let a,r=await s.fetchWrapper.fetch({event:e,plugins:o,request:i});for(const t of o||[])"cacheWillUpdate"in t&&(a=t.cacheWillUpdate.bind(t));if(!(a?a({event:e,request:i,response:r}):r.status<400))throw new c.WorkboxError("bad-precaching-response",{url:t,status:r.status});r.redirected&&(r=await async function(t){const e=t.clone(),n="body"in e?Promise.resolve(e.body):e.blob(),s=await n;return new Response(s,{headers:e.headers,status:e.status,statusText:e.statusText})}(r)),await n.cacheWrapper.put({event:e,plugins:o,request:i,response:r,cacheName:this.t,matchOptions:{ignoreSearch:!0}})}getURLsToCacheKeys(){return this.s}getCachedURLs(){return[...this.s.keys()]}getCacheKeyForURL(t){const e=new URL(t,location);return this.s.get(e.href)}}let u;const h=()=>(u||(u=new l),u);const d=(t,e)=>{const n=h().getURLsToCacheKeys();for(const s of function*(t,{ignoreURLParametersMatching:e,directoryIndex:n,cleanURLs:s,urlManipulation:c}={}){const o=new URL(t,location);o.hash="",yield o.href;const i=function(t,e){for(const n of[...t.searchParams.keys()])e.some(t=>t.test(n))&&t.searchParams.delete(n);return t}(o,e);if(yield i.href,n&&i.pathname.endsWith("/")){const t=new URL(i);t.pathname+=n,yield t.href}if(s){const t=new URL(i);t.pathname+=".html",yield t.href}if(c){const t=c({url:o});for(const e of t)yield e.href}}(t,e)){const t=n.get(s);if(t)return t}};let w=!1;const f=t=>{w||((({ignoreURLParametersMatching:t=[/^utm_/],directoryIndex:n="index.html",cleanURLs:s=!0,urlManipulation:c=null}={})=>{const o=e.cacheNames.getPrecacheName();addEventListener("fetch",e=>{const i=d(e.request.url,{cleanURLs:s,directoryIndex:n,ignoreURLParametersMatching:t,urlManipulation:c});if(!i)return;let a=caches.open(o).then(t=>t.match(i)).then(t=>t||fetch(i));e.respondWith(a)})})(t),w=!0)},y=t=>{const e=h(),n=i.get();t.waitUntil(e.install({event:t,plugins:n}).catch(t=>{throw t}))},p=t=>{const e=h(),n=i.get();t.waitUntil(e.activate({event:t,plugins:n}))},L=t=>{h().addToCacheList(t),t.length>0&&(addEventListener("install",y),addEventListener("activate",p))};return t.addPlugins=(t=>{i.add(t)}),t.addRoute=f,t.cleanupOutdatedCaches=(()=>{addEventListener("activate",t=>{const n=e.cacheNames.getPrecacheName();t.waitUntil((async(t,e="-precache-")=>{const n=(await caches.keys()).filter(n=>n.includes(e)&&n.includes(self.registration.scope)&&n!==t);return await Promise.all(n.map(t=>caches.delete(t))),n})(n).then(t=>{}))})}),t.getCacheKeyForURL=(t=>{return h().getCacheKeyForURL(t)}),t.precache=L,t.precacheAndRoute=((t,e)=>{L(t),f(e)}),t.PrecacheController=l,t}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-precaching.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.rangeRequests=function(e,n){"use strict";try{self["workbox:range-requests:4.3.1"]&&_()}catch(e){}async function t(e,t){try{if(206===t.status)return t;const s=e.headers.get("range");if(!s)throw new n.WorkboxError("no-range-header");const a=function(e){const t=e.trim().toLowerCase();if(!t.startsWith("bytes="))throw new n.WorkboxError("unit-must-be-bytes",{normalizedRangeHeader:t});if(t.includes(","))throw new n.WorkboxError("single-range-only",{normalizedRangeHeader:t});const s=/(\d*)-(\d*)/.exec(t);if(null===s||!s[1]&&!s[2])throw new n.WorkboxError("invalid-range-values",{normalizedRangeHeader:t});return{start:""===s[1]?null:Number(s[1]),end:""===s[2]?null:Number(s[2])}}(s),r=await t.blob(),i=function(e,t,s){const a=e.size;if(s>a||t<0)throw new n.WorkboxError("range-not-satisfiable",{size:a,end:s,start:t});let r,i;return null===t?(r=a-s,i=a):null===s?(r=t,i=a):(r=t,i=s+1),{start:r,end:i}}(r,a.start,a.end),o=r.slice(i.start,i.end),u=o.size,l=new Response(o,{status:206,statusText:"Partial Content",headers:t.headers});return l.headers.set("Content-Length",u),l.headers.set("Content-Range",`bytes ${i.start}-${i.end-1}/`+r.size),l}catch(e){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}}return e.createPartialResponse=t,e.Plugin=class{async cachedResponseWillBeUsed({request:e,cachedResponse:n}){return n&&e.headers.has("range")?await t(e,n):n}},e}({},workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-range-requests.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.routing=function(t,e,r){"use strict";try{self["workbox:routing:4.3.1"]&&_()}catch(t){}const s="GET",n=t=>t&&"object"==typeof t?t:{handle:t};class o{constructor(t,e,r){this.handler=n(e),this.match=t,this.method=r||s}}class i extends o{constructor(t,{whitelist:e=[/./],blacklist:r=[]}={}){super(t=>this.t(t),t),this.s=e,this.o=r}t({url:t,request:e}){if("navigate"!==e.mode)return!1;const r=t.pathname+t.search;for(const t of this.o)if(t.test(r))return!1;return!!this.s.some(t=>t.test(r))}}class u extends o{constructor(t,e,r){super(({url:e})=>{const r=t.exec(e.href);return r?e.origin!==location.origin&&0!==r.index?null:r.slice(1):null},e,r)}}class c{constructor(){this.i=new Map}get routes(){return this.i}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,r=this.handleRequest({request:e,event:t});r&&t.respondWith(r)})}addCacheListener(){self.addEventListener("message",async t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,r=Promise.all(e.urlsToCache.map(t=>{"string"==typeof t&&(t=[t]);const e=new Request(...t);return this.handleRequest({request:e})}));t.waitUntil(r),t.ports&&t.ports[0]&&(await r,t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const r=new URL(t.url,location);if(!r.protocol.startsWith("http"))return;let s,{params:n,route:o}=this.findMatchingRoute({url:r,request:t,event:e}),i=o&&o.handler;if(!i&&this.u&&(i=this.u),i){try{s=i.handle({url:r,request:t,event:e,params:n})}catch(t){s=Promise.reject(t)}return s&&this.h&&(s=s.catch(t=>this.h.handle({url:r,event:e,err:t}))),s}}findMatchingRoute({url:t,request:e,event:r}){const s=this.i.get(e.method)||[];for(const n of s){let s,o=n.match({url:t,request:e,event:r});if(o)return Array.isArray(o)&&o.length>0?s=o:o.constructor===Object&&Object.keys(o).length>0&&(s=o),{route:n,params:s}}return{}}setDefaultHandler(t){this.u=n(t)}setCatchHandler(t){this.h=n(t)}registerRoute(t){this.i.has(t.method)||this.i.set(t.method,[]),this.i.get(t.method).push(t)}unregisterRoute(t){if(!this.i.has(t.method))throw new r.WorkboxError("unregister-route-but-not-found-with-method",{method:t.method});const e=this.i.get(t.method).indexOf(t);if(!(e>-1))throw new r.WorkboxError("unregister-route-route-not-registered");this.i.get(t.method).splice(e,1)}}let a;const h=()=>(a||((a=new c).addFetchListener(),a.addCacheListener()),a);return t.NavigationRoute=i,t.RegExpRoute=u,t.registerNavigationRoute=((t,r={})=>{const s=e.cacheNames.getPrecacheName(r.cacheName),n=new i(async()=>{try{const e=await caches.match(t,{cacheName:s});if(e)return e;throw new Error(`The cache ${s} did not have an entry for `+`${t}.`)}catch(e){return fetch(t)}},{whitelist:r.whitelist,blacklist:r.blacklist});return h().registerRoute(n),n}),t.registerRoute=((t,e,s="GET")=>{let n;if("string"==typeof t){const r=new URL(t,location);n=new o(({url:t})=>t.href===r.href,e,s)}else if(t instanceof RegExp)n=new u(t,e,s);else if("function"==typeof t)n=new o(t,e,s);else{if(!(t instanceof o))throw new r.WorkboxError("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});n=t}return h().registerRoute(n),n}),t.Route=o,t.Router=c,t.setCatchHandler=(t=>{h().setCatchHandler(t)}),t.setDefaultHandler=(t=>{h().setDefaultHandler(t)}),t}({},workbox.core._private,workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-routing.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.strategies=function(e,t,s,n,r){"use strict";try{self["workbox:strategies:4.3.1"]&&_()}catch(e){}class i{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));let n,i=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(!i)try{i=await this.u(t,e)}catch(e){n=e}if(!i)throw new r.WorkboxError("no-response",{url:t.url,error:n});return i}async u(e,t){const r=await n.fetchWrapper.fetch({request:e,event:t,fetchOptions:this.i,plugins:this.s}),i=r.clone(),h=s.cacheWrapper.put({cacheName:this.t,request:e,response:i,event:t,plugins:this.s});if(t)try{t.waitUntil(h)}catch(e){}return r}}class h{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));const n=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(!n)throw new r.WorkboxError("no-response",{url:t.url});return n}}const u={cacheWillUpdate:({response:e})=>200===e.status||0===e.status?e:null};class a{constructor(e={}){if(this.t=t.cacheNames.getRuntimeName(e.cacheName),e.plugins){let t=e.plugins.some(e=>!!e.cacheWillUpdate);this.s=t?e.plugins:[u,...e.plugins]}else this.s=[u];this.o=e.networkTimeoutSeconds,this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){const s=[];"string"==typeof t&&(t=new Request(t));const n=[];let i;if(this.o){const{id:r,promise:h}=this.l({request:t,event:e,logs:s});i=r,n.push(h)}const h=this.q({timeoutId:i,request:t,event:e,logs:s});n.push(h);let u=await Promise.race(n);if(u||(u=await h),!u)throw new r.WorkboxError("no-response",{url:t.url});return u}l({request:e,logs:t,event:s}){let n;return{promise:new Promise(t=>{n=setTimeout(async()=>{t(await this.p({request:e,event:s}))},1e3*this.o)}),id:n}}async q({timeoutId:e,request:t,logs:r,event:i}){let h,u;try{u=await n.fetchWrapper.fetch({request:t,event:i,fetchOptions:this.i,plugins:this.s})}catch(e){h=e}if(e&&clearTimeout(e),h||!u)u=await this.p({request:t,event:i});else{const e=u.clone(),n=s.cacheWrapper.put({cacheName:this.t,request:t,response:e,event:i,plugins:this.s});if(i)try{i.waitUntil(n)}catch(e){}}return u}p({event:e,request:t}){return s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s})}}class c{constructor(e={}){this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],this.i=e.fetchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){let s,i;"string"==typeof t&&(t=new Request(t));try{i=await n.fetchWrapper.fetch({request:t,event:e,fetchOptions:this.i,plugins:this.s})}catch(e){s=e}if(!i)throw new r.WorkboxError("no-response",{url:t.url,error:s});return i}}class o{constructor(e={}){if(this.t=t.cacheNames.getRuntimeName(e.cacheName),this.s=e.plugins||[],e.plugins){let t=e.plugins.some(e=>!!e.cacheWillUpdate);this.s=t?e.plugins:[u,...e.plugins]}else this.s=[u];this.i=e.fetchOptions||null,this.h=e.matchOptions||null}async handle({event:e,request:t}){return this.makeRequest({event:e,request:t||e.request})}async makeRequest({event:e,request:t}){"string"==typeof t&&(t=new Request(t));const n=this.u({request:t,event:e});let i,h=await s.cacheWrapper.match({cacheName:this.t,request:t,event:e,matchOptions:this.h,plugins:this.s});if(h){if(e)try{e.waitUntil(n)}catch(i){}}else try{h=await n}catch(e){i=e}if(!h)throw new r.WorkboxError("no-response",{url:t.url,error:i});return h}async u({request:e,event:t}){const r=await n.fetchWrapper.fetch({request:e,event:t,fetchOptions:this.i,plugins:this.s}),i=s.cacheWrapper.put({cacheName:this.t,request:e,response:r.clone(),event:t,plugins:this.s});if(t)try{t.waitUntil(i)}catch(e){}return r}}const l={cacheFirst:i,cacheOnly:h,networkFirst:a,networkOnly:c,staleWhileRevalidate:o},q=e=>{const t=l[e];return e=>new t(e)},w=q("cacheFirst"),p=q("cacheOnly"),v=q("networkFirst"),y=q("networkOnly"),m=q("staleWhileRevalidate");return e.CacheFirst=i,e.CacheOnly=h,e.NetworkFirst=a,e.NetworkOnly=c,e.StaleWhileRevalidate=o,e.cacheFirst=w,e.cacheOnly=p,e.networkFirst=v,e.networkOnly=y,e.staleWhileRevalidate=m,e}({},workbox.core._private,workbox.core._private,workbox.core._private,workbox.core._private);
|
|
||||||
//# sourceMappingURL=workbox-strategies.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
this.workbox=this.workbox||{},this.workbox.streams=function(e){"use strict";try{self["workbox:streams:4.3.1"]&&_()}catch(e){}function n(e){const n=e.map(e=>Promise.resolve(e).then(e=>(function(e){return e.body&&e.body.getReader?e.body.getReader():e.getReader?e.getReader():new Response(e).body.getReader()})(e)));let t,r;const s=new Promise((e,n)=>{t=e,r=n});let o=0;return{done:s,stream:new ReadableStream({pull(e){return n[o].then(e=>e.read()).then(r=>{if(r.done)return++o>=n.length?(e.close(),void t()):this.pull(e);e.enqueue(r.value)}).catch(e=>{throw r(e),e})},cancel(){t()}})}}function t(e={}){const n=new Headers(e);return n.has("content-type")||n.set("content-type","text/html"),n}function r(e,r){const{done:s,stream:o}=n(e),a=t(r);return{done:s,response:new Response(o,{headers:a})}}let s=void 0;function o(){if(void 0===s)try{new ReadableStream({start(){}}),s=!0}catch(e){s=!1}return s}return e.concatenate=n,e.concatenateToResponse=r,e.isSupported=o,e.strategy=function(e,n){return async({event:s,url:a,params:c})=>{if(o()){const{done:t,response:o}=r(e.map(e=>e({event:s,url:a,params:c})),n);return s.waitUntil(t),o}const i=await Promise.all(e.map(e=>e({event:s,url:a,params:c})).map(async e=>{const n=await e;return n instanceof Response?n.blob():n})),u=t(n);return new Response(new Blob(i),{headers:u})}},e}({});
|
|
||||||
//# sourceMappingURL=workbox-streams.prod.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
!function(){"use strict";try{self["workbox:sw:4.3.1"]&&_()}catch(t){}const t="https://storage.googleapis.com/workbox-cdn/releases/4.3.1",e={backgroundSync:"background-sync",broadcastUpdate:"broadcast-update",cacheableResponse:"cacheable-response",core:"core",expiration:"expiration",googleAnalytics:"offline-ga",navigationPreload:"navigation-preload",precaching:"precaching",rangeRequests:"range-requests",routing:"routing",strategies:"strategies",streams:"streams"};self.workbox=new class{constructor(){return this.v={},this.t={debug:"localhost"===self.location.hostname,modulePathPrefix:null,modulePathCb:null},this.s=this.t.debug?"dev":"prod",this.o=!1,new Proxy(this,{get(t,s){if(t[s])return t[s];const o=e[s];return o&&t.loadModule(`workbox-${o}`),t[s]}})}setConfig(t={}){if(this.o)throw new Error("Config must be set before accessing workbox.* modules");Object.assign(this.t,t),this.s=this.t.debug?"dev":"prod"}loadModule(t){const e=this.i(t);try{importScripts(e),this.o=!0}catch(s){throw console.error(`Unable to import module '${t}' from '${e}'.`),s}}i(e){if(this.t.modulePathCb)return this.t.modulePathCb(e,this.t.debug);let s=[t];const o=`${e}.${this.s}.js`,r=this.t.modulePathPrefix;return r&&""===(s=r.split("/"))[s.length-1]&&s.splice(s.length-1,1),s.push(o),s.join("/")}}}();
|
|
||||||
//# sourceMappingURL=workbox-sw.js.map
|
|
@ -1,2 +0,0 @@
|
|||||||
try{self["workbox:window:4.3.1"]&&_()}catch(n){}var n=function(n,t){return new Promise(function(i){var e=new MessageChannel;e.port1.onmessage=function(n){return i(n.data)},n.postMessage(t,[e.port2])})};function t(n,t){for(var i=0;i<t.length;i++){var e=t[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(n,e.key,e)}}function i(n){if(void 0===n)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return n}try{self["workbox:core:4.3.1"]&&_()}catch(n){}var e=function(){var n=this;this.promise=new Promise(function(t,i){n.resolve=t,n.reject=i})},r=function(n,t){return new URL(n,location).href===new URL(t,location).href},o=function(n,t){Object.assign(this,t,{type:n})};function u(n){return function(){for(var t=[],i=0;i<arguments.length;i++)t[i]=arguments[i];try{return Promise.resolve(n.apply(this,t))}catch(n){return Promise.reject(n)}}}function a(n,t,i){return i?t?t(n):n:(n&&n.then||(n=Promise.resolve(n)),t?n.then(t):n)}function s(){}var c=function(c){var f,h;function v(n,t){var r;return void 0===t&&(t={}),(r=c.call(this)||this).t=n,r.i=t,r.o=0,r.u=new e,r.s=new e,r.h=new e,r.v=r.v.bind(i(i(r))),r.l=r.l.bind(i(i(r))),r.g=r.g.bind(i(i(r))),r.m=r.m.bind(i(i(r))),r}h=c,(f=v).prototype=Object.create(h.prototype),f.prototype.constructor=f,f.__proto__=h;var l,w,g,d=v.prototype;return d.register=u(function(n){var t,i,e=this,u=(void 0===n?{}:n).immediate,c=void 0!==u&&u;return t=function(){return e.p=Boolean(navigator.serviceWorker.controller),e.P=e.R(),a(e.k(),function(n){e.B=n,e.P&&(e.O=e.P,e.s.resolve(e.P),e.h.resolve(e.P),e.j(e.P),e.P.addEventListener("statechange",e.l,{once:!0}));var t=e.B.waiting;return t&&r(t.scriptURL,e.t)&&(e.O=t,Promise.resolve().then(function(){e.dispatchEvent(new o("waiting",{sw:t,wasWaitingBeforeRegister:!0}))})),e.O&&e.u.resolve(e.O),e.B.addEventListener("updatefound",e.g),navigator.serviceWorker.addEventListener("controllerchange",e.m,{once:!0}),"BroadcastChannel"in self&&(e.C=new BroadcastChannel("workbox"),e.C.addEventListener("message",e.v)),navigator.serviceWorker.addEventListener("message",e.v),e.B})},(i=function(){if(!c&&"complete"!==document.readyState)return function(n,t){if(!t)return n&&n.then?n.then(s):Promise.resolve()}(new Promise(function(n){return addEventListener("load",n)}))}())&&i.then?i.then(t):t(i)}),d.getSW=u(function(){return this.O||this.u.promise}),d.messageSW=u(function(t){return a(this.getSW(),function(i){return n(i,t)})}),d.R=function(){var n=navigator.serviceWorker.controller;if(n&&r(n.scriptURL,this.t))return n},d.k=u(function(){var n=this;return function(n,t){try{var i=n()}catch(n){return t(n)}return i&&i.then?i.then(void 0,t):i}(function(){return a(navigator.serviceWorker.register(n.t,n.i),function(t){return n.L=performance.now(),t})},function(n){throw n})}),d.j=function(t){n(t,{type:"WINDOW_READY",meta:"workbox-window"})},d.g=function(){var n=this.B.installing;this.o>0||!r(n.scriptURL,this.t)||performance.now()>this.L+6e4?(this.W=n,this.B.removeEventListener("updatefound",this.g)):(this.O=n,this.u.resolve(n)),++this.o,n.addEventListener("statechange",this.l)},d.l=function(n){var t=this,i=n.target,e=i.state,r=i===this.W,u=r?"external":"",a={sw:i,originalEvent:n};!r&&this.p&&(a.isUpdate=!0),this.dispatchEvent(new o(u+e,a)),"installed"===e?this._=setTimeout(function(){"installed"===e&&t.B.waiting===i&&t.dispatchEvent(new o(u+"waiting",a))},200):"activating"===e&&(clearTimeout(this._),r||this.s.resolve(i))},d.m=function(n){var t=this.O;t===navigator.serviceWorker.controller&&(this.dispatchEvent(new o("controlling",{sw:t,originalEvent:n})),this.h.resolve(t))},d.v=function(n){var t=n.data;this.dispatchEvent(new o("message",{data:t,originalEvent:n}))},l=v,(w=[{key:"active",get:function(){return this.s.promise}},{key:"controlling",get:function(){return this.h.promise}}])&&t(l.prototype,w),g&&t(l,g),v}(function(){function n(){this.D={}}var t=n.prototype;return t.addEventListener=function(n,t){this.T(n).add(t)},t.removeEventListener=function(n,t){this.T(n).delete(t)},t.dispatchEvent=function(n){n.target=this,this.T(n.type).forEach(function(t){return t(n)})},t.T=function(n){return this.D[n]=this.D[n]||new Set},n}());export{c as Workbox,n as messageSW};
|
|
||||||
//# sourceMappingURL=workbox-window.prod.es5.mjs.map
|
|
@ -1,2 +0,0 @@
|
|||||||
try{self["workbox:window:4.3.1"]&&_()}catch(t){}const t=(t,s)=>new Promise(i=>{let e=new MessageChannel;e.port1.onmessage=(t=>i(t.data)),t.postMessage(s,[e.port2])});try{self["workbox:core:4.3.1"]&&_()}catch(t){}class s{constructor(){this.promise=new Promise((t,s)=>{this.resolve=t,this.reject=s})}}class i{constructor(){this.t={}}addEventListener(t,s){this.s(t).add(s)}removeEventListener(t,s){this.s(t).delete(s)}dispatchEvent(t){t.target=this,this.s(t.type).forEach(s=>s(t))}s(t){return this.t[t]=this.t[t]||new Set}}const e=(t,s)=>new URL(t,location).href===new URL(s,location).href;class n{constructor(t,s){Object.assign(this,s,{type:t})}}const h=200,a=6e4;class o extends i{constructor(t,i={}){super(),this.i=t,this.h=i,this.o=0,this.l=new s,this.g=new s,this.u=new s,this.m=this.m.bind(this),this.v=this.v.bind(this),this.p=this.p.bind(this),this._=this._.bind(this)}async register({immediate:t=!1}={}){t||"complete"===document.readyState||await new Promise(t=>addEventListener("load",t)),this.C=Boolean(navigator.serviceWorker.controller),this.W=this.L(),this.S=await this.B(),this.W&&(this.R=this.W,this.g.resolve(this.W),this.u.resolve(this.W),this.P(this.W),this.W.addEventListener("statechange",this.v,{once:!0}));const s=this.S.waiting;return s&&e(s.scriptURL,this.i)&&(this.R=s,Promise.resolve().then(()=>{this.dispatchEvent(new n("waiting",{sw:s,wasWaitingBeforeRegister:!0}))})),this.R&&this.l.resolve(this.R),this.S.addEventListener("updatefound",this.p),navigator.serviceWorker.addEventListener("controllerchange",this._,{once:!0}),"BroadcastChannel"in self&&(this.T=new BroadcastChannel("workbox"),this.T.addEventListener("message",this.m)),navigator.serviceWorker.addEventListener("message",this.m),this.S}get active(){return this.g.promise}get controlling(){return this.u.promise}async getSW(){return this.R||this.l.promise}async messageSW(s){const i=await this.getSW();return t(i,s)}L(){const t=navigator.serviceWorker.controller;if(t&&e(t.scriptURL,this.i))return t}async B(){try{const t=await navigator.serviceWorker.register(this.i,this.h);return this.U=performance.now(),t}catch(t){throw t}}P(s){t(s,{type:"WINDOW_READY",meta:"workbox-window"})}p(){const t=this.S.installing;this.o>0||!e(t.scriptURL,this.i)||performance.now()>this.U+a?(this.k=t,this.S.removeEventListener("updatefound",this.p)):(this.R=t,this.l.resolve(t)),++this.o,t.addEventListener("statechange",this.v)}v(t){const s=t.target,{state:i}=s,e=s===this.k,a=e?"external":"",o={sw:s,originalEvent:t};!e&&this.C&&(o.isUpdate=!0),this.dispatchEvent(new n(a+i,o)),"installed"===i?this.D=setTimeout(()=>{"installed"===i&&this.S.waiting===s&&this.dispatchEvent(new n(a+"waiting",o))},h):"activating"===i&&(clearTimeout(this.D),e||this.g.resolve(s))}_(t){const s=this.R;s===navigator.serviceWorker.controller&&(this.dispatchEvent(new n("controlling",{sw:s,originalEvent:t})),this.u.resolve(s))}m(t){const{data:s}=t;this.dispatchEvent(new n("message",{data:s,originalEvent:t}))}}export{o as Workbox,t as messageSW};
|
|
||||||
//# sourceMappingURL=workbox-window.prod.mjs.map
|
|
@ -1,2 +0,0 @@
|
|||||||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((n=n||self).workbox={})}(this,function(n){"use strict";try{self["workbox:window:4.3.1"]&&_()}catch(n){}var t=function(n,t){return new Promise(function(i){var e=new MessageChannel;e.port1.onmessage=function(n){return i(n.data)},n.postMessage(t,[e.port2])})};function i(n,t){for(var i=0;i<t.length;i++){var e=t[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(n,e.key,e)}}function e(n){if(void 0===n)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return n}try{self["workbox:core:4.3.1"]&&_()}catch(n){}var r=function(){var n=this;this.promise=new Promise(function(t,i){n.resolve=t,n.reject=i})},o=function(n,t){return new URL(n,location).href===new URL(t,location).href},u=function(n,t){Object.assign(this,t,{type:n})};function s(n){return function(){for(var t=[],i=0;i<arguments.length;i++)t[i]=arguments[i];try{return Promise.resolve(n.apply(this,t))}catch(n){return Promise.reject(n)}}}function a(n,t,i){return i?t?t(n):n:(n&&n.then||(n=Promise.resolve(n)),t?n.then(t):n)}function c(){}var f=function(n){var f,h;function v(t,i){var o;return void 0===i&&(i={}),(o=n.call(this)||this).t=t,o.i=i,o.o=0,o.u=new r,o.s=new r,o.h=new r,o.v=o.v.bind(e(e(o))),o.l=o.l.bind(e(e(o))),o.g=o.g.bind(e(e(o))),o.m=o.m.bind(e(e(o))),o}h=n,(f=v).prototype=Object.create(h.prototype),f.prototype.constructor=f,f.__proto__=h;var l,w,d,g=v.prototype;return g.register=s(function(n){var t,i,e=this,r=(void 0===n?{}:n).immediate,s=void 0!==r&&r;return t=function(){return e.p=Boolean(navigator.serviceWorker.controller),e.P=e.j(),a(e.O(),function(n){e.R=n,e.P&&(e._=e.P,e.s.resolve(e.P),e.h.resolve(e.P),e.k(e.P),e.P.addEventListener("statechange",e.l,{once:!0}));var t=e.R.waiting;return t&&o(t.scriptURL,e.t)&&(e._=t,Promise.resolve().then(function(){e.dispatchEvent(new u("waiting",{sw:t,wasWaitingBeforeRegister:!0}))})),e._&&e.u.resolve(e._),e.R.addEventListener("updatefound",e.g),navigator.serviceWorker.addEventListener("controllerchange",e.m,{once:!0}),"BroadcastChannel"in self&&(e.B=new BroadcastChannel("workbox"),e.B.addEventListener("message",e.v)),navigator.serviceWorker.addEventListener("message",e.v),e.R})},(i=function(){if(!s&&"complete"!==document.readyState)return function(n,t){if(!t)return n&&n.then?n.then(c):Promise.resolve()}(new Promise(function(n){return addEventListener("load",n)}))}())&&i.then?i.then(t):t(i)}),g.getSW=s(function(){return this._||this.u.promise}),g.messageSW=s(function(n){return a(this.getSW(),function(i){return t(i,n)})}),g.j=function(){var n=navigator.serviceWorker.controller;if(n&&o(n.scriptURL,this.t))return n},g.O=s(function(){var n=this;return function(n,t){try{var i=n()}catch(n){return t(n)}return i&&i.then?i.then(void 0,t):i}(function(){return a(navigator.serviceWorker.register(n.t,n.i),function(t){return n.C=performance.now(),t})},function(n){throw n})}),g.k=function(n){t(n,{type:"WINDOW_READY",meta:"workbox-window"})},g.g=function(){var n=this.R.installing;this.o>0||!o(n.scriptURL,this.t)||performance.now()>this.C+6e4?(this.L=n,this.R.removeEventListener("updatefound",this.g)):(this._=n,this.u.resolve(n)),++this.o,n.addEventListener("statechange",this.l)},g.l=function(n){var t=this,i=n.target,e=i.state,r=i===this.L,o=r?"external":"",s={sw:i,originalEvent:n};!r&&this.p&&(s.isUpdate=!0),this.dispatchEvent(new u(o+e,s)),"installed"===e?this.W=setTimeout(function(){"installed"===e&&t.R.waiting===i&&t.dispatchEvent(new u(o+"waiting",s))},200):"activating"===e&&(clearTimeout(this.W),r||this.s.resolve(i))},g.m=function(n){var t=this._;t===navigator.serviceWorker.controller&&(this.dispatchEvent(new u("controlling",{sw:t,originalEvent:n})),this.h.resolve(t))},g.v=function(n){var t=n.data;this.dispatchEvent(new u("message",{data:t,originalEvent:n}))},l=v,(w=[{key:"active",get:function(){return this.s.promise}},{key:"controlling",get:function(){return this.h.promise}}])&&i(l.prototype,w),d&&i(l,d),v}(function(){function n(){this.D={}}var t=n.prototype;return t.addEventListener=function(n,t){this.M(n).add(t)},t.removeEventListener=function(n,t){this.M(n).delete(t)},t.dispatchEvent=function(n){n.target=this,this.M(n.type).forEach(function(t){return t(n)})},t.M=function(n){return this.D[n]=this.D[n]||new Set},n}());n.Workbox=f,n.messageSW=t,Object.defineProperty(n,"__esModule",{value:!0})});
|
|
||||||
//# sourceMappingURL=workbox-window.prod.umd.js.map
|
|
@ -11,7 +11,7 @@ export const trackEvent = (
|
|||||||
// Uncomment the next line to track locally
|
// Uncomment the next line to track locally
|
||||||
// console.log("Track Event", { category, action, label, value });
|
// console.log("Track Event", { category, action, label, value });
|
||||||
|
|
||||||
if (typeof window === "undefined" || process.env.JEST_WORKER_ID) {
|
if (typeof window === "undefined" || import.meta.env.VITE_WORKER_ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
DEFAULT_FONT_FAMILY,
|
DEFAULT_FONT_FAMILY,
|
||||||
DEFAULT_FONT_SIZE,
|
DEFAULT_FONT_SIZE,
|
||||||
ENV,
|
|
||||||
VERTICAL_ALIGN,
|
VERTICAL_ALIGN,
|
||||||
} from "./constants";
|
} from "./constants";
|
||||||
import { newElement, newLinearElement, newTextElement } from "./element";
|
import { newElement, newLinearElement, newTextElement } from "./element";
|
||||||
@ -384,7 +383,7 @@ const chartTypeBar = (
|
|||||||
y,
|
y,
|
||||||
groupId,
|
groupId,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT,
|
import.meta.env.DEV,
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
@ -473,7 +472,7 @@ const chartTypeLine = (
|
|||||||
y,
|
y,
|
||||||
groupId,
|
groupId,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT,
|
import.meta.env.DEV,
|
||||||
),
|
),
|
||||||
line,
|
line,
|
||||||
...lines,
|
...lines,
|
||||||
|
@ -4,8 +4,9 @@ import { reseed } from "../random";
|
|||||||
import { render, queryByTestId } from "../tests/test-utils";
|
import { render, queryByTestId } from "../tests/test-utils";
|
||||||
|
|
||||||
import ExcalidrawApp from "../excalidraw-app";
|
import ExcalidrawApp from "../excalidraw-app";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
|
|
||||||
describe("Test <App/>", () => {
|
describe("Test <App/>", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -255,6 +255,7 @@ import {
|
|||||||
isTransparent,
|
isTransparent,
|
||||||
easeToValuesRAF,
|
easeToValuesRAF,
|
||||||
muteFSAbortError,
|
muteFSAbortError,
|
||||||
|
isTestEnv,
|
||||||
easeOut,
|
easeOut,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
import {
|
import {
|
||||||
@ -1595,10 +1596,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
this.excalidrawContainerValue.container =
|
this.excalidrawContainerValue.container =
|
||||||
this.excalidrawContainerRef.current;
|
this.excalidrawContainerRef.current;
|
||||||
|
|
||||||
if (
|
if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
|
||||||
process.env.NODE_ENV === ENV.TEST ||
|
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT
|
|
||||||
) {
|
|
||||||
const setState = this.setState.bind(this);
|
const setState = this.setState.bind(this);
|
||||||
Object.defineProperties(window.h, {
|
Object.defineProperties(window.h, {
|
||||||
state: {
|
state: {
|
||||||
@ -1636,7 +1634,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
// bounding rects don't work in tests so updating
|
// bounding rects don't work in tests so updating
|
||||||
// the state on init would result in making the test enviro run
|
// the state on init would result in making the test enviro run
|
||||||
// in mobile breakpoint (0 width/height), making everything fail
|
// in mobile breakpoint (0 width/height), making everything fail
|
||||||
process.env.NODE_ENV !== "test"
|
!isTestEnv()
|
||||||
) {
|
) {
|
||||||
this.refreshDeviceState(this.excalidrawContainerRef.current);
|
this.refreshDeviceState(this.excalidrawContainerRef.current);
|
||||||
}
|
}
|
||||||
@ -8173,10 +8171,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
|
||||||
process.env.NODE_ENV === ENV.TEST ||
|
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT
|
|
||||||
) {
|
|
||||||
window.h = window.h || ({} as Window["h"]);
|
window.h = window.h || ({} as Window["h"]);
|
||||||
|
|
||||||
Object.defineProperties(window.h, {
|
Object.defineProperties(window.h, {
|
||||||
|
@ -16,7 +16,7 @@ const LibraryMenuBrowseButton = ({
|
|||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className="library-menu-browse-button"
|
className="library-menu-browse-button"
|
||||||
href={`${process.env.REACT_APP_LIBRARY_URL}?target=${
|
href={`${import.meta.env.VITE_APP_LIBRARY_URL}?target=${
|
||||||
window.name || "_blank"
|
window.name || "_blank"
|
||||||
}&referrer=${referrer}&useHash=true&token=${id}&theme=${theme}&version=${
|
}&referrer=${referrer}&useHash=true&token=${id}&theme=${theme}&version=${
|
||||||
VERSIONS.excalidrawLibrary
|
VERSIONS.excalidrawLibrary
|
||||||
|
@ -319,7 +319,7 @@ const PublishLibrary = ({
|
|||||||
formData.append("twitterHandle", libraryData.twitterHandle);
|
formData.append("twitterHandle", libraryData.twitterHandle);
|
||||||
formData.append("website", libraryData.website);
|
formData.append("website", libraryData.website);
|
||||||
|
|
||||||
fetch(`${process.env.REACT_APP_LIBRARY_BACKEND}/submit`, {
|
fetch(`${import.meta.env.VITE_APP_LIBRARY_BACKEND}/submit`, {
|
||||||
method: "post",
|
method: "post",
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
waitFor,
|
waitFor,
|
||||||
withExcalidrawDimensions,
|
withExcalidrawDimensions,
|
||||||
} from "../../tests/test-utils";
|
} from "../../tests/test-utils";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
export const assertSidebarDockButton = async <T extends boolean>(
|
export const assertSidebarDockButton = async <T extends boolean>(
|
||||||
hasDockButton: T,
|
hasDockButton: T,
|
||||||
@ -205,7 +206,7 @@ describe("Sidebar", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("<Sidebar.Header> should render close button", async () => {
|
it("<Sidebar.Header> should render close button", async () => {
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = vi.fn();
|
||||||
const CustomExcalidraw = () => {
|
const CustomExcalidraw = () => {
|
||||||
return (
|
return (
|
||||||
<Excalidraw
|
<Excalidraw
|
||||||
|
@ -53,7 +53,7 @@ export const SidebarInner = forwardRef(
|
|||||||
}: SidebarProps & Omit<React.RefAttributes<HTMLDivElement>, "onSelect">,
|
}: SidebarProps & Omit<React.RefAttributes<HTMLDivElement>, "onSelect">,
|
||||||
ref: React.ForwardedRef<HTMLDivElement>,
|
ref: React.ForwardedRef<HTMLDivElement>,
|
||||||
) => {
|
) => {
|
||||||
if (process.env.NODE_ENV === "development" && onDock && docked == null) {
|
if (import.meta.env.DEV && onDock && docked == null) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"Sidebar: `docked` must be set when `onDock` is supplied for the sidebar to be user-dockable. To hide this message, either pass `docked` or remove `onDock`",
|
"Sidebar: `docked` must be set when `onDock` is supplied for the sidebar to be user-dockable. To hide this message, either pass `docked` or remove `onDock`",
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`Test <App/> should show error modal when using brave and measureText API is not working 1`] = `
|
exports[`Test <App/> > should show error modal when using brave and measureText API is not working 1`] = `
|
||||||
<div
|
<div
|
||||||
data-testid="brave-measure-text-error"
|
data-testid="brave-measure-text-error"
|
||||||
>
|
>
|
||||||
|
@ -443,7 +443,7 @@ const _deepCopyElement = (val: any, depth: number = 0) => {
|
|||||||
// we're not cloning non-array & non-plain-object objects because we
|
// we're not cloning non-array & non-plain-object objects because we
|
||||||
// don't support them on excalidraw elements yet. If we do, we need to make
|
// don't support them on excalidraw elements yet. If we do, we need to make
|
||||||
// sure we start cloning them, so let's warn about it.
|
// sure we start cloning them, so let's warn about it.
|
||||||
if (process.env.NODE_ENV === "development") {
|
if (import.meta.env.DEV) {
|
||||||
if (
|
if (
|
||||||
objectType !== "[object Object]" &&
|
objectType !== "[object Object]" &&
|
||||||
objectType !== "[object Array]" &&
|
objectType !== "[object Array]" &&
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
|
import { vi } from "vitest";
|
||||||
import { getPerfectElementSize } from "./sizeHelpers";
|
import { getPerfectElementSize } from "./sizeHelpers";
|
||||||
import * as constants from "../constants";
|
import * as constants from "../constants";
|
||||||
|
|
||||||
const EPSILON_DIGITS = 3;
|
const EPSILON_DIGITS = 3;
|
||||||
|
// Needed so that we can mock the value of constants which is done in
|
||||||
|
// below tests. In Jest this wasn't needed as global override was possible
|
||||||
|
// but vite doesn't allow that hence we need to mock
|
||||||
|
vi.mock(
|
||||||
|
"../constants.ts",
|
||||||
|
//@ts-ignore
|
||||||
|
async (importOriginal) => {
|
||||||
|
const module: any = await importOriginal();
|
||||||
|
return { ...module };
|
||||||
|
},
|
||||||
|
);
|
||||||
describe("getPerfectElementSize", () => {
|
describe("getPerfectElementSize", () => {
|
||||||
it("should return height:0 if `elementType` is line and locked angle is 0", () => {
|
it("should return height:0 if `elementType` is line and locked angle is 0", () => {
|
||||||
const { height, width } = getPerfectElementSize("line", 149, 10);
|
const { height, width } = getPerfectElementSize("line", 149, 10);
|
||||||
expect(width).toBeCloseTo(149, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(149, EPSILON_DIGITS);
|
||||||
expect(height).toBeCloseTo(0, EPSILON_DIGITS);
|
expect(height).toBeCloseTo(0, EPSILON_DIGITS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return width:0 if `elementType` is line and locked angle is 90 deg (Math.PI/2)", () => {
|
it("should return width:0 if `elementType` is line and locked angle is 90 deg (Math.PI/2)", () => {
|
||||||
const { height, width } = getPerfectElementSize("line", 10, 140);
|
const { height, width } = getPerfectElementSize("line", 10, 140);
|
||||||
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
||||||
expect(height).toBeCloseTo(140, EPSILON_DIGITS);
|
expect(height).toBeCloseTo(140, EPSILON_DIGITS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return height:0 if `elementType` is arrow and locked angle is 0", () => {
|
it("should return height:0 if `elementType` is arrow and locked angle is 0", () => {
|
||||||
const { height, width } = getPerfectElementSize("arrow", 200, 20);
|
const { height, width } = getPerfectElementSize("arrow", 200, 20);
|
||||||
expect(width).toBeCloseTo(200, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(200, EPSILON_DIGITS);
|
||||||
@ -24,16 +37,19 @@ describe("getPerfectElementSize", () => {
|
|||||||
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
||||||
expect(height).toBeCloseTo(100, EPSILON_DIGITS);
|
expect(height).toBeCloseTo(100, EPSILON_DIGITS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return adjust height to be width * tan(locked angle)", () => {
|
it("should return adjust height to be width * tan(locked angle)", () => {
|
||||||
const { height, width } = getPerfectElementSize("arrow", 120, 185);
|
const { height, width } = getPerfectElementSize("arrow", 120, 185);
|
||||||
expect(width).toBeCloseTo(120, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(120, EPSILON_DIGITS);
|
||||||
expect(height).toBeCloseTo(207.846, EPSILON_DIGITS);
|
expect(height).toBeCloseTo(207.846, EPSILON_DIGITS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return height equals to width if locked angle is 45 deg", () => {
|
it("should return height equals to width if locked angle is 45 deg", () => {
|
||||||
const { height, width } = getPerfectElementSize("arrow", 135, 145);
|
const { height, width } = getPerfectElementSize("arrow", 135, 145);
|
||||||
expect(width).toBeCloseTo(135, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(135, EPSILON_DIGITS);
|
||||||
expect(height).toBeCloseTo(135, EPSILON_DIGITS);
|
expect(height).toBeCloseTo(135, EPSILON_DIGITS);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return height:0 and width:0 when width and height are 0", () => {
|
it("should return height:0 and width:0 when width and height are 0", () => {
|
||||||
const { height, width } = getPerfectElementSize("arrow", 0, 0);
|
const { height, width } = getPerfectElementSize("arrow", 0, 0);
|
||||||
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
expect(width).toBeCloseTo(0, EPSILON_DIGITS);
|
||||||
|
@ -955,7 +955,7 @@ describe("textWysiwyg", () => {
|
|||||||
// should center align horizontally and vertically by default
|
// should center align horizontally and vertically by default
|
||||||
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
85,
|
85,
|
||||||
4.5,
|
4.5,
|
||||||
]
|
]
|
||||||
@ -979,7 +979,7 @@ describe("textWysiwyg", () => {
|
|||||||
// should left align horizontally and bottom vertically after resize
|
// should left align horizontally and bottom vertically after resize
|
||||||
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
15,
|
15,
|
||||||
65,
|
65,
|
||||||
]
|
]
|
||||||
@ -1001,7 +1001,7 @@ describe("textWysiwyg", () => {
|
|||||||
// should right align horizontally and top vertically after resize
|
// should right align horizontally and top vertically after resize
|
||||||
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
resize(rectangle, "ne", [rectangle.x + 100, rectangle.y - 100]);
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
375,
|
375,
|
||||||
-539,
|
-539,
|
||||||
]
|
]
|
||||||
@ -1279,7 +1279,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Left"));
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
fireEvent.click(screen.getByTitle("Align top"));
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
15,
|
15,
|
||||||
25,
|
25,
|
||||||
]
|
]
|
||||||
@ -1290,7 +1290,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Center"));
|
fireEvent.click(screen.getByTitle("Center"));
|
||||||
fireEvent.click(screen.getByTitle("Align top"));
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
25,
|
25,
|
||||||
]
|
]
|
||||||
@ -1302,7 +1302,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Align top"));
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
|
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
45,
|
45,
|
||||||
25,
|
25,
|
||||||
]
|
]
|
||||||
@ -1313,7 +1313,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Center vertically"));
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
fireEvent.click(screen.getByTitle("Left"));
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
15,
|
15,
|
||||||
45,
|
45,
|
||||||
]
|
]
|
||||||
@ -1325,7 +1325,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Center vertically"));
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
|
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
45,
|
45,
|
||||||
]
|
]
|
||||||
@ -1337,7 +1337,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Center vertically"));
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
|
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
45,
|
45,
|
||||||
45,
|
45,
|
||||||
]
|
]
|
||||||
@ -1349,7 +1349,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Align bottom"));
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
|
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
15,
|
15,
|
||||||
65,
|
65,
|
||||||
]
|
]
|
||||||
@ -1360,7 +1360,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Center"));
|
fireEvent.click(screen.getByTitle("Center"));
|
||||||
fireEvent.click(screen.getByTitle("Align bottom"));
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
65,
|
65,
|
||||||
]
|
]
|
||||||
@ -1371,7 +1371,7 @@ describe("textWysiwyg", () => {
|
|||||||
fireEvent.click(screen.getByTitle("Right"));
|
fireEvent.click(screen.getByTitle("Right"));
|
||||||
fireEvent.click(screen.getByTitle("Align bottom"));
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
45,
|
45,
|
||||||
65,
|
65,
|
||||||
]
|
]
|
||||||
|
@ -171,10 +171,7 @@ class Collab extends PureComponent<Props, CollabState> {
|
|||||||
|
|
||||||
appJotaiStore.set(collabAPIAtom, collabAPI);
|
appJotaiStore.set(collabAPIAtom, collabAPI);
|
||||||
|
|
||||||
if (
|
if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
|
||||||
process.env.NODE_ENV === ENV.TEST ||
|
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT
|
|
||||||
) {
|
|
||||||
window.collab = window.collab || ({} as Window["collab"]);
|
window.collab = window.collab || ({} as Window["collab"]);
|
||||||
Object.defineProperties(window, {
|
Object.defineProperties(window, {
|
||||||
collab: {
|
collab: {
|
||||||
@ -860,10 +857,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) {
|
||||||
process.env.NODE_ENV === ENV.TEST ||
|
|
||||||
process.env.NODE_ENV === ENV.DEVELOPMENT
|
|
||||||
) {
|
|
||||||
window.collab = window.collab || ({} as Window["collab"]);
|
window.collab = window.collab || ({} as Window["collab"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ export const AppWelcomeScreen: React.FC<{
|
|||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
style={{ pointerEvents: "all" }}
|
style={{ pointerEvents: "all" }}
|
||||||
href={`${process.env.REACT_APP_PLUS_APP}?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenSignedInUser`}
|
href={`${
|
||||||
|
import.meta.env.VITE_APP_PLUS_APP
|
||||||
|
}?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenSignedInUser`}
|
||||||
key={idx}
|
key={idx}
|
||||||
>
|
>
|
||||||
Excalidraw+
|
Excalidraw+
|
||||||
|
@ -6,7 +6,9 @@ export const ExcalidrawPlusAppLink = () => {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
href={`${process.env.REACT_APP_PLUS_APP}?utm_source=excalidraw&utm_medium=app&utm_content=signedInUserRedirectButton#excalidraw-redirect`}
|
href={`${
|
||||||
|
import.meta.env.VITE_APP_PLUS_APP
|
||||||
|
}?utm_source=excalidraw&utm_medium=app&utm_content=signedInUserRedirectButton#excalidraw-redirect`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="plus-button"
|
className="plus-button"
|
||||||
|
@ -21,10 +21,12 @@ import { ResolutionType } from "../../utility-types";
|
|||||||
|
|
||||||
let FIREBASE_CONFIG: Record<string, any>;
|
let FIREBASE_CONFIG: Record<string, any>;
|
||||||
try {
|
try {
|
||||||
FIREBASE_CONFIG = JSON.parse(process.env.REACT_APP_FIREBASE_CONFIG);
|
FIREBASE_CONFIG = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG);
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Error JSON parsing firebase config. Supplied value: ${process.env.REACT_APP_FIREBASE_CONFIG}`,
|
`Error JSON parsing firebase config. Supplied value: ${
|
||||||
|
import.meta.env.VITE_APP_FIREBASE_CONFIG
|
||||||
|
}`,
|
||||||
);
|
);
|
||||||
FIREBASE_CONFIG = {};
|
FIREBASE_CONFIG = {};
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,8 @@ export const getSyncableElements = (elements: readonly ExcalidrawElement[]) =>
|
|||||||
isSyncableElement(element),
|
isSyncableElement(element),
|
||||||
) as SyncableExcalidrawElement[];
|
) as SyncableExcalidrawElement[];
|
||||||
|
|
||||||
const BACKEND_V2_GET = process.env.REACT_APP_BACKEND_V2_GET_URL;
|
const BACKEND_V2_GET = import.meta.env.VITE_APP_BACKEND_V2_GET_URL;
|
||||||
const BACKEND_V2_POST = process.env.REACT_APP_BACKEND_V2_POST_URL;
|
const BACKEND_V2_POST = import.meta.env.VITE_APP_BACKEND_V2_POST_URL;
|
||||||
|
|
||||||
const generateRoomId = async () => {
|
const generateRoomId = async () => {
|
||||||
const buffer = new Uint8Array(ROOM_ID_BYTES);
|
const buffer = new Uint8Array(ROOM_ID_BYTES);
|
||||||
@ -67,16 +67,16 @@ export const getCollabServer = async (): Promise<{
|
|||||||
url: string;
|
url: string;
|
||||||
polling: boolean;
|
polling: boolean;
|
||||||
}> => {
|
}> => {
|
||||||
if (process.env.REACT_APP_WS_SERVER_URL) {
|
if (import.meta.env.VITE_APP_WS_SERVER_URL) {
|
||||||
return {
|
return {
|
||||||
url: process.env.REACT_APP_WS_SERVER_URL,
|
url: import.meta.env.VITE_APP_WS_SERVER_URL,
|
||||||
polling: true,
|
polling: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(
|
const resp = await fetch(
|
||||||
`${process.env.REACT_APP_PORTAL_URL}/collab-server`,
|
`${import.meta.env.VITE_APP_PORTAL_URL}/collab-server`,
|
||||||
);
|
);
|
||||||
return await resp.json();
|
return await resp.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import { register as registerServiceWorker } from "../serviceWorkerRegistration";
|
|
||||||
import { EVENT } from "../constants";
|
|
||||||
|
|
||||||
// On Apple mobile devices add the proprietary app icon and splashscreen markup.
|
|
||||||
// No one should have to do this manually, and eventually this annoyance will
|
|
||||||
// go away once https://bugs.webkit.org/show_bug.cgi?id=183937 is fixed.
|
|
||||||
if (
|
|
||||||
/\b(iPad|iPhone|iPod|Safari)\b/.test(navigator.userAgent) &&
|
|
||||||
!matchMedia("(display-mode: standalone)").matches
|
|
||||||
) {
|
|
||||||
import(/* webpackChunkName: "pwacompat" */ "pwacompat");
|
|
||||||
}
|
|
||||||
|
|
||||||
registerServiceWorker({
|
|
||||||
onUpdate: (registration) => {
|
|
||||||
const waitingServiceWorker = registration.waiting;
|
|
||||||
if (waitingServiceWorker) {
|
|
||||||
waitingServiceWorker.addEventListener(
|
|
||||||
EVENT.STATE_CHANGE,
|
|
||||||
(event: Event) => {
|
|
||||||
const target = event.target as ServiceWorker;
|
|
||||||
const state = target.state as ServiceWorkerState;
|
|
||||||
if (state === "activated") {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
@ -7,7 +7,7 @@ const SentryEnvHostnameMap: { [key: string]: string } = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const REACT_APP_DISABLE_SENTRY =
|
const REACT_APP_DISABLE_SENTRY =
|
||||||
process.env.REACT_APP_DISABLE_SENTRY === "true";
|
import.meta.env.VITE_APP_DISABLE_SENTRY === "true";
|
||||||
|
|
||||||
// Disable Sentry locally or inside the Docker to avoid noise/respect privacy
|
// Disable Sentry locally or inside the Docker to avoid noise/respect privacy
|
||||||
const onlineEnv =
|
const onlineEnv =
|
||||||
@ -21,7 +21,7 @@ Sentry.init({
|
|||||||
? "https://7bfc596a5bf945eda6b660d3015a5460@sentry.io/5179260"
|
? "https://7bfc596a5bf945eda6b660d3015a5460@sentry.io/5179260"
|
||||||
: undefined,
|
: undefined,
|
||||||
environment: onlineEnv ? SentryEnvHostnameMap[onlineEnv] : undefined,
|
environment: onlineEnv ? SentryEnvHostnameMap[onlineEnv] : undefined,
|
||||||
release: process.env.REACT_APP_GIT_SHA,
|
release: import.meta.env.VITE_APP_GIT_SHA,
|
||||||
ignoreErrors: [
|
ignoreErrors: [
|
||||||
"undefined is not an object (evaluating 'window.__pad.performLoop')", // Only happens on Safari, but spams our servers. Doesn't break anything
|
"undefined is not an object (evaluating 'window.__pad.performLoop')", // Only happens on Safari, but spams our servers. Doesn't break anything
|
||||||
],
|
],
|
||||||
|
10
src/global.d.ts
vendored
10
src/global.d.ts
vendored
@ -38,16 +38,6 @@ interface CanvasRenderingContext2D {
|
|||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/facebook/create-react-app/blob/ddcb7d5/packages/react-scripts/lib/react-app.d.ts
|
|
||||||
declare namespace NodeJS {
|
|
||||||
interface ProcessEnv {
|
|
||||||
readonly REACT_APP_BACKEND_V2_GET_URL: string;
|
|
||||||
readonly REACT_APP_BACKEND_V2_POST_URL: string;
|
|
||||||
readonly REACT_APP_PORTAL_URL: string;
|
|
||||||
readonly REACT_APP_FIREBASE_CONFIG: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Clipboard extends EventTarget {
|
interface Clipboard extends EventTarget {
|
||||||
write(data: any[]): Promise<void>;
|
write(data: any[]): Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import fallbackLangData from "./locales/en.json";
|
import fallbackLangData from "./locales/en.json";
|
||||||
import percentages from "./locales/percentages.json";
|
import percentages from "./locales/percentages.json";
|
||||||
import { ENV } from "./constants";
|
|
||||||
import { jotaiScope, jotaiStore } from "./jotai";
|
import { jotaiScope, jotaiStore } from "./jotai";
|
||||||
import { atom, useAtomValue } from "jotai";
|
import { atom, useAtomValue } from "jotai";
|
||||||
import { NestedKeyOf } from "./utility-types";
|
import { NestedKeyOf } from "./utility-types";
|
||||||
@ -74,7 +73,7 @@ export const languages: Language[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const TEST_LANG_CODE = "__test__";
|
const TEST_LANG_CODE = "__test__";
|
||||||
if (process.env.NODE_ENV === ENV.DEVELOPMENT) {
|
if (import.meta.env.DEV) {
|
||||||
languages.unshift(
|
languages.unshift(
|
||||||
{ code: TEST_LANG_CODE, label: "test language" },
|
{ code: TEST_LANG_CODE, label: "test language" },
|
||||||
{
|
{
|
||||||
@ -145,7 +144,7 @@ export const t = (
|
|||||||
if (translation === undefined) {
|
if (translation === undefined) {
|
||||||
const errorMessage = `Can't find translation for ${path}`;
|
const errorMessage = `Can't find translation for ${path}`;
|
||||||
// in production, don't blow up the app on a missing translation key
|
// in production, don't blow up the app on a missing translation key
|
||||||
if (process.env.NODE_ENV === "production") {
|
if (import.meta.env.PROD) {
|
||||||
console.warn(errorMessage);
|
console.warn(errorMessage);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@ import { StrictMode } from "react";
|
|||||||
import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
import ExcalidrawApp from "./excalidraw-app";
|
import ExcalidrawApp from "./excalidraw-app";
|
||||||
|
|
||||||
import "./excalidraw-app/pwa";
|
|
||||||
import "./excalidraw-app/sentry";
|
import "./excalidraw-app/sentry";
|
||||||
window.__EXCALIDRAW_SHA__ = process.env.REACT_APP_GIT_SHA;
|
window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA;
|
||||||
const rootElement = document.getElementById("root")!;
|
const rootElement = document.getElementById("root")!;
|
||||||
const root = createRoot(rootElement);
|
const root = createRoot(rootElement);
|
||||||
root.render(
|
root.render(
|
||||||
|
@ -9,9 +9,9 @@ const parseEnvVariables = (filepath) => {
|
|||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
envVars.PKG_NAME = JSON.stringify(pkg.name);
|
envVars.VITE_PKG_NAME = JSON.stringify(pkg.name);
|
||||||
envVars.PKG_VERSION = JSON.stringify(pkg.version);
|
envVars.VITE_PKG_VERSION = JSON.stringify(pkg.version);
|
||||||
envVars.IS_EXCALIDRAW_NPM_PACKAGE = JSON.stringify(true);
|
envVars.VITE_IS_EXCALIDRAW_NPM_PACKAGE = JSON.stringify(true);
|
||||||
return envVars;
|
return envVars;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"css-loader": "6.7.1",
|
"css-loader": "6.7.1",
|
||||||
"dotenv": "16.0.1",
|
"dotenv": "16.0.1",
|
||||||
|
"import-meta-loader": "1.1.0",
|
||||||
"mini-css-extract-plugin": "2.6.1",
|
"mini-css-extract-plugin": "2.6.1",
|
||||||
"postcss-loader": "7.0.1",
|
"postcss-loader": "7.0.1",
|
||||||
"sass-loader": "13.0.2",
|
"sass-loader": "13.0.2",
|
||||||
|
@ -4,5 +4,5 @@ if (process.env.NODE_ENV !== ENV.TEST) {
|
|||||||
/* global __webpack_public_path__:writable */
|
/* global __webpack_public_path__:writable */
|
||||||
__webpack_public_path__ =
|
__webpack_public_path__ =
|
||||||
window.EXCALIDRAW_ASSET_PATH ||
|
window.EXCALIDRAW_ASSET_PATH ||
|
||||||
`https://unpkg.com/${process.env.PKG_NAME}@${process.env.PKG_VERSION}/dist/`;
|
`https://unpkg.com/${process.env.VITE_PKG_NAME}@${process.env.VITE_PKG_VERSION}/dist/`;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ module.exports = {
|
|||||||
exclude:
|
exclude:
|
||||||
/node_modules\/(?!(browser-fs-access|canvas-roundrect-polyfill))/,
|
/node_modules\/(?!(browser-fs-access|canvas-roundrect-polyfill))/,
|
||||||
use: [
|
use: [
|
||||||
|
{
|
||||||
|
loader: "import-meta-loader",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
loader: "ts-loader",
|
loader: "ts-loader",
|
||||||
options: {
|
options: {
|
||||||
|
@ -50,6 +50,9 @@ module.exports = {
|
|||||||
/node_modules\/(?!(browser-fs-access|canvas-roundrect-polyfill))/,
|
/node_modules\/(?!(browser-fs-access|canvas-roundrect-polyfill))/,
|
||||||
|
|
||||||
use: [
|
use: [
|
||||||
|
{
|
||||||
|
loader: "import-meta-loader",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
loader: "ts-loader",
|
loader: "ts-loader",
|
||||||
options: {
|
options: {
|
||||||
|
@ -2916,6 +2916,11 @@ import-local@^3.0.2:
|
|||||||
pkg-dir "^4.2.0"
|
pkg-dir "^4.2.0"
|
||||||
resolve-cwd "^3.0.0"
|
resolve-cwd "^3.0.0"
|
||||||
|
|
||||||
|
import-meta-loader@1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/import-meta-loader/-/import-meta-loader-1.1.0.tgz#927060305f2d0f88b495f2754aa33387ca6579d7"
|
||||||
|
integrity sha512-f96r2o8xT+b2KVlOY4x+1KTJmJiapZlf77j1WebR8NQgMG1dpdqijjGl4i/2jMoXch2CVqcQoTMfh5BR7bR8wA==
|
||||||
|
|
||||||
indexes-of@^1.0.1:
|
indexes-of@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
|
||||||
|
@ -915,7 +915,7 @@ const drawElementFromCanvas = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
process.env.REACT_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX ===
|
import.meta.env.VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX ===
|
||||||
"true" &&
|
"true" &&
|
||||||
hasBoundTextElement(element)
|
hasBoundTextElement(element)
|
||||||
) {
|
) {
|
||||||
|
@ -133,12 +133,13 @@ export const exportToSvg = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
let assetPath = "https://excalidraw.com/";
|
let assetPath = "https://excalidraw.com/";
|
||||||
|
|
||||||
// Asset path needs to be determined only when using package
|
// Asset path needs to be determined only when using package
|
||||||
if (process.env.IS_EXCALIDRAW_NPM_PACKAGE) {
|
if (import.meta.env.VITE_IS_EXCALIDRAW_NPM_PACKAGE) {
|
||||||
assetPath =
|
assetPath =
|
||||||
window.EXCALIDRAW_ASSET_PATH ||
|
window.EXCALIDRAW_ASSET_PATH ||
|
||||||
`https://unpkg.com/${process.env.PKG_NAME}@${process.env.PKG_VERSION}`;
|
`https://unpkg.com/${import.meta.env.VITE_PKG_NAME}@${
|
||||||
|
import.meta.env.PKG_VERSION
|
||||||
|
}`;
|
||||||
|
|
||||||
if (assetPath?.startsWith("/")) {
|
if (assetPath?.startsWith("/")) {
|
||||||
assetPath = assetPath.replace("/", `${window.location.origin}/`);
|
assetPath = assetPath.replace("/", `${window.location.origin}/`);
|
||||||
|
@ -1,147 +0,0 @@
|
|||||||
/// <reference lib="webworker" />
|
|
||||||
/* eslint-disable no-restricted-globals */
|
|
||||||
|
|
||||||
// This service worker can be customized!
|
|
||||||
// See https://developers.google.com/web/tools/workbox/modules
|
|
||||||
// for the list of available Workbox modules, or add any other
|
|
||||||
// code you'd like.
|
|
||||||
// You can also remove this file if you'd prefer not to use a
|
|
||||||
// service worker, and the Workbox build step will be skipped.
|
|
||||||
|
|
||||||
import { clientsClaim } from "workbox-core";
|
|
||||||
import { ExpirationPlugin } from "workbox-expiration";
|
|
||||||
import { precacheAndRoute, createHandlerBoundToURL } from "workbox-precaching";
|
|
||||||
import { registerRoute } from "workbox-routing";
|
|
||||||
import { CacheFirst, StaleWhileRevalidate } from "workbox-strategies";
|
|
||||||
|
|
||||||
declare const self: ServiceWorkerGlobalScope;
|
|
||||||
|
|
||||||
clientsClaim();
|
|
||||||
|
|
||||||
// Precache assets generated by your build process.
|
|
||||||
//
|
|
||||||
// Their URLs are injected into the __WB_MANIFEST during build (by workbox).
|
|
||||||
//
|
|
||||||
// This variable must be present somewhere in your service worker file,
|
|
||||||
// even if you decide not to use precaching. See https://cra.link/PWA.
|
|
||||||
//
|
|
||||||
// We don't want to precache i18n files so we filter them out
|
|
||||||
// (normally this should be configured in a webpack workbox plugin, but we don't
|
|
||||||
// have access to it in CRA) — this is because all users will use at most
|
|
||||||
// one or two languages, so there's no point fetching all of them. (They'll
|
|
||||||
// be cached as you load them.)
|
|
||||||
const manifest = self.__WB_MANIFEST.filter((entry) => {
|
|
||||||
return !/locales\/[\w-]+json/.test(
|
|
||||||
typeof entry === "string" ? entry : entry.url,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
precacheAndRoute(manifest);
|
|
||||||
|
|
||||||
// Set up App Shell-style routing, so that all navigation requests
|
|
||||||
// are fulfilled with your index.html shell. Learn more at
|
|
||||||
// https://developer.chrome.com/docs/workbox/app-shell-model/
|
|
||||||
//
|
|
||||||
// below is copied verbatim from CRA@5
|
|
||||||
const fileExtensionRegexp = new RegExp("/[^/?]+\\.[^/]+$");
|
|
||||||
registerRoute(
|
|
||||||
// Return false to exempt requests from being fulfilled by index.html.
|
|
||||||
({ request, url }: { request: Request; url: URL }) => {
|
|
||||||
// If this isn't a navigation, skip.
|
|
||||||
if (request.mode !== "navigate") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is a URL that starts with /_, skip.
|
|
||||||
if (url.pathname.startsWith("/_")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this looks like a URL for a resource, because it contains
|
|
||||||
// a file extension, skip.
|
|
||||||
if (url.pathname.match(fileExtensionRegexp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true to signal that we want to use the handler.
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
createHandlerBoundToURL(`${process.env.PUBLIC_URL}/index.html`),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Cache resources that aren't being precached
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
registerRoute(
|
|
||||||
new RegExp("/fonts.css"),
|
|
||||||
new StaleWhileRevalidate({
|
|
||||||
cacheName: "fonts",
|
|
||||||
plugins: [
|
|
||||||
// Ensure that once this runtime cache reaches a maximum size the
|
|
||||||
// least-recently used images are removed.
|
|
||||||
new ExpirationPlugin({ maxEntries: 50 }),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// since we serve fonts from, don't forget to append new ?v= param when
|
|
||||||
// updating fonts (glyphs) without changing the filename
|
|
||||||
registerRoute(
|
|
||||||
new RegExp("/.+.(ttf|woff2|otf)"),
|
|
||||||
new CacheFirst({
|
|
||||||
cacheName: "fonts",
|
|
||||||
plugins: [
|
|
||||||
// Ensure that once this runtime cache reaches a maximum size the
|
|
||||||
// least-recently used images are removed.
|
|
||||||
new ExpirationPlugin({
|
|
||||||
maxEntries: 50,
|
|
||||||
// 90 days
|
|
||||||
maxAgeSeconds: 7776000000,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
registerRoute(
|
|
||||||
new RegExp("/locales\\/[\\w-]+json"),
|
|
||||||
// Customize this strategy as needed, e.g., by changing to CacheFirst.
|
|
||||||
new CacheFirst({
|
|
||||||
cacheName: "locales",
|
|
||||||
plugins: [
|
|
||||||
// Ensure that once this runtime cache reaches a maximum size the
|
|
||||||
// least-recently used images are removed.
|
|
||||||
new ExpirationPlugin({
|
|
||||||
maxEntries: 50,
|
|
||||||
// 30 days
|
|
||||||
maxAgeSeconds: 2592000000,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
self.addEventListener("fetch", (event) => {
|
|
||||||
if (
|
|
||||||
event.request.method === "POST" &&
|
|
||||||
event.request.url.endsWith("/web-share-target")
|
|
||||||
) {
|
|
||||||
return event.respondWith(
|
|
||||||
(async () => {
|
|
||||||
const formData = await event.request.formData();
|
|
||||||
const file = formData.get("file");
|
|
||||||
const webShareTargetCache = await caches.open("web-share-target");
|
|
||||||
await webShareTargetCache.put("shared-file", new Response(file));
|
|
||||||
return Response.redirect("/?web-share-target", 303);
|
|
||||||
})(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// This allows the web app to trigger skipWaiting via
|
|
||||||
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
|
|
||||||
self.addEventListener("message", (event) => {
|
|
||||||
if (event.data && event.data.type === "SKIP_WAITING") {
|
|
||||||
self.skipWaiting();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,162 +0,0 @@
|
|||||||
// This optional code is used to register a service worker.
|
|
||||||
// register() is not called by default.
|
|
||||||
|
|
||||||
// This lets the app load faster on subsequent visits in production, and gives
|
|
||||||
// it offline capabilities. However, it also means that developers (and users)
|
|
||||||
// will only see deployed updates on subsequent visits to a page, after all the
|
|
||||||
// existing tabs open on the page have been closed, since previously cached
|
|
||||||
// resources are updated in the background.
|
|
||||||
|
|
||||||
// To learn more about the benefits of this model and instructions on how to
|
|
||||||
// opt-in, read https://bit.ly/CRA-PWA
|
|
||||||
|
|
||||||
const isLocalhost = Boolean(
|
|
||||||
window.location.hostname === "localhost" ||
|
|
||||||
// [::1] is the IPv6 localhost address.
|
|
||||||
window.location.hostname === "[::1]" ||
|
|
||||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
|
||||||
window.location.hostname.match(
|
|
||||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
type Config = {
|
|
||||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
|
||||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const register = (config?: Config) => {
|
|
||||||
if (
|
|
||||||
(process.env.NODE_ENV === "production" ||
|
|
||||||
process.env.REACT_APP_DEV_ENABLE_SW?.toLowerCase() === "true") &&
|
|
||||||
"serviceWorker" in navigator
|
|
||||||
) {
|
|
||||||
// The URL constructor is available in all browsers that support SW.
|
|
||||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
|
||||||
if (publicUrl.origin !== window.location.origin) {
|
|
||||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
|
||||||
// from what our page is served on. This might happen if a CDN is used to
|
|
||||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
|
||||||
const isWebexLP = window.location.pathname.startsWith("/webex");
|
|
||||||
if (isWebexLP) {
|
|
||||||
unregister(() => {
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
|
||||||
|
|
||||||
if (isLocalhost) {
|
|
||||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
|
||||||
checkValidServiceWorker(swUrl, config);
|
|
||||||
|
|
||||||
// Add some additional logging to localhost, pointing developers to the
|
|
||||||
// service worker/PWA documentation.
|
|
||||||
navigator.serviceWorker.ready.then(() => {
|
|
||||||
console.info(
|
|
||||||
"This web app is being served cache-first by a service " +
|
|
||||||
"worker. To learn more, visit https://bit.ly/CRA-PWA",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Is not localhost. Just register service worker
|
|
||||||
registerValidSW(swUrl, config);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const registerValidSW = (swUrl: string, config?: Config) => {
|
|
||||||
navigator.serviceWorker
|
|
||||||
.register(swUrl)
|
|
||||||
.then((registration) => {
|
|
||||||
registration.onupdatefound = () => {
|
|
||||||
const installingWorker = registration.installing;
|
|
||||||
if (installingWorker == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
installingWorker.onstatechange = () => {
|
|
||||||
if (installingWorker.state === "installed") {
|
|
||||||
if (navigator.serviceWorker.controller) {
|
|
||||||
// At this point, the updated precached content has been fetched,
|
|
||||||
// but the previous service worker will still serve the older
|
|
||||||
// content until all client tabs are closed.
|
|
||||||
|
|
||||||
console.info(
|
|
||||||
"New content is available and will be used when all tabs for this page are closed.",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Execute callback
|
|
||||||
if (config && config.onUpdate) {
|
|
||||||
config.onUpdate(registration);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// At this point, everything has been precached.
|
|
||||||
// It's the perfect time to display a
|
|
||||||
// "Content is cached for offline use." message.
|
|
||||||
|
|
||||||
console.info("Content is cached for offline use.");
|
|
||||||
|
|
||||||
// Execute callback
|
|
||||||
if (config && config.onSuccess) {
|
|
||||||
config.onSuccess(registration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error during service worker registration:", error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkValidServiceWorker = (swUrl: string, config?: Config) => {
|
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
|
||||||
fetch(swUrl, {
|
|
||||||
headers: { "Service-Worker": "script" },
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
|
||||||
const contentType = response.headers.get("content-type");
|
|
||||||
if (
|
|
||||||
response.status === 404 ||
|
|
||||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
|
||||||
) {
|
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
|
||||||
navigator.serviceWorker.ready.then((registration) => {
|
|
||||||
registration.unregister().then(() => {
|
|
||||||
window.location.reload();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Service worker found. Proceed as normal.
|
|
||||||
registerValidSW(swUrl, config);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.info(
|
|
||||||
"No internet connection found. App is running in offline mode.",
|
|
||||||
error.message,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const unregister = (callback?: () => void) => {
|
|
||||||
if ("serviceWorker" in navigator) {
|
|
||||||
navigator.serviceWorker.ready
|
|
||||||
.then((registration) => {
|
|
||||||
return registration.unregister();
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
callback?.();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,19 +1,16 @@
|
|||||||
|
// vitest.setup.ts
|
||||||
|
import "vitest-canvas-mock";
|
||||||
import "@testing-library/jest-dom";
|
import "@testing-library/jest-dom";
|
||||||
import "jest-canvas-mock";
|
import { vi } from "vitest";
|
||||||
import dotenv from "dotenv";
|
|
||||||
import polyfill from "./polyfill";
|
import polyfill from "./polyfill";
|
||||||
|
|
||||||
require("fake-indexeddb/auto");
|
require("fake-indexeddb/auto");
|
||||||
|
|
||||||
polyfill();
|
polyfill();
|
||||||
// jest doesn't know of .env.development so we need to init it ourselves
|
|
||||||
dotenv.config({
|
|
||||||
path: require("path").resolve(__dirname, "../.env.development"),
|
|
||||||
});
|
|
||||||
|
|
||||||
jest.mock("nanoid", () => {
|
vi.mock("nanoid", () => {
|
||||||
return {
|
return {
|
||||||
nanoid: jest.fn(() => "test-id"),
|
nanoid: vi.fn(() => "test-id"),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// ReactDOM is located inside index.tsx file
|
// ReactDOM is located inside index.tsx file
|
||||||
|
@ -11,23 +11,23 @@ describe("Test MobileMenu", () => {
|
|||||||
const { h } = window;
|
const { h } = window;
|
||||||
const dimensions = { height: 400, width: 800 };
|
const dimensions = { height: 400, width: 800 };
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
mockBoundingClientRect(dimensions);
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await render(<ExcalidrawApp />);
|
await render(<ExcalidrawApp />);
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
h.app.refreshDeviceState(h.app.excalidrawContainerRef.current!);
|
h.app.refreshDeviceState(h.app.excalidrawContainerRef.current!);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
mockBoundingClientRect(dimensions);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
restoreOriginalGetBoundingClientRect();
|
restoreOriginalGetBoundingClientRect();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set device correctly", () => {
|
it("should set device correctly", () => {
|
||||||
expect(h.app.device).toMatchInlineSnapshot(`
|
expect(h.app.device).toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"canDeviceFitSidebar": false,
|
"canDeviceFitSidebar": false,
|
||||||
"isLandscape": true,
|
"isLandscape": true,
|
||||||
"isMobile": true,
|
"isMobile": true,
|
||||||
@ -39,7 +39,6 @@ describe("Test MobileMenu", () => {
|
|||||||
|
|
||||||
it("should initialize with welcome screen and hide once user interacts", async () => {
|
it("should initialize with welcome screen and hide once user interacts", async () => {
|
||||||
expect(document.querySelector(".welcome-screen-center")).toMatchSnapshot();
|
expect(document.querySelector(".welcome-screen-center")).toMatchSnapshot();
|
||||||
|
|
||||||
UI.clickTool("rectangle");
|
UI.clickTool("rectangle");
|
||||||
expect(document.querySelector(".welcome-screen-center")).toBeNull();
|
expect(document.querySelector(".welcome-screen-center")).toBeNull();
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`Test MobileMenu should initialize with welcome screen and hide once user interacts 1`] = `
|
exports[`Test MobileMenu > should initialize with welcome screen and hide once user interacts 1`] = `
|
||||||
<div
|
<div
|
||||||
class="welcome-screen-center"
|
class="welcome-screen-center"
|
||||||
>
|
>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`tryParseSpreadsheet works for numbers with comma in them 1`] = `
|
exports[`tryParseSpreadsheet > works for numbers with comma in them 1`] = `
|
||||||
Object {
|
{
|
||||||
"spreadsheet": Object {
|
"spreadsheet": {
|
||||||
"labels": Array [
|
"labels": [
|
||||||
"Week 1",
|
"Week 1",
|
||||||
"Week 2",
|
"Week 2",
|
||||||
"Week 3",
|
"Week 3",
|
||||||
],
|
],
|
||||||
"title": "Users",
|
"title": "Users",
|
||||||
"values": Array [
|
"values": [
|
||||||
814,
|
814,
|
||||||
10301,
|
10301,
|
||||||
4264,
|
4264,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough arrow 1`] = `1`;
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > arrow 1`] = `1`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough arrow 2`] = `
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > arrow 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -11,7 +11,7 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -19,18 +19,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -49,16 +49,16 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough diamond 1`] = `1`;
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > diamond 1`] = `1`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough diamond 2`] = `
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > diamond 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -66,7 +66,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -83,16 +83,16 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough ellipse 1`] = `1`;
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > ellipse 1`] = `1`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough ellipse 2`] = `
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > ellipse 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -100,7 +100,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -117,8 +117,8 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough line 1`] = `
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > line 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -126,7 +126,7 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -134,18 +134,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -164,16 +164,16 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough rectangle 1`] = `1`;
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > rectangle 1`] = `1`;
|
||||||
|
|
||||||
exports[`Test dragCreate add element to the scene when pointer dragging long enough rectangle 2`] = `
|
exports[`Test dragCreate > add element to the scene when pointer dragging long enough > rectangle 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -181,7 +181,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,11 +1,11 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`Test Linear Elements Test bound text element should match styles for text editor 1`] = `
|
exports[`Test Linear Elements > Test bound text element > should match styles for text editor 1`] = `
|
||||||
<textarea
|
<textarea
|
||||||
class="excalidraw-wysiwyg"
|
class="excalidraw-wysiwyg"
|
||||||
data-type="wysiwyg"
|
data-type="wysiwyg"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
style="position: absolute; display: inline-block; min-height: 1em; margin: 0px; padding: 0px; border: 0px; outline: 0; resize: none; background: transparent; overflow: hidden; z-index: var(--zIndex-wysiwyg); word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; box-sizing: content-box; width: 10.5px; height: 25px; left: 35px; top: 7.5px; transform: translate(0px, 0px) scale(1) rotate(0deg); text-align: center; vertical-align: middle; color: rgb(30, 30, 30); opacity: 1; filter: var(--theme-filter); max-height: -7.5px; font: Emoji 20px 20px; line-height: 1.25; font-family: Virgil, Segoe UI Emoji;"
|
style="position: absolute; display: inline-block; min-height: 1em; backface-visibility: hidden; margin: 0px; padding: 0px; border: 0px; outline: 0; resize: none; background: transparent; overflow: hidden; z-index: var(--zIndex-wysiwyg); word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; box-sizing: content-box; width: 10.5px; height: 25px; left: 35px; top: 7.5px; transform: translate(0px, 0px) scale(1) rotate(0deg); text-align: center; vertical-align: middle; color: rgb(30, 30, 30); opacity: 1; filter: var(--theme-filter); max-height: -7.5px; font: Emoji 20px 20px; line-height: 1.25; font-family: Virgil, Segoe UI Emoji;"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
wrap="off"
|
wrap="off"
|
||||||
/>
|
/>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`duplicate element on move when ALT is clicked rectangle 1`] = `
|
exports[`duplicate element on move when ALT is clicked > rectangle 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0_copy",
|
"id": "id0_copy",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -15,7 +15,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 401146281,
|
"seed": 401146281,
|
||||||
@ -32,14 +32,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`duplicate element on move when ALT is clicked rectangle 2`] = `
|
exports[`duplicate element on move when ALT is clicked > rectangle 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -47,7 +47,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -64,14 +64,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`move element rectangle 1`] = `
|
exports[`move element > rectangle 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -79,7 +79,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -96,19 +96,19 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`move element rectangles with binding arrow 1`] = `
|
exports[`move element > rectangles with binding arrow 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [
|
"boundElements": [
|
||||||
Object {
|
{
|
||||||
"id": "id2",
|
"id": "id2",
|
||||||
"type": "arrow",
|
"type": "arrow",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -116,7 +116,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -133,19 +133,19 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`move element rectangles with binding arrow 2`] = `
|
exports[`move element > rectangles with binding arrow 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [
|
"boundElements": [
|
||||||
Object {
|
{
|
||||||
"id": "id2",
|
"id": "id2",
|
||||||
"type": "arrow",
|
"type": "arrow",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 300,
|
"height": 300,
|
||||||
"id": "id1",
|
"id": "id1",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -153,7 +153,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 449462985,
|
"seed": 449462985,
|
||||||
@ -170,20 +170,20 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`move element rectangles with binding arrow 3`] = `
|
exports[`move element > rectangles with binding arrow 3`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"endArrowhead": null,
|
"endArrowhead": null,
|
||||||
"endBinding": Object {
|
"endBinding": {
|
||||||
"elementId": "id1",
|
"elementId": "id1",
|
||||||
"focus": -0.46666666666666673,
|
"focus": -0.46666666666666673,
|
||||||
"gap": 10,
|
"gap": 10,
|
||||||
},
|
},
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 81.48231043525051,
|
"height": 81.48231043525051,
|
||||||
"id": "id2",
|
"id": "id2",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -191,23 +191,23 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
81,
|
81,
|
||||||
81.48231043525051,
|
81.48231043525051,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 401146281,
|
"seed": 401146281,
|
||||||
"startArrowhead": null,
|
"startArrowhead": null,
|
||||||
"startBinding": Object {
|
"startBinding": {
|
||||||
"elementId": "id0",
|
"elementId": "id0",
|
||||||
"focus": -0.6000000000000001,
|
"focus": -0.6000000000000001,
|
||||||
"gap": 10,
|
"gap": 10,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`multi point mode in linear elements arrow 1`] = `
|
exports[`multi point mode in linear elements > arrow 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -9,33 +9,33 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 110,
|
"height": 110,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"lastCommittedPoint": Array [
|
"lastCommittedPoint": [
|
||||||
70,
|
70,
|
||||||
110,
|
110,
|
||||||
],
|
],
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
30,
|
30,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
110,
|
110,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -54,8 +54,8 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`multi point mode in linear elements line 1`] = `
|
exports[`multi point mode in linear elements > line 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -63,33 +63,33 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 110,
|
"height": 110,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
"lastCommittedPoint": Array [
|
"lastCommittedPoint": [
|
||||||
70,
|
70,
|
||||||
110,
|
110,
|
||||||
],
|
],
|
||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
30,
|
30,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
110,
|
110,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`select single element on the scene arrow 1`] = `
|
exports[`select single element on the scene > arrow 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -9,7 +9,7 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -17,18 +17,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -47,8 +47,8 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`select single element on the scene arrow escape 1`] = `
|
exports[`select single element on the scene > arrow escape 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
@ -56,7 +56,7 @@ Object {
|
|||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -64,18 +64,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
30,
|
30,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -94,14 +94,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`select single element on the scene diamond 1`] = `
|
exports[`select single element on the scene > diamond 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -109,7 +109,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -126,14 +126,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`select single element on the scene ellipse 1`] = `
|
exports[`select single element on the scene > ellipse 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -141,7 +141,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
@ -158,14 +158,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`select single element on the scene rectangle 1`] = `
|
exports[`select single element on the scene > rectangle 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": null,
|
"boundElements": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 50,
|
"height": 50,
|
||||||
"id": "id0",
|
"id": "id0",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -173,7 +173,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": 337897,
|
"seed": 337897,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { queryByTestId, render, waitFor } from "./test-utils";
|
import { queryByTestId, render, waitFor } from "./test-utils";
|
||||||
|
|
||||||
import ExcalidrawApp from "../excalidraw-app";
|
import ExcalidrawApp from "../excalidraw-app";
|
||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
import { getDefaultAppState } from "../appState";
|
import { getDefaultAppState } from "../appState";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { vi } from "vitest";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import {
|
import {
|
||||||
render,
|
render,
|
||||||
@ -21,14 +22,14 @@ const { h } = window;
|
|||||||
|
|
||||||
const mouse = new Pointer("mouse");
|
const mouse = new Pointer("mouse");
|
||||||
|
|
||||||
jest.mock("../keys.ts", () => {
|
vi.mock("../keys.ts", async (importOriginal) => {
|
||||||
const actual = jest.requireActual("../keys.ts");
|
const module: any = await importOriginal();
|
||||||
return {
|
return {
|
||||||
__esmodule: true,
|
__esmodule: true,
|
||||||
...actual,
|
...module,
|
||||||
isDarwin: false,
|
isDarwin: false,
|
||||||
KEYS: {
|
KEYS: {
|
||||||
...actual.KEYS,
|
...module.KEYS,
|
||||||
CTRL_OR_CMD: "ctrlKey",
|
CTRL_OR_CMD: "ctrlKey",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { vi } from "vitest";
|
||||||
import { render, updateSceneData, waitFor } from "./test-utils";
|
import { render, updateSceneData, waitFor } from "./test-utils";
|
||||||
import ExcalidrawApp from "../excalidraw-app";
|
import ExcalidrawApp from "../excalidraw-app";
|
||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
@ -15,15 +16,18 @@ Object.defineProperty(window, "crypto", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock("../excalidraw-app/data/index.ts", () => ({
|
vi.mock("../excalidraw-app/data/index.ts", async (importActual) => {
|
||||||
|
const module = (await importActual()) as any;
|
||||||
|
return {
|
||||||
__esmodule: true,
|
__esmodule: true,
|
||||||
...jest.requireActual("../excalidraw-app/data/index.ts"),
|
...module,
|
||||||
getCollabServer: jest.fn(() => ({
|
getCollabServer: vi.fn(() => ({
|
||||||
url: /* doesn't really matter */ "http://localhost:3002",
|
url: /* doesn't really matter */ "http://localhost:3002",
|
||||||
})),
|
})),
|
||||||
}));
|
};
|
||||||
|
});
|
||||||
|
|
||||||
jest.mock("../excalidraw-app/data/firebase.ts", () => {
|
vi.mock("../excalidraw-app/data/firebase.ts", () => {
|
||||||
const loadFromFirebase = async () => null;
|
const loadFromFirebase = async () => null;
|
||||||
const saveToFirebase = () => {};
|
const saveToFirebase = () => {};
|
||||||
const isSavedToFirebase = () => true;
|
const isSavedToFirebase = () => true;
|
||||||
@ -45,8 +49,9 @@ jest.mock("../excalidraw-app/data/firebase.ts", () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock("socket.io-client", () => {
|
vi.mock("socket.io-client", () => {
|
||||||
return () => {
|
return {
|
||||||
|
default: () => {
|
||||||
return {
|
return {
|
||||||
close: () => {},
|
close: () => {},
|
||||||
on: () => {},
|
on: () => {},
|
||||||
@ -54,6 +59,7 @@ jest.mock("socket.io-client", () => {
|
|||||||
off: () => {},
|
off: () => {},
|
||||||
emit: () => {},
|
emit: () => {},
|
||||||
};
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import { copiedStyles } from "../actions/actionStyles";
|
|||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
import { setDateTimeForTests } from "../utils";
|
import { setDateTimeForTests } from "../utils";
|
||||||
import { LibraryItem } from "../types";
|
import { LibraryItem } from "../types";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
const checkpoint = (name: string) => {
|
const checkpoint = (name: string) => {
|
||||||
expect(renderScene.mock.calls.length).toMatchSnapshot(
|
expect(renderScene.mock.calls.length).toMatchSnapshot(
|
||||||
@ -39,7 +40,7 @@ const mouse = new Pointer("mouse");
|
|||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`restoreElements should restore arrow element correctly 1`] = `
|
exports[`restoreElements > should restore arrow element correctly 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"endArrowhead": null,
|
"endArrowhead": null,
|
||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id-arrow01",
|
"id": "id-arrow01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -17,18 +17,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
100,
|
100,
|
||||||
100,
|
100,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -47,14 +47,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore correctly with rectangle, ellipse and diamond elements 1`] = `
|
exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "blue",
|
"backgroundColor": "blue",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"fillStyle": "cross-hatch",
|
"fillStyle": "cross-hatch",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [
|
"groupIds": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3",
|
"3",
|
||||||
@ -66,7 +66,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 10,
|
"opacity": 10,
|
||||||
"roughness": 2,
|
"roughness": 2,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -83,14 +83,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore correctly with rectangle, ellipse and diamond elements 2`] = `
|
exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "blue",
|
"backgroundColor": "blue",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"fillStyle": "cross-hatch",
|
"fillStyle": "cross-hatch",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [
|
"groupIds": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3",
|
"3",
|
||||||
@ -102,7 +102,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 10,
|
"opacity": 10,
|
||||||
"roughness": 2,
|
"roughness": 2,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -119,14 +119,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore correctly with rectangle, ellipse and diamond elements 3`] = `
|
exports[`restoreElements > should restore correctly with rectangle, ellipse and diamond elements 3`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "blue",
|
"backgroundColor": "blue",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"fillStyle": "cross-hatch",
|
"fillStyle": "cross-hatch",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [
|
"groupIds": [
|
||||||
"1",
|
"1",
|
||||||
"2",
|
"2",
|
||||||
"3",
|
"3",
|
||||||
@ -138,7 +138,7 @@ Object {
|
|||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 10,
|
"opacity": 10,
|
||||||
"roughness": 2,
|
"roughness": 2,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -155,14 +155,14 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore freedraw element correctly 1`] = `
|
exports[`restoreElements > should restore freedraw element correctly 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 0,
|
"height": 0,
|
||||||
"id": "id-freedraw01",
|
"id": "id-freedraw01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -170,10 +170,10 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [],
|
"points": [],
|
||||||
"pressures": Array [],
|
"pressures": [],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -191,16 +191,16 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore line and draw elements correctly 1`] = `
|
exports[`restoreElements > should restore line and draw elements correctly 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"endArrowhead": null,
|
"endArrowhead": null,
|
||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id-line01",
|
"id": "id-line01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -208,18 +208,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
100,
|
100,
|
||||||
100,
|
100,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -238,16 +238,16 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore line and draw elements correctly 2`] = `
|
exports[`restoreElements > should restore line and draw elements correctly 2`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"endArrowhead": null,
|
"endArrowhead": null,
|
||||||
"endBinding": null,
|
"endBinding": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id-draw01",
|
"id": "id-draw01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -255,18 +255,18 @@ Object {
|
|||||||
"link": null,
|
"link": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"points": Array [
|
"points": [
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
100,
|
100,
|
||||||
100,
|
100,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 2,
|
"type": 2,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -285,18 +285,18 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore text element correctly passing value for each attribute 1`] = `
|
exports[`restoreElements > should restore text element correctly passing value for each attribute 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"baseline": 0,
|
"baseline": 0,
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"containerId": null,
|
"containerId": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"fontFamily": 1,
|
"fontFamily": 1,
|
||||||
"fontSize": 14,
|
"fontSize": 14,
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id-text01",
|
"id": "id-text01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -306,7 +306,7 @@ Object {
|
|||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"originalText": "text",
|
"originalText": "text",
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
@ -326,18 +326,18 @@ Object {
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`restoreElements should restore text element correctly with unknown font family, null text and undefined alignment 1`] = `
|
exports[`restoreElements > should restore text element correctly with unknown font family, null text and undefined alignment 1`] = `
|
||||||
Object {
|
{
|
||||||
"angle": 0,
|
"angle": 0,
|
||||||
"backgroundColor": "transparent",
|
"backgroundColor": "transparent",
|
||||||
"baseline": 0,
|
"baseline": 0,
|
||||||
"boundElements": Array [],
|
"boundElements": [],
|
||||||
"containerId": null,
|
"containerId": null,
|
||||||
"fillStyle": "hachure",
|
"fillStyle": "hachure",
|
||||||
"fontFamily": 1,
|
"fontFamily": 1,
|
||||||
"fontSize": 10,
|
"fontSize": 10,
|
||||||
"frameId": null,
|
"frameId": null,
|
||||||
"groupIds": Array [],
|
"groupIds": [],
|
||||||
"height": 100,
|
"height": 100,
|
||||||
"id": "id-text01",
|
"id": "id-text01",
|
||||||
"isDeleted": false,
|
"isDeleted": false,
|
||||||
@ -347,7 +347,7 @@ Object {
|
|||||||
"opacity": 100,
|
"opacity": 100,
|
||||||
"originalText": "test",
|
"originalText": "test",
|
||||||
"roughness": 1,
|
"roughness": 1,
|
||||||
"roundness": Object {
|
"roundness": {
|
||||||
"type": 3,
|
"type": 3,
|
||||||
},
|
},
|
||||||
"seed": Any<Number>,
|
"seed": Any<Number>,
|
||||||
|
@ -12,9 +12,10 @@ import { ImportedDataState } from "../../data/types";
|
|||||||
import { NormalizedZoomValue } from "../../types";
|
import { NormalizedZoomValue } from "../../types";
|
||||||
import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants";
|
import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants";
|
||||||
import { newElementWith } from "../../element/mutateElement";
|
import { newElementWith } from "../../element/mutateElement";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
describe("restoreElements", () => {
|
describe("restoreElements", () => {
|
||||||
const mockSizeHelper = jest.spyOn(sizeHelpers, "isInvisiblySmallElement");
|
const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement");
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockSizeHelper.mockReset();
|
mockSizeHelper.mockReset();
|
||||||
@ -152,7 +153,7 @@ describe("restoreElements", () => {
|
|||||||
it("when arrow element has undefined endArrowHead", () => {
|
it("when arrow element has undefined endArrowHead", () => {
|
||||||
const arrowElement = API.createElement({ type: "arrow" });
|
const arrowElement = API.createElement({ type: "arrow" });
|
||||||
Object.defineProperty(arrowElement, "endArrowhead", {
|
Object.defineProperty(arrowElement, "endArrowhead", {
|
||||||
get: jest.fn(() => undefined),
|
get: vi.fn(() => undefined),
|
||||||
});
|
});
|
||||||
|
|
||||||
const restoredElements = restore.restoreElements([arrowElement], null);
|
const restoredElements = restore.restoreElements([arrowElement], null);
|
||||||
@ -205,7 +206,7 @@ describe("restoreElements", () => {
|
|||||||
[1, 1],
|
[1, 1],
|
||||||
];
|
];
|
||||||
Object.defineProperty(lineElement_0, "points", {
|
Object.defineProperty(lineElement_0, "points", {
|
||||||
get: jest.fn(() => pointsEl_0),
|
get: vi.fn(() => pointsEl_0),
|
||||||
});
|
});
|
||||||
|
|
||||||
const pointsEl_1 = [
|
const pointsEl_1 = [
|
||||||
@ -213,7 +214,7 @@ describe("restoreElements", () => {
|
|||||||
[5, 6],
|
[5, 6],
|
||||||
];
|
];
|
||||||
Object.defineProperty(lineElement_1, "points", {
|
Object.defineProperty(lineElement_1, "points", {
|
||||||
get: jest.fn(() => pointsEl_1),
|
get: vi.fn(() => pointsEl_1),
|
||||||
});
|
});
|
||||||
|
|
||||||
const restoredElements = restore.restoreElements(
|
const restoredElements = restore.restoreElements(
|
||||||
@ -440,7 +441,7 @@ describe("restoreAppState", () => {
|
|||||||
const stubImportedAppState = getDefaultAppState();
|
const stubImportedAppState = getDefaultAppState();
|
||||||
|
|
||||||
Object.defineProperty(stubImportedAppState, "zoom", {
|
Object.defineProperty(stubImportedAppState, "zoom", {
|
||||||
get: jest.fn(() => null),
|
get: vi.fn(() => null),
|
||||||
});
|
});
|
||||||
|
|
||||||
const stubLocalAppState = getDefaultAppState();
|
const stubLocalAppState = getDefaultAppState();
|
||||||
|
@ -10,11 +10,12 @@ import {
|
|||||||
} from "./test-utils";
|
} from "./test-utils";
|
||||||
import { ExcalidrawLinearElement } from "../element/types";
|
import { ExcalidrawLinearElement } from "../element/types";
|
||||||
import { reseed } from "../random";
|
import { reseed } from "../random";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
@ -2,6 +2,7 @@ import { render } from "./test-utils";
|
|||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
|
|
||||||
import ExcalidrawApp from "../excalidraw-app";
|
import ExcalidrawApp from "../excalidraw-app";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
|
||||||
@ -97,11 +98,11 @@ const waitForNextAnimationFrame = () => {
|
|||||||
|
|
||||||
describe("fitToContent animated", () => {
|
describe("fitToContent animated", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(window, "requestAnimationFrame");
|
vi.spyOn(window, "requestAnimationFrame");
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should ease scroll the viewport to the selected element", async () => {
|
it("should ease scroll the viewport to the selected element", async () => {
|
||||||
|
@ -20,21 +20,21 @@ import ExcalidrawApp from "../excalidraw-app";
|
|||||||
import { mutateElement } from "../element/mutateElement";
|
import { mutateElement } from "../element/mutateElement";
|
||||||
import { NormalizedZoomValue } from "../types";
|
import { NormalizedZoomValue } from "../types";
|
||||||
import { ROUNDNESS } from "../constants";
|
import { ROUNDNESS } from "../constants";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
import * as blob from "../data/blob";
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
|
||||||
const mouse = new Pointer("mouse");
|
const mouse = new Pointer("mouse");
|
||||||
jest.mock("../data/blob", () => {
|
// This needs to fixed in vitest mock, as when importActual used with mock
|
||||||
const originalModule = jest.requireActual("../data/blob");
|
// the tests hangs - https://github.com/vitest-dev/vitest/issues/546.
|
||||||
|
// But fortunately spying and mocking the return value of spy works :p
|
||||||
|
|
||||||
|
const resizeImageFileSpy = vi.spyOn(blob, "resizeImageFile");
|
||||||
|
const generateIdFromFileSpy = vi.spyOn(blob, "generateIdFromFile");
|
||||||
|
|
||||||
|
resizeImageFileSpy.mockImplementation(async (imageFile: File) => imageFile);
|
||||||
|
generateIdFromFileSpy.mockImplementation(async () => "fileId" as FileId);
|
||||||
|
|
||||||
//Prevent Node.js modules errors (document is not defined etc...)
|
|
||||||
return {
|
|
||||||
__esModule: true,
|
|
||||||
...originalModule,
|
|
||||||
resizeImageFile: (imageFile: File) => imageFile,
|
|
||||||
generateIdFromFile: () => "fileId" as FileId,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
@ -42,7 +42,7 @@ beforeEach(async () => {
|
|||||||
mouse.reset();
|
mouse.reset();
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
sessionStorage.clear();
|
sessionStorage.clear();
|
||||||
jest.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|
||||||
Object.assign(document, {
|
Object.assign(document, {
|
||||||
elementFromPoint: () => GlobalTestState.canvas,
|
elementFromPoint: () => GlobalTestState.canvas,
|
||||||
@ -732,7 +732,6 @@ describe("image", () => {
|
|||||||
it("flips an unrotated image horizontally correctly", async () => {
|
it("flips an unrotated image horizontally correctly", async () => {
|
||||||
//paste image
|
//paste image
|
||||||
await createImage();
|
await createImage();
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
expect((h.elements[0] as ExcalidrawImageElement).scale).toEqual([1, 1]);
|
||||||
expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
expect(API.getSelectedElements().length).toBeGreaterThan(0);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { vi } from "vitest";
|
||||||
import { fireEvent, render, waitFor } from "./test-utils";
|
import { fireEvent, render, waitFor } from "./test-utils";
|
||||||
import { queryByTestId } from "@testing-library/react";
|
import { queryByTestId } from "@testing-library/react";
|
||||||
|
|
||||||
@ -29,11 +30,15 @@ const mockLibraryFilePromise = new Promise<Blob>(async (resolve, reject) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock("../data/filesystem.ts", () => ({
|
vi.mock("../data/filesystem.ts", async (importOriginal) => {
|
||||||
|
const module = await importOriginal();
|
||||||
|
return {
|
||||||
__esmodule: true,
|
__esmodule: true,
|
||||||
...jest.requireActual("../data/filesystem.ts"),
|
//@ts-ignore
|
||||||
fileOpen: jest.fn(() => mockLibraryFilePromise),
|
...module,
|
||||||
}));
|
fileOpen: vi.fn(() => mockLibraryFilePromise),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe("library", () => {
|
describe("library", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -24,8 +24,9 @@ import {
|
|||||||
} from "../element/textElement";
|
} from "../element/textElement";
|
||||||
import * as textElementUtils from "../element/textElement";
|
import * as textElementUtils from "../element/textElement";
|
||||||
import { ROUNDNESS, VERTICAL_ALIGN } from "../constants";
|
import { ROUNDNESS, VERTICAL_ALIGN } from "../constants";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
|
const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
|
||||||
@ -179,16 +180,16 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(renderScene).toHaveBeenCalledTimes(11);
|
expect(renderScene).toHaveBeenCalledTimes(11);
|
||||||
expect(line.points.length).toEqual(3);
|
expect(line.points.length).toEqual(3);
|
||||||
expect(line.points).toMatchInlineSnapshot(`
|
expect(line.points).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
40,
|
40,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
@ -273,16 +274,16 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect(line.points.length).toEqual(3);
|
expect(line.points.length).toEqual(3);
|
||||||
expect(line.points).toMatchInlineSnapshot(`
|
expect(line.points).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
40,
|
40,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
@ -315,12 +316,12 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(midPointsWithRoundEdge[1]).not.toEqual(midPointsWithSharpEdge[1]);
|
expect(midPointsWithRoundEdge[1]).not.toEqual(midPointsWithSharpEdge[1]);
|
||||||
|
|
||||||
expect(midPointsWithRoundEdge).toMatchInlineSnapshot(`
|
expect(midPointsWithRoundEdge).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
55.9697848965255,
|
55.9697848965255,
|
||||||
47.442326230998205,
|
47.442326230998205,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
76.08587175006699,
|
76.08587175006699,
|
||||||
43.294165939653226,
|
43.294165939653226,
|
||||||
],
|
],
|
||||||
@ -363,12 +364,12 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
||||||
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
||||||
expect(newMidPoints).toMatchInlineSnapshot(`
|
expect(newMidPoints).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
105.96978489652551,
|
105.96978489652551,
|
||||||
67.4423262309982,
|
67.4423262309982,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
126.08587175006699,
|
126.08587175006699,
|
||||||
63.294165939653226,
|
63.294165939653226,
|
||||||
],
|
],
|
||||||
@ -412,24 +413,24 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect((h.elements[0] as ExcalidrawLinearElement).points)
|
expect((h.elements[0] as ExcalidrawLinearElement).points)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
85,
|
85,
|
||||||
75,
|
75,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
105,
|
105,
|
||||||
70,
|
70,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
40,
|
40,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
@ -558,24 +559,24 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect((h.elements[0] as ExcalidrawLinearElement).points)
|
expect((h.elements[0] as ExcalidrawLinearElement).points)
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
85.96978489652551,
|
85.96978489652551,
|
||||||
77.4423262309982,
|
77.4423262309982,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
70,
|
70,
|
||||||
50,
|
50,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
106.08587175006699,
|
106.08587175006699,
|
||||||
73.29416593965323,
|
73.29416593965323,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
40,
|
40,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
@ -606,12 +607,12 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
||||||
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
||||||
expect(newMidPoints).toMatchInlineSnapshot(`
|
expect(newMidPoints).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
31.884084517616053,
|
31.884084517616053,
|
||||||
23.13275505472383,
|
23.13275505472383,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
77.74792546875662,
|
77.74792546875662,
|
||||||
44.57840982272327,
|
44.57840982272327,
|
||||||
],
|
],
|
||||||
@ -667,12 +668,12 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
expect(midPoints[0]).not.toEqual(newMidPoints[0]);
|
||||||
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
expect(midPoints[1]).not.toEqual(newMidPoints[1]);
|
||||||
expect(newMidPoints).toMatchInlineSnapshot(`
|
expect(newMidPoints).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
55.9697848965255,
|
55.9697848965255,
|
||||||
47.442326230998205,
|
47.442326230998205,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
76.08587175006699,
|
76.08587175006699,
|
||||||
43.294165939653226,
|
43.294165939653226,
|
||||||
],
|
],
|
||||||
@ -704,12 +705,12 @@ describe("Test Linear Elements", () => {
|
|||||||
[dragEndPositionOffset[0] + line.x, dragEndPositionOffset[1] + line.y],
|
[dragEndPositionOffset[0] + line.x, dragEndPositionOffset[1] + line.y],
|
||||||
);
|
);
|
||||||
expect(line.points).toMatchInlineSnapshot(`
|
expect(line.points).toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
Array [
|
[
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
Array [
|
[
|
||||||
-60,
|
-60,
|
||||||
-100,
|
-100,
|
||||||
],
|
],
|
||||||
@ -768,7 +769,7 @@ describe("Test Linear Elements", () => {
|
|||||||
textElement,
|
textElement,
|
||||||
);
|
);
|
||||||
expect(position).toMatchInlineSnapshot(`
|
expect(position).toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 25,
|
"x": 25,
|
||||||
"y": 10,
|
"y": 10,
|
||||||
}
|
}
|
||||||
@ -790,7 +791,7 @@ describe("Test Linear Elements", () => {
|
|||||||
textElement,
|
textElement,
|
||||||
);
|
);
|
||||||
expect(position).toMatchInlineSnapshot(`
|
expect(position).toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 75,
|
"x": 75,
|
||||||
"y": 60,
|
"y": 60,
|
||||||
}
|
}
|
||||||
@ -824,7 +825,7 @@ describe("Test Linear Elements", () => {
|
|||||||
textElement,
|
textElement,
|
||||||
);
|
);
|
||||||
expect(position).toMatchInlineSnapshot(`
|
expect(position).toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 85.82201843191861,
|
"x": 85.82201843191861,
|
||||||
"y": 75.63461309860818,
|
"y": 75.63461309860818,
|
||||||
}
|
}
|
||||||
@ -939,7 +940,7 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(textElement.angle).toBe(0);
|
expect(textElement.angle).toBe(0);
|
||||||
expect(getBoundTextElementPosition(arrow, textElement))
|
expect(getBoundTextElementPosition(arrow, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 75,
|
"x": 75,
|
||||||
"y": 60,
|
"y": 60,
|
||||||
}
|
}
|
||||||
@ -951,7 +952,7 @@ describe("Test Linear Elements", () => {
|
|||||||
`);
|
`);
|
||||||
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
105,
|
105,
|
||||||
@ -966,7 +967,7 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(textElement.angle).toBe(0);
|
expect(textElement.angle).toBe(0);
|
||||||
expect(getBoundTextElementPosition(container, textElement))
|
expect(getBoundTextElementPosition(container, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 21.73926141863671,
|
"x": 21.73926141863671,
|
||||||
"y": 73.31003398390868,
|
"y": 73.31003398390868,
|
||||||
}
|
}
|
||||||
@ -978,7 +979,7 @@ describe("Test Linear Elements", () => {
|
|||||||
`);
|
`);
|
||||||
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
102.41961302274555,
|
102.41961302274555,
|
||||||
@ -1004,7 +1005,7 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(container.height).toBe(50);
|
expect(container.height).toBe(50);
|
||||||
expect(getBoundTextElementPosition(container, textElement))
|
expect(getBoundTextElementPosition(container, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 75,
|
"x": 75,
|
||||||
"y": 60,
|
"y": 60,
|
||||||
}
|
}
|
||||||
@ -1016,7 +1017,7 @@ describe("Test Linear Elements", () => {
|
|||||||
`);
|
`);
|
||||||
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
20,
|
20,
|
||||||
105,
|
105,
|
||||||
@ -1030,7 +1031,7 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect({ width: container.width, height: container.height })
|
expect({ width: container.width, height: container.height })
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"height": 130,
|
"height": 130,
|
||||||
"width": 367,
|
"width": 367,
|
||||||
}
|
}
|
||||||
@ -1038,7 +1039,7 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect(getBoundTextElementPosition(container, textElement))
|
expect(getBoundTextElementPosition(container, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 272,
|
"x": 272,
|
||||||
"y": 45,
|
"y": 45,
|
||||||
}
|
}
|
||||||
@ -1050,7 +1051,7 @@ describe("Test Linear Elements", () => {
|
|||||||
`);
|
`);
|
||||||
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
expect(LinearElementEditor.getElementAbsoluteCoords(container, true))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Array [
|
[
|
||||||
20,
|
20,
|
||||||
35,
|
35,
|
||||||
502,
|
502,
|
||||||
@ -1072,7 +1073,7 @@ describe("Test Linear Elements", () => {
|
|||||||
expect(container.width).toBe(40);
|
expect(container.width).toBe(40);
|
||||||
expect(getBoundTextElementPosition(container, textElement))
|
expect(getBoundTextElementPosition(container, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 25,
|
"x": 25,
|
||||||
"y": 10,
|
"y": 10,
|
||||||
}
|
}
|
||||||
@ -1089,7 +1090,7 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect({ width: container.width, height: container.height })
|
expect({ width: container.width, height: container.height })
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"height": 130,
|
"height": 130,
|
||||||
"width": 340,
|
"width": 340,
|
||||||
}
|
}
|
||||||
@ -1097,7 +1098,7 @@ describe("Test Linear Elements", () => {
|
|||||||
|
|
||||||
expect(getBoundTextElementPosition(container, textElement))
|
expect(getBoundTextElementPosition(container, textElement))
|
||||||
.toMatchInlineSnapshot(`
|
.toMatchInlineSnapshot(`
|
||||||
Object {
|
{
|
||||||
"x": 75,
|
"x": 75,
|
||||||
"y": -5,
|
"y": -5,
|
||||||
}
|
}
|
||||||
@ -1154,7 +1155,7 @@ describe("Test Linear Elements", () => {
|
|||||||
"Online whiteboard collaboration
|
"Online whiteboard collaboration
|
||||||
made easy"
|
made easy"
|
||||||
`);
|
`);
|
||||||
const handleBindTextResizeSpy = jest.spyOn(
|
const handleBindTextResizeSpy = vi.spyOn(
|
||||||
textElementUtils,
|
textElementUtils,
|
||||||
"handleBindTextResize",
|
"handleBindTextResize",
|
||||||
);
|
);
|
||||||
|
@ -12,11 +12,12 @@ import {
|
|||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import { UI, Pointer, Keyboard } from "./helpers/ui";
|
import { UI, Pointer, Keyboard } from "./helpers/ui";
|
||||||
import { KEYS } from "../keys";
|
import { KEYS } from "../keys";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
@ -10,11 +10,12 @@ import * as Renderer from "../renderer/renderScene";
|
|||||||
import { KEYS } from "../keys";
|
import { KEYS } from "../keys";
|
||||||
import { ExcalidrawLinearElement } from "../element/types";
|
import { ExcalidrawLinearElement } from "../element/types";
|
||||||
import { reseed } from "../random";
|
import { reseed } from "../random";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`<Excalidraw/> <MainMenu/> should render main menu with host menu items if passed from host 1`] = `
|
exports[`<Excalidraw/> > <MainMenu/> > should render main menu with host menu items if passed from host 1`] = `
|
||||||
<div
|
<div
|
||||||
class="dropdown-menu"
|
class="dropdown-menu"
|
||||||
data-testid="dropdown-menu"
|
data-testid="dropdown-menu"
|
||||||
@ -108,7 +108,7 @@ exports[`<Excalidraw/> <MainMenu/> should render main menu with host menu items
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<Excalidraw/> Test UIOptions prop Test canvasActions should render menu with default items when "UIOPtions" is "undefined" 1`] = `
|
exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should render menu with default items when "UIOPtions" is "undefined" 1`] = `
|
||||||
<div
|
<div
|
||||||
class="dropdown-menu"
|
class="dropdown-menu"
|
||||||
data-testid="dropdown-menu"
|
data-testid="dropdown-menu"
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`exportToSvg with default arguments 1`] = `
|
exports[`exportToSvg > with default arguments 1`] = `
|
||||||
Object {
|
{
|
||||||
"activeEmbeddable": null,
|
"activeEmbeddable": null,
|
||||||
"activeTool": Object {
|
"activeTool": {
|
||||||
"customType": null,
|
"customType": null,
|
||||||
"lastActiveTool": null,
|
"lastActiveTool": null,
|
||||||
"locked": false,
|
"locked": false,
|
||||||
@ -40,7 +40,7 @@ Object {
|
|||||||
"exportScale": 1,
|
"exportScale": 1,
|
||||||
"exportWithDarkMode": false,
|
"exportWithDarkMode": false,
|
||||||
"fileHandle": null,
|
"fileHandle": null,
|
||||||
"frameRendering": Object {
|
"frameRendering": {
|
||||||
"clip": true,
|
"clip": true,
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"name": true,
|
"name": true,
|
||||||
@ -59,21 +59,21 @@ Object {
|
|||||||
"openMenu": null,
|
"openMenu": null,
|
||||||
"openPopup": null,
|
"openPopup": null,
|
||||||
"openSidebar": null,
|
"openSidebar": null,
|
||||||
"pasteDialog": Object {
|
"pasteDialog": {
|
||||||
"data": null,
|
"data": null,
|
||||||
"shown": false,
|
"shown": false,
|
||||||
},
|
},
|
||||||
"penDetected": false,
|
"penDetected": false,
|
||||||
"penMode": false,
|
"penMode": false,
|
||||||
"pendingImageElementId": null,
|
"pendingImageElementId": null,
|
||||||
"previousSelectedElementIds": Object {},
|
"previousSelectedElementIds": {},
|
||||||
"resizingElement": null,
|
"resizingElement": null,
|
||||||
"scrollX": 0,
|
"scrollX": 0,
|
||||||
"scrollY": 0,
|
"scrollY": 0,
|
||||||
"scrolledOutside": false,
|
"scrolledOutside": false,
|
||||||
"selectedElementIds": Object {},
|
"selectedElementIds": {},
|
||||||
"selectedElementsAreBeingDragged": false,
|
"selectedElementsAreBeingDragged": false,
|
||||||
"selectedGroupIds": Object {},
|
"selectedGroupIds": {},
|
||||||
"selectedLinearElement": null,
|
"selectedLinearElement": null,
|
||||||
"selectionElement": null,
|
"selectionElement": null,
|
||||||
"shouldCacheIgnoreZoom": false,
|
"shouldCacheIgnoreZoom": false,
|
||||||
@ -81,13 +81,13 @@ Object {
|
|||||||
"showStats": false,
|
"showStats": false,
|
||||||
"showWelcomeScreen": false,
|
"showWelcomeScreen": false,
|
||||||
"startBoundElement": null,
|
"startBoundElement": null,
|
||||||
"suggestedBindings": Array [],
|
"suggestedBindings": [],
|
||||||
"theme": "light",
|
"theme": "light",
|
||||||
"toast": null,
|
"toast": null,
|
||||||
"viewBackgroundColor": "#ffffff",
|
"viewBackgroundColor": "#ffffff",
|
||||||
"viewModeEnabled": false,
|
"viewModeEnabled": false,
|
||||||
"zenModeEnabled": false,
|
"zenModeEnabled": false,
|
||||||
"zoom": Object {
|
"zoom": {
|
||||||
"value": 1,
|
"value": 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { fireEvent, GlobalTestState, toggleMenu, render } from "../test-utils";
|
import { fireEvent, GlobalTestState, toggleMenu, render } from "../test-utils";
|
||||||
import { Excalidraw, Footer, MainMenu } from "../../packages/excalidraw/index";
|
import { Excalidraw, Footer, MainMenu } from "../../packages/excalidraw/index";
|
||||||
import { queryByText, queryByTestId } from "@testing-library/react";
|
import { queryByText, queryByTestId, screen } from "@testing-library/react";
|
||||||
import { GRID_SIZE, THEME } from "../../constants";
|
import { GRID_SIZE, THEME } from "../../constants";
|
||||||
import { t } from "../../i18n";
|
import { t } from "../../i18n";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
@ -42,7 +42,7 @@ describe("<Excalidraw/>", () => {
|
|||||||
container.getElementsByClassName("disable-zen-mode--visible").length,
|
container.getElementsByClassName("disable-zen-mode--visible").length,
|
||||||
).toBe(0);
|
).toBe(0);
|
||||||
expect(h.state.zenModeEnabled).toBe(true);
|
expect(h.state.zenModeEnabled).toBe(true);
|
||||||
|
screen.debug();
|
||||||
fireEvent.contextMenu(GlobalTestState.canvas, {
|
fireEvent.contextMenu(GlobalTestState.canvas, {
|
||||||
button: 2,
|
button: 2,
|
||||||
clientX: 1,
|
clientX: 1,
|
||||||
@ -74,7 +74,8 @@ describe("<Excalidraw/>", () => {
|
|||||||
</Footer>
|
</Footer>
|
||||||
</Excalidraw>,
|
</Excalidraw>,
|
||||||
));
|
));
|
||||||
expect(container.querySelector(".footer-center")).toMatchInlineSnapshot(`
|
expect(container.querySelector(".footer-center")).toMatchInlineSnapshot(
|
||||||
|
`
|
||||||
<div
|
<div
|
||||||
class="footer-center zen-mode-transition"
|
class="footer-center zen-mode-transition"
|
||||||
>
|
>
|
||||||
@ -82,7 +83,8 @@ describe("<Excalidraw/>", () => {
|
|||||||
This is a custom footer
|
This is a custom footer
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Test gridModeEnabled prop", () => {
|
describe("Test gridModeEnabled prop", () => {
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
import * as utils from "../../packages/utils";
|
import * as utils from "../../packages/utils";
|
||||||
import { diagramFactory } from "../fixtures/diagramFixture";
|
import { diagramFactory } from "../fixtures/diagramFixture";
|
||||||
|
import { vi } from "vitest";
|
||||||
import * as mockedSceneExportUtils from "../../scene/export";
|
import * as mockedSceneExportUtils from "../../scene/export";
|
||||||
|
|
||||||
import { MIME_TYPES } from "../../constants";
|
import { MIME_TYPES } from "../../constants";
|
||||||
|
|
||||||
jest.mock("../../scene/export", () => ({
|
const exportToSvgSpy = vi.spyOn(mockedSceneExportUtils, "exportToSvg");
|
||||||
__esmodule: true,
|
|
||||||
...jest.requireActual("../../scene/export"),
|
|
||||||
exportToSvg: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe("exportToCanvas", () => {
|
describe("exportToCanvas", async () => {
|
||||||
const EXPORT_PADDING = 10;
|
const EXPORT_PADDING = 10;
|
||||||
|
|
||||||
it("with default arguments", async () => {
|
it("with default arguments", async () => {
|
||||||
@ -32,10 +30,9 @@ describe("exportToCanvas", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("exportToBlob", () => {
|
describe("exportToBlob", async () => {
|
||||||
describe("mime type", () => {
|
describe("mime type", () => {
|
||||||
afterEach(jest.restoreAllMocks);
|
// afterEach(vi.restoreAllMocks);
|
||||||
|
|
||||||
it("should change image/jpg to image/jpeg", async () => {
|
it("should change image/jpg to image/jpeg", async () => {
|
||||||
const blob = await utils.exportToBlob({
|
const blob = await utils.exportToBlob({
|
||||||
...diagramFactory(),
|
...diagramFactory(),
|
||||||
@ -48,7 +45,6 @@ describe("exportToBlob", () => {
|
|||||||
});
|
});
|
||||||
expect(blob?.type).toBe(MIME_TYPES.jpg);
|
expect(blob?.type).toBe(MIME_TYPES.jpg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should default to image/png", async () => {
|
it("should default to image/png", async () => {
|
||||||
const blob = await utils.exportToBlob({
|
const blob = await utils.exportToBlob({
|
||||||
...diagramFactory(),
|
...diagramFactory(),
|
||||||
@ -57,16 +53,14 @@ describe("exportToBlob", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should warn when using quality with image/png", async () => {
|
it("should warn when using quality with image/png", async () => {
|
||||||
const consoleSpy = jest
|
const consoleSpy = vi
|
||||||
.spyOn(console, "warn")
|
.spyOn(console, "warn")
|
||||||
.mockImplementationOnce(() => void 0);
|
.mockImplementationOnce(() => void 0);
|
||||||
|
|
||||||
await utils.exportToBlob({
|
await utils.exportToBlob({
|
||||||
...diagramFactory(),
|
...diagramFactory(),
|
||||||
mimeType: MIME_TYPES.png,
|
mimeType: MIME_TYPES.png,
|
||||||
quality: 1,
|
quality: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(consoleSpy).toHaveBeenCalledWith(
|
expect(consoleSpy).toHaveBeenCalledWith(
|
||||||
`"quality" will be ignored for "${MIME_TYPES.png}" mimeType`,
|
`"quality" will be ignored for "${MIME_TYPES.png}" mimeType`,
|
||||||
);
|
);
|
||||||
@ -75,10 +69,12 @@ describe("exportToBlob", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("exportToSvg", () => {
|
describe("exportToSvg", () => {
|
||||||
const mockedExportUtil = mockedSceneExportUtils.exportToSvg as jest.Mock;
|
const passedElements = () => exportToSvgSpy.mock.calls[0][0];
|
||||||
const passedElements = () => mockedExportUtil.mock.calls[0][0];
|
const passedOptions = () => exportToSvgSpy.mock.calls[0][1];
|
||||||
const passedOptions = () => mockedExportUtil.mock.calls[0][1];
|
|
||||||
afterEach(jest.resetAllMocks);
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
it("with default arguments", async () => {
|
it("with default arguments", async () => {
|
||||||
await utils.exportToSvg({
|
await utils.exportToSvg({
|
||||||
|
@ -17,10 +17,11 @@ import {
|
|||||||
} from "./test-utils";
|
} from "./test-utils";
|
||||||
import { defaultLang } from "../i18n";
|
import { defaultLang } from "../i18n";
|
||||||
import { FONT_FAMILY } from "../constants";
|
import { FONT_FAMILY } from "../constants";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
const { h } = window;
|
const { h } = window;
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
|
|
||||||
const mouse = new Pointer("mouse");
|
const mouse = new Pointer("mouse");
|
||||||
const finger1 = new Pointer("touch", 1);
|
const finger1 = new Pointer("touch", 1);
|
||||||
@ -156,6 +157,7 @@ describe("regression tests", () => {
|
|||||||
}
|
}
|
||||||
it("change the properties of a shape", () => {
|
it("change the properties of a shape", () => {
|
||||||
UI.clickTool("rectangle");
|
UI.clickTool("rectangle");
|
||||||
|
|
||||||
mouse.down(10, 10);
|
mouse.down(10, 10);
|
||||||
mouse.up(10, 10);
|
mouse.up(10, 10);
|
||||||
togglePopover("Background");
|
togglePopover("Background");
|
||||||
|
@ -9,11 +9,12 @@ import { ExcalidrawTextElement } from "../element/types";
|
|||||||
import ExcalidrawApp from "../excalidraw-app";
|
import ExcalidrawApp from "../excalidraw-app";
|
||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
import { KEYS } from "../keys";
|
import { KEYS } from "../keys";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
File diff suppressed because one or more lines are too long
@ -61,7 +61,7 @@ describe("exportToSvg", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(svgElement.getAttribute("filter")).toMatchInlineSnapshot(
|
expect(svgElement.getAttribute("filter")).toMatchInlineSnapshot(
|
||||||
`"themeFilter"`,
|
'"_themeFilter_f32792"',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,11 +13,12 @@ import { reseed } from "../random";
|
|||||||
import { API } from "./helpers/api";
|
import { API } from "./helpers/api";
|
||||||
import { Keyboard, Pointer, UI } from "./helpers/ui";
|
import { Keyboard, Pointer, UI } from "./helpers/ui";
|
||||||
import { SHAPES } from "../shapes";
|
import { SHAPES } from "../shapes";
|
||||||
|
import { vi } from "vitest";
|
||||||
|
|
||||||
// Unmount ReactDOM from root
|
// Unmount ReactDOM from root
|
||||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||||
|
|
||||||
const renderScene = jest.spyOn(Renderer, "renderScene");
|
const renderScene = vi.spyOn(Renderer, "renderScene");
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
renderScene.mockClear();
|
renderScene.mockClear();
|
||||||
|
@ -160,7 +160,7 @@ export const throttleRAF = <T extends any[]>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ret = (...args: T) => {
|
const ret = (...args: T) => {
|
||||||
if (process.env.NODE_ENV === "test") {
|
if (import.meta.env.MODE === "test") {
|
||||||
fn(...args);
|
fn(...args);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -772,7 +772,7 @@ export const arrayToMapWithIndex = <T extends { id: string }>(
|
|||||||
return acc;
|
return acc;
|
||||||
}, new Map<string, [element: T, index: number]>());
|
}, new Map<string, [element: T, index: number]>());
|
||||||
|
|
||||||
export const isTestEnv = () => process.env.NODE_ENV === "test";
|
export const isTestEnv = () => import.meta.env.MODE === "test";
|
||||||
|
|
||||||
export const wrapEvent = <T extends Event>(name: EVENT, nativeEvent: T) => {
|
export const wrapEvent = <T extends Event>(name: EVENT, nativeEvent: T) => {
|
||||||
return new CustomEvent(name, {
|
return new CustomEvent(name, {
|
||||||
|
59
src/vite-env.d.ts
vendored
Normal file
59
src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
|
/// <reference types="vite-plugin-pwa/react" />
|
||||||
|
/// <reference types="vite-plugin-pwa/info" />
|
||||||
|
/// <reference types="vite-plugin-svgr/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
// The port to run the dev server
|
||||||
|
VITE_APP_PORT: string;
|
||||||
|
|
||||||
|
VITE_APP_BACKEND_V2_GET_URL: string;
|
||||||
|
VITE_APP_BACKEND_V2_POST_URL: string;
|
||||||
|
|
||||||
|
VITE_APP_LIBRARY_URL: string;
|
||||||
|
VITE_APP_LIBRARY_BACKEND: string;
|
||||||
|
|
||||||
|
// collaboration WebSocket server (https: string
|
||||||
|
VITE_APP_WS_SERVER_URL: string;
|
||||||
|
|
||||||
|
// set this only if using the collaboration workflow we use on excalidraw.com
|
||||||
|
VITE_APP_PORTAL_URL: string;
|
||||||
|
|
||||||
|
VITE_APP_FIREBASE_CONFIG: string;
|
||||||
|
|
||||||
|
// whether to enable Service Workers in development
|
||||||
|
VITE_APP_DEV_ENABLE_SW: string;
|
||||||
|
// whether to disable live reload / HMR. Usuaully what you want to do when
|
||||||
|
// debugging Service Workers.
|
||||||
|
VITE_APP_DEV_DISABLE_LIVE_RELOAD: string;
|
||||||
|
|
||||||
|
FAST_REFRESH: string;
|
||||||
|
|
||||||
|
// MATOMO
|
||||||
|
VITE_APP_MATOMO_URL: string;
|
||||||
|
VITE_APP_CDN_MATOMO_TRACKER_URL: string;
|
||||||
|
VITE_APP_MATOMO_SITE_ID: string;
|
||||||
|
|
||||||
|
//Debug flags
|
||||||
|
|
||||||
|
// To enable bounding box for text containers
|
||||||
|
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: string;
|
||||||
|
VITE_APP_DISABLE_SENTRY: string;
|
||||||
|
// Set this flag to false if you want to open the overlay by default
|
||||||
|
VITE_APP_COLLAPSE_OVERLAY: string;
|
||||||
|
// Enable eslint in dev server
|
||||||
|
VITE_APP_ENABLE_ESLINT: string;
|
||||||
|
|
||||||
|
VITE_PKG_NAME: string;
|
||||||
|
VITE_PKG_VERSION: string;
|
||||||
|
VITE_IS_EXCALIDRAW_NPM_PACKAGE: string;
|
||||||
|
|
||||||
|
VITE_WORKER_ID: string;
|
||||||
|
MODE: string;
|
||||||
|
DEV: string;
|
||||||
|
PROD: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"include": ["src/packages/excalidraw", "src/global.d.ts", "src/css.d.ts"],
|
"include": ["src/packages/excalidraw", "src/global.d.ts", "src/css.d.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"types": ["vite/client", "vite-plugin-svgr/client"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"emitDeclarationOnly": true,
|
"emitDeclarationOnly": true,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"module": "esnext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es6",
|
"target": "ESNext",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
@ -8,9 +8,9 @@
|
|||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
181
vite.config.ts
Normal file
181
vite.config.ts
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
import { defineConfig, loadEnv } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import svgrPlugin from "vite-plugin-svgr";
|
||||||
|
import { ViteEjsPlugin } from "vite-plugin-ejs";
|
||||||
|
import { VitePWA } from "vite-plugin-pwa";
|
||||||
|
import checker from "vite-plugin-checker";
|
||||||
|
|
||||||
|
// To load .env.local variables
|
||||||
|
const envVars = loadEnv("", process.cwd());
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
server: {
|
||||||
|
port: Number(envVars.VITE_APP_PORT || 3000),
|
||||||
|
// open the browser
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: "build",
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
// Creating separate chunk for locales except for en and percentages.json so they
|
||||||
|
// can be cached at runtime and not merged with
|
||||||
|
// app precache. en.json and percentages.json are needed for first load
|
||||||
|
// or fallback hence not clubbing with locales so first load followed by offline mode works fine. This is how CRA used to work too.
|
||||||
|
manualChunks(id) {
|
||||||
|
if (
|
||||||
|
id.includes("src/locales") &&
|
||||||
|
id.match(/en.json|percentages.json/) === null
|
||||||
|
) {
|
||||||
|
const index = id.indexOf("locales/");
|
||||||
|
// Taking the substring after "locales/"
|
||||||
|
return `locales/${id.substring(index + 8)}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourcemap: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
react(),
|
||||||
|
checker({
|
||||||
|
typescript: true,
|
||||||
|
eslint:
|
||||||
|
envVars.VITE_APP_ENABLE_ESLINT === "false"
|
||||||
|
? undefined
|
||||||
|
: { lintCommand: 'eslint "./src/**/*.{js,ts,tsx}"' },
|
||||||
|
overlay: {
|
||||||
|
initialIsOpen: envVars.VITE_APP_COLLAPSE_OVERLAY === "false",
|
||||||
|
badgeStyle: "margin-bottom: 4rem; margin-left: 1rem",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
svgrPlugin(),
|
||||||
|
ViteEjsPlugin(),
|
||||||
|
VitePWA({
|
||||||
|
devOptions: {
|
||||||
|
/* set this flag to true to enable in Development mode */
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
workbox: {
|
||||||
|
// Don't push fonts and locales to app precache
|
||||||
|
globIgnores: ["fonts.css", "**/locales/**"],
|
||||||
|
runtimeCaching: [
|
||||||
|
{
|
||||||
|
urlPattern: new RegExp("/.+.(ttf|woff2|otf)"),
|
||||||
|
handler: "CacheFirst",
|
||||||
|
options: {
|
||||||
|
cacheName: "fonts",
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 50,
|
||||||
|
maxAgeSeconds: 60 * 60 * 24 * 90, // <== 90 days
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: new RegExp("fonts.css"),
|
||||||
|
handler: "StaleWhileRevalidate",
|
||||||
|
options: {
|
||||||
|
cacheName: "fonts",
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: new RegExp("locales/[^/]+.js"),
|
||||||
|
handler: "CacheFirst",
|
||||||
|
options: {
|
||||||
|
cacheName: "locales",
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 50,
|
||||||
|
maxAgeSeconds: 60 * 60 * 24 * 30, // <== 30 days
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
manifest: {
|
||||||
|
short_name: "Excalidraw",
|
||||||
|
name: "Excalidraw",
|
||||||
|
description:
|
||||||
|
"Excalidraw is a whiteboard tool that lets you easily sketch diagrams that have a hand-drawn feel to them.",
|
||||||
|
icons: [
|
||||||
|
{
|
||||||
|
src: "logo-180x180.png",
|
||||||
|
sizes: "180x180",
|
||||||
|
type: "image/png",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "apple-touch-icon.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "256x256",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
start_url: "/",
|
||||||
|
display: "standalone",
|
||||||
|
theme_color: "#121212",
|
||||||
|
background_color: "#ffffff",
|
||||||
|
file_handlers: [
|
||||||
|
{
|
||||||
|
action: "/",
|
||||||
|
accept: {
|
||||||
|
"application/vnd.excalidraw+json": [".excalidraw"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
share_target: {
|
||||||
|
action: "/web-share-target",
|
||||||
|
method: "POST",
|
||||||
|
enctype: "multipart/form-data",
|
||||||
|
params: {
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
name: "file",
|
||||||
|
accept: [
|
||||||
|
"application/vnd.excalidraw+json",
|
||||||
|
"application/json",
|
||||||
|
".excalidraw",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
screenshots: [
|
||||||
|
{
|
||||||
|
src: "/screenshots/virtual-whiteboard.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/screenshots/wireframe.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/screenshots/illustration.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/screenshots/shapes.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/screenshots/collaboration.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "/screenshots/export.png",
|
||||||
|
type: "image/png",
|
||||||
|
sizes: "462x945",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
publicDir: "./public",
|
||||||
|
});
|
9
vitest.config.ts
Normal file
9
vitest.config.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { defineConfig } from "vitest/config";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
setupFiles: ["./src/setupTests.ts"],
|
||||||
|
globals: true,
|
||||||
|
environment: "jsdom",
|
||||||
|
},
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user