mirror of
https://github.com/dream-num/univer.git
synced 2026-08-30 17:21:11 +08:00
chore: migrate to eslint 8+ (#1235)
* chore: migrate to eslint 8+ * chore: remove unused deps * fix: fix type check * chore(eslint): add missing rules
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
# Build
|
||||
dist
|
||||
lib
|
||||
local
|
||||
.turbo
|
||||
|
||||
# Coverage
|
||||
coverage-report/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
.cache/
|
||||
|
||||
# yarn v2
|
||||
.yarn
|
||||
|
||||
# Vite
|
||||
vite-env.d.ts
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
const { resolve } = require('node:path');
|
||||
const tsConfig = require('./tsconfig.json');
|
||||
|
||||
/**
|
||||
* @type {import('eslint').Linter.Config}
|
||||
*/
|
||||
const config = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
'prettier',
|
||||
'import',
|
||||
'import-newlines',
|
||||
'unused-imports',
|
||||
'simple-import-sort',
|
||||
'react',
|
||||
'header',
|
||||
],
|
||||
extends: [
|
||||
'airbnb-base', // https://www.npmjs.com/package/eslint-config-airbnb-base
|
||||
'airbnb-typescript/base', // https://www.npmjs.com/package/eslint-config-airbnb-typescript
|
||||
// "plugin:@typescript-eslint/recommended",// no need https://typescript-eslint.io/
|
||||
'plugin:prettier/recommended',
|
||||
'prettier',
|
||||
],
|
||||
rules: {
|
||||
'header/header': [
|
||||
2,
|
||||
'block',
|
||||
[
|
||||
'*',
|
||||
' * Copyright 2023-present DreamNum Inc.',
|
||||
' *',
|
||||
' * Licensed under the Apache License, Version 2.0 (the "License");',
|
||||
' * you may not use this file except in compliance with the License.',
|
||||
' * You may obtain a copy of the License at',
|
||||
' *',
|
||||
' * http://www.apache.org/licenses/LICENSE-2.0',
|
||||
' *',
|
||||
' * Unless required by applicable law or agreed to in writing, software',
|
||||
' * distributed under the License is distributed on an "AS IS" BASIS,',
|
||||
' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
|
||||
' * See the License for the specific language governing permissions and',
|
||||
' * limitations under the License.',
|
||||
' ',
|
||||
],
|
||||
2,
|
||||
],
|
||||
'no-cond-assign': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: true,
|
||||
},
|
||||
],
|
||||
// turn on errors for missing imports
|
||||
'import/no-unresolved': [
|
||||
2,
|
||||
{
|
||||
ignore: ['\\.less$', '^@'],
|
||||
},
|
||||
],
|
||||
'import/no-cycle': 'warn',
|
||||
'no-param-reassign': 'off',
|
||||
'no-bitwise': 'off',
|
||||
'default-case': 'off',
|
||||
'class-methods-use-this': 'off',
|
||||
'consistent-return': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'max-classes-per-file': 'off',
|
||||
'prefer-destructuring': 'off',
|
||||
'no-plusplus': 'off',
|
||||
'no-return-assign': 'off',
|
||||
'no-continue': 'off',
|
||||
'no-loop-func': 'off',
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'warn',
|
||||
// Interfaces' names should start with a capital 'I'.
|
||||
{
|
||||
selector: 'interface',
|
||||
format: ['PascalCase'],
|
||||
custom: {
|
||||
regex: '^I[A-Z0-9]',
|
||||
match: true,
|
||||
},
|
||||
},
|
||||
// Private fields of a class should start with an underscore '_'.
|
||||
{
|
||||
selector: ['classMethod', 'classProperty'],
|
||||
modifiers: ['private'],
|
||||
format: ['camelCase'],
|
||||
leadingUnderscore: 'require',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/no-shadow': 'off',
|
||||
'@typescript-eslint/no-loop-func': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'off',
|
||||
'guard-for-in': 'off',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-lonely-if': 'off',
|
||||
radix: 'off',
|
||||
'no-nested-ternary': 'off',
|
||||
'no-new': 'off',
|
||||
'no-unused-expressions': 'off',
|
||||
'no-console': ['error', { allow: ["warn", "error"] }],
|
||||
'no-multi-assign': 'off',
|
||||
'no-restricted-properties': 'off',
|
||||
'no-control-regex': 'off',
|
||||
'no-await-in-loop': 'off',
|
||||
'@typescript-eslint/array-type': [
|
||||
'error',
|
||||
{
|
||||
default: 'array-simple',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/explicit-member-accessibility': [
|
||||
'error',
|
||||
{
|
||||
accessibility: 'no-public',
|
||||
},
|
||||
],
|
||||
'spaced-comment': 'off',
|
||||
eqeqeq: [
|
||||
'error',
|
||||
'always',
|
||||
{
|
||||
null: 'ignore',
|
||||
},
|
||||
],
|
||||
// eslint-plugin-unused-imports
|
||||
'@typescript-eslint/consistent-type-assertions': 'off',
|
||||
'@typescript-eslint/default-param-last': 'off',
|
||||
'@typescript-eslint/lines-between-class-members': [
|
||||
'warn',
|
||||
{ enforce: [{ blankLine: 'always', prev: '*', next: 'method' }] },
|
||||
{ exceptAfterSingleLine: true },
|
||||
],
|
||||
// '@typescript-eslint/member-ordering': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/no-redeclare': 'off', // dependency interface and dependency token share the same name
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
'grouped-accessor-pairs': 'off',
|
||||
'no-magic-numbers': ['warn', { ignore: [0, 1, -1, 2] }],
|
||||
'no-unsafe-optional-chaining': 'off',
|
||||
'prefer-regex-literals': 'off',
|
||||
'simple-import-sort/exports': 'error',
|
||||
'simple-import-sort/imports': 'error',
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'@typescript-eslint/consistent-type-definitions': ['warn'],
|
||||
'@typescript-eslint/consistent-type-imports': ['warn'],
|
||||
'react/self-closing-comp': [
|
||||
'error',
|
||||
{
|
||||
component: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
// https://www.npmjs.com/package/eslint-import-resolver-typescript
|
||||
settings: {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
||||
},
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
node: {
|
||||
extensions: ['.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
overrides: [
|
||||
...tsConfig.references.map(({ path }) => ({
|
||||
files: [`${path}/src/**/*.ts`, `${path}/src/**/*.tsx`],
|
||||
parserOptions: {
|
||||
project: resolve(__dirname, './tsconfig.eslint.json'),
|
||||
},
|
||||
})),
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
@@ -13,4 +13,4 @@ close #
|
||||
|
||||
<!-- A description of the proposed changes. -->
|
||||
|
||||
<!-- How to test them. -->
|
||||
<!-- How to test them. -->
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
name: 📌 Check PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
pull-requests: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
subjectPattern: ^(?![A-Z]).+$
|
||||
validate:
|
||||
name: validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
subjectPattern: ^(?![A-Z]).+$
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
name: 🌍 Issues Translator
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: usthe/issues-translate-action@v2.7
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: usthe/issues-translate-action@v2.7
|
||||
|
||||
@@ -2,7 +2,7 @@ name: 📤 Preview Deploy
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['📦 Build']
|
||||
workflows: [📦 Build]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
@@ -133,7 +133,7 @@ jobs:
|
||||
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
||||
vercel-org-id: ${{ secrets.ORG_ID}}
|
||||
vercel-project-id: ${{ secrets.PROJECT_ID}}
|
||||
vercel-args: '--prod'
|
||||
vercel-args: --prod
|
||||
|
||||
- name: 🚀 Deploy to Vercel (demo)
|
||||
uses: amondnet/vercel-action@v25
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "es5",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
+25
-9
@@ -1,5 +1,21 @@
|
||||
import { type StorybookConfig } from 'storybook';
|
||||
import { join, dirname } from 'path';
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { dirname, join } from 'node:path';
|
||||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
@@ -14,22 +30,22 @@ const config: StorybookConfig = {
|
||||
{
|
||||
directory: '../packages/design/src/**',
|
||||
files: '*.stories.@(js|jsx|mjs|ts|tsx)',
|
||||
titlePrefix: 'Design'
|
||||
titlePrefix: 'Design',
|
||||
},
|
||||
{
|
||||
directory: '../packages/ui/src/**',
|
||||
files: '*.stories.@(js|jsx|mjs|ts|tsx)',
|
||||
titlePrefix: 'Base UI'
|
||||
titlePrefix: 'Base UI',
|
||||
},
|
||||
{
|
||||
directory: '../packages/sheets-numfmt/src/**',
|
||||
files: '*.stories.@(js|jsx|mjs|ts|tsx)',
|
||||
titlePrefix: 'Numfmt'
|
||||
titlePrefix: 'Numfmt',
|
||||
},
|
||||
{
|
||||
directory: '../packages/find-replace/src/**',
|
||||
files: '*.stories.@(js|jsx|mjs|ts|tsx)',
|
||||
titlePrefix: 'Find & Replace'
|
||||
titlePrefix: 'Find & Replace',
|
||||
},
|
||||
],
|
||||
addons: [
|
||||
@@ -39,18 +55,18 @@ const config: StorybookConfig = {
|
||||
getAbsolutePath('@storybook/addon-docs'),
|
||||
],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/react-vite'),
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
docs: {
|
||||
autodocs: true,
|
||||
},
|
||||
async viteFinal(config, options) {
|
||||
async viteFinal(config) {
|
||||
config.css = {
|
||||
modules: {
|
||||
localsConvention: 'camelCaseOnly',
|
||||
generateScopedName: 'univer-[local]',
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return config;
|
||||
|
||||
+21
-5
@@ -1,11 +1,27 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { type Preview } from '@storybook/react';
|
||||
import type { Preview } from '@storybook/react';
|
||||
import { defaultTheme, greenTheme, themeInstance } from '@univerjs/design';
|
||||
|
||||
export const themes: Record<string, Record<string, string>> = {
|
||||
default: defaultTheme,
|
||||
green: greenTheme
|
||||
}
|
||||
green: greenTheme,
|
||||
};
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
@@ -36,8 +52,8 @@ const preview: Preview = {
|
||||
|
||||
return (
|
||||
<Story />
|
||||
)
|
||||
}]
|
||||
);
|
||||
}],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
|
||||
Vendored
+43
-8
@@ -1,12 +1,4 @@
|
||||
|
||||
{
|
||||
|
||||
"editor.codeActionsOnSave": {
|
||||
"mode": "explicit",
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
"editor.formatOnSave": false,
|
||||
"javascript.preferences.importModuleSpecifier": "relative",
|
||||
"typescript.preferences.importModuleSpecifier": "relative",
|
||||
"commentTranslate.targetLanguage": "zh-CN",
|
||||
@@ -90,4 +82,47 @@
|
||||
"Xinwei"
|
||||
],
|
||||
"vsicons.presets.angular": false,
|
||||
|
||||
// Enable the ESlint flat config support
|
||||
"eslint.experimental.useFlatConfig": true,
|
||||
|
||||
// Disable the default formatter, use eslint instead
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
|
||||
// Auto fix
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "never",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
|
||||
// Silent the stylistic rules in you IDE, but still auto fix them
|
||||
"eslint.rules.customizations": [
|
||||
{ "rule": "style/*", "severity": "off" },
|
||||
{ "rule": "format/*", "severity": "off" },
|
||||
{ "rule": "*-indent", "severity": "off" },
|
||||
{ "rule": "*-spacing", "severity": "off" },
|
||||
{ "rule": "*-spaces", "severity": "off" },
|
||||
{ "rule": "*-order", "severity": "off" },
|
||||
{ "rule": "*-dangle", "severity": "off" },
|
||||
{ "rule": "*-newline", "severity": "off" },
|
||||
{ "rule": "*quotes", "severity": "off" },
|
||||
{ "rule": "*semi", "severity": "off" }
|
||||
],
|
||||
|
||||
// Enable eslint for all supported languages
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"vue",
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"yaml",
|
||||
"toml"
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -171,4 +171,4 @@ npm create @univerjs/cli init <project-name>
|
||||
|
||||
## Links
|
||||
|
||||
* [How to Contribute to Facade API](./packages/facade/docs/CONTRIBUTING.md)
|
||||
* [How to Contribute to Facade API](./packages/facade/docs/CONTRIBUTING.md)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
@@ -57,7 +57,6 @@ Highlights of Univer:
|
||||
| [Multi Instances](https://univer.work/playground/?title=Multi%20Instance)<br>Run multi Univer instances on the same page |  |
|
||||
| [Uniscript](https://univer.work/playground/?title=Uniscript)<br>Use Uniscript to automate your workflow |  |
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
We recommend to import Univer as a npm package. Please checkout the [Quick Start](https://univer.work/en-us/guides/quick-start/) section on the documentation website. We also have an [online playground](https://univer.work/playground/) which can help you preview Univer without setting up the development environment.
|
||||
|
||||
+12
-12
@@ -1,13 +1,13 @@
|
||||
coverage:
|
||||
patch: false
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# basic
|
||||
target: auto
|
||||
threshold: 0
|
||||
base: auto
|
||||
# advanced settings
|
||||
if_ci_failed: error
|
||||
informational: false
|
||||
only_pulls: false
|
||||
patch: false
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# basic
|
||||
target: auto
|
||||
threshold: 0
|
||||
base: auto
|
||||
# advanced settings
|
||||
if_ci_failed: error
|
||||
informational: false
|
||||
only_pulls: false
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@univerjs/infra",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": true,
|
||||
"description": "Some infrastructures for univerjs",
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"homepage": "https://github.com/dream-num/univer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dream-num/univer.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
"./tsconfigs/*.json": "./tsconfigs/*",
|
||||
"./tsconfigs/*": "./tsconfigs/*.json"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"jsx": "react",
|
||||
"lib": ["ESNext", "DOM", "DOM.Iterable", "WebWorker"],
|
||||
"useDefineForClassFields": true,
|
||||
|
||||
"experimentalDecorators": true,
|
||||
"module": "ESNext",
|
||||
|
||||
"moduleResolution": "bundler",
|
||||
|
||||
"resolveJsonModule": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
|
||||
"strict": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noEmit": true,
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
+338
-323
@@ -1,437 +1,452 @@
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { expect, type Page, test } from '@playwright/test';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('https://demo.playwright.dev/todomvc');
|
||||
await page.goto('https://demo.playwright.dev/todomvc');
|
||||
});
|
||||
|
||||
const TODO_ITEMS = [
|
||||
'buy some cheese',
|
||||
'feed the cat',
|
||||
'book a doctors appointment'
|
||||
'buy some cheese',
|
||||
'feed the cat',
|
||||
'book a doctors appointment',
|
||||
];
|
||||
|
||||
test.describe('New Todo', () => {
|
||||
test('should allow me to add todo items', async ({ page }) => {
|
||||
test('should allow me to add todo items', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
// Create 1st todo.
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
// Create 1st todo.
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
|
||||
// Make sure the list only has one todo item.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText([
|
||||
TODO_ITEMS[0]
|
||||
]);
|
||||
// Make sure the list only has one todo item.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
]);
|
||||
|
||||
// Create 2nd todo.
|
||||
await newTodo.fill(TODO_ITEMS[1]);
|
||||
await newTodo.press('Enter');
|
||||
// Create 2nd todo.
|
||||
await newTodo.fill(TODO_ITEMS[1]);
|
||||
await newTodo.press('Enter');
|
||||
|
||||
// Make sure the list now has two todo items.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
TODO_ITEMS[1]
|
||||
]);
|
||||
// Make sure the list now has two todo items.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
TODO_ITEMS[1],
|
||||
]);
|
||||
|
||||
await checkNumberOfTodosInLocalStorage(page, 2);
|
||||
});
|
||||
await checkNumberOfTodosInLocalStorage(page, 2);
|
||||
});
|
||||
|
||||
test('should clear text input field when an item is added', async ({ page }) => {
|
||||
test('should clear text input field when an item is added', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
// Create one todo item.
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
// Create one todo item.
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
|
||||
// Check that input is empty.
|
||||
await expect(newTodo).toBeEmpty();
|
||||
await checkNumberOfTodosInLocalStorage(page, 1);
|
||||
});
|
||||
// Check that input is empty.
|
||||
await expect(newTodo).toBeEmpty();
|
||||
await checkNumberOfTodosInLocalStorage(page, 1);
|
||||
});
|
||||
|
||||
test('should append new items to the bottom of the list', async ({ page }) => {
|
||||
test('should append new items to the bottom of the list', async ({ page }) => {
|
||||
// Create 3 items.
|
||||
await createDefaultTodos(page);
|
||||
await createDefaultTodos(page);
|
||||
|
||||
// create a todo count locator
|
||||
const todoCount = page.getByTestId('todo-count')
|
||||
|
||||
// Check test using different methods.
|
||||
await expect(page.getByText('3 items left')).toBeVisible();
|
||||
await expect(todoCount).toHaveText('3 items left');
|
||||
await expect(todoCount).toContainText('3');
|
||||
await expect(todoCount).toHaveText(/3/);
|
||||
// create a todo count locator
|
||||
const todoCount = page.getByTestId('todo-count');
|
||||
|
||||
// Check all items in one call.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
// Check test using different methods.
|
||||
await expect(page.getByText('3 items left')).toBeVisible();
|
||||
await expect(todoCount).toHaveText('3 items left');
|
||||
await expect(todoCount).toContainText('3');
|
||||
await expect(todoCount).toHaveText(/3/);
|
||||
|
||||
// Check all items in one call.
|
||||
await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Mark all as completed', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
test.afterEach(async ({ page }) => {
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
|
||||
test('should allow me to mark all items as completed', async ({ page }) => {
|
||||
test('should allow me to mark all items as completed', async ({ page }) => {
|
||||
// Complete all todos.
|
||||
await page.getByLabel('Mark all as complete').check();
|
||||
await page.getByLabel('Mark all as complete').check();
|
||||
|
||||
// Ensure all todos have 'completed' class.
|
||||
await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']);
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
});
|
||||
// Ensure all todos have 'completed' class.
|
||||
await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']);
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
});
|
||||
|
||||
test('should allow me to clear the complete state of all items', async ({ page }) => {
|
||||
const toggleAll = page.getByLabel('Mark all as complete');
|
||||
// Check and then immediately uncheck.
|
||||
await toggleAll.check();
|
||||
await toggleAll.uncheck();
|
||||
test('should allow me to clear the complete state of all items', async ({ page }) => {
|
||||
const toggleAll = page.getByLabel('Mark all as complete');
|
||||
// Check and then immediately uncheck.
|
||||
await toggleAll.check();
|
||||
await toggleAll.uncheck();
|
||||
|
||||
// Should be no completed classes.
|
||||
await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']);
|
||||
});
|
||||
// Should be no completed classes.
|
||||
await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']);
|
||||
});
|
||||
|
||||
test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => {
|
||||
const toggleAll = page.getByLabel('Mark all as complete');
|
||||
await toggleAll.check();
|
||||
await expect(toggleAll).toBeChecked();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => {
|
||||
const toggleAll = page.getByLabel('Mark all as complete');
|
||||
await toggleAll.check();
|
||||
await expect(toggleAll).toBeChecked();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
|
||||
// Uncheck first todo.
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
await firstTodo.getByRole('checkbox').uncheck();
|
||||
// Uncheck first todo.
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
await firstTodo.getByRole('checkbox').uncheck();
|
||||
|
||||
// Reuse toggleAll locator and make sure its not checked.
|
||||
await expect(toggleAll).not.toBeChecked();
|
||||
// Reuse toggleAll locator and make sure its not checked.
|
||||
await expect(toggleAll).not.toBeChecked();
|
||||
|
||||
await firstTodo.getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
await firstTodo.getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 3);
|
||||
|
||||
// Assert the toggle all is checked again.
|
||||
await expect(toggleAll).toBeChecked();
|
||||
});
|
||||
// Assert the toggle all is checked again.
|
||||
await expect(toggleAll).toBeChecked();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Item', () => {
|
||||
|
||||
test('should allow me to mark items as complete', async ({ page }) => {
|
||||
test('should allow me to mark items as complete', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
// Create two items.
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
// Create two items.
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
|
||||
// Check first item.
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
await firstTodo.getByRole('checkbox').check();
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
// Check first item.
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
await firstTodo.getByRole('checkbox').check();
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
|
||||
// Check second item.
|
||||
const secondTodo = page.getByTestId('todo-item').nth(1);
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await secondTodo.getByRole('checkbox').check();
|
||||
// Check second item.
|
||||
const secondTodo = page.getByTestId('todo-item').nth(1);
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await secondTodo.getByRole('checkbox').check();
|
||||
|
||||
// Assert completed class.
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
await expect(secondTodo).toHaveClass('completed');
|
||||
});
|
||||
// Assert completed class.
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
await expect(secondTodo).toHaveClass('completed');
|
||||
});
|
||||
|
||||
test('should allow me to un-mark items as complete', async ({ page }) => {
|
||||
test('should allow me to un-mark items as complete', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
// Create two items.
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
// Create two items.
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
const secondTodo = page.getByTestId('todo-item').nth(1);
|
||||
const firstTodoCheckbox = firstTodo.getByRole('checkbox');
|
||||
const firstTodo = page.getByTestId('todo-item').nth(0);
|
||||
const secondTodo = page.getByTestId('todo-item').nth(1);
|
||||
const firstTodoCheckbox = firstTodo.getByRole('checkbox');
|
||||
|
||||
await firstTodoCheckbox.check();
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await firstTodoCheckbox.check();
|
||||
await expect(firstTodo).toHaveClass('completed');
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
|
||||
await firstTodoCheckbox.uncheck();
|
||||
await expect(firstTodo).not.toHaveClass('completed');
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 0);
|
||||
});
|
||||
await firstTodoCheckbox.uncheck();
|
||||
await expect(firstTodo).not.toHaveClass('completed');
|
||||
await expect(secondTodo).not.toHaveClass('completed');
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 0);
|
||||
});
|
||||
|
||||
test('should allow me to edit an item', async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
test('should allow me to edit an item', async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
const secondTodo = todoItems.nth(1);
|
||||
await secondTodo.dblclick();
|
||||
await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]);
|
||||
await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
const secondTodo = todoItems.nth(1);
|
||||
await secondTodo.dblclick();
|
||||
await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]);
|
||||
await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
|
||||
// Explicitly assert the new text value.
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2]
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
// Explicitly assert the new text value.
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Editing', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
|
||||
test('should hide other controls when editing', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item').nth(1);
|
||||
await todoItem.dblclick();
|
||||
await expect(todoItem.getByRole('checkbox')).not.toBeVisible();
|
||||
await expect(todoItem.locator('label', {
|
||||
hasText: TODO_ITEMS[1],
|
||||
})).not.toBeVisible();
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
test('should hide other controls when editing', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item').nth(1);
|
||||
await todoItem.dblclick();
|
||||
await expect(todoItem.getByRole('checkbox')).not.toBeVisible();
|
||||
await expect(todoItem.locator('label', {
|
||||
hasText: TODO_ITEMS[1],
|
||||
})).not.toBeVisible();
|
||||
await checkNumberOfTodosInLocalStorage(page, 3);
|
||||
});
|
||||
|
||||
test('should save edits on blur', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur');
|
||||
test('should save edits on blur', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur');
|
||||
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
|
||||
test('should trim entered text', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages ');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
test('should trim entered text', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages ');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
'buy some sausages',
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
await checkTodosInLocalStorage(page, 'buy some sausages');
|
||||
});
|
||||
|
||||
test('should remove the item if an empty text string was entered', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
test('should remove the item if an empty text string was entered', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter');
|
||||
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
});
|
||||
await expect(todoItems).toHaveText([
|
||||
TODO_ITEMS[0],
|
||||
TODO_ITEMS[2],
|
||||
]);
|
||||
});
|
||||
|
||||
test('should cancel edits on escape', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape');
|
||||
await expect(todoItems).toHaveText(TODO_ITEMS);
|
||||
});
|
||||
test('should cancel edits on escape', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).dblclick();
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages');
|
||||
await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape');
|
||||
await expect(todoItems).toHaveText(TODO_ITEMS);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Counter', () => {
|
||||
test('should display the current number of todo items', async ({ page }) => {
|
||||
test('should display the current number of todo items', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
// create a todo count locator
|
||||
const todoCount = page.getByTestId('todo-count')
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
// create a todo count locator
|
||||
const todoCount = page.getByTestId('todo-count');
|
||||
|
||||
await expect(todoCount).toContainText('1');
|
||||
await newTodo.fill(TODO_ITEMS[0]);
|
||||
await newTodo.press('Enter');
|
||||
|
||||
await newTodo.fill(TODO_ITEMS[1]);
|
||||
await newTodo.press('Enter');
|
||||
await expect(todoCount).toContainText('2');
|
||||
await expect(todoCount).toContainText('1');
|
||||
|
||||
await checkNumberOfTodosInLocalStorage(page, 2);
|
||||
});
|
||||
await newTodo.fill(TODO_ITEMS[1]);
|
||||
await newTodo.press('Enter');
|
||||
await expect(todoCount).toContainText('2');
|
||||
|
||||
await checkNumberOfTodosInLocalStorage(page, 2);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Clear completed button', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
});
|
||||
|
||||
test('should display the correct text', async ({ page }) => {
|
||||
await page.locator('.todo-list li .toggle').first().check();
|
||||
await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible();
|
||||
});
|
||||
test('should display the correct text', async ({ page }) => {
|
||||
await page.locator('.todo-list li .toggle').first().check();
|
||||
await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should remove completed items when clicked', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).getByRole('checkbox').check();
|
||||
await page.getByRole('button', { name: 'Clear completed' }).click();
|
||||
await expect(todoItems).toHaveCount(2);
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]);
|
||||
});
|
||||
test('should remove completed items when clicked', async ({ page }) => {
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
await todoItems.nth(1).getByRole('checkbox').check();
|
||||
await page.getByRole('button', { name: 'Clear completed' }).click();
|
||||
await expect(todoItems).toHaveCount(2);
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]);
|
||||
});
|
||||
|
||||
test('should be hidden when there are no items that are completed', async ({ page }) => {
|
||||
await page.locator('.todo-list li .toggle').first().check();
|
||||
await page.getByRole('button', { name: 'Clear completed' }).click();
|
||||
await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden();
|
||||
});
|
||||
test('should be hidden when there are no items that are completed', async ({ page }) => {
|
||||
await page.locator('.todo-list li .toggle').first().check();
|
||||
await page.getByRole('button', { name: 'Clear completed' }).click();
|
||||
await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Persistence', () => {
|
||||
test('should persist its data', async ({ page }) => {
|
||||
test('should persist its data', async ({ page }) => {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
for (const item of TODO_ITEMS.slice(0, 2)) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
const firstTodoCheck = todoItems.nth(0).getByRole('checkbox');
|
||||
await firstTodoCheck.check();
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]);
|
||||
await expect(firstTodoCheck).toBeChecked();
|
||||
await expect(todoItems).toHaveClass(['completed', '']);
|
||||
const todoItems = page.getByTestId('todo-item');
|
||||
const firstTodoCheck = todoItems.nth(0).getByRole('checkbox');
|
||||
await firstTodoCheck.check();
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]);
|
||||
await expect(firstTodoCheck).toBeChecked();
|
||||
await expect(todoItems).toHaveClass(['completed', '']);
|
||||
|
||||
// Ensure there is 1 completed item.
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
// Ensure there is 1 completed item.
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
|
||||
// Now reload.
|
||||
await page.reload();
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]);
|
||||
await expect(firstTodoCheck).toBeChecked();
|
||||
await expect(todoItems).toHaveClass(['completed', '']);
|
||||
});
|
||||
// Now reload.
|
||||
await page.reload();
|
||||
await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]);
|
||||
await expect(firstTodoCheck).toBeChecked();
|
||||
await expect(todoItems).toHaveClass(['completed', '']);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Routing', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
// make sure the app had a chance to save updated todos in storage
|
||||
// before navigating to a new view, otherwise the items can get lost :(
|
||||
// in some frameworks like Durandal
|
||||
await checkTodosInLocalStorage(page, TODO_ITEMS[0]);
|
||||
});
|
||||
|
||||
test('should allow me to display active items', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item');
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
await expect(todoItem).toHaveCount(2);
|
||||
await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]);
|
||||
});
|
||||
|
||||
test('should respect the back button', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item');
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
|
||||
await test.step('Showing all items', async () => {
|
||||
await page.getByRole('link', { name: 'All' }).click();
|
||||
await expect(todoItem).toHaveCount(3);
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await createDefaultTodos(page);
|
||||
// make sure the app had a chance to save updated todos in storage
|
||||
// before navigating to a new view, otherwise the items can get lost :(
|
||||
// in some frameworks like Durandal
|
||||
await checkTodosInLocalStorage(page, TODO_ITEMS[0]);
|
||||
});
|
||||
|
||||
await test.step('Showing active items', async () => {
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
test('should allow me to display active items', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item');
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
await expect(todoItem).toHaveCount(2);
|
||||
await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]);
|
||||
});
|
||||
|
||||
await test.step('Showing completed items', async () => {
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
test('should respect the back button', async ({ page }) => {
|
||||
const todoItem = page.getByTestId('todo-item');
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
|
||||
await test.step('Showing all items', async () => {
|
||||
await page.getByRole('link', { name: 'All' }).click();
|
||||
await expect(todoItem).toHaveCount(3);
|
||||
});
|
||||
|
||||
await test.step('Showing active items', async () => {
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
});
|
||||
|
||||
await test.step('Showing completed items', async () => {
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
});
|
||||
|
||||
await expect(todoItem).toHaveCount(1);
|
||||
await page.goBack();
|
||||
await expect(todoItem).toHaveCount(2);
|
||||
await page.goBack();
|
||||
await expect(todoItem).toHaveCount(3);
|
||||
});
|
||||
|
||||
await expect(todoItem).toHaveCount(1);
|
||||
await page.goBack();
|
||||
await expect(todoItem).toHaveCount(2);
|
||||
await page.goBack();
|
||||
await expect(todoItem).toHaveCount(3);
|
||||
});
|
||||
test('should allow me to display completed items', async ({ page }) => {
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
await expect(page.getByTestId('todo-item')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('should allow me to display completed items', async ({ page }) => {
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
await expect(page.getByTestId('todo-item')).toHaveCount(1);
|
||||
});
|
||||
test('should allow me to display all items', async ({ page }) => {
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
await page.getByRole('link', { name: 'All' }).click();
|
||||
await expect(page.getByTestId('todo-item')).toHaveCount(3);
|
||||
});
|
||||
|
||||
test('should allow me to display all items', async ({ page }) => {
|
||||
await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check();
|
||||
await checkNumberOfCompletedTodosInLocalStorage(page, 1);
|
||||
await page.getByRole('link', { name: 'Active' }).click();
|
||||
await page.getByRole('link', { name: 'Completed' }).click();
|
||||
await page.getByRole('link', { name: 'All' }).click();
|
||||
await expect(page.getByTestId('todo-item')).toHaveCount(3);
|
||||
});
|
||||
test('should highlight the currently applied filter', async ({ page }) => {
|
||||
await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected');
|
||||
|
||||
test('should highlight the currently applied filter', async ({ page }) => {
|
||||
await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected');
|
||||
|
||||
//create locators for active and completed links
|
||||
const activeLink = page.getByRole('link', { name: 'Active' });
|
||||
const completedLink = page.getByRole('link', { name: 'Completed' });
|
||||
await activeLink.click();
|
||||
//create locators for active and completed links
|
||||
const activeLink = page.getByRole('link', { name: 'Active' });
|
||||
const completedLink = page.getByRole('link', { name: 'Completed' });
|
||||
await activeLink.click();
|
||||
|
||||
// Page change - active items.
|
||||
await expect(activeLink).toHaveClass('selected');
|
||||
await completedLink.click();
|
||||
// Page change - active items.
|
||||
await expect(activeLink).toHaveClass('selected');
|
||||
await completedLink.click();
|
||||
|
||||
// Page change - completed items.
|
||||
await expect(completedLink).toHaveClass('selected');
|
||||
});
|
||||
// Page change - completed items.
|
||||
await expect(completedLink).toHaveClass('selected');
|
||||
});
|
||||
});
|
||||
|
||||
async function createDefaultTodos(page: Page) {
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
// create a new todo locator
|
||||
const newTodo = page.getByPlaceholder('What needs to be done?');
|
||||
|
||||
for (const item of TODO_ITEMS) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
for (const item of TODO_ITEMS) {
|
||||
await newTodo.fill(item);
|
||||
await newTodo.press('Enter');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) {
|
||||
return await page.waitForFunction(e => {
|
||||
return JSON.parse(localStorage['react-todos']).length === e;
|
||||
}, expected);
|
||||
return await page.waitForFunction((e) => {
|
||||
return JSON.parse(localStorage['react-todos']).length === e;
|
||||
}, expected);
|
||||
}
|
||||
|
||||
async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) {
|
||||
return await page.waitForFunction(e => {
|
||||
return JSON.parse(localStorage['react-todos']).filter((todo: any) => todo.completed).length === e;
|
||||
}, expected);
|
||||
return await page.waitForFunction((e) => {
|
||||
return JSON.parse(localStorage['react-todos']).filter((todo: any) => todo.completed).length === e;
|
||||
}, expected);
|
||||
}
|
||||
|
||||
async function checkTodosInLocalStorage(page: Page, title: string) {
|
||||
return await page.waitForFunction(t => {
|
||||
return JSON.parse(localStorage['react-todos']).map((todo: any) => todo.title).includes(t);
|
||||
}, title);
|
||||
return await page.waitForFunction((t) => {
|
||||
return JSON.parse(localStorage['react-todos']).map((todo: any) => todo.title).includes(t);
|
||||
}, title);
|
||||
}
|
||||
|
||||
+25
-9
@@ -1,18 +1,34 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
test('has title', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Playwright/);
|
||||
});
|
||||
|
||||
test('get started link', async ({ page }) => {
|
||||
await page.goto('https://playwright.dev/');
|
||||
await page.goto('https://playwright.dev/');
|
||||
|
||||
// Click the get started link.
|
||||
await page.getByRole('link', { name: 'Get started' }).click();
|
||||
// Click the get started link.
|
||||
await page.getByRole('link', { name: 'Get started' }).click();
|
||||
|
||||
// Expects page to have a heading with the name of Installation.
|
||||
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
|
||||
// Expects page to have a heading with the name of Installation.
|
||||
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
import antfu from '@antfu/eslint-config';
|
||||
import header from 'eslint-plugin-header';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
|
||||
export default antfu({
|
||||
stylistic: {
|
||||
indent: 4,
|
||||
semi: true,
|
||||
},
|
||||
react: true,
|
||||
yaml: {
|
||||
overrides: {
|
||||
'yaml/indent': ['error', 4, { indicatorValueIndent: 2 }],
|
||||
},
|
||||
},
|
||||
markdown: false,
|
||||
rules: {
|
||||
'import/no-cycle': 'error',
|
||||
'ts/no-explicit-any': 'warn',
|
||||
'style/brace-style': ['warn', '1tbs', { allowSingleLine: true }],
|
||||
'style/comma-dangle': ['error', {
|
||||
arrays: 'always-multiline',
|
||||
objects: 'always-multiline',
|
||||
imports: 'always-multiline',
|
||||
exports: 'always-multiline',
|
||||
enums: 'always-multiline',
|
||||
functions: 'never',
|
||||
}],
|
||||
'style/arrow-parens': ['error', 'always'],
|
||||
curly: ['error', 'multi-line'],
|
||||
'antfu/if-newline': 'off',
|
||||
'style/spaced-comment': 'off',
|
||||
'tunicorn/number-literal-case': 'off',
|
||||
'style/indent-binary-ops': 'off',
|
||||
|
||||
'style/indent': ['error', 4, {
|
||||
ObjectExpression: 'first',
|
||||
SwitchCase: 1,
|
||||
ignoreComments: true,
|
||||
}],
|
||||
'sort-imports': [
|
||||
'error',
|
||||
{
|
||||
allowSeparatedGroups: false,
|
||||
// ignoreCase: false,
|
||||
ignoreCase: true,
|
||||
ignoreDeclarationSort: true,
|
||||
ignoreMemberSort: false,
|
||||
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
|
||||
},
|
||||
],
|
||||
|
||||
// TODO: debatable rules
|
||||
'test/prefer-lowercase-title': 'off',
|
||||
'antfu/top-level-function': 'off',
|
||||
'style/operator-linebreak': 'off',
|
||||
'unicorn/no-new-array': 'off',
|
||||
'unicorn/prefer-includes': 'off',
|
||||
'prefer-arrow-callback': 'off',
|
||||
'no-restricted-globals': 'off',
|
||||
'unicorn/prefer-string-starts-ends-with': 'warn',
|
||||
|
||||
// TODO: just for compatibility with old code
|
||||
'unused-imports/no-unused-vars': 'warn',
|
||||
'style/jsx-closing-tag-location': 'warn',
|
||||
'ts/ban-types': 'warn',
|
||||
'unicorn/prefer-dom-node-text-content': 'warn',
|
||||
'unicorn/prefer-number-properties': 'warn',
|
||||
'no-prototype-builtins': 'warn',
|
||||
'style/no-tabs': 'warn',
|
||||
'style/quotes': ['warn', 'single', { avoidEscape: true }],
|
||||
|
||||
'react/display-name': 'off',
|
||||
'react-hooks/rules-of-hooks': 'off',
|
||||
'eslint-comments/no-unlimited-disable': 'off',
|
||||
'ts/prefer-ts-expect-error': 'off',
|
||||
'ts/ban-ts-comment': 'off',
|
||||
'ts/no-duplicate-enum-values': 'off',
|
||||
'no-cond-assign': 'warn',
|
||||
'antfu/consistent-list-newline': 'off',
|
||||
'ts/no-use-before-define': 'warn',
|
||||
'intunicorn/number-literal-case': 'off',
|
||||
'ts/no-redeclare': 'warn',
|
||||
'test/no-identical-title': 'warn',
|
||||
'ts/no-non-null-asserted-optional-chain': 'warn',
|
||||
'no-restricted-syntax': 'warn',
|
||||
'prefer-regex-literals': 'warn',
|
||||
'ts/no-this-alias': 'warn',
|
||||
'prefer-promise-reject-errors': 'warn',
|
||||
'no-new': 'warn',
|
||||
'unicorn/error-message': 'warn',
|
||||
'ts/prefer-literal-enum-member': 'warn',
|
||||
'style/jsx-curly-newline': ['warn', { multiline: 'forbid', singleline: 'forbid' }],
|
||||
'no-control-regex': 'warn',
|
||||
'style/jsx-wrap-multilines': 'warn',
|
||||
'ts/no-import-type-side-effects': 'warn',
|
||||
'style/quote-props': ['warn', 'as-needed'],
|
||||
'unicorn/number-literal-case': 'warn',
|
||||
'react/no-direct-mutation-state': 'warn',
|
||||
'style/jsx-curly-brace-presence': 'warn',
|
||||
'style/multiline-ternary': 'warn',
|
||||
'unicorn/prefer-type-error': 'warn',
|
||||
'accessor-pairs': 'warn',
|
||||
},
|
||||
}, {
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
ignores: ['**/*.d.ts', '**/vite.config.ts', 'playwright.config.ts'],
|
||||
plugins: {
|
||||
header,
|
||||
},
|
||||
rules: {
|
||||
'header/header': [
|
||||
2,
|
||||
'block',
|
||||
[
|
||||
'*',
|
||||
' * Copyright 2023-present DreamNum Inc.',
|
||||
' *',
|
||||
' * Licensed under the Apache License, Version 2.0 (the "License");',
|
||||
' * you may not use this file except in compliance with the License.',
|
||||
' * You may obtain a copy of the License at',
|
||||
' *',
|
||||
' * http://www.apache.org/licenses/LICENSE-2.0',
|
||||
' *',
|
||||
' * Unless required by applicable law or agreed to in writing, software',
|
||||
' * distributed under the License is distributed on an "AS IS" BASIS,',
|
||||
' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
|
||||
' * See the License for the specific language governing permissions and',
|
||||
' * limitations under the License.',
|
||||
' ',
|
||||
],
|
||||
2,
|
||||
],
|
||||
},
|
||||
}, {
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {
|
||||
'ts/naming-convention': [
|
||||
'warn',
|
||||
// Interfaces' names should start with a capital 'I'.
|
||||
{
|
||||
selector: 'interface',
|
||||
format: ['PascalCase'],
|
||||
custom: {
|
||||
regex: '^I[A-Z0-9]',
|
||||
match: true,
|
||||
},
|
||||
},
|
||||
// Private fields of a class should start with an underscore '_'.
|
||||
{
|
||||
selector: ['classMethod', 'classProperty'],
|
||||
modifiers: ['private'],
|
||||
format: ['camelCase'],
|
||||
leadingUnderscore: 'require',
|
||||
},
|
||||
],
|
||||
},
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
},
|
||||
});
|
||||
@@ -1,11 +1,12 @@
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import esbuild from 'esbuild';
|
||||
import cleanPlugin from 'esbuild-plugin-clean';
|
||||
import copyPlugin from 'esbuild-plugin-copy';
|
||||
import stylePlugin from 'esbuild-style-plugin';
|
||||
import minimist from 'minimist';
|
||||
import { execSync } from 'node:child_process';
|
||||
|
||||
const nodeModules = path.resolve(process.cwd(), './node_modules');
|
||||
|
||||
@@ -18,8 +19,8 @@ const monacoEditorEntryPoints = ['vs/language/typescript/ts.worker.js', 'vs/edit
|
||||
const gitCommitHash = execSync('git rev-parse --short HEAD').toString().trim();
|
||||
const gitRefName = execSync('git symbolic-ref -q --short HEAD || git describe --tags --exact-match').toString().trim();
|
||||
|
||||
const monacoBuildTask = () =>
|
||||
esbuild.build({
|
||||
function monacoBuildTask() {
|
||||
return esbuild.build({
|
||||
entryPoints: monacoEditorEntryPoints.map((entry) => `./node_modules/monaco-editor/esm/${entry}`),
|
||||
bundle: true,
|
||||
color: true,
|
||||
@@ -32,6 +33,7 @@ const monacoBuildTask = () =>
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const ctx = await esbuild[args.watch ? 'context' : 'build']({
|
||||
bundle: true,
|
||||
@@ -93,11 +95,13 @@ if (args.watch) {
|
||||
await monacoBuildTask();
|
||||
await ctx.watch();
|
||||
|
||||
const { host, port } = await ctx.serve({
|
||||
const { port } = await ctx.serve({
|
||||
servedir: './local',
|
||||
port: 3002,
|
||||
});
|
||||
|
||||
const url = `http://localhost:${port}`;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Local server: ${url}`);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "univer-examples",
|
||||
"private": true,
|
||||
"description": "Univer vanilla ts demo project",
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build:demo": "node ./esbuild.config.mjs",
|
||||
"dev:demo": "node ./esbuild.config.mjs --watch"
|
||||
"dev:demo": "node ./esbuild.config.mjs --watch",
|
||||
"lint:types": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
@@ -14,8 +15,8 @@
|
||||
"@univerjs/docs": "workspace:*",
|
||||
"@univerjs/docs-ui": "workspace:*",
|
||||
"@univerjs/engine-formula": "workspace:*",
|
||||
"@univerjs/find-replace": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
"@univerjs/find-replace": "workspace:*",
|
||||
"@univerjs/icons": "^0.1.26",
|
||||
"@univerjs/rpc": "workspace:*",
|
||||
"@univerjs/sheets": "workspace:*",
|
||||
@@ -39,6 +40,7 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.46",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"esbuild": "^0.19.10",
|
||||
"esbuild-plugin-clean": "^1.0.1",
|
||||
"esbuild-plugin-copy": "^2.1.1",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable node/prefer-global/process */
|
||||
import { LocaleType, Univer } from '@univerjs/core';
|
||||
import { defaultTheme } from '@univerjs/design';
|
||||
import { UniverDocsPlugin } from '@univerjs/docs';
|
||||
@@ -65,7 +66,6 @@ univer.createUniverDoc(DEFAULT_DOCUMENT_DATA_CN);
|
||||
|
||||
// use for console test
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
interface Window {
|
||||
univer?: Univer;
|
||||
}
|
||||
|
||||
+14
-5
@@ -22,9 +22,13 @@ import styles from './styles.module.less';
|
||||
// package info
|
||||
// eslint-disable-next-line no-console
|
||||
console.table({
|
||||
// eslint-disable-next-line node/prefer-global/process
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
// eslint-disable-next-line node/prefer-global/process
|
||||
GIT_COMMIT_HASH: process.env.GIT_COMMIT_HASH,
|
||||
// eslint-disable-next-line node/prefer-global/process
|
||||
GIT_REF_NAME: process.env.GIT_REF_NAME,
|
||||
// eslint-disable-next-line node/prefer-global/process
|
||||
BUILD_TIME: process.env.BUILD_TIME,
|
||||
});
|
||||
|
||||
@@ -33,23 +37,28 @@ function Examples() {
|
||||
<section className={styles.examples}>
|
||||
<a className={styles.btn} href="./sheets/">
|
||||
<span> Univer Sheets</span>
|
||||
<div className={styles.btnBg}>→</div>{' '}
|
||||
<div className={styles.btnBg}>→</div>
|
||||
{' '}
|
||||
</a>
|
||||
<a className={styles.btn} href="./docs/">
|
||||
<span> Univer Docs</span>
|
||||
<div className={styles.btnBg}>→</div>{' '}
|
||||
<div className={styles.btnBg}>→</div>
|
||||
{' '}
|
||||
</a>
|
||||
<a className={styles.btn} href="./slides/">
|
||||
<span> Univer Slides</span>
|
||||
<div className={styles.btnBg}>→</div>{' '}
|
||||
<div className={styles.btnBg}>→</div>
|
||||
{' '}
|
||||
</a>
|
||||
<a className={styles.btn} href="./sheets-multi/">
|
||||
<span> Univer Multi Instance</span>
|
||||
<div className={styles.btnBg}>→</div>{' '}
|
||||
<div className={styles.btnBg}>→</div>
|
||||
{' '}
|
||||
</a>
|
||||
<a className={styles.btn} href="./uniscript/">
|
||||
<span> Uniscript</span>
|
||||
<div className={styles.btnBg}>→</div>{' '}
|
||||
<div className={styles.btnBg}>→</div>
|
||||
{' '}
|
||||
</a>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -33,10 +33,10 @@ export const NotificationOperation: ICommand = {
|
||||
value.indexOf('Success') > -1
|
||||
? 'success'
|
||||
: value.indexOf('Info') > -1
|
||||
? 'info'
|
||||
: value.indexOf('Warning') > -1
|
||||
? 'warning'
|
||||
: 'error';
|
||||
? 'info'
|
||||
: value.indexOf('Warning') > -1
|
||||
? 'warning'
|
||||
: 'error';
|
||||
notificationService.show({
|
||||
type,
|
||||
content: value || 'Notification Content',
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable node/prefer-global/process */
|
||||
import type { ICommand, IStyleData, IWorkbookData } from '@univerjs/core';
|
||||
import { CommandType, ISnapshotPersistenceService, IUniverInstanceService, ObjectMatrix } from '@univerjs/core';
|
||||
import type { IAccessor } from '@wendellhu/redi';
|
||||
@@ -65,8 +66,9 @@ export const SaveSnapshotOptions: ICommand = {
|
||||
const sheet = snapshot.sheets[sheetId];
|
||||
snapshot.sheets = { [sheetId]: sheet };
|
||||
snapshot.sheetOrder = [sheetId];
|
||||
break;
|
||||
}
|
||||
// eslint-disable-next-line no-fallthrough
|
||||
|
||||
case 'workbook': {
|
||||
const text = JSON.stringify(filterStyle(snapshot), null, 2);
|
||||
// navigator.clipboard.writeText(text);
|
||||
|
||||
@@ -28,7 +28,7 @@ import { UniverSheetsNumfmtPlugin } from '@univerjs/sheets-numfmt';
|
||||
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
|
||||
import { UniverUIPlugin } from '@univerjs/ui';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { Mosaic, MosaicWindow } from 'react-mosaic-component';
|
||||
|
||||
import { DEFAULT_WORKBOOK_DATA_DEMO } from '../data';
|
||||
@@ -99,7 +99,7 @@ export const App = (
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(App, document.getElementById('container'));
|
||||
createRoot(document.getElementById('container')!).render(App);
|
||||
|
||||
factory('app-a')();
|
||||
factory('app-b')();
|
||||
|
||||
@@ -84,7 +84,6 @@ univer.registerPlugin(UniverSheetsFindPlugin);
|
||||
univer.createUniverSheet(DEFAULT_WORKBOOK_DATA_DEMO);
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
interface Window {
|
||||
univer?: Univer;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ univer.createUniverSlide(DEFAULT_SLIDE_DATA);
|
||||
|
||||
// use for console test
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
interface Window {
|
||||
univer?: Univer;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
const activeSheet = univerAPI.getCurrentSheet().getActiveSheet();
|
||||
|
||||
// Set A1:B2 to bold
|
||||
|
||||
@@ -69,7 +69,6 @@ univer.registerPlugin(UniverUniscriptPlugin, {
|
||||
univer.createUniverSheet(UNISCRIT_WORKBOOK_DATA_DEMO);
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
interface Window {
|
||||
univer?: Univer;
|
||||
}
|
||||
|
||||
+4
-10
@@ -1,14 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "local",
|
||||
"downlevelIteration": true,
|
||||
"esModuleInterop": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"types": ["esbuild-style-plugin"]
|
||||
"types": ["esbuild-style-plugin"],
|
||||
"outDir": "local"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "local"]
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
+18
-23
@@ -1,29 +1,31 @@
|
||||
{
|
||||
"name": "univer",
|
||||
"type": "module",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": true,
|
||||
"author": "DreamNum Inc. <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.17.0",
|
||||
"pnpm": "^8.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "husky install",
|
||||
"pre-commit": "lint-staged",
|
||||
"dev:demo": "turbo dev:demo",
|
||||
"dev:storybook": "storybook dev -p 6006 --no-open",
|
||||
"lint": "eslint --cache **/src/**/*.{tsx,ts}",
|
||||
"lint:fix": "eslint --cache **/src/**/*.{tsx,ts} --fix",
|
||||
"lint:style": "stylelint **/*.less",
|
||||
"lint:types": "tsc --noEmit -p tsconfig.eslint.json",
|
||||
"lint:types": "turbo lint:types",
|
||||
"test": "turbo test -- --passWithNoTests",
|
||||
"coverage": "turbo coverage -- --passWithNoTests",
|
||||
"build": "turbo build",
|
||||
"build:demo": "turbo build:demo",
|
||||
"build:storybook": "storybook build"
|
||||
"build:storybook": "storybook build",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.17.0",
|
||||
"pnpm": "^8.6.2"
|
||||
},
|
||||
"author": "DreamNum Inc. <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.6.3",
|
||||
"@commitlint/cli": "^18.4.3",
|
||||
"@commitlint/config-conventional": "^18.4.4",
|
||||
"@playwright/test": "^1.40.1",
|
||||
@@ -37,32 +39,25 @@
|
||||
"@storybook/testing-library": "^0.2.2",
|
||||
"@types/node": "^20.10.6",
|
||||
"@types/react": "^18.2.46",
|
||||
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
||||
"@typescript-eslint/parser": "^6.17.0",
|
||||
"@typescript-eslint/parser": "^6.19.1",
|
||||
"@univerjs/design": "workspace:*",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-header": "~3.1.1",
|
||||
"eslint-plugin-import-newlines": "^1.3.4",
|
||||
"eslint-plugin-prettier": "^5.1.2",
|
||||
"eslint-plugin-header": "^3.1.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-unused-imports": "^3.0.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.5",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^15.2.0",
|
||||
"prettier": "^3.1.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"storybook": "^7.6.7",
|
||||
"stylelint": "^15.11.0",
|
||||
"stylelint-config-clean-order": "^5.2.0",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-standard-less": "^2.0.0",
|
||||
"stylelint-config-standard": "^34.0.0",
|
||||
"stylelint": "^15.11.0",
|
||||
"stylelint-config-standard-less": "^2.0.0",
|
||||
"turbo": "^1.11.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
|
||||
+17
-15
@@ -1,9 +1,20 @@
|
||||
{
|
||||
"name": "@univerjs/core",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "Core library for Univer.",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"homepage": "https://github.com/dream-num/univer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dream-num/univer.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -24,28 +35,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"homepage": "https://github.com/dream-num/univer",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dream-num/univer.git"
|
||||
"peerDependencies": {
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wendellhu/redi": "^0.12.13",
|
||||
@@ -56,15 +61,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/numeral": "^2.0.5",
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import type { Ctor, Injector } from '@wendellhu/redi';
|
||||
|
||||
import type { Plugin, PluginCtor } from '../plugin/plugin';
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import type { IDisposable } from '@wendellhu/redi';
|
||||
import { Inject, Injector } from '@wendellhu/redi';
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import { Injector } from '@wendellhu/redi';
|
||||
|
||||
import type { DocumentDataModel } from '../docs/data-model/document-data-model';
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
export function throttle<T extends (...args: any[]) => any>(fn: T, wait: number = 16): T {
|
||||
let lastTime = 0;
|
||||
let timer: number | null = null;
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import type { Ctor, Injector } from '@wendellhu/redi';
|
||||
|
||||
export type PluginCtor<T extends Plugin> = Ctor<T> & { type: PluginType };
|
||||
@@ -42,7 +40,6 @@ export abstract class Plugin {
|
||||
this._name = name;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
onStarting(injector: Injector): void {}
|
||||
|
||||
onReady(): void {}
|
||||
|
||||
@@ -161,7 +161,6 @@ export const ICommandService = createIdentifier<ICommandService>('anywhere.comma
|
||||
* The registry of commands.
|
||||
*/
|
||||
export class CommandRegistry {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private readonly _commands = new Map<string, ICommand>();
|
||||
|
||||
registerCommand(command: ICommand): IDisposable {
|
||||
@@ -385,7 +384,7 @@ export class CommandService implements ICommandService {
|
||||
try {
|
||||
result = this._injector.invoke(command.handler, params) as R;
|
||||
if (result instanceof Promise) {
|
||||
throw new Error('[CommandService]: Command handler should not return a promise.');
|
||||
throw new TypeError('[CommandService]: Command handler should not return a promise.');
|
||||
}
|
||||
|
||||
this._commandExecutingLevel--;
|
||||
@@ -443,7 +442,7 @@ class MultiCommand implements IMultiCommand {
|
||||
for (const item of this._implementations) {
|
||||
const preconditions = item.command.preconditions;
|
||||
if (!preconditions || (preconditions && preconditions(contextService))) {
|
||||
logService.debug(`[MultiCommand]`, `executing implementation "${item.command.name}".`);
|
||||
logService.debug('[MultiCommand]', `executing implementation "${item.command.name}".`);
|
||||
const result = await injector.invoke(item.command.handler, params);
|
||||
if (result) {
|
||||
return true;
|
||||
|
||||
@@ -33,7 +33,6 @@ export interface IConfigService {
|
||||
}
|
||||
|
||||
export class ConfigService implements IConfigService {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private readonly _config: Map<string, any> = new Map();
|
||||
|
||||
getConfig<T>(id: string): Nullable<T> {
|
||||
|
||||
@@ -55,7 +55,6 @@ export const LifecycleToModules = new Map<LifecycleStages, Array<DependencyIdent
|
||||
* Register some modules here that will automatically run when Univer progressed to a certain lifecycle stage
|
||||
*/
|
||||
export function OnLifecycle(lifecycleStage: LifecycleStages, identifier: DependencyIdentifier<unknown>) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const decorator = function decorator(_: Ctor<unknown>) {
|
||||
runOnLifecycle(lifecycleStage, identifier);
|
||||
};
|
||||
|
||||
@@ -36,7 +36,6 @@ function getValue(locale: ILocales[LocaleType], key: string): Nullable<string> {
|
||||
try {
|
||||
if (locale[key]) return locale[key] as string;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return key.split('.').reduce((a: any, b: string) => a[b], locale);
|
||||
} catch (error) {
|
||||
console.warn('Key %s not found', key);
|
||||
|
||||
@@ -20,7 +20,7 @@ import { createIdentifier } from '@wendellhu/redi';
|
||||
|
||||
import { Disposable } from '../../shared/lifecycle';
|
||||
|
||||
export enum LogLevel /* eslint-disable no-magic-numbers */ {
|
||||
export enum LogLevel {
|
||||
SILENT = 0,
|
||||
ERROR = 1,
|
||||
WARN = 2,
|
||||
@@ -28,7 +28,6 @@ export enum LogLevel /* eslint-disable no-magic-numbers */ {
|
||||
VERBOSE = 4,
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type ArgsType = any[];
|
||||
|
||||
export interface ILogService {
|
||||
|
||||
@@ -52,7 +52,7 @@ export class ColorBuilder {
|
||||
return this.asRgbColor();
|
||||
}
|
||||
case ColorType.UNSUPPORTED: {
|
||||
throw Error('unsupported color type');
|
||||
throw new Error('unsupported color type');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,9 +118,9 @@ export class Color {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||
let string = null;
|
||||
if (result) {
|
||||
const r = parseInt(result[1], 16);
|
||||
const g = parseInt(result[2], 16);
|
||||
const b = parseInt(result[3], 16);
|
||||
const r = Number.parseInt(result[1], 16);
|
||||
const g = Number.parseInt(result[2], 16);
|
||||
const b = Number.parseInt(result[3], 16);
|
||||
string = `rgba(${r},${g},${b})`;
|
||||
}
|
||||
return string;
|
||||
@@ -283,10 +283,10 @@ export class RgbColor extends Color {
|
||||
static RGB_COLOR_AMT: number = 0;
|
||||
|
||||
static RGBA_EXTRACT: RegExp = new RegExp(
|
||||
`\\s*rgba\\s*\\((\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d.\\d|\\d\\s*)\\)\\s*`
|
||||
'\\s*rgba\\s*\\((\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d.\\d|\\d\\s*)\\)\\s*'
|
||||
);
|
||||
|
||||
static RGB_EXTRACT: RegExp = new RegExp(`\\s*rgb\\s*\\((\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d+\\s*)\\)\\s*`);
|
||||
static RGB_EXTRACT: RegExp = new RegExp('\\s*rgb\\s*\\((\\s*\\d+\\s*),(\\s*\\d+\\s*),(\\s*\\d+\\s*)\\)\\s*');
|
||||
|
||||
private _cssString: string;
|
||||
|
||||
|
||||
@@ -23,11 +23,9 @@ import type { Nullable } from '../common/type-utils';
|
||||
import type { Observer } from '../observer/observable';
|
||||
import { isObserver } from '../observer/observable';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function toDisposable(observer: Nullable<Observer<any>>): IDisposable;
|
||||
export function toDisposable(subscription: SubscriptionLike): IDisposable;
|
||||
export function toDisposable(callback: () => void): IDisposable;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function toDisposable(v: SubscriptionLike | (() => void) | Nullable<Observer<any>>): IDisposable {
|
||||
let disposed = false;
|
||||
|
||||
|
||||
@@ -30,5 +30,5 @@ export const getTypeFromPermissionItemList = (list: PermissionPoint[]) =>
|
||||
list.some((item) => item.status === PermissionStatus.INIT)
|
||||
? PermissionStatus.INIT
|
||||
: list.some((item) => item.status === PermissionStatus.FETCHING)
|
||||
? PermissionStatus.FETCHING
|
||||
: PermissionStatus.DONE;
|
||||
? PermissionStatus.FETCHING
|
||||
: PermissionStatus.DONE;
|
||||
|
||||
@@ -184,6 +184,7 @@ export class Rectangle {
|
||||
ranges[0]
|
||||
);
|
||||
}
|
||||
|
||||
static getRelativeRange = (range: IRange, originRange: IRange) =>
|
||||
({
|
||||
startRow: range.startRow - originRange.startRow,
|
||||
|
||||
@@ -364,11 +364,11 @@ export class Range {
|
||||
if (p && Array.isArray(p.body?.textRuns)) {
|
||||
return isAllFormatInTextRuns('ul', p.body?.textRuns!) === BooleanNumber.TRUE
|
||||
? {
|
||||
s: BooleanNumber.TRUE,
|
||||
}
|
||||
s: BooleanNumber.TRUE,
|
||||
}
|
||||
: {
|
||||
s: BooleanNumber.FALSE,
|
||||
};
|
||||
s: BooleanNumber.FALSE,
|
||||
};
|
||||
}
|
||||
|
||||
return this.getUnderlines()[0][0];
|
||||
@@ -397,11 +397,11 @@ export class Range {
|
||||
if (p && Array.isArray(p.body?.textRuns)) {
|
||||
return isAllFormatInTextRuns('st', p.body?.textRuns!) === BooleanNumber.TRUE
|
||||
? {
|
||||
s: BooleanNumber.TRUE,
|
||||
}
|
||||
s: BooleanNumber.TRUE,
|
||||
}
|
||||
: {
|
||||
s: BooleanNumber.FALSE,
|
||||
};
|
||||
s: BooleanNumber.FALSE,
|
||||
};
|
||||
}
|
||||
|
||||
return this.getStrikeThroughs()[0][0];
|
||||
|
||||
@@ -71,31 +71,28 @@ export enum VerticalAlign {
|
||||
*/
|
||||
export enum WrapStrategy {
|
||||
UNSPECIFIED,
|
||||
|
||||
/**
|
||||
* Lines that are longer than the cell width will be written in the next cell over, so long as that cell is empty. If the next cell over is non-empty, this behaves the same as CLIP . The text will never wrap to the next line unless the user manually inserts a new line. Example:
|
||||
|
||||
|
||||
| First sentence. |
|
||||
| Manual newline that is very long. <- Text continues into next cell
|
||||
| Next newline. |
|
||||
* | First sentence. |
|
||||
* | Manual newline that is very long. <- Text continues into next cell
|
||||
* | Next newline. |
|
||||
*/
|
||||
OVERFLOW,
|
||||
|
||||
/**
|
||||
* Lines that are longer than the cell width will be clipped. The text will never wrap to the next line unless the user manually inserts a new line. Example:
|
||||
|
||||
|
||||
| First sentence. |
|
||||
| Manual newline t| <- Text is clipped
|
||||
| Next newline. |
|
||||
* | First sentence. |
|
||||
* | Manual newline t| <- Text is clipped
|
||||
* | Next newline. |
|
||||
*/
|
||||
CLIP,
|
||||
|
||||
/**
|
||||
* Words that are longer than a line are wrapped at the character level rather than clipped. Example:
|
||||
|
||||
|
||||
| Cell has a |
|
||||
| loooooooooo| <- Word is broken.
|
||||
| ong word. |
|
||||
* | Cell has a |
|
||||
* | loooooooooo| <- Word is broken.
|
||||
* | ong word. |
|
||||
*/
|
||||
WRAP,
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ export interface ICellDataForSheetInterceptor extends ICellData {
|
||||
isInArrayFormulaRange?: Nullable<boolean>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function isICellData(value: any): value is ICellData {
|
||||
return (
|
||||
value &&
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib/types",
|
||||
"downlevelIteration": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "preserve",
|
||||
"emitDecoratorMetadata": true,
|
||||
"strictPropertyInitialization": false
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import { name } from './package.json';
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
{
|
||||
"name": "@univerjs/design",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "UI component library for building exceptional Univer.",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"sideEffects": [
|
||||
"**/*.css"
|
||||
],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -26,26 +34,24 @@
|
||||
"./lib/*": "./lib/*"
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"sideEffects": [
|
||||
"**/*.css"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rc-component/color-picker": "^1.4.1",
|
||||
"@rc-component/trigger": "^1.18.2",
|
||||
@@ -70,6 +76,7 @@
|
||||
"@types/react": "^18.2.47",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"happy-dom": "^12.10.3",
|
||||
@@ -77,12 +84,6 @@
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.9.0",
|
||||
"react-dom": ">=16.9.0",
|
||||
"rxjs": "^7.8.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,10 +83,10 @@ export function Avatar(props: IAvatarProps) {
|
||||
const sizeStyle =
|
||||
typeof size === 'number'
|
||||
? {
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size}px`,
|
||||
}
|
||||
width: size,
|
||||
height: size,
|
||||
lineHeight: `${size}px`,
|
||||
}
|
||||
: {};
|
||||
|
||||
const _className = clsx(styles.avatar, {
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Avatar } from '../Avatar';
|
||||
|
||||
describe('Avatar', () => {
|
||||
test('renders correctly', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Avatar size="small">Jane Doe</Avatar>);
|
||||
expect(container);
|
||||
});
|
||||
|
||||
test('renders the children', () => {
|
||||
it('renders the children', () => {
|
||||
const { getByText } = render(<Avatar>Test</Avatar>);
|
||||
const childrenElement = getByText('Test');
|
||||
expect(childrenElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders the image', () => {
|
||||
it('renders the image', () => {
|
||||
const { container } = render(<Avatar src="test.png" />);
|
||||
|
||||
expect(container.querySelector('img')).not.toBeNull();
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Button } from '../Button';
|
||||
|
||||
describe('Button', () => {
|
||||
test('renders correctly', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Button type="primary">btn1</Button>);
|
||||
expect(container);
|
||||
});
|
||||
|
||||
test('click onClick function', () => {
|
||||
it('click onClick function', () => {
|
||||
let a = 1;
|
||||
|
||||
const { container } = render(
|
||||
@@ -44,7 +44,7 @@ describe('Button', () => {
|
||||
expect(a).toEqual(2);
|
||||
});
|
||||
|
||||
test('should prevent event when button is disabled', () => {
|
||||
it('should prevent event when button is disabled', () => {
|
||||
let a = 1;
|
||||
|
||||
const { container } = render(
|
||||
|
||||
@@ -83,32 +83,34 @@ export function CascaderList(props: ICascaderListProps) {
|
||||
return (
|
||||
<section className={styles.cascaderList}>
|
||||
{activeOptions.map((options, index) =>
|
||||
options.length ? (
|
||||
<ul key={index} className={styles.cascaderListBoard}>
|
||||
{options.map((option) => (
|
||||
<li
|
||||
key={option.value}
|
||||
className={clsx(styles.cascaderListItem, {
|
||||
[styles.cascaderListItemActive]: option.value === value[index],
|
||||
})}
|
||||
>
|
||||
<a
|
||||
className={styles.cascaderListOption}
|
||||
onClick={() => handleChange(index, option.value)}
|
||||
options.length
|
||||
? (
|
||||
<ul key={index} className={styles.cascaderListBoard}>
|
||||
{options.map((option) => (
|
||||
<li
|
||||
key={option.value}
|
||||
className={clsx(styles.cascaderListItem, {
|
||||
[styles.cascaderListItemActive]: option.value === value[index],
|
||||
})}
|
||||
>
|
||||
<span className={styles.cascaderListCheckMark}>
|
||||
{option.value === value[index] && <CheckMarkSingle />}
|
||||
</span>
|
||||
<span>{option.label}</span>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<section key={index} className={styles.cascaderListEmpty}>
|
||||
无
|
||||
</section>
|
||||
)
|
||||
<a
|
||||
className={styles.cascaderListOption}
|
||||
onClick={() => handleChange(index, option.value)}
|
||||
>
|
||||
<span className={styles.cascaderListCheckMark}>
|
||||
{option.value === value[index] && <CheckMarkSingle />}
|
||||
</span>
|
||||
<span>{option.label}</span>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
: (
|
||||
<section key={index} className={styles.cascaderListEmpty}>
|
||||
无
|
||||
</section>
|
||||
)
|
||||
)}
|
||||
{value.length <= 0 && <section className={styles.cascaderListEmpty}>无</section>}
|
||||
</section>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import React, { useState } from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Checkbox } from '../../checkbox/Checkbox';
|
||||
import { CheckboxGroup } from '../CheckboxGroup';
|
||||
@@ -35,7 +35,7 @@ describe('CheckboxGroup', () => {
|
||||
</CheckboxGroup>
|
||||
);
|
||||
|
||||
test('click Checkbox', async () => {
|
||||
it('click Checkbox', async () => {
|
||||
render(group);
|
||||
|
||||
let result = ['0'];
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Checkbox } from '../Checkbox';
|
||||
|
||||
describe('Checkbox', () => {
|
||||
const component = <Checkbox value="0">text</Checkbox>;
|
||||
|
||||
test('click Checkbox', async () => {
|
||||
it('click Checkbox', async () => {
|
||||
const { container } = render(component);
|
||||
|
||||
fireEvent.click(container.querySelector('input')!);
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React, { useContext } from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { ILocale } from '../../../locale';
|
||||
import { enUS, zhCN } from '../../../locale';
|
||||
import { ConfigContext, ConfigProvider } from '../ConfigProvider';
|
||||
|
||||
describe('ConfigProvider', () => {
|
||||
test('should render correctly', () => {
|
||||
it('should render correctly', () => {
|
||||
let _mountContainer: HTMLElement | null = null;
|
||||
let _locale: ILocale | null = null;
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('ConfigProvider', () => {
|
||||
root.unmount();
|
||||
});
|
||||
|
||||
test('should render correctly when mountContainer is not document.body', () => {
|
||||
it('should render correctly when mountContainer is not document.body', () => {
|
||||
const mountContainer = document.createElement('div');
|
||||
document.body.appendChild(mountContainer);
|
||||
|
||||
@@ -73,7 +73,7 @@ describe('ConfigProvider', () => {
|
||||
root.unmount();
|
||||
});
|
||||
|
||||
test('should render correctly when locale is invalid', () => {
|
||||
it('should render correctly when locale is invalid', () => {
|
||||
const mountContainer = document.createElement('div');
|
||||
document.body.appendChild(mountContainer);
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Container } from '../Container';
|
||||
|
||||
describe('Container', () => {
|
||||
test('should display initial Container', () => {
|
||||
it('should display initial Container', () => {
|
||||
const { container } = render(<Container>container content Text</Container>);
|
||||
|
||||
expect(container.textContent).toMatch('container content Text');
|
||||
|
||||
@@ -77,28 +77,30 @@ export function Dialog(props: IDialogProps) {
|
||||
|
||||
const { mountContainer } = useContext(ConfigContext);
|
||||
|
||||
const TitleIfDraggable = draggable ? (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (dragDisabled) {
|
||||
setDragDisabled(false);
|
||||
}
|
||||
}}
|
||||
onMouseOut={() => {
|
||||
setDragDisabled(true);
|
||||
}}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
) : (
|
||||
title
|
||||
);
|
||||
const TitleIfDraggable = draggable
|
||||
? (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (dragDisabled) {
|
||||
setDragDisabled(false);
|
||||
}
|
||||
}}
|
||||
onMouseOut={() => {
|
||||
setDragDisabled(true);
|
||||
}}
|
||||
onFocus={() => {}}
|
||||
onBlur={() => {}}
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
title
|
||||
);
|
||||
|
||||
const modalRender = (modal: React.ReactNode) =>
|
||||
draggable ? <Draggable disabled={dragDisabled}>{modal}</Draggable> : modal;
|
||||
|
||||
@@ -32,14 +32,14 @@ export default meta;
|
||||
export const Playground = {
|
||||
render() {
|
||||
function handleRedirect() {
|
||||
window.open('https://univer-icons.vercel.app/', '_blank');
|
||||
window.open('https://univer.ai/icons', '_blank');
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
Check out our icon library at{' '}
|
||||
Check out our icon library at
|
||||
<Button type="link" onClick={handleRedirect}>
|
||||
https://univer-icons.vercel.app/
|
||||
https://univer.ai/icons
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Button } from '../../button/Button';
|
||||
import { Message } from '../Message';
|
||||
|
||||
describe('Message', () => {
|
||||
test('renders correctly', () => {
|
||||
it('renders correctly', () => {
|
||||
const message = new Message(document.body);
|
||||
|
||||
const { container } = render(
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Radio } from '../../radio/Radio';
|
||||
import { RadioGroup } from '../RadioGroup';
|
||||
@@ -35,7 +35,7 @@ describe('RadioGroup', () => {
|
||||
</RadioGroup>
|
||||
);
|
||||
|
||||
test('click Radio', async () => {
|
||||
it('click Radio', async () => {
|
||||
render(group);
|
||||
|
||||
fireEvent.click(screen.getByText('1'));
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
import { fireEvent, render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Radio } from '../Radio';
|
||||
|
||||
describe('Radio', () => {
|
||||
const component = <Radio value="0">text</Radio>;
|
||||
|
||||
test('click Radio', async () => {
|
||||
it('click Radio', async () => {
|
||||
const { container } = render(component);
|
||||
|
||||
fireEvent.click(container.querySelector('input')!);
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Scrollbar } from '../Scrollbar';
|
||||
|
||||
describe('Scrollbar', () => {
|
||||
test('should not render thumb', () => {
|
||||
it('should not render thumb', () => {
|
||||
const { container } = render(
|
||||
<section style={{ height: '100px' }}>
|
||||
<Scrollbar>
|
||||
|
||||
@@ -71,7 +71,8 @@ export const SelectGroup = {
|
||||
{
|
||||
label: (
|
||||
<span>
|
||||
Option 3-2 <strong>xxx</strong>
|
||||
Option 3-2
|
||||
<strong>xxx</strong>
|
||||
</span>
|
||||
),
|
||||
value: 'option32',
|
||||
|
||||
@@ -34,7 +34,8 @@ export interface ISliderProps {
|
||||
*/
|
||||
min?: number;
|
||||
|
||||
/** The maximum value the slider can slide to
|
||||
/**
|
||||
* The maximum value the slider can slide to
|
||||
* @default 400
|
||||
*/
|
||||
max?: number;
|
||||
@@ -45,7 +46,8 @@ export interface ISliderProps {
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
/** The maximum value the slider can slide to
|
||||
/**
|
||||
* The maximum value the slider can slide to
|
||||
* @default 100
|
||||
*/
|
||||
resetPoint?: number;
|
||||
@@ -176,7 +178,7 @@ export function Slider(props: ISliderProps) {
|
||||
|
||||
<Dropdown
|
||||
placement="topLeft"
|
||||
overlay={
|
||||
overlay={(
|
||||
<div className={styles.sliderShortcuts}>
|
||||
{shortcuts?.map((item) => (
|
||||
<a
|
||||
@@ -188,13 +190,19 @@ export function Slider(props: ISliderProps) {
|
||||
onClick={() => onChange && onChange(item)}
|
||||
>
|
||||
{item === value && <span className={styles.sliderShortcutIcon}>✔</span>}
|
||||
<span>{item}%</span>
|
||||
<span>
|
||||
{item}
|
||||
%
|
||||
</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
>
|
||||
<a className={styles.sliderValue}>{value}%</a>
|
||||
<a className={styles.sliderValue}>
|
||||
{value}
|
||||
%
|
||||
</a>
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import React, { useState } from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Slider } from '../Slider';
|
||||
|
||||
describe('Slider', () => {
|
||||
test('renders correctly', () => {
|
||||
it('renders correctly', () => {
|
||||
const { container } = render(<Slider min={0} max={100} value={90} />);
|
||||
expect(container);
|
||||
});
|
||||
|
||||
test('renders correctly with resetPoint', () => {
|
||||
it('renders correctly with resetPoint', () => {
|
||||
let value = 90;
|
||||
|
||||
function handleChange(point: number) {
|
||||
@@ -40,7 +40,7 @@ describe('Slider', () => {
|
||||
expect(value).toBe(30);
|
||||
});
|
||||
|
||||
test('renders correctly with steps', () => {
|
||||
it('renders correctly with steps', () => {
|
||||
let result = 10;
|
||||
function Demo() {
|
||||
const [value, setValue] = useState(result);
|
||||
@@ -66,7 +66,7 @@ describe('Slider', () => {
|
||||
expect(result).toBe(20);
|
||||
});
|
||||
|
||||
test('renders correctly with shortcuts', () => {
|
||||
it('renders correctly with shortcuts', () => {
|
||||
let result = 10;
|
||||
function Demo() {
|
||||
const [value, setValue] = useState(result);
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { Tree } from '../Tree';
|
||||
|
||||
describe('Tree', () => {
|
||||
test('defaultExpandAll', async () => {
|
||||
it('defaultExpandAll', async () => {
|
||||
const { container } = render(
|
||||
<Tree
|
||||
data={[
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import type React from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import type { Observable, Subscription } from 'rxjs';
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
{
|
||||
"name": "@univerjs/docs-ui",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "Univer normal ui-plugin-docs",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"sideEffects": [
|
||||
"**/*.css"
|
||||
],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -26,26 +34,28 @@
|
||||
"./lib/*": "./lib/*"
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"sideEffects": [
|
||||
"**/*.css"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/design": "workspace:*",
|
||||
"@univerjs/docs": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
"@univerjs/ui": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"react": ">=16.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/design": "workspace:*",
|
||||
@@ -58,6 +68,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.47",
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"happy-dom": "^12.10.3",
|
||||
@@ -65,16 +76,6 @@
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/design": "workspace:*",
|
||||
"@univerjs/docs": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
"@univerjs/ui": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"react": ">=16.9.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true,
|
||||
"strictPropertyInitialization": false
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
|
||||
+16
-15
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"name": "@univerjs/docs",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "UniverSheet normal base-docs",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -25,23 +30,27 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
"@univerjs/sheets": "workspace:*",
|
||||
"@univerjs/ui": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
@@ -51,21 +60,13 @@
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"happy-dom": "^12.10.3",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@univerjs/engine-render": "workspace:*",
|
||||
"@univerjs/sheets": "workspace:*",
|
||||
"@univerjs/ui": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
IUniverInstanceService,
|
||||
MemoryCursor,
|
||||
} from '@univerjs/core';
|
||||
import { type TextRange } from '@univerjs/engine-render';
|
||||
import type { TextRange } from '@univerjs/engine-render';
|
||||
|
||||
import { TextSelectionManagerService } from '../../services/text-selection-manager.service';
|
||||
import type { IRichTextEditingMutationParams } from '../mutations/core-editing.mutation';
|
||||
@@ -337,8 +337,8 @@ function getReverseFormatValueInSelection(
|
||||
return /bl|it/.test(key)
|
||||
? BooleanNumber.FALSE
|
||||
: /ul|st/.test(key)
|
||||
? {
|
||||
? {
|
||||
s: BooleanNumber.FALSE,
|
||||
}
|
||||
: BaselineOffset.NORMAL;
|
||||
: BaselineOffset.NORMAL;
|
||||
}
|
||||
|
||||
@@ -149,23 +149,23 @@ export const ListOperationCommand: ICommand<IListOperationCommandParams> = {
|
||||
paragraphs: [
|
||||
isAlreadyOrdered
|
||||
? {
|
||||
paragraphStyle,
|
||||
startIndex: 0,
|
||||
}
|
||||
paragraphStyle,
|
||||
startIndex: 0,
|
||||
}
|
||||
: {
|
||||
...paragraph,
|
||||
startIndex: 0,
|
||||
bullet: {
|
||||
...(paragraph.bullet ?? {
|
||||
nestingLevel: 0,
|
||||
textStyle: {
|
||||
fs: 20,
|
||||
},
|
||||
}),
|
||||
listType,
|
||||
listId,
|
||||
},
|
||||
},
|
||||
...paragraph,
|
||||
startIndex: 0,
|
||||
bullet: {
|
||||
...(paragraph.bullet ?? {
|
||||
nestingLevel: 0,
|
||||
textStyle: {
|
||||
fs: 20,
|
||||
},
|
||||
}),
|
||||
listType,
|
||||
listId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
segmentId,
|
||||
|
||||
@@ -108,8 +108,8 @@ export class MoveCursorController extends Disposable {
|
||||
const { startOffset, endOffset, style, collapsed, direction: rangeDirection } = activeRange;
|
||||
|
||||
if (allRanges.length > 1) {
|
||||
let min = Infinity;
|
||||
let max = -Infinity;
|
||||
let min = Number.POSITIVE_INFINITY;
|
||||
let max = Number.NEGATIVE_INFINITY;
|
||||
|
||||
for (const range of allRanges) {
|
||||
min = Math.min(min, range.startOffset!);
|
||||
@@ -130,11 +130,11 @@ export class MoveCursorController extends Disposable {
|
||||
const anchorOffset = collapsed
|
||||
? startOffset
|
||||
: rangeDirection === RANGE_DIRECTION.FORWARD
|
||||
? startOffset
|
||||
: endOffset;
|
||||
? startOffset
|
||||
: endOffset;
|
||||
|
||||
let focusOffset = collapsed ? endOffset : rangeDirection === RANGE_DIRECTION.FORWARD ? endOffset : startOffset;
|
||||
const dataStreamLength = docDataModel.getBody()!.dataStream.length ?? Infinity;
|
||||
const dataStreamLength = docDataModel.getBody()!.dataStream.length ?? Number.POSITIVE_INFINITY;
|
||||
|
||||
if (direction === Direction.LEFT || direction === Direction.RIGHT) {
|
||||
const preSpan = skeleton.findNodeByCharIndex(focusOffset - 1);
|
||||
@@ -208,14 +208,14 @@ export class MoveCursorController extends Disposable {
|
||||
|
||||
const { startOffset, endOffset, style, collapsed } = activeRange;
|
||||
|
||||
const dataStreamLength = docDataModel.getBody()!.dataStream.length ?? Infinity;
|
||||
const dataStreamLength = docDataModel.getBody()!.dataStream.length ?? Number.POSITIVE_INFINITY;
|
||||
|
||||
if (direction === Direction.LEFT || direction === Direction.RIGHT) {
|
||||
let cursor;
|
||||
|
||||
if (!activeRange.collapsed || allRanges.length > 1) {
|
||||
let min = Infinity;
|
||||
let max = -Infinity;
|
||||
let min = Number.POSITIVE_INFINITY;
|
||||
let max = Number.NEGATIVE_INFINITY;
|
||||
|
||||
for (const range of allRanges) {
|
||||
min = Math.min(min, range.startOffset!);
|
||||
@@ -323,7 +323,7 @@ export class MoveCursorController extends Disposable {
|
||||
const divide = span.parent;
|
||||
|
||||
if (divide == null) {
|
||||
return -Infinity;
|
||||
return Number.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
const divideLeft = divide.left;
|
||||
@@ -340,7 +340,7 @@ export class MoveCursorController extends Disposable {
|
||||
span?: IDocumentSkeletonSpan;
|
||||
distance: number;
|
||||
} = {
|
||||
distance: Infinity,
|
||||
distance: Number.POSITIVE_INFINITY,
|
||||
};
|
||||
|
||||
for (const divide of line.divides) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true,
|
||||
"strictPropertyInitialization": false
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import { name } from './package.json';
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"name": "@univerjs/engine-formula",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "UniverSheet normal base-formula-engine",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -25,23 +30,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": "^0.12.13",
|
||||
@@ -50,17 +56,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/big.js": "^6.2.2",
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class CustomFunction extends BaseFunction {
|
||||
|
||||
function createFunction(functionString: string, functionName: string) {
|
||||
const instance = new CustomFunction(functionName);
|
||||
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
||||
// eslint-disable-next-line no-new-func
|
||||
const functionCalculate = new Function(`return ${functionString}`)();
|
||||
instance.calculateCustom = functionCalculate;
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
import { ConcatenateType } from '../../basics/common';
|
||||
import { ErrorType } from '../../basics/error-type';
|
||||
import { ObjectClassType } from '../../basics/object-class-type';
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { ErrorType } from '../../../basics/error-type';
|
||||
import { valueObjectCompare } from '../../../engine/utils/object-compare';
|
||||
import { type ArrayValueObject } from '../../../engine/value-object/array-value-object';
|
||||
import type { ArrayValueObject } from '../../../engine/value-object/array-value-object';
|
||||
import { type BaseValueObject, ErrorValueObject } from '../../../engine/value-object/base-value-object';
|
||||
import { BaseFunction } from '../../base-function';
|
||||
|
||||
@@ -43,9 +43,9 @@ export class Sumif extends BaseFunction {
|
||||
// sumRange has the same dimensions as range
|
||||
const sumRangeArray = sumRange
|
||||
? (sumRange as ArrayValueObject).slice(
|
||||
[0, (range as ArrayValueObject).getRowCount()],
|
||||
[0, (range as ArrayValueObject).getColumnCount()]
|
||||
)
|
||||
[0, (range as ArrayValueObject).getRowCount()],
|
||||
[0, (range as ArrayValueObject).getColumnCount()]
|
||||
)
|
||||
: (range as ArrayValueObject);
|
||||
|
||||
if (!sumRangeArray) {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true,
|
||||
"strictPropertyInitialization": false
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import { name } from './package.json';
|
||||
@@ -31,7 +31,7 @@ export default defineConfig(({ mode }) => ({
|
||||
external: [
|
||||
'@univerjs/core',
|
||||
'@wendellhu/redi',
|
||||
'rxjs'
|
||||
'rxjs',
|
||||
],
|
||||
output: {
|
||||
globals: {
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"name": "@univerjs/engine-numfmt",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "UniverSheet normal plugin UI manager",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -25,36 +30,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"numfmt": "^2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "@univerjs/infra/tsconfigs/base",
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"outDir": "lib",
|
||||
"esModuleInterop": true,
|
||||
"types": ["./src/types/index.d.ts"]
|
||||
"rootDir": "src",
|
||||
"outDir": "lib/types"
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
"references": [{ "path": "./tsconfig.node.json" }],
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "@univerjs/infra/tsconfigs/node",
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { resolve } from 'path';
|
||||
import { resolve } from 'node:path';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import { name } from './package.json';
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"name": "@univerjs/engine-render",
|
||||
"version": "0.1.0-beta.2",
|
||||
"private": false,
|
||||
"description": "UniverSheet normal base-render",
|
||||
"keywords": [],
|
||||
"author": "DreamNum <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [],
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"main": "./lib/cjs/index.js",
|
||||
"module": "./lib/es/index.js",
|
||||
"types": "./lib/types/index.d.ts",
|
||||
@@ -25,23 +30,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./*": "./src/*"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"build": "tsc && vite build"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": "^0.12.13",
|
||||
@@ -50,17 +56,12 @@
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@univerjs/infra": "workspace:*",
|
||||
"@vitest/coverage-istanbul": "^1.1.1",
|
||||
"less": "^4.2.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite-plugin-dts": "^3.7.0",
|
||||
"vite-plugin-externals": "^0.6.2",
|
||||
"vitest": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@univerjs/core": "workspace:*",
|
||||
"@wendellhu/redi": ">=0.12.12",
|
||||
"rxjs": ">=7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user