mirror of
https://github.com/jaywcjlove/reference.git
synced 2025-06-16 20:21:22 +08:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
593662f3c6 | |||
a5ec6ff25c | |||
a34e5372fe | |||
b0eb01e566 | |||
2fcd80f34d | |||
6eb1ef3260 | |||
1ee5910d86 | |||
c221cd1ac3 | |||
f1d7c9e585 | |||
f13778aa5a | |||
45a20dd749 | |||
c19283b71f | |||
9a5e90d6e6 | |||
eeb88275fd | |||
01100e3c4a | |||
edaf58f327 | |||
864ef36fd6 | |||
7f4e2f5b1c | |||
417353e1ae | |||
0468d5ec52 | |||
db26d12c9d | |||
7728dfaa75 |
87
.github/workflows/ci.yml
vendored
87
.github/workflows/ci.yml
vendored
@ -16,9 +16,94 @@ jobs:
|
||||
- run: npm install
|
||||
- run: npm run build
|
||||
|
||||
- name: Create Tag
|
||||
id: create_tag
|
||||
uses: jaywcjlove/create-tag-action@main
|
||||
with:
|
||||
package-path: ./package.json
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
commit_message: ${{ github.event.head_commit.message }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist
|
||||
publish_dir: ./dist
|
||||
|
||||
- name: Generate Changelog
|
||||
id: changelog
|
||||
uses: jaywcjlove/changelog-generator@main
|
||||
with:
|
||||
filter-author: (小弟调调™)
|
||||
filter: (^[\s]+?[R|r]elease)|(^[R|r]elease)
|
||||
|
||||
|
||||
- name: Create Release
|
||||
uses: ncipollo/release-action@v1
|
||||
if: steps.create_tag.outputs.successful
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: ${{ steps.create_tag.outputs.version }}
|
||||
tag: ${{ steps.create_tag.outputs.version }}
|
||||
body: |
|
||||
|
||||
${{ steps.changelog.outputs.compareurl }}
|
||||
|
||||
${{ steps.changelog.outputs.changelog }}
|
||||
|
||||
## Docker
|
||||
[](https://hub.docker.com/r/wcjiang/reference) [](https://hub.docker.com/r/wcjiang/reference) [](https://hub.docker.com/r/wcjiang/reference)
|
||||
|
||||
轻松通过 `docker` 部署 `Quick Reference` 网站。
|
||||
|
||||
```bash
|
||||
docker pull wcjiang/reference
|
||||
```
|
||||
|
||||
```bash
|
||||
docker run --name reference --rm -d -p 9667:3000 wcjiang/reference:latest
|
||||
# Or
|
||||
docker run --name reference -itd -p 9667:3000 wcjiang/reference:latest
|
||||
```
|
||||
|
||||
在浏览器中访问以下 URL
|
||||
|
||||
```bash
|
||||
http://localhost:9667/
|
||||
```
|
||||
|
||||
# Create Docker Image in Github
|
||||
- name: Login to GitHub registry
|
||||
run: echo ${{ github.token }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Build docker image
|
||||
run: docker build -t ghcr.io/jaywcjlove/reference:latest .
|
||||
|
||||
- name: Publish to GitHub registry
|
||||
run: docker push ghcr.io/jaywcjlove/reference:latest
|
||||
|
||||
- name: Tag docker image (beta) and publish to GitHub registry
|
||||
if: steps.create_tag.outputs.successful
|
||||
run: |
|
||||
echo "version: v${{ steps.changelog.outputs.version }}"
|
||||
docker tag ghcr.io/jaywcjlove/reference:latest ghcr.io/jaywcjlove/reference:${{steps.changelog.outputs.version}}
|
||||
docker push ghcr.io/jaywcjlove/reference:${{steps.changelog.outputs.version}}
|
||||
|
||||
# Create Docker Image
|
||||
- name: Docker login
|
||||
run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build reference image
|
||||
run: docker image build -t reference .
|
||||
|
||||
- name: Tags & Push image(latest)
|
||||
run: |
|
||||
echo "DOCKER_USER: ${{ secrets.DOCKER_USER }}"
|
||||
docker tag reference ${{ secrets.DOCKER_USER }}/reference:latest
|
||||
docker push ${{ secrets.DOCKER_USER }}/reference:latest
|
||||
|
||||
- name: Tags & Push image
|
||||
if: steps.create_tag.outputs.successful
|
||||
run: |
|
||||
echo "outputs.tag - ${{ steps.changelog.outputs.version }}"
|
||||
docker tag reference ${{ secrets.DOCKER_USER }}/reference:${{steps.changelog.outputs.version}}
|
||||
docker push ${{ secrets.DOCKER_USER }}/reference:${{steps.changelog.outputs.version}}
|
7
Dockerfile
Normal file
7
Dockerfile
Normal file
@ -0,0 +1,7 @@
|
||||
# https://lipanski.com/posts/smallest-docker-image-static-website
|
||||
# https://github.com/lipanski/docker-static-website
|
||||
FROM lipanski/docker-static-website:latest
|
||||
|
||||
# Copy the static website
|
||||
# Use the .dockerignore file to control what ends up inside the image!
|
||||
COPY ./dist .
|
12
README.md
12
README.md
@ -1,6 +1,13 @@
|
||||
Quick Reference
|
||||
===
|
||||
|
||||
<!--rehype:ignore:start-->
|
||||
[](https://github.com/jaywcjlove/reference/actions/workflows/ci.yml)
|
||||
[](https://hub.docker.com/r/wcjiang/reference)
|
||||
[](https://hub.docker.com/r/wcjiang/reference)
|
||||
[](https://hub.docker.com/r/wcjiang/reference)
|
||||
<!--rehype:ignore:end-->
|
||||
|
||||
为开发人员分享快速参考备忘清单(主要是方便自己),在看到 [Reference](https://github.com/Randy8080/reference) 快速参考备忘单,感觉非常简单,造轮子使命感突然来了,造个中文版本的,为了方便自己的技术栈查阅,立马撸起来 :)。
|
||||
|
||||
如果您发现此处的备忘单不合适,您可以通过提交 [PR](https://github.com/jaywcjlove/reference/blob/main/CONTRIBUTING.md) 来修复它或提供更好的备忘清单,只针对【中文】用户。以下是开源天使提供的一些备忘清单和快速参考 :)。
|
||||
@ -13,17 +20,22 @@ Quick Reference
|
||||
[JavaScript](./docs/javascript.md)<!--rehype:style=background: rgb(203 183 31/var(\-\-bg\-opacity));-->
|
||||
[JSON](./docs/json.md)<!--rehype:style=background: rgb(57 59 60/var(\-\-bg\-opacity));-->
|
||||
[React](./docs/react.md)<!--rehype:style=background: rgb(34 143 173/var(\-\-bg\-opacity));-->
|
||||
[Styled Components](./docs/styled-components.md)<!--rehype:style=background: rgb(221 60 184/var(\-\-bg\-opacity));-->
|
||||
[TOML](./docs/toml.md)<!--rehype:style=background: rgb(132 132 132/var(\-\-bg\-opacity));-->
|
||||
[Markdown](./docs/markdown.md)<!--rehype:style=background: rgb(103 61 156/var(\-\-bg\-opacity));-->
|
||||
[TypeScript](./docs/typescript.md)<!--rehype:style=background: rgb(49 120 198/var(\-\-bg\-opacity));-->
|
||||
[YAML](./docs/yaml.md)<!--rehype:style=background: rgb(91 163 230/var(\-\-bg\-opacity));-->
|
||||
<!--rehype:class=home-card-->
|
||||
|
||||
## 工具包
|
||||
|
||||
[Emmet](./docs/emmet.md)<!--rehype:style=background: rgb(122 203 23/var(\-\-bg\-opacity));-->
|
||||
[nginx](./docs/nginx.md)<!--rehype:style=background: rgb(0 193 9/var(\-\-bg\-opacity));-->
|
||||
[npm](./docs/npm.md)<!--rehype:style=background: rgb(203 2 0/var(\-\-bg\-opacity));-->
|
||||
[package.json](./docs/package.json.md)<!--rehype:style=background: rgb(132 132 132/var(\-\-bg\-opacity));-->
|
||||
[Semver](./docs/semver.md)<!--rehype:style=background: rgb(106 111 141/var(\-\-bg\-opacity));-->
|
||||
[Sketch](./docs/sketch.md)<!--rehype:style=background: rgb(223 148 0/var(\-\-bg\-opacity));-->
|
||||
[Sublime Text](./docs/sublime-text.md)<!--rehype:style=background: rgb(223 148 0/var(\-\-bg\-opacity));-->
|
||||
[Jest](./docs/jest.md)<!--rehype:style=background: rgb(153 66 91/var(\-\-bg\-opacity));-->
|
||||
[RegEx](./docs/regex.md)<!--rehype:style=background: rgb(149 36 155/var(\-\-bg\-opacity));-->
|
||||
[VSCode](./docs/vscode.md)<!--rehype:style=background: rgb(91 163 230/var(\-\-bg\-opacity));-->
|
||||
|
@ -25,12 +25,13 @@ $ docker run -d -p 80:80 docker/getting-started
|
||||
在前台创建并运行容器
|
||||
|
||||
```shell
|
||||
$ docker run -it -p 8001:8080 --name my-nginx nginx
|
||||
$ docker run -it -p --rm 8001:8080 --name my-nginx nginx
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
- `-it` - 交互式 bash 模式
|
||||
- `--rm` - 容器终止运行后自动删除容器文件
|
||||
- `-p 8001:8080` - 将 `8001` 端口映射到容器中的 `8080` 端口
|
||||
- `--name my-nginx` - 指定名称
|
||||
- `nginx` - 要使用的镜像
|
||||
@ -291,6 +292,64 @@ $ docker volume ls
|
||||
$ docker volume prune
|
||||
```
|
||||
|
||||
### Docker Compose
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`docker-compose up` | 创建和启动容器
|
||||
`docker-compose up -d` | 以分离模式创建和启动容器
|
||||
`docker-compose down` | 停止和删除容器、网络、映像和卷
|
||||
`docker-compose logs` | 查看容器的输出
|
||||
`docker-compose restart` | 重启所有服务
|
||||
`docker-compose pull` | 拉取所有图片服务
|
||||
`docker-compose build` | 构建所有图像服务
|
||||
`docker-compose config` | 验证并查看 Compose 文件
|
||||
`docker-compose scale <service_name>=<replica>` | 规模特殊服务
|
||||
`docker-compose top` | 显示正在运行的进程
|
||||
`docker-compose run -rm -p 2022:22 web bash` | 启动 Web 服务并运行 bash 作为其命令,删除旧容器。
|
||||
|
||||
### Docker Services
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`docker service create <options> <image> <command>` | 创建新服务
|
||||
`docker service inspect --pretty <service_name>` | 显示详细信息服务
|
||||
`docker service ls` | 列出服务
|
||||
`docker service ps` | 列出服务的任务
|
||||
`docker service scale <service_name>=<replica>` | 规模特殊服务
|
||||
`docker service update <options> <service_name>` | 更新服务选项
|
||||
|
||||
### Docker Stack
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`docker stack ls` | 列出此 Docker 主机上所有正在运行的应用程序
|
||||
`docker stack deploy -c <composefile> <appname>` | 运行指定的 Compose 文件
|
||||
`docker stack services <appname>` | 列出与应用关联的服务
|
||||
`docker stack ps <appname>` | 列出与应用关联的正在运行的容器
|
||||
`docker stack rm <appname>` | 拆掉一个应用程序
|
||||
|
||||
### Docker Machine
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`docker-machine create --driver virtualbox myvm1` | 创建虚拟机(Mac、Win7、Linux)
|
||||
`docker-machine create -d hyperv --hyperv-virtual-switch "myswitch" myvm1` | Win10
|
||||
`docker-machine env myvm1` | 查看有关您的节点的基本信息
|
||||
`docker-machine ssh myvm1 "docker node ls"` | 列出集群中的节点
|
||||
`docker-machine ssh myvm1 "docker node inspect <node ID>"` | 检查节点
|
||||
`docker-machine ssh myvm1 "docker swarm join-token -q worker"` | 查看加入令牌
|
||||
`docker-machine ssh myvm1` | 打开与 VM 的 SSH 会话; 输入“exit”结束
|
||||
`docker-machine ssh myvm2 "docker swarm leave"` | 让工人离开群体
|
||||
`docker-machine ssh myvm1 "docker swarm leave -f"` | 让主人离开,杀群
|
||||
`docker-machine start myvm1` | 启动当前未运行的 VM
|
||||
`docker-machine stop $(docker-machine ls -q)` | 停止所有正在运行的虚拟机
|
||||
`docker-machine rm $(docker-machine ls -q)` | 删除所有虚拟机及其磁盘映像
|
||||
`docker-machine scp docker-compose.yml myvm1:~` | 将文件复制到节点的主目录
|
||||
`docker-machine ssh myvm1 "docker stack deploy -c <file> <app>"` | 部署应用
|
||||
|
||||
另见
|
||||
----
|
||||
|
||||
|
2404
docs/emmet.md
Normal file
2404
docs/emmet.md
Normal file
File diff suppressed because it is too large
Load Diff
34
docs/git.md
34
docs/git.md
@ -328,25 +328,21 @@ Git 技巧
|
||||
|
||||
### 重命名分支
|
||||
|
||||
#### **重命名**为`new`
|
||||
|
||||
```shell
|
||||
$ git branch -m <new>
|
||||
$ git branch -m <old> <new> # 重命名分支
|
||||
```
|
||||
|
||||
#### **推送**并重置
|
||||
|
||||
```shell
|
||||
$ git push origin -u <new>
|
||||
```
|
||||
|
||||
#### **删除**远程分支
|
||||
|
||||
```shell
|
||||
$ git push origin --delete <old> # 方法1
|
||||
$ git push origin :oldBranchName # 方法2
|
||||
```
|
||||
- **重命名**为`new`
|
||||
```shell
|
||||
$ git branch -m <new>
|
||||
$ git branch -m <old> <new> #重命名分支
|
||||
```
|
||||
- **推送**并重置
|
||||
```shell
|
||||
$ git push origin -u <new>
|
||||
```
|
||||
- **删除**远程分支
|
||||
```shell
|
||||
$ git push origin --delete <old> #方法1
|
||||
$ git push origin :oldBranchName #方法2
|
||||
```
|
||||
<!--rehype:className=style-timeline-->
|
||||
|
||||
### Log
|
||||
|
||||
|
307
docs/jest.md
307
docs/jest.md
@ -5,8 +5,10 @@ Jest 是一款优雅、简洁的 JavaScript 测试框架。
|
||||
|
||||
入门
|
||||
----
|
||||
<!--rehype:body-class=cols-6-->
|
||||
|
||||
### 介绍
|
||||
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
||||
|
||||
[Jest](https://jestjs.io/) 是一款优雅、简洁的 JavaScript 测试框架。
|
||||
|
||||
@ -16,9 +18,54 @@ Jest 是一款优雅、简洁的 JavaScript 测试框架。
|
||||
- `快照` 轻松编写持续追踪大型对象的测试,并在测试旁或代码内显示实时快照。
|
||||
- `代码覆盖` 无需其他操作,您仅需添加 `--coverage` 参数来生成代码覆盖率报告。
|
||||
|
||||
### 测试结构
|
||||
### 快速开始
|
||||
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
||||
|
||||
```bash
|
||||
npm install --save-dev jest
|
||||
```
|
||||
|
||||
Add to `package.json`
|
||||
|
||||
```js
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
}
|
||||
```
|
||||
|
||||
运行你的测试
|
||||
|
||||
```bash
|
||||
npm test -- --watch
|
||||
```
|
||||
|
||||
查看: [Getting started](https://jestjs.io/docs/getting-started)
|
||||
|
||||
### 编写测试
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
describe('My work', () => {
|
||||
test('works', () => {
|
||||
expect(2).toEqual(2)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### BDD 语法
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js {2}
|
||||
describe('My work', () => {
|
||||
it('works', () => { // `it`是`test`的别名
|
||||
···
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 测试结构
|
||||
<!--rehype:wrap-class=col-span-3 row-span-2-->
|
||||
|
||||
```js
|
||||
describe('makePoniesPink', () => {
|
||||
beforeAll(() => {
|
||||
@ -40,6 +87,143 @@ describe('makePoniesPink', () => {
|
||||
})
|
||||
```
|
||||
|
||||
### 聚焦测试
|
||||
|
||||
```js
|
||||
describe.only(···)
|
||||
|
||||
it.only(···)
|
||||
// 别名: fit()
|
||||
```
|
||||
|
||||
查看: [test.only](https://jestjs.io/docs/api#testonlyname-fn-timeout)
|
||||
|
||||
### 可选参数
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
| Flag | Description |
|
||||
| --------------------- | ---------------------------------------- |
|
||||
| `--coverage` | 查看测试覆盖率摘要 |
|
||||
| `--detectOpenHandles` | 查看未关闭端口的摘要 |
|
||||
| `--runInBand` | 一个接一个地运行所有测试 |
|
||||
| `--bail,-b` | 失败跳出测试 |
|
||||
|
||||
更多参数查看 [Jest CLI Options](https://jestjs.io/docs/next/cli#--bailn)
|
||||
|
||||
### 跳过测试
|
||||
|
||||
```js
|
||||
describe.skip(···)
|
||||
|
||||
it.skip(···)
|
||||
// 别名: xit()
|
||||
```
|
||||
|
||||
查看: [test.skip](https://jestjs.io/docs/next/api#testskipname-fn)
|
||||
|
||||
### 基本测试用例
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value).not.toBe(value)
|
||||
.toEqual(value)
|
||||
.toBeTruthy()
|
||||
// Errors 测试
|
||||
expect(value).toThrow(error)
|
||||
.toThrowErrorMatchingSnapshot()
|
||||
```
|
||||
|
||||
### 快照
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toMatchSnapshot()
|
||||
.toMatchInlineSnapshot()
|
||||
```
|
||||
|
||||
### Errors
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toThrow(error)
|
||||
.toThrowErrorMatchingSnapshot()
|
||||
```
|
||||
|
||||
### Objects
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toBeInstanceOf(Class)
|
||||
.toMatchObject(object)
|
||||
.toHaveProperty(keyPath, value)
|
||||
```
|
||||
|
||||
### Objects
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toContain(item)
|
||||
.toContainEqual(item)
|
||||
.toHaveLength(number)
|
||||
```
|
||||
|
||||
### Numbers
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toBeCloseTo(number, numDigits)
|
||||
.toBeGreaterThan(number)
|
||||
.toBeGreaterThanOrEqual(number)
|
||||
.toBeLessThan(number)
|
||||
.toBeLessThanOrEqual(number)
|
||||
```
|
||||
|
||||
### Booleans
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toBeFalsy()
|
||||
.toBeNull()
|
||||
.toBeTruthy()
|
||||
.toBeUndefined()
|
||||
.toBeDefined()
|
||||
```
|
||||
|
||||
### Strings
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect(value)
|
||||
.toMatch(regexpOrString)
|
||||
```
|
||||
|
||||
### NaN
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
test('当值为 NaN 时通过', () => {
|
||||
expect(NaN).toBeNaN();
|
||||
expect(1).not.toBeNaN();
|
||||
});
|
||||
```
|
||||
|
||||
### Others
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```js
|
||||
expect.extend(matchers)
|
||||
expect.any(constructor)
|
||||
expect.addSnapshotSerializer(serializer)
|
||||
|
||||
expect.assertions(1)
|
||||
```
|
||||
|
||||
匹配器
|
||||
----
|
||||
|
||||
@ -293,8 +477,6 @@ expect(fn).toThrowErrorMatchingSnapshot()
|
||||
### 实例
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
请参阅 Jest 文档中的 [更多示例](https://jestjs.io/docs/en/tutorial-async)。
|
||||
|
||||
在异步测试中指定一些预期的断言是一个很好的做法,所以如果你的断言根本没有被调用,测试将会失败。
|
||||
|
||||
```js
|
||||
@ -314,6 +496,7 @@ beforeEach(expect.hasAssertions)
|
||||
```
|
||||
|
||||
这将验证每个测试用例至少存在一个断言。 它还可以与更具体的 `expect.assertions(3)` 声明配合使用。
|
||||
请参阅 Jest 文档中的 [更多示例](https://jestjs.io/docs/en/tutorial-async)
|
||||
|
||||
### async/await
|
||||
|
||||
@ -337,8 +520,8 @@ test('async test', (done) => {
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const result = getAsyncOperationResult()
|
||||
expect(result).toBe(true)
|
||||
const res = getAsyncOperatResult()
|
||||
expect(res).toBe(true)
|
||||
done()
|
||||
} catch (err) {
|
||||
done.fail(err)
|
||||
@ -374,18 +557,28 @@ test('call the callback', () => {
|
||||
const callback = jest.fn()
|
||||
fn(callback)
|
||||
expect(callback).toBeCalled()
|
||||
expect(callback.mock.calls[0][1].baz).toBe('pizza') // 第一次调用的第二个参数
|
||||
expect(callback.mock.calls[0][1].baz)
|
||||
.toBe('pizza') // 第一次调用的第二个参数
|
||||
|
||||
// 匹配第一个和最后一个参数,但忽略第二个参数
|
||||
expect(callback).toHaveBeenLastCalledWith('meal', expect.anything(), 'margarita')
|
||||
expect(callback)
|
||||
.toHaveBeenLastCalledWith(
|
||||
'meal',
|
||||
expect.anything(),
|
||||
'margarita'
|
||||
)
|
||||
})
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
您还可以使用快照:
|
||||
|
||||
```js
|
||||
test('call the callback', () => {
|
||||
// mockName 在 Jest 22+ 中可用
|
||||
const callback = jest.fn().mockName('Unicorn')
|
||||
const callback = jest.fn()
|
||||
.mockName('Unicorn')
|
||||
|
||||
fn(callback)
|
||||
expect(callback).toMatchSnapshot()
|
||||
// ->
|
||||
@ -411,6 +604,7 @@ const callback = jest.fn(() => true)
|
||||
```js
|
||||
const callback
|
||||
= jest.fn().mockReturnValue(true)
|
||||
|
||||
const callbackOnce
|
||||
= jest.fn().mockReturnValueOnce(true)
|
||||
```
|
||||
@ -418,26 +612,29 @@ const callbackOnce
|
||||
或解析值:
|
||||
|
||||
```js
|
||||
const promise
|
||||
const promise
|
||||
= jest.fn().mockResolvedValue(true)
|
||||
const promiseOnce
|
||||
|
||||
const promiseOnce
|
||||
= jest.fn().mockResolvedValueOnce(true)
|
||||
```
|
||||
|
||||
他们甚至可以拒绝值:
|
||||
|
||||
```js
|
||||
const failedPromise
|
||||
= jest.fn().mockRejectedValue('Error')
|
||||
const failedPromiseOnce
|
||||
= jest.fn().mockRejectedValueOnce('Error')
|
||||
const failedPromise =
|
||||
jest.fn().mockRejectedValue('Error')
|
||||
|
||||
const failedPromiseOnce =
|
||||
jest.fn().mockRejectedValueOnce('Error')
|
||||
```
|
||||
|
||||
你甚至可以结合这些:
|
||||
|
||||
```js
|
||||
const callback
|
||||
= jest.fn().mockReturnValueOnce(false).mockReturnValue(true)
|
||||
const callback = jest.fn()
|
||||
.mockReturnValueOnce(false)
|
||||
.mockReturnValue(true)
|
||||
// ->
|
||||
// call 1: false
|
||||
// call 2+: true
|
||||
@ -446,13 +643,20 @@ const callback
|
||||
### 使用 `jest.mock` 方法模拟模块
|
||||
|
||||
```js
|
||||
jest.mock('lodash/memoize', () => (a) => a) // The original lodash/memoize should exist
|
||||
jest.mock('lodash/memoize', () => (a) => a, { virtual: true }) // The original lodash/memoize isn’t required
|
||||
// 原来的 lodash/memoize 应该存在
|
||||
jest.mock(
|
||||
'lodash/memoize',
|
||||
() => (a) => a
|
||||
)
|
||||
// 不需要原始的 lodash/memoize
|
||||
jest.mock(
|
||||
'lodash/memoize',
|
||||
() => (a) => a,
|
||||
{ virtual: true }
|
||||
)
|
||||
```
|
||||
|
||||
[jest.mock docs](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options)
|
||||
|
||||
> 注意:当使用 `babel-jest` 时,对 `jest.mock` 的调用将自动提升到代码块的顶部。 如果您想明确避免这种行为,请使用 `jest.doMock`。
|
||||
注意:当使用 `babel-jest` 时,对 [`jest.mock`](https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options) 的调用将自动提升到代码块的顶部。 如果您想明确避免这种行为,请使用 `jest.doMock`。
|
||||
|
||||
### 使用模拟文件模拟模块
|
||||
|
||||
@ -468,22 +672,18 @@ module.exports = (a) => a
|
||||
jest.mock('lodash/memoize')
|
||||
```
|
||||
|
||||
注意:当使用 `babel-jest` 时,对 `jest.mock` 的调用将自动提升到代码块的顶部。 如果您想明确避免这种行为,请使用 `jest.doMock`。
|
||||
注意:当使用 `babel-jest` 时,对 `jest.mock` 的调用将自动提升到代码块的顶部。 如果您想明确避免这种行为,请使用 `jest.doMock`。[手动模拟文档](https://jestjs.io/docs/en/manual-mocks)
|
||||
|
||||
[手动模拟文档](https://jestjs.io/docs/en/manual-mocks)
|
||||
|
||||
### 模拟对象方法
|
||||
### 模拟 getters 和 setters
|
||||
|
||||
```js
|
||||
const spy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
||||
expect(console.log.mock.calls).toEqual([['dope'], ['nope']])
|
||||
spy.mockRestore()
|
||||
```
|
||||
|
||||
```js
|
||||
const spy = jest.spyOn(ajax, 'request').mockImplementation(() => Promise.resolve({ success: true }))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.mockRestore()
|
||||
const getTitle = jest.fn(() => 'pizza')
|
||||
const setTitle = jest.fn()
|
||||
const location = {}
|
||||
Object.defineProperty(location, 'title', {
|
||||
get: getTitle,
|
||||
set: setTitle,
|
||||
})
|
||||
```
|
||||
|
||||
### 模拟 getter 和 setter (Jest 22.1.0+)
|
||||
@ -508,8 +708,9 @@ const setTitle = jest
|
||||
jest.useFakeTimers()
|
||||
test('kill the time', () => {
|
||||
const callback = jest.fn()
|
||||
// 运行一些使用 setTimeout 或 setInterval 的代码
|
||||
const actual = someFunctionThatUseTimers(callback)
|
||||
// 运行使用 setTimeout或setInterval 的代码
|
||||
const actual
|
||||
= someFunctionThatUseTimers(callback)
|
||||
// 快进直到所有定时器都执行完毕
|
||||
jest.runAllTimers()
|
||||
// 同步检查结果
|
||||
@ -524,8 +725,9 @@ test('kill the time', () => {
|
||||
jest.useFakeTimers()
|
||||
test('kill the time', () => {
|
||||
const callback = jest.fn()
|
||||
// 运行一些使用 setTimeout 或 setInterval 的代码
|
||||
const actual = someFunctionThatUseTimers(callback)
|
||||
// 运行使用 setTimeout或setInterval 的代码
|
||||
const actual
|
||||
= someFunctionThatUseTimers(callback)
|
||||
// 快进 250 毫秒
|
||||
jest.advanceTimersByTime(250)
|
||||
// 同步检查结果
|
||||
@ -533,20 +735,29 @@ test('kill the time', () => {
|
||||
})
|
||||
```
|
||||
|
||||
对于特殊情况,请使用 [jest.runOnlyPendingTimers()](https://jestjs.io/docs/en/timer-mocks#run-pending-timers)。
|
||||
> 对于特殊情况,请使用 [jest.runOnlyPendingTimers()](https://jestjs.io/docs/en/timer-mocks#run-pending-timers)。
|
||||
|
||||
**注意:** 您应该在测试用例中调用 `jest.useFakeTimers()` 以使用其他假计时器方法。
|
||||
|
||||
### 模拟 getters 和 setters
|
||||
### 模拟对象方法
|
||||
|
||||
```js
|
||||
const getTitle = jest.fn(() => 'pizza')
|
||||
const setTitle = jest.fn()
|
||||
const location = {}
|
||||
Object.defineProperty(location, 'title', {
|
||||
get: getTitle,
|
||||
set: setTitle,
|
||||
})
|
||||
const spy = jest.spyOn(console, 'log')
|
||||
.mockImplementation(() => {})
|
||||
|
||||
expect(console.log.mock.calls)
|
||||
.toEqual([['dope'], ['nope']])
|
||||
spy.mockRestore()
|
||||
```
|
||||
|
||||
```js
|
||||
const spy = jest.spyOn(ajax, 'request')
|
||||
.mockImplementation(
|
||||
() => Promise.resolve({success: true})
|
||||
)
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
spy.mockRestore()
|
||||
```
|
||||
|
||||
### 清除和恢复模拟
|
||||
@ -558,8 +769,10 @@ Object.defineProperty(location, 'title', {
|
||||
// 清除模拟使用日期
|
||||
// (fn.mock.calls、fn.mock.instances)
|
||||
fn.mockClear()
|
||||
|
||||
// 清除并删除任何模拟的返回值或实现
|
||||
fn.mockReset()
|
||||
|
||||
// 重置并恢复初始实现
|
||||
fn.mockRestore()
|
||||
```
|
||||
|
@ -42,7 +42,7 @@ Header 2
|
||||
```
|
||||
|
||||
### 无序列表
|
||||
<!--rehype:wrap-style=grid-row: span 2/span 2;-->
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
```markdown
|
||||
* Item 1
|
||||
@ -64,7 +64,7 @@ Header 2
|
||||
+ Item 1
|
||||
+ Item 2
|
||||
```
|
||||
或者
|
||||
或者**任务**列表
|
||||
|
||||
```markdown
|
||||
- [ ] Checkbox off
|
||||
@ -80,41 +80,27 @@ Header 2
|
||||
b. item 3b
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 链接
|
||||
|
||||
```markdown
|
||||
[link](http://google.com)
|
||||
```
|
||||
|
||||
```markdown
|
||||
[link][google]
|
||||
[google]: http://google.com
|
||||
```
|
||||
|
||||
```markdown
|
||||
<http://google.com>
|
||||
```
|
||||
|
||||
### 强调
|
||||
|
||||
```markdown
|
||||
*斜体*
|
||||
_斜体_
|
||||
```
|
||||
*斜体* _斜体_ **粗体** __粗体__
|
||||
|
||||
```markdown
|
||||
**粗体**
|
||||
__粗体__
|
||||
```
|
||||
|
||||
```markdown
|
||||
`内联代码`
|
||||
~~删除~~
|
||||
`内联代码` ~~删除~~
|
||||
```
|
||||
|
||||
### 水平线
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
连字符
|
||||
|
||||
@ -134,9 +120,15 @@ __粗体__
|
||||
___
|
||||
```
|
||||
|
||||
### 换行
|
||||
|
||||
```markdown
|
||||
在当前行的结尾加 2 个空格··
|
||||
这行就会新起一行\
|
||||
反斜杠也可以换行
|
||||
```
|
||||
|
||||
|
||||
尾部添加两个空格,或者添加 `\` 反斜杠
|
||||
|
||||
### 代码
|
||||
|
||||
@ -165,33 +157,49 @@ console.log("This is a block code")
|
||||
```
|
||||
|
||||
### 表格
|
||||
<!--rehype:wrap-style=grid-column: span 2/span 2;-->
|
||||
|
||||
```markdown
|
||||
| 左栏 | 中间栏 | 右栏 |
|
||||
|:------------|:-------------:|-------------:|
|
||||
| 单元格 1 | 居中 | $1600 |
|
||||
| 单元格 2 | 单元格 3 | $12 |
|
||||
| 左栏 | 中间栏 | 右栏 |
|
||||
| ----------| ------------ | --------- |
|
||||
| 单元格 1 | 居中 | $1600 |
|
||||
| 单元格 2 | 单元格 3 | $12 |
|
||||
```
|
||||
|
||||
简单的风格
|
||||
|
||||
```markdown
|
||||
左栏 | 中间栏 | 右栏
|
||||
:----------:|:-------------:|:-----------:
|
||||
单元格 1 | 居中 | $1600
|
||||
单元格 2 | 单元格 3 | $12
|
||||
左栏 | 中间栏 | 右栏
|
||||
:-------: | :-------:|:-------:
|
||||
单元格 1 | 居中 | $1600
|
||||
单元格 2 | 单元格 3 | $12
|
||||
```
|
||||
|
||||
Markdown 表格生成器:[tableconvert.com](https://tableconvert.com/)
|
||||
|
||||
### 图片
|
||||
<!--rehype:wrap-style=grid-column: span 2/span 2;-->
|
||||
### 脚注 (Footnotes)
|
||||
|
||||
```markdown
|
||||

|
||||
这是一个简单的脚注[^1]。
|
||||
|
||||

|
||||
一个脚注也可以有多行[^2]。
|
||||
|
||||
你也可以使用文字,更贴合你的写作风格[^note]。
|
||||
|
||||
[^1]:我的参考。
|
||||
[^2]:每个新行都应以 2 个空格为前缀。
|
||||
这允许你有一个多行的脚注。
|
||||
[^note]:
|
||||
推荐使用数字命名脚注,但文本更容易识别和链接。
|
||||
脚注使用了不同的语法,使用 4 个空格作为新行。
|
||||
```
|
||||
|
||||
### 图片
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```markdown
|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
#### 带链接的图片
|
||||
@ -199,19 +207,19 @@ Markdown 表格生成器:[tableconvert.com](https://tableconvert.com/)
|
||||
```markdown
|
||||
[](https://github.com/)
|
||||
|
||||
[](link_url)
|
||||
[](link_url)
|
||||
```
|
||||
|
||||
#### 参考风格
|
||||
|
||||
```markdown
|
||||
![alt text][logo]
|
||||
![替代文字][logo]
|
||||
|
||||
[logo]: /images/logo.png "Logo Title"
|
||||
```
|
||||
|
||||
|
||||
### 反斜杠转义
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
| 字符 | 转义 | 描述 |
|
||||
|------------|--------|-------------|
|
||||
@ -226,4 +234,16 @@ Markdown 表格生成器:[tableconvert.com](https://tableconvert.com/)
|
||||
| \+ | \\\+ | plus sign 加号 |
|
||||
| \- | \\\- | minus sign \(hyphen\) 减号(连字符) |
|
||||
| \. | \\\. | dot 点 |
|
||||
| \! | \\\! | exclamation mark 感叹号 |
|
||||
| \! | \\\! | exclamation mark 感叹号 |
|
||||
|
||||
### 行内 HTML 元素
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```html
|
||||
目前只支持部分段内 HTML 元素效果,包括 <kdb>, <b>, <i>, <em>, <sup>, <sub>, <br>
|
||||
```
|
||||
|
||||
另见
|
||||
----
|
||||
|
||||
- [GitHub 风格的 Markdown 规范](https://github.github.com/gfm/) _(github.com)_
|
870
docs/nginx.md
Normal file
870
docs/nginx.md
Normal file
@ -0,0 +1,870 @@
|
||||
NGINX 备忘清单
|
||||
===
|
||||
|
||||
这个 nginx 快速参考备忘单显示了它的常用命和配置使用清单。
|
||||
|
||||
入门
|
||||
----
|
||||
|
||||
### 服务管理
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```bash
|
||||
sudo systemctl status nginx # nginx当前状态
|
||||
sudo systemctl reload nginx # 重新加载 nginx
|
||||
sudo systemctl restart nginx # 重启nginx
|
||||
|
||||
sudo nginx -t # 检查语法
|
||||
nginx # 启动
|
||||
nginx -s reload # 重启
|
||||
nginx -s stop # 关闭进程
|
||||
nginx -s quit # 平滑关闭nginx
|
||||
nginx -V # 查看nginx的安装状态,
|
||||
```
|
||||
|
||||
### Docker 安装
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```bash
|
||||
docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx
|
||||
```
|
||||
|
||||
### 简单代理
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
```
|
||||
|
||||
### 全局变量
|
||||
<!--rehype:wrap-class=col-span-2 row-span-4-->
|
||||
|
||||
| 变量 | 说明
|
||||
:- | :-
|
||||
`$args` | 这个变量等于请求行中的参数,同 `$query_string`
|
||||
`$remote_port` | 客户端的端口
|
||||
`$content_length` | 请求头中的 `Content-length` 字段
|
||||
`$remote_user` | 已经经过 `Auth Basic Module` 验证的用户名
|
||||
`$content_type` | 请求头中的 `Content-Type` 字段
|
||||
`$request_filename` | 当前请求的文件路径,由 `root` 或alias指令与URI请求生成
|
||||
`$document_root` | 当前请求在 `root` 指令中指定的值
|
||||
`$scheme` | HTTP方法(如http,https)
|
||||
`$host` | 请求主机头字段,否则为服务器名称
|
||||
`$hostname` | 主机名
|
||||
`$http_user_agent` | 客户端`agent`信息
|
||||
`$http_cookie` | 客户端`cookie`信息
|
||||
`$server_protocol` | 请求使用的协议,通常是`HTTP/1.0`或`HTTP/1.1`
|
||||
`$server_addr` | 服务器地址,在完成一次系统调用后可以确定这个值
|
||||
`$server_name` | 服务器名称
|
||||
`$server_port` | 请求到达服务器的端口号
|
||||
`$limit_rate` | 这个变量可以限制连接速率
|
||||
`$request_method` | 客户端请求的动作,如 GET/POST
|
||||
`$request_uri` | 包含请求参数的原始URI,不包含主机名,如:`/foo/bar.php?arg=baz`
|
||||
`$remote_addr` | 客户端的IP地址
|
||||
`$uri` | 不带请求参数的当前URI,`$uri`不包含主机名,如 `/foo/bar.html`
|
||||
`$document_uri` | 与 `$uri` 相同
|
||||
`$nginx_version` | `nginx` 版本
|
||||
|
||||
更多全局变量[查看官方文档](https://nginx.org/en/docs/varindex.html)
|
||||
|
||||
### 监听端口
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80; # 标准 HTTP 协议
|
||||
listen 443 ssl; # 标准 HTTPS 协议
|
||||
listen 443 ssl http2; # 对于 http2
|
||||
listen [::]:80; # 使用 IPv6 在 80 上收听
|
||||
# 仅收听使用 IPv6
|
||||
listen [::]:80 ipv6only=on;
|
||||
}
|
||||
```
|
||||
|
||||
### 域名 (server_name)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
# 监听 example.com
|
||||
server_name example.com;
|
||||
# 监听多个域
|
||||
server_name example.com www.example.com;
|
||||
# 监听所有子域
|
||||
server_name *.example.com;
|
||||
# 监听所有顶级域
|
||||
server_name example.*;
|
||||
# 监听未指定的主机名(监听 IP 地址本身)
|
||||
server_name "";
|
||||
}
|
||||
```
|
||||
|
||||
### 负载均衡(简单实例)
|
||||
|
||||
```nginx
|
||||
upstream node_js {
|
||||
server 0.0.0.0:3000;
|
||||
server 0.0.0.0:4000;
|
||||
server 127.155.142.421;
|
||||
}
|
||||
```
|
||||
|
||||
### 负载均衡(权重)
|
||||
|
||||
```nginx
|
||||
upstream test {
|
||||
server localhost:8080 weight=9;
|
||||
server localhost:8081 weight=1;
|
||||
}
|
||||
```
|
||||
|
||||
### upstream ip_hash
|
||||
|
||||
```nginx {2}
|
||||
upstream test {
|
||||
ip_hash;
|
||||
server localhost:8080;
|
||||
server localhost:8081;
|
||||
}
|
||||
```
|
||||
|
||||
解决负载均衡 `session` 的问题
|
||||
|
||||
### upstream fair
|
||||
|
||||
```nginx {2}
|
||||
upstream backend {
|
||||
fair;
|
||||
server localhost:8080;
|
||||
server localhost:8081;
|
||||
}
|
||||
```
|
||||
|
||||
响应时间短的优先分配
|
||||
|
||||
### server 可选参数
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`weight` | 访问权重数值越高,收到请求越多
|
||||
`fail_timeout` | 指定的时间内必须提供响应
|
||||
`max_fails` | 尝试失败服务器连接的最大次数
|
||||
`down` | 标记一个服务器不再接受任何请求
|
||||
`backup` | 有服务器宕机,标记的机器接收请求
|
||||
|
||||
配置示例
|
||||
|
||||
```nginx
|
||||
upstream test {
|
||||
server 127.0.0.1:83 weight=9; # 权重
|
||||
server 127.0.0.1:83 weight=1; # 权重
|
||||
# 失败超时时间
|
||||
server 127.0.0.1:83 max_fails=3;
|
||||
server 127.0.0.1:83 weight=3 down;
|
||||
}
|
||||
```
|
||||
|
||||
### upstream url_hash
|
||||
|
||||
```nginx {2,3}
|
||||
upstream backend {
|
||||
hash $request_uri;
|
||||
hash_method crc32;
|
||||
server localhost:8080;
|
||||
server localhost:8081;
|
||||
}
|
||||
```
|
||||
|
||||
按访问url的hash结果来分配请求
|
||||
|
||||
### upstream keepalive
|
||||
|
||||
```nginx {4}
|
||||
upstream memcached_backend {
|
||||
server 127.0.0.1:11211;
|
||||
server 10.0.0.2:11211;
|
||||
keepalive 32;
|
||||
}
|
||||
```
|
||||
|
||||
激活缓存以连接到上游服务器
|
||||
|
||||
### 子文件夹中的代理
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx {1,2}
|
||||
location /folder/ { # / 很重要!
|
||||
proxy_pass http://127.0.0.1:3000/; # / 很重要!
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
```
|
||||
|
||||
### 反向代理
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
#### 基础
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://0.0.0.0:3000;
|
||||
# 其中 0.0.0.0:3000 是绑定在
|
||||
# 0.0.0.0端口3000 列表上的 Node.js 服务器
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 基础 + (upstream)
|
||||
|
||||
```nginx
|
||||
upstream node_js {
|
||||
server 0.0.0.0:3000;
|
||||
# 其中 0.0.0.0:3000 是绑定在
|
||||
# 0.0.0.0端口3000 列表上的 Node.js 服务器
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://node_js;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 升级连接(适用于支持 WebSockets 的应用程序)
|
||||
|
||||
```nginx
|
||||
upstream node_js {
|
||||
server 0.0.0.0:3000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://node_js;
|
||||
proxy_redirect off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
适用于 Node.js、Streamlit、Jupyter 等
|
||||
|
||||
### 静态资源(传统 Web 服务器)
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
root /path/to/website;
|
||||
# root /www/data/ 示例,如果里面没有'root',它将寻找 /www/data/index.html
|
||||
location / {
|
||||
}
|
||||
location /images/ { # 如果里面没有“root”,它将寻找 /www/data/images/index.html
|
||||
}
|
||||
location /videos/ { # 由于里面有“root”,它会寻找 /www/media/videos/index.html
|
||||
root /www/media;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HTTPS 协议
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
大多数 SSL 选项取决于您的应用程序做什么或需要什么
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name example.com;
|
||||
ssl on;
|
||||
|
||||
ssl_certificate /path/to/cert.pem;
|
||||
ssl_certificate_key /path/to/privkey.pem;
|
||||
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /path/to/fullchain.pem;
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
}
|
||||
```
|
||||
|
||||
您可以使用 Let's Encrypt 轻松保护您的网站/应用程序。去 [lets-encrypt](https://certbot.eff.org/lets-encrypt/ubuntuxenial-nginx.html) 获取更多信息
|
||||
|
||||
|
||||
### 重定向(301永久)
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
将 www.example.com 重定向到 example.com
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name www.example.com;
|
||||
return 301 http://example.com$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
将 http 重定向到 https
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
return 301 https://example.com$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
### 重定向(302临时)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name yourdomain.com;
|
||||
return 302 http://otherdomain.com;
|
||||
}
|
||||
```
|
||||
|
||||
### 永久重定向到 HTTPS 安全域
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name yourdomain.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
### 重定向参数
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`permanent` | 永久性重定向。日志中的状态码为 `301`
|
||||
`redirect` | 临时重定向。日志中的状态码为 `302`
|
||||
|
||||
### HTTP 请求端真实的IP
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
示例
|
||||
----
|
||||
<!--rehype:body-class=cols-6-->
|
||||
|
||||
### websocket 的代理 keepalive
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
```nginx
|
||||
# Upstreams
|
||||
upstream backend {
|
||||
server 127.0.0.1:3000;
|
||||
keepalive 5;
|
||||
}
|
||||
# HTTP Server
|
||||
server {
|
||||
server_name your_hostname.com;
|
||||
error_log /var/log/nginx/rocketchat.access.log;
|
||||
location / {
|
||||
proxy_pass http://backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forward-Proto http;
|
||||
proxy_set_header X-Nginx-Proxy true;
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
### Apache 的反向代理
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
server_name domain.tld;
|
||||
|
||||
access_log /log/domain.tld.access.log;
|
||||
error_log /log/domain.tld.error.log;
|
||||
root /var/www/domain.tld/htdocs;
|
||||
|
||||
# 将请求传递给 Apache 后端
|
||||
location / {
|
||||
proxy_pass http://backend;
|
||||
}
|
||||
# 使用后备处理静态文件
|
||||
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|ttf|m4a|mp4|ttf|rss|atom|jpe?g|gif|cur|heic|png|tiff|ico|zip|webm|mp3|aac|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf|webp)$ {
|
||||
add_header "Access-Control-Allow-Origin" "*";
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
expires max;
|
||||
try_files $uri @fallback;
|
||||
}
|
||||
# 如果找不到文件,则回退以将请求传递给 Apache
|
||||
location @fallback {
|
||||
proxy_pass http://backend;
|
||||
}
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
### Gitlab 的反向代理
|
||||
<!--rehype:wrap-class=col-span-4 row-span-3-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
#侦听的80端口
|
||||
listen 80;
|
||||
server_name git.example.cn;
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
# 以下是一些反向代理的配置可删除
|
||||
proxy_redirect off;
|
||||
# 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
|
||||
proxy_set_header Host $host;
|
||||
client_max_body_size 10m; # 允许客户端请求的最大单文件字节数
|
||||
client_body_buffer_size 128k; # 缓冲区代理缓冲用户端请求的最大字节数
|
||||
proxy_connect_timeout 300; # nginx跟后端服务器连接超时时间(代理连接超时)
|
||||
proxy_send_timeout 300; # 后端服务器数据回传时间(代理发送超时)
|
||||
proxy_read_timeout 300; # 连接成功后,后端服务器响应时间(代理接收超时)
|
||||
# 设置代理服务器(nginx)保存用户头信息的缓冲区大小
|
||||
proxy_buffer_size 4k;
|
||||
# proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
|
||||
proxy_buffers 4 32k;
|
||||
# 高负荷下缓冲大小(proxy_buffers*2)
|
||||
proxy_busy_buffers_size 64k;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 重定向整个网站
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
server_name old-site.com;
|
||||
return 301 $scheme://new-site.com$request_uri;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
### 重定向单页
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
location = /oldpage.html {
|
||||
return 301 http://example.org/newpage.html;
|
||||
}
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
### 重定向整个子路径
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
location /old-site {
|
||||
rewrite ^/old-site/(.*) http://example.org/new-site/$1 permanent;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
### 负载均衡
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
```nginx
|
||||
upstream example {
|
||||
ip_hash;
|
||||
# upstream的负载均衡,weight是权重,可以根据机器配置定义权重。
|
||||
# weigth参数表示权值,权值越高被分配到的几率越大。
|
||||
server 192.168.122.11:8081 ;
|
||||
server 127.0.0.1:82 weight=3;
|
||||
server 127.0.0.1:83 weight=3 down;
|
||||
server 127.0.0.1:84 weight=3; max_fails=3 fail_timeout=20s;
|
||||
server 127.0.0.1:85 weight=4;;
|
||||
keepalive 32;
|
||||
}
|
||||
server {
|
||||
#侦听的80端口
|
||||
listen 80;
|
||||
server_name git.example.cn;
|
||||
location / {
|
||||
# 在这里设置一个代理,和 upstream 的名字一样
|
||||
proxy_pass http://example;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 内容缓存
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
允许浏览器基本上永久地缓存静态内容。 Nginx 将为您设置 Expires 和 Cache-Control 头信息
|
||||
|
||||
```nginx {3}
|
||||
location /static {
|
||||
root /data;
|
||||
expires max;
|
||||
}
|
||||
```
|
||||
|
||||
如果要求浏览器永远不会缓存响应(例如用于跟踪请求),请使用 `-1`
|
||||
|
||||
```nginx {3}
|
||||
location = /empty.gif {
|
||||
empty_gif;
|
||||
expires -1;
|
||||
}
|
||||
```
|
||||
|
||||
### 跨域问题
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.xxx.com;
|
||||
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET,POST,HEAD';
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 重定向 URI 来解决跨域问题
|
||||
<!--rehype:wrap-class=col-span-3 row-span-2-->
|
||||
|
||||
```nginx
|
||||
upstream test {
|
||||
server 127.0.0.1:8080;
|
||||
server localhost:8081;
|
||||
}
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.xxx.com;
|
||||
location / {
|
||||
root html; # 去请求../html文件夹里的文件
|
||||
index index.html index.htm; # 首页响应地址
|
||||
}
|
||||
# 用于拦截请求,匹配任何以 /api/开头的地址,
|
||||
# 匹配符合以后,停止往下搜索正则。
|
||||
location ^~/api/{
|
||||
# 代表重写拦截进来的请求,并且只能对域名后边的除去传递的参数外的字符串起作用
|
||||
# 例如www.a.com/api/msg?meth=1&par=2重写,只对/api/msg重写。
|
||||
# rewrite后面的参数是一个简单的正则 ^/api/(.*)$,
|
||||
# $1代表正则中的第一个(),$2代表第二个()的值,以此类推。
|
||||
rewrite ^/api/(.*)$ /$1 break;
|
||||
|
||||
# 把请求代理到其他主机
|
||||
# 其中 http://www.b.com/ 写法和 http://www.b.com写法的区别如下
|
||||
# 如果你的请求地址是他 http://server/html/test.jsp
|
||||
# 配置一: http://www.b.com/ 后面有“/”
|
||||
# 将反向代理成 http://www.b.com/html/test.jsp 访问
|
||||
# 配置一: http://www.b.com 后面没有有“/”
|
||||
# 将反向代理成 http://www.b.com/test.jsp 访问
|
||||
proxy_pass http://test;
|
||||
|
||||
# 如果 proxy_pass URL 是 http://a.xx.com/platform/ 这种情况
|
||||
# proxy_cookie_path应该设置成 /platform/ / (注意两个斜杠之间有空格)。
|
||||
proxy_cookie_path /platfrom/ /;
|
||||
|
||||
# 设置 Cookie 头通过
|
||||
proxy_pass_header Set-Cookie;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 跳转到带 www 的域上面
|
||||
<!--rehype:wrap-class=col-span-3-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
# 配置正常的带www的域名
|
||||
server_name www.wangchujiang.com;
|
||||
root /home/www/wabg/download;
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html =404;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
# 将不带 www 的 wangchujiang.com
|
||||
# 永久性重定向到 https://www.wangchujiang.com
|
||||
server_name wangchujiang.com;
|
||||
rewrite ^(.*) https://www.wangchujiang.com$1 permanent;
|
||||
}
|
||||
```
|
||||
|
||||
### 代理转发
|
||||
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
||||
|
||||
```nginx
|
||||
upstream server-api {
|
||||
# api 代理服务地址
|
||||
server 127.0.0.1:3110;
|
||||
}
|
||||
upstream server-resource {
|
||||
# 静态资源 代理服务地址
|
||||
server 127.0.0.1:3120;
|
||||
}
|
||||
server {
|
||||
listen 3111;
|
||||
server_name localhost; # 这里指定域名
|
||||
root /home/www/server-statics;
|
||||
# 匹配 api 路由的反向代理到API服务
|
||||
location ^~/api/ {
|
||||
rewrite ^/(.*)$ /$1 break;
|
||||
proxy_pass http://server-api;
|
||||
}
|
||||
# 假设这里验证码也在API服务中
|
||||
location ^~/captcha {
|
||||
rewrite ^/(.*)$ /$1 break;
|
||||
proxy_pass http://server-api;
|
||||
}
|
||||
# 假设你的图片资源全部在另外一个服务上面
|
||||
location ^~/img/ {
|
||||
rewrite ^/(.*)$ /$1 break;
|
||||
proxy_pass http://server-resource;
|
||||
}
|
||||
# 路由在前端,后端没有真实路由,
|
||||
# 路由不存在的 404 状态的页面返回 /index.html
|
||||
# 使用场景,用在 React/Vue项目没有真实路由
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html =404;
|
||||
# 空格很重要 ^
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 屏蔽 IP
|
||||
<!--rehype:wrap-class=col-span-4-->
|
||||
|
||||
可以放到 `http`, `server`, `location`, `limit_except` 语句块
|
||||
|
||||
```nginx
|
||||
include blockip.conf;
|
||||
```
|
||||
|
||||
在 `blockip.conf` 里面输入内容,如:
|
||||
|
||||
```nginx
|
||||
deny 165.91.122.67;
|
||||
|
||||
deny IP; # 屏蔽单个 ip 访问
|
||||
allow IP; # 允许单个 ip 访问
|
||||
deny all; # 屏蔽所有 ip 访问
|
||||
allow all; # 允许所有 ip 访问
|
||||
deny 123.0.0.0/8; # 屏蔽整个段即从 123.0.0.1 到 123.255.255.254 访问的命令
|
||||
deny 124.45.0.0/16; # 屏蔽IP段即从 123.45.0.1 到 123.45.255.254 访问的命令
|
||||
deny 123.45.6.0/24; # 屏蔽IP段即从 123.45.6.1 到 123.45.6.254 访问的命令
|
||||
|
||||
# 如果你想实现这样的应用,除了几个IP外,其他全部拒绝
|
||||
allow 1.1.1.1;
|
||||
allow 1.1.1.2;
|
||||
deny all;
|
||||
```
|
||||
|
||||
### 强制将 http 重定向到 https
|
||||
<!--rehype:wrap-class=col-span-4-->
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name example.com;
|
||||
rewrite ^ https://$http_host$request_uri? permanent; # 强制将 http 重定向到 https
|
||||
# 在错误页面和“服务器”响应头字段中启用或禁用发射nginx版本。 防止黑客利用版本漏洞攻击
|
||||
server_tokens off;
|
||||
}
|
||||
```
|
||||
|
||||
### 代理转发连接替换
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
location ^~/api/upload {
|
||||
rewrite ^/(.*)$ /wfs/v1/upload break;
|
||||
proxy_pass http://wfs-api;
|
||||
}
|
||||
```
|
||||
|
||||
将地址 `/api/upload` 替换为 `/wfs/v1/upload`
|
||||
|
||||
### 爬虫 User-Agent 过滤
|
||||
<!--rehype:wrap-class=col-span-4-->
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
if ($http_user_agent ~* "python|curl|java|wget|httpclient|okhttp") {
|
||||
return 503;
|
||||
}
|
||||
# 正常处理
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
### 图片防盗链
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
location ~* \.(gif|jpg|png|swf|flv)$ {
|
||||
root html;
|
||||
|
||||
valid_referers none blocked *.nginx.com;
|
||||
|
||||
if ($invalid_referer) {
|
||||
rewrite ^/ www.nginx.cn;
|
||||
# return 404;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 虚拟目录配置
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
location /img/ {
|
||||
alias /var/www/image/;
|
||||
}
|
||||
# 访问 /img/ 目录里面的文件时,
|
||||
# 会自动去 /var/www/image/ 目录找文件
|
||||
location /img/ {
|
||||
root /var/www/image;
|
||||
}
|
||||
# 访问 /img/ 目录下的文件时,
|
||||
# 会去 /var/www/image/img/ 目录下找文件
|
||||
```
|
||||
|
||||
### 屏蔽文件目录
|
||||
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
||||
|
||||
通用备份和归档文件
|
||||
|
||||
```nginx
|
||||
location ~* "\.(old|orig|original|php#|php~|php_bak|save|swo|aspx?|tpl|sh|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rdf)$" {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
拒绝访问 `.git` 和 `.svn` 目录
|
||||
|
||||
```nginx
|
||||
location ~ (.git|.svn) {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
拒绝访问隐藏文件和目录
|
||||
|
||||
```nginx
|
||||
location ~ /\.(?!well-known\/) {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
|
||||
### 防盗图配置
|
||||
<!--rehype:wrap-class=col-span-4-->
|
||||
|
||||
```nginx
|
||||
location ~ \/public\/(css|js|img)\/.*\.(js|css|gif|jpg|jpeg|png|bmp|swf) {
|
||||
valid_referers none blocked *.jslite.io;
|
||||
if ($invalid_referer) {
|
||||
rewrite ^/ http://wangchujiang.com/piratesp.png;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 阻止常见攻击
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
#### base64编码的网址
|
||||
|
||||
```nginx
|
||||
location ~* "(base64_encode)(.*)(\()" {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
|
||||
#### javascript eval() url
|
||||
|
||||
```nginx
|
||||
location ~* "(eval\()" {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
|
||||
### Gzip 配置
|
||||
<!--rehype:wrap-class=col-span-4 row-span-2-->
|
||||
|
||||
```nginx
|
||||
gzip on;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_comp_level 6;
|
||||
gzip_http_version 1.1;
|
||||
gzip_min_length 256;
|
||||
gzip_proxied any;
|
||||
gzip_vary on;
|
||||
gzip_types
|
||||
text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml
|
||||
text/javascript application/javascript application/x-javascript
|
||||
text/x-json application/json application/x-web-app-manifest+json
|
||||
text/css text/plain text/x-component
|
||||
font/opentype application/x-font-ttf application/vnd.ms-fontobject
|
||||
image/x-icon;
|
||||
gzip_disable "msie6";
|
||||
```
|
||||
|
||||
### 使网站不可索引
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```nginx
|
||||
add_header X-Robots-Tag "noindex";
|
||||
|
||||
location = /robots.txt {
|
||||
return 200 "User-agent: *\nDisallow: /\n";
|
||||
}
|
||||
```
|
||||
|
||||
另见
|
||||
---
|
||||
|
||||
- [Nginx 安装维护入门学习笔记](https://jaywcjlove.github.io/nginx-tutorial) _(jaywcjlove.github.io)_
|
||||
- [](https://virtubox.github.io/advanced-nginx-cheatsheet/) _(virtubox.github.io)_
|
10
docs/npm.md
10
docs/npm.md
@ -138,6 +138,16 @@ npm unpublish <package-name>@<version>
|
||||
|
||||
注意:如果您取消发布整个包,则必须在 24 小时后才能发布该包的任何新版本。
|
||||
|
||||
### 发布包 npmjs.org
|
||||
|
||||
```bash
|
||||
npm publish
|
||||
# 第一次需要指定公开参数
|
||||
npm publish --access public
|
||||
```
|
||||
|
||||
发布公开包,到 npmjs.org
|
||||
|
||||
配置
|
||||
---
|
||||
|
||||
|
@ -101,7 +101,7 @@ https://registry.npmjs.org/[包名]/-/[包名]-[version].tgz
|
||||
|
||||
鼓励使用开源 [(OSI-approved)](https://opensource.org/licenses/alphabetical) 许可证,除非你有特别的原因不用它。 如果你开发的包是你工作的一部分,最好和公司讨论后再做决定。
|
||||
|
||||
**license字段必须是以下之一:**
|
||||
#### **license字段必须是以下之一**
|
||||
|
||||
- 如果你使用标准的许可证,需要一个有效地 [SPDX 许可证标识](https://spdx.org/licenses/)。
|
||||
- 如果你用多种标准许可证,需要有效的 [SPDX 许可证表达式2.0语法表达式](https://www.npmjs.com/package/spdx)。
|
||||
|
@ -1,7 +1,7 @@
|
||||
Quick Reference 备忘清单
|
||||
===
|
||||
|
||||
这是您可以在 Quick Reference 备忘单上使用的样式参考,快速参与贡献!
|
||||
这是您可以在 Quick Reference 备忘单上使用的样式参考,快速参与[贡献](https://github.com/jaywcjlove/reference/blob/main/CONTRIBUTING.md)!
|
||||
|
||||
入门
|
||||
---
|
||||
@ -51,8 +51,8 @@ HTML 存放在仓库根目录下的 `dist` 目录中,将 `dist/index.html` 静
|
||||
|
||||
#### 语法
|
||||
|
||||
`<!--rehype:` + `key=value` + `&` + `key=value` + `-->`
|
||||
`标识开始` + `参数` + `分隔符` + `参数` + `标识结束`
|
||||
`<!--rehype:` _+_ `key=value` _+_ **`&`** _+_ `key=value` _+_ `-->`
|
||||
`标识开始` + `参数` + `分隔符(&)` + `参数` + `标识结束`
|
||||
|
||||
#### 示例
|
||||
|
||||
@ -72,7 +72,6 @@ HTML 存放在仓库根目录下的 `dist` 目录中,将 `dist/index.html` 静
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
|
||||
#### 参数说明
|
||||
|
||||
类 | 说明
|
||||
@ -142,6 +141,8 @@ export const Student = (
|
||||
```jsx {1,4-5}
|
||||
```
|
||||
|
||||
代码行高亮可以和代码行号一起使用。
|
||||
|
||||
### Tooltips
|
||||
|
||||
[鼠标移动到上面有提示](https://github.com/jaywcjlove/reference) _Tooltips 的提示内容_<!--rehype:tooltips-->
|
||||
@ -180,11 +181,15 @@ export const Student = (
|
||||
### 代码行号
|
||||
|
||||
```jsx showLineNumbers
|
||||
export const Student = (
|
||||
<div className="Student"></div>
|
||||
);
|
||||
export const Student = <div>学生</div>;
|
||||
const school = <div>学校</div>;
|
||||
```
|
||||
|
||||
下面是 `Markdown` 代码示例
|
||||
|
||||
```markdown
|
||||
```jsx showLineNumbers
|
||||
```
|
||||
|
||||
### 内置类样式
|
||||
|
||||
@ -203,6 +208,7 @@ export const Student = (
|
||||
`<yel>` | <yel>黄色</yel>
|
||||
`<pur>` | <pur>紫色</pur>
|
||||
`<code>` 或 <code>\`\`</code> | <code>绿</code>`色`
|
||||
`<del>` 或 `~~删除~~` | <del>~~红色~~</del>
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
|
||||
@ -578,6 +584,25 @@ H2 部分
|
||||
|
||||
`<!--rehype:className=cols-4-->`
|
||||
|
||||
### 列表步骤
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
- **重命名为 new_name**
|
||||
```bash
|
||||
$ git branch -m <new_name>
|
||||
```
|
||||
- 推送和**重置**
|
||||
```bash
|
||||
$ git push origin -u <new_name>
|
||||
```
|
||||
- 删除远程分支
|
||||
```bash
|
||||
$ git push origin --delete <old>
|
||||
```
|
||||
<!--rehype:className=style-timeline-->
|
||||
|
||||
`<!--rehype:className=style-timeline-->`
|
||||
|
||||
### 没有标记
|
||||
|
||||
- Item 1
|
||||
@ -586,10 +611,22 @@ H2 部分
|
||||
- Item 4
|
||||
- Item 5
|
||||
- Item 6
|
||||
- Item 7
|
||||
- Item 8
|
||||
- Item 9
|
||||
<!--rehype:className=cols-3 style-none-->
|
||||
|
||||
`<!--rehype:className=cols-3 style-none-->`
|
||||
|
||||
### 圆圈标记
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 3
|
||||
<!--rehype:className=style-round-->
|
||||
|
||||
`<!--rehype:className=style-round-->`
|
||||
|
||||
H2 部分 - 5列效果展示
|
||||
---
|
||||
<!--rehype:body-class=cols-5-->
|
||||
|
322
docs/react.md
322
docs/react.md
@ -12,9 +12,9 @@ React 备忘清单
|
||||
React 是一个用于构建用户界面的 JavaScript 库。
|
||||
|
||||
- [React 官方文档](https://reactjs.org/) _(reactjs.org)_
|
||||
- [Styled Components 备忘清单](./styled-components.md) _(jaywcjlove.github.io)_
|
||||
|
||||
```js
|
||||
import React from 'react'
|
||||
import {createRoot} from 'react-dom/client'
|
||||
import App from './App'
|
||||
```
|
||||
@ -46,14 +46,15 @@ import ReactDOM from 'react-dom'
|
||||
export class Hello extends Component {
|
||||
...
|
||||
}
|
||||
export default function World() {
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
使用 `export` 或者 `export default` 导出 `Hello` 组件
|
||||
使用 `export` 导出 **`Hello`**,`export default` 导出 **`World`** 组件
|
||||
|
||||
```jsx
|
||||
import { Hello } from './hello.js';
|
||||
|
||||
const Example = <Hello />;
|
||||
import World, { Hello } from './hello.js';
|
||||
```
|
||||
|
||||
使用 `import` 导入 `Hello` 组件,在示例中使用。
|
||||
@ -327,7 +328,7 @@ const Student = () => (
|
||||
|
||||
从 `v16.2.0` 开始 `Fragment` 可用于返回多个子节点,而无需向 DOM 添加额外的包装节点。或者使用 `<></>` 效果是一样的。
|
||||
|
||||
```jsx
|
||||
```jsx {2,5}
|
||||
const Student = () => (
|
||||
<>
|
||||
<Avatar src="./demo.jpg" />
|
||||
@ -340,7 +341,7 @@ const Student = () => (
|
||||
|
||||
### 返回字符串
|
||||
|
||||
```jsx
|
||||
```jsx {2}
|
||||
render() {
|
||||
return 'Look ma, no spans!';
|
||||
}
|
||||
@ -1011,12 +1012,313 @@ Menu.Item = ({ children }) => (
|
||||
<Menu>
|
||||
```
|
||||
|
||||
生命周期
|
||||
---
|
||||
|
||||
Hooks
|
||||
---
|
||||
|
||||
### Hooks API 参考
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
#### 基础 Hook
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`useState` | 返回一个 `state`,更新 `state` 的函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usestate)
|
||||
`useEffect` | 可能有副作用代码的函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useeffect)
|
||||
`useContext` | 接收并返回该 `context` 的当前值 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usecontext)
|
||||
|
||||
#### 额外的 Hook
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`useReducer` | `useState` 的替代方案 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usestate)
|
||||
`useCallback` | 返回一个回调函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usecallback)
|
||||
`useMemo` | 返回一个 [memoized](https://en.wikipedia.org/wiki/Memoization) 值[#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usememo)
|
||||
`useRef` | 返回一个可变的 `ref` 对象 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useref)
|
||||
`useImperativeHandle` | 暴露给父组件的实例值 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useimperativehandle)
|
||||
`useLayoutEffect` | DOM 变更后同步调用函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#uselayouteffect)
|
||||
`useDebugValue` | 开发者工具中显示标签 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usedebugvalue)
|
||||
`useDeferredValue` | 接受并返回该值的新副本 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usedeferredvalue)
|
||||
`useTransition` | 过渡任务的等待状态 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usetransition)
|
||||
`useId` | 用于生成唯一 ID [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useid)
|
||||
|
||||
#### Library Hooks
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`useSyncExternalStore` | 读取和订阅外部数据源 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usesyncexternalstore)
|
||||
`useInsertionEffect` | DOM 突变之前 同步触发 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usesyncexternalstore)
|
||||
|
||||
### 函数式更新
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```jsx
|
||||
function Counter({ initialCount }) {
|
||||
const [count, setCount] = useState(initialCount);
|
||||
return (
|
||||
<>
|
||||
Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button>
|
||||
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
|
||||
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### useRef
|
||||
|
||||
```jsx
|
||||
function TextInputWithFocusButton() {
|
||||
const $input = useRef(null);
|
||||
const onButtonClick = () => {
|
||||
$input.current.focus();
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<input ref={$input} type="text" />
|
||||
<button onClick={onButtonClick}>
|
||||
聚焦输入
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
`current` 指向已挂载到 DOM 上的文本输入元素
|
||||
|
||||
### useImperativeHandle
|
||||
|
||||
```jsx
|
||||
function FancyInput(props, ref) {
|
||||
const inputRef = useRef();
|
||||
useImperativeHandle(ref, () => ({
|
||||
focus: () => {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
}));
|
||||
return <input ref={inputRef} />;
|
||||
}
|
||||
FancyInput = forwardRef(FancyInput);
|
||||
```
|
||||
|
||||
父组件使用
|
||||
|
||||
```jsx
|
||||
<FancyInput ref={inputRef} />
|
||||
inputRef.current.focus()
|
||||
```
|
||||
|
||||
### useEffect
|
||||
|
||||
```jsx
|
||||
useEffect(() => {
|
||||
const subs = props.source.subscribe();
|
||||
return () => {
|
||||
subs.unsubscribe();
|
||||
};
|
||||
}, [props.source]);
|
||||
```
|
||||
|
||||
### useCallback
|
||||
|
||||
```jsx
|
||||
const memoizedCallback = useCallback(
|
||||
() => {
|
||||
doSomething(a, b);
|
||||
},
|
||||
[a, b],
|
||||
);
|
||||
```
|
||||
|
||||
### useMemo
|
||||
|
||||
```jsx
|
||||
const memoizedValue = useMemo(
|
||||
() => {
|
||||
return computeExpensiveValue(a, b)
|
||||
},
|
||||
[a, b]
|
||||
);
|
||||
```
|
||||
|
||||
### useId
|
||||
|
||||
```jsx
|
||||
function Checkbox() {
|
||||
const id = useId();
|
||||
return (
|
||||
<>
|
||||
<label htmlFor={id}>
|
||||
你喜欢React吗?
|
||||
</label>
|
||||
<input id={id} type="checkbox" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
用于生成跨服务端和客户端稳定的唯一 `ID` 的同时避免 `hydration` 不匹配
|
||||
|
||||
### useDebugValue
|
||||
|
||||
```jsx
|
||||
function useFriendStatus(friendID) {
|
||||
const [
|
||||
isOnline, setIsOnline
|
||||
] = useState(null);
|
||||
// ...
|
||||
// 在开发者工具中的这个 Hook 旁边显示标签
|
||||
// e.g. "FriendStatus: Online"
|
||||
useDebugValue(
|
||||
isOnline ? 'Online' : 'Offline'
|
||||
);
|
||||
return isOnline;
|
||||
}
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
不推荐你向每个自定义 `Hook` 添加 `debug` 值
|
||||
|
||||
### componentDidMount & componentWillUnmount
|
||||
|
||||
```jsx
|
||||
useEffect(
|
||||
() => {
|
||||
// componentDidMount
|
||||
// 组件挂载时,可以在这里完成你的任务
|
||||
return () => {
|
||||
// componentWillUnmount
|
||||
// 卸载时执行,清除 effect
|
||||
};
|
||||
},
|
||||
[ ]
|
||||
);
|
||||
```
|
||||
|
||||
这是一个类似 `class` 组件中 `componentDidMount` & `componentWillUnmount` 两个生命周期函数的写法。
|
||||
|
||||
生命周期
|
||||
---
|
||||
<!--rehype:body-class=cols-2-->
|
||||
|
||||
### 挂载
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`constructor` _(props)_ | 渲染前 [#](https://zh-hans.reactjs.org/docs/react-component.html#constructor)
|
||||
`static getDerivedStateFromProps()` | 调用 `render` 方法之前调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
||||
`render()` | `class` 组件中唯一必须实现的方法 [#](https://reactjs.org/docs/react-component.html#render)
|
||||
`componentDidMount()` | 在组件挂载后(插入 DOM 树中)立即调用 [#](https://reactjs.org/docs/react-component.html#componentdidmount)
|
||||
`UNSAFE_componentWillMount()` | 在挂载之前被调用,建议使用 `constructor()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillmount)
|
||||
|
||||
在 `constructor()` 上设置初始状态。在 `componentDidMount()` 上添加 DOM 事件处理程序、计时器(等),然后在 `componentWillUnmount()` 上删除它们。
|
||||
|
||||
### 卸载
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`componentWillUnmount()` | 在组件卸载及销毁之前直接调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentwillunmount)
|
||||
|
||||
### 过时 API
|
||||
|
||||
过时方法 | 新方法
|
||||
:- | -
|
||||
~~`componentWillMount()`~~ | `UNSAFE_componentWillMount()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillmount)
|
||||
~~`componentWillReceiveProps()`~~ | `UNSAFE_componentWillReceiveProps()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops)
|
||||
~~`componentWillUpdate()`~~ | `UNSAFE_componentWillUpdate()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillupdate)
|
||||
|
||||
17+ 之后不再支持,在 `17` 版本之后,只有新的 `UNSAFE_` 生命周期名称可以使用。
|
||||
|
||||
### 更新
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`static getDerivedStateFromProps(props, state)` | 调用 `render` 之前调用,在初始挂载及后续更新时都会被调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
||||
`shouldComponentUpdate(nextProps, nextState)` | 如果返回 `false`,则跳过 `render()` [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
||||
`render()` | 在不修改组件 `state` 的情况下,每次调用时都返回相同的结果 [#](https://zh-hans.reactjs.org/docs/react-component.html#render)
|
||||
`getSnapshotBeforeUpdate()` | 在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置) [#](https://zh-hans.reactjs.org/docs/react-component.html#getsnapshotbeforeupdate)
|
||||
`componentDidUpdate()` | 这里使用 `setState()`,但记得比较 `props`。首次渲染不会执行此方法 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentdidupdate)
|
||||
|
||||
### 错误处理
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
方法 | 描述
|
||||
:- | -
|
||||
`static getDerivedStateFromError(error)` | 后代组件抛出错误后被调用,它将抛出的错误作为参数,并返回一个值以更新 `state` [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromerror)
|
||||
`componentDidCatch(error, info)` | 在后代组件抛出错误后被调用,会在“提交”阶段被调用,因此允许执行副作用 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentdidcatch)
|
||||
|
||||
### render()
|
||||
|
||||
```jsx {2}
|
||||
class Welcome extends React.Component {
|
||||
render() {
|
||||
return <h1>Hello, {this.props.name}</h1>;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### constructor()
|
||||
|
||||
```jsx {1}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
// 不要在这里调用 this.setState()
|
||||
this.state = { counter: 0 };
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
}
|
||||
```
|
||||
|
||||
### static getDerivedStateFromError()
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```jsx {7,13}
|
||||
class ErrorBoundary extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error) {
|
||||
// 更新 state 使下一次渲染可以显降级 UI
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
// 你可以渲染任何自定义的降级 UI
|
||||
return <h1>Something went wrong.</h1>;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### componentDidUpdate()
|
||||
|
||||
```jsx {1}
|
||||
componentDidUpdate(prevProps) {
|
||||
// 典型用法(不要忘记比较 props):
|
||||
if (this.props.uid !== prevProps.uid) {
|
||||
this.fetchData(this.props.uid);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### getSnapshotBeforeUpdate()
|
||||
|
||||
```jsx
|
||||
getSnapshotBeforeUpdate(prevProps, prevState) {
|
||||
// 我们是否在 list 中添加新的 items ?
|
||||
// 捕获滚动位置以便我们稍后调整滚动位置。
|
||||
if (prevProps.list.length < this.props.list.length) {
|
||||
const list = this.listRef.current;
|
||||
return list.scrollHeight - list.scrollTop;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
PropTypes 属性类型检查
|
||||
---
|
||||
|
201
docs/regex.md
201
docs/regex.md
@ -65,7 +65,7 @@ RegEX 备忘清单
|
||||
- \$
|
||||
- \\
|
||||
- \?
|
||||
<!--rehype:className=cols-3-->
|
||||
<!--rehype:className=cols-3 style-none-->
|
||||
|
||||
使用 `\` 转义这些特殊字符
|
||||
|
||||
@ -175,6 +175,33 @@ RegEX 备忘清单
|
||||
`(?(?=...)yes\|no)` | 有条件的前瞻
|
||||
`(?(?<=...)yes\|no)` | 有条件的往后看
|
||||
|
||||
### 递归
|
||||
|
||||
:-|-
|
||||
:-|-
|
||||
`(?R)` | 递归整个模式
|
||||
`(?1)` | 递归第一个子模式
|
||||
`(?+1)` | 递归第一个相对子模式
|
||||
`(?&name)` | 递归子模式`name`
|
||||
`(?P=name)` | 匹配子模式`name`
|
||||
`(?P>name)` | 递归子模式`name`
|
||||
|
||||
### 标志/修饰符
|
||||
|
||||
:-|-
|
||||
:-|-
|
||||
`g` | 全部
|
||||
`m` | 多行
|
||||
`i` | 不区分大小写
|
||||
`x` | 忽略空格
|
||||
`s` | 单线
|
||||
`u` | 统一码
|
||||
`X` | 扩展
|
||||
`U` | 不贪心
|
||||
`A` | 锚
|
||||
`J` | 重复的组名
|
||||
`d` | 结果包含捕获组子字符串开始和结束的索引
|
||||
|
||||
### 零宽度断言
|
||||
|
||||
:-|-
|
||||
@ -190,34 +217,6 @@ RegEX 备忘清单
|
||||
|
||||
零宽度断言 允许您在主模式之前(向后看)或之后(lookahead)匹配一个组,而不会将其包含在结果中。
|
||||
|
||||
### 标志/修饰符
|
||||
|
||||
:-|-
|
||||
:-|-
|
||||
`g` | 全球的
|
||||
`m` | 多行
|
||||
`i` | 不区分大小写
|
||||
`x` | 忽略空格
|
||||
`s` | 单线
|
||||
`u` | 统一码
|
||||
`X` | 扩展
|
||||
`U` | 不贪心
|
||||
`A` | 锚
|
||||
`J` | 重复的组名
|
||||
|
||||
|
||||
### 递归
|
||||
|
||||
:-|-
|
||||
:-|-
|
||||
`(?R)` | 递归整个模式
|
||||
`(?1)` | 递归第一个子模式
|
||||
`(?+1)` | 递归第一个相对子模式
|
||||
`(?&name)` | 递归子模式`name`
|
||||
`(?P=name)` | 匹配子模式`name`
|
||||
`(?P>name)` | 递归子模式`name`
|
||||
|
||||
|
||||
### POSIX 字符类
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
@ -287,6 +286,27 @@ RegEX 备忘清单
|
||||
使用 `\` 搜索这些特殊字符:<br> `[ \ ^ $ . | ? * + ( ) { }`
|
||||
|
||||
|
||||
### 速记类
|
||||
|
||||
范例 | 说明
|
||||
:-|-
|
||||
`\w ` | “单词”字符 <br> _(字母、数字或下划线)_
|
||||
`\d ` | 数字
|
||||
`\s ` | 空格 <br> _(空格、制表符、vtab、换行符)_
|
||||
`\W, \D, or \S ` | 不是单词、数字或空格
|
||||
`[\D\S] ` | 表示不是数字或空格,两者都匹配
|
||||
`[^\d\s] ` | 禁止数字和空格
|
||||
|
||||
### 出现次数
|
||||
|
||||
范例 | 说明
|
||||
:-|-
|
||||
`colou?r` | 匹配 <yel>color</yel> 或 <yel>color</yel>
|
||||
`[BW]ill[ieamy's]*` | 匹配 <yel>Bill</yel>、<yel>Willy</yel>、<yel>William's</yel> 等。
|
||||
`[a-zA-Z]+` | 匹配 1 个或多个字母
|
||||
`\d{3}-\d{2}-\d{4}` | 匹配 SSN
|
||||
`[a-z]\w{1,7}` | 匹配 UW NetID
|
||||
|
||||
### 备择方案
|
||||
|
||||
范例 | 说明
|
||||
@ -309,28 +329,6 @@ RegEX 备忘清单
|
||||
|
||||
在 `[ ]` 中总是转义 `. \ ]` 有时是 `^ - .`
|
||||
|
||||
|
||||
### 速记类
|
||||
|
||||
范例 | 说明
|
||||
:-|-
|
||||
`\w ` | “单词”字符 <br> _(字母、数字或下划线)_
|
||||
`\d ` | 数字
|
||||
`\s ` | 空格 <br> _(空格、制表符、vtab、换行符)_
|
||||
`\W, \D, or \S ` | 不是单词、数字或空格
|
||||
`[\D\S] ` | 表示不是数字或空格,两者都匹配
|
||||
`[^\d\s] ` | 禁止数字和空格
|
||||
|
||||
### 出现次数
|
||||
|
||||
范例 | 说明
|
||||
:-|-
|
||||
`colou?r` | 匹配 <yel>color</yel> 或 <yel>color</yel>
|
||||
`[BW]ill[ieamy's]*` | 匹配 <yel>Bill</yel>、<yel>Willy</yel>、<yel>William's</yel> 等。
|
||||
`[a-zA-Z]+` | 匹配 1 个或多个字母
|
||||
`\d{3}-\d{2}-\d{4}` | 匹配 SSN
|
||||
`[a-z]\w{1,7}` | 匹配 UW NetID
|
||||
|
||||
### 贪婪与懒惰
|
||||
|
||||
范例 | 说明
|
||||
@ -340,7 +338,6 @@ RegEX 备忘清单
|
||||
`*? +? {n,}?`<br>_lazy_ | 尽可能少匹配
|
||||
`<.+?>` | 在 \<<yel>b</yel>>bold\<<yel>\/b</yel>> 中找到 2 个匹配项
|
||||
|
||||
|
||||
### 范围
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
@ -370,7 +367,6 @@ RegEX 备忘清单
|
||||
`(?-x)` | 自由空间模式关闭
|
||||
/regex/`ismx` | 修改整个字符串的模式
|
||||
|
||||
|
||||
### 组
|
||||
|
||||
范例 | 说明
|
||||
@ -394,7 +390,7 @@ RegEX 备忘清单
|
||||
|
||||
范例 | 说明
|
||||
:-|-
|
||||
`on(?:click\|load)` | 快于:<br>`on(click\|load)`
|
||||
`on(?:click\|load)` | 快于:`on(click\|load)`
|
||||
|
||||
尽可能使用非捕获或原子组
|
||||
|
||||
@ -543,8 +539,11 @@ M(?(?=.*?\bher\b)s|r)\.
|
||||
如果想要匹配句子中的 `.` 则要写成 `\.` 以下这个例子 `\.?` 是选择性匹配.
|
||||
|
||||
### 锚点
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
#### `^` 号
|
||||
匹配指定开头或结尾的字符串就要使用到锚点。
|
||||
|
||||
#### `^` 号 (符串的开头)
|
||||
|
||||
表达式 | 匹配示例
|
||||
:- | -
|
||||
@ -552,32 +551,32 @@ M(?(?=.*?\bher\b)s|r)\.
|
||||
`^(T\|t)he` | `The` car is parked in the garage.
|
||||
<!--rehype:className=show-header-->
|
||||
|
||||
#### `$` 号
|
||||
#### `$` 号 (否是最后一个)
|
||||
|
||||
表达式 | 匹配示例
|
||||
:- | -
|
||||
`(at\.)` | The fat c`at.` s`at.` on the m`at.`
|
||||
`(at\.)$` | The fat cat. sat. on the m`at`.
|
||||
`(at\.)$` | The fat cat. sat. on the m`at.`
|
||||
<!--rehype:className=show-header-->
|
||||
|
||||
### 简写字符集
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
<!--rehype:wrap-class=row-span-4-->
|
||||
|
||||
|简写|描述|
|
||||
|:----:|----|
|
||||
|`.`|除换行符外的所有字符|
|
||||
|`\w`|匹配所有字母数字,等同于 `[a-zA-Z0-9_]`|
|
||||
|`\W`|匹配所有非字母数字,即符号,等同于: `[^\w]`|
|
||||
|`\w`|匹配所有字母数字<br />等同于 `[a-zA-Z0-9_]`|
|
||||
|`\W`|匹配所有非字母数字,即符号<br />等同于: `[^\w]`|
|
||||
|`\d`|匹配数字: `[0-9]`|
|
||||
|`\D`|匹配非数字: `[^\d]`|
|
||||
|`\s`|匹配所有空格字符,等同于: `[\t\n\f\r\p{Z}]`|
|
||||
|`\s`|匹配所有空格字符<br />等同于:`[\t\n\f\r\p{Z}]`|
|
||||
|`\S`|匹配所有非空格字符: `[^\s]`|
|
||||
|`\f`|匹配一个换页符|
|
||||
|`\n`|匹配一个换行符|
|
||||
|`\r`|匹配一个回车符|
|
||||
|`\t`|匹配一个制表符|
|
||||
|`\v`|匹配一个垂直制表符|
|
||||
|`\p`|匹配 CR/LF(等同于 `\r\n`),用来匹配 DOS 行终止符|
|
||||
|`\p`|匹配 CR/LF(等同于 `\r\n`)<br />用来匹配 DOS 行终止符|
|
||||
<!--rehype:className=show-header-->
|
||||
|
||||
正则表达式提供一些常用的字符集简写。
|
||||
@ -756,6 +755,38 @@ False
|
||||
JavaScript 中的正则表达式
|
||||
---------------
|
||||
|
||||
### RegExp
|
||||
<!--rehype:wrap-class=row-span-4-->
|
||||
|
||||
#### 属性
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`dotAll` | 是否使用了 `s` 修饰符
|
||||
`flags` | 返回标志的字符串
|
||||
`global` | 是否使用了 `g` (全部)修饰符
|
||||
`hasIndices` | 是否使用了 `d` 修饰符
|
||||
`ignoreCase` | 匹配文本的时候是否忽略大小写 `i`
|
||||
`multiline` | 是否进行多行搜索 `m`
|
||||
`lastIndex` | 该索引表示从哪里开始下一个匹配
|
||||
`source` | 正则表达式的文本
|
||||
`sticky` | 搜索是否是 sticky
|
||||
`unicode` | Unicode 功能是否开启
|
||||
|
||||
#### 方法
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`match()` | 获取匹配结果
|
||||
`matchAll()` | 所有匹配项
|
||||
`replace()` | 替换所有符合正则模式的匹配项
|
||||
`search()` | 搜索以取得匹配正则模式的项
|
||||
`split()` | 切割字符串返回字符串数组
|
||||
~~`compile()`~~ | (重新)编译正则表达式
|
||||
`exec()` | 指定字符串中执行一个搜索匹配
|
||||
`test()` | 正则表达式与指定的字符串是否匹配
|
||||
`toString()` | 返回该正则表达式的字符串
|
||||
|
||||
### test()
|
||||
|
||||
```javascript
|
||||
@ -763,11 +794,8 @@ let textA = 'I like APPles very much';
|
||||
let textB = 'I like APPles';
|
||||
let regex = /apples$/i
|
||||
|
||||
// Output: false
|
||||
console.log(regex.test(textA));
|
||||
|
||||
// Output: true
|
||||
console.log(regex.test(textB));
|
||||
console.log(regex.test(textA)); // false
|
||||
console.log(regex.test(textB)); // true
|
||||
```
|
||||
|
||||
### search()
|
||||
@ -776,29 +804,22 @@ console.log(regex.test(textB));
|
||||
let text = 'I like APPles very much';
|
||||
let regexA = /apples/;
|
||||
let regexB = /apples/i;
|
||||
|
||||
// Output: -1
|
||||
console.log(text.search(regexA));
|
||||
|
||||
// Output: 7
|
||||
console.log(text.search(regexB));
|
||||
```
|
||||
|
||||
console.log(text.search(regexA)); // -1
|
||||
console.log(text.search(regexB)); // 7
|
||||
```
|
||||
|
||||
### exec()
|
||||
|
||||
```javascript
|
||||
let text = 'Do you like apples?';
|
||||
let regex= /apples/;
|
||||
|
||||
// Output: apples
|
||||
console.log(regex.exec(text)[0]);
|
||||
|
||||
// Output: Do you like apples?
|
||||
console.log(regex.exec(text).input);
|
||||
```
|
||||
|
||||
|
||||
### match()
|
||||
|
||||
```javascript
|
||||
@ -809,7 +830,6 @@ let regex = /apples/gi;
|
||||
console.log(text.match(regex));
|
||||
```
|
||||
|
||||
|
||||
### split()
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
@ -844,15 +864,33 @@ let result = text.replace(regex, 'mangoes');
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
### 属性示例
|
||||
|
||||
```javascript
|
||||
/d/s.dotAll; // => true
|
||||
/d/g.global; // => true
|
||||
/d/ig.flags; // => "gi"
|
||||
/d/d.hasIndices; // => true
|
||||
/d/i.ignoreCase; // => true
|
||||
```
|
||||
|
||||
### 多行文本中使用正则表达式
|
||||
|
||||
```js
|
||||
let s = "Please yes\nmake my day!";
|
||||
|
||||
s.match(/yes[^]*day/);
|
||||
// 返回 'yes\nmake my day'
|
||||
```
|
||||
|
||||
### replaceAll()
|
||||
|
||||
```javascript
|
||||
let regex = /apples/gi;
|
||||
let text = 'Here are apples and apPleS';
|
||||
// Output: Here are mangoes and mangoes
|
||||
let result = text.replaceAll(regex, "mangoes");
|
||||
console.log(result);
|
||||
|
||||
text.replaceAll(regex, "mangoes");
|
||||
// 返回: Here are mangoes and mangoes
|
||||
```
|
||||
<!--rehype:className=wrap-text-->
|
||||
|
||||
@ -879,6 +917,7 @@ PHP中的正则表达式
|
||||
```php
|
||||
$str = "Visit Microsoft!";
|
||||
$regex = "/microsoft/i";
|
||||
|
||||
// Output: Visit QuickRef!
|
||||
echo preg_replace($regex, "QuickRef", $str);
|
||||
```
|
||||
|
1110
docs/styled-components.md
Normal file
1110
docs/styled-components.md
Normal file
File diff suppressed because it is too large
Load Diff
150
docs/sublime-text.md
Normal file
150
docs/sublime-text.md
Normal file
@ -0,0 +1,150 @@
|
||||
Sublime Text 备忘清单
|
||||
===
|
||||
|
||||
这个 [Sublime Text](https://www.sublimetext.com/) 快速参考备忘单显示了它的键盘快捷键和命令。
|
||||
|
||||
## 快捷键
|
||||
|
||||
### 文本编辑初学者
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
[Sublime Text](https://www.sublimetext.com/) 是一个用于代码、标记的复杂文本编辑器。
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌘ D` | 选择单词(重复包括单词的下一个实例)
|
||||
`⌘ L` | 选择行(重复以包括下一行)
|
||||
`⌘ ⇧ L` | 将选择拆分为多行(多行编辑)
|
||||
`⌘ ⇧ A` | 选择标签内的文本(重复以展开)
|
||||
`⌃ ⇧ M` | 选择大括号或尖括号(重复展开)
|
||||
`⌘ X` | 剪切一行
|
||||
`⌃ M` | 转到匹配的括号
|
||||
`⌃ ↩︎` or `↩︎` | 在后面插入行
|
||||
`⌘ ↵` | 在后面插入行
|
||||
`⇧ ⌘ ↵` | 在前面插入行
|
||||
`⇧ ⌥ ▲` | 选择当前行光标之前
|
||||
`⇧ ⌥ ▼` | 选择当前行光标之后
|
||||
`⇧ ⌃ M` | 选择当前括号的所有内容
|
||||
`⌥ ⇠/⇢` | 进行逐词移动,相应的
|
||||
`⌥ ⇧ ⇠/⇢` | 进行逐词选择
|
||||
`⌘ U` | 返回到历史光标位置(撤销)
|
||||
`⌃ M` | 快速的在起始括号和结尾括号间切换
|
||||
`⌃ ⇧ M` | 则可以快速选择括号间的内容
|
||||
`⌃ ⇧ J` | 对于缩进型语言(例如Python)可以使用
|
||||
`⌃ ⌘ D` | 复制整行
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
查看:[Sublime Text](https://www.sublimetext.com/) 官网
|
||||
|
||||
### 代码折叠
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌘ Alt [` | 折叠最近的块
|
||||
`⌘ Alt ]` | 展开最近的块
|
||||
`⌘ K ⌘ 1` | 折叠所有第一级代码块
|
||||
`⌘ K ⌘ 2` | 折叠所有二级代码块
|
||||
`⌘ K ⌘ 3` | 折叠所有第三级代码块(等)
|
||||
`⌘ K ⌘ T` | 折叠所有 HTML 属性
|
||||
`⌘ K ⌘ 0` | 展开一切
|
||||
`⌘ K 0` | 代码展开
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### macOS 键盘符号
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌘` | Command()
|
||||
`⌃` | Control
|
||||
`⌥` | Option(alt)
|
||||
`⇧` | Shift
|
||||
`⇪` | Caps Lock(大写)
|
||||
`fn` | 功能键就是fn
|
||||
`↩︎` | return/Enter
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 编辑
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌘ ⇧ D` | 复制当前行/选择
|
||||
`⌘ ⇧ K` | 删除当前行/选择
|
||||
`⇧ del` | 删除当前行/选择
|
||||
`⌘ ⇧ ▲` | 移动队列
|
||||
`⌘ ⇧ ▼` | 下移一行
|
||||
`⌘ ▼/▲`| 移动到首行/尾行
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 转到
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌘ P` | 去任何地方
|
||||
`⌘ G` | 转到行号
|
||||
`⌘ R` | 转到符号
|
||||
`⌘ P, :` | 转到行号(`:`之后输入数字)
|
||||
`⌘ P, #` | 转到并列出字符串模糊匹配(`#`之后输入字符)
|
||||
`⌘ P, @` | 转到并列出符号(`@`之后开始输入符号名称)
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 选择(Selecting)
|
||||
|
||||
- `⌘ + D`
|
||||
选择光标所在的单词,并高亮该词出现的所有位置
|
||||
- `⌘ + D`
|
||||
择该词出现的下一个位置
|
||||
- `⌘ + U` 进行回退,使用Esc退
|
||||
<!--rehype:className=style-timeline shortcuts-->
|
||||
|
||||
----
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌃ K` / `⌘ K K` | 从光标处删除到行末尾
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 拆分窗口
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⇧ ⌥ 2` | 将视图拆分为两列
|
||||
`⇧ ⌥ 1` | 将视图还原为单列
|
||||
`⇧ ⌥ 5` | 将视图设置为网格(4 组)
|
||||
`⌃ 2` | 跳到第 2 组
|
||||
`⇧ ⌃ 2` | 将文件移动到组 2
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 文本操作
|
||||
|
||||
快捷键 | 说明
|
||||
:- | -
|
||||
`⌃ K ⌃ L` | 转换为小写
|
||||
`⌃ K ⌃ U` | 转换为大写
|
||||
`⇧ ⌃ K` | 删除行
|
||||
`⌃BACKSPACE` | 向后删除单词
|
||||
`⌃DEL` | 删除单词转发
|
||||
<!--rehype:className=shortcuts-->
|
||||
|
||||
### 命令行中启动编辑器
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```bash
|
||||
sudo ln -s /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl\
|
||||
/usr/local/bin/subl
|
||||
```
|
||||
<!--rehype:className=wrap-text -->
|
||||
|
||||
#### 在命令行中使用 **subl** 命令
|
||||
|
||||
```bash
|
||||
$ subl .
|
||||
$ subl README.md
|
||||
```
|
||||
|
||||
软链放到这个目录 `/usr/local/bin/subl`,这是因为 `Rootless` 机制,不能存放到 ~~`/usr/bin/subl`~~ 位置。
|
||||
|
||||
另见
|
||||
----
|
||||
|
||||
- [Sublime Text 官网](https://www.sublimetext.com/) _(sublimetext.com)_
|
||||
- [Sublime 编辑器快捷键](https://jaywcjlove.github.io/handbook/Shortcuts/sublime.html) _(jaywcjlove.github.io)_
|
@ -1258,6 +1258,7 @@ class MyComponent extends React.Component<Props, {}> {
|
||||
```
|
||||
|
||||
### 泛型组件
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
```tsx
|
||||
// 一个泛型组件
|
||||
|
524
docs/yaml.md
Normal file
524
docs/yaml.md
Normal file
@ -0,0 +1,524 @@
|
||||
YAML 备忘清单
|
||||
====
|
||||
|
||||
这是理解和编写 YAML 格式配置文件的快速参考备忘单。
|
||||
|
||||
入门
|
||||
-----------
|
||||
|
||||
### 介绍
|
||||
|
||||
[YAML](https://yaml.org/) 是一种数据序列化语言,旨在供人类直接读写
|
||||
|
||||
- YAML 不允许使用制表符
|
||||
- 元素部分之间必须有空间
|
||||
- YAML 区分大小写
|
||||
- 以 `.yaml` 或 `.yml` 扩展名结束您的 YAML 文件
|
||||
- YAML 是 JSON 的超集
|
||||
- Ansible playbook 是 YAML 文件
|
||||
<!--rehype:className=style-round-->
|
||||
|
||||
|
||||
### 标量类型
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```yaml
|
||||
n1: 1 # 整数
|
||||
n2: 1.234 # 浮点
|
||||
s1: 'abc' # 字符串
|
||||
s2: "abc" # 字符串
|
||||
s3: abc # 字符串
|
||||
b: false # 布尔类型
|
||||
d: 2015-04-05 # 日期类型
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"n1": 1,
|
||||
"n2": 1.234,
|
||||
"s1": "abc",
|
||||
"s2": "abc",
|
||||
"s3": "abc",
|
||||
"b": false,
|
||||
"d": "2015-04-05"
|
||||
}
|
||||
```
|
||||
|
||||
使用空格缩进。 元素部分之间必须有空间。
|
||||
|
||||
### 变量
|
||||
|
||||
```yaml
|
||||
some_thing: &VAR_NAME foobar
|
||||
other_thing: *VAR_NAME
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json {.wrap}
|
||||
{
|
||||
"some_thing": "foobar",
|
||||
"other_thing": "foobar"
|
||||
}
|
||||
```
|
||||
|
||||
### 注释
|
||||
|
||||
```yaml
|
||||
# A single line comment example
|
||||
# block level comment example
|
||||
# comment line 1
|
||||
# comment line 2
|
||||
# comment line 3
|
||||
```
|
||||
|
||||
### 多行字符串
|
||||
|
||||
```yaml
|
||||
description: |
|
||||
hello
|
||||
world
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json {.wrap}
|
||||
{"description": "hello\nworld\n"}
|
||||
```
|
||||
|
||||
### 继承
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```yaml
|
||||
parent: &defaults
|
||||
a: 2
|
||||
b: 3
|
||||
child:
|
||||
<<: *defaults
|
||||
b: 4
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json {.wrap}
|
||||
{
|
||||
"parent": {
|
||||
"a": 2,
|
||||
"b": 3
|
||||
},
|
||||
"child": {
|
||||
"a": 2,
|
||||
"b": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 参考
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```yaml
|
||||
values: &ref
|
||||
- Will be
|
||||
- reused below
|
||||
|
||||
other_values:
|
||||
i_am_ref: *ref
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json {.wrap}
|
||||
{
|
||||
"values": [
|
||||
"Will be",
|
||||
"reused below"
|
||||
],
|
||||
"other_values": {
|
||||
"i_am_ref": [
|
||||
"Will be",
|
||||
"reused below"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 折叠的字符串
|
||||
|
||||
```yaml
|
||||
description: >
|
||||
hello
|
||||
world
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json {.wrap}
|
||||
{"description": "hello world\n"}
|
||||
```
|
||||
|
||||
### 两份文件
|
||||
|
||||
```yaml
|
||||
---
|
||||
document: this is doc 1
|
||||
---
|
||||
document: this is doc 2
|
||||
```
|
||||
|
||||
YAML使用`---`将指令与文档内容分开。
|
||||
|
||||
YAML Collections
|
||||
-----------
|
||||
|
||||
### 序列
|
||||
|
||||
```yaml
|
||||
- Mark McGwire
|
||||
- Sammy Sosa
|
||||
- Ken Griffey
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
[
|
||||
"Mark McGwire",
|
||||
"Sammy Sosa",
|
||||
"Ken Griffey"
|
||||
]
|
||||
```
|
||||
|
||||
### 映射
|
||||
|
||||
```yaml
|
||||
hr: 65 # Home runs
|
||||
avg: 0.278 # Batting average
|
||||
rbi: 147 # Runs Batted In
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"hr": 65,
|
||||
"avg": 0.278,
|
||||
"rbi": 147
|
||||
}
|
||||
```
|
||||
|
||||
### 映射到序列
|
||||
|
||||
```yaml
|
||||
attributes:
|
||||
- a1
|
||||
- a2
|
||||
methods: [getter, setter]
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"attributes": ["a1", "a2"],
|
||||
"methods": ["getter", "setter"]
|
||||
}
|
||||
```
|
||||
|
||||
### 映射序列
|
||||
|
||||
```yaml
|
||||
children:
|
||||
- name: Jimmy Smith
|
||||
age: 15
|
||||
- name: Jimmy Smith
|
||||
age: 15
|
||||
-
|
||||
name: Sammy Sosa
|
||||
age: 12
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"children": [
|
||||
{"name": "Jimmy Smith", "age": 15},
|
||||
{"name": "Jimmy Smith", "age": 15},
|
||||
{"name": "Sammy Sosa", "age": 12}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 序列的序列
|
||||
|
||||
```yaml
|
||||
my_sequences:
|
||||
- [1, 2, 3]
|
||||
- [4, 5, 6]
|
||||
-
|
||||
- 7
|
||||
- 8
|
||||
- 9
|
||||
- 0
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"my_sequences": [
|
||||
[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9, 0]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 映射的映射
|
||||
|
||||
```yaml
|
||||
Mark McGwire: {hr: 65, avg: 0.278}
|
||||
Sammy Sosa: {
|
||||
hr: 63,
|
||||
avg: 0.288
|
||||
}
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"Mark McGwire": {
|
||||
"hr": 65,
|
||||
"avg": 0.278
|
||||
},
|
||||
"Sammy Sosa": {
|
||||
"hr": 63,
|
||||
"avg": 0.288
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 嵌套集合
|
||||
|
||||
```yaml
|
||||
Jack:
|
||||
id: 1
|
||||
name: Franc
|
||||
salary: 25000
|
||||
hobby:
|
||||
- a
|
||||
- b
|
||||
location: {country: "A", city: "A-A"}
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"Jack": {
|
||||
"id": 1,
|
||||
"name": "Franc",
|
||||
"salary": 25000,
|
||||
"hobby": ["a", "b"],
|
||||
"location": {
|
||||
"country": "A", "city": "A-A"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 无序集
|
||||
|
||||
```yaml
|
||||
set1: !!set
|
||||
? one
|
||||
? two
|
||||
set2: !!set {'one', "two"}
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"set1": {"one": null, "two": null},
|
||||
"set2": {"one": null, "two": null}
|
||||
}
|
||||
```
|
||||
|
||||
集合表示为一个映射,其中每个键都与一个空值相关联
|
||||
|
||||
|
||||
### 有序映射
|
||||
|
||||
```yaml
|
||||
ordered: !!omap
|
||||
- Mark McGwire: 65
|
||||
- Sammy Sosa: 63
|
||||
- Ken Griffy: 58
|
||||
```
|
||||
|
||||
#### ↓ 等效的 JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"ordered": [
|
||||
{"Mark McGwire": 65},
|
||||
{"Sammy Sosa": 63},
|
||||
{"Ken Griffy": 58}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
YAML 参考
|
||||
--------------
|
||||
|
||||
### 条款
|
||||
|
||||
- 序列又名数组或列表
|
||||
- 标量又名字符串或数字
|
||||
- 映射又名哈希或字典
|
||||
<!--rehype:className=style-round-->
|
||||
|
||||
基于 YAML.org [refcard](https://yaml.org/refcard.html)。
|
||||
|
||||
### 文档指标
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`%` | 指令指标
|
||||
`---` | 文档标题
|
||||
`...` | 文档终结者
|
||||
|
||||
### 收集指标
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`?` | 关键指标
|
||||
`:` | 价值指标
|
||||
`-` | 嵌套系列条目指示器
|
||||
`,` | 单独的内联分支条目
|
||||
`[]` | 环绕串联系列分支
|
||||
`{}` | 环绕在线键控分支
|
||||
|
||||
### 别名指标
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`&` | 锚属性
|
||||
`*` | 别名指示符
|
||||
|
||||
### 特殊键
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`=` | 默认“值”映射键
|
||||
`<<` | 合并来自另一个映射的键
|
||||
|
||||
### 标量指标
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`''` | 环绕内联未转义标量
|
||||
`"` | 环绕内嵌转义标量
|
||||
`|` | 块标量指示器
|
||||
`>` | 折叠标量指示器
|
||||
`-` | 剥离 chomp 修饰符(`|-` 或 `>-`)
|
||||
`+` | 保留 chomp 修饰符(`|+` 或 `>+`)
|
||||
`1-9` | 显式缩进修饰符(`|1` 或 `>2`)。 <br/> 修饰符可以组合(`|2-`, `>+1`)
|
||||
|
||||
### 标签属性(通常未指定)
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
:- | :-
|
||||
:- | :-
|
||||
`none` | 未指定的标签(由应用程序自动解析)
|
||||
`!` | 非特定标签(默认情况下,`!!map`/`!!seq`/`!!str`)
|
||||
`!foo` | 主要(按照惯例,表示本地 `!foo` 标记)
|
||||
`!!foo` | 次要的(按照惯例,表示 `tag:yaml.org,2002:foo`)
|
||||
`!h!foo` | 需要 `%TAG !h! <prefix>`(然后表示 `<prefix>foo`)
|
||||
`!<foo>` | 逐字标记(始终表示“foo”)
|
||||
|
||||
### 杂项指标
|
||||
|
||||
| | |
|
||||
|-----|-----------------------------|
|
||||
| `#` | 一次性评论指示器 |
|
||||
| <code>\`@</code> | 两者都保留供将来使用 |
|
||||
|
||||
|
||||
### 核心类型(默认自动标签)
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
| | |
|
||||
|---------|------------------------------------------|
|
||||
| `!!map` | `{Hash table, dictionary, mapping}` |
|
||||
| `!!seq` | `{List, array, tuple, vector, sequence}` |
|
||||
| `!!str` | Unicode 字符串 |
|
||||
|
||||
### 转义码
|
||||
<!--rehype:wrap-class=row-span-3-->
|
||||
|
||||
#### Numeric
|
||||
|
||||
- `\x12` (8-bit)
|
||||
- `\u1234` (16-bit)
|
||||
- `\U00102030` (32-bit)
|
||||
<!--rehype:className=cols-2 style-none-->
|
||||
|
||||
#### Protective
|
||||
|
||||
- `\\` (\\)
|
||||
- `\"` (")
|
||||
- `\ ` ( )
|
||||
- `\<TAB>` (TAB)
|
||||
<!--rehype:className=cols-3 style-none-->
|
||||
|
||||
#### C
|
||||
- `\0` (NUL)
|
||||
- `\a` (BEL)
|
||||
- `\b` (BS)
|
||||
- `\f` (FF)
|
||||
- `\n` (LF)
|
||||
- `\r` (CR)
|
||||
- `\t` (TAB)
|
||||
- `\v` (VTAB)
|
||||
<!--rehype:className=cols-3 style-none-->
|
||||
|
||||
#### 额外的
|
||||
|
||||
- `\e` (ESC)
|
||||
- `\_` (NBSP)
|
||||
- `\N` (NEL)
|
||||
- `\L` (LS)
|
||||
- `\P` (PS)
|
||||
<!--rehype:className=cols-3 style-none-->
|
||||
|
||||
### 更多类型
|
||||
|
||||
| | |
|
||||
|----------|-----------------------------|
|
||||
| `!!set` | `{cherries, plums, apples}` |
|
||||
| `!!omap` | `[one: 1, two: 2]` |
|
||||
|
||||
### 与语言无关的标量类型
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
|
||||
| | |
|
||||
|---------------------------|--------------------------------------------|
|
||||
| `{~, null}` | 空(无值)。 |
|
||||
| `[1234, 0x4D2, 02333]` | [十进制整数、十六进制整数、八进制整数] |
|
||||
| `[1_230.15, 12.3015e+02]` | [固定浮点数,指数浮点数] |
|
||||
| `[.inf, -.Inf, .NAN]` | [无穷大(浮点数),负数,不是数字] |
|
||||
| `{Y, true, Yes, ON}` | 布尔真 |
|
||||
| `{n, FALSE, No, off}` | 布尔假 |
|
||||
|
||||
另见
|
||||
---
|
||||
|
||||
- [YAML Reference Card](https://yaml.org/refcard.html) _(yaml.org)_
|
||||
- [Learn X in Y minutes](https://learnxinyminutes.com/docs/yaml/) _(learnxinyminutes.com)_
|
||||
- [YAML lint online](http://www.yamllint.com/) _(yamllint.com)_
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "reference",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "为开发人员分享快速参考备忘单(主要是方便自己)。",
|
||||
"author": "jaywcjlove",
|
||||
"license": "MIT",
|
||||
|
3
scripts/assets/emmet.svg
Normal file
3
scripts/assets/emmet.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="1em" width="1em" viewBox="0 0 153 151">
|
||||
<path d="M76.2378757,0 C118.342892,0 152.475751,33.7082594 152.475751,75.2895046 C152.475751,116.87075 118.342892,150.579009 76.2378757,150.579009 C34.1328596,150.579009 0,116.87075 0,75.2895046 C0,33.7082594 34.1328596,0 76.2378757,0 Z M60.5934369,46.9019586 L19.8384036,56.9645627 L92.6150779,128.835332 L102.803239,88.5872762 L94.3131047,80.2021662 L87.0356763,108.950356 L70.5395345,92.6594199 L75.3909542,73.9732442 L56.2267408,78.5252622 L39.7305989,62.2343264 L68.8415078,55.0474265 L60.5934369,46.9019586 Z M116.873372,33.007443 L76.1189361,43.0694569 L84.367007,51.2149248 L102.561176,47.1421909 L98.1944795,64.8703887 L106.684613,73.2549084 L116.873372,33.007443 Z" transform="translate(0 .421)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 824 B |
3
scripts/assets/nginx.svg
Normal file
3
scripts/assets/nginx.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="1em" width="1em" viewBox="0 0 46 52">
|
||||
<path d="M21.6686953,0.373850863 C22.4859141,-0.124616954 23.5140859,-0.124616954 24.3575391,0.373850863 L44.6555781,12.0199042 C45.4992109,12.491911 46,13.3837179 46,14.3541925 L46,37.6459416 C46,38.6164162 45.4992109,39.5084019 44.6555781,39.9804087 L24.3575391,51.6262832 C23.5403203,52.1245723 22.5123281,52.1245723 21.6686953,51.6262832 L1.37083594,39.9804087 C0.948929687,39.7444053 0.606265625,39.4295553 0.369078125,39.009934 C0.105476562,38.5903128 0,38.1444094 0,37.672045 L0,14.3541925 C0,13.3837179 0.500789062,12.491911 1.37101563,12.0199042 Z M32.1078203,14.5377872 C31.4147694,14.5348957 30.749258,14.8075453 30.2591927,15.2951641 C29.7691273,15.782783 29.4951098,16.444972 29.4980391,17.134563 L29.4980391,30.0655834 L18.5843594,17.0821774 L17.7937344,16.1378062 C16.9238672,15.0623815 15.4739687,14.5640925 14.2348437,14.5640925 C12.5215234,14.5640925 11.2825549,15.6919028 11.2825549,17.0821774 L11.2825549,34.8918533 C11.2796492,35.5814132 11.5536421,36.2435748 12.0436685,36.7311885 C12.5336949,37.2188021 13.1991599,37.4914728 13.8921797,37.4886291 C14.5852306,37.4915206 15.250742,37.218871 15.7408073,36.7312522 C16.2308727,36.2436333 16.5048902,35.5814443 16.5019609,34.8918533 L16.5019609,21.9869363 L28.2062656,35.8886101 C29.0761328,36.9640348 30.5260312,37.4623238 31.7651562,37.4623238 C33.4784766,37.4623238 34.7174451,36.3345135 34.7174451,34.9444177 L34.7174451,17.134563 C34.7203508,16.4450031 34.4463579,15.7828415 33.9563315,15.2952278 C33.4663051,14.8076142 32.8008401,14.5349435 32.1078203,14.5377872 Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
3
scripts/assets/styled-components.svg
Normal file
3
scripts/assets/styled-components.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="1em" width="1em">
|
||||
<path d="m16.214 6.762-.075.391c-.116.741-.074.953.244 1.228l.307.254-.318 1.418c-.19.846-.423 1.555-.571 1.788-.127.201-.275.497-.307.656-.053.19-.233.381-.508.55-.243.138-.72.508-1.058.805-.27.243-.456.392-.557.456l-.33.261a1.4 1.4 0 0 0-.189.411c-.023.107-.01.178.024.23.033.05.09.085.168.107a.954.954 0 0 0 .282.023 3 3 0 0 0 .632-.112c.07-.019.125-.037.173-.053.074-.091.245-.263.548-.562.804-.793 1.111-1.227.794-1.11-.117.042-.064-.064.137-.276.424-.413.667-1.037 1.175-2.994.402-1.545.402-1.567.698-1.567.139 0 .532.024.532.024V6.762h-.902zm3.839 3.165c-.064 0-.17.096-.233.202-.116.19.021.306 1.767 1.396 1.037.657 1.873 1.217 1.852 1.26-.021.031-.868.582-1.883 1.217-1.842 1.142-1.852 1.153-1.683 1.386.212.275 0 .37 2.391-1.122L24 13.155v-.836l-1.937-1.196c-1.047-.656-1.957-1.185-2.01-1.196zm-16.085.117c-.053 0-.963.54-2.01 1.185L0 12.425v.836l1.947 1.217c1.08.666 1.99 1.217 2.032 1.217.042 0 .127-.096.212-.212.127-.201.02-.286-1.768-1.418C.72 12.996.54 12.848.71 12.732c.106-.074.91-.572 1.778-1.111 1.979-1.217 1.873-1.133 1.714-1.387-.063-.105-.17-.2-.233-.19zm8.684.023c-.292-.002-.92.443-2.8 1.978-.081.193-.088.326-.051.412.024.059.068.1.129.13.06.03.138.048.224.055.171.015.373-.012.536-.044l.11-.025a.386.386 0 0 1 .144-.118c.116-.064.603-.508 1.09-.984.857-.868 1.058-1.26.709-1.387a.24.24 0 0 0-.09-.017zm2.196.603c-.257.007-.72.305-1.513.938-.398.323-.65.497-.785.533l-.524.414c-.197.36-.226.583-.174.706a.25.25 0 0 0 .138.134.644.644 0 0 0 .24.045 2.18 2.18 0 0 0 .58-.085 3.466 3.466 0 0 0 .291-.092l.029-.012.053-.028c.1-.129.33-.372.618-.652.91-.878 1.375-1.502 1.28-1.735-.043-.113-.117-.17-.233-.166zm-2.424 1.08c-.074.008-.24.136-.539.398-.432.382-.903.602-1.066.504a3.97 3.97 0 0 1-.114.024c-.166.033-.373.06-.558.045a.708.708 0 0 1-.252-.063.337.337 0 0 1-.168-.17c-.037-.09-.037-.202.005-.345l-.65.534-1.471 1.217v1.973l4.82-3.797a.41.41 0 0 1 .016-.123c.037-.134.035-.202-.023-.196zm2.074.639c-.073 0-.195.103-.39.31-.265.283-.682.557-.903.613l-.034.018a2.191 2.191 0 0 1-.11.042c-.06.02-.138.044-.228.068-.18.049-.404.094-.604.089a.732.732 0 0 1-.275-.054.344.344 0 0 1-.184-.18c-.058-.139-.035-.334.092-.611L7.61 16.033v1.205h1.868l3.962-3.112c.103-.114.258-.27.467-.465.56-.519.687-.698.687-.963 0-.206-.023-.31-.096-.31zm.943 1.95-.339.338c-.19.18-.529.402-.761.497l-.046.02-.003.005-.01.01c-.009.007-.013.008-.02.011a3.432 3.432 0 0 1-.282.093 3.058 3.058 0 0 1-.65.115 1.035 1.035 0 0 1-.31-.027.364.364 0 0 1-.218-.144c-.048-.074-.062-.173-.035-.295a1.11 1.11 0 0 1 .095-.25l-3.197 2.526h4.252l.508-.582c.698-.814 1.016-1.396 1.016-1.894z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
3
scripts/assets/sublime-text.svg
Normal file
3
scripts/assets/sublime-text.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor" height="1em" width="1em">
|
||||
<path d="M20.953.004a.397.397 0 0 0-.18.017L3.225 5.585c-.175.055-.323.214-.402.398a.42.42 0 0 0-.06.22v5.726a.42.42 0 0 0 .06.22c.079.183.227.341.402.397l7.454 2.364-7.454 2.363c-.255.08-.463.374-.463.655v5.688c0 .282.208.444.463.363l17.55-5.565c.237-.075.426-.336.452-.6.003-.022.013-.04.013-.065V12.06c0-.281-.208-.575-.463-.656L13.4 9.065l7.375-2.339c.255-.08.462-.375.462-.656V.384c0-.211-.117-.355-.283-.38z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 532 B |
4
scripts/assets/xpath.svg
Normal file
4
scripts/assets/xpath.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="1em" width="1em">
|
||||
<path fill="none" d="M0 0h24v24H0z"/>
|
||||
<path d="M10 2a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H8v2h5V9a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-1H8v6h5v-1a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-1H7a1 1 0 0 1-1-1V8H4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1h6zm9 16h-4v2h4v-2zm0-8h-4v2h4v-2zM9 4H5v2h4V4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 449 B |
6
scripts/assets/yaml.svg
Normal file
6
scripts/assets/yaml.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 512 470.647">
|
||||
<polygon points="235.793 0 143.978 137.674 143.978 224.949 87.702 224.949 87.702 137.674 0 0 63.25 0 119.018 88.646 175.243 0 235.793 0 235.793 0"/>
|
||||
<path d="M330.294,175.451h-101.861l-20.717,50.024h-45.106l95.38,-224.949h46.137l91.51,224.949h-48.2l-17.144,-50.024zm-16.92,-44.911l-31.226,-82.55l-34.837,82.55h66.063z"/>
|
||||
<polygon points="87.701 250.177 87.701 470.647 135.004 470.647 135.004 318.569 184.509 420.789 221.743 420.789 272.939 314.976 272.939 470.602 318.318 470.602 318.318 250.177 256.358 250.177 201.381 349.883 149.021 250.177 87.701 250.177 87.701 250.177"/>
|
||||
<polygon points="512 422.735 395.638 422.735 395.638 250.125 347.442 250.125 347.442 469.647 512 469.647 512 422.737 512 422.735"/>
|
||||
</svg>
|
After Width: | Height: | Size: 810 B |
@ -203,8 +203,7 @@ table td:first-child>code {
|
||||
--text-opacity: 1;
|
||||
color: rgb(5 150 105/var(--text-opacity));
|
||||
}
|
||||
table td:first-child>del>code {
|
||||
text-decoration: inherit;
|
||||
table td > del, table td:first-child > del > code, .wrap-body p > del > code {
|
||||
color: var(--color-danger-fg);
|
||||
}
|
||||
|
||||
@ -293,21 +292,34 @@ body.home .h1wrap p {
|
||||
grid-template-columns: repeat(2,minmax(0,1fr));
|
||||
}
|
||||
|
||||
[data-color-mode*='light'] body .home-card a {
|
||||
--text-opacity: 0.75;
|
||||
color: rgb(15 19 24/var(--text-opacity));
|
||||
}
|
||||
[data-color-mode*='light'] body .home-card a:hover {
|
||||
--text-opacity: 0.85;
|
||||
color: rgb(241 245 249/var(--text-opacity)) !important;
|
||||
}
|
||||
.home-card a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
cursor: pointer;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
padding: 0rem 1rem;
|
||||
height: 4rem;
|
||||
box-shadow: 0 0 #0000,0 0 #0000,0 1px 2px 0 rgba(0,0,0,0.05);
|
||||
color: var(--color-fg-default);
|
||||
--text-opacity: 0.75;
|
||||
color: rgb(241 245 249/var(--text-opacity));
|
||||
--bg-opacity: 0.5;
|
||||
background-color: rgb(62 69 72/var(--bg-opacity));
|
||||
transition: all .3s;
|
||||
text-decoration: none;
|
||||
}
|
||||
.home-card a:hover {
|
||||
--bg-opacity: 1;
|
||||
--text-opacity: 0.75;
|
||||
}
|
||||
.home-card a svg {
|
||||
min-width: 1.6rem;
|
||||
@ -576,6 +588,55 @@ body:not(.home) .h2wrap > h2 a::after {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.h2wrap-body ul.style-timeline {
|
||||
counter-reset: stepCount;
|
||||
}
|
||||
.h2wrap-body ul.style-timeline li:first-child:before {
|
||||
background-color: #228e6c;
|
||||
color: rgb(226 232 240/1);
|
||||
}
|
||||
.h2wrap-body ul.style-timeline li::before {
|
||||
color: #228e6c;
|
||||
background-color: #fff;
|
||||
counter-increment: stepCount;
|
||||
content: counter(stepCount);
|
||||
border-radius: initial;
|
||||
border-radius: 0.5rem;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
text-align: center;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.30rem;
|
||||
border: 2px solid #228e6c;
|
||||
top: -1px;
|
||||
left: -14px;
|
||||
}
|
||||
.h2wrap-body ul.style-timeline li:last-child {
|
||||
border-image: linear-gradient(to bottom,#228e6c,rgba(0,0,0,0)) 1 100%;
|
||||
}
|
||||
.h2wrap-body ul.style-timeline li {
|
||||
border-bottom: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 25px !important;
|
||||
border-left: 2px solid #228e6c;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.h2wrap-body ul.style-timeline li > pre {
|
||||
padding: 0 !important;
|
||||
padding-top: 10px !important;
|
||||
height: initial !important;
|
||||
}
|
||||
|
||||
.h2wrap-body ul.style-round li::before {
|
||||
border-radius: 9999px;
|
||||
border-width: 2px;
|
||||
height: 0.5rem;
|
||||
width: 0.5rem;
|
||||
border-color: #228e6c;
|
||||
background: transparent;
|
||||
top: 14px;
|
||||
}
|
||||
|
||||
.wrap-body ul:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@ -629,6 +690,9 @@ body:not(.home) .h2wrap > h2 a::after {
|
||||
.cols-5 {
|
||||
grid-template-columns: repeat(5,minmax(0,1fr)) !important;
|
||||
}
|
||||
.cols-6 {
|
||||
grid-template-columns: repeat(6,minmax(0,1fr)) !important;
|
||||
}
|
||||
.col-span-2 {
|
||||
grid-column: span 2/span 2;
|
||||
}
|
||||
@ -795,19 +859,16 @@ body:not(.home) .h2wrap > h2 a::after {
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.home-card {
|
||||
grid-template-columns: repeat(4,minmax(0,1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 375px) {
|
||||
@media only screen and (max-width: 375px) {
|
||||
.header-nav .title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.header-nav .max-container {
|
||||
padding-top: 0.85rem;
|
||||
}
|
||||
.header-nav .menu a, .header-nav .menu button {
|
||||
padding: 0.2rem 0.3rem;
|
||||
}
|
||||
.wrap-header.h1wrap > h1 {
|
||||
margin-bottom: 2rem;
|
||||
font-size: 2rem;
|
||||
@ -816,15 +877,21 @@ body:not(.home) .h2wrap > h2 a::after {
|
||||
margin-top: 1.6rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.wrap-header.h2wrap > h2 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
.wrap-header.h3wrap > .wrap-body {
|
||||
overflow: auto;
|
||||
}
|
||||
.tooltip:hover .tooltiptext {
|
||||
display: none;
|
||||
}
|
||||
.h1wrap-body {
|
||||
gap: 2rem;
|
||||
}
|
||||
.home-card {
|
||||
gap: 1rem;
|
||||
}
|
||||
.wrap-header.h2wrap > h2 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
a.home-button {
|
||||
padding-left: 1.1rem;
|
||||
padding-right: 1.1rem;
|
||||
@ -835,4 +902,23 @@ body:not(.home) .h2wrap > h2 a::after {
|
||||
.footer-wrap {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
table td, table th {
|
||||
display: block;
|
||||
text-align: left !important;
|
||||
}
|
||||
table td + td, table th + th {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.home-card {
|
||||
grid-template-columns: repeat(4,minmax(0,1fr));
|
||||
}
|
||||
.wrap-header.h3wrap > .wrap-body {
|
||||
overflow: initial;
|
||||
}
|
||||
.tooltip:hover .tooltiptext {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user