From c3aba2003cb74b8f289ea0dcbdfe74b3cd56a4ea Mon Sep 17 00:00:00 2001 From: Steve Xu Date: Tue, 19 Dec 2023 10:12:14 +0800 Subject: [PATCH] fix: update the README.md script --- README.md | 3 +- e2e/a.ts | 4 +- package.json | 9 +- post-install.js | 2 +- scripts/update-md.ts | 453 +++-------------------- src/containers/FormulaBar/DefineName.tsx | 23 +- src/formula/eval.ts | 4 +- src/formula/formula/index.ts | 4 +- src/formula/formula/text.ts | 4 +- 9 files changed, 76 insertions(+), 430 deletions(-) diff --git a/README.md b/README.md index 7f2a8c9c..22c052c5 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ npm run start - [x] Fill color - [x] Text wrapping - [x] Formulas +- [x] Define Name - [x] Insert row, column - [x] Delete row, column - [x] Insert Sheet @@ -51,6 +52,7 @@ npm run start - [x] ASIN - [x] ASINH - [x] ATAN +- [x] ATAN2 - [x] ATANH - [x] CHAR - [x] CODE @@ -72,4 +74,3 @@ npm run start - [x] UNICHAR - [x] UNICODE - [x] UPPER - diff --git a/e2e/a.ts b/e2e/a.ts index 32f6bfe4..eceafb6a 100644 --- a/e2e/a.ts +++ b/e2e/a.ts @@ -10,7 +10,7 @@ let port = 8000; beforeAll(async () => { await setupPuppeteer(); - await sleep(500); + await sleep(1000); getPort(); }); afterAll(async () => { @@ -49,7 +49,7 @@ export function sleep(milliseconds: number): Promise { export async function openPage(): Promise { const filePath = `http://localhost:${port}`; await browserPage.goto(filePath); - await sleep(200); + await sleep(500); } export function getTestIdSelector(testId: string): string { diff --git a/package.json b/package.json index 28fa93c0..3e45e076 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,13 @@ "build": "node ./scripts/esbuild.js", "test": "jest --config ./scripts/unit-test-jest.config.js --forceExit --detectOpenHandles", "coverage": "npm run test -- --coverage", - "ci": "npm run test && npm run e2e && npm run build && npm run type-check && npm run lint", + "ci": "npm run test && npm run e2e && npm run build && npm run type-check && npm run update-md && npm run lint", "type-check": "npx tsc", "postinstall": "node ./post-install.js", - "prebuild": "node ./post-install.js", + "prebuild": "npm run postinstall", "e2e": "jest --config ./scripts/e2e-jest.config.js --forceExit --detectOpenHandles", - "lint": "npm run lint-es && npm run lint-ox", - "lint-es": "eslint --fix --quiet --ext .ts,.tsx ./", - "lint-ox": "pnpm dlx oxlint@latest" + "lint": "pnpm dlx oxlint@latest && eslint --fix --quiet --ext .ts,.tsx ./", + "update-md": "node ./scripts/update-md.js" }, "repository": { "type": "git", diff --git a/post-install.js b/post-install.js index f5192fb1..492cea70 100644 --- a/post-install.js +++ b/post-install.js @@ -22,7 +22,7 @@ function init() { entryPoints: [filePath], outfile: temp, format: 'cjs', - target: 'es2020', + // target: 'es2020', }); } else if (ext === '.js') { fs.unlink(filePath, (error) => { diff --git a/scripts/update-md.ts b/scripts/update-md.ts index 7fff6e94..fbc23d8c 100644 --- a/scripts/update-md.ts +++ b/scripts/update-md.ts @@ -1,412 +1,55 @@ import * as fs from 'fs'; import * as path from 'path'; -const ALL_FORMULAS = [ - 'ABS', - 'ACCRINT', - 'ACOS', - 'ACOSH', - 'ACOT', - 'ACOTH', - 'ADD', - 'AGGREGATE', - 'AND', - 'ARABIC', - 'ARGS2ARRAY', - 'ASIN', - 'ASINH', - 'ATAN', - 'ATAN2', - 'ATANH', - 'AVEDEV', - 'AVERAGE', - 'AVERAGEA', - 'AVERAGEIF', - 'AVERAGEIFS', - 'BASE', - 'BESSELI', - 'BESSELJ', - 'BESSELK', - 'BESSELY', - 'BETA.DIST', - 'BETA.INV', - 'BETADIST', - 'BETAINV', - 'BIN2DEC', - 'BIN2HEX', - 'BIN2OCT', - 'BINOM.DIST', - 'BINOM.DIST.RANGE', - 'BINOM.INV', - 'BINOMDIST', - 'BITAND', - 'BITLSHIFT', - 'BITOR', - 'BITRSHIFT', - 'BITXOR', - 'CEILING', - 'CEILINGMATH', - 'CEILINGPRECISE', - 'CHAR', - 'CHISQ.DIST', - 'CHISQ.DIST.RT', - 'CHISQ.INV', - 'CHISQ.INV.RT', - 'CHOOSE', - 'CHOOSE', - 'CLEAN', - 'CODE', - 'COLUMN', - 'COLUMNS', - 'COMBIN', - 'COMBINA', - 'COMPLEX', - 'CONCATENATE', - 'CONFIDENCE', - 'CONFIDENCE.NORM', - 'CONFIDENCE.T', - 'CONVERT', - 'CORREL', - 'COS', - 'COSH', - 'COT', - 'COTH', - 'COUNT', - 'COUNTA', - 'COUNTBLANK', - 'COUNTIF', - 'COUNTIFS', - 'COUNTIN', - 'COUNTUNIQUE', - 'COVARIANCE.P', - 'COVARIANCE.S', - 'CSC', - 'CSCH', - 'CUMIPMT', - 'CUMPRINC', - 'DATE', - 'DATEVALUE', - 'DAY', - 'DAYS', - 'DAYS360', - 'DB', - 'DDB', - 'DEC2BIN', - 'DEC2HEX', - 'DEC2OCT', - 'DECIMAL', - 'DEGREES', - 'DELTA', - 'DEVSQ', - 'DIVIDE', - 'DOLLARDE', - 'DOLLARFR', - 'E', - 'EDATE', - 'EFFECT', - 'EOMONTH', - 'EQ', - 'ERF', - 'ERFC', - 'EVEN', - 'EXACT', - 'EXP', - 'EXPON.DIST', - 'EXPONDIST', - 'F.DIST', - 'F.DIST.RT', - 'F.INV', - 'F.INV.RT', - 'FACT', - 'FACTDOUBLE', - 'FALSE', - 'FDIST', - 'FDISTRT', - 'FIND', - 'FINV', - 'FINVRT', - 'FISHER', - 'FISHERINV', - 'FLATTEN', - 'FLOOR', - 'FORECAST', - 'FREQUENCY', - 'FV', - 'FVSCHEDULE', - 'GAMMA', - 'GAMMA.DIST', - 'GAMMA.INV', - 'GAMMADIST', - 'GAMMAINV', - 'GAMMALN', - 'GAMMALN.PRECISE', - 'GAUSS', - 'GCD', - 'GEOMEAN', - 'GESTEP', - 'GROWTH', - 'GTE', - 'HARMEAN', - 'HEX2BIN', - 'HEX2DEC', - 'HEX2OCT', - 'HOUR', - 'HTML2TEXT', - 'HYPGEOM.DIST', - 'HYPGEOMDIST', - 'IF', - 'IMABS', - 'IMAGINARY', - 'IMARGUMENT', - 'IMCONJUGATE', - 'IMCOS', - 'IMCOSH', - 'IMCOT', - 'IMCSC', - 'IMCSCH', - 'IMDIV', - 'IMEXP', - 'IMLN', - 'IMLOG10', - 'IMLOG2', - 'IMPOWER', - 'IMPRODUCT', - 'IMREAL', - 'IMSEC', - 'IMSECH', - 'IMSIN', - 'IMSINH', - 'IMSQRT', - 'IMSUB', - 'IMSUM', - 'IMTAN', - 'INT', - 'INTERCEPT', - 'INTERVAL', - 'IPMT', - 'IRR', - 'ISBINARY', - 'ISBLANK', - 'ISEVEN', - 'ISLOGICAL', - 'ISNONTEXT', - 'ISNUMBER', - 'ISODD', - 'ISODD', - 'ISOWEEKNUM', - 'ISPMT', - 'ISTEXT', - 'JOIN', - 'KURT', - 'LARGE', - 'LCM', - 'LEFT', - 'LEN', - 'LINEST', - 'LN', - 'LOG', - 'LOG10', - 'LOGEST', - 'LOGNORM.DIST', - 'LOGNORM.INV', - 'LOGNORMDIST', - 'LOGNORMINV', - 'LOWER', - 'LT', - 'LTE', - 'MATCH', - 'MAX', - 'MAXA', - 'MEDIAN', - 'MID', - 'MIN', - 'MINA', - 'MINUS', - 'MINUTE', - 'MIRR', - 'MOD', - 'MODE.MULT', - 'MODE.SNGL', - 'MODEMULT', - 'MODESNGL', - 'MONTH', - 'MROUND', - 'MULTINOMIAL', - 'MULTIPLY', - 'NE', - 'NEGBINOM.DIST', - 'NEGBINOMDIST', - 'NETWORKDAYS', - 'NOMINAL', - 'NORM.DIST', - 'NORM.INV', - 'NORM.S.DIST', - 'NORM.S.INV', - 'NORMDIST', - 'NORMINV', - 'NORMSDIST', - 'NORMSINV', - 'NOT', - 'NOW', - 'NPER', - 'NPV', - 'NUMBERS', - 'OCT2BIN', - 'OCT2DEC', - 'OCT2HEX', - 'ODD', - 'OR', - 'PDURATION', - 'PEARSON', - 'PERCENTILEEXC', - 'PERCENTILEINC', - 'PERCENTRANKEXC', - 'PERCENTRANKINC', - 'PERMUT', - 'PERMUTATIONA', - 'PHI', - 'PI', - 'PMT', - 'POISSON.DIST', - 'POISSONDIST', - 'POW', - 'POWER', - 'PPMT', - 'PROB', - 'PRODUCT', - 'PROPER', - 'PV', - 'QUARTILE.EXC', - 'QUARTILE.INC', - 'QUARTILEEXC', - 'QUARTILEINC', - 'QUOTIENT', - 'RADIANS', - 'RAND', - 'RANDBETWEEN', - 'RANK.AVG', - 'RANK.EQ', - 'RANKAVG', - 'RANKEQ', - 'RATE', - 'REFERENCE', - 'REGEXEXTRACT', - 'REGEXMATCH', - 'REGEXREPLACE', - 'REPLACE', - 'REPT', - 'RIGHT', - 'ROMAN', - 'ROUND', - 'ROUNDDOWN', - 'ROUNDUP', - 'ROW', - 'ROWS', - 'RRI', - 'RSQ', - 'SEARCH', - 'SEC', - 'SECH', - 'SECOND', - 'SERIESSUM', - 'SIGN', - 'SIN', - 'SINH', - 'SKEW', - 'SKEW.P', - 'SKEWP', - 'SLN', - 'SLOPE', - 'SMALL', - 'SPLIT', - 'SPLIT', - 'SQRT', - 'SQRTPI', - 'STANDARDIZE', - 'STDEV.P', - 'STDEV.S', - 'STDEVA', - 'STDEVP', - 'STDEVPA', - 'STDEVS', - 'STEYX', - 'SUBSTITUTE', - 'SUBTOTAL', - 'SUM', - 'SUMIF', - 'SUMIFS', - 'SUMPRODUCT', - 'SUMSQ', - 'SUMX2MY2', - 'SUMX2PY2', - 'SUMXMY2', - 'SWITCH', - 'SYD', - 'T', - 'T.DIST', - 'T.DIST.2T', - 'T.DIST.RT', - 'T.INV', - 'T.INV.2T', - 'TAN', - 'TANH', - 'TBILLEQ', - 'TBILLPRICE', - 'TBILLYIELD', - 'TDIST', - 'TDIST2T', - 'TDISTRT', - 'TIME', - 'TIMEVALUE', - 'TINV', - 'TINV2T', - 'TODAY', - 'TRANSPOSE', - 'TREND', - 'TRIM', - 'TRIMMEAN', - 'TRUE', - 'TRUNC', - 'UNICHAR', - 'UNICODE', - 'UNIQUE', - 'UPPER', - 'VAR.P', - 'VAR.S', - 'VARA', - 'VARP', - 'VARPA', - 'VARS', - 'WEEKDAY', - 'WEEKNUM', - 'WEIBULL.DIST', - 'WEIBULLDIST', - 'WORKDAY', - 'XIRR', - 'XNPV', - 'XOR', - 'YEAR', - 'YEARFRAC', -]; -const FORMULA_TAG = '## Formula'; -function handleFormula(data: any = {}) { - console.log(ALL_FORMULAS); - const allFormulas = Object.keys(data); - allFormulas.sort((a, b) => a.localeCompare(b)); - const set = new Set(Object.keys(data).filter((key) => Boolean(data[key]))); - const result: string[] = []; - for (const item of allFormulas) { - result.push(`[${set.has(item) ? 'x' : ' '}] ${item}`); +const FORMULA_DIR = path.join(process.cwd(), 'dist/src/formula/formula'); +const PREFIX_TEXT = 'const formulas = {'; +const END_TEXT = '}'; +const FORMULA_TAG = '### Supported Formulas'; +const MD_PATH = path.join(process.cwd(), 'README.md'); +const ENCODE = 'utf-8'; + +function updateMarkdown() { + if (!fs.existsSync(FORMULA_DIR)) { + return; } - const text = result.map((item, i) => `${i + 1}. ${item}`).join('\n'); - const mdPath = path.join(process.cwd(), 'README.md'); - const mdText = fs.readFileSync(mdPath, 'utf-8'); - const index = mdText.indexOf(FORMULA_TAG); + const list = fs.readdirSync(FORMULA_DIR); + let formulaNames: string[] = []; - fs.writeFileSync( - mdPath, - `${mdText.slice(0, index + FORMULA_TAG.length)}\n\n${set.size}/${allFormulas.length}\n\n${text}`, - ); + for (const item of list) { + const filePath = path.join(FORMULA_DIR, item); + const result = fs.lstatSync(filePath); + if (!result.isDirectory()) { + const text = fs.readFileSync(filePath, ENCODE); + const start = text.indexOf(PREFIX_TEXT); + if (start <= 0) { + continue; + } + let end = start; + while (end < text.length && text[end] !== END_TEXT) { + end++; + } + const temp = text.slice(start + PREFIX_TEXT.length, end); + const keyList = temp + .trim() + .split('\n') + .map((item) => { + const list = /[A-Z0-9]+/g.exec(item.trim()); + return list![0]; + }) + .filter((v) => v); + formulaNames = formulaNames.concat(keyList); + } + } + formulaNames = Array.from(new Set(formulaNames)); + formulaNames.sort((a, b) => a.localeCompare(b)); + const result = formulaNames.map((item) => `- [x] ${item}`).join('\n'); + const oldText = fs.readFileSync(MD_PATH, ENCODE); + const index = oldText.indexOf(FORMULA_TAG); + const mdText = `${oldText.slice( + 0, + index + FORMULA_TAG.length, + )}\n\n${result}\n`; + fs.writeFileSync(MD_PATH, mdText); } -handleFormula(); +updateMarkdown(); diff --git a/src/containers/FormulaBar/DefineName.tsx b/src/containers/FormulaBar/DefineName.tsx index 4f6765cb..5c62bee5 100644 --- a/src/containers/FormulaBar/DefineName.tsx +++ b/src/containers/FormulaBar/DefineName.tsx @@ -23,18 +23,21 @@ export const DefineName: React.FunctionComponent = ({ if (event.key === 'Enter') { const t = event.currentTarget.value.toLowerCase(); ref.current?.blur(); - const oldRange = controller.checkDefineName(t); - if (oldRange) { - controller.setActiveCell(oldRange); + const range = controller.checkDefineName(t); + if (range) { + setValue(displayName); + controller.setActiveCell(range); return; - } + } + const r = parseCell(t); + const sheetInfo = controller.getSheetInfo(controller.getCurrentSheetId()); + if (r && r.col < sheetInfo.colCount && r.row < sheetInfo.rowCount) { + setValue(displayName); + controller.setActiveCell(r); + return; + } if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t) && t.length <= 255) { - const range = parseCell(t); - if (range) { - controller.setActiveCell(range); - } else { - controller.setDefineName(controller.getActiveCell(), t); - } + controller.setDefineName(controller.getActiveCell(), t); } else { setValue(displayName); } diff --git a/src/formula/eval.ts b/src/formula/eval.ts index 93e778bb..788b5827 100644 --- a/src/formula/eval.ts +++ b/src/formula/eval.ts @@ -1,6 +1,6 @@ import { Scanner } from './scanner'; import { Parser } from './parser'; -import formulas, { CustomError } from './formula'; +import allFormulas, { CustomError } from './formula'; import { Interpreter } from './interpreter'; import { CellDataMap, @@ -14,7 +14,7 @@ export function parseFormula( source: string, cellData: CellDataMap = new CellDataMapImpl(), definedNamesMap: DefinedNamesMap = new DefinedNamesMapImpl(), - functionMap: FormulaType = formulas, + functionMap: FormulaType = allFormulas, ): InterpreterResult { let expressionStr = ''; try { diff --git a/src/formula/formula/index.ts b/src/formula/formula/index.ts index 0fcbad00..1b3df33d 100644 --- a/src/formula/formula/index.ts +++ b/src/formula/formula/index.ts @@ -2,9 +2,9 @@ import textFormulas from './text'; import mathFormulas from './math'; import type { FormulaType } from '@/types'; -const formulas: FormulaType = { +const allFormulas: FormulaType = { ...textFormulas, ...mathFormulas, }; export * from './error'; -export default formulas; +export default allFormulas; diff --git a/src/formula/formula/text.ts b/src/formula/formula/text.ts index fbc36006..7c6d1741 100644 --- a/src/formula/formula/text.ts +++ b/src/formula/formula/text.ts @@ -44,7 +44,7 @@ export const CONCAT = (...list: ResultType[]): string => { return list.join(''); }; -const textFormulas: TextFormulaType = { +const formulas: TextFormulaType = { CONCAT, CONCATENATE: CONCAT, SPLIT, @@ -59,4 +59,4 @@ const textFormulas: TextFormulaType = { T, }; -export default textFormulas; +export default formulas;