From 6e70a1d4df5c7c679af10d73bca12732a646814e Mon Sep 17 00:00:00 2001 From: JiXieShi Date: Thu, 21 Mar 2024 15:25:12 +0800 Subject: [PATCH] Init v3.2 --- .gitignore | 14 + LICENSE | 21 ++ README.md | 112 ++++++ blog.go | 26 ++ config.json | 19 + config/main.go | 109 ++++++ config/system.go | 14 + config/user.go | 37 ++ controller/article.go | 25 ++ controller/category.go | 16 + controller/dashboard.go | 35 ++ controller/extraNav.go | 26 ++ controller/index.go | 35 ++ controller/webhook.go | 61 ++++ go.mod | 4 + go.sum | 9 + models/articles.go | 238 ++++++++++++ models/category.go | 69 ++++ models/common.go | 50 +++ models/extra_nav.go | 31 ++ models/html_template.go | 91 +++++ models/pagination.go | 48 +++ routes/main.go | 24 ++ themes/blog/article.html | 55 +++ themes/blog/categories.html | 17 + themes/blog/dashboard.html | 45 +++ themes/blog/extraNav.html | 7 + themes/blog/index.html | 55 +++ themes/blog/layouts/footer.html | 15 + themes/blog/layouts/head.html | 69 ++++ themes/blog/public/css/app.css | 477 +++++++++++++++++++++++++ themes/blog/public/css/prism.css | 5 + themes/blog/public/fonts/josefin.woff2 | Bin 0 -> 33880 bytes themes/blog/public/img/date.svg | 1 + themes/blog/public/img/favicon.ico | Bin 0 -> 9662 bytes themes/blog/public/img/favicon.svg | 1 + themes/blog/public/img/folder.svg | 1 + themes/blog/public/img/search.svg | 1 + themes/blog/public/img/tag.svg | 1 + themes/blog/public/js/marked.min.js | 6 + themes/blog/public/js/prism.js | 27 ++ utils/cmd.go | 15 + utils/cmd_test.go | 13 + utils/file.go | 65 ++++ utils/git.go | 19 + utils/git_test.go | 14 + utils/short_url.go | 43 +++ utils/short_url_test.go | 14 + 配置说明.md | 35 ++ 49 files changed, 2115 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 blog.go create mode 100644 config.json create mode 100644 config/main.go create mode 100644 config/system.go create mode 100644 config/user.go create mode 100644 controller/article.go create mode 100644 controller/category.go create mode 100644 controller/dashboard.go create mode 100644 controller/extraNav.go create mode 100644 controller/index.go create mode 100644 controller/webhook.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 models/articles.go create mode 100644 models/category.go create mode 100644 models/common.go create mode 100644 models/extra_nav.go create mode 100644 models/html_template.go create mode 100644 models/pagination.go create mode 100644 routes/main.go create mode 100644 themes/blog/article.html create mode 100644 themes/blog/categories.html create mode 100644 themes/blog/dashboard.html create mode 100644 themes/blog/extraNav.html create mode 100644 themes/blog/index.html create mode 100644 themes/blog/layouts/footer.html create mode 100644 themes/blog/layouts/head.html create mode 100644 themes/blog/public/css/app.css create mode 100644 themes/blog/public/css/prism.css create mode 100644 themes/blog/public/fonts/josefin.woff2 create mode 100644 themes/blog/public/img/date.svg create mode 100644 themes/blog/public/img/favicon.ico create mode 100644 themes/blog/public/img/favicon.svg create mode 100644 themes/blog/public/img/folder.svg create mode 100644 themes/blog/public/img/search.svg create mode 100644 themes/blog/public/img/tag.svg create mode 100644 themes/blog/public/js/marked.min.js create mode 100644 themes/blog/public/js/prism.js create mode 100644 utils/cmd.go create mode 100644 utils/cmd_test.go create mode 100644 utils/file.go create mode 100644 utils/git.go create mode 100644 utils/git_test.go create mode 100644 utils/short_url.go create mode 100644 utils/short_url_test.go create mode 100644 配置说明.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..975caa0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.DS_Store + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw* +web +images +cache +go_lib diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b137289 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 xusenlin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..32acbc4 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# Blog + +> Blog 是基于 go 语言开发的,不依赖第三方 go 库,适合用来学习和展示 markdown 文档的精美博客。 + + +:chestnut: [JiXieShi](http://www.starss.cc/) (个人博客,正在使用) +--- + +## 项目背景 +博客从最早的静态 Html+Css 主页到 Wordpress 、Typecho 、Hexo 、Hugo 一路尝试过来,虽然他们都是很优秀的开源项目,但是没有一款符合我内心真正的诉求。 +他们有的要么太重了要么部署不方便要么对存储的文章不友好,我就放弃了之前在Typecho上的文章,同时调整分类也不那么灵活,有的迁移也不方便。 +自己太懒,不想自己做文章备份,不想安装数据库,快速响应也是必须的,所以才有了用 GOLANG 来写一个简单博客的想法。 +当然,自己的这个项目并不能和这些优秀的开源项目相比较,它只是符合我自己的诉求顺便用来学习GOLANG的项目。(写文章也能增加github的活跃度,逃 :)) + +## Blog 在做什么 + + +简单来说,Blog 会使用 git 将你的 .md 文档仓库克隆到当前目录下, 然后并行加载和解析文章关键信息并生成内容,呈现一个博客站点。 +当你向你的 git 仓库提交文章的时候,你可以设置 webHooks 来自动通知 Blog 更新同步文章,或者可以在仪表盘里手动更新文章。 + + +## 安装 +你可以克隆当前仓库,然后在 JSON 文件里面配置好你文档的 Git 地址和 WebHook 秘钥,编译源代码并放入后台运行。 + + +## 使用 + +- 配置好 config.json 文件,详细的配置说明文件在当前仓库根目录的《配置说明.md》 +- 新建一个 git 仓库,用来存放你的文章,但是对你的目录结构有一些要求 +如下: +``` + |-- assets //博客静态文件,存放一些图片资源,方便显示到文档里 + |-- content + | |-- GOLANG //分类目录 + | |-- GOLANG基础 // 子分类目录,但是在页面上不会产生分类目录 + | |--- GOLANG基础语法.md + | |-- 其他分类 + | |--- xxx.md + |-- extra_nav // Blog只会有 Blog Categories 两个导航,其他导航可以放到这个目录下,比如自己的简历,作品之类的 + +``` +content目录下的一级目录代表一个分类,如果一级目录下有子级目录也不会产生新的分类,子级目录的文档也会属于一级目录的分类。 + +- 每一篇文章的开头可以配置一些文章的属性,具体可以看 配置说明.md +如下: +``` + ```json + { + "date":"2019.01.02 14:33",//最少需要 + "tags": ["BLOG","其它tag"],//可以不填,不过最好添加一些tag,后面可以做一些好玩的东西。 + "title": "文章的标题,一般不用填写,默认使用文件名", + "description": "文章描述,不填写自动取正文200个字,可以在app.json中配置", + "author": "JiXieShi", //文章作者,可以不用填写,现在也没有使用到 + "musicId":"网易云歌单ID" //文章的配歌 + } + ``` +``` +我会根据关键字```json来解析,不用担心这个会显示到文章内容里面,我在解析的时候就将它去掉了。 +如果不再文章前面添加这一段json也是可以的,不过我不建议这么做,因为这样就和V1.0版本没什么区别了,没有了文章属性,排序都是个问题。 +最后,mac markdown 文章编辑器推荐 Typora。 + +> 提示:```json 前面不能有其它字符。 + +- 切换主题色和搜索文章在仪表盘里,访问/admin 可以查看仪表盘, +如果不想让别人知道你的仪表盘地址可以自己配置dashboard字段。 + + +## TODO +- [x] 1.移动端更好的适配 +- [x] 2.根目录可以添加其他文件生成导航 +- [x] 3.仪表盘支持切换主题色 +- [x] 4.仪表盘支持搜索 +- [x] 5.tags的展示 +- [x] 6.仪表盘添加手动更新文章功能 +- [x] 7.添加webHook支持(去掉自动更新) +- [x] 8.添加评论支持(在配置里开启,所有评论都会储存在仓库的Issues) +- [x] 9.支持网易云音乐 +- [x] 10.支持自定义切换主题 + +> 后续尽善尽美之后,我可能会提供其他漂亮的主题皮肤,也欢迎大家参与进来。 + +## 特性 + +1. 响应迅速 ---没有什么依赖,得益于GOLANG的运行速度,部署在阿里云的博客平均响应在50毫秒内。 +2. 迁移方便 ---GOLANG交叉编译可以方便的发布二进制文件到不同的操作系统,执行二进制文件并克隆博客文件即可运行你的博客。 +3. 小巧精美 ---非常简单的代码方便学习和改造,即使有一天你厌倦Blog,你的文章也能很好的迁移和阅读。 +4. 分类调整 ---随时调整你的文章分类,你可以把一个文件夹里所有的东西移动到其他分类里的某个地方,不管有多少层级,分类发生了什么翻天覆地的变化,下一次更新就能展示。 + +## 更新日志 + +### V3.2 +* 加入Tag搜索和展示 + +### V3.1 +* 去掉标题的.MD后缀 +* 网易云音乐改为左下悬浮,同时由音乐id改为歌单id +* 增加主题配置项(ps:虽然只有一个简单主题) + +### V3.0 +* 完全重构,添加了短链,美化了 URL +* 自动完成克隆工作 +* 添加了网易云音乐功能 +* 文件自动生成导航(导航排序通过时间可自定义) + + + + +## 感谢 + +## License + +MIT © Richard McRichface diff --git a/blog.go b/blog.go new file mode 100644 index 0000000..658a662 --- /dev/null +++ b/blog.go @@ -0,0 +1,26 @@ +package main + +import ( + "blog/config" + "blog/models" + "blog/routes" + "fmt" + "net/http" + "strconv" +) + +func init() { + models.CompiledContent() //克隆或者更新文章、递归生成文章、导航、短链 Map、加载模板 +} + +func main() { + + routes.InitRoute() + fmt.Printf("Version:v%v \n", config.Cfg.Version) + fmt.Printf("ListenAndServe On Port %v \n", config.Cfg.Port) + fmt.Printf("Dashboard On Path %v \n", config.Cfg.Dashboard) + fmt.Printf("UpdateArticle's GitHookUrl: %v Secret: %v \n", config.Cfg.GitHookUrl, config.Cfg.WebHookSecret) + if err := http.ListenAndServe(":"+strconv.Itoa(config.Cfg.Port), nil); err != nil { + fmt.Println("ServeErr:", err) + } +} diff --git a/config.json b/config.json new file mode 100644 index 0000000..d20b24c --- /dev/null +++ b/config.json @@ -0,0 +1,19 @@ +{ + "port": 8080, + "pageSize": 3, + "descriptionLen": 200, + "author": "JiXieShi", + "icp": "", + "webHookSecret": "jixieshi", + "categoryDisplayQuantity": 6, + "utterancesRepo": "jixishi/blog_docs", + "timeLayout": "2006.01.02 15:04", + "siteName": "JiXieShi's Blog", + "htmlKeywords": "forest blog,Golang,ARM,BE6,前端,硬件", + "htmlDescription": "JiXieShi's Personal blog", + "documentGitUrl": "https://github.com/jixishi/blog_docs.git", + "themePath": "/blog", + "themeColor": "#2196f3", + "dashboard": "adminjxs", + "themeOption": ["#673ab7","#f44336","#9c27b0","#2196f3","#607d8b","#795548"] +} diff --git a/config/main.go b/config/main.go new file mode 100644 index 0000000..8381c6e --- /dev/null +++ b/config/main.go @@ -0,0 +1,109 @@ +package config + +import ( + "blog/utils" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + "strings" +) + +type Config struct { + userConfig + systemConfig +} + +// + +var Cfg Config + +func init() { + var err error + + Cfg.CurrentDir, err = os.Getwd() + if err != nil { + panic(err) + } + + configFile, err := ioutil.ReadFile(Cfg.CurrentDir + "/config.json") + if err != nil { + panic(err) + } + + err = json.Unmarshal(configFile, &Cfg) + if err != nil { + panic(err) + } + + if "" == Cfg.Dashboard || + !strings.HasPrefix(Cfg.Dashboard, "/") { + Cfg.Dashboard = "/admin" + } + if "" == Cfg.ThemePath || + !strings.HasPrefix(Cfg.ThemePath, "/") { + Cfg.ThemesDir = Cfg.CurrentDir + "/themes/blog" //+ Cfg.ThemePath + } else { + Cfg.ThemesDir = Cfg.CurrentDir + "/themes" + Cfg.ThemePath + } + repoName, err := utils.GetRepoName(Cfg.DocumentGitUrl) + + if err != nil { + panic(err) + } + + Cfg.AppName = "WebServer" + Cfg.Version = 3.2 + Cfg.DocumentDir = Cfg.CurrentDir + "/" + repoName + Cfg.GitHookUrl = "/api/git_push_hook" + Cfg.AppRepository = "https://gitea.starss.cc/JiXieShi/Blog" +} + +func Initial() { + if _, err := exec.LookPath("git"); err != nil { + fmt.Println("请先安装git") + panic(err) + } + if !utils.IsDir(Cfg.DocumentDir) { + fmt.Println("正在克隆文档仓库,请稍等...") + out, err := utils.RunCmdByDir(Cfg.CurrentDir, "git", "clone", Cfg.DocumentGitUrl) + if err != nil { + panic(err) + } + fmt.Println(out) + } else { + out, err := utils.RunCmdByDir(Cfg.DocumentDir, "git", "pull") + fmt.Println(out) + if err != nil { + panic(err) + } + + } + if err := checkDocDirAndBindConfig(&Cfg); err != nil { + fmt.Println("文档缺少必要的目录") + panic(err) + } + + imgDir := Cfg.CurrentDir + "/images" + if !utils.IsDir(imgDir) { + if os.Mkdir(imgDir, os.ModePerm) != nil { + panic("生成images目录失败!") + } + } +} + +func checkDocDirAndBindConfig(cfg *Config) error { + dirs := []string{"assets", "content", "extra_nav"} + for _, dir := range dirs { + absoluteDir := Cfg.DocumentDir + "/" + dir + if !utils.IsDir(absoluteDir) { + return errors.New("documents cannot lack " + absoluteDir + " dir") + } + } + cfg.DocumentAssetsDir = cfg.DocumentDir + "/assets" + cfg.DocumentContentDir = cfg.DocumentDir + "/content" + cfg.DocumentExtraNavDir = cfg.DocumentDir + "/extra_nav" + return nil +} diff --git a/config/system.go b/config/system.go new file mode 100644 index 0000000..74bc1cf --- /dev/null +++ b/config/system.go @@ -0,0 +1,14 @@ +package config + +type systemConfig struct { + AppName string + Version float32 + CurrentDir string + ThemesDir string + GitHookUrl string + AppRepository string + DocumentDir string + DocumentAssetsDir string + DocumentContentDir string + DocumentExtraNavDir string +} diff --git a/config/user.go b/config/user.go new file mode 100644 index 0000000..9bd2334 --- /dev/null +++ b/config/user.go @@ -0,0 +1,37 @@ +package config + +type userConfig struct { + SiteName string `json:"siteName"` + + Author string `json:"author"` + + Icp string `json:"icp"` + + TimeLayout string `json:"timeLayout"` + + Port int `json:"port"` + + WebHookSecret string `json:"webHookSecret"` + + CategoryDisplayQuantity int `json:"categoryDisplayQuantity"` + + UtterancesRepo string `json:"utterancesRepo"` + + PageSize int `json:"pageSize"` + + DescriptionLen int `json:"descriptionLen"` + + DocumentGitUrl string `json:"documentGitUrl"` + + HtmlKeywords string `json:"htmlKeywords"` + + HtmlDescription string `json:"htmlDescription"` + + ThemePath string `json:"themePath"` + + ThemeColor string `json:"themeColor"` + + ThemeOption []string `json:"themeOption"` + + Dashboard string `json:"dashboard"` +} diff --git a/controller/article.go b/controller/article.go new file mode 100644 index 0000000..2433eb8 --- /dev/null +++ b/controller/article.go @@ -0,0 +1,25 @@ +package controller + +import ( + "blog/models" + "net/http" +) + +func Article(w http.ResponseWriter, r *http.Request) { + articleTemplate := models.Template.Article + + if err := r.ParseForm(); err != nil { + articleTemplate.WriteError(w, err) + } + key := r.Form.Get("key") + + path := models.ArticleShortUrlMap[key] + + articleDetail, err := models.ReadArticleDetail(path) + + if err != nil { + articleTemplate.WriteError(w, err) + } + + articleTemplate.WriteData(w, models.BuildViewData("Article", articleDetail)) +} diff --git a/controller/category.go b/controller/category.go new file mode 100644 index 0000000..d905867 --- /dev/null +++ b/controller/category.go @@ -0,0 +1,16 @@ +package controller + +import ( + "blog/config" + "blog/models" + "net/http" +) + +func Category(w http.ResponseWriter, r *http.Request) { + + categoriesTemplate := models.Template.Categories + + result := models.GroupByCategory(&models.ArticleList, config.Cfg.CategoryDisplayQuantity) + + categoriesTemplate.WriteData(w, models.BuildViewData("Categories", result)) +} diff --git a/controller/dashboard.go b/controller/dashboard.go new file mode 100644 index 0000000..9622dc9 --- /dev/null +++ b/controller/dashboard.go @@ -0,0 +1,35 @@ +package controller + +import ( + "blog/config" + "blog/models" + "net/http" + "strconv" +) + +func Dashboard(w http.ResponseWriter, r *http.Request) { + + var dashboardMsg []string + dashboardTemplate := models.Template.Dashboard + + if err := r.ParseForm(); err != nil { + dashboardTemplate.WriteError(w, err) + } + + index, err := strconv.Atoi(r.Form.Get("theme")) + if err == nil && index < len(config.Cfg.ThemeOption) { + config.Cfg.ThemeColor = config.Cfg.ThemeOption[index] + dashboardMsg = append(dashboardMsg, "颜色切换成功!") + } + + action := r.Form.Get("action") + if "updateArticle" == action { + models.CompiledContent() + dashboardMsg = append(dashboardMsg, "文章更新成功!") + } + + dashboardTemplate.WriteData(w, models.BuildViewData("Dashboard", map[string]interface{}{ + "msg": dashboardMsg, + })) + +} diff --git a/controller/extraNav.go b/controller/extraNav.go new file mode 100644 index 0000000..fd2e463 --- /dev/null +++ b/controller/extraNav.go @@ -0,0 +1,26 @@ +package controller + +import ( + "blog/models" + "net/http" +) + +func ExtraNav(w http.ResponseWriter, r *http.Request) { + extraNavTemplate := models.Template.ExtraNav + + if err := r.ParseForm(); err != nil { + extraNavTemplate.WriteError(w, err) + } + + name := r.Form.Get("name") + for _, nav := range models.Navigation { + if nav.Title == name { + articleDetail, err := models.ReadArticleDetail(nav.Path) + if err != nil { + extraNavTemplate.WriteError(w, err) + } + extraNavTemplate.WriteData(w, models.BuildViewData(nav.Title, articleDetail)) + return + } + } +} diff --git a/controller/index.go b/controller/index.go new file mode 100644 index 0000000..8dc1c4f --- /dev/null +++ b/controller/index.go @@ -0,0 +1,35 @@ +package controller + +import ( + "blog/config" + "blog/models" + "net/http" + "strconv" +) + +func Index(w http.ResponseWriter, r *http.Request) { + + indexTemplate := models.Template.Index + + if err := r.ParseForm(); err != nil { + indexTemplate.WriteError(w, err) + } + + page, err := strconv.Atoi(r.Form.Get("page")) + if err != nil { + page = 1 + } + articles := models.ArticleList + + search := r.Form.Get("search") + category := r.Form.Get("category") + tag := r.Form.Get("tag") + + if search != "" || category != "" || tag != "" { + articles = models.ArticleSearch(&articles, search, category, tag) + } + + result := models.Pagination(&articles, page, config.Cfg.PageSize) + + indexTemplate.WriteData(w, models.BuildViewData("Blog", result)) +} diff --git a/controller/webhook.go b/controller/webhook.go new file mode 100644 index 0000000..0de2485 --- /dev/null +++ b/controller/webhook.go @@ -0,0 +1,61 @@ +package controller + +import ( + "blog/models" + "fmt" + "net/http" +) + +func GithubHook(w http.ResponseWriter, r *http.Request) { + + //err := r.ParseForm() + //if err != nil { + // SedResponse(w, err.Error()) + // return + //} + // + //if "" == config.Cfg.WebHookSecret || "push" != r.Header.Get("x-github-event") { + // SedResponse(w, "No Configuration WebHookSecret Or Not Pushing Events") + // log.Println("No Configuration WebHookSecret Or Not Pushing Events") + // return + //} + // + //sign := r.Header.Get("X-Hub-Signature") + // + //bodyContent, err := ioutil.ReadAll(r.Body) + // + //if err != nil { + // SedResponse(w, err.Error()) + // log.Println("WebHook err:" + err.Error()) + // return + //} + // + //if err = r.Body.Close(); err != nil { + // SedResponse(w, err.Error()) + // log.Println("WebHook err:" + err.Error()) + // return + //} + // + //mac := hmac.New(sha1.New, []byte(config.Cfg.WebHookSecret)) + //mac.Write(bodyContent) + //expectedHash := "sha1=" + hex.EncodeToString(mac.Sum(nil)) + // + //if sign != expectedHash { + // SedResponse(w, "WebHook err:Signature does not match") + // log.Println("WebHook err:Signature does not match") + // return + //} + + SedResponse(w, "ok") + + models.CompiledContent() +} + +func SedResponse(w http.ResponseWriter, msg string) { + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json; charset=utf-8") + _, err := w.Write([]byte(`{"msg": "` + msg + `"}`)) + if err != nil { + fmt.Println(err) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3bf03a4 --- /dev/null +++ b/go.mod @@ -0,0 +1,4 @@ +module blog + +go 1.13 + diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1d9a30c --- /dev/null +++ b/go.sum @@ -0,0 +1,9 @@ +github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/models/articles.go b/models/articles.go new file mode 100644 index 0000000..964daf2 --- /dev/null +++ b/models/articles.go @@ -0,0 +1,238 @@ +package models + +import ( + "blog/config" + "blog/utils" + "bytes" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "sort" + "strings" + "time" +) + +type Time time.Time + +type Article struct { + Title string `json:"title"` + Date Time `json:"date"` + Description string `json:"description"` + Tags []string `json:"tags"` + Author string `json:"author"` + MusicId string `json:"musicId"` + Path string + ShortUrl string + Category string +} + +type Articles []Article + +type ArticleDetail struct { + Article + Body string +} + +func initArticlesAndImages(dir string) (Articles, map[string]string, error) { + var articles Articles + shortUrlMap := make(map[string]string) + + articles, err := RecursiveReadArticles(dir) + if err != nil { + return articles, shortUrlMap, err + } + sort.Sort(articles) + for i := len(articles) - 1; i >= 0; i-- { + //这里必须使用倒序的方式生成 shortUrl,因为如果有相同的文章标题, + // 倒序会将最老的文章优先生成shortUrl,保证和之前的 shortUrl一样 + article := articles[i] + keyword := utils.GenerateShortUrl(article.Title, func(url, keyword string) bool { + //保证 keyword 唯一 + _, ok := shortUrlMap[keyword] + return !ok + }) + articles[i].ShortUrl = keyword + shortUrlMap[keyword] = article.Path + } + return articles, shortUrlMap, nil +} + +func ArticleSearch(articles *Articles, search string, category string, tag string) Articles { + + var articleList Articles + for _, article := range *articles { + + pass := true + + if search != "" && strings.Index(article.Title, search) == -1 { + pass = false + } + if category != "" && strings.Index(article.Category, category) == -1 { + pass = false + } + if tag != "" { + pass = false + for _, tagx := range article.Tags { + if strings.Index(tagx, tag) != -1 { + pass = true + break + } + } + } + if pass { + articleList = append(articleList, article) + } + + } + return articleList +} + +func RecursiveReadArticles(dir string) (Articles, error) { + + var articles Articles + + dirInfo, err := os.Stat(dir) + + if err != nil { + return articles, err + } + if !dirInfo.IsDir() { + return articles, errors.New("目标不是一个目录") + } + + fileOrDir, err := ioutil.ReadDir(dir) + if err != nil { + return articles, err + } + + for _, fileInfo := range fileOrDir { + name := fileInfo.Name() + path := dir + "/" + name + upperName := strings.ToUpper(name) + if fileInfo.IsDir() { + subArticles, err := RecursiveReadArticles(path) + if err != nil { + return articles, err + } + articles = append(articles, subArticles...) + } else if strings.HasSuffix(upperName, ".MD") { + article, err := ReadArticle(path) + if err != nil { + return articles, err + } + articles = append(articles, article) + } else if strings.HasSuffix(upperName, ".PNG") || + strings.HasSuffix(upperName, ".GIF") || + strings.HasSuffix(upperName, ".JPG") { + + dst := config.Cfg.CurrentDir + "/images/" + name + fmt.Println(utils.IsFile(dst)) + if !utils.IsFile(dst) { + _, _ = utils.CopyFile(path, dst) + } + } + + } + return articles, nil +} + +func ReadArticle(path string) (Article, error) { + article, _, err := readMarkdown(path) + if err != nil { + return article, err + } + return article, nil +} + +func ReadArticleDetail(path string) (ArticleDetail, error) { + _, articleDetail, err := readMarkdown(path) + if err != nil { + return articleDetail, err + } + return articleDetail, nil +} + +func readMarkdown(path string) (Article, ArticleDetail, error) { + var article Article + var articleDetail ArticleDetail + mdFile, err := os.Stat(path) + + if err != nil { + return article, articleDetail, err + } + if mdFile.IsDir() { + return article, articleDetail, errors.New("this path is Dir") + } + markdown, err := ioutil.ReadFile(path) + + if err != nil { + return article, articleDetail, err + } + markdown = bytes.TrimSpace(markdown) + + article.Path = path + article.Category = GetCategoryName(path) + article.Title = strings.TrimSuffix(strings.ToUpper(mdFile.Name()), ".MD") + article.Date = Time(mdFile.ModTime()) + + if !bytes.HasPrefix(markdown, []byte("```json")) { + article.Description = cropDesc(markdown) + articleDetail.Article = article + articleDetail.Body = string(markdown) + return article, articleDetail, nil + } + + markdown = bytes.Replace(markdown, []byte("```json"), []byte(""), 1) + markdownArrInfo := bytes.SplitN(markdown, []byte("```"), 2) + + article.Description = cropDesc(markdownArrInfo[1]) + + if err := json.Unmarshal(bytes.TrimSpace(markdownArrInfo[0]), &article); err != nil { + article.Title = "文章[" + article.Title + "]解析 JSON 出错,请检查。" + article.Description = err.Error() + return article, articleDetail, nil + } + article.Path = path + article.Title = strings.ToUpper(article.Title) + + articleDetail.Article = article + articleDetail.Body = string(markdownArrInfo[1]) + return article, articleDetail, nil +} + +func cropDesc(c []byte) string { + content := []rune(string(c)) + contentLen := len(content) + + if contentLen <= config.Cfg.DescriptionLen { + return string(content[0:contentLen]) + } + + return string(content[0:config.Cfg.DescriptionLen]) +} + +func (t *Time) UnmarshalJSON(b []byte) error { + date, err := time.ParseInLocation(`"`+config.Cfg.TimeLayout+`"`, string(b), time.Local) + if err != nil { + return nil + } + *t = Time(date) + return nil +} + +func (t Time) MarshalJSON() ([]byte, error) { + + return []byte(t.Format(`"` + config.Cfg.TimeLayout + `"`)), nil +} + +func (t Time) Format(layout string) string { + return time.Time(t).Format(layout) +} + +func (a Articles) Len() int { return len(a) } + +func (a Articles) Less(i, j int) bool { return time.Time(a[i].Date).After(time.Time(a[j].Date)) } + +func (a Articles) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/models/category.go b/models/category.go new file mode 100644 index 0000000..fd82888 --- /dev/null +++ b/models/category.go @@ -0,0 +1,69 @@ +package models + +import ( + "blog/config" + "sort" + "strings" +) + +type Category struct { + Name string + Quantity int + Articles Articles +} +type Categories []Category + +func GetCategoryName(path string) string { + var categoryName string + newPath := strings.Replace(path, config.Cfg.DocumentContentDir+"/", "", 1) + + if strings.Index(newPath, "/") == -1 { //文件在根目录下(content/)没有分类名称 + categoryName = "未分类" + } else { + categoryName = strings.Split(newPath, "/")[0] + } + return categoryName +} + +func GroupByCategory(articles *Articles, articleQuantity int) Categories { + + var categories Categories + categoryMap := make(map[string]Articles) + + for _, article := range *articles { + + _, existedCategory := categoryMap[article.Category] + if existedCategory { + categoryMap[article.Category] = append(categoryMap[article.Category], article) + } else { + categoryMap[article.Category] = Articles{article} + } + } + for categoryName, articles := range categoryMap { + articleLen := len(articles) + + var articleList Articles + if articleQuantity <= 0 { + articleList = articles + } else { + if articleQuantity > articleLen { + articleList = articles[0:articleLen] + } else { + articleList = articles[0:articleQuantity] + } + } + categories = append(categories, Category{ + Name: categoryName, + Quantity: articleLen, + Articles: articleList, + }) + } + sort.Sort(categories) + return categories +} + +func (c Categories) Len() int { return len(c) } + +func (c Categories) Less(i, j int) bool { return c[i].Quantity > c[j].Quantity } + +func (c Categories) Swap(i, j int) { c[i], c[j] = c[j], c[i] } diff --git a/models/common.go b/models/common.go new file mode 100644 index 0000000..b8b8129 --- /dev/null +++ b/models/common.go @@ -0,0 +1,50 @@ +package models + +import ( + "blog/config" + "sync" +) + +var Navigation Navs +var ArticleList Articles +var ArticleShortUrlMap map[string]string //用来保证文章 shortUrl 唯一和快速定位文章 +var Template HtmlTemplate + +func CompiledContent() { + config.Initial() //克隆或者更新文档库 + //下面是对内容的生成 + wg := sync.WaitGroup{} + var err error + //导航 + wg.Add(1) + go func() { + Navigation, err = initExtraNav(config.Cfg.DocumentExtraNavDir) + if err != nil { + panic(err) + } + wg.Done() + }() + + //加载html模板 + wg.Add(1) + go func() { + Template, err = initHtmlTemplate(config.Cfg.ThemesDir) + if err != nil { + panic(err) + } + wg.Done() + }() + + //文章 + wg.Add(1) + go func() { + ArticleList, ArticleShortUrlMap, err = initArticlesAndImages(config.Cfg.DocumentContentDir) + if err != nil { + panic(err) + } + wg.Done() + }() + wg.Wait() + //启用并发比之前节约4倍左右的时间 + return +} diff --git a/models/extra_nav.go b/models/extra_nav.go new file mode 100644 index 0000000..6c1a2a2 --- /dev/null +++ b/models/extra_nav.go @@ -0,0 +1,31 @@ +package models + +import ( + "sort" + "strings" +) + +type Nav struct { + Title string + Path string +} +type Navs []Nav + +func initExtraNav(dir string) (Navs, error) { + + var navigation Navs + var extraNav Articles + + extraNav, err := RecursiveReadArticles(dir) + if err != nil { + return navigation, err + } + sort.Sort(extraNav) + + for _, article := range extraNav { + title := strings.Title(strings.ToLower(article.Title)) + navigation = append(navigation, Nav{Title: title, Path: article.Path}) + } + + return navigation, nil +} diff --git a/models/html_template.go b/models/html_template.go new file mode 100644 index 0000000..d647be4 --- /dev/null +++ b/models/html_template.go @@ -0,0 +1,91 @@ +package models + +import ( + "blog/config" + "fmt" + "html/template" + "io" +) + +type TemplatePointer struct { + *template.Template +} + +type HtmlTemplate struct { + Article TemplatePointer + Categories TemplatePointer + Dashboard TemplatePointer + ExtraNav TemplatePointer + Index TemplatePointer +} + +func (t TemplatePointer) WriteData(w io.Writer, data interface{}) { + + err := t.Execute(w, data) + if err != nil { + if _, e := w.Write([]byte(err.Error())); e != nil { + fmt.Println(e) + } + } +} + +func (t TemplatePointer) WriteError(w io.Writer, err error) { + if _, e := w.Write([]byte(err.Error())); e != nil { + fmt.Println(e) + } +} + +func BuildViewData(title string, data interface{}) map[string]interface{} { + return map[string]interface{}{ + "Title": title, + "Data": data, + "Config": config.Cfg, + "Navs": Navigation, + } +} + +func initHtmlTemplate(viewDir string) (HtmlTemplate, error) { + var htmlTemplate HtmlTemplate + + tp, err := readHtmlTemplate( + []string{"index", "extraNav", "dashboard", "categories", "article"}, + viewDir) + if err != nil { + return htmlTemplate, err + } + + htmlTemplate.Index = tp[0] + htmlTemplate.ExtraNav = tp[1] + htmlTemplate.Dashboard = tp[2] + htmlTemplate.Categories = tp[3] + htmlTemplate.Article = tp[4] + + return htmlTemplate, nil +} + +func SpreadDigit(n int) []int { + var r []int + for i := 1; i <= n; i++ { + r = append(r, i) + } + return r +} + +func readHtmlTemplate(htmlFileName []string, viewDir string) ([]TemplatePointer, error) { + var htmlTemplate []TemplatePointer + + head := viewDir + "/layouts/head.html" + footer := viewDir + "/layouts/footer.html" + + for _, name := range htmlFileName { + + tp, err := template.New(name+".html"). + Funcs(template.FuncMap{"SpreadDigit": SpreadDigit}). + ParseFiles(viewDir+"/"+name+".html", head, footer) + if err != nil { + return htmlTemplate, err + } + htmlTemplate = append(htmlTemplate, TemplatePointer{tp}) + } + return htmlTemplate, nil +} diff --git a/models/pagination.go b/models/pagination.go new file mode 100644 index 0000000..a1e7b7f --- /dev/null +++ b/models/pagination.go @@ -0,0 +1,48 @@ +package models + +import ( + "math" +) + +type PageResult struct { + List Articles `json:"list"` + Total int `json:"total"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + TotalPage int +} + +func Pagination(articles *Articles, page int, pageSize int) PageResult { + + articleLen := len(*articles) + totalPage := int(math.Floor(float64(articleLen / pageSize))) + + if (articleLen % pageSize) != 0 { + totalPage++ + } + result := PageResult{ + Total: articleLen, + Page: page, + PageSize: pageSize, + TotalPage: totalPage, + } + if page < 1 { + result.Page = 1 + } + if page > result.TotalPage { + result.Page = result.TotalPage + } + + if articleLen <= result.PageSize { + result.List = (*articles)[0:articleLen] + } else { + startNum := (result.Page - 1) * result.PageSize + endNum := startNum + result.PageSize + if endNum > articleLen { + endNum = articleLen + } + result.List = (*articles)[startNum:endNum] + } + + return result +} diff --git a/routes/main.go b/routes/main.go new file mode 100644 index 0000000..4186762 --- /dev/null +++ b/routes/main.go @@ -0,0 +1,24 @@ +package routes + +import ( + "blog/config" + "blog/controller" + "net/http" +) + +func InitRoute() { + + http.HandleFunc("/", controller.Index) + http.HandleFunc("/blog", controller.Index) + http.HandleFunc("/categories", controller.Category) + http.HandleFunc("/article", controller.Article) + http.HandleFunc("/extra-nav", controller.ExtraNav) + + http.HandleFunc(config.Cfg.GitHookUrl, controller.GithubHook) + http.HandleFunc(config.Cfg.Dashboard, controller.Dashboard) + + http.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.Dir(config.Cfg.ThemesDir+"/public")))) + http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir(config.Cfg.DocumentAssetsDir)))) + http.Handle("/images/", http.StripPrefix("/images/", http.FileServer(http.Dir(config.Cfg.CurrentDir+"/images")))) + +} diff --git a/themes/blog/article.html b/themes/blog/article.html new file mode 100644 index 0000000..0081c66 --- /dev/null +++ b/themes/blog/article.html @@ -0,0 +1,55 @@ +{{template "header" .}} +
- {{ .Title }} -
+ +

{{ .Data.Title }}

+ +
+ + + + 分类于 + {{ .Data.Category }} + + + + + + 发表于{{ .Data.Date.Format "2006-01-02 15:04" }} + + + + + Tags: + {{ range .Data.Tags }} + {{.}} + {{ end }} + + + + +
+ +{{ if ne .Data.MusicId "" }} + + + + + +
+ +{{ end }} +
+ +
+ + + +{{if ne .Config.UtterancesRepo ""}} + +{{end}} +{{template "footer" .}} \ No newline at end of file diff --git a/themes/blog/categories.html b/themes/blog/categories.html new file mode 100644 index 0000000..ed899c2 --- /dev/null +++ b/themes/blog/categories.html @@ -0,0 +1,17 @@ +{{template "header" .}} +
- {{ .Title }} -
+
+ {{range .Data}} +
+ +

{{ .Name }} ({{ .Quantity }})

+
+ +
+ {{end}} +
+{{template "footer" .}} \ No newline at end of file diff --git a/themes/blog/dashboard.html b/themes/blog/dashboard.html new file mode 100644 index 0000000..c914c85 --- /dev/null +++ b/themes/blog/dashboard.html @@ -0,0 +1,45 @@ +{{template "header" .}} +
- {{ .Title }} -
+

Search:

+
+ +
+

Theme:

+
+ +
+

Action:

+
+ +
+ {{ if .Data.msg }} +
+ {{range $msg := .Data.msg }} + {{ $msg }} + {{ end }} + x +
+ {{ end }} + 提示:更新文章会执行git pull命令,和你的仓库网络有关,等待时间可能会稍长。 + +{{template "footer" .}} \ No newline at end of file diff --git a/themes/blog/extraNav.html b/themes/blog/extraNav.html new file mode 100644 index 0000000..1f601f2 --- /dev/null +++ b/themes/blog/extraNav.html @@ -0,0 +1,7 @@ +{{template "header" .}} +
- {{ .Title }} -
+
+ +{{template "footer" .}} diff --git a/themes/blog/index.html b/themes/blog/index.html new file mode 100644 index 0000000..5fd4721 --- /dev/null +++ b/themes/blog/index.html @@ -0,0 +1,55 @@ +{{template "header" .}} +
- {{ .Title }} -
+ + + + + +{{template "footer" .}} \ No newline at end of file diff --git a/themes/blog/layouts/footer.html b/themes/blog/layouts/footer.html new file mode 100644 index 0000000..97ee427 --- /dev/null +++ b/themes/blog/layouts/footer.html @@ -0,0 +1,15 @@ +{{define "footer"}} + + + + +{{ end}} \ No newline at end of file diff --git a/themes/blog/layouts/head.html b/themes/blog/layouts/head.html new file mode 100644 index 0000000..a77d75e --- /dev/null +++ b/themes/blog/layouts/head.html @@ -0,0 +1,69 @@ +{{define "header"}} + + + + + + + + + + + {{ .Title }} - {{ .Config.SiteName }} + + + + + + + + + + + +
+ {{ end }} \ No newline at end of file diff --git a/themes/blog/public/css/app.css b/themes/blog/public/css/app.css new file mode 100644 index 0000000..141f226 --- /dev/null +++ b/themes/blog/public/css/app.css @@ -0,0 +1,477 @@ + +*{ + box-sizing: border-box; +} +html { + font-family: josefin sans,-apple-system,BlinkMacSystemFont,helvetica neue,pingfang sc,hiragino sans gb,STHeiti,microsoft yahei,wenquanyi micro hei,Arial,Verdana,sans-serif; +} +html::-webkit-scrollbar { + width: 8px; + height: 8px +} + +html::-webkit-scrollbar-thumb { + height: 40px; + background-color: #eee; + border-radius: 0 +} + +html::-webkit-scrollbar-thumb:hover { + background-color: #ddd +} +pre{ + padding: 1em; + margin: .5em 0; + overflow: auto; + background: #f5f2f0; +} +body{ + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + min-height: 100vh; +} + + +a{ + color: #161209; + text-decoration: none; + transition: color .2s ease,border-color .46s ease,background .46s ease,opacity .46s ease; +} + +a:hover{ + color: #673ab7; + color: var(--primary,#673ab7); + +} +p{ + line-height: 2em; +} + +blockquote{ + text-indent: 2em; + position: relative; + margin: 20px 0; +} +blockquote::before{ + position: absolute; + left: -32px; + top: -10px; + content: '“'; + font-family: fantasy; + font-size: 40px; + color: #673ab7; + color: var(--primary,#673ab7); +} + + +@media screen and (max-width: 860px){ + body{ + padding: 6px; + } +} +@font-face { + font-family: josefin sans; + font-style: normal; + font-weight: 400; + src: url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.eot); + src: local("Josefin Sans"),local("JosefinSans-Normal"),url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.eot?#iefix) format("embedded-opentype"),url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.woff2) format("woff2"),url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.woff) format("woff"),url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.ttf) format("truetype"),url(//lib.baomitu.com/fonts/josefin-sans/josefin-sans-regular.svg#JosefinSans) format("svg") +} + + +.container { + width: auto; + max-width: 1200px; + text-align: center; + margin: 0 auto; + +} + +.head{ + width: 100%; + height: 64px; +} +.head-content{ + display: flex; + height: 100%; + align-items: center; + justify-content: space-between; +} +@media screen and (max-width: 860px){ + .head-content{ + padding-top: 10px; + flex-direction: column; + } +} + +.nav a{ + padding: 0 8px; +} + +.sub-title { + position: relative; + width: 100%; + text-align: right; + font-size: 32px; + margin-bottom: 82px; +} +@media screen and (max-width: 860px){ + .sub-title { + display: none; + } +} +.post-warp{ + position: relative; + width: 100%; + overflow: hidden; + max-width: 780px; + margin: 0 auto; + min-height: calc(100vh - 120px); + padding: 46px 0; +} +@media screen and (max-width: 860px){ + .post-warp{ + min-height: calc(100vh - 132px); + } +} + +.markdow img{ + width: 100%; + border-radius: 4px; +} + + +.footer{ + color: #999; + display: flex; + height: 54px; + line-height: 1; + align-items: center; + justify-content: center; +} +.footer-divider{ + margin: 0 10px; +} +@media screen and (max-width: 860px){ + .footer{ + flex-direction: column; + } + .footer span{ + text-align: center; + padding: 4px 0; + } + .footer-divider{ + display: none; + } +} + +.footer a{ + color: #999; + margin: 0 8px; +} +pre{ + border-radius: 3px; + font-size: 14px; + line-height: 1.6; + overflow: auto; +} +hr{ + border: none; + overflow: hidden; +} +hr:after{ + content: ''; + display: block; + margin: 30px auto; + width: 10%; + height: 1px; + background: #ccc; + text-align: center; +} + + +/*Categories*/ + +.categories{ + display: flex; + width: 100%; + justify-content: space-between; + flex-wrap:wrap; +} +.categories-card{ + width: 50%; + margin-bottom: 46px; + min-height: 250px; + padding: 0 16px; +} +@media screen and (max-width: 860px){ + .categories-card{ + width: 100%; + } +} +.icon{ + width: 16px; + height: 16px; +} +.categories-article{ + text-indent: 2em; +} +.categories-article a{ + display: block; + margin-bottom: 10px; + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +/*Pagination*/ + +.pagination{ + display: flex; + margin: 60px 0; + width: 100%; + justify-content: center; + padding: 0; +} +.pagination li{ + list-style-type: none; + margin: 0 10px; + width: 20px; +} +.pagination li a { + text-align: center; + display: block; + width: 100%; + color: #bfbfbf; + padding-bottom: 6px; +} +.pagination li a:hover,.pagination .active a{ + border-bottom: 3px solid #673ab7; + border-bottom: 3px solid var(--primary,#673ab7); +} + +/*Index*/ +.articles{ + margin: 0; + padding: 0; + min-height: 400px; +} +.articles li{ + padding-bottom: 8px; + list-style-type: none; + margin: 40px 0; + text-align: center; + } + +.articles li:after{ + content: ''; + display: block; + margin: 60px auto; + width: 10%; + height: 1px; + background: #ccc; + text-align: center; +} + +.articles li:last-child:after{ + display: none; +} +.read-all{ + display: inline-block; + padding: 4px 20px; + font-size: 14px; + color: #fff; + background: #673ab7; + border: 2px solid #673ab7; + background: var(--primary,#673ab7); + border: 2px solid var(--primary,#673ab7); + text-decoration: none; + border-radius: 2px; + transition-property: background-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + transition-delay: 0s; +} + +.read-all:hover{ + background: #fff; +} + +.articles li .title{ + color: #555; + font-size: 20px; + font-weight: normal; +} +.articles li .title:hover{ + color: #673ab7; + color: var(--primary,#673ab7); +} +.article-info{ + margin:20px 0 60px; + color: #999; + font-size: 14px; + height: 40px; + display: flex; + justify-content: center; + align-items: center; + flex-flow: wrap; +} + +.article-info img{ + position: relative; + top: 2px; + width: 16px; + height: 16px; +} +.article-img img{ + position: relative; + width: 300px; + height: 200px; + border-radius:3%; + object-fit:cover; +} +.article-info .divider-line{ + width: 2px; + height: 16px; + background: #999; + margin: 0 14px; +} +.article{ + padding: 10px 0; + margin: 10px 0; +} +.articles .description{ + color: #555; + font-size: 16px; + text-align: left; + line-height: 2; + text-indent: 2em; + margin-bottom: 40px; +} +@media screen and (max-width: 860px){ + .articles .description{ + padding: 0 10px; + } +} + +.sub{ + font-size: 14px; +} + +/*dashboard*/ +.item-content{ + width: 100%; + height: 120px; + display: flex; + justify-content: center; + align-items: center; +} +.search-box{ + height: 40px; + display: flex; + border-radius: 2px; + align-items: center; + justify-content: space-between; + border: 1px solid #673ab7; + border: 1px solid var(--primary,#673ab7); + width: 320px; +} +.search-input{ + text-align: center; + flex: 1; + border: none; + height: 30px; + padding: 0 10px; +} +.search-input:focus,.search-input:active{ + border: none; + outline:none; +} +.search-icon{ + cursor: pointer; + margin: 0 10px; + width: 20px; + height: 20px; +} +.colors{ + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; + padding: 0; +} + +.colors li{ + width: 40px; + height: 40px; + margin: 10px 20px; + border-radius: 2px; + cursor: pointer; + position: relative; +} +.colors li.active:before{ + content: ''; + width: 10px; + height: 10px; + background-color: #fff; + display: block; + position: absolute; + top: 15px; + left: 15px; + border-radius: 2px; +} +.action{ + display: flex; + flex-wrap: wrap; + list-style: none; + margin: 0; + padding: 0; +} +.action a{ + padding: 8px 16px; + border-radius: 2px; + opacity: .8; + color: #fff; + background-color: #673ab7; + background-color: var(--primary,#673ab7); + font-size: 14px; +} +.action a:hover{ + opacity: 1; + box-shadow: 0 0 4px rgba(0,0,0,.2); +} +.action-tip{ + font-size: 14px; + color: #673ab7; + color: var(--primary,#673ab7); +} +.action-msg{ + z-index: 1400; + position: fixed; + top: 24px; + left: auto; + right: 24px; + color: #fff; + display: flex; + flex-direction: column; + padding: 12px 16px; + flex-wrap: wrap; + align-items: flex-start; + justify-content: center; + opacity: 1; + min-width: 288px; + border-radius: 4px; + background-color: #673ab7; + background-color: var(--primary,#673ab7); + box-shadow: 0 3px 5px -1px rgba(0,0,0,0.2), 0 6px 10px 0 rgba(0,0,0,0.14), 0 1px 18px 0 rgba(0,0,0,0.12); +} +.action-msg .close{ + color: #fff; + cursor: pointer; + position: absolute; + top: auto; + font-size: 16px; + right: 24px; +} diff --git a/themes/blog/public/css/prism.css b/themes/blog/public/css/prism.css new file mode 100644 index 0000000..2aba946 --- /dev/null +++ b/themes/blog/public/css/prism.css @@ -0,0 +1,5 @@ +/* PrismJS 1.28.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+cpp+cmake+go+java+json+json5+kotlin+lua+markup-templating+nginx+php+python+verilog+yaml&plugins=line-highlight+show-language+toolbar+copy-to-clipboard */ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} +pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)} +div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none} diff --git a/themes/blog/public/fonts/josefin.woff2 b/themes/blog/public/fonts/josefin.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ea74c6180d85a87ea34ac49d338a53abf29a9832 GIT binary patch literal 33880 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 literal 0 HcmV?d00001 diff --git a/themes/blog/public/img/date.svg b/themes/blog/public/img/date.svg new file mode 100644 index 0000000..0e1791b --- /dev/null +++ b/themes/blog/public/img/date.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/blog/public/img/favicon.ico b/themes/blog/public/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a9024f4e1f7db07c4a28800fa4aee39e6c7ecd39 GIT binary patch literal 9662 zcmeI1Ym8l0701s|+S{iC)mEV5Gzf?lWAT%TjT55OYAs?ry}jq0`=E`F09s6{F{UOp zX$%?-)+q8)QUNJQ6B1*Mi63Z#5#s}l3ACn?+#u=)V;LWnL53NBzjOB)Z|9y<=hDGf zW;g%Y_w2p)TK~QF+H3D~8bt&ATe~*m@9OCOOQL9H6h)T-nxbog?OC}vik2_wpwlq- zcg_QI9+>mM|Azcon=Rt4maBisHTvYf790n1x@$TIl{-)DuAu+t zL9U4Z6O3IY=k9{Mb68G&Ul{u&`qt=^Gb!33Cm7rNgWeyZcZlE7=FMA9QQeVEE~L+# zU&P(EHgd01w!6qvo#0}S&;NGX7ufz%N}~}6oyk?`FmBwl?^9pBepQdk!2k91KLg76 z|A9Wwxt{UW>b9uath)z_OIF9k|*>3{*JjnB6P^e0IV4OV*%J~18 zzPExx9j*iV*;myz zyjLn;)S(~9(F2V83Xscfn>KA4s8*{*;#r$EfVRxzW&B@+--nbfE1unPyiMER2zvHi zaDn-4=6fK-p=a&)gN_@xG;$7<=VRpL|B)bH#^3f&DqB|m8AIufLDwPXOb#sGcSU*v z|8p7t3oy>}`%hG^jE-qawRy8z3iOhZkgT*a{i9{F!%sC+0}k8^E&%&4+jo&Kjpq#;Hp*Sp!njA7FL&6!{qJ4u z;hHp#={*!$G+>Y zZ)N98kxjV({r^CaKOO%=aPhsfNL6Noe$L#fb-St6YH$}Vo^O$o{Jk6<=4!e87<~FzIp5LRMR%=J0 zD*1Qb57WKKO@Jc)H>2n5GCz2}XagkR1#q0XT;%%pTjT?biF<)u4)DCN%(nWq16CtT z&hFv=ByE>~QYvBmGGy4}+4x&(wdz?(QhetsRg`gwvsgr@_bu;@-k~>w(qZ0ny#ph2 z9hmO_UA`}t&A+p6r}BE2=Z0O2-nANUE2B@_UBU}Wm~T#i5pDL9GYgf6#;~tkOTU2_o6m#Wz$)iwe|HI-jJs`Mg#IPdWqeMOEIy5^ zyMXz|JI9TT=le8c!V|##un}9QzHQ&`5<{CvFa^BX{3O5VYGxt{$Q zpCxJUNzJC;iM%@}Yv9oW=A1*|abR2=4Zl58?Q0_Y27FDdxDWb2TW5)Wj~f4Ph%?w2 z=YF61&c{2P==}c?-_Y&r88_E3=Ycs7%z5B{(F2oNiK3a;ql1%^%711ct0$spkI!RK zG-N$mX%AYr*S)4v95aD=iw+C zA8uF1Pp#*5o)4GS-Fl|<4vr3LXL4|CNV}7jv7wB|-tpm#*OBqzjOXF;;f!~C-MVZZ X`MmOZ=JU?|Fq!*BPog&~|GNGMlGosG literal 0 HcmV?d00001 diff --git a/themes/blog/public/img/favicon.svg b/themes/blog/public/img/favicon.svg new file mode 100644 index 0000000..611548f --- /dev/null +++ b/themes/blog/public/img/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/blog/public/img/folder.svg b/themes/blog/public/img/folder.svg new file mode 100644 index 0000000..6e6f743 --- /dev/null +++ b/themes/blog/public/img/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/blog/public/img/search.svg b/themes/blog/public/img/search.svg new file mode 100644 index 0000000..7233a4d --- /dev/null +++ b/themes/blog/public/img/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/blog/public/img/tag.svg b/themes/blog/public/img/tag.svg new file mode 100644 index 0000000..e47d643 --- /dev/null +++ b/themes/blog/public/img/tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/themes/blog/public/js/marked.min.js b/themes/blog/public/js/marked.min.js new file mode 100644 index 0000000..085cfb5 --- /dev/null +++ b/themes/blog/public/js/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +!function(e){"use strict";var k={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:f,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:f,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:f,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function a(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||b.defaults,this.rules=k.normal,this.options.pedantic?this.rules=k.pedantic:this.options.gfm&&(this.options.tables?this.rules=k.tables:this.rules=k.gfm)}k._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,k._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,k.def=i(k.def).replace("label",k._label).replace("title",k._title).getRegex(),k.bullet=/(?:[*+-]|\d{1,9}\.)/,k.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,k.item=i(k.item,"gm").replace(/bull/g,k.bullet).getRegex(),k.list=i(k.list).replace(/bull/g,k.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+k.def.source+")").getRegex(),k._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",k._comment=//,k.html=i(k.html,"i").replace("comment",k._comment).replace("tag",k._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),k.paragraph=i(k.paragraph).replace("hr",k.hr).replace("heading",k.heading).replace("lheading",k.lheading).replace("tag",k._tag).getRegex(),k.blockquote=i(k.blockquote).replace("paragraph",k.paragraph).getRegex(),k.normal=d({},k),k.gfm=d({},k.normal,{fences:/^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),k.gfm.paragraph=i(k.paragraph).replace("(?!","(?!"+k.gfm.fences.source.replace("\\1","\\2")+"|"+k.list.source.replace("\\1","\\3")+"|").getRegex(),k.tables=d({},k.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),k.pedantic=d({},k.normal,{html:i("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",k._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),a.rules=k,a.lex=function(e,t){return new a(t).lex(e)},a.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},a.prototype.token=function(e,t){var n,r,s,i,l,o,a,h,p,u,c,g,f,d,m,b;for(e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),1 ?/gm,""),this.token(s,t),this.tokens.push({type:"blockquote_end"});else if(s=this.rules.list.exec(e)){for(e=e.substring(s[0].length),a={type:"list_start",ordered:d=1<(i=s[2]).length,start:d?+i:"",loose:!1},this.tokens.push(a),n=!(h=[]),f=(s=s[0].match(this.rules.item)).length,c=0;c?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:f,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:f,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",n.em=i(n.em).replace(/punctuation/g,n._punctuation).getRegex(),n._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,n._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,n._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,n.autolink=i(n.autolink).replace("scheme",n._scheme).replace("email",n._email).getRegex(),n._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,n.tag=i(n.tag).replace("comment",k._comment).replace("attribute",n._attribute).getRegex(),n._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/,n._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/,n._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,n.link=i(n.link).replace("label",n._label).replace("href",n._href).replace("title",n._title).getRegex(),n.reflink=i(n.reflink).replace("label",n._label).getRegex(),n.normal=d({},n),n.pedantic=d({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:i(/^!?\[(label)\]\((.*?)\)/).replace("label",n._label).getRegex(),reflink:i(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",n._label).getRegex()}),n.gfm=d({},n.normal,{escape:i(n.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(i[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(i[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(i[0])&&(this.inRawBlock=!1),e=e.substring(i[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):u(i[0]):i[0];else if(i=this.rules.link.exec(e)){var a=m(i[2],"()");if(-1$/,"$1"),o+=this.outputLink(i,{href:p.escapes(r),title:p.escapes(s)}),this.inLink=!1}else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){o+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),o+=this.renderer.strong(this.output(i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),o+=this.renderer.em(this.output(i[6]||i[5]||i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),o+=this.renderer.codespan(u(i[2].trim(),!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),o+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),o+=this.renderer.del(this.output(i[1]));else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),r="@"===i[2]?"mailto:"+(n=u(this.mangle(i[1]))):n=u(i[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.inRawBlock?o+=this.renderer.text(i[0]):o+=this.renderer.text(u(this.smartypants(i[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===i[2])r="mailto:"+(n=u(i[0]));else{for(;l=i[0],i[0]=this.rules._backpedal.exec(i[0])[0],l!==i[0];);n=u(i[0]),r="www."===i[1]?"http://"+n:n}e=e.substring(i[0].length),o+=this.renderer.link(r,null,n)}return o},p.escapes=function(e){return e?e.replace(p.rules._escapes,"$1"):e},p.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},p.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},p.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,s=0;s'+(n?e:u(e,!0))+"\n":"
"+(n?e:u(e,!0))+"
"},r.prototype.blockquote=function(e){return"
\n"+e+"
\n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},r.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.checkbox=function(e){return" "},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},r.prototype.image=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},r.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},h.parse=function(e,t){return new h(t).parse(e)},h.prototype.parse=function(e){this.inline=new p(e.links,this.options),this.inlineText=new p(e.links,d({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},h.prototype.next=function(){return this.token=this.tokens.pop()},h.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},h.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},h.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,c(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t))for(var n=t;this.seen[n]++,t=n+"-"+this.seen[n],this.seen.hasOwnProperty(t););return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var o={},g=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function f(){}function d(e){for(var t,n,r=1;rt)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}f.exec=f,b.options=b.setOptions=function(e){return d(b.defaults,e),b},b.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new r,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},b.defaults=b.getDefaults(),b.Parser=h,b.parser=h.parse,b.Renderer=r,b.TextRenderer=s,b.Lexer=a,b.lexer=a.lex,b.InlineLexer=p,b.inlineLexer=p.output,b.Slugger=t,b.parse=b,"undefined"!=typeof module&&"object"==typeof exports?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):e.marked=b}(this||("undefined"!=typeof window?window:global)); \ No newline at end of file diff --git a/themes/blog/public/js/prism.js b/themes/blog/public/js/prism.js new file mode 100644 index 0000000..1f40124 --- /dev/null +++ b/themes/blog/public/js/prism.js @@ -0,0 +1,27 @@ +/* PrismJS 1.28.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+cpp+cmake+go+java+json+json5+kotlin+lua+markup-templating+nginx+php+python+verilog+yaml&plugins=line-highlight+show-language+toolbar+copy-to-clipboard */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\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",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],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})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:a},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:a.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.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:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},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:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var o=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],s=a.variable[1].inside,i=0;i>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],char:Prism.languages.c.char,comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}}}),Prism.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Prism.languages.c.boolean; +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:import|module)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); +Prism.languages.cmake={comment:/#.*/,string:{pattern:/"(?:[^\\"]|\\.)*"/,greedy:!0,inside:{interpolation:{pattern:/\$\{(?:[^{}$]|\$\{[^{}$]*\})*\}/,inside:{punctuation:/\$\{|\}/,variable:/\w+/}}}},variable:/\b(?:CMAKE_\w+|\w+_(?:(?:BINARY|SOURCE)_DIR|DESCRIPTION|HOMEPAGE_URL|ROOT|VERSION(?:_MAJOR|_MINOR|_PATCH|_TWEAK)?)|(?:ANDROID|APPLE|BORLAND|BUILD_SHARED_LIBS|CACHE|CPACK_(?:ABSOLUTE_DESTINATION_FILES|COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY|ERROR_ON_ABSOLUTE_INSTALL_DESTINATION|INCLUDE_TOPLEVEL_DIRECTORY|INSTALL_DEFAULT_DIRECTORY_PERMISSIONS|INSTALL_SCRIPT|PACKAGING_INSTALL_PREFIX|SET_DESTDIR|WARN_ON_ABSOLUTE_INSTALL_DESTINATION)|CTEST_(?:BINARY_DIRECTORY|BUILD_COMMAND|BUILD_NAME|BZR_COMMAND|BZR_UPDATE_OPTIONS|CHANGE_ID|CHECKOUT_COMMAND|CONFIGURATION_TYPE|CONFIGURE_COMMAND|COVERAGE_COMMAND|COVERAGE_EXTRA_FLAGS|CURL_OPTIONS|CUSTOM_(?:COVERAGE_EXCLUDE|ERROR_EXCEPTION|ERROR_MATCH|ERROR_POST_CONTEXT|ERROR_PRE_CONTEXT|MAXIMUM_FAILED_TEST_OUTPUT_SIZE|MAXIMUM_NUMBER_OF_(?:ERRORS|WARNINGS)|MAXIMUM_PASSED_TEST_OUTPUT_SIZE|MEMCHECK_IGNORE|POST_MEMCHECK|POST_TEST|PRE_MEMCHECK|PRE_TEST|TESTS_IGNORE|WARNING_EXCEPTION|WARNING_MATCH)|CVS_CHECKOUT|CVS_COMMAND|CVS_UPDATE_OPTIONS|DROP_LOCATION|DROP_METHOD|DROP_SITE|DROP_SITE_CDASH|DROP_SITE_PASSWORD|DROP_SITE_USER|EXTRA_COVERAGE_GLOB|GIT_COMMAND|GIT_INIT_SUBMODULES|GIT_UPDATE_CUSTOM|GIT_UPDATE_OPTIONS|HG_COMMAND|HG_UPDATE_OPTIONS|LABELS_FOR_SUBPROJECTS|MEMORYCHECK_(?:COMMAND|COMMAND_OPTIONS|SANITIZER_OPTIONS|SUPPRESSIONS_FILE|TYPE)|NIGHTLY_START_TIME|P4_CLIENT|P4_COMMAND|P4_OPTIONS|P4_UPDATE_OPTIONS|RUN_CURRENT_SCRIPT|SCP_COMMAND|SITE|SOURCE_DIRECTORY|SUBMIT_URL|SVN_COMMAND|SVN_OPTIONS|SVN_UPDATE_OPTIONS|TEST_LOAD|TEST_TIMEOUT|TRIGGER_SITE|UPDATE_COMMAND|UPDATE_OPTIONS|UPDATE_VERSION_ONLY|USE_LAUNCHERS)|CYGWIN|ENV|EXECUTABLE_OUTPUT_PATH|GHS-MULTI|IOS|LIBRARY_OUTPUT_PATH|MINGW|MSVC(?:10|11|12|14|60|70|71|80|90|_IDE|_TOOLSET_VERSION|_VERSION)?|MSYS|PROJECT_NAME|UNIX|WIN32|WINCE|WINDOWS_PHONE|WINDOWS_STORE|XCODE))\b/,property:/\b(?:cxx_\w+|(?:ARCHIVE_OUTPUT_(?:DIRECTORY|NAME)|COMPILE_DEFINITIONS|COMPILE_PDB_NAME|COMPILE_PDB_OUTPUT_DIRECTORY|EXCLUDE_FROM_DEFAULT_BUILD|IMPORTED_(?:IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_LANGUAGES|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|NO_SONAME|OBJECTS|SONAME)|INTERPROCEDURAL_OPTIMIZATION|LIBRARY_OUTPUT_DIRECTORY|LIBRARY_OUTPUT_NAME|LINK_FLAGS|LINK_INTERFACE_LIBRARIES|LINK_INTERFACE_MULTIPLICITY|LOCATION|MAP_IMPORTED_CONFIG|OSX_ARCHITECTURES|OUTPUT_NAME|PDB_NAME|PDB_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_DIRECTORY|RUNTIME_OUTPUT_NAME|STATIC_LIBRARY_FLAGS|VS_CSHARP|VS_DOTNET_REFERENCEPROP|VS_DOTNET_REFERENCE|VS_GLOBAL_SECTION_POST|VS_GLOBAL_SECTION_PRE|VS_GLOBAL|XCODE_ATTRIBUTE)_\w+|\w+_(?:CLANG_TIDY|COMPILER_LAUNCHER|CPPCHECK|CPPLINT|INCLUDE_WHAT_YOU_USE|OUTPUT_NAME|POSTFIX|VISIBILITY_PRESET)|ABSTRACT|ADDITIONAL_MAKE_CLEAN_FILES|ADVANCED|ALIASED_TARGET|ALLOW_DUPLICATE_CUSTOM_TARGETS|ANDROID_(?:ANT_ADDITIONAL_OPTIONS|API|API_MIN|ARCH|ASSETS_DIRECTORIES|GUI|JAR_DEPENDENCIES|NATIVE_LIB_DEPENDENCIES|NATIVE_LIB_DIRECTORIES|PROCESS_MAX|PROGUARD|PROGUARD_CONFIG_PATH|SECURE_PROPS_PATH|SKIP_ANT_STEP|STL_TYPE)|ARCHIVE_OUTPUT_DIRECTORY|ATTACHED_FILES|ATTACHED_FILES_ON_FAIL|AUTOGEN_(?:BUILD_DIR|ORIGIN_DEPENDS|PARALLEL|SOURCE_GROUP|TARGETS_FOLDER|TARGET_DEPENDS)|AUTOMOC|AUTOMOC_(?:COMPILER_PREDEFINES|DEPEND_FILTERS|EXECUTABLE|MACRO_NAMES|MOC_OPTIONS|SOURCE_GROUP|TARGETS_FOLDER)|AUTORCC|AUTORCC_EXECUTABLE|AUTORCC_OPTIONS|AUTORCC_SOURCE_GROUP|AUTOUIC|AUTOUIC_EXECUTABLE|AUTOUIC_OPTIONS|AUTOUIC_SEARCH_PATHS|BINARY_DIR|BUILDSYSTEM_TARGETS|BUILD_RPATH|BUILD_RPATH_USE_ORIGIN|BUILD_WITH_INSTALL_NAME_DIR|BUILD_WITH_INSTALL_RPATH|BUNDLE|BUNDLE_EXTENSION|CACHE_VARIABLES|CLEAN_NO_CUSTOM|COMMON_LANGUAGE_RUNTIME|COMPATIBLE_INTERFACE_(?:BOOL|NUMBER_MAX|NUMBER_MIN|STRING)|COMPILE_(?:DEFINITIONS|FEATURES|FLAGS|OPTIONS|PDB_NAME|PDB_OUTPUT_DIRECTORY)|COST|CPACK_DESKTOP_SHORTCUTS|CPACK_NEVER_OVERWRITE|CPACK_PERMANENT|CPACK_STARTUP_SHORTCUTS|CPACK_START_MENU_SHORTCUTS|CPACK_WIX_ACL|CROSSCOMPILING_EMULATOR|CUDA_EXTENSIONS|CUDA_PTX_COMPILATION|CUDA_RESOLVE_DEVICE_SYMBOLS|CUDA_SEPARABLE_COMPILATION|CUDA_STANDARD|CUDA_STANDARD_REQUIRED|CXX_EXTENSIONS|CXX_STANDARD|CXX_STANDARD_REQUIRED|C_EXTENSIONS|C_STANDARD|C_STANDARD_REQUIRED|DEBUG_CONFIGURATIONS|DEFINE_SYMBOL|DEFINITIONS|DEPENDS|DEPLOYMENT_ADDITIONAL_FILES|DEPLOYMENT_REMOTE_DIRECTORY|DISABLED|DISABLED_FEATURES|ECLIPSE_EXTRA_CPROJECT_CONTENTS|ECLIPSE_EXTRA_NATURES|ENABLED_FEATURES|ENABLED_LANGUAGES|ENABLE_EXPORTS|ENVIRONMENT|EXCLUDE_FROM_ALL|EXCLUDE_FROM_DEFAULT_BUILD|EXPORT_NAME|EXPORT_PROPERTIES|EXTERNAL_OBJECT|EchoString|FAIL_REGULAR_EXPRESSION|FIND_LIBRARY_USE_LIB32_PATHS|FIND_LIBRARY_USE_LIB64_PATHS|FIND_LIBRARY_USE_LIBX32_PATHS|FIND_LIBRARY_USE_OPENBSD_VERSIONING|FIXTURES_CLEANUP|FIXTURES_REQUIRED|FIXTURES_SETUP|FOLDER|FRAMEWORK|Fortran_FORMAT|Fortran_MODULE_DIRECTORY|GENERATED|GENERATOR_FILE_NAME|GENERATOR_IS_MULTI_CONFIG|GHS_INTEGRITY_APP|GHS_NO_SOURCE_GROUP_FILE|GLOBAL_DEPENDS_DEBUG_MODE|GLOBAL_DEPENDS_NO_CYCLES|GNUtoMS|HAS_CXX|HEADER_FILE_ONLY|HELPSTRING|IMPLICIT_DEPENDS_INCLUDE_TRANSFORM|IMPORTED|IMPORTED_(?:COMMON_LANGUAGE_RUNTIME|CONFIGURATIONS|GLOBAL|IMPLIB|LIBNAME|LINK_DEPENDENT_LIBRARIES|LINK_INTERFACE_(?:LANGUAGES|LIBRARIES|MULTIPLICITY)|LOCATION|NO_SONAME|OBJECTS|SONAME)|IMPORT_PREFIX|IMPORT_SUFFIX|INCLUDE_DIRECTORIES|INCLUDE_REGULAR_EXPRESSION|INSTALL_NAME_DIR|INSTALL_RPATH|INSTALL_RPATH_USE_LINK_PATH|INTERFACE_(?:AUTOUIC_OPTIONS|COMPILE_DEFINITIONS|COMPILE_FEATURES|COMPILE_OPTIONS|INCLUDE_DIRECTORIES|LINK_DEPENDS|LINK_DIRECTORIES|LINK_LIBRARIES|LINK_OPTIONS|POSITION_INDEPENDENT_CODE|SOURCES|SYSTEM_INCLUDE_DIRECTORIES)|INTERPROCEDURAL_OPTIMIZATION|IN_TRY_COMPILE|IOS_INSTALL_COMBINED|JOB_POOLS|JOB_POOL_COMPILE|JOB_POOL_LINK|KEEP_EXTENSION|LABELS|LANGUAGE|LIBRARY_OUTPUT_DIRECTORY|LINKER_LANGUAGE|LINK_(?:DEPENDS|DEPENDS_NO_SHARED|DIRECTORIES|FLAGS|INTERFACE_LIBRARIES|INTERFACE_MULTIPLICITY|LIBRARIES|OPTIONS|SEARCH_END_STATIC|SEARCH_START_STATIC|WHAT_YOU_USE)|LISTFILE_STACK|LOCATION|MACOSX_BUNDLE|MACOSX_BUNDLE_INFO_PLIST|MACOSX_FRAMEWORK_INFO_PLIST|MACOSX_PACKAGE_LOCATION|MACOSX_RPATH|MACROS|MANUALLY_ADDED_DEPENDENCIES|MEASUREMENT|MODIFIED|NAME|NO_SONAME|NO_SYSTEM_FROM_IMPORTED|OBJECT_DEPENDS|OBJECT_OUTPUTS|OSX_ARCHITECTURES|OUTPUT_NAME|PACKAGES_FOUND|PACKAGES_NOT_FOUND|PARENT_DIRECTORY|PASS_REGULAR_EXPRESSION|PDB_NAME|PDB_OUTPUT_DIRECTORY|POSITION_INDEPENDENT_CODE|POST_INSTALL_SCRIPT|PREDEFINED_TARGETS_FOLDER|PREFIX|PRE_INSTALL_SCRIPT|PRIVATE_HEADER|PROCESSORS|PROCESSOR_AFFINITY|PROJECT_LABEL|PUBLIC_HEADER|REPORT_UNDEFINED_PROPERTIES|REQUIRED_FILES|RESOURCE|RESOURCE_LOCK|RULE_LAUNCH_COMPILE|RULE_LAUNCH_CUSTOM|RULE_LAUNCH_LINK|RULE_MESSAGES|RUNTIME_OUTPUT_DIRECTORY|RUN_SERIAL|SKIP_AUTOGEN|SKIP_AUTOMOC|SKIP_AUTORCC|SKIP_AUTOUIC|SKIP_BUILD_RPATH|SKIP_RETURN_CODE|SOURCES|SOURCE_DIR|SOVERSION|STATIC_LIBRARY_FLAGS|STATIC_LIBRARY_OPTIONS|STRINGS|SUBDIRECTORIES|SUFFIX|SYMBOLIC|TARGET_ARCHIVES_MAY_BE_SHARED_LIBS|TARGET_MESSAGES|TARGET_SUPPORTS_SHARED_LIBS|TESTS|TEST_INCLUDE_FILE|TEST_INCLUDE_FILES|TIMEOUT|TIMEOUT_AFTER_MATCH|TYPE|USE_FOLDERS|VALUE|VARIABLES|VERSION|VISIBILITY_INLINES_HIDDEN|VS_(?:CONFIGURATION_TYPE|COPY_TO_OUT_DIR|DEBUGGER_(?:COMMAND|COMMAND_ARGUMENTS|ENVIRONMENT|WORKING_DIRECTORY)|DEPLOYMENT_CONTENT|DEPLOYMENT_LOCATION|DOTNET_REFERENCES|DOTNET_REFERENCES_COPY_LOCAL|INCLUDE_IN_VSIX|IOT_STARTUP_TASK|KEYWORD|RESOURCE_GENERATOR|SCC_AUXPATH|SCC_LOCALPATH|SCC_PROJECTNAME|SCC_PROVIDER|SDK_REFERENCES|SHADER_(?:DISABLE_OPTIMIZATIONS|ENABLE_DEBUG|ENTRYPOINT|FLAGS|MODEL|OBJECT_FILE_NAME|OUTPUT_HEADER_FILE|TYPE|VARIABLE_NAME)|STARTUP_PROJECT|TOOL_OVERRIDE|USER_PROPS|WINRT_COMPONENT|WINRT_EXTENSIONS|WINRT_REFERENCES|XAML_TYPE)|WILL_FAIL|WIN32_EXECUTABLE|WINDOWS_EXPORT_ALL_SYMBOLS|WORKING_DIRECTORY|WRAP_EXCLUDE|XCODE_(?:EMIT_EFFECTIVE_PLATFORM_NAME|EXPLICIT_FILE_TYPE|FILE_ATTRIBUTES|LAST_KNOWN_FILE_TYPE|PRODUCT_TYPE|SCHEME_(?:ADDRESS_SANITIZER|ADDRESS_SANITIZER_USE_AFTER_RETURN|ARGUMENTS|DISABLE_MAIN_THREAD_CHECKER|DYNAMIC_LIBRARY_LOADS|DYNAMIC_LINKER_API_USAGE|ENVIRONMENT|EXECUTABLE|GUARD_MALLOC|MAIN_THREAD_CHECKER_STOP|MALLOC_GUARD_EDGES|MALLOC_SCRIBBLE|MALLOC_STACK|THREAD_SANITIZER(?:_STOP)?|UNDEFINED_BEHAVIOUR_SANITIZER(?:_STOP)?|ZOMBIE_OBJECTS))|XCTEST)\b/,keyword:/\b(?:add_compile_definitions|add_compile_options|add_custom_command|add_custom_target|add_definitions|add_dependencies|add_executable|add_library|add_link_options|add_subdirectory|add_test|aux_source_directory|break|build_command|build_name|cmake_host_system_information|cmake_minimum_required|cmake_parse_arguments|cmake_policy|configure_file|continue|create_test_sourcelist|ctest_build|ctest_configure|ctest_coverage|ctest_empty_binary_directory|ctest_memcheck|ctest_read_custom_files|ctest_run_script|ctest_sleep|ctest_start|ctest_submit|ctest_test|ctest_update|ctest_upload|define_property|else|elseif|enable_language|enable_testing|endforeach|endfunction|endif|endmacro|endwhile|exec_program|execute_process|export|export_library_dependencies|file|find_file|find_library|find_package|find_path|find_program|fltk_wrap_ui|foreach|function|get_cmake_property|get_directory_property|get_filename_component|get_property|get_source_file_property|get_target_property|get_test_property|if|include|include_directories|include_external_msproject|include_guard|include_regular_expression|install|install_files|install_programs|install_targets|link_directories|link_libraries|list|load_cache|load_command|macro|make_directory|mark_as_advanced|math|message|option|output_required_files|project|qt_wrap_cpp|qt_wrap_ui|remove|remove_definitions|return|separate_arguments|set|set_directory_properties|set_property|set_source_files_properties|set_target_properties|set_tests_properties|site_name|source_group|string|subdir_depends|subdirs|target_compile_definitions|target_compile_features|target_compile_options|target_include_directories|target_link_directories|target_link_libraries|target_link_options|target_sources|try_compile|try_run|unset|use_mangled_mesa|utility_source|variable_requires|variable_watch|while|write_file)(?=\s*\()\b/,boolean:/\b(?:FALSE|OFF|ON|TRUE)\b/,namespace:/\b(?:INTERFACE|PRIVATE|PROPERTIES|PUBLIC|SHARED|STATIC|TARGET_OBJECTS)\b/,operator:/\b(?:AND|DEFINED|EQUAL|GREATER|LESS|MATCHES|NOT|OR|STREQUAL|STRGREATER|STRLESS|VERSION_EQUAL|VERSION_GREATER|VERSION_LESS)\b/,inserted:{pattern:/\b\w+::\w+\b/,alias:"class-name"},number:/\b\d+(?:\.\d+)*\b/,function:/\b[a-z_]\w*(?=\s*\()\b/i,punctuation:/[()>}]|\$[<{]/}; +Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"]; +!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json; +!function(n){var e=/("|')(?:\\(?:\r\n?|\n|.)|(?!\1)[^\\\r\n])*\1/;n.languages.json5=n.languages.extend("json",{property:[{pattern:RegExp(e.source+"(?=\\s*:)"),greedy:!0},{pattern:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/,alias:"unquoted"}],string:{pattern:e,greedy:!0},number:/[+-]?\b(?:NaN|Infinity|0x[a-fA-F\d]+)\b|[+-]?(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[eE][+-]?\d+\b)?/})}(Prism); +!function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism); +Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; +!function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism); +!function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;e.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(Prism); +!function(e){var a=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:a,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:a,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(a){/<\?/.test(a.code)&&e.languages["markup-templating"].buildPlaceholders(a,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"php")}))}(Prism); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +Prism.languages.verilog={comment:{pattern:/\/\/.*|\/\*[\s\S]*?\*\//,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"kernel-function":{pattern:/\B\$\w+\b/,alias:"property"},constant:/\B`\w+\b/,function:/\b\w+(?=\()/,keyword:/\b(?:alias|and|assert|assign|assume|automatic|before|begin|bind|bins|binsof|bit|break|buf|bufif0|bufif1|byte|case|casex|casez|cell|chandle|class|clocking|cmos|config|const|constraint|context|continue|cover|covergroup|coverpoint|cross|deassign|default|defparam|design|disable|dist|do|edge|else|end|endcase|endclass|endclocking|endconfig|endfunction|endgenerate|endgroup|endinterface|endmodule|endpackage|endprimitive|endprogram|endproperty|endsequence|endspecify|endtable|endtask|enum|event|expect|export|extends|extern|final|first_match|for|force|foreach|forever|fork|forkjoin|function|generate|genvar|highz0|highz1|if|iff|ifnone|ignore_bins|illegal_bins|import|incdir|include|initial|inout|input|inside|instance|int|integer|interface|intersect|join|join_any|join_none|large|liblist|library|local|localparam|logic|longint|macromodule|matches|medium|modport|module|nand|negedge|new|nmos|nor|noshowcancelled|not|notif0|notif1|null|or|output|package|packed|parameter|pmos|posedge|primitive|priority|program|property|protected|pull0|pull1|pulldown|pullup|pulsestyle_ondetect|pulsestyle_onevent|pure|rand|randc|randcase|randsequence|rcmos|real|realtime|ref|reg|release|repeat|return|rnmos|rpmos|rtran|rtranif0|rtranif1|scalared|sequence|shortint|shortreal|showcancelled|signed|small|solve|specify|specparam|static|string|strong0|strong1|struct|super|supply0|supply1|table|tagged|task|this|throughout|time|timeprecision|timeunit|tran|tranif0|tranif1|tri|tri0|tri1|triand|trior|trireg|type|typedef|union|unique|unsigned|use|uwire|var|vectored|virtual|void|wait|wait_order|wand|weak0|weak1|while|wildcard|wire|with|within|wor|xnor|xor)\b/,important:/\b(?:always|always_comb|always_ff|always_latch)\b(?: *@)?/,number:/\B##?\d+|(?:\b\d+)?'[odbh] ?[\da-fzx_?]+|\b(?:\d*[._])?\d+(?:e[-+]?\d+)?/i,operator:/[-+{}^~%*\/?=!<>&|]+/,punctuation:/[[\];(),.:]/}; +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,(function(){return t})).replace(/<>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=!0;Prism.plugins.lineHighlight={highlightLines:function(r,a,u){var c=(a="string"==typeof a?a:r.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+r.getAttribute("data-line-offset")||0,h=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML=" 
     ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(r).lineHeight),f=Prism.util.isActive(r,t),p=r.querySelector("code"),g=f?r:p||r,m=[],v=p&&g!=p?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(r,p):0;c.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i,o=r.querySelector('.line-highlight[data-range="'+e+'"]')||document.createElement("div");if(m.push((function(){o.setAttribute("aria-hidden","true"),o.setAttribute("data-range",e),o.className=(u||"")+" line-highlight"})),f&&Prism.plugins.lineNumbers){var s=Prism.plugins.lineNumbers.getLine(r,i),l=Prism.plugins.lineNumbers.getLine(r,n);if(s){var a=s.offsetTop+v+"px";m.push((function(){o.style.top=a}))}if(l){var c=l.offsetTop-s.offsetTop+l.offsetHeight+"px";m.push((function(){o.style.height=c}))}}else m.push((function(){o.setAttribute("data-start",String(i)),n>i&&o.setAttribute("data-end",String(n)),o.style.top=(i-d-1)*h+v+"px",o.textContent=new Array(n-i+2).join(" \n")}));m.push((function(){o.style.width=r.scrollWidth+"px"})),m.push((function(){g.appendChild(o)}))}));var y=r.id;if(f&&Prism.util.isActive(r,i)&&y){s(r,i)||m.push((function(){r.classList.add(i)}));var b=parseInt(r.getAttribute("data-start")||"1");o(".line-numbers-rows > span",r).forEach((function(e,t){var i=t+b;e.onclick=function(){var e=y+"."+i;n=!1,location.hash=e,setTimeout((function(){n=!0}),1)}}))}return function(){m.forEach(l)}}};var r=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(a(t)){var i=0;o(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(a(n)){clearTimeout(r);var o=Prism.plugins.lineNumbers,l=i.plugins&&i.plugins.lineNumbers;s(n,t)&&o&&!l?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),r=setTimeout(u,1))}})),window.addEventListener("hashchange",u),window.addEventListener("resize",(function(){o("pre").filter(a).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(l)}))}function o(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function s(e,t){return e.classList.contains(t)}function l(e){e()}function a(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function u(){var e=location.hash.slice(1);o(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),r=document.getElementById(i);r&&(r.hasAttribute("data-line")||r.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(r,t,"temporary ")(),n&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}(); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var e=[],t={},n=function(){};Prism.plugins.toolbar={};var a=Prism.plugins.toolbar.registerButton=function(n,a){var r;r="function"==typeof a?a:function(e){var t;return"function"==typeof a.onClick?((t=document.createElement("button")).type="button",t.addEventListener("click",(function(){a.onClick.call(this,e)}))):"string"==typeof a.url?(t=document.createElement("a")).href=a.url:t=document.createElement("span"),a.className&&t.classList.add(a.className),t.textContent=a.text,t},n in t?console.warn('There is a button with the key "'+n+'" registered already.'):e.push(t[n]=r)},r=Prism.plugins.toolbar.hook=function(a){var r=a.element.parentNode;if(r&&/pre/i.test(r.nodeName)&&!r.parentNode.classList.contains("code-toolbar")){var o=document.createElement("div");o.classList.add("code-toolbar"),r.parentNode.insertBefore(o,r),o.appendChild(r);var i=document.createElement("div");i.classList.add("toolbar");var l=e,d=function(e){for(;e;){var t=e.getAttribute("data-toolbar-order");if(null!=t)return(t=t.trim()).length?t.split(/\s*,\s*/g):[];e=e.parentElement}}(a.element);d&&(l=d.map((function(e){return t[e]||n}))),l.forEach((function(e){var t=e(a);if(t){var n=document.createElement("div");n.classList.add("toolbar-item"),n.appendChild(t),i.appendChild(n)}})),o.appendChild(i)}};a("label",(function(e){var t=e.element.parentNode;if(t&&/pre/i.test(t.nodeName)&&t.hasAttribute("data-label")){var n,a,r=t.getAttribute("data-label");try{a=document.querySelector("template#"+r)}catch(e){}return a?n=a.content:(t.hasAttribute("data-url")?(n=document.createElement("a")).href=t.getAttribute("data-url"):n=document.createElement("span"),n.textContent=r),n}})),Prism.hooks.add("complete",r)}}(); +!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document)if(Prism.plugins.toolbar){var e={none:"Plain text",plain:"Plain text",plaintext:"Plain text",text:"Plain text",txt:"Plain text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache Configuration",apl:"APL",aql:"AQL",ino:"Arduino",arff:"ARFF",armasm:"ARM Assembly","arm-asm":"ARM Assembly",art:"Arturo",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET (C#)",asm6502:"6502 Assembly",asmatmel:"Atmel AVR Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt",avisynth:"AviSynth",avs:"AviSynth","avro-idl":"Avro IDL",avdl:"Avro IDL",awk:"AWK",gawk:"GAWK",basic:"BASIC",bbcode:"BBcode",bnf:"BNF",rbnf:"RBNF",bsl:"BSL (1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS Extras",csv:"CSV",cue:"CUE",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT (Graphviz)",gv:"DOT (Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore security rules",ftl:"FreeMarker Template Language",gml:"GameMaker Language",gamemakerlanguage:"GameMaker Language",gap:"GAP (CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",gettext:"gettext",po:"gettext",glsl:"GLSL",gn:"GN",gni:"GN","linker-script":"GNU Linker Script",ld:"GNU Linker Script","go-module":"Go module","go-mod":"Go module",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU Message Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS Extras",json:"JSON",webmanifest:"Web App Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack trace","js-templates":"JS Templates",keepalived:"Keepalived Configure",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir (КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM IR",log:"Log file",lolcode:"LOLCODE",magma:"Magma (CAS)",md:"Markdown","markup-templating":"Markup templating",matlab:"MATLAB",maxscript:"MAXScript",mel:"MEL",metafont:"METAFONT",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object Pascal",psl:"PATROL Scripting Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP Extras","plant-uml":"PlantUML",plantuml:"PlantUML",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q (kdb+ database)",qml:"QML",rkt:"Racket",cshtml:"Razor C#",razor:"Razor C#",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rpy:"Ren'py",res:"ReScript",rest:"reST (reStructuredText)",robotframework:"Robot Framework",robot:"Robot Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)","shell-session":"Shell session","sh-session":"Shell session",shellsession:"Shell session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity (Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy (Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",stata:"Stata Ado",iecst:"Structured Text (IEC 61131-3)",supercollider:"SuperCollider",sclang:"SuperCollider",systemd:"Systemd configuration file","t4-templating":"T4 templating","t4-cs":"T4 Text Templates (C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates (VB)",tap:"TAP",tt2:"Template Toolkit 2",toml:"TOML",trickle:"trickle",troy:"troy",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uorazor:"UO Razor Script",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly","web-idl":"Web IDL",webidl:"Web IDL",wgsl:"WGSL",wiki:"Wiki markup",wolfram:"Wolfram language",nb:"Mathematica Notebook",wl:"Wolfram language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo (REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",(function(a){var t=a.element.parentNode;if(t&&/pre/i.test(t.nodeName)){var o,s=t.getAttribute("data-language")||e[a.language]||((o=a.language)?(o.substring(0,1).toUpperCase()+o.substring(1)).replace(/s(?=cript)/,"S"):o);if(s){var r=document.createElement("span");return r.textContent=s,r}}}))}else console.warn("Show Languages plugin loaded before Toolbar plugin.")}(); +!function(){function t(t){var e=document.createElement("textarea");e.value=t.getText(),e.style.top="0",e.style.left="0",e.style.position="fixed",document.body.appendChild(e),e.focus(),e.select();try{var o=document.execCommand("copy");setTimeout((function(){o?t.success():t.error()}),1)}catch(e){setTimeout((function(){t.error(e)}),1)}document.body.removeChild(e)}"undefined"!=typeof Prism&&"undefined"!=typeof document&&(Prism.plugins.toolbar?Prism.plugins.toolbar.registerButton("copy-to-clipboard",(function(e){var o=e.element,n=function(t){var e={copy:"Copy","copy-error":"Press Ctrl+C to copy","copy-success":"Copied!","copy-timeout":5e3};for(var o in e){for(var n="data-prismjs-"+o,c=t;c&&!c.hasAttribute(n);)c=c.parentElement;c&&(e[o]=c.getAttribute(n))}return e}(o),c=document.createElement("button");c.className="copy-to-clipboard-button",c.setAttribute("type","button");var r=document.createElement("span");return c.appendChild(r),u("copy"),function(e,o){e.addEventListener("click",(function(){!function(e){navigator.clipboard?navigator.clipboard.writeText(e.getText()).then(e.success,(function(){t(e)})):t(e)}(o)}))}(c,{getText:function(){return o.textContent},success:function(){u("copy-success"),i()},error:function(){u("copy-error"),setTimeout((function(){!function(t){window.getSelection().selectAllChildren(t)}(o)}),1),i()}}),c;function i(){setTimeout((function(){u("copy")}),n["copy-timeout"])}function u(t){r.textContent=n[t],c.setAttribute("data-copy-state",t)}})):console.warn("Copy to Clipboard plugin loaded before Toolbar plugin."))}(); diff --git a/utils/cmd.go b/utils/cmd.go new file mode 100644 index 0000000..f8b1390 --- /dev/null +++ b/utils/cmd.go @@ -0,0 +1,15 @@ +package utils + +import ( + "os/exec" +) + +func RunCmdByDir(dir string, cmdName string, arg ...string) (string, error) { + cmd := exec.Command(cmdName, arg ...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + return "", err + } + return string(out), nil +} diff --git a/utils/cmd_test.go b/utils/cmd_test.go new file mode 100644 index 0000000..40a05d2 --- /dev/null +++ b/utils/cmd_test.go @@ -0,0 +1,13 @@ +package utils_test + +import ( + "blog/utils" + "testing" +) + +func TestRunCmdByDir(t *testing.T) { + _, err := utils.RunCmdByDir("./", "ping", "127.0.0.1") + if err != nil { + t.Error("run cmd error", err) + } +} diff --git a/utils/file.go b/utils/file.go new file mode 100644 index 0000000..f10a854 --- /dev/null +++ b/utils/file.go @@ -0,0 +1,65 @@ +package utils + +import ( + "errors" + "fmt" + "io" + "os" +) + +func IsDir(name string) bool { + if info, err := os.Stat(name); err == nil { + return info.IsDir() + } + return false +} + + +func IsFile(filename string) bool { + existed := true + if _, err := os.Stat(filename); os.IsNotExist(err) { + existed = false + } + return existed +} + +func MakeDir(dir string) error { + if !IsDir(dir) { + return os.MkdirAll(dir, os.ModePerm) + } + return nil +} + +func RemoveDir(dir string) error { + + if !IsDir(dir) { + return errors.New("cannot delete without directory") + } + + return os.RemoveAll(dir) +} + +func CopyFile(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} \ No newline at end of file diff --git a/utils/git.go b/utils/git.go new file mode 100644 index 0000000..833ee9d --- /dev/null +++ b/utils/git.go @@ -0,0 +1,19 @@ +package utils + +import ( + "errors" + "strings" +) + +//通过git url 返回仓库的名字 +func GetRepoName(gitUrl string) (string, error) { + + if !strings.HasSuffix(gitUrl, ".git") { + return "", errors.New("git URL must end with .git!") + } + + noSuffixUrl := strings.TrimSuffix(gitUrl, ".git") + urlArr := strings.Split(noSuffixUrl, "/") + + return urlArr[ len(urlArr)-1 ], nil +} diff --git a/utils/git_test.go b/utils/git_test.go new file mode 100644 index 0000000..e71318c --- /dev/null +++ b/utils/git_test.go @@ -0,0 +1,14 @@ +package utils_test + +import ( + "blog/utils" + "testing" +) + +func TestGetRepoName(t *testing.T) { + url := "http://jsit205.vaiwan.cn/JiXieShi/blog.git" + name, err := utils.GetRepoName(url) + if err != nil || name != "blog" { + t.Error("repository name error") + } +} diff --git a/utils/short_url.go b/utils/short_url.go new file mode 100644 index 0000000..3471dad --- /dev/null +++ b/utils/short_url.go @@ -0,0 +1,43 @@ +package utils + +import ( + "crypto/md5" + "fmt" + "strconv" +) + +const charset = "A0a12B3b4CDc56Ede7FGf8Hg9IhJKiLjkMNlmOPnQRopqrSstTuvUVwxWXyYzZ" + +func generateCharset(url, hexMd5 string, len, sectionNum int, cb func(url, keyword string) bool) string { + for i := 0; i < sectionNum; i++ { + sectionHex := hexMd5[i*8 : 8+i*8] + bits, _ := strconv.ParseUint(sectionHex, 16, 32) + bits = bits & 0x3FFFFFFF + keyword := "" + for j := 0; j < len; j++ { + idx := bits & 0x3D + keyword = keyword + string(charset[idx]) + bits = bits >> 5 + } + if cb(url, keyword) { + return keyword + } + } + return "" +} + +// 起初生成6位的短码,当四组6位短码都重复时,再生成8位的短码,因此总共会有8个短码供你选择。 + +func GenerateShortUrl(url string, cb func(url, keyword string) bool) string { + if url == "" || cb == nil { + return "" + } + hexMd5 := fmt.Sprintf("%x", md5.Sum([]byte(url))) + sections := len(hexMd5) / 8 + + keyword := generateCharset(url, hexMd5, 6, sections, cb) + if keyword == "" { + return generateCharset(url, hexMd5, 8, sections, cb) + } + return keyword +} diff --git a/utils/short_url_test.go b/utils/short_url_test.go new file mode 100644 index 0000000..b94c241 --- /dev/null +++ b/utils/short_url_test.go @@ -0,0 +1,14 @@ +package utils_test + +import ( + "blog/utils" + "testing" +) + +func TestGenerateShortUrl(t *testing.T) { + url := "http://jsit205.vaiwan.cn/JiXieShi/blog.git" + shortUrl := utils.GenerateShortUrl(url, func(url, keyword string) bool { return true }) + if shortUrl != "ItMIz7" { + t.Error("generate short URL error") + } +} diff --git a/配置说明.md b/配置说明.md new file mode 100644 index 0000000..1bebf04 --- /dev/null +++ b/配置说明.md @@ -0,0 +1,35 @@ +## config.json 配置说明 + +- "port": 服务器监听的端口号, +- "pageSize": 首页每一页的文章数量, +- "descriptionLen": 文章没有配置description字段时,默认取文章内容多少个字作为描述, +- "author": 博客作者,网站底部展示, +- "icp": 网站的备案号, +- "webHookSecret": 博客文章更新勾子的密钥,这里要和你在仓库设置的密钥一样, +- "categoryDisplayQuantity": 在分类页面下,每个分类下最多展示多少篇文章, +- "utterancesRepo": 是否开启utterances评论,留空没有评论,否则填写评论存储的仓库name/repo, +- "timeLayout": 解析时间的格式,保持和你文章里面的date字段一样,除非了解Golang的时间解析,否则不要修改, +- "siteName": 网站的名字, +- "documentGitUrl": 你文章的git地址,应用会把文章克隆在当前目录下,必须公开并且以.git结尾, +- "htmlKeywords": 网页里面的htmlKeywords, +- "htmlDescription": 网页里面的htmlDescription, +- "themePath": 主题路径,留空使用/blog, +- "themeColor": 博客的主题颜色, +- "dashboardEntrance": 网站仪表盘的访问路径,留空使用/admin, +- "themeOption": 网站可选择的主题颜色 + + +## MD 文章支持的字段 + +- "title": 文章标题,不填使用文件名, +- "date": 文章日期,排序使用(导航文章使用这个来排序), +- "description": 文章描述 +- "tags": 文章 tag +- "author": 文章作者 +- "musicId": 网易云的歌单ID + +> 文章的这些字段全部可以为空,但是没有日期会默认使用文件生成的日期,那样每次迁移文档时间都是不可控的。 + +## 其他 +开启utterances评论之后,utterancesRepo指向的仓库必须是公开并且可以被评论的,具体使用请访问 https://utteranc.es +webHook的地址: 你的域名/api/git_push_hook