This commit is contained in:
xiaoxiaoqiong 2022-04-22 11:07:34 +08:00
parent b856e6cdd7
commit 7f9298f948
37 changed files with 1469 additions and 1 deletions

19
50x.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Error</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>An error occurred.</h1>
<p>Sorry, the page you are looking for is currently unavailable.<br/>
Please try again later.</p>
<p>If you are the system administrator of this resource then you should check
the error log for details.</p>
<p><em>Faithfully yours, nginx.</em></p>
</body>
</html>

244
README.md
View File

@ -1,2 +1,244 @@
# osredm_help # 红山开源平台开源项目使用手册
## 1. 开源项目:项目管理
项目是用户创建的对应于一个小组或团队的协同实践社区,由项目管理员、开发人员和报告人员组成,提供问题跟踪、版本管理、里程碑、代码质量分析、资源托管、交流研讨等功能。
注意:未开展分组作业或项目开发的用户暂不涉及本章内容。
### 1.1 基本操作流程
开源项目是一种协同实践社区,支持团队和小组开展各种协作活动。 开源项目的典型操作流程如下:
1. 项目创建:团队(或小组)的核心成员首先创建一个项目。
2. 成员添加:通知团队其他成员在红山开源平台上注册(如已注册则忽略此步),将团队成员加入项目。
3. 问题跟踪:发布不同类型的问题,指派给责任人,并跟踪问题的解决进度。
4. 版本管理基于Git版本库实现分布式版本控制。
5. 交流互动:基于讨论区等工具开展深度技术交流和研讨。 上述步骤的详细操作参见以下章节。
### 1.2 项目创建
项目包括创建1、创建镜像项目2、创建托管项目3、创建组织。
1、创建镜像项目 点击右上角“⊕”,选择“创建镜像项目”,如下图所示: ![创建镜像项目](./static/img/3266.png) 填写项目基本信息,包括项目拥有者、镜像版本库地址、项目名称、项目简介等信息,并点击“创建项目”如下图所示: ![img](./static/img/3267.png)
2、创建托管项目 点击右上角“⊕”,选择“创建托管项目”,如下图所示: ![img](./static/img/3239.png) 填写项目基本信息,包括项目拥有者、项目名称、项目简介等信息,并点击“创建项目”如下图所示: ![img](./static/img/3240.png)
3、创建组织 点击右上角“⊕”,选择“创建组织”,如下图所示: ![img](./static/img/3241.png) 填写组织基本信息,包括组织名称、组织描述等,选择可见性,并上传头像后,点击“创建组织”如下图所示: ![img](./static/img/3242.png)
### 1.3 项目配置
项目的管理员可以对项目进行多种配置。 可配置的内容主要包括:
1. 项目基本信息:包括项目名称和简介,还包括项目是否公开、是否隐藏项目代码库以及删除项目
2. 成员管理:为项目添加各种角色的成员,点击“成员”标签页
3. 关联组织:将项目关联到相应的组织,点击“组织”标签页
4. 创建里程碑:为项目创建阶段性的产品版本,点击“里程碑”标签页
5. 创建版本库为项目创建版本库Git点击“版本库”标签页
### 1.4 成员管理
项目管理员可以在项目配置中管理项目的成员。
1、点击“仓库设置”进入标签页选择左侧菜单栏的“协作者管理”将看到如下页面 ![img](./static/img/3243.png) 2、在下图所示的搜索框内输入欲添加成员的用户名如下图所示 ![img](./static/img/3244.png) 3、在搜索结果中选择想要添加的成员点击“添加成员”如下图所示 ![img](./static/img/3245.png) 4、成员添加成功后可为其选择角色包括管理员、开发者、报告者三种如下图所示 ![img](./static/img/3246.png) 注意:项目成员的不同角色具有不同权限。 管理员:可以对项目中的所有模块进行操作。 开发者:不能对项目进行配置。 报告者:不能对版本库进行操作。
### 1.5 删除项目
管理员可以删除项目。步骤如下: 点击“仓库设置”,进入标签页,选择左侧菜单栏的“基本设置”,点击下方的“删除本仓库”,即可删除当前项目。 ![img](./static/img/3247.png)
### 1.6 发布问题
1、点击“易修(Issue)”,进入标签页,点击页面右侧的“创建任务”。 ![img](./static/img/3260.png) 2、填写任务标题及内容选择指派成员、状态、类型、优先度等点击“创建”。 ![img](./static/img/3251.png) ![img](./static/img/3252.png) ![img](./static/img/3253.png) ![img](./static/img/3254.png) ![img](./static/img/3255.png) 3、出现如下图所示信息时表明问题发布成功。 ![img](./static/img/3256.png) 4、点击已发布的问题进入问题详情页面点击下图所示的评论区输入栏。 ![img](./static/img/3257.png) 5、点开输入栏后出现下图所示输入界面输入想要评论的内容后点击“评论”。 ![img](./static/img/3258.png) 6、出现如下图所示信息时表明评论成功。 ![img](./static/img/3259.png) 注意: 每个问题都相当于一个可以进度追踪的帖子。因此支持回复、点赞、@等。 在问题截止日期的前一天,系统将对问题的发布人和被指派人发送提示消息。
### 1.7 新建里程碑
管理员可以新建里程碑。步骤如下: 1、点击“里程碑”进入标签页点击页面右侧的“新建里程碑”。 ![img](./static/img/3261.png) 2、填写新里程碑相关信息包括标题、描述等选择截止日期后点击“创建里程碑”。 ![img](./static/img/3262.png) 3、出现如下图所示信息时表明新的里程碑创建成功。 ![img](./static/img/3263.png) 注意:项目成员在发布问题时。将在“目标版本”属性中看到新建的版本。
### 1.8 关联里程碑
项目成员可以将项目问题关联到里程碑,从而使里程碑包含明确的任务列表。 步骤如下: 1、进入某个问题的页面编辑“里程碑”属性从“里程碑”下拉框中选择适当的里程碑点击“提交”。 ![img](./static/img/3264.png) 2、出现如下图所示信息时表明里程碑关联成功。 ![img](./static/img/3265.png)
## 2. 开源项目:版本管理
版本管理又称版本控制,是一种分布式协同编程的重要工具。没有掌握好版本管理工具,团队式协同开发是不可想象的。
红山开源平台集成了Gitlab版本管理系统可以提供标准的Git版本库操作流程。 因此在使用本平台提供的Git仓库时。可以直接参考本手册。也可以在互联网中搜索相关问题的解决方法。 详见Git使用指南https://git-scm.com/book/zh/v2
注意:未开展项目开发的用户暂不涉及本章内容。
### 2.1 基本操作流程
Git版本库的使用非常灵活功能非常强大但其基本流程也是非常简单的
1. 在平台上新建远程版本库或fork一个远程版本库
2. 将远程库clone到本地
3. 在本地库中创建分支缺省为master
4. 提交commit代码到本地分支
5. 推送push代码到远程库的分支/下拉pull远程库的代码到本地
6. 解决冲突
7. 合并分支
以上是一个在实际操作中反复进行的基本流程。
注意: 在多人协同编程的情况下每个成员在开发自己的模块时尽可能先从master或developer分支下载最新代码并与本地分支合并否则时间久了合并分支将是一个灾难。 上连基本流程可以使用Git命令行客户端、Tortoise Git客户端等工具完成。
### 2.2 fork版本库
用户对某一个版本库的fork操作将会为该用户创建一个同名项目和同名版本库。
操作步骤进入需要fork的版本库页面点击右上角的Fork按钮即可。
注意: 任何用户都可以fork一个公开的版本库。 连续两次fork同一版本时系统将直接跳转到第一次fork后的版本库。
### 2.3 新建版本库
管理员可以新建版本库。步骤如下:
1. 进入相应的开源项目的“项目配置”页面
2. 点击“版本库”标签页,点击“新建版本库”链接
3. 填写版本库名称后,点击“创建”
注意: 同一用户名下的版本不能重名。 平台也将在近期提供SSH访问方式。
### 2.4 克隆版本库(clone)
克隆版本库是将开源项目的版本库完整的克隆到本地的过程。其中包括了版本库的所有提交记录。步骤如下:
1. 确定需要克隆的版本库地址:从项目的版本库页面中即可找到该地址
2. 在本地的git命令行执行
```bash
git clone https://git.osredm.com/xxx/yyy.git
```
其中“https:// git.osredm.com /xxx/yyy.git”是版本库的地址xxx为用户IDyyy为项目名称
3. 如果项目是私有的,根据提示输入版本库用户名和密码,输入当前用户的红山开源平台登录名和密码即可
注意:如果项目公开, 无需输入口令, 可以直接克隆。 对于私有项目,只有项目成员才具有克隆的权限。
### 2.5 新建分支、切换分支
+ 新建分支
新建分支是指在本地库创建一个新的分支(用于开发新的功能),并且将其同步到远程库。主要步骤如下:
1. 从已有的分支创建新的分支如从master分支例如创建一个dev分支 `git checkout -b dev`
2. 创建后可以查看一下当前分支确认当前分支已经切换到dev `git branch dev master`
3. 提交该新的分支到远程仓库: `git push origin dev:devl`
其中: dev为本地新建分支:devl为远程分支如果devl不存在则会自动创建分支。这里dev应该等于devl。
+ 切换分支
切换分支是指将当前工作分支换为另一个分支 。假设本地仓库有master和dev两个分支当前分支是master其实也可以是其他分支。那么切换到dev分支的命令是 `git checkout dev`
注意用户可以使用git branch命令确认当的分支是否已经切换到dev
### 2.6 提交代码(commit)
项目成员在本地编辑代码或修改文件后,可以将新修改的文件提交到本地库:
1. 将新修改的所有文件添加到本地版本库的暂存区stage `git add .`
注意:如果仅添加单个文件,或一类文件,可以: `git add somefile.txt #添加单个文件`
2. 将提交到暂存区的修改提交到本地的当前分支: `git commit -m “myfirstcommit”`
其中“mycommit”中的内容是关于本次提交的说明文字。
注意commit只能将修改的文件提交到本地库与远程库没有关系。
### 2.7 推送代码(push)
项目成员可以将本地提交后的改动,推送到远程库。
假设用户需要将本地库的dev分支推送至远程库的dev分支执行 `git push -u origin dev `
如果用户的当前的本地分支己经是dev, 那么执行: `git push`
如果用户需要将本地的全部分支推送到远程库。那么执行: `git push -all origin`
注意: push代码时会提示输入用户密码请输入红山开源平台登录名和密码即可。 Push代码之前通常要先pull解决冲突后才能提交否则不是最新的文件就提交不上去。
### 2.8 下拉代码(pull)
下拉代码是指从远程版本库获取代码文件到本地分支。
例如用户希望将远程版本库的devl分支下拉到本地的dev分支需要执行 `git pull origin dev devl`
注意下拉代码时可能会出现冲突即两个分支对同一个文件的同一行代码做了不同的修改。此时常利用merge来解决冲突。
### 2.9 合并分支(merge)
合并分支是指将一个分支合并到当前分支。通常有两种情况:
1. 将一个本地分支合并到当前分支:
例如假设用户希望将本地库的devl分支合并到当前分支dev ,命令如下: `git merge dev1`
2. 将一个远程库的分支合并到当前分支:
例如假设用户希望将远程库的devl分支合并到当前分支dev,有多种方法,这里仅给出最基本的:
```bash
git checkout -b temp #新建一个临时分支temp
git pull origin dev1:temp #将远程devl分支下拉到temp分支
git checkout dev #切换到本地dev分支
git merge temp #合并分支(可能 产生冲突合并完成后应删除temp分支)
```
注意:合并分支可能会出现冲突(即两个分支对同一个文件的同一行代码做了不同的修改)。
### 2.10 解决冲突
冲突是两次不同的提交修改了同一行代码导致的,通常表现为两个分支对同一行代码做了不同的修改。 版本冲突主要出现在以下两种情况:
第一种情况在对远程版本库进行pull操作时。
第二种情况对本地版本库的不同分支进行merge操作时。
解决冲突的主要方法有两种:
1. 对于简单的冲突,直接修改有冲突的文件,然后重新提交即可
2. 对于复杂的冲突,需要用**git merge tool**来解决。 复杂的冲突解决方法(基于git merge tool)将在近期提供给大家
### 2.11 常见错误
新手在使用Git时经常遇到各种错误由于平台集成的是标准Git服务(Gitlab),建议大家可以直接在互联网搜索疑难问题的解决办法。 或参考Git使用手册 https://git-scm.com/book/zh/v2 为给大家提供方便,这里先列出一种最常见的错误:
错误1:
```bash
fatal:The remote end hung up unexpectedly
```
Windows环境解决方法在.git/config文件中加入 `[http] postBuffer = 524288000`
Linux环境解决方法在命令行执行 `git config http.postBuffer 524288000`
注:后续我们将列出更多的错误解决办法。
## 3. 致谢
红山开源平台的不断发展主要归功于平台的用户页献者群体。他们不仅是使用者,也是设计者、体验者和测试者,他们为平台献策献力,极大拓展了开发团队的视野、提高了开发团队的效率。可以说,没有他们的页献就没有大家看到的红山开源社区。
如有疏漏请指正,我们将及时更新。

31
index.html Normal file
View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="./static/css/theme.css">
<link rel="shortcut icon" href="./static/img/1na.png">
<title>红山开源社区</title>
</head>
<body>
<nav>
<a href="https://forge.osredm.com/projects">返回主站</a>
</nav>
<div id="app">加载中....</div>
<script>
if (typeof navigator.serviceWorker !== 'undefined') {
navigator.serviceWorker.register('sw.js')
}
window.$docsify = {
//...
relativePath: true,
}
</script>
<script src="./static/js/index.js"></script>
<script src="./static/js/bash.js"></script>
<script src="./static/js/zomm_img.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

858
static/css/theme.css Normal file
View File

@ -0,0 +1,858 @@
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600");
* {
-webkit-font-smoothing: antialiased;
-webkit-overflow-scrolling: touch;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-text-size-adjust: none;
-webkit-touch-callout: none;
box-sizing: border-box;
}
body:not(.ready) {
overflow: hidden;
}
body:not(.ready) [data-cloak],
body:not(.ready) .app-nav,
body:not(.ready) > nav {
display: none;
}
div#app {
font-size: 30px;
font-weight: lighter;
margin: 40vh auto;
text-align: center;
}
div#app:empty::before {
content: 'Loading...';
}
.emoji {
height: 1.2rem;
vertical-align: middle;
}
.progress {
background-color: var(--theme-color, #5091ff);
height: 2px;
left: 0px;
position: fixed;
right: 0px;
top: 0px;
transition: width 0.2s, opacity 0.4s;
width: 0%;
z-index: 999999;
}
.search a:hover {
color: var(--theme-color, #5091ff);
}
.search .search-keyword {
color: var(--theme-color, #5091ff);
font-style: normal;
font-weight: bold;
}
html,
body {
height: 100%;
}
body {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
color: #34495e;
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 15px;
letter-spacing: 0;
margin: 0;
overflow-x: hidden;
}
img {
max-width: 100%;
}
a[disabled] {
cursor: not-allowed;
opacity: 0.6;
}
kbd {
border: solid 1px #ccc;
border-radius: 3px;
display: inline-block;
font-size: 12px !important;
line-height: 12px;
margin-bottom: 3px;
padding: 3px 5px;
vertical-align: middle;
}
li input[type='checkbox'] {
margin: 0 0.2em 0.25em 0;
vertical-align: middle;
}
.app-nav {
margin: 25px 60px 0 0;
position: absolute;
right: 0;
text-align: right;
z-index: 10;
/* navbar dropdown */
}
.app-nav.no-badge {
margin-right: 25px;
}
.app-nav p {
margin: 0;
}
.app-nav > a {
margin: 0 1rem;
padding: 5px 0;
}
.app-nav ul,
.app-nav li {
display: inline-block;
list-style: none;
margin: 0;
}
.app-nav a {
color: inherit;
font-size: 16px;
text-decoration: none;
transition: color 0.3s;
}
.app-nav a:hover {
color: var(--theme-color, #5091ff);
}
.app-nav a.active {
border-bottom: 2px solid var(--theme-color, #5091ff);
color: var(--theme-color, #5091ff);
}
.app-nav li {
display: inline-block;
margin: 0 1rem;
padding: 5px 0;
position: relative;
cursor: pointer;
}
.app-nav li ul {
background-color: #fff;
border: 1px solid #ddd;
border-bottom-color: #ccc;
border-radius: 4px;
box-sizing: border-box;
display: none;
max-height: calc(100vh - 61px);
overflow-y: auto;
padding: 10px 0;
position: absolute;
right: -15px;
text-align: left;
top: 100%;
white-space: nowrap;
}
.app-nav li ul li {
display: block;
font-size: 14px;
line-height: 1rem;
margin: 0;
margin: 8px 14px;
white-space: nowrap;
}
.app-nav li ul a {
display: block;
font-size: inherit;
margin: 0;
padding: 0;
}
.app-nav li ul a.active {
border-bottom: 0;
}
.app-nav li:hover ul {
display: block;
}
.github-corner {
border-bottom: 0;
position: fixed;
right: 0;
text-decoration: none;
top: 0;
z-index: 1;
}
.github-corner:hover .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
.github-corner svg {
color: #fff;
fill: var(--theme-color, #5091ff);
height: 80px;
width: 80px;
}
main {
display: block;
position: relative;
width: 100vw;
height: 100%;
z-index: 0;
}
main.hidden {
display: none;
}
.anchor {
display: inline-block;
text-decoration: none;
transition: all 0.3s;
}
.anchor span {
color: #34495e;
}
.anchor:hover {
text-decoration: underline;
}
.sidebar {
border-right: 1px solid rgba(0,0,0,0.07);
overflow-y: auto;
padding: 40px 0 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
transition: transform 250ms ease-out;
width: 300px;
z-index: 20;
}
.sidebar > h1 {
margin: 0 auto 1rem;
font-size: 1.5rem;
font-weight: 300;
text-align: center;
}
.sidebar > h1 a {
color: inherit;
text-decoration: none;
}
.sidebar > h1 .app-nav {
display: block;
position: static;
}
.sidebar .sidebar-nav {
line-height: 2em;
padding-bottom: 40px;
}
.sidebar li.collapse .app-sub-sidebar {
display: none;
}
.sidebar ul {
margin: 0 0 0 15px;
padding: 0;
}
.sidebar li > p {
font-weight: 700;
margin: 0;
}
.sidebar ul,
.sidebar ul li {
list-style: none;
}
.sidebar ul li a {
border-bottom: none;
display: block;
}
.sidebar ul li ul {
padding-left: 20px;
}
.sidebar::-webkit-scrollbar {
width: 4px;
}
.sidebar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px;
}
.sidebar:hover::-webkit-scrollbar-thumb {
background: rgba(136,136,136,0.4);
}
.sidebar:hover::-webkit-scrollbar-track {
background: rgba(136,136,136,0.1);
}
.sidebar-toggle {
background-color: transparent;
background-color: rgba(255,255,255,0.8);
border: 0;
outline: none;
padding: 10px;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
transition: opacity 0.3s;
width: 284px;
z-index: 30;
cursor: pointer;
}
.sidebar-toggle:hover .sidebar-toggle-button {
opacity: 0.4;
}
.sidebar-toggle span {
background-color: var(--theme-color, #5091ff);
display: block;
margin-bottom: 4px;
width: 16px;
height: 2px;
}
body.sticky .sidebar,
body.sticky .sidebar-toggle {
position: fixed;
}
.content {
padding-top: 60px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 300px;
transition: left 250ms ease;
}
.markdown-section {
margin: 0 auto;
max-width: 80%;
padding: 30px 15px 40px 15px;
position: relative;
}
.markdown-section > * {
box-sizing: border-box;
font-size: inherit;
}
.markdown-section > :first-child {
margin-top: 0 !important;
}
.markdown-section hr {
border: none;
border-bottom: 1px solid #eee;
margin: 2em 0;
}
.markdown-section iframe {
border: 1px solid #eee;
/* fix horizontal overflow on iOS Safari */
width: 1px;
min-width: 100%;
}
.markdown-section table {
border-collapse: collapse;
border-spacing: 0;
display: block;
margin-bottom: 1rem;
overflow: auto;
width: 100%;
}
.markdown-section th {
border: 1px solid #ddd;
font-weight: bold;
padding: 6px 13px;
}
.markdown-section td {
border: 1px solid #ddd;
padding: 6px 13px;
}
.markdown-section tr {
border-top: 1px solid #ccc;
}
.markdown-section tr:nth-child(2n) {
background-color: #f8f8f8;
}
.markdown-section p.tip {
background-color: #f8f8f8;
border-bottom-right-radius: 2px;
border-left: 4px solid #f66;
border-top-right-radius: 2px;
margin: 2em 0;
padding: 12px 24px 12px 30px;
position: relative;
}
.markdown-section p.tip:before {
background-color: #f66;
border-radius: 100%;
color: #fff;
content: '!';
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
font-weight: bold;
left: -12px;
line-height: 20px;
position: absolute;
height: 20px;
width: 20px;
text-align: center;
top: 14px;
}
.markdown-section p.tip code {
background-color: #efefef;
}
.markdown-section p.tip em {
color: #34495e;
}
.markdown-section p.warn {
background: rgba(66,185,131,0.1);
border-radius: 2px;
padding: 1rem;
}
.markdown-section ul.task-list > li {
list-style-type: none;
}
body.close .sidebar {
transform: translateX(-300px);
}
body.close .sidebar-toggle {
width: auto;
}
body.close .content {
left: 0;
}
@media print {
.github-corner,
.sidebar-toggle,
.sidebar,
.app-nav {
display: none;
}
}
@media screen and (max-width: 768px) {
.github-corner,
.sidebar-toggle,
.sidebar {
position: fixed;
}
.app-nav {
margin-top: 16px;
}
.app-nav li ul {
top: 30px;
}
main {
height: auto;
min-height: 100vh;
overflow-x: hidden;
}
.sidebar {
left: -300px;
transition: transform 250ms ease-out;
}
.content {
left: 0;
max-width: 100vw;
position: static;
padding-top: 20px;
transition: transform 250ms ease;
}
.app-nav,
.github-corner {
transition: transform 250ms ease-out;
}
.sidebar-toggle {
background-color: transparent;
width: auto;
padding: 30px 30px 10px 10px;
}
body.close .sidebar {
transform: translateX(300px);
}
body.close .sidebar-toggle {
background-color: rgba(255,255,255,0.8);
transition: 1s background-color;
width: 284px;
padding: 10px;
}
body.close .content {
transform: translateX(300px);
}
body.close .app-nav,
body.close .github-corner {
display: none;
}
.github-corner:hover .octo-arm {
-webkit-animation: none;
animation: none;
}
.github-corner .octo-arm {
-webkit-animation: octocat-wave 560ms ease-in-out;
animation: octocat-wave 560ms ease-in-out;
}
}
@-webkit-keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
@keyframes octocat-wave {
0%, 100% {
transform: rotate(0);
}
20%, 60% {
transform: rotate(-25deg);
}
40%, 80% {
transform: rotate(10deg);
}
}
section.cover {
align-items: center;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100vh;
width: 100vw;
display: none;
}
section.cover.show {
display: flex;
}
section.cover.has-mask .mask {
background-color: #fff;
opacity: 0.8;
position: absolute;
top: 0;
height: 100%;
width: 100%;
}
section.cover .cover-main {
flex: 1;
margin: -20px 16px 0;
text-align: center;
position: relative;
}
section.cover a {
color: inherit;
text-decoration: none;
}
section.cover a:hover {
text-decoration: none;
}
section.cover p {
line-height: 1.5rem;
margin: 1em 0;
}
section.cover h1 {
color: inherit;
font-size: 2.5rem;
font-weight: 300;
margin: 0.625rem 0 2.5rem;
position: relative;
text-align: center;
}
section.cover h1 a {
display: block;
}
section.cover h1 small {
bottom: -0.4375rem;
font-size: 1rem;
position: absolute;
}
section.cover blockquote {
font-size: 1.5rem;
text-align: center;
}
section.cover ul {
line-height: 1.8;
list-style-type: none;
margin: 1em auto;
max-width: 500px;
padding: 0;
}
section.cover .cover-main > p:last-child a {
border-color: var(--theme-color, #5091ff);
border-radius: 2rem;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: var(--theme-color, #5091ff);
display: inline-block;
font-size: 1.05rem;
letter-spacing: 0.1rem;
margin: 0.5rem 1rem;
padding: 0.75em 2rem;
text-decoration: none;
transition: all 0.15s ease;
}
section.cover .cover-main > p:last-child a:last-child {
background-color: var(--theme-color, #5091ff);
color: #fff;
}
section.cover .cover-main > p:last-child a:last-child:hover {
color: inherit;
opacity: 0.8;
}
section.cover .cover-main > p:last-child a:hover {
color: inherit;
}
section.cover blockquote > p > a {
border-bottom: 2px solid var(--theme-color, #5091ff);
transition: color 0.3s;
}
section.cover blockquote > p > a:hover {
color: var(--theme-color, #5091ff);
}
body {
background-color: #fff;
}
/* sidebar */
.sidebar {
background-color: #fff;
color: #364149;
}
.sidebar li {
margin: 6px 0 6px 0;
}
.sidebar ul li a {
color: #505d6b;
font-size: 14px;
font-weight: normal;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.sidebar ul li a:hover {
text-decoration: underline;
}
.sidebar ul li ul {
padding: 0;
}
.sidebar ul li.active > a {
border-right: 2px solid;
color: var(--theme-color, #5091ff);
font-weight: 600;
}
.app-sub-sidebar li::before {
content: '-';
padding-right: 4px;
float: left;
}
/* markdown content found on pages */
.markdown-section h1,
.markdown-section h2,
.markdown-section h3,
.markdown-section h4,
.markdown-section strong {
color: #2c3e50;
font-weight: 600;
}
.markdown-section a {
color: var(--theme-color, #5091ff);
font-weight: 600;
}
.markdown-section h1 {
font-size: 2rem;
margin: 0 0 1rem;
}
.markdown-section h2 {
font-size: 1.75rem;
margin: 45px 0 0.8rem;
}
.markdown-section h3 {
font-size: 1.5rem;
margin: 40px 0 0.6rem;
}
.markdown-section h4 {
font-size: 1.25rem;
}
.markdown-section h5 {
font-size: 1rem;
}
.markdown-section h6 {
color: #777;
font-size: 1rem;
}
.markdown-section figure,
.markdown-section p {
margin: 1.2em 0;
}
.markdown-section p,
.markdown-section ul,
.markdown-section ol {
line-height: 1.6rem;
word-spacing: 0.05rem;
}
.markdown-section ul,
.markdown-section ol {
padding-left: 1.5rem;
}
.markdown-section blockquote {
border-left: 4px solid var(--theme-color, #5091ff);
color: #858585;
margin: 2em 0;
padding-left: 20px;
}
.markdown-section blockquote p {
font-weight: 600;
margin-left: 0;
}
.markdown-section iframe {
margin: 1em 0;
}
.markdown-section em {
color: #7f8c8d;
}
.markdown-section code,
.markdown-section pre,
.markdown-section output::after {
font-family: 'Roboto Mono', Monaco, courier, monospace;
}
.markdown-section code,
.markdown-section pre {
background-color: #f8f8f8;
}
.markdown-section pre,
.markdown-section output {
margin: 1.2em 0;
position: relative;
}
.markdown-section pre > code,
.markdown-section output {
border-radius: 2px;
display: block;
}
.markdown-section pre > code,
.markdown-section output::after {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
}
.markdown-section code {
border-radius: 2px;
color: #e96900;
margin: 0 2px;
padding: 3px 5px;
white-space: pre-wrap;
}
.markdown-section > :not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) code {
font-size: 0.8rem;
}
.markdown-section pre {
padding: 0 1.4rem;
line-height: 1.5rem;
overflow: auto;
word-wrap: normal;
}
.markdown-section pre > code {
color: #525252;
font-size: 0.8rem;
padding: 2.2em 5px;
line-height: inherit;
margin: 0 2px;
max-width: inherit;
overflow: inherit;
white-space: inherit;
}
.markdown-section output {
padding: 1.7rem 1.4rem;
border: 1px dotted #ccc;
}
.markdown-section output > :first-child {
margin-top: 0;
}
.markdown-section output > :last-child {
margin-bottom: 0;
}
.markdown-section code::after,
.markdown-section code::before,
.markdown-section output::after,
.markdown-section output::before {
letter-spacing: 0.05rem;
}
.markdown-section pre::after,
.markdown-section output::after {
color: #ccc;
font-size: 0.6rem;
font-weight: 600;
height: 15px;
line-height: 15px;
padding: 5px 10px 0;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
.markdown-section pre::after,
.markdown-section output::after {
content: attr(data-lang);
}
/* code highlight */
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8e908c;
}
.token.namespace {
opacity: 0.7;
}
.token.boolean,
.token.number {
color: #c76b29;
}
.token.punctuation {
color: #525252;
}
.token.property {
color: #c08b30;
}
.token.tag {
color: #2973b7;
}
.token.string {
color: var(--theme-color, #5091ff);
}
.token.selector {
color: #6679cc;
}
.token.attr-name {
color: #2973b7;
}
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #22a2c9;
}
.token.attr-value,
.token.control,
.token.directive,
.token.unit {
color: var(--theme-color, #5091ff);
}
.token.keyword,
.token.function {
color: #e96900;
}
.token.statement,
.token.regex,
.token.atrule {
color: #22a2c9;
}
.token.placeholder,
.token.variable {
color: #3d8fd1;
}
.token.deleted {
text-decoration: line-through;
}
.token.inserted {
border-bottom: 1px dotted #202746;
text-decoration: none;
}
.token.italic {
font-style: italic;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.important {
color: #c94922;
}
.token.entity {
cursor: help;
}
code .token {
-moz-osx-font-smoothing: initial;
-webkit-font-smoothing: initial;
min-height: 1.5rem;
position: relative;
left: auto;
}

BIN
static/img/1na.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
static/img/3239.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 KiB

BIN
static/img/3240.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

BIN
static/img/3241.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

BIN
static/img/3242.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

BIN
static/img/3243.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

BIN
static/img/3244.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

BIN
static/img/3245.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
static/img/3246.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

BIN
static/img/3247.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

BIN
static/img/3251.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

BIN
static/img/3252.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

BIN
static/img/3253.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

BIN
static/img/3254.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
static/img/3255.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

BIN
static/img/3256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
static/img/3257.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
static/img/3258.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
static/img/3259.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

BIN
static/img/3260.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

BIN
static/img/3261.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

BIN
static/img/3262.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

BIN
static/img/3263.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
static/img/3264.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

BIN
static/img/3265.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

BIN
static/img/3266.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

BIN
static/img/3267.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

227
static/js/bash.js Normal file
View File

@ -0,0 +1,227 @@
(function (Prism) {
// $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|'
// + LC_ALL, RANDOM, REPLY, SECONDS.
// + make sure PS1..4 are here as they are not always set,
// - some useless things.
var envVars = '\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b';
var commandAfterHeredoc = {
pattern: /(^(["']?)\w+\2)[ \t]+\S.*/,
lookbehind: true,
alias: 'punctuation', // this looks reasonably well in all themes
inside: null // see below
};
var insideString = {
'bash': commandAfterHeredoc,
'environment': {
pattern: RegExp('\\$' + envVars),
alias: 'constant'
},
'variable': [
// [0]: Arithmetic Environment
{
pattern: /\$?\(\([\s\S]+?\)\)/,
greedy: true,
inside: {
// If there is a $ sign at the beginning highlight $(( and )) as variable
'variable': [
{
pattern: /(^\$\(\([\s\S]+)\)\)/,
lookbehind: true
},
/^\$\(\(/
],
'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,
// Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic
'operator': /--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,
// If there is no $ sign at the beginning highlight (( and )) as punctuation
'punctuation': /\(\(?|\)\)?|,|;/
}
},
// [1]: Command Substitution
{
pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,
greedy: true,
inside: {
'variable': /^\$\(|^`|\)$|`$/
}
},
// [2]: Brace expansion
{
pattern: /\$\{[^}]+\}/,
greedy: true,
inside: {
'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,
'punctuation': /[\[\]]/,
'environment': {
pattern: RegExp('(\\{)' + envVars),
lookbehind: true,
alias: 'constant'
}
}
},
/\$(?:\w+|[#?*!@$])/
],
// Escape sequences from echo and printf's manuals, and escaped quotes.
'entity': /\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/
};
Prism.languages.bash = {
'shebang': {
pattern: /^#!\s*\/.*/,
alias: 'important'
},
'comment': {
pattern: /(^|[^"{\\$])#.*/,
lookbehind: true
},
'function-name': [
// a) function foo {
// b) foo() {
// c) function foo() {
// but not “foo {”
{
// a) and c)
pattern: /(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,
lookbehind: true,
alias: 'function'
},
{
// b)
pattern: /\b[\w-]+(?=\s*\(\s*\)\s*\{)/,
alias: 'function'
}
],
// Highlight variable names as variables in for and select beginnings.
'for-or-select': {
pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/,
alias: 'variable',
lookbehind: true
},
// Highlight variable names as variables in the left-hand part
// of assignments (“=” and “+=”).
'assign-left': {
pattern: /(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,
inside: {
'environment': {
pattern: RegExp('(^|[\\s;|&]|[<>]\\()' + envVars),
lookbehind: true,
alias: 'constant'
}
},
alias: 'variable',
lookbehind: true
},
'string': [
// Support for Here-documents https://en.wikipedia.org/wiki/Here_document
{
pattern: /((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,
lookbehind: true,
greedy: true,
inside: insideString
},
// Here-document with quotes around the tag
// → No expansion (so no “inside”).
{
pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,
lookbehind: true,
greedy: true,
inside: {
'bash': commandAfterHeredoc
}
},
// “Normal” string
{
// https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
pattern: /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,
lookbehind: true,
greedy: true,
inside: insideString
},
{
// https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html
pattern: /(^|[^$\\])'[^']*'/,
lookbehind: true,
greedy: true
},
{
// https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html
pattern: /\$'(?:[^'\\]|\\[\s\S])*'/,
greedy: true,
inside: {
'entity': insideString.entity
}
}
],
'environment': {
pattern: RegExp('\\$?' + envVars),
alias: 'constant'
},
'variable': insideString.variable,
'function': {
pattern: /(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,
lookbehind: true
},
'keyword': {
pattern: /(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,
lookbehind: true
},
// https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html
'builtin': {
pattern: /(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,
lookbehind: true,
// Alias added to make those easier to distinguish from strings.
alias: 'class-name'
},
'boolean': {
pattern: /(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,
lookbehind: true
},
'file-descriptor': {
pattern: /\B&\d\b/,
alias: 'important'
},
'operator': {
// Lots of redirections here, but not just that.
pattern: /\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,
inside: {
'file-descriptor': {
pattern: /^\d/,
alias: 'important'
}
}
},
'punctuation': /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,
'number': {
pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,
lookbehind: true
}
};
commandAfterHeredoc.inside = Prism.languages.bash;
/* Patterns in command substitution. */
var toBeCopied = [
'comment',
'function-name',
'for-or-select',
'assign-left',
'string',
'environment',
'function',
'keyword',
'builtin',
'boolean',
'file-descriptor',
'operator',
'punctuation',
'number'
];
var inside = insideString.variable[1].inside;
for (var i = 0; i < toBeCopied.length; i++) {
inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]];
}
Prism.languages.shell = Prism.languages.bash;
}(Prism));

File diff suppressed because one or more lines are too long

1
static/js/index.js Normal file

File diff suppressed because one or more lines are too long

1
static/js/zomm_img.js Normal file

File diff suppressed because one or more lines are too long

83
sw.js Normal file
View File

@ -0,0 +1,83 @@
/* ===========================================================
* docsify sw.js
* ===========================================================
* Copyright 2016 @huxpro
* Licensed under Apache 2.0
* Register service worker.
* ========================================================== */
const RUNTIME = 'docsify'
const HOSTNAME_WHITELIST = [
self.location.hostname,
'fonts.gstatic.com',
'fonts.googleapis.com',
'cdn.jsdelivr.net'
]
// The Util Function to hack URLs of intercepted requests
const getFixedUrl = (req) => {
var now = Date.now()
var url = new URL(req.url)
// 1. fixed http URL
// Just keep syncing with location.protocol
// fetch(httpURL) belongs to active mixed content.
// And fetch(httpRequest) is not supported yet.
url.protocol = self.location.protocol
// 2. add query for caching-busting.
// Github Pages served with Cache-Control: max-age=600
// max-age on mutable content is error-prone, with SW life of bugs can even extend.
// Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
// Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
if (url.hostname === self.location.hostname) {
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
}
return url.href
}
/**
* @Lifecycle Activate
* New one activated when old isnt being used.
*
* waitUntil(): activating ====> activated
*/
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})
/**
* @Functional Fetch
* All network requests are being intercepted here.
*
* void respondWith(Promise<Response> r)
*/
self.addEventListener('fetch', event => {
// Skip some of cross-origin requests, like those for Google Analytics.
if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
// Stale-while-revalidate
// similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
// Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
const cached = caches.match(event.request)
const fixedUrl = getFixedUrl(event.request)
const fetched = fetch(fixedUrl, { cache: 'no-store' })
const fetchedCopy = fetched.then(resp => resp.clone())
// Call respondWith() with whatever we get first.
// If the fetch fails (e.g disconnected), wait for the cache.
// If theres nothing in cache, wait for the fetch.
// If neither yields a response, return offline pages.
event.respondWith(
Promise.race([fetched.catch(_ => cached), cached])
.then(resp => resp || fetched)
.catch(_ => { /* eat any errors */ })
)
// Update the cache with the version we fetched (only for ok status)
event.waitUntil(
Promise.all([fetchedCopy, caches.open(RUNTIME)])
.then(([response, cache]) => response.ok && cache.put(event.request, response))
.catch(_ => { /* eat any errors */ })
)
}
})