diff --git a/README.md b/README.md index d4874b7..d8fef7a 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ Quick Reference 为开发人员分享快速参考备忘单(主要是方便自己),在看到 [Reference](https://github.com/Randy8080/reference) 快速参考备忘单,感觉非常简单,造轮子使命感突然来了,造个中文版本的,为了方便自己的技术栈查阅,立马撸起来 :)。 -如果您发现此处的备忘单不合适,您可以通过提交 PR 来修复它或提供更好的备忘单,只针对【中文】用户。 +如果您发现此处的备忘单不合适,您可以通过提交 PR 来修复它或提供更好的备忘清单,只针对【中文】用户。 -以下是开源天使提供的一些备忘单和快速参考 :)。 +以下是开源天使提供的一些备忘清单和快速参考 :)。 ## 编程 @@ -18,6 +18,10 @@ Quick Reference [VSCode](./docs/vscode.md) +## Linux 命令 + +[Cron](./docs/cron.md) + ## License MIT © [Kenny Wong](https://github.com/jaywcjlove) diff --git a/docs/cron.md b/docs/cron.md new file mode 100644 index 0000000..3dba57d --- /dev/null +++ b/docs/cron.md @@ -0,0 +1,104 @@ +Cron 备忘清单 +=== + + +[Cron](https://en.wikipedia.org/wiki/Cron) 最适合安排重复性任务。 可以使用关联的 at 实用程序来完成一次性任务的调度。 + +Crontab 格式 +------ + + +### 格式 + +``` +Min Hour Day Mon Weekday +分钟 小时 天 月 周 +``` + +------- + +``` +* * * * * 要执行的命令 +┬ ┬ ┬ ┬ ┬ +│ │ │ │ └─ 星期几 (0=周日 .. 6=星期六) +│ │ │ └────── 月 (1..12) +│ │ └─────────── 月份中的某天 (1..31) +│ └──────────────── 小时 (0..23) +└───────────────────── 分钟 (0..59) +``` + +------ + +| 字段 | 范围 | 特殊字符 | +|--------------|--------|--------------------| +| 分钟 Minute | 0 - 59 | , - * / | +| 小时 Hour | 0 - 23 | , - * / | +| 月份中的某天 | 1 - 31 | , - * ? / L W | +| 月 Month | 1 - 12 | , - * / | +| 星期几 | 0 - 6 | , - * ? / L # | + + +### 示例 + +| Example | Description | +|----------------|------------------------| +| `*/15 * * * *` | 每 15 分钟 | +| `0 * * * *` | 每隔一小时 | +| `0 */2 * * *` | 每 2 小时 | +| `15 2 * * *` | 每天凌晨 2 点 15 分 | +| `15 2 * * ?` | 每天凌晨 2 点 15 分 | +| `10 9 * * 5` | 每周五上午 9:10 | +| `0 0 * * 0` | 每个星期日的午夜 | +| `15 2 * * 1L` | 每月最后一个星期一凌晨 2 点 15 分 | +| `15 0 * * 4#2` | 每个月的第二个星期四早上 00:15 | +| `0 0 0 1 * *` | 每个月的 1 日(每月) | +| `0 0 0 1 1 *` | 每年 1 月 1 日(每年) | +| `@reboot` | 每次重启 _(非标准)_ | + + + +### 特殊字符串 + +| 特殊字符串 | 意义 | +|----------------|----------------------------------------------------| +| @reboot | 运行一次,在系统启动时 _(非标准)_ | +| @yearly | 每年运行一次,“0 0 1 1 *” _(非标准)_ | +| @annually | (与@yearly 相同)_(非标准)_ | +| @monthly | 每月运行一次,“0 0 1 * *” _(非标准)_ | +| @weekly | 每周运行一次,“0 0 * * 0” _(非标准)_ | +| @daily | 每天运行一次,“0 0 * * *” _(非标准)_ | +| @midnight | (与@daily 相同)_(非标准)_ | +| @hourly | 每小时运行一次,“0 * * * *” _(非标准)_ | + + +### Crontab 命令 + +| - | - | +|--------------|---------------------------------------------| +| `crontab -e` | 如果不存在,则编辑或创建一个 crontab 文件。 | +| `crontab -l` | 显示 crontab 文件。 | +| `crontab -r` | 删除 crontab 文件。 | +| `crontab -v` | 显示您上次编辑 crontab 文件的时间。 _(非标准)_ | + + + +### 特殊字符 + + + +| 特殊字符 | 说明 | +|---------------------|------------------------------------------------------------------------------------------| +| `Asterik(*)` | 匹配字段中的所有值或任何可能的值。 | +| `Hyphen(-)` | 用于定义范围。例如:第 5 个字段(星期几)中的 1-5 每个工作日,即星期一到星期五 | +| `Slash (/)` | 第一个字段(分钟)/15 表示每十五分钟或范围的增量。 | +| `Comma (,)` | 用于分隔项目。例如:第二个字段(小时)中的 2、6、8 在凌晨 2 点、早上 6 点和早上 8 点执行 | +| `L` | 仅允许用于 `月份中的某天` 或 `星期几` 字段,`星期几` 中的 `2L` 表示每个月的最后一个星期二 | +| `Hash (#)` | 仅允许用于 `星期几` 字段,后面必须在 1 到 5 的范围内。例如,`4#1` 表示给定月份的“第一个星期四”。 | +| `Question mark (?)` | 可以代替“*”并允许用于月份和星期几。使用仅限于 cron 表达式中的 `月份中的某天` 或 `星期几`。 | + + +## Also see + +* [Devhints](https://devhints.io/cron) _(devhints.io)_ +* [Crontab Generator](https://crontab-generator.org/) _(crontab-generator.org)_ +* [Crontab guru](https://crontab.guru/) _(crontab.guru)_ \ No newline at end of file diff --git a/docs/javascript.md b/docs/javascript.md index 7435e31..77e12aa 100644 --- a/docs/javascript.md +++ b/docs/javascript.md @@ -1053,7 +1053,7 @@ module.exports = { } ``` -### Require Module +### 加载模块 ```javascript // main.js @@ -1068,7 +1068,7 @@ JavaScript Promises ---- -### Promise states +### Promise 状态 @@ -1086,7 +1086,7 @@ const promise = new Promise((resolve, reject) => { promise.then((res) => console.log(res), (err) => console.error(err)); ``` -### Executor function +### 执行器函数 ```javascript const executorFn = (resolve, reject) => { @@ -1104,7 +1104,7 @@ const loginAlert = () =>{ setTimeout(loginAlert, 6000); ``` -### .then() method +### .then() 方法 ```javascript const promise = new Promise((resolve, reject) => { @@ -1119,7 +1119,7 @@ promise.then((res) => { }); ``` -### .catch() method +### .catch() 方法 ```javascript const promise = new Promise((resolve, reject) => { @@ -1154,7 +1154,7 @@ Promise.all([promise1, promise2]).then((res) => { }); ``` -### Avoiding nested Promise and .then() +### 避免嵌套的 Promise 和 .then() ```javascript const promise = new Promise((resolve, reject) => { @@ -1171,11 +1171,11 @@ const oneDot = (star) => { const print = (val) => { console.log(val); }; -// Chaining them all together +// 将它们链接在一起 promise.then(twoStars).then(oneDot).then(print); ``` -### Creating +### 创建 ```javascript const executorFn = (resolve, reject) => { @@ -1184,7 +1184,7 @@ const executorFn = (resolve, reject) => { const promise = new Promise(executorFn); ``` -### Chaining multiple .then() +### 链接多个 .then() ```javascript const promise = new Promise(resolve => setTimeout(() => resolve('dAlan'), 100)); @@ -1201,7 +1201,7 @@ JavaScript Async-Await ---- -### Asynchronous +### 异步 ```javascript function helloWorld() { @@ -1211,19 +1211,19 @@ function helloWorld() { }, 2000); }); } -const msg = async function() { //Async Function Expression +const msg = async function() { // 异步函数表达式 const msg = await helloWorld(); console.log('Message:', msg); } -const msg1 = async () => { //Async Arrow Function +const msg1 = async () => { // 异步箭头函数 const msg = await helloWorld(); console.log('Message:', msg); } -msg(); // Message: Hello World! <-- after 2 seconds -msg1(); // Message: Hello World! <-- after 2 seconds +msg(); // Message: Hello World! <-- 2 秒后 +msg1(); // Message: Hello World! <-- 2 秒后 ``` -### Resolving Promises +### 解决 Promises ```javascript let pro1 = Promise.resolve(5); @@ -1237,7 +1237,7 @@ Promise.all([pro1, pro2, pro3]).then(function(values) { // expected => Array [5, 44, "foo"] ``` -### Async Await Promises +### 异步等待 Promises ```javascript function helloWorld() { @@ -1251,22 +1251,22 @@ async function msg() { const msg = await helloWorld(); console.log('Message:', msg); } -msg(); // Message: Hello World! <-- after 2 seconds +msg(); // Message: Hello World! <-- 2 秒后 ``` -### Error Handling +### 错误处理 ```javascript -let json = '{ "age": 30 }'; // incomplete data +let json = '{ "age": 30 }'; // 数据不完整 try { - let user = JSON.parse(json); // <-- no errors + let user = JSON.parse(json); // <-- 没有错误 console.log( user.name ); // no name! } catch (e) { console.error( "Invalid JSON data!" ); } ``` -### Aysnc await operator +### 异步等待运算符 ```javascript function helloWorld() { @@ -1280,7 +1280,7 @@ async function msg() { const msg = await helloWorld(); console.log('Message:', msg); } -msg(); // Message: Hello World! <-- after 2 seconds +msg(); // Message: Hello World! <-- 2 秒后 ``` JavaScript 请求 @@ -1402,7 +1402,7 @@ fetch('https://api-xxx.com/endpoint', { }) ``` -### async await syntax +### async await 语法 diff --git a/scripts/build.mjs b/scripts/build.mjs index ab8594d..9da8d29 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -1,43 +1,3 @@ -import fs from 'fs-extra'; -import path from 'path'; -import recursiveReaddirFiles from 'recursive-readdir-files'; -import { create } from './create.mjs'; +import { run } from './index.mjs'; -const OUTOUT = path.resolve(process.cwd(), 'dist'); -const DOCS = path.resolve(process.cwd(), 'docs'); -const CSSPATH = path.resolve(process.cwd(), 'scripts/style.css'); -const CSS_OUTPUT_PATH = path.resolve(OUTOUT, 'style/style.css'); - -async function createHTML(files = [], num = 0) { - const dataFile = files[num]; - if (!dataFile) { - console.log('\ndone!') - return; - } - ++num; - - const mdstr = await fs.readFile(dataFile.path); - const htmlPath = path.relative(DOCS, dataFile.path); - const outputHTMLPath = path.resolve(OUTOUT, 'docs', htmlPath).replace(/README.md$/i, 'index.html').replace(/.md$/, '.html'); - - await fs.ensureDir(path.dirname(outputHTMLPath)); - const html = create(mdstr.toString(), { - css: [path.relative(path.dirname(outputHTMLPath), CSS_OUTPUT_PATH)] - }); - await fs.writeFile(outputHTMLPath, html); - console.log(`♻️ \x1b[32;1m ${path.relative(OUTOUT, outputHTMLPath)} \x1b[0m`) - createHTML(files, num) -} - -;(async () => { - await fs.ensureDir(OUTOUT); - await fs.emptyDir(OUTOUT); - await fs.ensureDir(path.dirname(CSS_OUTPUT_PATH)); - await fs.copyFile(CSSPATH, CSS_OUTPUT_PATH) - const files = await recursiveReaddirFiles(process.cwd(), { - ignored: /\/(node_modules|\.git)/, - exclude: /(\.json|mjs)$/, - filter: (item) => item.ext === 'md', - }); - createHTML(files); -})(); +run() diff --git a/scripts/create.mjs b/scripts/create.mjs index d82ae39..7410191 100644 --- a/scripts/create.mjs +++ b/scripts/create.mjs @@ -3,6 +3,7 @@ import rehypeDocument from 'rehype-document'; import rehypeFormat from 'rehype-format'; import { rehypeUrls } from './nodes/rehypeUrls.mjs'; import { htmlTagAddAttri } from './nodes/htmlTagAddAttri.mjs'; +import { footer } from './nodes/footer.mjs'; /** 标记 Number */ function panelAddNumber(arr = [], result = []) { @@ -61,10 +62,10 @@ export function getTocsTree(arr = [], result = []) { if (level === 1) warpCls.push('max-container'); const warpStyle = toc.properties['data-warp-style']; - const bodyStyle = toc.properties['data-body-style']; delete toc.properties['data-warp-style'] - delete toc.properties['data-body-style'] - + const warpClass = toc.properties['warp-class']; + if (warpClass) warpCls.push(warpClass); + delete toc.properties['warp-class']; const panle = { type: 'element', tagName: 'div', @@ -91,10 +92,15 @@ export function getTocsTree(arr = [], result = []) { const childs = getChilds([...data.slice(n + 1)], level); const resultChilds = getTocsTree(childs); if (resultChilds.length > 0) { + const bodyStyle = toc.properties['data-body-style']; + delete toc.properties['data-body-style'] + + const bodyClass = toc.properties['body-class']; + delete toc.properties['body-class'] panle.children = panle.children.concat({ type: 'element', tagName: 'div', - properties: { class: `h${level}warp-body`, style: bodyStyle }, + properties: { class: [`h${level}warp-body`, bodyClass], style: bodyStyle }, children: [...resultChilds] }); } @@ -126,6 +132,7 @@ export function create(str = '', options = {}) { rehypeUrls(node); if (node.type === 'element' && node.tagName === 'body') { node.children = getTocsTree([ ...node.children ]); + node.children.push(footer()); } } } diff --git a/scripts/index.mjs b/scripts/index.mjs new file mode 100644 index 0000000..eb9da08 --- /dev/null +++ b/scripts/index.mjs @@ -0,0 +1,43 @@ +import fs from 'fs-extra'; +import path from 'path'; +import recursiveReaddirFiles from 'recursive-readdir-files'; +import { create } from './create.mjs'; + +const OUTOUT = path.resolve(process.cwd(), 'dist'); +const DOCS = path.resolve(process.cwd(), 'docs'); +const CSSPATH = path.resolve(process.cwd(), 'scripts/style.css'); +const CSS_OUTPUT_PATH = path.resolve(OUTOUT, 'style/style.css'); + +async function createHTML(files = [], num = 0) { + const dataFile = files[num]; + if (!dataFile) { + console.log('\ndone!') + return; + } + ++num; + + const mdstr = await fs.readFile(dataFile.path); + const htmlPath = path.relative(DOCS, dataFile.path); + const outputHTMLPath = path.resolve(OUTOUT, 'docs', htmlPath).replace(/README.md$/i, 'index.html').replace(/.md$/, '.html'); + + await fs.ensureDir(path.dirname(outputHTMLPath)); + const html = create(mdstr.toString(), { + css: [path.relative(path.dirname(outputHTMLPath), CSS_OUTPUT_PATH)] + }); + await fs.writeFile(outputHTMLPath, html); + console.log(`♻️ \x1b[32;1m ${path.relative(OUTOUT, outputHTMLPath)} \x1b[0m`) + createHTML(files, num) +} + +export async function run() { + await fs.ensureDir(OUTOUT); + await fs.emptyDir(OUTOUT); + await fs.ensureDir(path.dirname(CSS_OUTPUT_PATH)); + await fs.copyFile(CSSPATH, CSS_OUTPUT_PATH) + const files = await recursiveReaddirFiles(process.cwd(), { + ignored: /\/(node_modules|\.git)/, + exclude: /(\.json|mjs)$/, + filter: (item) => item.ext === 'md', + }); + createHTML(files); +} diff --git a/scripts/nodes/footer.mjs b/scripts/nodes/footer.mjs index e69de29..789b4c7 100644 --- a/scripts/nodes/footer.mjs +++ b/scripts/nodes/footer.mjs @@ -0,0 +1,22 @@ + +export function footer() { + return { + type: 'element', + tagName: 'footer', + properties: { + class: 'footer-warp', + }, + children: [ + { + type: 'element', + tagName: 'footer', + properties: { + class: ['max-container'], + }, + children: [ + { type: 'text', value: '© 2022 Kenny Wang, All rights reserved.' } + ], + } + ], + }; +} diff --git a/scripts/style.css b/scripts/style.css index 587c2fe..e5bf62f 100644 --- a/scripts/style.css +++ b/scripts/style.css @@ -288,6 +288,13 @@ pre { overflow-x: auto; } +.cols-2 { + grid-template-columns: repeat(2,minmax(0,1fr)); +} +.col-span-2 { + grid-column: span 2/span 2; +} + [data-color-mode*='light'], [data-color-mode*='light'] body { --color-prettylights-syntax-comment: #6e7781; --color-prettylights-syntax-constant: #0550ae; @@ -447,4 +454,11 @@ pre { .token.italic { font-style: italic; } .token.entity { cursor: help; } -/* 代码高亮 End */ \ No newline at end of file +/* 代码高亮 End */ + + +.footer-warp { + margin-top: 3.5rem; + color: rgb(100 116 139/1); + background-color: rgb(30 41 59/1); +} \ No newline at end of file