├── .npmrc ├── public ├── logo.png ├── basic.gif └── logo.svg ├── .eslintrc ├── renovate.json ├── .vscodeignore ├── .vscode ├── extensions.json ├── settings.json ├── tasks.json └── launch.json ├── .gitignore ├── src ├── templates │ ├── page-vue3.ts │ ├── page-composition.ts │ ├── component-vue3.ts │ ├── component-composition.ts │ ├── component-vue2.ts │ └── page-vue2.ts ├── extension.ts ├── command.ts ├── template.ts ├── utils.ts └── generate.ts ├── tsconfig.json ├── LICENSE ├── CHANGELOG.md ├── README.md ├── package.json └── pnpm-lock.yaml /.npmrc: -------------------------------------------------------------------------------- 1 | enable-pre-post-scripts = true 2 | shamefully-hoist=true 3 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uni-helper/uni-create-view/HEAD/public/logo.png -------------------------------------------------------------------------------- /public/basic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uni-helper/uni-create-view/HEAD/public/basic.gif -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@antfu", 3 | "ignorePatterns": [ 4 | "out", 5 | "dist", 6 | "**/*.d.ts" 7 | ] 8 | } -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>uni-helper/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | src/** 4 | .gitignore 5 | .yarnrc 6 | vsc-extension-quickstart.md 7 | **/tsconfig.json 8 | **/.eslintrc.json 9 | **/*.map 10 | **/*.ts 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | unpackage/ 4 | dist/ 5 | test/ 6 | out 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Editor directories and files 18 | .project 19 | .idea 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw* 25 | *.vsix -------------------------------------------------------------------------------- /src/templates/page-vue3.ts: -------------------------------------------------------------------------------- 1 | const template = `\ 2 | 5 | 6 | > 7 | <% if (!options.setup) { -%> 8 | import { defineComponent } from 'vue' 9 | export default defineComponent({ 10 | setup: () => {} 11 | }) 12 | <% } -%> 13 | 14 | 15 | >\ 16 | ` 17 | export default template 18 | -------------------------------------------------------------------------------- /src/templates/page-composition.ts: -------------------------------------------------------------------------------- 1 | const template = `\ 2 | 5 | 6 | > 7 | <% if (!options.setup) { -%> 8 | import { defineComponent } from '@vue/composition-api' 9 | export default defineComponent({ 10 | setup: () => {} 11 | }) 12 | <% } -%> 13 | 14 | 15 | >\ 16 | ` 17 | export default template 18 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/templates/component-vue3.ts: -------------------------------------------------------------------------------- 1 | const template = `\ 2 | 5 | 6 | > 7 | <% if (options.setup) { -%> 8 | const props = defineProps(); 9 | <% } -%> 10 | <% if (!options.setup) { -%> 11 | import { defineComponent } from 'vue' 12 | export default defineComponent({ 13 | props: {}, 14 | setup: () => {} 15 | }) 16 | <% } -%> 17 | 18 | 19 | >\ 20 | ` 21 | export default template 22 | -------------------------------------------------------------------------------- /src/templates/component-composition.ts: -------------------------------------------------------------------------------- 1 | const template = `\ 2 | 5 | 6 | > 7 | <% if (options.setup) { -%> 8 | const props = defineProps(); 9 | <% } -%> 10 | <% if (!options.setup) { -%> 11 | import { defineComponent } from '@vue/composition-api' 12 | export default defineComponent({ 13 | props: {}, 14 | setup: () => {} 15 | }) 16 | <% } -%> 17 | 18 | 19 | >\ 20 | ` 21 | export default template 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2020" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": true /* enable all strict type-checking options */ 12 | /* Additional Checks */ 13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | import type * as vscode from 'vscode' 2 | import { createCommand } from './command' 3 | 4 | export function activate(context: vscode.ExtensionContext) { 5 | const subscriptions = [ 6 | createCommand({ 7 | name: '页面', 8 | command: 'create-uniapp-view.createPage', 9 | }), 10 | createCommand({ 11 | name: '页面', 12 | options: { subcontract: true }, 13 | command: 'create-uniapp-view.createSubcontractPage', 14 | }), 15 | createCommand({ 16 | name: '组件', 17 | options: { component: true }, 18 | command: 'create-uniapp-view.createComponent', 19 | }), 20 | ] 21 | 22 | context.subscriptions.push(...subscriptions) 23 | } 24 | 25 | // 停用您的扩展程序时调用此方法 26 | export function deactivate() { } 27 | -------------------------------------------------------------------------------- /src/templates/component-vue2.ts: -------------------------------------------------------------------------------- 1 | // data 不能为箭头函数, 否则 this 为 undefined 2 | const content = `\ 3 | name: "<%- options.name%>", 4 | props: {}, 5 | data() { 6 | return {} 7 | }, 8 | computed: {}, 9 | methods: {}, 10 | watch: {}, 11 | 12 | // 组件周期函数--监听组件挂载完毕 13 | mounted() {}, 14 | // 组件周期函数--监听组件数据更新之前 15 | beforeUpdate() {}, 16 | // 组件周期函数--监听组件数据更新之后 17 | updated() {}, 18 | // 组件周期函数--监听组件激活(显示) 19 | activated() {}, 20 | // 组件周期函数--监听组件停用(隐藏) 21 | deactivated() {}, 22 | // 组件周期函数--监听组件销毁之前 23 | beforeDestroy() {},\ 24 | ` 25 | 26 | const template = `\ 27 | 30 | 31 | > 32 | <% if (options.typescript) { -%> 33 | import Vue from 'vue'; 34 | export default Vue.extend({ 35 | <% } else { -%> 36 | export default { 37 | <% } -%> 38 | ${content} 39 | <%= options.typescript ? '})' : '}' %> 40 | 41 | 42 | >\ 43 | ` 44 | export default template 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-PRESENT Hairyf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/templates/page-vue2.ts: -------------------------------------------------------------------------------- 1 | const content = `\ 2 | components: {}, 3 | data() { 4 | return {} 5 | }, 6 | computed: {}, 7 | methods: {}, 8 | watch: {}, 9 | 10 | // 页面周期函数--监听页面加载 11 | onLoad() {}, 12 | // 页面周期函数--监听页面初次渲染完成 13 | onReady() {}, 14 | // 页面周期函数--监听页面显示(not-nvue) 15 | onShow() {}, 16 | // 页面周期函数--监听页面隐藏 17 | onHide() {}, 18 | // 页面周期函数--监听页面卸载 19 | onUnload() {}, 20 | // 页面处理函数--监听用户下拉动作 21 | // onPullDownRefresh() { uni.stopPullDownRefresh(); }, 22 | // 页面处理函数--监听用户上拉触底 23 | // onReachBottom() {}, 24 | // 页面处理函数--监听页面滚动(not-nvue) 25 | // onPageScroll(event) {}, 26 | // 页面处理函数--用户点击右上角分享 27 | // onShareAppMessage(options) {},\ 28 | ` 29 | 30 | const template = `\ 31 | 34 | 35 | > 36 | <% if (options.typescript) { -%> 37 | import Vue from 'vue'; 38 | export default Vue.extend({ 39 | <% } else { -%> 40 | export default { 41 | <% } -%> 42 | ${content} 43 | <%= options.typescript ? '})' : '}' %> 44 | 45 | 46 | >\ 47 | ` 48 | 49 | export default template 50 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ], 16 | "outFiles": [ 17 | "${workspaceFolder}/out/**/*.js" 18 | ], 19 | "preLaunchTask": "${defaultBuildTask}" 20 | }, 21 | { 22 | "name": "Extension Tests", 23 | "type": "extensionHost", 24 | "request": "launch", 25 | "runtimeExecutable": "${execPath}", 26 | "args": [ 27 | "--extensionDevelopmentPath=${workspaceFolder}", 28 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" 29 | ], 30 | "outFiles": [ 31 | "${workspaceFolder}/out/test/**/*.js" 32 | ], 33 | "preLaunchTask": "${defaultBuildTask}" 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "uni-create-view" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [2.0.9] 8 | - 更新 logo 图标 9 | 10 | ## [2.0.8] 11 | - 调整项目目录、新增 .eslintrc 配置 12 | - 使用 pnpm 替换 yarn 工具 13 | - 添加 LICENSE 协议 14 | - 调整、优化插件默认配置 15 | - README 文档补充优化 16 | 17 | ## [2.0.6] 18 | - 删除页面无用的属性[#13] 19 | - 修复错误的模板语法[#12] 20 | - template 模板 data 更改 21 | 22 | ## [2.0.4] 23 | - 保留支持 `composition-api(vue2)`,文档优化 24 | 25 | ## [2.0.2] 26 | - 修复 window 环境下路径 `\\` 问题 27 | 28 | ## [2.0.1] 29 | - 新增文档内容 30 | 31 | # [2.0.0] 32 | - 支持组件页面 style scoped 选项 33 | - 重构主逻辑 34 | - 修复无法写入 pages.json 35 | - 支持 setup 语法 36 | - 支持 vue3 模版 37 | - 支持自定义名称 index 或者使用文件夹名称 38 | - 模版逻辑优化,使用 ejs 实现 39 | - 优化查询上层文件逻辑 40 | 41 | ## [1.3.6] 42 | - 新增 composition-api 选项 43 | - 优化模板判断逻辑 44 | 45 | ## [1.3.5] 46 | - 新增输入页面名称使用空格分割输入内容时, 左侧为页面文件名称, 右侧为"navigationBarTitleText"名称 47 | 48 | ## [1.3.4] 49 | - 修复右键后无反应 bug 50 | 51 | ## [1.3.2] 52 | - 支持 pages.json 中添加注释 53 | 54 | ## [1.3.1] 55 | - 支持单文件创建 56 | 57 | ## [1.3.0] 58 | - 新增 nvue 生命周期兼容性提示 59 | - 支持深度目录创建页面 60 | - 支持创建分包页面 61 | - 清除多余语法 62 | 63 | ## [1.2.7] 64 | - 更换 `computed` 排版顺序 65 | - 添加 `onPullDownRefresh` 默认释放上拉刷新 `uni.stopPullDownRefresh()` 66 | -------------------------------------------------------------------------------- /src/command.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode' 2 | import { generate } from './generate' 3 | import { getConfiguration, logger } from './utils' 4 | 5 | export interface CreateCommandOptions { 6 | /** 命令名称 */ 7 | name: string 8 | /** 命令 */ 9 | command: string 10 | /** 配置 */ 11 | options?: { component?: boolean; subcontract?: boolean } 12 | } 13 | 14 | export function createCommand(options: CreateCommandOptions) { 15 | return vscode.commands.registerCommand(options.command, async (uri) => { 16 | const componentText = `输入${options.name}名称` 17 | const pageText = `${componentText},空格分隔字段(navigationBarTitleText)` 18 | const input = await vscode.window.showInputBox({ prompt: options.name === '页面' ? pageText : componentText }) 19 | 20 | if (!input) { 21 | logger('error', `${options.name}名称不能为空!`) 22 | throw new Error(`${options.name}名称不能为空!`) 23 | } 24 | const { message, status } = await generate({ 25 | names: { view: input.split(' ')[0], page: input.split(' ')[1] || '' }, 26 | nameType: getConfiguration('create-uniapp-view.name'), 27 | path: uri.fsPath, 28 | component: options.options?.component, 29 | subcontract: options.options?.subcontract, 30 | typescript: getConfiguration('create-uniapp-view.typescript'), 31 | styleType: getConfiguration('create-uniapp-view.style'), 32 | directory: getConfiguration('create-uniapp-view.directory'), 33 | template: getConfiguration('create-uniapp-view.template'), 34 | setup: getConfiguration('create-uniapp-view.setup'), 35 | scoped: getConfiguration('create-uniapp-view.scoped'), 36 | }) 37 | 38 | logger(status, message) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 |

5 | 6 | 7 |

UniApp Create View for VS Code

8 | 9 |

10 | 在 VS Code 右键目录文件夹快速创建页面与组建,创建视图页面时将自动添加 `pages.json` 中! 11 |

12 | 13 |
14 |

15 | Visual Studio | 16 | Github Page | 17 | Hairy's Blog 18 |

19 | 20 |
21 | 22 | ## Features 23 | 24 | - 📁 创建页面、分包页面,自动查找根目录下 `pages.json` 文件并写入 25 | - 📦 可深度目录创建,写入 `pages.json` 后仍可保留注释 26 | - ✨ 可配置 `vue(2|3)|composition-api|setup` 组件、页面模板 27 | - 👕 可配置 `scss|less|stylus|sass` 预编辑器类型 28 | - 🦾 `typescript` 为默认开发语言(可在设置中关闭) 29 | 30 | 31 | 32 | > 使用 `composition-api(vue2)` 模版,建议配合 [uni-composition-api](https://github.com/TuiMao233/uni-composition-api) 使用 33 | 34 | ## 基本使用(page、component) 35 | 36 | 右键打开菜单选择创建类型,可选择创建组件、页面、分包页面,空格分割视图名称与页面名称(navigationBarTitleText) 37 | 38 |

39 | 40 |

41 | 42 | ## 深度目录 43 | 44 | `^1.3.0` 新增扩展能力,无特殊需求还是建议使用单文件模式。 45 | 46 | ![](https://qie-online-sale-qiniu.wsandos.com/exts.gif) 47 | 48 | ## 分包页面 49 | 50 | `^1.3.0` 新增功能,用于创建分包页面,并自动添加至 `subPackages` 字段中。 51 | 52 | > 注意:`cli` 创建的项目需要在`package.json`中添加参数 `--minimize`,具体参考官方文档:[dcloud.io](https://uniapp.dcloud.io/collocation/pages?id=subpackages) 53 | 54 | ![](https://qie-online-sale-qiniu.wsandos.com/1dddw1334.gif) 55 | 56 | ## License 57 | 58 | [MIT](./LICENSE) License © 2021-PRESENT [Hairyf](https://github.com/hairyf) -------------------------------------------------------------------------------- /src/template.ts: -------------------------------------------------------------------------------- 1 | import * as ejs from 'ejs' 2 | import cv2 from './templates/component-vue2' 3 | import cv3 from './templates/component-vue3' 4 | import pv2 from './templates/page-vue2' 5 | import pv3 from './templates/page-vue3' 6 | import pv2c from './templates/page-composition' 7 | import cv2c from './templates/component-composition' 8 | 9 | const ALL_TEMPLATES = { 10 | ['vue2' as string]: { page: pv2, component: cv2 }, 11 | ['vue3' as string]: { page: pv3, component: cv3 }, 12 | ['composition-api(vue2)' as string]: { page: pv2c, component: cv2c }, 13 | } 14 | 15 | export interface CreateViewTemplateOptions { 16 | template?: string 17 | name?: string 18 | typescript?: boolean 19 | styleType?: string 20 | component?: boolean 21 | setup?: string 22 | scoped?: boolean 23 | } 24 | 25 | export function createViewTemplate(options: CreateViewTemplateOptions) { 26 | const templates = ALL_TEMPLATES[options.template || 'vue2'] 27 | const template = templates[options.component ? 'component' : 'page'] 28 | 29 | const handle = (attrs: (string | boolean | undefined)[]) => { 30 | const _v = attrs.filter(Boolean).join(' ').trim() 31 | return _v ? ` ${_v}` : '' 32 | } 33 | 34 | const scriptAttrs = handle([ 35 | options.typescript && 'lang="ts"', 36 | options.template === 'vue3' && options.setup && 'setup', 37 | ]) 38 | 39 | const styleAttrs = handle([ 40 | options.styleType !== 'css' && `lang="${options.styleType}"`, 41 | options.scoped && 'scoped', 42 | ]) 43 | 44 | const data = { 45 | name: options.name, 46 | setup: options.setup, 47 | typescript: options.typescript, 48 | scriptAttrs, 49 | styleAttrs, 50 | } 51 | return ejs.render(template, { options: data }) 52 | } 53 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import path = require('path') 2 | import slash = require('slash') 3 | import * as vscode from 'vscode' 4 | import * as fs from 'fs-extra' 5 | 6 | export type SearchFileResult = Promise<{ path: string; data: string } | null | undefined> 7 | 8 | export function logger(type: string, message = '') { 9 | switch (type) { 10 | case 'success': 11 | return vscode.window.showInformationMessage(`Success: ${message}`) 12 | case 'warning': 13 | return vscode.window.showWarningMessage(`Warning: ${message}`) 14 | case 'error': 15 | return vscode.window.showErrorMessage(`Failed: ${message}`) 16 | } 17 | } 18 | 19 | export function getConfiguration(section: string) { 20 | return vscode.workspace.getConfiguration().get(section) 21 | } 22 | 23 | export function isDirectory(path: string) { 24 | try { 25 | return fs.statSync(path).isDirectory() 26 | } 27 | catch (error) { 28 | return false 29 | } 30 | } 31 | 32 | export function isFileAccess(path: string) { 33 | return new Promise((resolve) => { 34 | fs.access(path, (error: any) => { 35 | if (error) 36 | resolve(false) 37 | else resolve(true) 38 | }) 39 | }) 40 | } 41 | 42 | export function upwardSearchFile(currentPath: string, fileName: string): SearchFileResult { 43 | const recursion = async (appPath: string): Promise => { 44 | const recursPath = slash(path.resolve(appPath, fileName)) 45 | // 递归出口: 路径是根路径, 停止递归 46 | if (recursPath.split('/').length < 1) 47 | return null 48 | 49 | if (await isFileAccess(recursPath || '/')) { 50 | const stat = fs.lstatSync(recursPath) 51 | const data = stat.isFile() ? fs.readFileSync(recursPath, 'utf-8') : '' 52 | return { path: recursPath, data } 53 | } 54 | else { 55 | return recursion(path.resolve(appPath, '../')) 56 | } 57 | } 58 | 59 | return recursion(currentPath) 60 | } 61 | -------------------------------------------------------------------------------- /src/generate.ts: -------------------------------------------------------------------------------- 1 | import path = require('path') 2 | import * as fs from 'fs-extra' 3 | import * as JSONC from 'comment-json' 4 | import slash = require('slash') 5 | import { createViewTemplate } from './template' 6 | import { isDirectory, upwardSearchFile } from './utils' 7 | 8 | export interface GenerateOptions { 9 | /** 创建路径 */ 10 | path: string 11 | 12 | nameType: string 13 | /** 多个名称内容 */ 14 | names: { 15 | /** 视图名称(组件/文件夹/文件) */ 16 | view: string 17 | /** 页面名称(navigationBarTitleText) */ 18 | page: string 19 | } 20 | 21 | /** 创建是否包含文件夹 */ 22 | directory?: boolean 23 | 24 | /** options */ 25 | typescript?: boolean 26 | styleType?: string 27 | component?: boolean 28 | template?: string 29 | setup?: string 30 | scoped?: boolean 31 | subcontract?: boolean 32 | } 33 | export interface GenerateResult { 34 | status: string 35 | message: string 36 | } 37 | 38 | export async function generate(options: GenerateOptions): Promise { 39 | const names = options.names 40 | const directoryPath = path.resolve(options.path, names.view) 41 | 42 | // #region 判断路径是否存在 / 符合创建环境 43 | if (!isDirectory(options.path)) 44 | return { status: 'error', message: '创建错误, 该路径不是文件夹' } 45 | 46 | if (options.directory) { 47 | if (!isDirectory(directoryPath)) 48 | fs.ensureDir(directoryPath) 49 | else return { status: 'error', message: '创建错误, 该文件夹已存在!' } 50 | } 51 | // #endregion 52 | 53 | // #region 生成模版 54 | const isIndex = options.nameType === 'index' 55 | const filePath = options.directory ? `${names.view}/${isIndex ? 'index' : names.view}.vue` : `${names.view}.vue` 56 | const template = createViewTemplate({ name: names.view, ...options }) 57 | fs.writeFileSync(path.resolve(options.path, filePath), template, { flag: 'w' }) 58 | // #endregion 59 | 60 | // 组件则跳过 61 | if (options.component) 62 | return { status: 'success', message: '创建组件成功!' } 63 | 64 | // 写入 pages.json 65 | const status = await writePagesJson(options) 66 | if (status) 67 | return status 68 | 69 | return { status: 'success', message: '创建页面成功!' } 70 | } 71 | 72 | export async function writePagesJson(options: GenerateOptions) { 73 | const names = options.names 74 | options.path = slash(options.path) 75 | 76 | const pagesJsonFile = await upwardSearchFile(options.path, 'pages.json') 77 | if (!pagesJsonFile) 78 | return { status: 'warning', message: '创建页面成功! 但pages.json未找到' } 79 | 80 | // 获取基于项目目录下的 pages 文件和根目录 81 | const pagesSplit = pagesJsonFile.path.split('pages.json') 82 | 83 | const isIndex = options.nameType === 'index' 84 | const rootPath = options.path.replace(pagesSplit[0], '') 85 | const filePath = options.directory ? `${names.view}/${isIndex ? 'index' : names.view}` : `${names.view}` 86 | 87 | // 读取 pages.json, 准备 page 信息 88 | const pagesJson = JSONC.parse(pagesJsonFile.data) as Record 89 | const page = { path: filePath, style: { navigationBarTitleText: names.page || names.view } } 90 | 91 | // 如果是分包页面 92 | if (options.subcontract) { 93 | pagesJson.subPackages = pagesJson.subPackages || [] 94 | const findRoot = pagesJson.subPackages.find((v: any) => v.root === rootPath) 95 | const root = findRoot || { root: rootPath, pages: [] } 96 | root.pages.push(page) 97 | if (!findRoot) 98 | pagesJson.subPackages.push(root) 99 | } 100 | else { 101 | pagesJson.pages = pagesJson.pages || [] 102 | page.path = slash(path.join(rootPath, page.path)) 103 | pagesJson.pages.push(page) 104 | } 105 | 106 | const newPagesJson = JSONC.stringify(pagesJson, null, '\t') 107 | fs.writeFileSync(pagesJsonFile.path, newPagesJson) 108 | } 109 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "publisher": "mrmaoddxxaa", 3 | "name": "create-uniapp-view", 4 | "displayName": "uni-create-view", 5 | "version": "2.1.0", 6 | "description": "快速创建 uniapp 视图与组件!", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/uni-helper/uni-create-view", 10 | "directory": "." 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/uni-helper/uni-create-view" 14 | }, 15 | "keywords": [ 16 | "uniapp", 17 | "page", 18 | "components", 19 | "uni-app", 20 | "uni" 21 | ], 22 | "prettier": "@hairy/eslint/prettier.js", 23 | "categories": [ 24 | "Other" 25 | ], 26 | "main": "./out/extension.js", 27 | "icon": "public/logo.png", 28 | "engines": { 29 | "vscode": "^1.47.0" 30 | }, 31 | "activationEvents": [ 32 | "onCommand:create-uniapp-view.createPage", 33 | "onCommand:create-uniapp-view.createComponent" 34 | ], 35 | "contributes": { 36 | "configuration": { 37 | "title": "create-uniapp-view 创建 page、component 时的配置项", 38 | "properties": { 39 | "create-uniapp-view.typescript": { 40 | "type": "boolean", 41 | "default": true, 42 | "description": "创建视图时是否选择 TypeScript 为默认语言" 43 | }, 44 | "create-uniapp-view.directory": { 45 | "type": "boolean", 46 | "default": false, 47 | "description": "创建视图时是否创建同名文件夹" 48 | }, 49 | "create-uniapp-view.name": { 50 | "type": [ 51 | "string" 52 | ], 53 | "default": "index", 54 | "enum": [ 55 | "index", 56 | "与文件夹同名" 57 | ], 58 | "description": "创建文件夹中生成的文件名" 59 | }, 60 | "create-uniapp-view.style": { 61 | "type": [ 62 | "string" 63 | ], 64 | "default": "css", 65 | "enum": [ 66 | "css", 67 | "scss", 68 | "less", 69 | "stylus", 70 | "sass" 71 | ], 72 | "description": "创建视图时 CSS 预处理器的类型" 73 | }, 74 | "create-uniapp-view.scoped": { 75 | "type": "boolean", 76 | "default": true, 77 | "description": "创建模版时,是否使用