-
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
create-vuepress-theme-plume
package (#153)
* feat: add `create-vuepress-theme-plume` package * feat(cli): add support deploy
- Loading branch information
1 parent
a4dc03f
commit 7407939
Showing
54 changed files
with
2,117 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (C) 2021 - PRESENT by pengzhanbo | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# create-vuepress-theme-plume | ||
|
||
The cli for create vuepress-theme-plume's project | ||
|
||
## Usage | ||
|
||
```sh | ||
# npm | ||
npm init vuepress-theme-plume@latest | ||
# pnpm | ||
pnpm create vuepress-theme-plume@latest | ||
# yarn | ||
yarn create vuepress-theme-plume@latest | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/usr/bin/env node | ||
import '../lib/index.js' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
{ | ||
"name": "create-vuepress-theme-plume", | ||
"type": "module", | ||
"version": "1.0.0-rc.90", | ||
"description": "The cli for create vuepress-theme-plume's project", | ||
"author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)", | ||
"license": "MIT", | ||
"homepage": "https://theme-plume.vuejs.press/", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git", | ||
"directory": "cli" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues" | ||
}, | ||
"keywords": [ | ||
"VuePress", | ||
"theme", | ||
"plume", | ||
"cli" | ||
], | ||
"bin": "./bin/index.js", | ||
"files": [ | ||
"bin", | ||
"lib", | ||
"templates" | ||
], | ||
"scripts": { | ||
"build": "tsup" | ||
}, | ||
"dependencies": { | ||
"@clack/prompts": "^0.7.0", | ||
"@pengzhanbo/utils": "^1.1.2", | ||
"cac": "^6.7.14", | ||
"execa": "^9.3.1", | ||
"handlebars": "^4.7.8", | ||
"picocolors": "^1.0.1" | ||
}, | ||
"theme-plume": { | ||
"vuepress": "2.0.0-rc.14" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type { Bundler, Langs, Options } from './types.js' | ||
|
||
export const languageOptions: Options<Langs> = [ | ||
{ label: 'English', value: 'en-US' }, | ||
{ label: '简体中文', value: 'zh-CN' }, | ||
] | ||
|
||
export const bundlerOptions: Options<Bundler> = [ | ||
{ label: 'Vite', value: 'vite' }, | ||
{ label: 'Webpack', value: 'webpack' }, | ||
] | ||
|
||
export enum Mode { | ||
init, | ||
create, | ||
} | ||
|
||
export enum DeployType { | ||
github = 'github', | ||
vercel = 'vercel', | ||
netlify = 'netlify', | ||
custom = 'custom', | ||
} | ||
|
||
export const deployOptions: Options<DeployType> = [ | ||
{ label: 'Custom', value: DeployType.custom }, | ||
{ label: 'GitHub Pages', value: DeployType.github }, | ||
{ label: 'Vercel', value: DeployType.vercel }, | ||
{ label: 'Netlify', value: DeployType.netlify }, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import path from 'node:path' | ||
import process from 'node:process' | ||
import fs from 'node:fs' | ||
import { execaCommand } from 'execa' | ||
import { createPackageJson } from './packageJson.js' | ||
import { createRender } from './render.js' | ||
import { getTemplate, readFiles, readJsonFile, writeFiles } from './utils/index.js' | ||
import type { File, ResolvedData } from './types.js' | ||
import { DeployType, Mode } from './constants.js' | ||
|
||
export async function generate(mode: Mode, data: ResolvedData): Promise<void> { | ||
const cwd = process.cwd() | ||
|
||
let userPkg: Record<string, any> = {} | ||
if (mode === Mode.init) { | ||
const pkgPath = path.join(cwd, 'package.json') | ||
if (fs.existsSync(pkgPath)) { | ||
userPkg = (await readJsonFile(pkgPath)) || {} | ||
} | ||
} | ||
|
||
const fileList: File[] = [ | ||
// add package.json | ||
await createPackageJson(mode, userPkg, data), | ||
// add docs files | ||
...await createDocsFiles(data), | ||
// add vuepress and theme-plume configs | ||
...updateFileListTarget(await readFiles(getTemplate('.vuepress')), `${data.docsDir}/.vuepress`), | ||
] | ||
|
||
// add repo root files | ||
if (mode === Mode.create) { | ||
fileList.push(...await readFiles(getTemplate('common'))) | ||
if (data.packageManager === 'pnpm') { | ||
fileList.push({ | ||
filepath: '.npmrc', | ||
content: 'shamefully-hoist=true\nshell-emulator=true', | ||
}) | ||
} | ||
if (data.packageManager === 'yarn') { | ||
const { stdout: yarnVersion } = await execaCommand('yarn --version') | ||
if (yarnVersion.startsWith('2')) { | ||
fileList.push({ | ||
filepath: '.yarnrc.yml', | ||
content: 'nodeLinker: \'node-modules\'\n', | ||
}) | ||
} | ||
} | ||
} | ||
|
||
// rewrite git files begin ================================== | ||
if (data.git) | ||
fileList.push(...await readFiles(getTemplate('git'))) | ||
|
||
if (mode === Mode.init) { | ||
const gitignorePath = path.join(cwd, '.gitignore') | ||
const docs = data.docsDir | ||
if (fs.existsSync(gitignorePath)) { | ||
const content = await fs.promises.readFile(gitignorePath, 'utf-8') | ||
fileList.push({ | ||
filepath: '.gitignore', | ||
content: `${content}\n${docs}/.vuepress/.cache\n${docs}/.vuepress/.temp\n${docs}/.vuepress/dist\n`, | ||
}) | ||
} | ||
} | ||
// rewrite git files end ==================================== | ||
|
||
if (data.deploy !== DeployType.custom) { | ||
fileList.push(...await readFiles(getTemplate(`deploy/${data.deploy}`))) | ||
} | ||
|
||
const render = createRender(data) | ||
|
||
const renderedFiles = fileList.map((file) => { | ||
if (file.filepath.endsWith('.handlebars')) | ||
file.content = render(file.content) | ||
|
||
return file | ||
}) | ||
|
||
const ext = data.useTs ? '' : userPkg.type !== 'module' ? '.mjs' : '.js' | ||
const REG_EXT = /\.ts$/ | ||
const output = mode === Mode.create ? path.join(cwd, data.root) : cwd | ||
await writeFiles(renderedFiles, output, (filepath) => { | ||
if (filepath.endsWith('.d.ts')) | ||
return filepath | ||
if (ext) | ||
return filepath.replace(REG_EXT, ext) | ||
return filepath | ||
}) | ||
} | ||
|
||
async function createDocsFiles(data: ResolvedData): Promise<File[]> { | ||
const fileList: File[] = [] | ||
if (data.multiLanguage) { | ||
const enDocs = await readFiles(getTemplate('docs/en')) | ||
const zhDocs = await readFiles(getTemplate('docs/zh')) | ||
|
||
if (data.defaultLanguage === 'en-US') { | ||
fileList.push(...enDocs) | ||
fileList.push(...updateFileListTarget(zhDocs, 'zh')) | ||
} | ||
else { | ||
fileList.push(...zhDocs) | ||
fileList.push(...updateFileListTarget(enDocs, 'en')) | ||
} | ||
} | ||
else { | ||
if (data.defaultLanguage === 'en-US') | ||
fileList.push(...await readFiles(getTemplate('docs/en'))) | ||
else | ||
fileList.push(...await readFiles(getTemplate('docs/zh'))) | ||
} | ||
|
||
return updateFileListTarget(fileList, data.docsDir) | ||
} | ||
|
||
function updateFileListTarget(fileList: File[], target: string): File[] { | ||
return fileList.map(({ filepath, content }) => ({ | ||
filepath: path.join(target, filepath), | ||
content, | ||
})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import cac from 'cac' | ||
import { run } from './run.js' | ||
import { Mode } from './constants.js' | ||
|
||
declare const __CLI_VERSION__: string | ||
|
||
const cli = cac('create-vuepress-theme-plume') | ||
|
||
cli | ||
.command('[root]', 'create a new vuepress-theme-plume project / 创建新的 vuepress-theme-plume 项目') | ||
.action((root: string) => run(Mode.create, root)) | ||
|
||
cli | ||
.command('init [root]', 'Initial vuepress-theme-plume in the existing project / 在现有项目中初始化 vuepress-theme-plume') | ||
.action((root: string) => run(Mode.init, root)) | ||
|
||
cli.help() | ||
|
||
cli.version(__CLI_VERSION__) | ||
|
||
cli.parse() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { Locale } from '../types.js' | ||
|
||
export const en: Locale = { | ||
'question.root': 'Where would you want to initialize VuePress?', | ||
'question.site.name': 'Site Name:', | ||
'question.site.description': 'Site Description:', | ||
'question.bundler': 'Select a bundler', | ||
'question.multiLanguage': 'Do you want to use multiple languages?', | ||
'question.defaultLanguage': 'Select the default language of the site', | ||
'question.useTs': 'Use TypeScript?', | ||
'question.injectNpmScripts': 'Inject npm scripts?', | ||
'question.deploy': 'Deploy type:', | ||
'question.git': 'Initialize a git repository?', | ||
'question.installDeps': 'Install dependencies?', | ||
|
||
'spinner.start': '🚀 Creating...', | ||
'spinner.stop': '🎉 Create success!', | ||
'spinner.git': '📄 Initializing git repository...', | ||
'spinner.install': '📦 Installing dependencies...', | ||
'spinner.command': '🔨 Execute the following command to start:', | ||
|
||
'hint.cancel': 'Operation cancelled.', | ||
'hint.root': 'The path cannot be an absolute path, and cannot contain the parent path.', | ||
'hint.root.illegal': 'Project names cannot contain special characters.', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { Langs, Locale } from '../types.js' | ||
import { en } from './en.js' | ||
import { zh } from './zh.js' | ||
|
||
export const locales: Record<Langs, Locale> = { | ||
'zh-CN': zh, | ||
'en-US': en, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { Locale } from '../types.js' | ||
|
||
export const zh: Locale = { | ||
'question.root': '您想在哪里初始化 VuePress?', | ||
'question.site.name': '站点名称:', | ||
'question.site.description': '站点描述信息:', | ||
'question.bundler': '请选择打包工具', | ||
'question.multiLanguage': '是否使用多语言?', | ||
'question.defaultLanguage': '请选择站点默认语言', | ||
'question.useTs': '是否使用 TypeScript?', | ||
'question.injectNpmScripts': '是否注入 npm 脚本?', | ||
'question.deploy': '部署方式:', | ||
'question.git': '是否初始化 git 仓库?', | ||
'question.installDeps': '是否安装依赖?', | ||
|
||
'spinner.start': '🚀 正在创建...', | ||
'spinner.stop': '🎉 创建成功!', | ||
'spinner.git': '📄 初始化 git 仓库...', | ||
'spinner.install': '📦 安装依赖...', | ||
'spinner.command': '🔨 执行以下命令即可启动:', | ||
|
||
'hint.cancel': '操作已取消。', | ||
'hint.root': '文件路径不能是绝对路径,不能包含父路径。', | ||
'hint.root.illegal': '文件夹不能包含特殊字符。', | ||
} |
Oops, something went wrong.