diff --git a/package.json b/package.json index b24badb..ec4aab9 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,9 @@ "vitepress": "^1.2.0" }, "scripts": { - "docs:dev": "vitepress dev", - "docs:build": "vitepress build", - "docs:preview": "vitepress preview" + "docs:dev": "node ./src/hooks.js && vitepress dev", + "docs:build": "node ./src/hooks.js && vitepress build", + "docs:preview": "node ./src/hooks.js && vitepress preview" }, "dependencies": { "@metalsmith/collections": "^1.3.0", @@ -16,7 +16,7 @@ "@metalsmith/layouts": "^2.7.0", "@metalsmith/markdown": "^1.10.0", "@metalsmith/permalinks": "^3.0.1", - "chalk": "^5.3.0", + "chalk": "^5.3.0", "commander": "^12.1.0", "gogocode": "^1.0.55", "handlebars": "^4.7.8", diff --git a/src/api-examples.md b/src/api-examples.md deleted file mode 100644 index 1e1a60c..0000000 --- a/src/api-examples.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -outline: deep ---- - -# Runtime API Examples - -This page demonstrates1 usage of some of the runtime APIs provided by VitePress1. - -The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: - -```md - - -## Results - -### Theme Data -
{{ theme }}
- -### Page Data -
{{ page }}
- -### Page Frontmatter -
{{ frontmatter }}
-``` - - - -## Results - -### Theme Data -
{{ theme }}
- -### Page Data -
{{ page }}
- -### Page Frontmatter -
{{ frontmatter }}
- -## More - -Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata). diff --git a/src/frontend/library/Metalsmith/index-source.md b/src/frontend/library/Metalsmith/index-source.md new file mode 100644 index 0000000..173cde9 --- /dev/null +++ b/src/frontend/library/Metalsmith/index-source.md @@ -0,0 +1,22 @@ + +``` + const Metalsmith = require('metalsmith'); +let layouts = require('@metalsmith/layouts'); + +Metalsmith(__dirname) + .metadata({ + site: { + title: 'My Website', + }, + }) + .source('./src') + .destination('./build') + .clean(true) + .use(layouts({ + pattern: '**/*.html' + })) + .build(function (err) { + if (err) throw err; + }); +``` + \ No newline at end of file diff --git a/src/frontend/library/commander/commander.js b/src/frontend/library/commander/commander.js old mode 100644 new mode 100755 index ed25715..cc39096 --- a/src/frontend/library/commander/commander.js +++ b/src/frontend/library/commander/commander.js @@ -1,3 +1,4 @@ +#!/usr/bin/env node const { program } = require('commander'); diff --git a/src/frontend/library/commander/commander.md b/src/frontend/library/commander/commander.md index 22f550b..f64a358 100644 --- a/src/frontend/library/commander/commander.md +++ b/src/frontend/library/commander/commander.md @@ -1,7 +1,7 @@ # commander.js ## 名词概念 -1. 选项(options):终端传递的以`-`或者`--`开头的参数。 +1. 选项(option):终端传递的以`-`或者`--`开头的参数。 2. 命令(command):终端可以调用的命令,例如git add .中的add 3. 子命令(sub-command):一个独立的文件,名称默认为`主命令文件名称-子命令名称` 4. 选项参数,命令参数:跟在选项或者命令之后的参数,<>表示必选,[]表示可选,终端没出现该选项名称或者命令名称时候,默认为undefined @@ -29,7 +29,7 @@ node ./commander.js start clone placeA placeB // 会调用同级目录下面的c ``` const { program } = require('commander'); // program是一个全局的Command实例 -program.options("-s --search") // 返回全局Command实例 +program.option("-s --search") // 返回全局Command实例 .command('commandA") // 创建一个CommandA实例 .command('commandB") // 在CommandA实例下面创建一个新的CommandB实例 @@ -41,6 +41,6 @@ program.command('commandC') //在全局Command下面创建一个新的CommandC [具体见官方文档](https://github.com/tj/commander.js/blob/HEAD/Readme_zh-CN.md) - option - command -- action 参数为命令的所有参数,外加上解析出来的options和command实例 +- action 参数为命令的所有参数,外加上解析出来的option和command实例 - version - hook \ No newline at end of file diff --git a/src/frontend/library/commander/index-source.md b/src/frontend/library/commander/index-source.md new file mode 100644 index 0000000..118fd49 --- /dev/null +++ b/src/frontend/library/commander/index-source.md @@ -0,0 +1,72 @@ + +``` + #!/usr/bin/env node +const { program } = require('commander'); + + +let op1 = program.option('-s --search', 'search') +// 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中) +// 返回新生成的命令(即该子命令)以供继续配置 +let a = program + .command('clone [destination]'); + +a.description('clone a repository into a newly created directory') + .action((source, destination) => { + console.log('clone command called', source, destination); + }) + .hook('postAction', (a, b) => { + console.log('postAction', a === b); + }) + .hook('preAction', (a, b) => { + console.log('preAction', a === b); + }); + +let c = program + .command('cloneC [destination]') + .command('cloneCAfter [destination]') + +c.description('clone a repository into a newly created directory') + .action((source, destination) => { + console.log('clone command called', source, destination); + }) + .hook('postAction', (a, b) => { + console.log('postAction', a === b); + }) + .hook('preAction', (a, b) => { + console.log('preAction', a === b); + }); + +let isAEqualC = a === c + + +// 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数) +// 返回最顶层的命令以供继续添加子命令 +let b = program + .command('start ', 'start service', { executableFile: 'myUpdateSubCommand' }) + .command('stop [service]', 'stop named service, or all if no name supplied'); + +b.helpOption('-e, --HELP', 'read more information'); + + +program.addHelpCommand('start [command]', 'show assistance'); + +// program +// .version('0.1.0') +// .argument('', 'user to login') +// .argument('[password]', 'password for user, if required', 'no password given') +// .action((username, password) => { +// console.log('username:', username); +// console.log('password:', password); +// }); + +// 分别装配命令 +// 返回最顶层的命令以供继续添加子命令 +// program +// .addCommand(build.makeBuildCommand()); + +program.parse(); +let m = 12 +console.log(m); + +``` + \ No newline at end of file diff --git a/src/frontend/library/gogocode/index-source.md b/src/frontend/library/gogocode/index-source.md new file mode 100644 index 0000000..267b058 --- /dev/null +++ b/src/frontend/library/gogocode/index-source.md @@ -0,0 +1,76 @@ + +``` + const $ = require('gogocode'); +let path = require('path'); +let fs = require('fs') + +let filePath = path.resolve(__dirname, './test.js'); +let str = fs.readFileSync(filePath, { encoding: 'utf-8' }); +const ast = $(str); +const test1 = ast.find('const $_$variable = $_$value'); +let test1Match = test1.match + +// const code = test1.generate(); +// ast.replace('function log(){}', `let log = 12;`); +// let code2 = ast.generate(); +// console.log(code2) + +let test2 = ast.find('function log($$$param){$$$statement}') +let test2match = test2.match; + +let ddd = ast.replace('function log($$$param){$$$statement}', 'function testLog($$$params){$$$statement}') +let replacedValue = ast.generate(); +fs.writeFileSync('output.js', replacedValue) + + +test1.each(item => { + let variable = item.match.variable[0].value; + let value = item.match.value[0].value; + console.log('variable value', variable, value) +}) + +const res = ast.find('const dict = { $$$0 }'); +const kvs = res.match['$$$0']; +kvs.map((kv) => `${kv.key.name}:${kv.value.value}`); +// a:1,b:2,c:f + + + +const console1 = ast.find('function testLog($_$0) {}') +let console2 = console1.find('console.log($_$0)'); + +// 找到 reactClass 定义的语句 +const reactClass = ast.find('class $_$0 extends React.Component {}'); + +// 找到 jsx 里面带有 onClick 属性的标签 +const onClick = reactClass.find('<$_$0 onClick={$_$1}>'); + +// 创建一个数组用来收集 onClick 对应的 hanlder 的名称 +const clickFnNames = []; + +// 有可能找到很多个带有 onClick 的标签,我们这里用 each 去处理每一条 +onClick.each((e) => { + // 用 match[1][0] 来找到 $_$1 匹配到的第一个 onClick 属性对应的 handler 节点 + // 取 value 即为节点名 + // handlerName = 'this.handleClick' + const handlerName = e.match[1][0].value; + clickFnNames.push(handlerName); +}); + +let value = clickFnNames.map((name) => `${name} = ${name}.bind(this)`).join(';') + +// 替换原有的 constructor,但利用 $$$ 保留原有的参数和语句,只是在最后补上 bind 语句即可 +reactClass.replace( + 'constructor($$$0) { $$$1 }', + `constructor($$$0) { + $$$1; + ${clickFnNames.map((name) => `${name} = ${name}.bind(this)`).join(';')} + }`, +); + +let result = reactClass.generate() + + +fs.writeFileSync('output2.js', result) +``` + \ No newline at end of file diff --git a/src/frontend/library/gogocode/index.md b/src/frontend/library/gogocode/index.md index 38d1765..b0cf600 100644 --- a/src/frontend/library/gogocode/index.md +++ b/src/frontend/library/gogocode/index.md @@ -4,7 +4,7 @@ let ast = gogocode(string) // 生成gogoCode的ast实例 ## 实例方法: 全部返回的都是gogocode实例,只不过他们的match不一样而已,返回值是一个对象,但是有each方法,返回匹配的多个值,直接调用match只会返回匹配的第一个值(改值是一个对象,对象的key是$_$name里面的name) -- find: 匹配某格式文本,并且将其命名,ast.find('const $_$key = $_$value'), 可以使用.match或者(.each(item,index => item.match)index为1是表示第一个)获取第一个匹配的,如果有多个匹配,只能.each(item => item.match) +- find: 匹配某格式文本,并且将其命名,ast.find('const $\_$key = $\_$value'), 可以使用.match或者(.each(item,index => item.match)index为1是表示第一个)获取第一个匹配的,如果有多个匹配,只能.each(item => item.match) - replaceBy: find之后直接替换 diff --git a/src/frontend/library/inquirer/index-source.md b/src/frontend/library/inquirer/index-source.md new file mode 100644 index 0000000..9044534 --- /dev/null +++ b/src/frontend/library/inquirer/index-source.md @@ -0,0 +1,64 @@ + +``` + /** + * Input prompt example + */ + +import chalk from 'chalk'; +import inquirer from "inquirer"; + +const hexRegEx = /(\d|[a-f])/gim; +const isHex = (value) => + (value.match(hexRegEx) || []).length === value.length && + (value.length === 3 || value.length === 6); + +const questions = [ + { + type: 'checkbox', + choices: [{ name: 'haha', value: 'a', disabled: true }, { name: '第二个', value: 'b' }, { value: 'c' }], + name: 'first_name', + message: "What's your first name", + }, + { + type: 'input', + name: 'last_name', + message: "What's your last name", + default() { + return 'Doe'; + }, + }, + { + type: 'input', + name: 'fav_color', + message: "What's your favorite color", + transformer(color, answers, flags) { + const text = chalk.hex(isHex(color) ? color : 'fff')(color); + if (flags.isFinal) { + return text + '!'; + } + + return text; + }, + }, + // { + // type: 'input', + // name: 'phone', + // message: "What's your phone number", + // validate(value) { + // const pass = value.match( + // /^([01])?[\s.-]?\(?(\d{3})\)?[\s.-]?(\d{3})[\s.-]?(\d{4})\s?((?:#|ext\.?\s?|x\.?\s?)(?:\d+)?)?$/i, + // ); + // if (pass) { + // return true; + // } + + // return 'Please enter a valid phone number'; + // }, + // }, +]; + +inquirer.prompt(questions).then((answers) => { + console.log(JSON.stringify(answers, null, ' ')); +}); +``` + \ No newline at end of file diff --git a/src/frontend/library/inquirer/index.md b/src/frontend/library/inquirer/index.md index 376f991..1ba5e92 100644 --- a/src/frontend/library/inquirer/index.md +++ b/src/frontend/library/inquirer/index.md @@ -1,3 +1,3 @@ # inquirer -命令行交互库 \ No newline at end of file +命令行交互库, 统一所有交互,然后再后面的then作为返回值处理 \ No newline at end of file diff --git a/src/frontend/library/ora/index-source.md b/src/frontend/library/ora/index-source.md new file mode 100644 index 0000000..27f2836 --- /dev/null +++ b/src/frontend/library/ora/index-source.md @@ -0,0 +1,28 @@ + +``` + import ora from 'ora'; + +const spinner = ora('Loading unicorns').start(); + +async function changeColor() { + await new Promise(resolve => { + setTimeout(() => { + spinner.color = 'yellow'; + spinner.text = 'Loading rainbows'; + resolve() + }, 1000); + }) + + new Promise(resolve => { + setTimeout(() => { + spinner.stop(); + resolve() + }, 1000); + }) + +} + +changeColor(); + +``` + \ No newline at end of file diff --git a/src/frontend/library/semver/index-source.md b/src/frontend/library/semver/index-source.md new file mode 100644 index 0000000..fd2d9b7 --- /dev/null +++ b/src/frontend/library/semver/index-source.md @@ -0,0 +1,5 @@ + +``` + +``` + \ No newline at end of file diff --git a/src/frontend/library/shelljs/index-source.md b/src/frontend/library/shelljs/index-source.md new file mode 100644 index 0000000..1f3f8f3 --- /dev/null +++ b/src/frontend/library/shelljs/index-source.md @@ -0,0 +1,15 @@ + +``` + var shell = require('shelljs'); +// var path = require('path'); +// console.log('dddd') +// shell.echo('hahah') +// let res = shell.cat(`${__dirname}/shelljs.js`); +// console.log(res.stdout) + +let a = shell.cd("../"); +let b = shell.ls(); +console.log(a, b) + +``` + \ No newline at end of file diff --git a/src/hooks.js b/src/hooks.js new file mode 100644 index 0000000..a269fc5 --- /dev/null +++ b/src/hooks.js @@ -0,0 +1,51 @@ +#!/usr/bin/env node + +let { program } = require("commander"); +let { readFileSync, readdirSync, writeFileSync } = require("fs"); +let path = require('path'); + +program.command('prebuild').description('发布之前执行的hook') + .action(() => { + appendJSToMD(__dirname) + }) + + +function appendJSToMD(dirPath) { + console.log(__dirname) + let currentDirName = path.basename(dirPath) + let dirInfoList = readdirSync(dirPath, { withFileTypes: true }); + // 该文件夹下面有index.js 或者dirname.js 同时该文件下面有index.md + let files = dirInfoList.filter(item => item.isFile()); + let dirs = dirInfoList.filter(item => item.isDirectory()); + let origin = null, destination = null; + files.forEach(item => { + if (['index.md', `${currentDirName}.md`].includes(item.name)) { + destination = item + return; + } + if (['index.js', `${currentDirName}.js`, 'index.mjs', `${currentDirName}.mjs`].includes(item.name)) { + origin = item; + return; + } + }) + + if (origin && destination) { + let originText = readFileSync(path.resolve(dirPath, origin.name)); + writeFileSync(path.resolve(dirPath, "index-source.md"), ` +\`\`\` + ${originText} +\`\`\` + `) + } + + dirs.forEach(item => { + appendJSToMD(path.resolve(dirPath, item.name)) + }) + + + + console.log('dir', dirInfoList); +} + + +appendJSToMD(__dirname); \ No newline at end of file diff --git a/src/index.md b/src/index.md index 2b219d6..798c888 100644 --- a/src/index.md +++ b/src/index.md @@ -9,10 +9,8 @@ hero: actions: - theme: brand1 text: Markdown Examples - link: /markdown-examples - theme: alt text: API Examples - link: /api-examples features: - title: Feature A1 diff --git a/src/markdown-examples.md b/src/markdown-examples.md deleted file mode 100644 index b726568..0000000 --- a/src/markdown-examples.md +++ /dev/null @@ -1 +0,0 @@ -examples \ No newline at end of file