From fb3180f2f2fbad54b4ab3a4262bda4939f7e8835 Mon Sep 17 00:00:00 2001 From: wangyu Date: Wed, 6 Dec 2023 15:37:37 +0800 Subject: [PATCH] modified: babel.config.js modified: example/App.tsx modified: example/index.tsx modified: index.ts modified: package.json modified: src/parser/Lexer.ts modified: src/parser/mappingRule.ts modified: src/parser/parseMappingRule.ts modified: src/parser/parser.ts modified: src/types/types.ts modified: tsconfig.json --- packages/inula-intl/babel.config.js | 18 ++--- packages/inula-intl/example/App.tsx | 2 +- packages/inula-intl/example/index.tsx | 4 +- packages/inula-intl/index.ts | 2 +- packages/inula-intl/package.json | 11 ++- packages/inula-intl/src/parser/Lexer.ts | 74 ++++++++++--------- packages/inula-intl/src/parser/mappingRule.ts | 2 +- .../inula-intl/src/parser/parseMappingRule.ts | 28 +++---- packages/inula-intl/src/parser/parser.ts | 17 ++--- packages/inula-intl/src/types/types.ts | 17 +++-- packages/inula-intl/tsconfig.json | 12 ++- 11 files changed, 97 insertions(+), 90 deletions(-) diff --git a/packages/inula-intl/babel.config.js b/packages/inula-intl/babel.config.js index ed7275da..df5b4f0b 100644 --- a/packages/inula-intl/babel.config.js +++ b/packages/inula-intl/babel.config.js @@ -13,7 +13,7 @@ * See the Mulan PSL v2 for more details. */ -const {preset} = require("./jest.config"); +const { preset } = require('./jest.config'); module.exports = { presets: [ [ @@ -23,19 +23,15 @@ module.exports = { browsers: ['> 1%', 'last 2 versions', 'not ie <= 8'], node: 'current', }, - useBuiltIns: 'usage', - corejs: 3, }, ], + ['@babel/preset-typescript'], [ - '@babel/preset-typescript', - ], - [ - "@babel/preset-react", + '@babel/preset-react', { - "runtime": "automatic", - "importSource": "openinula" - } - ] + runtime: 'automatic', + importSource: 'openinula', + }, + ], ], }; diff --git a/packages/inula-intl/example/App.tsx b/packages/inula-intl/example/App.tsx index 205a38f1..ba6166c7 100644 --- a/packages/inula-intl/example/App.tsx +++ b/packages/inula-intl/example/App.tsx @@ -39,7 +39,7 @@ const App = () => {
- +
diff --git a/packages/inula-intl/example/index.tsx b/packages/inula-intl/example/index.tsx index f4185e04..0678d203 100644 --- a/packages/inula-intl/example/index.tsx +++ b/packages/inula-intl/example/index.tsx @@ -17,9 +17,7 @@ import App from './App' function render() { Inula.render( - <> - - , + , document.querySelector('#root') as any ) } diff --git a/packages/inula-intl/index.ts b/packages/inula-intl/index.ts index da43b69b..776255b8 100644 --- a/packages/inula-intl/index.ts +++ b/packages/inula-intl/index.ts @@ -54,7 +54,7 @@ export default { IntlProvider: I18nProvider, injectIntl: injectIntl, RawIntlProvider: InjectProvider, -} +}; // 用于定义文本 export function defineMessages>(msgs: U): U { diff --git a/packages/inula-intl/package.json b/packages/inula-intl/package.json index e370b1b0..13d73b75 100644 --- a/packages/inula-intl/package.json +++ b/packages/inula-intl/package.json @@ -4,10 +4,11 @@ "description": "", "main": "build/intl.umd.js", "type": "commonjs", - "types": "build/index.d.ts", + "types": "build/@types/index.d.ts", "scripts": { "demo-serve": "webpack serve --mode=development", - "build": "rollup --config rollup.config.js", + "rollup-build": "rollup --config rollup.config.js && npm run build-types", + "build-types": "tsc -p tsconfig.json && rollup -c build-type.js", "test": "jest --config jest.config.js", "test-c": "jest --coverage" }, @@ -33,6 +34,7 @@ "@rollup/plugin-babel": "^6.0.3", "@rollup/plugin-node-resolve": "^7.1.3", "@rollup/plugin-typescript": "^11.0.0", + "rollup-plugin-dts": "^6.1.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@types/node": "^16.18.27", @@ -40,7 +42,6 @@ "babel": "^6.23.0", "babel-jest": "^29.5.0", "babel-loader": "^9.1.2", - "core-js": "3.31.0", "html-webpack-plugin": "^5.5.1", "jest": "29.3.1", "jest-environment-jsdom": "^29.5.0", @@ -56,8 +57,6 @@ "typescript": "4.9.3", "webpack": "^5.81.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.13.3", - "react": "18.2.0", - "react-dom": "18.2.0" + "webpack-dev-server": "^4.13.3" } } diff --git a/packages/inula-intl/src/parser/Lexer.ts b/packages/inula-intl/src/parser/Lexer.ts index c233861e..f4a602b1 100644 --- a/packages/inula-intl/src/parser/Lexer.ts +++ b/packages/inula-intl/src/parser/Lexer.ts @@ -14,51 +14,45 @@ */ import ruleUtils from '../utils/parseRuleUtils'; -import { LexerInterface } from "../types/interfaces"; - -const getMatch = ruleUtils.checkSticky() - ? // 正则表达式具有 sticky 标志 - (regexp, buffer) => regexp.exec(buffer) - : // 正则表达式具有 global 标志,匹配的字符串长度为 0,则表示匹配失败 - (regexp, buffer) => (regexp.exec(buffer)[0].length === 0 ? null : regexp.exec(buffer)); +import { LexerInterface } from '../types/interfaces'; class Lexer implements LexerInterface { readonly startState: string; readonly states: Record; private buffer: string = ''; private stack: string[] = []; - private index; - private line; - private col; - private queuedText; - private state; - private groups; - private error; + private index: number = 0; + private line: number = 1; + private col: number = 1; + private queuedText: string = ''; + private state: string = ''; + private groups: string[] = []; + private error: Record | undefined; private regexp; - private fast; - private queuedGroup; - private value; + private fast: object = {}; + private queuedGroup: string | null = ''; + private value: string = ''; - constructor(states, state) { - this.startState = state; - this.states = states; + constructor(unionReg: Record, startState: string) { + this.startState = startState; + this.states = unionReg; this.buffer = ''; this.stack = []; this.reset(); } - public reset(data?, info?) { + public reset(data?: string) { this.buffer = data || ''; this.index = 0; - this.line = info ? info.line : 1; - this.col = info ? info.col : 1; - this.queuedText = info ? info.queuedText : ''; - this.setState(info ? info.state : this.startState); - this.stack = info && info.stack ? info.stack.slice() : []; + this.line = 1; + this.col = 1; + this.queuedText = ''; + this.setState(this.startState); + this.stack = []; return this; } - private setState(state) { + private setState(state: string) { if (!state || this.state === state) { return; } @@ -71,15 +65,15 @@ class Lexer implements LexerInterface { } private popState() { - this.setState(this.stack.pop()); + this.setState(this.stack.pop()); } - private pushState(state) { + private pushState(state: string) { this.stack.push(this.state); this.setState(state); } - private getGroup(match) { + private getGroup(match: Record) { const groupCount = this.groups.length; for (let i = 0; i < groupCount; i++) { if (match[i + 1] !== undefined) { @@ -127,7 +121,7 @@ class Lexer implements LexerInterface { const group = this.getGroup(match); const text = match[0]; - if (error.fallback && match.index !== index) { + if (error?.fallback && match.index !== index) { this.queuedGroup = group; this.queuedText = text; return this.getToken(error, buffer.slice(index, match.index), index); @@ -136,7 +130,14 @@ class Lexer implements LexerInterface { return this.getToken(group, text, index); } - private getToken(group, text, offset) { + /** + * 獲取Token + * @param group 解析模板后獲得的屬性值 + * @param text 文本屬性的信息 + * @param offset 偏移量 + * @private + */ + private getToken(group: any, text: string, offset: number) { let lineNum = 0; let last = 1; // 最后一个换行符的索引位置 if (group.lineBreaks) { @@ -192,9 +193,14 @@ class Lexer implements LexerInterface { next: (): IteratorResult => { const token = this.next(); return { value: token, done: !token } as IteratorResult; - } - } + }, + }; } } +const getMatch = ruleUtils.checkSticky() + ? // 正则表达式具有 sticky 标志 + (regexp, buffer) => regexp.exec(buffer) + : // 正则表达式具有 global 标志,匹配的字符串长度为 0,则表示匹配失败 + (regexp, buffer) => (regexp.exec(buffer)[0].length === 0 ? null : regexp.exec(buffer)); export default Lexer; diff --git a/packages/inula-intl/src/parser/mappingRule.ts b/packages/inula-intl/src/parser/mappingRule.ts index 962816ca..54bee482 100644 --- a/packages/inula-intl/src/parser/mappingRule.ts +++ b/packages/inula-intl/src/parser/mappingRule.ts @@ -70,5 +70,5 @@ const select: Record = { export const mappingRule: Record = { body, arg, - select + select, }; diff --git a/packages/inula-intl/src/parser/parseMappingRule.ts b/packages/inula-intl/src/parser/parseMappingRule.ts index 55e9af13..9323378c 100644 --- a/packages/inula-intl/src/parser/parseMappingRule.ts +++ b/packages/inula-intl/src/parser/parseMappingRule.ts @@ -16,16 +16,16 @@ import Lexer from './Lexer'; import { mappingRule } from './mappingRule'; import ruleUtils from '../utils/parseRuleUtils'; -import { RawToken } from "../types/types"; +import { RawToken } from '../types/types'; const defaultErrorRule = ruleUtils.getRuleOptions('error', { lineBreaks: true, shouldThrow: true }); // 解析规则并生成词法分析器所需的数据结构,以便进行词法分析操作 function parseRules(rules: Record, hasStates: boolean): Record { let errorRule: Record | null = null; - const fast = {}; - let enableFast = true; - let unicodeFlag = null; + const fast: object = {}; + let enableFast: boolean = true; + let unicodeFlag: boolean | null = null; const groups: Record[] = []; const parts: string[] = []; @@ -108,11 +108,11 @@ export function checkStateGroup(group: Record, name: string, map: R } // 将国际化解析规则注入分词器中 -function parseMappingRule(mappingRule: Record, start?: string): Lexer { +function parseMappingRule(mappingRule: Record, startState?: string): Lexer { const keys = Object.getOwnPropertyNames(mappingRule); - if (!start) { - start = keys[0]; + if (!startState) { + startState = keys[0]; } // 将每个状态的规则解析为规则数组,并存储在 ruleMap 对象中 @@ -153,27 +153,27 @@ function parseMappingRule(mappingRule: Record, start?: string): Lex } } - const map = {}; + const mappingAllRules = {}; - // 将规则映射为词法分析器数据结构,并存储在 map 对象中 + // 将规则映射为词法分析器数据结构,并存储在 mappingAllRules 对象中 keys.forEach(key => { - map[key] = parseRules(ruleMap[key], true); + mappingAllRules[key] = parseRules(ruleMap[key], true); }); // 检查状态组中的规则是否正确引用了其他状态 keys.forEach(name => { - const state = map[name]; + const state = mappingAllRules[name]; const groups = state.groups; groups.forEach(group => { - checkStateGroup(group, name, map); + checkStateGroup(group, name, mappingAllRules); }); const fastKeys = Object.getOwnPropertyNames(state.fast); fastKeys.forEach(fastKey => { - checkStateGroup(state.fast[fastKey], name, map); + checkStateGroup(state.fast[fastKey], name, mappingAllRules); }); }); - return new Lexer(map, start); + return new Lexer(mappingAllRules, startState); } function processFast(match, fast: {}, options) { diff --git a/packages/inula-intl/src/parser/parser.ts b/packages/inula-intl/src/parser/parser.ts index 76a6f9fd..cf885f67 100644 --- a/packages/inula-intl/src/parser/parser.ts +++ b/packages/inula-intl/src/parser/parser.ts @@ -17,7 +17,7 @@ import { lexer } from './parseMappingRule'; import { RawToken, Token } from '../types/types'; import { DEFAULT_PLURAL_KEYS } from '../constants'; import { Content, FunctionArg, PlainArg, Select, TokenContext } from '../types/interfaces'; -import Lexer from "./Lexer"; +import Lexer from './Lexer'; const getContext = (lt: Record): TokenContext => ({ offset: lt.offset, @@ -29,15 +29,14 @@ const getContext = (lt: Record): TokenContext => ({ export const checkSelectType = (value: string): boolean => { return value === 'plural' || value === 'select' || value === 'selectordinal'; -} +}; class Parser { - lexer: Lexer; cardinalKeys: string[] = DEFAULT_PLURAL_KEYS; ordinalKeys: string[] = DEFAULT_PLURAL_KEYS; constructor(message: string) { - this.lexer = lexer.reset(message); + lexer.reset(message); } isSelectKeyValid(token: RawToken, type: Select['type'], value: string) { @@ -60,7 +59,7 @@ class Parser { isPlural = true; } - for (const token of this.lexer) { + for (const token of lexer) { switch (token.type) { case 'offset': { if (type === 'select') { @@ -97,7 +96,7 @@ class Parser { parseToken(token: RawToken, isPlural: boolean): PlainArg | FunctionArg | Select { const context = getContext(token); - const nextToken = this.lexer.next(); + const nextToken = lexer.next(); if (!nextToken) { throw new Error('The message end position is invalid.'); @@ -111,7 +110,7 @@ class Parser { return { type: 'argument', arg: token.value, ctx: context }; } case 'func-simple': { - const end = this.lexer.next(); + const end = lexer.next(); if (!end) { throw new Error('The message end position is invalid.'); } @@ -159,7 +158,7 @@ class Parser { const tokens: any[] = []; let content: string | Content | null = null; - for (const token of this.lexer) { + for (const token of lexer) { if (token.type === 'argument') { if (content) { content = null; @@ -175,7 +174,7 @@ class Parser { } else if (token.type === 'doubleapos') { tokens.push(token.value); } else if (token.type === 'quoted') { - tokens.push(token.value) + tokens.push(token.value); } else if (token.type === 'content') { tokens.push(token.value); } else { diff --git a/packages/inula-intl/src/types/types.ts b/packages/inula-intl/src/types/types.ts index 2a7e463b..d5607ab6 100644 --- a/packages/inula-intl/src/types/types.ts +++ b/packages/inula-intl/src/types/types.ts @@ -21,9 +21,10 @@ import { Select, FunctionArg, I18nContextProps, - configProps + configProps, + InjectedIntl, } from './interfaces'; -import I18n from "../core/I18n"; +import I18n from '../core/I18n'; export type Error = string | ((message, id, context) => string); @@ -71,11 +72,15 @@ export type RawToken = { col: number; }; -export type I18nProviderProps = I18nContextProps & configProps +export type I18nProviderProps = I18nContextProps & configProps; export type IntlType = { i18n: I18n; - formatMessage: Function, - formatNumber: Function, - formatDate: Function, + formatMessage: Function; + formatNumber: Function; + formatDate: Function; +}; + +export interface InjectedIntlProps { + intl: InjectedIntl; } diff --git a/packages/inula-intl/tsconfig.json b/packages/inula-intl/tsconfig.json index 2ea73c31..f3ff266e 100644 --- a/packages/inula-intl/tsconfig.json +++ b/packages/inula-intl/tsconfig.json @@ -31,6 +31,7 @@ "declaration": true, "experimentalDecorators": true, "downlevelIteration": true, + "declarationDir": "./build/@types", // 赋值为空数组使@types/node不会起作用 "lib": [ "dom", @@ -53,19 +54,22 @@ } }, "include": [ - "./src/**/*", - "./src/format/**/*.ts", - "./example/**/*" + "./index.ts" ], "exclude": [ "node_modules", "lib", "**/*.spec.ts", - "dev" + "dev", + "./example/**/*", + "./tsconfig.json" ], "types": [ "node", "jest", "@testing-library/jest-dom" + ], + "files": [ + "./index.ts" ] }