diff --git a/.github/workflows/master-deploy.yml b/.github/workflows/master-deploy.yml index e6fa4662e1..76f563fac7 100644 --- a/.github/workflows/master-deploy.yml +++ b/.github/workflows/master-deploy.yml @@ -15,7 +15,7 @@ jobs: - name: Setup node uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '16' - name: Install dependencies run: yarn bootstrap diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 9023a3f349..03e5643b02 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -11,7 +11,8 @@ jobs: - name: Setup node uses: actions/setup-node@v2 with: - node-version: '12' + node-version: '16' + cache: 'yarn' - name: Install dependencies run: yarn bootstrap - name: Lint diff --git a/build/gen-dts.js b/build/gen-dts.js new file mode 100644 index 0000000000..7c10ad58b3 --- /dev/null +++ b/build/gen-dts.js @@ -0,0 +1,165 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const path = require('path') +const fs = require('fs') +const { Project } = require('ts-morph') +const vueCompiler = require('@vue/compiler-sfc') +const klawSync = require('klaw-sync') +const ora = require('ora') + +const TSCONFIG_PATH = path.resolve(__dirname, '../tsconfig.json') +const DEMO_RE = /\/demo\/\w+\.vue$/ +const TEST_RE = /__test__|__tests__/ +const excludedFiles = [ + 'mock', + 'package.json', + 'spec', + 'test', + 'tests', + 'css', + '.DS_Store', +] +const exclude = path => !excludedFiles.some(f => path.includes(f)) + +/** + * fork = require( https://github.com/egoist/vue-dts-gen/blob/main/src/index.ts + */ +const genVueTypes = async () => { + const project = new Project({ + compilerOptions: { + allowJs: true, + declaration: true, + emitDeclarationOnly: true, + noEmitOnError: false, + outDir: path.resolve(__dirname, '../dist'), + baseUrl: path.resolve(__dirname, '../'), + paths: { + '@element-plus/*': ['packages/*'], + }, + }, + tsConfigFilePath: TSCONFIG_PATH, + skipAddingFilesFromTsConfig: true, + }) + + const sourceFiles = [] + + const filePaths = klawSync(path.resolve(__dirname, '../packages'), { + nodir: true, + }) + .map(item => item.path) + .filter(path => !DEMO_RE.test(path)) + .filter(path => !TEST_RE.test(path)) + .filter(exclude) + + await Promise.all( + filePaths.map(async file => { + if (file.endsWith('.vue')) { + const content = await fs.promises.readFile(file, 'utf-8') + const sfc = vueCompiler.parse(content) + const { script, scriptSetup } = sfc.descriptor + if (script || scriptSetup) { + let content = '' + let isTS = false + if (script && script.content) { + content += script.content + if (script.lang === 'ts') isTS = true + } + if (scriptSetup) { + const compiled = vueCompiler.compileScript(sfc.descriptor, { + id: 'xxx', + }) + content += compiled.content + if (scriptSetup.lang === 'ts') isTS = true + } + const sourceFile = project.createSourceFile( + path.relative(process.cwd(), file) + (isTS ? '.ts' : '.js'), + content, + ) + sourceFiles.push(sourceFile) + } + } else if (file.endsWith('.ts')) { + const sourceFile = project.addSourceFileAtPath(file) + sourceFiles.push(sourceFile) + } + }), + ) + + // const diagnostics = project.getPreEmitDiagnostics() + + // TODO: print all diagnoses status and fix them one by one. + // console.log(project.formatDiagnosticsWithColorAndContext(diagnostics)) + + await project.emit({ + emitOnlyDtsFiles: true, + }) + + const ROOT_PATH = path.resolve(__dirname, '../packages') + const excludes = ['utils', 'directives', 'hooks', 'locale'] + const ElementPlusSign = '@element-plus/' + for (const sourceFile of sourceFiles) { + const sourceFilePathName = sourceFile.getFilePath() + + if (sourceFilePathName.includes('packages/element-plus')) { + sourceFile.getExportDeclarations().map(modifySpecifier) + } + + sourceFile.getImportDeclarations().map(modifySpecifier) + + function modifySpecifier(d) { + const specifier = d.getModuleSpecifierValue() + + if (specifier && specifier.includes(ElementPlusSign)) { + const importItem = specifier.slice(ElementPlusSign.length) + let replacer + if (excludes.some(e => importItem.startsWith(e))) { + replacer = '' + } else { + replacer = 'el-' + } + const originalPath = path.resolve( + ROOT_PATH, + `./${replacer}${importItem}`, + ) + const sourceFilePath = sourceFile.getFilePath() + + const sourceDir = sourceFilePath.includes('packages/element-plus') + ? path.dirname(path.resolve(sourceFilePath, '../')) + : path.dirname(sourceFilePath) + const replaceTo = path.relative(sourceDir, originalPath) + // This is a delicated judgment which might fail when edge case occurs + d.setModuleSpecifier( + replaceTo.startsWith('.') ? replaceTo : `./${replaceTo}`, + ) + } + } + // console.log(sourceFile.getFilePath()) + + const emitOutput = sourceFile.getEmitOutput() + for (const outputFile of emitOutput.getOutputFiles()) { + const filepath = outputFile.getFilePath() + + await fs.promises.mkdir(path.dirname(filepath), { + recursive: true, + }) + + await fs.promises.writeFile(filepath, outputFile.getText(), 'utf8') + } + } +} + +// const cwd = process.cwd() + +// function getRelativePath(_path) { +// console.log(_path) +// const relativePath = path.relative( +// cwd, +// path.resolve(__dirname, '../packages'), +// ) +// // console.log(path.relative(_path, relativePath)) +// return path.relative(_path, relativePath) +// } + +const spinner = ora('Generate types...\n').start() + +genVueTypes() + .then(() => spinner.succeed('Success !\n')) + .catch(e => spinner.fail(`${e} !\n`)) diff --git a/package.json b/package.json index ac346ea3ac..ec2cc88fbc 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,11 @@ "bootstrap": "yarn --frozen-lockfile && npx lerna bootstrap && yarn gen:version", "gen:version": "node build/gen-version.js", "build": "yarn bootstrap && yarn clean:lib && yarn build:esm-bundle && yarn build:lib && yarn build:lib-full && yarn build:esm && yarn build:utils && yarn build:locale && yarn build:locale-umd && yarn build:theme && yarn build:helper", - "clean:lib": "rimraf lib && rimraf es", + "clean:lib": "rimraf lib && rimraf es && rimraf dist", "build:lib": "cross-env LIBMODE=core webpack --config ./build/webpack.config.js", "build:lib-full": "cross-env LIBMODE=full webpack --config ./build/webpack.config.js", "build:esm-bundle": "rollup --config ./build/rollup.config.bundle.js && yarn build:type", - "build:type": "node build/gen-type.js", + "build:type": "node build/gen-dts.js", "build:esm": "node ./build/bincomp.js", "build:components": "rollup --config ./build/rollup.config.js", "build:utils": "cross-env BABEL_ENV=utils babel packages/utils --extensions .ts --out-dir lib/utils", @@ -78,6 +78,7 @@ "husky": "^4.2.5", "import-from": "^3.0.0", "jest": "^26.6.3", + "klaw-sync": "^6.0.0", "lerna": "^3.22.1", "lint-staged": "^10.2.13", "markdown-it": "^11.0.0", @@ -85,7 +86,7 @@ "markdown-it-chain": "^1.3.0", "markdown-it-container": "^3.0.0", "mini-css-extract-plugin": "^0.11.2", - "ora": "^5.1.0", + "ora": "^5.4.1", "rimraf": "^3.0.2", "rollup": "^2.28.2", "rollup-plugin-css-only": "^2.1.0", @@ -99,6 +100,7 @@ "throttle-debounce": "2.3.0", "transliteration": "^2.1.11", "ts-loader": "^8.0.3", + "ts-morph": "^11.0.3", "typescript": "^4.0.2", "url-loader": "^4.1.0", "vue": "3.1.1", @@ -152,7 +154,7 @@ "packages" ], "main": "lib/index.js", - "module": "lib/index.esm.js", + "module": "es/index.js", "typings": "lib/index.d.ts", "unpkg": "lib/index.js", "style": "lib/theme-chalk/index.css", diff --git a/packages/dropdown/src/dropdown.d.ts b/packages/dropdown/src/dropdown.ts similarity index 100% rename from packages/dropdown/src/dropdown.d.ts rename to packages/dropdown/src/dropdown.ts diff --git a/packages/dropdown/src/useDropdown.ts b/packages/dropdown/src/useDropdown.ts index 602b5fefee..e30ba4b182 100644 --- a/packages/dropdown/src/useDropdown.ts +++ b/packages/dropdown/src/useDropdown.ts @@ -2,7 +2,7 @@ import { inject, computed, ref } from 'vue' import { generateId, useGlobalConfig } from '@element-plus/utils/util' import { EVENT_CODE } from '@element-plus/utils/aria' import { on, addClass } from '@element-plus/utils/dom' -import { IElDropdownInstance } from './dropdown' +import type { IElDropdownInstance } from './dropdown' export const useDropdown = () => { const ELEMENT = useGlobalConfig() diff --git a/packages/element-plus/components.ts b/packages/element-plus/components.ts new file mode 100644 index 0000000000..b9ee8300a6 --- /dev/null +++ b/packages/element-plus/components.ts @@ -0,0 +1,88 @@ +export { default as ElAffix } from '@element-plus/affix' +export { default as ElAlert } from '@element-plus/alert' +export { default as ElAside } from '@element-plus/aside' +export { default as ElAutocomplete } from '@element-plus/autocomplete' +export { default as ElAvatar } from '@element-plus/avatar' +export { default as ElBacktop } from '@element-plus/backtop' +export { default as ElBadge } from '@element-plus/badge' +export { default as ElBreadcrumb } from '@element-plus/breadcrumb' +export { default as ElBreadcrumbItem } from '@element-plus/breadcrumb-item' +export { default as ElButton } from '@element-plus/button' +export { default as ElButtonGroup } from '@element-plus/button-group' +export { default as ElCalendar } from '@element-plus/calendar' +export { default as ElCard } from '@element-plus/card' +export { default as ElCarousel } from '@element-plus/carousel' +export { default as ElCarouselItem } from '@element-plus/carousel-item' +export { default as ElCascader } from '@element-plus/cascader' +export { default as ElCascaderPanel } from '@element-plus/cascader-panel' +export { default as ElCheckbox } from '@element-plus/checkbox' +export { default as ElCheckboxButton } from '@element-plus/checkbox-button' +export { default as ElCheckboxGroup } from '@element-plus/checkbox-group' +export { default as ElCol } from '@element-plus/col' +export { default as ElCollapse } from '@element-plus/collapse' +export { default as ElCollapseItem } from '@element-plus/collapse-item' +export { default as ElCollapseTransition } from '@element-plus/collapse-transition' +export { default as ElColorPicker } from '@element-plus/color-picker' +export { default as ElContainer } from '@element-plus/container' +export { default as ElDatePicker } from '@element-plus/date-picker' +export { default as ElDialog } from '@element-plus/dialog' +export { default as ElDivider } from '@element-plus/divider' +export { default as ElDrawer } from '@element-plus/drawer' +export { default as ElDropdown } from '@element-plus/dropdown' +export { default as ElDropdownItem } from '@element-plus/dropdown-item' +export { default as ElDropdownMenu } from '@element-plus/dropdown-menu' +export { default as ElEmpty } from '@element-plus/empty' +export { default as ElFooter } from '@element-plus/footer' +export { default as ElForm } from '@element-plus/form' +export { default as ElFormItem } from '@element-plus/form-item' +export { default as ElHeader } from '@element-plus/header' +export { default as ElIcon } from '@element-plus/icon' +export { default as ElImage } from '@element-plus/image' +export { default as ElImageViewer } from '@element-plus/image-viewer' +export { default as ElInput } from '@element-plus/input' +export { default as ElInputNumber } from '@element-plus/input-number' +export { default as ElLink } from '@element-plus/link' +export { default as ElMain } from '@element-plus/main' +export { default as ElMenu } from '@element-plus/menu' +export { default as ElMenuItem } from '@element-plus/menu-item' +export { default as ElMenuItemGroup } from '@element-plus/menu-item-group' +export { default as ElOption } from '@element-plus/option' +export { default as ElOptionGroup } from '@element-plus/option-group' +export { default as ElPageHeader } from '@element-plus/page-header' +export { default as ElPagination } from '@element-plus/pagination' +export { default as ElPopconfirm } from '@element-plus/popconfirm' +export { default as ElPopper } from '@element-plus/popper' +export { default as ElProgress } from '@element-plus/progress' +export { default as ElRadio } from '@element-plus/radio' +export { default as ElRadioButton } from '@element-plus/radio-button' +export { default as ElRadioGroup } from '@element-plus/radio-group' +export { default as ElRate } from '@element-plus/rate' +export { default as ElRow } from '@element-plus/row' +export { default as ElScrollbar } from '@element-plus/scrollbar' +export { default as ElSelect } from '@element-plus/select' +export { default as ElSlider } from '@element-plus/slider' +export { default as ElStep } from '@element-plus/step' +export { default as ElSteps } from '@element-plus/steps' +export { default as ElSubmenu } from '@element-plus/submenu' +export { default as ElSwitch } from '@element-plus/switch' +export { default as ElTabPane } from '@element-plus/tab-pane' +export { default as ElTable } from '@element-plus/table' +export { default as ElTableColumn } from '@element-plus/table-column' +export { default as ElTabs } from '@element-plus/tabs' +export { default as ElTag } from '@element-plus/tag' +export { default as ElTimePicker } from '@element-plus/time-picker' +export { default as ElTimeSelect } from '@element-plus/time-select' +export { default as ElTimeline } from '@element-plus/timeline' +export { default as ElTimelineItem } from '@element-plus/timeline-item' +export { default as ElTooltip } from '@element-plus/tooltip' +export { default as ElTransfer } from '@element-plus/transfer' +export { default as ElTree } from '@element-plus/tree' +export { default as ElUpload } from '@element-plus/upload' +export { default as ElSpace } from '@element-plus/space' +export { default as ElSkeleton } from '@element-plus/skeleton' +export { default as ElSkeletonItem } from '@element-plus/skeleton-item' +export { default as ElCheckTag } from '@element-plus/check-tag' +export { default as ElDescriptions } from '@element-plus/descriptions' +export { default as ElDescriptionsItem } from '@element-plus/descriptions-item' +export { default as ElResult } from '@element-plus/result' +export { default as ElSelectV2 } from '@element-plus/select-v2' diff --git a/packages/element-plus/index.ts b/packages/element-plus/index.ts index e40cedd76f..3f3f444376 100644 --- a/packages/element-plus/index.ts +++ b/packages/element-plus/index.ts @@ -1,108 +1,20 @@ -import type { App } from 'vue' -import ElAffix from '@element-plus/affix' -import ElAlert from '@element-plus/alert' -import ElAside from '@element-plus/aside' -import ElAutocomplete from '@element-plus/autocomplete' -import ElAvatar from '@element-plus/avatar' -import ElBacktop from '@element-plus/backtop' -import ElBadge from '@element-plus/badge' -import ElBreadcrumb from '@element-plus/breadcrumb' -import ElBreadcrumbItem from '@element-plus/breadcrumb-item' -import ElButton from '@element-plus/button' -import ElButtonGroup from '@element-plus/button-group' -import ElCalendar from '@element-plus/calendar' -import ElCard from '@element-plus/card' -import ElCarousel from '@element-plus/carousel' -import ElCarouselItem from '@element-plus/carousel-item' -import ElCascader from '@element-plus/cascader' -import ElCascaderPanel from '@element-plus/cascader-panel' -import ElCheckbox from '@element-plus/checkbox' -import ElCheckboxButton from '@element-plus/checkbox-button' -import ElCheckboxGroup from '@element-plus/checkbox-group' -import ElCol from '@element-plus/col' -import ElCollapse from '@element-plus/collapse' -import ElCollapseItem from '@element-plus/collapse-item' -import ElCollapseTransition from '@element-plus/collapse-transition' -import ElColorPicker from '@element-plus/color-picker' -import ElContainer from '@element-plus/container' -import ElDatePicker from '@element-plus/date-picker' -import ElDialog from '@element-plus/dialog' -import ElDivider from '@element-plus/divider' -import ElDrawer from '@element-plus/drawer' -import ElDropdown from '@element-plus/dropdown' -import ElDropdownItem from '@element-plus/dropdown-item' -import ElDropdownMenu from '@element-plus/dropdown-menu' -import ElEmpty from '@element-plus/empty' -import ElFooter from '@element-plus/footer' -import ElForm from '@element-plus/form' -import ElFormItem from '@element-plus/form-item' -import ElHeader from '@element-plus/header' -import ElIcon from '@element-plus/icon' -import ElImage from '@element-plus/image' -import ElImageViewer from '@element-plus/image-viewer' -import ElInfiniteScroll from '@element-plus/infinite-scroll' -import ElInput from '@element-plus/input' -import ElInputNumber from '@element-plus/input-number' -import ElLink from '@element-plus/link' -import ElLoading from '@element-plus/loading' -import ElMain from '@element-plus/main' -import ElMenu from '@element-plus/menu' -import ElMenuItem from '@element-plus/menu-item' -import ElMenuItemGroup from '@element-plus/menu-item-group' -import ElMessage from '@element-plus/message' -import ElMessageBox from '@element-plus/message-box' -import ElNotification from '@element-plus/notification' -import ElOption from '@element-plus/option' -import ElOptionGroup from '@element-plus/option-group' -import ElPageHeader from '@element-plus/page-header' -import ElPagination from '@element-plus/pagination' -import ElPopconfirm from '@element-plus/popconfirm' -import ElPopover from '@element-plus/popover' -import ElPopper from '@element-plus/popper' -import ElProgress from '@element-plus/progress' -import ElRadio from '@element-plus/radio' -import ElRadioButton from '@element-plus/radio-button' -import ElRadioGroup from '@element-plus/radio-group' -import ElRate from '@element-plus/rate' -import ElRow from '@element-plus/row' -import ElScrollbar from '@element-plus/scrollbar' -import ElSelect from '@element-plus/select' -import ElSlider from '@element-plus/slider' -import ElStep from '@element-plus/step' -import ElSteps from '@element-plus/steps' -import ElSubmenu from '@element-plus/submenu' -import ElSwitch from '@element-plus/switch' -import ElTabPane from '@element-plus/tab-pane' -import ElTable from '@element-plus/table' -import ElTableColumn from '@element-plus/table-column' -import ElTabs from '@element-plus/tabs' -import ElTag from '@element-plus/tag' -import ElTimePicker from '@element-plus/time-picker' -import ElTimeSelect from '@element-plus/time-select' -import ElTimeline from '@element-plus/timeline' -import ElTimelineItem from '@element-plus/timeline-item' -import ElTooltip from '@element-plus/tooltip' -import ElTransfer from '@element-plus/transfer' -import ElTree from '@element-plus/tree' -import ElUpload from '@element-plus/upload' -import ElSpace from '@element-plus/space' -import ElSkeleton from '@element-plus/skeleton' -import ElSkeletonItem from '@element-plus/skeleton-item' -import ElCheckTag from '@element-plus/check-tag' -import ElDescriptions from '@element-plus/descriptions' -import ElDescriptionsItem from '@element-plus/descriptions-item' -import ElResult from '@element-plus/result' -import ElSelectV2 from '@element-plus/select-v2' -import { use, i18n } from '@element-plus/locale' -// if you encountered problems alike "Can't resolve './version'" -// please run `yarn bootstrap` first -import { version as version_ } from './version' -import type { InstallOptions } from '@element-plus/utils/config' +import { setLocale, i18n } from '@element-plus/locale' import { setConfig } from '@element-plus/utils/config' import isServer from '@element-plus/utils/isServer' +// if you encountered problems alike "Can't resolve './version'" +// please run `yarn bootstrap` first +import * as components from './components' +import * as plugins from './plugins' +import { version as version_ } from './version' import dayjs from 'dayjs' +import type { App } from 'vue' +import type { InstallOptions } from '@element-plus/utils/config' + +export * from './components' +export * from './plugins' + type DWindow = Window & typeof globalThis & { dayjs?: typeof dayjs } @@ -118,230 +30,30 @@ if (!isServer) { const version = version_ // version_ to fix tsc issue -const locale = use - const defaultInstallOpt: InstallOptions = { size: '' as ComponentSize, zIndex: 2000, } -const components = [ - ElAffix, - ElAlert, - ElAside, - ElAutocomplete, - ElAvatar, - ElBacktop, - ElBadge, - ElBreadcrumb, - ElBreadcrumbItem, - ElButton, - ElButtonGroup, - ElCalendar, - ElCard, - ElCarousel, - ElCarouselItem, - ElCascader, - ElCascaderPanel, - ElCheckbox, - ElCheckboxButton, - ElCheckboxGroup, - ElCheckTag, - ElCol, - ElCollapse, - ElCollapseItem, - ElCollapseTransition, - ElColorPicker, - ElContainer, - ElDatePicker, - ElDialog, - ElDivider, - ElDrawer, - ElDropdown, - ElDropdownItem, - ElDropdownMenu, - ElEmpty, - ElFooter, - ElForm, - ElFormItem, - ElHeader, - ElIcon, - ElImage, - ElImageViewer, - ElInput, - ElInputNumber, - ElLink, - ElMain, - ElMenu, - ElMenuItem, - ElMenuItemGroup, - ElOption, - ElOptionGroup, - ElPageHeader, - ElPagination, - ElPopconfirm, - ElPopper, - ElProgress, - ElRadio, - ElRadioButton, - ElRadioGroup, - ElRate, - ElRow, - ElScrollbar, - ElSelect, - ElSlider, - ElStep, - ElSteps, - ElSubmenu, - ElSwitch, - ElTabPane, - ElTable, - ElTableColumn, - ElTabs, - ElTag, - ElTimePicker, - ElTimeSelect, - ElTimeline, - ElTimelineItem, - ElTooltip, - ElTransfer, - ElTree, - ElUpload, - ElSpace, - ElSkeleton, - ElSkeletonItem, - ElDescriptions, - ElDescriptionsItem, - ElResult, - ElSelectV2, -] - -const plugins = [ - ElInfiniteScroll, - ElLoading, - ElMessage, - ElMessageBox, - ElNotification, - ElPopover, -] - const install = (app: App, opt: InstallOptions): void => { const option = Object.assign(defaultInstallOpt, opt) - locale(option.locale) + setLocale(option.locale, app) if (option.i18n) { i18n(option.i18n) } app.config.globalProperties.$ELEMENT = option setConfig(option) - components.forEach(component => { - app.component(component.name, component) + Object.keys(components).forEach(c => { + app.use(components[c]) }) - plugins.forEach(plugin => { - app.use(plugin) + Object.keys(plugins).forEach(plugin => { + app.use(plugins[plugin]) }) } -export { - ElAffix, - ElAlert, - ElAside, - ElAutocomplete, - ElAvatar, - ElBacktop, - ElBadge, - ElBreadcrumb, - ElBreadcrumbItem, - ElButton, - ElButtonGroup, - ElCalendar, - ElCard, - ElCarousel, - ElCarouselItem, - ElCascader, - ElCascaderPanel, - ElCheckbox, - ElCheckboxButton, - ElCheckboxGroup, - ElCheckTag, - ElCol, - ElCollapse, - ElCollapseItem, - ElCollapseTransition, - ElColorPicker, - ElContainer, - ElDatePicker, - ElDialog, - ElDivider, - ElDrawer, - ElDropdown, - ElDropdownItem, - ElDropdownMenu, - ElEmpty, - ElFooter, - ElForm, - ElFormItem, - ElHeader, - ElIcon, - ElImage, - ElImageViewer, - ElInfiniteScroll, - ElInput, - ElInputNumber, - ElLink, - ElLoading, - ElMain, - ElMenu, - ElMenuItem, - ElMenuItemGroup, - ElMessage, - ElMessageBox, - ElNotification, - ElOption, - ElOptionGroup, - ElPageHeader, - ElPagination, - ElPopconfirm, - ElPopover, - ElPopper, - ElProgress, - ElRadio, - ElRadioButton, - ElRadioGroup, - ElRate, - ElRow, - ElScrollbar, - ElSelect, - ElSlider, - ElStep, - ElSteps, - ElSubmenu, - ElSwitch, - ElTabPane, - ElTable, - ElTableColumn, - ElTabs, - ElTag, - ElTimePicker, - ElTimeSelect, - ElTimeline, - ElTimelineItem, - ElTooltip, - ElTransfer, - ElTree, - ElUpload, - ElSpace, - ElSkeleton, - ElSkeletonItem, - ElDescriptions, - ElDescriptionsItem, - ElResult, - ElSelectV2, - version, - install, - locale, -} +export { version } export default { version, diff --git a/packages/element-plus/plugins.ts b/packages/element-plus/plugins.ts new file mode 100644 index 0000000000..30dd2b7d02 --- /dev/null +++ b/packages/element-plus/plugins.ts @@ -0,0 +1,6 @@ +export { default as ElInfiniteScroll } from '@element-plus/infinite-scroll' +export { default as ElLoading } from '@element-plus/loading' +export { default as ElMessage } from '@element-plus/message' +export { default as ElMessageBox } from '@element-plus/message-box' +export { default as ElNotification } from '@element-plus/notification' +export { default as ElPopover } from '@element-plus/popover' diff --git a/packages/locale/index.ts b/packages/locale/index.ts index 289dbf9c0b..3945166c3e 100644 --- a/packages/locale/index.ts +++ b/packages/locale/index.ts @@ -1,6 +1,7 @@ -import defaultLang from './lang/en' import dayjs from 'dayjs' +import defaultLang from './lang/en' +import type { App } from 'vue' export type TranslatePair = { [key: string]: string | string[] | TranslatePair @@ -12,6 +13,7 @@ export type Language = { } let lang: Language = defaultLang as Language +let app: App let i18nHandler: null | ((...args: any[]) => string) = null @@ -22,18 +24,21 @@ export const i18n = (fn: (...args: any[]) => string) => { function template(str: string, option) { if(!str || !option) return str - return str.replace(/\{(\w+)\}/g, (match, key) => { + return str.replace(/\{(\w+)\}/g, (_, key) => { return option[key] }) } -export const t = (...args: any[]): string => { - if (i18nHandler) return i18nHandler(...args) - +const defaultTranslator = (...args: any[]) => { const [path, option] = args let value const array = path.split('.') - let current = lang + let current: Record + if (!app) { + current = lang + } else { + current = app.config.globalProperties.$ELEMENT.locale + } for (let i = 0, j = array.length; i < j; i++) { const property = array[i] value = current[property] @@ -41,14 +46,24 @@ export const t = (...args: any[]): string => { if (!value) return '' current = value } - return '' } -export const use = (l: Language): void => { +export const t = (...args: any[]): string => { + if (i18nHandler) { + const translation = i18nHandler(...args) + if (!translation) { + return defaultTranslator(...args) + } + } + return defaultTranslator(...args) +} + +export const use = (l: Language, _app: App): void => { lang = l || lang + app = _app if (lang.name) { dayjs.locale(lang.name) } } -export default { use, t, i18n } +export const setLocale = use diff --git a/scripts/build.sh b/scripts/build.sh index 86b4639a67..b54498b442 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -7,17 +7,11 @@ # which means the result will not contain folder name includes utils yarn bootstrap yarn clean:lib -yarn build:esm-bundle -tar --exclude=index.esm.js -zcvf ./es.gz ./lib -mkdir -p es -tar -zxvf ./es.gz --strip-component 2 -C ./es +yarn build:type + yarn build:lib yarn build:lib-full -# -P2 stands for 2 maximum parallel, with -# node .build/build.js command -# find './packages' -type d -maxdepth 1 ! -name '*util*' ! -name '__mocks__' ! -name 'locale' ! -name 'theme*' -print0 | xargs -I {} -P2 -0 node ./build/build.comps.js {} - yarn build:components find ./packages/utils -type f ! -name '*.test.ts' ! -name 'package.json' -print0 \ @@ -25,7 +19,7 @@ find ./packages/utils -type f ! -name '*.test.ts' ! -name 'package.json' -print0 node ./build/build.entry.js -find ./packages/locale -type f ! -name '*.spec.ts' ! -name 'package.json' -print0 \ +find ./packages/locale -type f ! -name '*.spec.ts' ! -name 'package.json' ! -name '.DS_Store' -print0 \ | xargs -P2 -0 -I {} node ./build/build-util.js {} yarn build:locale-umd @@ -34,6 +28,33 @@ yarn build:theme yarn build:helper -# Post build clean up +# Post build cp type definitions +touch temp +find dist -type d ! -name 'element-plus' -depth 1 -print0 | xargs -0 -I {} sh -c "basename {}" > temp -rm ./es.gz +input="./temp" + +mkdir -p tempDir +while IFS= read -r line +do + filepath="el-$line" + case "$line" in + directives|locale|utils|hooks) + filepath="$line" + ;; + esac + mv "dist/$line" "tempDir/$filepath" + cp -nR "tempDir/" es + cp -nR "tempDir/" lib + +done < "$input" + +cp packages/utils/types.ts es/utils/ +cp dist/element-plus/* lib +cp packages/utils/types.ts lib/utils/ +cp dist/element-plus/* es + + +# Post build cleanup +rm -rf temp +rm -rf tempDir diff --git a/yarn.lock b/yarn.lock index 3dfca4664b..d242354870 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2308,6 +2308,16 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@ts-morph/common@~0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.10.1.tgz#be15b9ab13a32bbc1f6a6bd7dc056b2247b272eb" + integrity sha512-rKN/VtZUUlW4M+6vjLFSaFc1Z9sK+1hh0832ucPtPkXqOw/mSWE80Lau4z2zTPNTqtxAjfZbvKpQcEwJy0KIEg== + dependencies: + fast-glob "^3.2.5" + minimatch "^3.0.4" + mkdirp "^1.0.4" + path-browserify "^1.0.1" + "@types/anymatch@*": version "1.3.1" resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" @@ -3496,6 +3506,11 @@ base64-js@^1.0.2: version "1.3.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -3554,6 +3569,15 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.1.1, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3760,6 +3784,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-modules@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.1.0.tgz#aad97c15131eb76b65b50ef208e7584cd76a7484" @@ -4137,10 +4169,10 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.5.0.tgz#12763e47251bf951cb75c201dfa58ff1bcb2d047" - integrity sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ== +cli-spinners@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.0.tgz#36c7dc98fb6a9a76bd6238ec3f77e2425627e939" + integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q== cli-truncate@^2.1.0: version "2.1.0" @@ -4240,6 +4272,11 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" +code-block-writer@^10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-10.1.1.tgz#ad5684ed4bfb2b0783c8b131281ae84ee640a42f" + integrity sha512-67ueh2IRGst/51p0n6FvPrnRjAGHY5F8xdjkgrYE7DDzpJe6qA07RYQ9VcoUeo5ATOjSOiWpSL3SWBRRbempMw== + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -7184,6 +7221,11 @@ icss-utils@^5.0.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -7711,6 +7753,11 @@ is-unc-path@^1.0.0: dependencies: unc-path-regex "^0.1.2" +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -8405,6 +8452,13 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -8774,6 +8828,14 @@ log-symbols@^4.0.0: dependencies: chalk "^4.0.0" +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -9364,7 +9426,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -mute-stream@0.0.8, mute-stream@~0.0.4: +mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -9851,17 +9913,18 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-5.1.0.tgz#b188cf8cd2d4d9b13fd25383bc3e5cba352c94f8" - integrity sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w== +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== dependencies: + bl "^4.1.0" chalk "^4.1.0" cli-cursor "^3.1.0" - cli-spinners "^2.4.0" + cli-spinners "^2.5.0" is-interactive "^1.0.0" - log-symbols "^4.0.0" - mute-stream "0.0.8" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" strip-ansi "^6.0.0" wcwidth "^1.0.1" @@ -10143,6 +10206,11 @@ path-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -11035,7 +11103,7 @@ read@1, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" dependencies: @@ -12741,6 +12809,14 @@ ts-loader@^8.0.3: micromatch "^4.0.0" semver "^6.0.0" +ts-morph@^11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-11.0.3.tgz#01a92b3c2b5a48ccdf318ec90864229b8061d056" + integrity sha512-ymuPkndv9rzqTLiHWMkVrFXWcN4nBiBGhRP/kTC9F5amAAl7BNLfyrsTzMD1o9A0zishKoF1KQT/0yyFhJnPgA== + dependencies: + "@ts-morph/common" "~0.10.1" + code-block-writer "^10.1.1" + tslib@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"