diff --git a/.gitignore b/.gitignore
index 7db53e38e91e812e04b17ba4da0bff69cc00e2d7..fa4da9be8f31c1d453cab0e49a160bcb5e584c34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ yarn-error.log
packages/devui-vue/devui/vue-devui.ts
packages/devui-vue/devui/theme/theme.scss
packages/devui-vue/docs/.vitepress/config/sidebar.ts
+/packages/devui-cli/lib/
diff --git a/README.md b/README.md
index 7032a70ee6a51adac432ab6b7df70bea3d641396..a930fe3ad9699f981e3cebadf5f9b352de1d0cd5 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
+
diff --git a/package.json b/package.json
index 05e54180e333e016861f725422283e2fa6f925e4..89d20a4803ba8ba21e061c95c090e031a395598a 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,9 @@
"name": "root",
"private": true,
"scripts": {
- "dev": "lerna run dev",
+ "prepare": "yarn build:cli",
+ "build:cli": "lerna exec --scope @devui/cli yarn build",
+ "dev": "lerna exec --scope vue-devui yarn dev",
"build": "lerna run build",
"build:lib": "lerna run build:lib"
},
diff --git a/packages/devui-cli/README.md b/packages/devui-cli/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..396c156323d35cb97645e695fd67aac08d54f609
--- /dev/null
+++ b/packages/devui-cli/README.md
@@ -0,0 +1,3 @@
+# devui-cli
+
+devui-cli
diff --git a/packages/devui-cli/bin.js b/packages/devui-cli/bin.js
new file mode 100755
index 0000000000000000000000000000000000000000..3bd8a4236df14e12ab0f9cad53212b3c6d92e4e2
--- /dev/null
+++ b/packages/devui-cli/bin.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require("./lib/bin");
diff --git a/packages/devui-cli/package.json b/packages/devui-cli/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..187c7a92cc412fd722ac8e7a5f5ad0f42f618dcf
--- /dev/null
+++ b/packages/devui-cli/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "@devui/cli",
+ "version": "1.0.0",
+ "license": "MIT",
+ "main": "lib/index.js",
+ "typings": "lib/index.d.ts",
+ "bin": {
+ "devui-cli": "./bin.js"
+ },
+ "scripts": {
+ "dev": "tsc --watch",
+ "build": "tsc"
+ },
+ "devDependencies": {
+ "@types/chalk": "^2.2.0",
+ "@types/commander": "^2.12.2",
+ "@types/ora": "^3.2.0",
+ "@types/node": "^14.11.8",
+ "@types/fs-extra": "^9.0.2",
+ "@babel/traverse": "^7.15.4",
+ "@babel/parser": "^7.15.5",
+ "@types/babel-traverse": "^6.25.7",
+ "vite": "^2.4.4",
+ "chalk": "^4.1.2",
+ "commander": "^8.1.0",
+ "inquirer": "^8.1.2",
+ "ora": "^5.4.1",
+ "typescript": "^4.3.2"
+ }
+}
diff --git a/packages/devui-cli/src/bin.ts b/packages/devui-cli/src/bin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..79eaabc8d40a56899c9f971fadc03ad44999c6f2
--- /dev/null
+++ b/packages/devui-cli/src/bin.ts
@@ -0,0 +1,33 @@
+#!/usr/bin/env node
+import { Command } from "commander";
+import { create, validateCreateType } from "./commands/create";
+import { generateTheme } from "./commands/generate-theme";
+import { CREATE_SUPPORT_TYPES, VERSION } from "./shared/constant";
+
+import {build} from '.';
+
+
+const program = new Command();
+
+program.version(VERSION);
+
+program
+ .command("create")
+ .description("创建一个组件模板或配置文件")
+ .option(
+ "-t --type ",
+ `创建类型,可选值:${CREATE_SUPPORT_TYPES.join(", ")}`,
+ validateCreateType
+ )
+ .option("--ignore-parse-error", "忽略解析错误", false)
+ .option("--cover", "覆盖原文件", false)
+ .action(create);
+
+program.command("build").description("打包组件库").action(build);
+
+program
+ .command("generate:theme")
+ .description("生成主题变量文件")
+ .action(generateTheme);
+
+program.parse().version(VERSION);
diff --git a/packages/devui-vue/devui-cli/commands/build.js b/packages/devui-cli/src/commands/build.ts
similarity index 32%
rename from packages/devui-vue/devui-cli/commands/build.js
rename to packages/devui-cli/src/commands/build.ts
index 48c472f47b673f88f715fc4b738f97ea93d45a35..362dd98437843ce1700ab35d5ea1a0a2de1b679a 100644
--- a/packages/devui-vue/devui-cli/commands/build.js
+++ b/packages/devui-cli/src/commands/build.ts
@@ -1,59 +1,62 @@
-const path = require('path')
-const fs = require('fs')
-const fsExtra = require('fs-extra')
-const { defineConfig, build } = require('vite')
-const vue = require('@vitejs/plugin-vue')
-const vueJsx = require('@vitejs/plugin-vue-jsx')
+import fs from "fs";
+import fsExtra from "fs-extra";
+import path from "path";
+import type { InlineConfig } from "vite";
+import { build as ViteBuild } from "vite";
+import { CWD } from "../shared/constant";
-const entryDir = path.resolve(__dirname, '../../devui')
-const outputDir = path.resolve(__dirname, '../../build')
+const vue = require("@vitejs/plugin-vue");
+const vueJsx = require("@vitejs/plugin-vue-jsx");
-const baseConfig = defineConfig({
+const entryDir = path.join(CWD, "/devui");
+const outputDir = path.join(CWD, "build");
+
+const baseConfig: InlineConfig = {
configFile: false,
publicDir: false,
- plugins: [ vue(), vueJsx() ]
-})
+ plugins: [vue(), vueJsx()],
+};
const rollupOptions = {
- external: ['vue', 'vue-router'],
+ external: ["vue", "vue-router"],
output: {
globals: {
- vue: 'Vue'
- }
- }
-}
+ vue: "Vue",
+ },
+ },
+};
const buildSingle = async (name) => {
- await build(defineConfig({
+ await ViteBuild({
...baseConfig,
build: {
rollupOptions,
lib: {
entry: path.resolve(entryDir, name),
- name: 'index',
- fileName: 'index',
- formats: ['es', 'umd']
+ name: "index",
+ fileName: "index",
+ formats: ["es", "umd"],
},
- outDir: path.resolve(outputDir, name)
- }
- }))
-}
+ outDir: path.resolve(outputDir, name),
+ },
+ });
+};
const buildAll = async () => {
- await build(defineConfig({
+ await ViteBuild({
...baseConfig,
build: {
rollupOptions,
lib: {
- entry: path.resolve(entryDir, 'vue-devui.ts'),
- name: 'vue-devui',
- fileName: 'vue-devui',
- formats: ['es', 'umd']
+ entry: path.resolve(entryDir, "vue-devui.ts"),
+ name: "vue-devui",
+ fileName: "vue-devui",
+ formats: ["es", "umd"],
},
- outDir: outputDir
- }
- }))
-}
+ outDir: outputDir,
+ },
+ });
+};
const createPackageJson = (name) => {
const fileStr = `{
@@ -62,26 +65,26 @@ const createPackageJson = (name) => {
"main": "index.umd.js",
"module": "index.es.js",
"style": "style.css"
-}`
+}`;
fsExtra.outputFile(
path.resolve(outputDir, `${name}/package.json`),
fileStr,
- 'utf-8'
- )
-}
+ "utf-8"
+ );
+};
-exports.build = async () => {
- await buildAll()
+export const build = async () => {
+ await buildAll();
- const components = fs.readdirSync(entryDir).filter(name => {
- const componentDir = path.resolve(entryDir, name)
- const isDir = fs.lstatSync(componentDir).isDirectory()
- return isDir && fs.readdirSync(componentDir).includes('index.ts')
- })
+ const components = fs.readdirSync(entryDir).filter((name) => {
+ const componentDir = path.resolve(entryDir, name);
+ const isDir = fs.lstatSync(componentDir).isDirectory();
+ return isDir && fs.readdirSync(componentDir).includes("index.ts");
+ });
- for(const name of components) {
- await buildSingle(name)
- createPackageJson(name)
+ for (const name of components) {
+ await buildSingle(name);
+ createPackageJson(name);
}
-}
+};
diff --git a/packages/devui-vue/devui-cli/commands/create.js b/packages/devui-cli/src/commands/create.ts
similarity index 35%
rename from packages/devui-vue/devui-cli/commands/create.js
rename to packages/devui-cli/src/commands/create.ts
index 91433ada765ab462e4ed653fca4eecaf3aa28150..08042ef5212b3e3c7cb215e28c58cf059af4b977 100644
--- a/packages/devui-vue/devui-cli/commands/create.js
+++ b/packages/devui-cli/src/commands/create.ts
@@ -1,106 +1,117 @@
-const logger = require('../shared/logger')
-const {
- bigCamelCase,
- resolveDirFilesInfo,
- parseExportByFileInfo,
- parseComponentInfo
-} = require('../shared/utils')
-const fs = require('fs-extra')
-const { resolve } = require('path')
-const {
- DEVUI_NAMESPACE,
- DEVUI_DIR,
- TESTS_DIR_NAME,
- COMPONENT_PARTS_MAP,
- INDEX_FILE_NAME,
- DOCS_FILE_NAME,
- VUE_DEVUI_FILE,
- VUE_DEVUI_IGNORE_DIRS,
- VUE_DEVUI_FILE_NAME,
+import fs from "fs-extra";
+import inquirer from "inquirer";
+import { isEmpty, kebabCase } from "lodash";
+import ora from "ora";
+import { resolve } from "path";
+import {
+ selectCategory,
+ selectParts,
+ typeName,
+ typeTitle,
+} from "../inquirers/component";
+import { selectCreateType } from "../inquirers/create";
+import {
CREATE_SUPPORT_TYPES,
- CREATE_UNFINISHED_TYPES,
CREATE_SUPPORT_TYPE_MAP,
+ CREATE_UNFINISHED_TYPES,
+ DEVUI_DIR,
+ DOCS_FILE_NAME,
+ INDEX_FILE_NAME,
SITES_COMPONENTS_DIR,
+ TESTS_DIR_NAME,
VITEPRESS_SIDEBAR_FILE,
- VITEPRESS_SIDEBAR_FILE_NAME
-} = require('../shared/constant')
-const { isEmpty, kebabCase } = require('lodash')
-const inquirer = require('inquirer')
-const { selectCreateType } = require('../inquirers/create')
-const { selectCategory, selectParts, typeName, typeTitle } = require('../inquirers/component')
-const {
+ VITEPRESS_SIDEBAR_FILE_NAME,
+ VUE_DEVUI_FILE,
+ VUE_DEVUI_FILE_NAME,
+ VUE_DEVUI_IGNORE_DIRS,
+} from "../shared/constant";
+import { logger } from "../shared/logger";
+import {
+ bigCamelCase,
+ parseComponentInfo,
+ parseExportByFileInfo,
+ resolveDirFilesInfo,
+} from "../shared/utils";
+import {
createComponentTemplate,
- createStyleTemplate,
- createTypesTemplate,
createDirectiveTemplate,
- createServiceTemplate,
+ createDocumentTemplate,
createIndexTemplate,
+ createServiceTemplate,
+ createStyleTemplate,
createTestsTemplate,
- createDocumentTemplate
-} = require('../templates/component')
-const { createVueDevuiTemplate } = require('../templates/vue-devui')
-const ora = require('ora')
-const { createVitepressSidebarTemplate } = require('../templates/vitepress-sidebar')
+ createTypesTemplate,
+} from "../templates/component";
+import { createVitepressSidebarTemplate } from "../templates/vitepress-sidebar";
+import { createVueDevuiTemplate } from "../templates/vue-devui";
-exports.validateCreateType = (type) => {
- const re = new RegExp('^(' + CREATE_SUPPORT_TYPES.map((t) => `(${t})`).join('|') + ')$')
- const flag = re.test(type)
+export const validateCreateType = (type) => {
+ const re = new RegExp(
+ "^(" + CREATE_SUPPORT_TYPES.map((t) => `(${t})`).join("|") + ")$"
+ );
+ const flag = re.test(type);
- !flag && logger.error(`类型错误,可选类型为:${CREATE_SUPPORT_TYPES.join(', ')}`)
+ !flag &&
+ logger.error(`类型错误,可选类型为:${CREATE_SUPPORT_TYPES.join(", ")}`);
- return flag ? type : null
-}
+ return flag ? type : null;
+};
// TODO: 待优化代码结构
-exports.create = async (cwd) => {
- let { type } = cwd
+export const create = async (cwd) => {
+ let { type } = cwd;
if (isEmpty(type)) {
- const result = await inquirer.prompt([selectCreateType()])
- type = result.type
+ const result = await inquirer.prompt([selectCreateType()]);
+ type = result.type;
}
if (CREATE_UNFINISHED_TYPES.includes(type)) {
- logger.info('抱歉,该功能暂未完成!')
- process.exit(0)
+ logger.info("抱歉,该功能暂未完成!");
+ process.exit(0);
}
- let params = {}
+ let params: any = {};
try {
switch (type) {
case CREATE_SUPPORT_TYPE_MAP.component:
- params = await inquirer.prompt([typeName(), typeTitle(), selectCategory(), selectParts()])
- params.hasComponent = params.parts.includes('component')
- params.hasDirective = params.parts.includes('directive')
- params.hasService = params.parts.includes('service')
-
- await createComponent(params, cwd)
- break
- case CREATE_SUPPORT_TYPE_MAP['vue-devui']:
+ params = await inquirer.prompt([
+ typeName(),
+ typeTitle(),
+ selectCategory(),
+ selectParts(),
+ ]);
+ params.hasComponent = params.parts.includes("component");
+ params.hasDirective = params.parts.includes("directive");
+ params.hasService = params.parts.includes("service");
+
+ await createComponent({ params, cwd });
+ break;
+ case CREATE_SUPPORT_TYPE_MAP["vue-devui"]:
// 创建 devui/vue-devui.ts
- await createVueDevui(params, cwd)
+ await createVueDevui(params, cwd);
// 创建 docs/.vitepress/config/sidebar.ts
- await createVitepressSidebar()
- break
+ await createVitepressSidebar();
+ break;
default:
- break
+ break;
}
} catch (e) {
- logger.error(e.toString())
- process.exit(1)
+ logger.error(e.toString());
+ process.exit(1);
}
-}
+};
-async function createComponent(params = {}) {
- let { name, hasComponent, hasDirective, hasService } = params
+async function createComponent(params) {
+ let { name, hasComponent, hasDirective, hasService } = params;
- const componentName = kebabCase(name)
- const styleName = kebabCase(name)
- const typesName = kebabCase(name) + '-types'
- const directiveName = kebabCase(name) + '-directive'
- const serviceName = kebabCase(name) + '-service'
- const testName = kebabCase(name) + '.spec'
+ const componentName = kebabCase(name);
+ const styleName = kebabCase(name);
+ const typesName = kebabCase(name) + "-types";
+ const directiveName = kebabCase(name) + "-directive";
+ const serviceName = kebabCase(name) + "-service";
+ const testName = kebabCase(name) + ".spec";
const _params = {
...params,
@@ -109,126 +120,146 @@ async function createComponent(params = {}) {
directiveName,
serviceName,
styleName,
- testName
- }
-
- const componentTemplate = createComponentTemplate(_params)
- const styleTemplate = createStyleTemplate(_params)
- const typesTemplate = createTypesTemplate(_params)
- const directiveTemplate = createDirectiveTemplate(_params)
- const serviceTemplate = createServiceTemplate(_params)
- const indexTemplate = createIndexTemplate(_params)
+ testName,
+ };
+
+ const componentTemplate = createComponentTemplate(_params);
+ const styleTemplate = createStyleTemplate(_params);
+ const typesTemplate = createTypesTemplate(_params);
+ const directiveTemplate = createDirectiveTemplate();
+ const serviceTemplate = createServiceTemplate(_params);
+ const indexTemplate = createIndexTemplate(_params);
// 增加测试模板
- const testsTemplate = createTestsTemplate(_params)
+ const testsTemplate = createTestsTemplate(_params);
// 增加文档模板
- const docTemplate = createDocumentTemplate(_params)
+ const docTemplate = createDocumentTemplate(_params);
- const componentDir = resolve(DEVUI_DIR, componentName)
- const srcDir = resolve(componentDir, 'src')
- const testsDir = resolve(DEVUI_DIR, componentName, TESTS_DIR_NAME)
- const docsDir = resolve(SITES_COMPONENTS_DIR, componentName)
+ const componentDir = resolve(DEVUI_DIR, componentName);
+ const srcDir = resolve(componentDir, "src");
+ const testsDir = resolve(DEVUI_DIR, componentName, TESTS_DIR_NAME);
+ const docsDir = resolve(SITES_COMPONENTS_DIR, componentName);
if (fs.pathExistsSync(componentDir)) {
- logger.error(`${bigCamelCase(componentName)} 组件目录已存在!`)
- process.exit(1)
+ logger.error(`${bigCamelCase(componentName)} 组件目录已存在!`);
+ process.exit(1);
}
- let spinner = ora(`创建组件 ${bigCamelCase(componentName)} 开始...`).start()
+ let spinner = ora(`创建组件 ${bigCamelCase(componentName)} 开始...`).start();
try {
- await Promise.all([fs.mkdirs(componentDir), fs.mkdirs(srcDir), fs.mkdirs(testsDir)])
+ await Promise.all([
+ fs.mkdirs(componentDir),
+ fs.mkdirs(srcDir),
+ fs.mkdirs(testsDir),
+ ]);
const writeFiles = [
fs.writeFile(resolve(componentDir, INDEX_FILE_NAME), indexTemplate),
fs.writeFile(resolve(testsDir, `${testName}.ts`), testsTemplate),
- ]
+ ];
if (!fs.existsSync(docsDir)) {
- fs.mkdirSync(docsDir)
- writeFiles.push(fs.writeFile(resolve(docsDir, DOCS_FILE_NAME), docTemplate))
+ fs.mkdirSync(docsDir);
+ writeFiles.push(
+ fs.writeFile(resolve(docsDir, DOCS_FILE_NAME), docTemplate)
+ );
} else {
- logger.warning(`\n${bigCamelCase(componentName)} 组件文档已存在:${resolve(docsDir, DOCS_FILE_NAME)}`)
+ logger.warning(
+ `\n${bigCamelCase(componentName)} 组件文档已存在:${resolve(
+ docsDir,
+ DOCS_FILE_NAME
+ )}`
+ );
}
if (hasComponent || hasService) {
- writeFiles.push(fs.writeFile(resolve(srcDir, `${typesName}.ts`), typesTemplate))
+ writeFiles.push(
+ fs.writeFile(resolve(srcDir, `${typesName}.ts`), typesTemplate)
+ );
}
if (hasComponent) {
writeFiles.push(
- fs.writeFile(resolve(srcDir, `${componentName}.tsx`), componentTemplate),
+ fs.writeFile(
+ resolve(srcDir, `${componentName}.tsx`),
+ componentTemplate
+ ),
fs.writeFile(resolve(srcDir, `${styleName}.scss`), styleTemplate)
- )
+ );
}
if (hasDirective) {
- writeFiles.push(fs.writeFile(resolve(srcDir, `${directiveName}.ts`), directiveTemplate))
+ writeFiles.push(
+ fs.writeFile(resolve(srcDir, `${directiveName}.ts`), directiveTemplate)
+ );
}
if (hasService) {
- writeFiles.push(fs.writeFile(resolve(srcDir, `${serviceName}.ts`), serviceTemplate))
+ writeFiles.push(
+ fs.writeFile(resolve(srcDir, `${serviceName}.ts`), serviceTemplate)
+ );
}
- await Promise.all(writeFiles)
+ await Promise.all(writeFiles);
- spinner.succeed(`创建组件 ${bigCamelCase(componentName)} 成功!`)
- logger.info(`组件目录:${componentDir}`)
+ spinner.succeed(`创建组件 ${bigCamelCase(componentName)} 成功!`);
+ logger.info(`组件目录:${componentDir}`);
} catch (e) {
- spinner.fail(e.toString())
- process.exit(1)
+ spinner.fail(e.toString());
+ process.exit(1);
}
}
async function createVueDevui(params, { ignoreParseError }) {
- const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS)
- const exportModules = []
+ const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS);
+ const exportModules = [];
fileInfo.forEach((f) => {
- const em = parseExportByFileInfo(f, ignoreParseError)
+ const em = parseExportByFileInfo(f, ignoreParseError);
- if (isEmpty(em)) return
+ if (isEmpty(em)) return;
- exportModules.push(em)
- })
+ exportModules.push(em);
+ });
- const template = createVueDevuiTemplate(exportModules)
+ const template = createVueDevuiTemplate(exportModules);
- let spinner = ora(`创建 ${VUE_DEVUI_FILE_NAME} 文件开始...`).start()
+ let spinner = ora(`创建 ${VUE_DEVUI_FILE_NAME} 文件开始...`).start();
try {
- await fs.writeFile(VUE_DEVUI_FILE, template, { encoding: 'utf-8' })
+ await fs.writeFile(VUE_DEVUI_FILE, template, { encoding: "utf-8" });
- spinner.succeed(`创建 ${VUE_DEVUI_FILE_NAME} 文件成功!`)
- logger.info(`文件地址:${VUE_DEVUI_FILE}`)
+ spinner.succeed(`创建 ${VUE_DEVUI_FILE_NAME} 文件成功!`);
+ logger.info(`文件地址:${VUE_DEVUI_FILE}`);
} catch (e) {
- spinner.fail(e.toString())
- process.exit(1)
+ spinner.fail(e.toString());
+ process.exit(1);
}
}
async function createVitepressSidebar() {
- const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS)
- const componentsInfo = []
+ const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS);
+ const componentsInfo = [];
fileInfo.forEach((f) => {
- const info = parseComponentInfo(f.dirname)
+ const info = parseComponentInfo(f.dirname);
- if (isEmpty(info)) return
+ if (isEmpty(info)) return;
- componentsInfo.push(info)
- })
+ componentsInfo.push(info);
+ });
- const template = createVitepressSidebarTemplate(componentsInfo)
+ const template = createVitepressSidebarTemplate(componentsInfo);
- let spinner = ora(`创建 ${VITEPRESS_SIDEBAR_FILE_NAME} 文件开始...`).start()
+ let spinner = ora(`创建 ${VITEPRESS_SIDEBAR_FILE_NAME} 文件开始...`).start();
try {
- await fs.writeFile(VITEPRESS_SIDEBAR_FILE, template, { encoding: 'utf-8' })
+ await fs.writeFile(VITEPRESS_SIDEBAR_FILE, template, { encoding: "utf-8" });
- spinner.succeed(`创建 ${VITEPRESS_SIDEBAR_FILE_NAME} 文件成功!`)
- logger.info(`文件地址:${VITEPRESS_SIDEBAR_FILE}`)
+ spinner.succeed(`创建 ${VITEPRESS_SIDEBAR_FILE_NAME} 文件成功!`);
+ logger.info(`文件地址:${VITEPRESS_SIDEBAR_FILE}`);
} catch (e) {
- spinner.fail(e.toString())
- process.exit(1)
+ spinner.fail(e.toString());
+ process.exit(1);
}
}
diff --git a/packages/devui-cli/src/commands/generate-theme.ts b/packages/devui-cli/src/commands/generate-theme.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c8aea78a8d25f4d2b1397ceb4c0c435a07454768
--- /dev/null
+++ b/packages/devui-cli/src/commands/generate-theme.ts
@@ -0,0 +1,14 @@
+import fs from "fs-extra";
+import path from "path";
+import { CWD } from "../shared/constant";
+
+require("esbuild-register");
+const theme = require(path.join(CWD, "/devui/theme/themes/light"));
+const themeFilePath = path.join(CWD, "/devui/theme/theme.scss");
+const fileStr = Object.entries(theme)
+ .map(([key, value]) => `$${key}: var(--${key}, ${value})`)
+ .join(";\n");
+
+export const generateTheme = async () => {
+ await fs.outputFile(themeFilePath, fileStr, "utf-8");
+};
diff --git a/packages/devui-cli/src/index.ts b/packages/devui-cli/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6e80f56a8d3fc54c9813c04d2d7bd266bcec5f5e
--- /dev/null
+++ b/packages/devui-cli/src/index.ts
@@ -0,0 +1,4 @@
+import { create } from "./commands/create";
+import { build } from './commands/build';
+
+export { build, create };
diff --git a/packages/devui-cli/src/inquirers/component.ts b/packages/devui-cli/src/inquirers/component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..99485f0c9594f979e3fef99b313d7cf3e20d3e10
--- /dev/null
+++ b/packages/devui-cli/src/inquirers/component.ts
@@ -0,0 +1,56 @@
+import {
+ COMPONENT_PARTS_MAP,
+ VITEPRESS_SIDEBAR_CATEGORY,
+} from "../shared/constant";
+
+export const typeName = () => ({
+ name: "name",
+ type: "input",
+ message: "(必填)请输入组件 name ,将用作目录及文件名:",
+ validate: (value) => {
+ if (value.trim() === "") {
+ return "组件 name 是必填项!";
+ }
+ return true;
+ },
+});
+
+export const typeTitle = () => ({
+ name: "title",
+ type: "input",
+ message: "(必填)请输入组件中文名称,将用作文档列表显示:",
+ validate: (value) => {
+ if (value.trim() === "") {
+ return "组件名称是必填项!";
+ }
+ return true;
+ },
+});
+
+export const selectCategory = () => ({
+ name: "category",
+ type: "list",
+ message: "(必填)请选择组件分类,将用作文档列表分类:",
+ choices: VITEPRESS_SIDEBAR_CATEGORY,
+ default: 0,
+});
+
+export const typeAliasName = () => ({
+ name: "alias",
+ type: "input",
+ message: "(选填)请输入组件 name 别名,将用作组件别名被导出:",
+});
+
+export const selectParts = () => ({
+ name: "parts",
+ type: "checkbox",
+ message: "(必填)请选择包含部件,将自动生成部件文件:",
+ choices: COMPONENT_PARTS_MAP,
+ default: [],
+ validate: (value) => {
+ if (value.length === 0) {
+ return "部件必须包含至少一项";
+ }
+ return true;
+ },
+});
diff --git a/packages/devui-cli/src/inquirers/create.ts b/packages/devui-cli/src/inquirers/create.ts
new file mode 100644
index 0000000000000000000000000000000000000000..01b9a46267fe89cca6160f60c0994921c7489a17
--- /dev/null
+++ b/packages/devui-cli/src/inquirers/create.ts
@@ -0,0 +1,9 @@
+import { CREATE_SUPPORT_TYPES } from "../shared/constant";
+
+export const selectCreateType = () => ({
+ name: "type",
+ type: "list",
+ message: "(必填)请选择创建类型:",
+ choices: CREATE_SUPPORT_TYPES,
+ default: 0,
+});
diff --git a/packages/devui-cli/src/shared/constant.ts b/packages/devui-cli/src/shared/constant.ts
new file mode 100644
index 0000000000000000000000000000000000000000..853b4dcbad54f691747a71a2b1cf80cba10f9c23
--- /dev/null
+++ b/packages/devui-cli/src/shared/constant.ts
@@ -0,0 +1,58 @@
+import { join } from "path";
+// @ts-ignore
+import packageJson from "../../package.json";
+
+const { version } = packageJson;
+export const VERSION = version;
+export const CWD = process.cwd();
+export const DEVUI_DIR = join(CWD, "devui");
+export const DEVUI_NAMESPACE = "d";
+export const CSS_CLASS_PREFIX = "devui";
+export const TESTS_DIR_NAME = "__tests__";
+export const INDEX_FILE_NAME = "index.ts";
+export const DOCS_FILE_NAME = "index.md";
+export const VUE_DEVUI_IGNORE_DIRS = ["shared", "style"];
+export const VUE_DEVUI_FILE_NAME = "vue-devui.ts";
+export const VUE_DEVUI_FILE = join(DEVUI_DIR, VUE_DEVUI_FILE_NAME);
+export const SITES_DIR = join(CWD, "docs");
+export const SITES_COMPONENTS_DIR_NAME = "components";
+export const SITES_COMPONENTS_DIR = join(SITES_DIR, SITES_COMPONENTS_DIR_NAME);
+export const VITEPRESS_DIR = join(SITES_DIR, ".vitepress");
+export const VITEPRESS_SIDEBAR_FILE_NAME = "sidebar.ts";
+export const VITEPRESS_SIDEBAR_FILE = join(
+ VITEPRESS_DIR,
+ `config/${VITEPRESS_SIDEBAR_FILE_NAME}`
+);
+
+// 这里的分类顺序将会影响最终生成的页面侧边栏顺序
+export const VITEPRESS_SIDEBAR_CATEGORY = [
+ "通用",
+ "导航",
+ "反馈",
+ "数据录入",
+ "数据展示",
+ "布局",
+];
+
+export const COMPONENT_PARTS_MAP = [
+ {
+ name: "component(组件)",
+ value: "component",
+ },
+ {
+ name: "directive(指令)",
+ value: "directive",
+ },
+ {
+ name: "service(服务)",
+ value: "service",
+ },
+];
+
+export const CREATE_SUPPORT_TYPE_MAP = Object.freeze({
+ component: "component",
+ "vue-devui": "vue-devui",
+ "theme-variable": "theme-variable",
+});
+export const CREATE_SUPPORT_TYPES = Object.keys(CREATE_SUPPORT_TYPE_MAP);
+export const CREATE_UNFINISHED_TYPES = [];
diff --git a/packages/devui-cli/src/shared/logger.ts b/packages/devui-cli/src/shared/logger.ts
new file mode 100644
index 0000000000000000000000000000000000000000..680d5583a24562c8a03116745a2f7c07c98956f3
--- /dev/null
+++ b/packages/devui-cli/src/shared/logger.ts
@@ -0,0 +1,16 @@
+import chalk from "chalk";
+
+export const logger = {
+ info(text: string) {
+ console.log(chalk.hex("#00afef")(text));
+ },
+ success(text: string) {
+ console.log(chalk.hex("#00c48f")(text));
+ },
+ warning(text: string) {
+ console.log(chalk.hex("#ff9800")(text));
+ },
+ error(text: string) {
+ console.log(chalk.hex("#f44336")(text));
+ },
+};
diff --git a/packages/devui-vue/devui-cli/shared/utils.js b/packages/devui-cli/src/shared/utils.ts
similarity index 33%
rename from packages/devui-vue/devui-cli/shared/utils.js
rename to packages/devui-cli/src/shared/utils.ts
index 11fb60c7065a929734587fda721d59df57f0960a..436848cb1c3040e08bdc54d095c9bc677e84d903 100644
--- a/packages/devui-vue/devui-cli/shared/utils.js
+++ b/packages/devui-cli/src/shared/utils.ts
@@ -1,16 +1,17 @@
-const { camelCase, upperFirst } = require('lodash')
-const { INDEX_FILE_NAME, DEVUI_DIR } = require('./constant')
-const { resolve } = require('path')
-const logger = require('./logger')
-const fs = require('fs-extra')
-const traverse = require("@babel/traverse").default
-const babelParser = require("@babel/parser")
-
-exports.bigCamelCase = (str) => {
- return upperFirst(camelCase(str))
-}
+import fs from "fs-extra";
+import { camelCase, upperFirst } from "lodash";
+import { resolve } from "path";
+import { DEVUI_DIR, INDEX_FILE_NAME } from "./constant";
+import { logger } from "./logger";
+
+const traverse = require("@babel/traverse").default;
+const babelParser = require("@babel/parser");
+
+export const bigCamelCase = (str: string) => {
+ return upperFirst(camelCase(str));
+};
-exports.resolveDirFilesInfo = (targetDir, ignoreDirs = []) => {
+export const resolveDirFilesInfo = (targetDir: string, ignoreDirs = []) => {
return fs
.readdirSync(targetDir)
.filter(
@@ -21,104 +22,111 @@ exports.resolveDirFilesInfo = (targetDir, ignoreDirs = []) => {
fs.existsSync(resolve(targetDir, dir, INDEX_FILE_NAME))
)
.map((dir) => ({
- name: this.bigCamelCase(dir),
+ name: bigCamelCase(dir),
dirname: dir,
- path: resolve(targetDir, dir, INDEX_FILE_NAME)
- }))
+ path: resolve(targetDir, dir, INDEX_FILE_NAME),
+ }));
+};
+
+interface exportModuleI {
+ default: string;
+ parts: Array;
+ fileInfo: string;
}
-exports.parseExportByFileInfo = (fileInfo, ignoreParseError) => {
- const exportModule = {}
- const indexContent = fs.readFileSync(fileInfo.path, { encoding: 'utf-8' })
+export const parseExportByFileInfo = (fileInfo, ignoreParseError) => {
+ const exportModule: exportModuleI = { default: "", fileInfo: "", parts: [] };
+ const indexContent = fs.readFileSync(fileInfo.path, { encoding: "utf-8" });
const ast = babelParser.parse(indexContent, {
- sourceType: 'module',
- plugins: [
- 'typescript'
- ]
- })
+ sourceType: "module",
+ plugins: ["typescript"],
+ });
- const exportName = []
- let exportDefault = null
+ const exportName = [];
+ let exportDefault = null;
traverse(ast, {
- ExportNamedDeclaration({node}) {
+ ExportNamedDeclaration({ node }) {
if (node.specifiers.length) {
- node.specifiers.forEach(specifier => {
- exportName.push(specifier.local.name)
- })
+ node.specifiers.forEach((specifier) => {
+ exportName.push(specifier.local.name);
+ });
} else if (node.declaration) {
if (node.declaration.declarations) {
- node.declaration.declarations.forEach(dec => {
- exportName.push(dec.id.name)
- })
+ node.declaration.declarations.forEach((dec) => {
+ exportName.push(dec.id.name);
+ });
} else if (node.declaration.id) {
- exportName.push(node.declaration.id.name)
+ exportName.push(node.declaration.id.name);
}
}
},
ExportDefaultDeclaration() {
- exportDefault = fileInfo.name + 'Install'
- }
- })
+ exportDefault = fileInfo.name + "Install";
+ },
+ });
if (!exportDefault) {
- logger.error(`${fileInfo.path} must have "export default".`)
+ logger.error(`${fileInfo.path} must have "export default".`);
if (ignoreParseError) {
- return exportModule
+ return exportModule;
} else {
- process.exit(1)
+ process.exit(1);
}
}
if (!exportName.length) {
- logger.error(`${fileInfo.path} must have "export xxx".`)
-
+ logger.error(`${fileInfo.path} must have "export xxx".`);
+
if (ignoreParseError) {
- return exportModule
+ return exportModule;
} else {
- process.exit(1)
+ process.exit(1);
}
}
- exportModule.default = exportDefault
- exportModule.parts = exportName
- exportModule.fileInfo = fileInfo
+ exportModule.default = exportDefault;
+ exportModule.parts = exportName;
+ exportModule.fileInfo = fileInfo;
- return exportModule
-}
+ return exportModule;
+};
-exports.parseComponentInfo = (name) => {
+export const parseComponentInfo = (name: string) => {
const componentInfo = {
- name: this.bigCamelCase(name)
- }
- let hasExportDefault = false
- const indexContent = fs.readFileSync(resolve(DEVUI_DIR, name, INDEX_FILE_NAME), { encoding: 'utf-8' })
+ name: bigCamelCase(name),
+ };
+ let hasExportDefault = false;
+ const indexContent = fs.readFileSync(
+ resolve(DEVUI_DIR, name, INDEX_FILE_NAME),
+ { encoding: "utf-8" }
+ );
const ast = babelParser.parse(indexContent, {
- sourceType: 'module',
- plugins: [
- 'typescript'
- ]
- })
+ sourceType: "module",
+ plugins: ["typescript"],
+ });
traverse(ast, {
- ExportDefaultDeclaration({node}) {
- hasExportDefault = true
+ ExportDefaultDeclaration({ node }) {
+ hasExportDefault = true;
if (node.declaration && node.declaration.properties) {
- const properties = node.declaration.properties
- properties.forEach(pro => {
- if (pro.type === 'ObjectProperty') {
- componentInfo[pro.key.name] = pro.value.value
+ const properties = node.declaration.properties;
+ properties.forEach((pro) => {
+ if (pro.type === "ObjectProperty") {
+ componentInfo[pro.key.name] = pro.value.value;
}
- })
+ });
}
- }
- })
+ },
+ });
if (!hasExportDefault) {
- logger.warning(`${componentInfo.name} must have "export default" and component info.`)
+ logger.warning(
+ `${componentInfo.name} must have "export default" and component info.`
+ );
}
- return componentInfo
-}
+ return componentInfo;
+};
diff --git a/packages/devui-vue/devui-cli/templates/component.js b/packages/devui-cli/src/templates/component.ts
similarity index 61%
rename from packages/devui-vue/devui-cli/templates/component.js
rename to packages/devui-cli/src/templates/component.ts
index 8e0909c48621ec4cf315e1321554456a05282cc7..d70617bbbee89a49c9230a0f357783215a1e7ec0 100644
--- a/packages/devui-vue/devui-cli/templates/component.js
+++ b/packages/devui-cli/src/templates/component.ts
@@ -1,11 +1,17 @@
-const { DEVUI_NAMESPACE, CSS_CLASS_PREFIX } = require('../shared/constant')
-const { camelCase } = require('lodash')
-const { bigCamelCase } = require('../shared/utils')
+import { camelCase } from "lodash";
+import { CSS_CLASS_PREFIX, DEVUI_NAMESPACE } from "../shared/constant";
+import { bigCamelCase } from "../shared/utils";
// 创建组件模板
-exports.createComponentTemplate = ({ styleName, componentName, typesName }) => `\
+export const createComponentTemplate = ({
+ styleName,
+ componentName,
+ typesName,
+}) => `\
import { defineComponent } from 'vue'
-import { ${camelCase(componentName)}Props, ${bigCamelCase(componentName)}Props } from './${typesName}'
+import { ${camelCase(componentName)}Props, ${bigCamelCase(
+ componentName
+)}Props } from './${typesName}'
import './${styleName}.scss'
export default defineComponent({
@@ -18,10 +24,10 @@ export default defineComponent({
}
}
})
-`
+`;
// 创建类型声明模板
-exports.createTypesTemplate = ({ componentName }) => `\
+export const createTypesTemplate = ({ componentName }) => `\
import type { PropType, ExtractPropTypes } from 'vue'
export const ${camelCase(componentName)}Props = {
@@ -30,11 +36,13 @@ export const ${camelCase(componentName)}Props = {
} \*\/
} as const
-export type ${bigCamelCase(componentName)}Props = ExtractPropTypes
-`
+export type ${bigCamelCase(
+ componentName
+)}Props = ExtractPropTypes
+`;
// 创建指令模板
-exports.createDirectiveTemplate = () => `\
+export const createDirectiveTemplate = () => `\
// can export function.
export default {
created() { },
@@ -45,9 +53,13 @@ export default {
beforeUnmount() { },
unmounted() { }
}
-`
+`;
// 创建server模板
-exports.createServiceTemplate = ({ componentName, typesName, serviceName }) => `\
+export const createServiceTemplate = ({
+ componentName,
+ typesName,
+ serviceName,
+}) => `\
import { ${bigCamelCase(componentName)}Props } from './${typesName}'
const ${bigCamelCase(serviceName)} = {
@@ -55,17 +67,17 @@ const ${bigCamelCase(serviceName)} = {
}
export default ${bigCamelCase(serviceName)}
-`
+`;
// 创建scss模板
-exports.createStyleTemplate = ({ componentName }) => `\
+export const createStyleTemplate = ({ componentName }) => `\
.${CSS_CLASS_PREFIX}-${componentName} {
//
}
-`
+`;
// 创建index模板
-exports.createIndexTemplate = ({
+export const createIndexTemplate = ({
title,
category,
hasComponent,
@@ -73,27 +85,39 @@ exports.createIndexTemplate = ({
hasService,
componentName,
directiveName,
- serviceName
+ serviceName,
}) => {
- const importComponentStr = `\nimport ${bigCamelCase(componentName)} from './src/${componentName}'`
- const importDirectiveStr = `\nimport ${bigCamelCase(directiveName)} from './src/${directiveName}'`
- const importServiceStr = `\nimport ${bigCamelCase(serviceName)} from './src/${serviceName}'`
-
- const installComponentStr = ` app.use(${bigCamelCase(componentName)} as any)`
- const installDirectiveStr = `\n app.directive('${bigCamelCase(componentName)}', ${bigCamelCase(directiveName)})`
- const installServiceStr = `\n app.config.globalProperties.$${camelCase(serviceName)} = ${bigCamelCase(
+ const importComponentStr = `\nimport ${bigCamelCase(
+ componentName
+ )} from './src/${componentName}'`;
+ const importDirectiveStr = `\nimport ${bigCamelCase(
+ directiveName
+ )} from './src/${directiveName}'`;
+ const importServiceStr = `\nimport ${bigCamelCase(
+ serviceName
+ )} from './src/${serviceName}'`;
+
+ const installComponentStr = ` app.use(${bigCamelCase(
+ componentName
+ )} as any)`;
+ const installDirectiveStr = `\n app.directive('${bigCamelCase(
+ componentName
+ )}', ${bigCamelCase(directiveName)})`;
+ const installServiceStr = `\n app.config.globalProperties.$${camelCase(
serviceName
- )}`
+ )} = ${bigCamelCase(serviceName)}`;
- const getPartStr = (state, str) => (state ? str : '')
+ const getPartStr = (state, str) => (state ? str : "");
- const importStr = getPartStr(hasComponent, importComponentStr) +
- getPartStr(hasDirective, importDirectiveStr) +
- getPartStr(hasService, importServiceStr)
+ const importStr =
+ getPartStr(hasComponent, importComponentStr) +
+ getPartStr(hasDirective, importDirectiveStr) +
+ getPartStr(hasService, importServiceStr);
- const installStr = getPartStr(hasComponent, installComponentStr) +
- getPartStr(hasDirective, installDirectiveStr) +
- getPartStr(hasService, installServiceStr)
+ const installStr =
+ getPartStr(hasComponent, installComponentStr) +
+ getPartStr(hasDirective, installDirectiveStr) +
+ getPartStr(hasService, installServiceStr);
return `\
import type { App } from 'vue'\
@@ -101,17 +125,19 @@ ${importStr}
${
hasComponent
? `\n${bigCamelCase(componentName)}.install = function(app: App): void {
- app.component(${bigCamelCase(componentName)}.name, ${bigCamelCase(componentName)})
+ app.component(${bigCamelCase(componentName)}.name, ${bigCamelCase(
+ componentName
+ )})
}\n`
- : ''
+ : ""
}
export { ${[
hasComponent ? bigCamelCase(componentName) : null,
hasDirective ? bigCamelCase(directiveName) : null,
- hasService ? bigCamelCase(serviceName) : null
+ hasService ? bigCamelCase(serviceName) : null,
]
.filter((p) => p !== null)
- .join(', ')} }
+ .join(", ")} }
export default {
title: '${bigCamelCase(componentName)} ${title}',
@@ -121,39 +147,36 @@ export default {
${installStr}
}
}
-`
-}
+`;
+};
// 创建测试模板
-exports.createTestsTemplate = ({
+export const createTestsTemplate = ({
componentName,
directiveName,
serviceName,
hasComponent,
hasDirective,
- hasService
+ hasService,
}) => `\
import { mount } from '@vue/test-utils';
import { ${[
- hasComponent ? bigCamelCase(componentName) : null,
- hasDirective ? bigCamelCase(directiveName) : null,
- hasService ? bigCamelCase(serviceName) : null
- ]
- .filter((p) => p !== null)
- .join(', ')} } from '../index';
+ hasComponent ? bigCamelCase(componentName) : null,
+ hasDirective ? bigCamelCase(directiveName) : null,
+ hasService ? bigCamelCase(serviceName) : null,
+]
+ .filter((p) => p !== null)
+ .join(", ")} } from '../index';
describe('${componentName} test', () => {
it('${componentName} init render', async () => {
// todo
})
})
-`
+`;
// 创建文档模板
-exports.createDocumentTemplate = ({
- componentName,
- title
-}) => `\
+export const createDocumentTemplate = ({ componentName, title }) => `\
# ${bigCamelCase(componentName)} ${title}
// todo 组件描述
@@ -209,4 +232,4 @@ d-${componentName} 事件
| | | | |
| | | | |
-`
+`;
diff --git a/packages/devui-vue/devui-cli/templates/vitepress-sidebar.js b/packages/devui-cli/src/templates/vitepress-sidebar.ts
similarity index 35%
rename from packages/devui-vue/devui-cli/templates/vitepress-sidebar.js
rename to packages/devui-cli/src/templates/vitepress-sidebar.ts
index ee079340e486e227daea5c8190784cbeea83c7ad..452a48466f0f15f921a70818a91e166bf69a6873 100644
--- a/packages/devui-vue/devui-cli/templates/vitepress-sidebar.js
+++ b/packages/devui-cli/src/templates/vitepress-sidebar.ts
@@ -1,35 +1,47 @@
-const { kebabCase } = require('lodash')
-const { SITES_COMPONENTS_DIR_NAME, VITEPRESS_SIDEBAR_CATEGORY } = require('../shared/constant')
-const logger = require('../shared/logger')
+import { kebabCase } from "lodash";
+import {
+ SITES_COMPONENTS_DIR_NAME,
+ VITEPRESS_SIDEBAR_CATEGORY,
+} from "../shared/constant";
+import { logger } from "../shared/logger";
function buildComponentOptions(text, name, status) {
- return { text, link: `/${SITES_COMPONENTS_DIR_NAME}/${kebabCase(name)}/`, status }
+ return {
+ text,
+ link: `/${SITES_COMPONENTS_DIR_NAME}/${kebabCase(name)}/`,
+ status,
+ };
}
function buildCategoryOptions(text, children = []) {
- return { text, children }
+ return { text, children };
}
-exports.createVitepressSidebarTemplate = (componentsInfo = []) => {
- const rootNav = { text: '快速开始', link: '/' }
- const categoryMap = VITEPRESS_SIDEBAR_CATEGORY.reduce((map, cate) => map.set(cate, []), new Map())
+export const createVitepressSidebarTemplate = (componentsInfo = []) => {
+ const rootNav = { text: "快速开始", link: "/" };
+ const categoryMap = VITEPRESS_SIDEBAR_CATEGORY.reduce(
+ (map, cate) => map.set(cate, []),
+ new Map()
+ );
componentsInfo.forEach((info) => {
if (categoryMap.has(info.category)) {
- categoryMap.get(info.category).push(buildComponentOptions(info.title, info.name, info.status))
+ categoryMap
+ .get(info.category)
+ .push(buildComponentOptions(info.title, info.name, info.status));
} else {
- logger.warning(`组件 ${info.name} 的分类 ${info.category} 不存在!`)
+ logger.warning(`组件 ${info.name} 的分类 ${info.category} 不存在!`);
}
- })
+ });
const sidebar = [].concat(
rootNav,
Array.from(categoryMap).map(([k, v]) => buildCategoryOptions(k, v))
- )
+ );
return `\
export default {
- '/': ${JSON.stringify(sidebar, null, 2).replace(/\n/g, '\n\t')}
-}
-`
+ '/': ${JSON.stringify(sidebar, null, 2).replace(/\n/g, "\n\t")}
}
+`;
+};
diff --git a/packages/devui-vue/devui-cli/templates/vue-devui.js b/packages/devui-cli/src/templates/vue-devui.ts
similarity index 31%
rename from packages/devui-vue/devui-cli/templates/vue-devui.js
rename to packages/devui-cli/src/templates/vue-devui.ts
index c6def01b3867c322248f3e06ce151b9f4d15b30e..14be28eaff4aa767e5f0116122f56001e3d6e5fc 100644
--- a/packages/devui-vue/devui-cli/templates/vue-devui.js
+++ b/packages/devui-cli/src/templates/vue-devui.ts
@@ -1,36 +1,38 @@
-const { relative } = require('path')
-const { INDEX_FILE_NAME, VERSION, VUE_DEVUI_FILE } = require('../shared/constant')
+import { relative } from "path";
+import { INDEX_FILE_NAME, VERSION, VUE_DEVUI_FILE } from "../shared/constant";
-exports.createVueDevuiTemplate = (exportModules = []) => {
- const packages = []
- const imports = []
- const installs = []
+export const createVueDevuiTemplate = (exportModules = []) => {
+ const packages = [];
+ const imports = [];
+ const installs = [];
exportModules.forEach((m) => {
- const { fileInfo } = m
+ const { fileInfo } = m;
const relativePath = relative(VUE_DEVUI_FILE, fileInfo.path)
- .replace(/\\/g, '/')
- .replace('..', '.')
- .replace('/' + INDEX_FILE_NAME, '')
+ .replace(/\\/g, "/")
+ .replace("..", ".")
+ .replace("/" + INDEX_FILE_NAME, "");
- const importStr = `import ${m.default}, { ${m.parts.join(', ')} } from '${relativePath}'`
+ const importStr = `import ${m.default}, { ${m.parts.join(
+ ", "
+ )} } from '${relativePath}'`;
- packages.push(...m.parts)
- imports.push(importStr)
- installs.push(m.default)
- })
+ packages.push(...m.parts);
+ imports.push(importStr);
+ installs.push(m.default);
+ });
const template = `\
import type { App } from 'vue'
-${imports.join('\n')}
+${imports.join("\n")}
const installs = [
- ${installs.join(',\n\t')}
+ ${installs.join(",\n\t")}
]
export {
- ${packages.join(',\n\t')}
+ ${packages.join(",\n\t")}
}
export default {
@@ -39,7 +41,7 @@ export default {
installs.forEach((p) => app.use(p as any))
}
}
-`
+`;
- return template
-}
+ return template;
+};
diff --git a/packages/devui-cli/tsconfig.json b/packages/devui-cli/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..2d6eda1d30bd1985352e529fa63762c03ca0397a
--- /dev/null
+++ b/packages/devui-cli/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "outDir": "./lib",
+ "module": "commonjs",
+ "declaration": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "lib": ["esnext", "dom"]
+ },
+ "include": ["src/**/*", "site"],
+ "exclude": ["node_modules"]
+}
diff --git a/packages/devui-vue/devui-cli/commands/generate-theme.js b/packages/devui-vue/devui-cli/commands/generate-theme.js
deleted file mode 100644
index 3acfa026b87d7bc467abdb1015a9d2cae6cc2d0b..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/commands/generate-theme.js
+++ /dev/null
@@ -1,16 +0,0 @@
-require('esbuild-register')
-const path = require('path')
-const fs = require('fs-extra')
-const theme = require('../../devui/theme/themes/light.ts').default
-
-const fileStr = Object.entries(theme)
-.map(([key, value]) => `$${key}: var(--${key}, ${value})`)
-.join(';\n')
-
-exports.generateTheme = async () => {
- await fs.outputFile(
- path.resolve(__dirname, '../../devui/theme/theme.scss'),
- fileStr,
- 'utf-8'
- )
-}
\ No newline at end of file
diff --git a/packages/devui-vue/devui-cli/index.js b/packages/devui-vue/devui-cli/index.js
deleted file mode 100755
index d4ed9906e6fe7e2f2b8c41cab1765391bdae6fd0..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env node
-const { Command } = require('commander')
-const { create, validateCreateType } = require('./commands/create')
-const { build } = require('./commands/build')
-const { generateTheme } = require('./commands/generate-theme')
-const { VERSION, CREATE_SUPPORT_TYPES } = require('./shared/constant')
-
-const program = new Command()
-
-program
- .command('create')
- .description('创建一个组件模板或配置文件')
- .option('-t --type ', `创建类型,可选值:${CREATE_SUPPORT_TYPES.join(', ')}`, validateCreateType)
- .option('--ignore-parse-error', '忽略解析错误', false)
- .option('--cover', '覆盖原文件', false)
- .action(create)
-
-program
- .command('build')
- .description('打包组件库')
- .action(build)
-
-program
- .command('generate:theme')
- .description('生成主题变量文件')
- .action(generateTheme)
-
-program.parse().version(VERSION)
diff --git a/packages/devui-vue/devui-cli/inquirers/component.js b/packages/devui-vue/devui-cli/inquirers/component.js
deleted file mode 100644
index 355a2b09470c21a9c0f78df8314393d67da0f72d..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/inquirers/component.js
+++ /dev/null
@@ -1,53 +0,0 @@
-const { COMPONENT_PARTS_MAP, VITEPRESS_SIDEBAR_CATEGORY } = require('../shared/constant')
-
-exports.typeName = () => ({
- name: 'name',
- type: 'input',
- message: '(必填)请输入组件 name ,将用作目录及文件名:',
- validate: (value) => {
- if (value.trim() === '') {
- return '组件 name 是必填项!'
- }
- return true
- }
-})
-
-exports.typeTitle = () => ({
- name: 'title',
- type: 'input',
- message: '(必填)请输入组件中文名称,将用作文档列表显示:',
- validate: (value) => {
- if (value.trim() === '') {
- return '组件名称是必填项!'
- }
- return true
- }
-})
-
-exports.selectCategory = () => ({
- name: 'category',
- type: 'list',
- message: '(必填)请选择组件分类,将用作文档列表分类:',
- choices: VITEPRESS_SIDEBAR_CATEGORY,
- default: 0
-})
-
-exports.typeAliasName = () => ({
- name: 'alias',
- type: 'input',
- message: '(选填)请输入组件 name 别名,将用作组件别名被导出:'
-})
-
-exports.selectParts = () => ({
- name: 'parts',
- type: 'checkbox',
- message: '(必填)请选择包含部件,将自动生成部件文件:',
- choices: COMPONENT_PARTS_MAP,
- default: [],
- validate: (value) => {
- if (value.length === 0) {
- return '部件必须包含至少一项'
- }
- return true
- }
-})
diff --git a/packages/devui-vue/devui-cli/inquirers/create.js b/packages/devui-vue/devui-cli/inquirers/create.js
deleted file mode 100644
index 5bc07766b51469dd82c4cd1a75ac125ad5d81065..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/inquirers/create.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const { CREATE_SUPPORT_TYPES } = require('../shared/constant')
-
-exports.selectCreateType = () => ({
- name: 'type',
- type: 'list',
- message: '(必填)请选择创建类型:',
- choices: CREATE_SUPPORT_TYPES,
- default: 0
-})
diff --git a/packages/devui-vue/devui-cli/shared/constant.js b/packages/devui-vue/devui-cli/shared/constant.js
deleted file mode 100644
index 6288409782d590df0d3e450b4f279a854a627793..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/shared/constant.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const { resolve } = require('path')
-const { version } = require('../../package.json')
-
-exports.VERSION = version
-exports.CWD = process.cwd()
-exports.DEVUI_DIR = resolve(this.CWD, 'devui')
-exports.DEVUI_NAMESPACE = 'd'
-exports.CSS_CLASS_PREFIX = 'devui'
-exports.TESTS_DIR_NAME = '__tests__'
-exports.INDEX_FILE_NAME = 'index.ts'
-exports.DOCS_FILE_NAME = 'index.md'
-exports.VUE_DEVUI_IGNORE_DIRS = ['shared', 'style']
-exports.VUE_DEVUI_FILE_NAME = 'vue-devui.ts'
-exports.VUE_DEVUI_FILE = resolve(this.DEVUI_DIR, this.VUE_DEVUI_FILE_NAME)
-exports.SITES_DIR = resolve(this.CWD, 'docs')
-exports.SITES_COMPONENTS_DIR_NAME = 'components'
-exports.SITES_COMPONENTS_DIR = resolve(this.SITES_DIR, this.SITES_COMPONENTS_DIR_NAME)
-exports.VITEPRESS_DIR = resolve(this.SITES_DIR, '.vitepress')
-exports.VITEPRESS_SIDEBAR_FILE_NAME = 'sidebar.ts'
-exports.VITEPRESS_SIDEBAR_FILE = resolve(this.VITEPRESS_DIR, `config/${this.VITEPRESS_SIDEBAR_FILE_NAME}`)
-
-// 这里的分类顺序将会影响最终生成的页面侧边栏顺序
-exports.VITEPRESS_SIDEBAR_CATEGORY = ['通用', '导航', '反馈', '数据录入', '数据展示', '布局']
-
-exports.COMPONENT_PARTS_MAP = [
- {
- name: 'component(组件)',
- value: 'component'
- },
- {
- name: 'directive(指令)',
- value: 'directive'
- },
- {
- name: 'service(服务)',
- value: 'service'
- }
-]
-
-exports.CREATE_SUPPORT_TYPE_MAP = Object.freeze({
- component: 'component',
- 'vue-devui': 'vue-devui',
- 'theme-variable': 'theme-variable',
-})
-exports.CREATE_SUPPORT_TYPES = Object.keys(this.CREATE_SUPPORT_TYPE_MAP)
-exports.CREATE_UNFINISHED_TYPES = []
diff --git a/packages/devui-vue/devui-cli/shared/logger.js b/packages/devui-vue/devui-cli/shared/logger.js
deleted file mode 100644
index 4b97da0e33d88dd6405d4b16747d46d099617f4f..0000000000000000000000000000000000000000
--- a/packages/devui-vue/devui-cli/shared/logger.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const chalk = require('chalk')
-
-module.exports = {
- info(text) {
- console.log(chalk.hex('#00afef')(text))
- },
- success(text) {
- console.log(chalk.hex('#00c48f')(text))
- },
- warning(text) {
- console.log(chalk.hex('#ff9800')(text))
- },
- error(text) {
- console.log(chalk.hex('#f44336')(text))
- }
-}
diff --git a/packages/devui-vue/package.json b/packages/devui-vue/package.json
index 991512f692cde0eefdf39f67d004a08557ba627f..00356e6147e72cf119dddb10fe8ec43a1cfba8a0 100644
--- a/packages/devui-vue/package.json
+++ b/packages/devui-vue/package.json
@@ -22,7 +22,8 @@
"devui-cli": "./devui-cli/index.js"
},
"scripts": {
- "dev": "yarn generate:theme && vitepress dev docs",
+ "predev": "devui-cli create -t vue-devui --ignore-parse-error && yarn generate:theme",
+ "dev": "vitepress dev docs",
"build": "yarn generate:theme && vitepress build docs && cp public/* docs/.vitepress/dist/assets",
"serve": "vitepress serve docs",
"app:dev": "vite",
@@ -33,15 +34,15 @@
"lint": "eslint \"{src,devui}/**/*.{vue,js,ts,jsx,tsx}\"",
"lint:fix": "eslint --fix \"{src,devui}/**/*.{vue,js,ts,jsx,tsx}\"",
"stylelint": "stylelint --fix \"{devui,src}/**/*.{scss,css}\"",
- "build:components": "node ./devui-cli/index.js build",
- "generate:theme": "node ./devui-cli/index.js generate:theme",
+ "build:components": "devui-cli build",
+ "generate:theme": "devui-cli generate:theme",
"copy": "cp package.json build && cp README.md build && cp devui/theme/theme.scss build/theme",
"clean:cli": "npm uninstall -g devui-cli & npm uninstall -g vue-devui",
- "cli:create": "node ./devui-cli/index.js create -t component",
- "predev": "node ./devui-cli/index.js create -t vue-devui --ignore-parse-error",
- "prebuild": "node ./devui-cli/index.js create -t vue-devui --ignore-parse-error"
+ "cli:create": "devui-cli create -t component",
+ "prebuild": "devui-cli create -t vue-devui --ignore-parse-error"
},
"dependencies": {
+ "@devui/cli": "^1.0.0",
"@devui-design/icons": "^1.3.0",
"@types/lodash-es": "^4.17.4",
"async-validator": "^4.0.2",