├── public
├── imgs
│ ├── alipay.png
│ ├── favicon.ico
│ ├── gogs-lg.png
│ ├── macaron.png
│ ├── brands
│ │ ├── igt.png
│ │ ├── notabug.png
│ │ ├── prosnav.jpg
│ │ ├── xizhe.png
│ │ ├── yeeuu.png
│ │ ├── cnssuestc.jpg
│ │ ├── gxbolian.jpg
│ │ └── tripleback.png
│ └── screenshoots
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ └── 9.png
├── scss
│ ├── main.scss
│ ├── _markdown.scss
│ ├── _home.scss
│ ├── _common.scss
│ └── _unsemantic.scss
├── css
│ ├── prettify.css
│ └── main.css
└── js
│ ├── gogsweb.js
│ ├── prettify.js
│ └── gogsweb.min.js
├── .gitignore
├── .bra.toml
├── .gopmfile
├── conf
├── app.ini
└── locale
│ ├── locale_zh-CN.ini
│ ├── locale_en-US.ini
│ ├── locale_ru-RU.ini
│ └── locale_fr-FR.ini
├── README.md
├── templates
├── page.tmpl
├── macaron
│ ├── head.tmpl
│ ├── navbar.tmpl
│ └── footer.tmpl
├── gogs
│ ├── head.tmpl
│ ├── footer.tmpl
│ └── navbar.tmpl
├── base
│ ├── disqus.tmpl
│ └── docs.tmpl
├── document_gogs.tmpl
├── document_macaron.tmpl
└── home_gogs.tmpl
├── routers
├── macaron.go
└── gogs.go
├── modules
├── base
│ └── template.go
├── setting
│ └── setting.go
└── log
│ └── log.go
├── models
├── http.go
├── press.go
└── models.go
├── gogsweb.go
└── LICENSE
/public/imgs/alipay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/alipay.png
--------------------------------------------------------------------------------
/public/imgs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/favicon.ico
--------------------------------------------------------------------------------
/public/imgs/gogs-lg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/gogs-lg.png
--------------------------------------------------------------------------------
/public/imgs/macaron.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/macaron.png
--------------------------------------------------------------------------------
/public/imgs/brands/igt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/igt.png
--------------------------------------------------------------------------------
/public/imgs/brands/notabug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/notabug.png
--------------------------------------------------------------------------------
/public/imgs/brands/prosnav.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/prosnav.jpg
--------------------------------------------------------------------------------
/public/imgs/brands/xizhe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/xizhe.png
--------------------------------------------------------------------------------
/public/imgs/brands/yeeuu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/yeeuu.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/1.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/2.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/3.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/4.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/5.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/6.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/7.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/8.png
--------------------------------------------------------------------------------
/public/imgs/screenshoots/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/screenshoots/9.png
--------------------------------------------------------------------------------
/public/imgs/brands/cnssuestc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/cnssuestc.jpg
--------------------------------------------------------------------------------
/public/imgs/brands/gxbolian.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/gxbolian.jpg
--------------------------------------------------------------------------------
/public/imgs/brands/tripleback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gogs/gogsweb/HEAD/public/imgs/brands/tripleback.png
--------------------------------------------------------------------------------
/public/scss/main.scss:
--------------------------------------------------------------------------------
1 | /*!
2 | Copyright © Gogs 2014, all right reversed.
3 | */
4 | @import "unsemantic";
5 | @import "common";
6 | @import "home";
7 | @import "markdown";
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | gogsweb
3 | *.exe
4 | *.exe~
5 | config.codekit
6 | conf/docTree.json
7 | docs/
8 | .idea/
9 | .sass-cache
10 | conf/custom.ini
11 | gogsweb.sublime-project
12 | gogsweb.sublime-workspace
--------------------------------------------------------------------------------
/.bra.toml:
--------------------------------------------------------------------------------
1 | [run]
2 | init_cmds = [["./gogsweb"]]
3 | watch_all = true
4 | watch_dirs = [
5 | "$WORKDIR/conf",
6 | "$WORKDIR/models",
7 | "$WORKDIR/modules",
8 | "$WORKDIR/routers"
9 | ]
10 | watch_exts = [".go", ".ini"]
11 | build_delay = 1500
12 | cmds = [
13 | ["go", "install"],
14 | ["go", "build"],
15 | ["./gogsweb"]
16 | ]
--------------------------------------------------------------------------------
/.gopmfile:
--------------------------------------------------------------------------------
1 | [target]
2 | path = github.com/gogits/gogsweb
3 |
4 | [deps]
5 | github.com/Unknwon/com =
6 | github.com/Unknwon/goconfig =
7 | github.com/Unknwon/macaron =
8 | github.com/macaron-contrib/i18n =
9 | github.com/robfig/cron =
10 | github.com/slene/blackfriday =
11 |
12 | [res]
13 | include = templates|public|conf
14 |
15 |
--------------------------------------------------------------------------------
/conf/app.ini:
--------------------------------------------------------------------------------
1 | apps = gogs,macaron
2 |
3 | [app]
4 | run_mode = dev
5 | http_port = 8091
6 | https = false
7 | https_cert =
8 | https_key =
9 |
10 | [i18n]
11 | langs = en-US,zh-CN,fr-FR
12 | names = English,简体中文,Français
13 |
14 | [github]
15 | client_id =
16 | client_secret =
17 |
18 | [gogs]
19 | repo_name = gogits/docs
20 |
21 | [macaron]
22 | repo_name = macaron-contrib/docs
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Gogs Web
2 | ========
3 |
4 | An open source project for official documentation website of [Gogs](http://gogs.io) and [Macaron](http://macaron.gogs.io).
5 |
6 | ## Introduction
7 |
8 | As a study example of [Macaron](http://macaron.gogs.io) framework, this project has following features to show you:
9 |
10 | - Multiple sites in one program.
11 | - TODO
12 |
13 | ## Configuration
14 |
15 | TODO
16 |
17 | ## License
18 |
19 | Gogs Web is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text.
--------------------------------------------------------------------------------
/templates/page.tmpl:
--------------------------------------------------------------------------------
1 | {{template "gogs/head" .}}
2 | {{template "gogs/navbar" .}}
3 |
4 |
5 |
6 |
7 |
8 | {{.Data|str2html}}
9 |
10 |
11 |
14 | {{template "base/disqus" .}}
15 |
16 |
17 |
18 | {{template "gogs/footer" .}}
--------------------------------------------------------------------------------
/public/css/prettify.css:
--------------------------------------------------------------------------------
1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
--------------------------------------------------------------------------------
/templates/macaron/head.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Macaron - {{.i18n.Tr "macaron_desc"}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/templates/gogs/head.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gogs: Go Git Service - {{.i18n.Tr "gogs_desc"}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/templates/base/disqus.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
13 | Please enable JavaScript to view the comments powered by Disqus.
14 | comments powered by
--------------------------------------------------------------------------------
/templates/gogs/footer.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
19 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/templates/base/docs.tmpl:
--------------------------------------------------------------------------------
1 | {{with .Doc}}
2 | {{range .Docs}}
3 |
4 | {{if .Name}}
5 | {{ if .IsDir}}
6 |
7 |
8 | {{if .HasContent}}
9 |
{{.Name}}
10 | {{else}}
11 | {{.Name}}
12 | {{end}}
13 |
14 | {{template "base/docs" dict "root" $.root "Doc" .}}
15 |
16 | {{else}}
17 | {{.Name}}
18 | {{end}}
19 | {{end}}
20 |
21 | {{end}}
22 | {{end}}
--------------------------------------------------------------------------------
/routers/macaron.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package routers
16 |
17 | import (
18 | "github.com/Unknwon/macaron"
19 | "github.com/macaron-contrib/i18n"
20 | )
21 |
22 | func MacaronDocs(ctx *macaron.Context, locale i18n.Locale) {
23 | docs(ctx, locale, "macaron")
24 | }
25 |
26 | func MacaronStatic(ctx *macaron.Context) {
27 | docsStatic(ctx, "macaron")
28 | }
29 |
--------------------------------------------------------------------------------
/templates/macaron/navbar.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{range .AllLangs}}
8 | {{.Name}}
9 | {{end}}
10 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/templates/gogs/navbar.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{range .AllLangs}}
8 | {{.Name}}
9 | {{end}}
10 |
11 |
12 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/templates/document_gogs.tmpl:
--------------------------------------------------------------------------------
1 | {{template "gogs/head" .}}
2 | {{template "gogs/navbar" .}}
3 |
4 |
5 |
6 |
7 |
8 | {{with .DocRoot.Doc}}
9 | {{if .HasContent}}
10 |
11 | {{end}}
12 | {{template "base/docs" dict "root" $ "Doc" .}}
13 | {{end}}
14 |
15 |
16 |
17 |
18 |
19 | {{.Data|str2html}}
20 |
21 |
22 |
25 | {{template "base/disqus" .}}
26 |
27 |
28 |
29 | {{template "gogs/footer" .}}
--------------------------------------------------------------------------------
/templates/macaron/footer.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
19 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/templates/document_macaron.tmpl:
--------------------------------------------------------------------------------
1 | {{template "macaron/head" .}}
2 | {{template "macaron/navbar" .}}
3 |
4 |
5 |
6 |
7 |
8 | {{with .DocRoot.Doc}}
9 | {{if .HasContent}}
10 |
11 | {{end}}
12 | {{template "base/docs" dict "root" $ "Doc" .}}
13 | {{end}}
14 |
15 |
16 |
17 |
18 |
19 | {{.Data|str2html}}
20 |
21 |
22 |
25 | {{template "base/disqus" .}}
26 |
27 |
28 |
29 | {{template "macaron/footer" .}}
--------------------------------------------------------------------------------
/conf/locale/locale_zh-CN.ini:
--------------------------------------------------------------------------------
1 | gogs_desc = 极易搭建的自助 Git 服务
2 | macaron_desc = 高生产力和模块化设计的 Go Web 框架
3 |
4 | menu = 菜单
5 | home = 首页
6 | download = 下载安装
7 | docs = 使用手册
8 | blog = 官方博客
9 |
10 | try_demo = 在线体验
11 | screenshots = 界面预览
12 | scroll = 滑动
13 | get_started = 开始使用
14 | who_are_use = 使用 Gogs 的团队及公司
15 |
16 | about = 关于我们
17 | team = 开发团队
18 | donate = 捐赠我们
19 |
20 | easy_install = 易安装
21 | easy_install_desc = 您除了可以根据操作系统平台通过 二进制运行 ,还可以通过 Docker 或 Vagrant ,以及 包管理 安装。
22 | cross_platform = 跨平台
23 | cross_platform_desc = 任何 Go 语言 支持的平台都可以运行 Gogs,包括 Windows、Mac、Linux 以及 ARM。
24 | lightweight = 轻量级
25 | lightweight_desc = 一个廉价的树莓派的配置足以满足 Gogs 的最低系统硬件要求。
26 | opensource = 开源化
27 | opensource_desc = 所有的代码都开源在 GitHub 上,赶快加入我们来共同发展这个伟大的项目!
28 |
29 | faq = 常见问题
30 | known_issues = 已知问题
31 | troubleshooting = 故障排查
32 | cheat_sheet = 配置文件手册
33 | release_notes = 公告与高阶指南
34 | subscribe_news = 订阅新闻邮件
--------------------------------------------------------------------------------
/modules/base/template.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknown
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package base
16 |
17 | import (
18 | "errors"
19 | "html/template"
20 | )
21 |
22 | func Dict(values ...interface{}) (map[string]interface{}, error) {
23 | if len(values)%2 != 0 {
24 | return nil, errors.New("invalid dict call")
25 | }
26 | dict := make(map[string]interface{}, len(values)/2)
27 | for i := 0; i < len(values); i += 2 {
28 | key, ok := values[i].(string)
29 | if !ok {
30 | return nil, errors.New("dict keys must be strings")
31 | }
32 | dict[key] = values[i+1]
33 | }
34 | return dict, nil
35 | }
36 |
37 | func Str2html(raw string) template.HTML {
38 | return template.HTML(raw)
39 | }
40 |
--------------------------------------------------------------------------------
/conf/locale/locale_en-US.ini:
--------------------------------------------------------------------------------
1 | gogs_desc = A painless self-hosted Git service
2 | macaron_desc = High productive and modular design web framework in Go
3 |
4 | menu = Menu
5 | home = Home
6 | download = Download
7 | docs = Documentation
8 | blog = Blog
9 |
10 | try_demo = Try a Demo
11 | screenshots = Screenshots
12 | scroll = Scroll
13 | get_started = Getting Started
14 | who_are_use = Who Is Using Gogs
15 |
16 | about = About
17 | team = Team
18 | donate = Donate
19 |
20 | easy_install = Easy to install
21 | easy_install_desc = Simply run the binary for your platform. Or ship Gogs with Docker or Vagrant , or get it packaged .
22 | cross_platform = Cross-platform
23 | cross_platform_desc = Gogs runs anywhere Go can compile for: Windows, Mac, Linux, ARM, etc.
24 | lightweight = Lightweight
25 | lightweight_desc = Gogs has low minimal requirements and can run on an inexpensive Raspberry Pi.
26 | opensource = Open Source
27 | opensource_desc = It's all on GitHub ! Join us by contributing to make this project even better.
28 |
29 | faq = FAQs
30 | known_issues = Known issues
31 | troubleshooting = Troubleshooting
32 | cheat_sheet = Configuration Cheat Sheet
33 | release_notes = Release notes and tips
34 | subscribe_news = Subscribe Newsletter
--------------------------------------------------------------------------------
/conf/locale/locale_ru-RU.ini:
--------------------------------------------------------------------------------
1 | gogs_desc = Хранилище Git-репозиториев, написанное на Go
2 | macaron_desc = Высокопроизводительный модульный веб-фреймворк на Go
3 |
4 | menu = Меню
5 | home = Главная
6 | download = Скачать
7 | docs = Документация
8 | blog = Блог
9 |
10 | try_demo = Попробовать
11 | screenshots = Скриншоты
12 | scroll = Прокрутка
13 | get_started = С чего начать
14 | who_are_use = Кто использует Gogs
15 |
16 | about = О проекте
17 | team = Команда
18 | donate = Поддержать
19 |
20 | easy_install = Простой в установке
21 | easy_install_desc = Просто запустите файл для вашей платформы. Или воспользуйтесь Docker или Vagrant . Или просто установите пакет для вашей системы.
22 | cross_platform = Кросс-платформенный
23 | cross_platform_desc = Gogs работает везде, где работает Go : Windows, Mac, Linux, ARM, и т.д.
24 | lightweight = Легкий
25 | lightweight_desc = Минимальные системные требования позволяют запустить Gogs даже на Raspberry Pi.
26 | opensource = Открытый
27 | opensource_desc = Весь код на GitHub ! Присоединяйтесь к развитию проекта.
28 |
29 | faq = FAQ
30 | known_issues = Известные проблемы
31 | troubleshooting = Решение проблем
32 | cheat_sheet = Шпаргалка по настройке
33 | release_notes = Замечания к релизу и советы
--------------------------------------------------------------------------------
/conf/locale/locale_fr-FR.ini:
--------------------------------------------------------------------------------
1 | gogs_desc = Un service git auto-hébergé sans-douleur
2 | macaron_desc = Productions élevé et conception modulaire framework web écrit en Go
3 |
4 | menu = Menu
5 | home = Accueil
6 | download = Téléchargement
7 | docs = Documentation
8 | blog = Blog
9 |
10 | try_demo = Essayer la démo
11 | screenshots = Captures d'écran
12 | scroll = Faites défiler
13 | get_started = Prise en main
14 | who_are_use = Qui utilise Gogs
15 |
16 | about = A propos
17 | team = L'équipe
18 | donate = Donner
19 |
20 | easy_install = Facile à installer
21 | easy_install_desc = Simplement en exécutant le binaire sur votre plate-forme. Ou exécuter Gogs avec Docker ou Vagrant , ou l'obtenir par packaged .
22 | cross_platform = Multi-platforme
23 | cross_platform_desc = Gogs fonctionne partout où Go peut compiler : Windows, Mac, Linux, ARM, etc.
24 | lightweight = Léger
25 | lightweight_desc = Gogs a des exigences minimales faibles et peut fonctionner sur un Raspberry Pi peu coûteux.
26 | opensource = Libre de droit
27 | opensource_desc = Il est disponible sur GitHub ! Rejoignez-nous en contribuant à ce projet pour qu'il soit meilleur.
28 |
29 | faq = FAQs
30 | known_issues = Problèmes connus
31 | troubleshooting = Guide de dépannage
32 | cheat_sheet = Fiche de configuration de triche
33 | release_notes = Notes de publication et conseils
34 |
--------------------------------------------------------------------------------
/models/http.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package models
16 |
17 | import (
18 | "flag"
19 | "net"
20 | "net/http"
21 | "time"
22 |
23 | "github.com/gogits/gogsweb/modules/log"
24 | )
25 |
26 | var (
27 | dialTimeout = flag.Duration("dial_timeout", 10*time.Second, "Timeout for dialing an HTTP connection.")
28 | requestTimeout = flag.Duration("request_timeout", 20*time.Second, "Time out for roundtripping an HTTP request.")
29 | )
30 |
31 | func timeoutDial(network, addr string) (net.Conn, error) {
32 | return net.DialTimeout(network, addr, *dialTimeout)
33 | }
34 |
35 | type transport struct {
36 | t http.Transport
37 | }
38 |
39 | func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
40 | timer := time.AfterFunc(*requestTimeout, func() {
41 | t.t.CancelRequest(req)
42 | log.Error("Canceled request for %s", req.URL)
43 | })
44 | defer timer.Stop()
45 | resp, err := t.t.RoundTrip(req)
46 | return resp, err
47 | }
48 |
49 | var (
50 | httpTransport = &transport{t: http.Transport{Dial: timeoutDial, ResponseHeaderTimeout: *requestTimeout / 2}}
51 | httpClient = &http.Client{Transport: httpTransport}
52 | )
53 |
--------------------------------------------------------------------------------
/public/js/gogsweb.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | // Small devices menu.
3 | $('#menu-link').click(function () {
4 | $('#wide-nav').slideToggle('fast');
5 | });
6 |
7 | $('main').click(function () {
8 | if ($('#menu-link').is(':visible')) {
9 | $('#wide-nav').slideUp('fast');
10 | }
11 | });
12 |
13 | // Language option button.
14 | $('#lang').on('change', function () {
15 | document.location.href = this.options[this.selectedIndex].value;
16 | });
17 |
18 | // Render code blocks.
19 | $('.markdown').find('pre > code').parent().addClass('prettyprint');
20 | prettyPrint();
21 |
22 | // Encode url.
23 | var $doc = $('.docs-markdown');
24 | $doc.find('a').each(function () {
25 | var node = $(this);
26 | var link = node.attr('href');
27 | var index = link.indexOf('#');
28 | if (link.indexOf('http') === 0 && link.indexOf(window.location.hostname) === -1) {
29 | return;
30 | }
31 | if (index < 0 || index + 1 > link.length) {
32 | return;
33 | }
34 | var val = link.substring(index + 1, link.length);
35 | val = encodeURIComponent(decodeURIComponent(val).toLowerCase().replace(/\s+/g, '-'));
36 | node.attr('href', link.substring(0, index) + '#' + val);
37 | });
38 |
39 | // Set anchor.
40 | $doc.find('h1, h2, h3, h4, h5, h6').each(function () {
41 | var node = $(this);
42 | if (node.hasClass('ui')) {
43 | return;
44 | }
45 | var val = encodeURIComponent(node.text().toLowerCase().replace(/\s+/g, "-"));
46 | node = node.wrap('
');
47 | node.append(' ');
48 | });
49 | });
--------------------------------------------------------------------------------
/modules/setting/setting.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package setting
16 |
17 | import (
18 | "fmt"
19 |
20 | "github.com/Unknwon/com"
21 | "github.com/Unknwon/macaron"
22 | "gopkg.in/ini.v1"
23 | )
24 |
25 | const (
26 | CFG_PATH = "conf/app.ini"
27 | CFG_CUSTOM_PATH = "conf/custom.ini"
28 | )
29 |
30 | type App struct {
31 | Name string
32 | RepoName string
33 | }
34 |
35 | var (
36 | Cfg *ini.File
37 |
38 | Apps []App
39 | HttpPort int
40 | Https bool
41 | HttpsCert string
42 | HttpsKey string
43 | Langs, Names []string
44 | GithubCred string
45 | )
46 |
47 | func setGithubCredentials(id, secret string) {
48 | GithubCred = "client_id=" + id + "&client_secret=" + secret
49 | }
50 |
51 | func init() {
52 | var err error
53 | Cfg, err = ini.Load(CFG_PATH)
54 | if err != nil {
55 | panic(fmt.Errorf("fail to load config file '%s': %v", CFG_PATH, err))
56 | }
57 | if com.IsFile(CFG_CUSTOM_PATH) {
58 | if err = Cfg.Append(CFG_CUSTOM_PATH); err != nil {
59 | panic(fmt.Errorf("fail to load config file '%s': %v", CFG_CUSTOM_PATH, err))
60 | }
61 | }
62 |
63 | appNames := Cfg.Section("").Key("apps").Strings(",")
64 | Apps = make([]App, len(appNames))
65 | for i, name := range appNames {
66 | Apps[i] = App{name, Cfg.Section(name).Key("repo_name").String()}
67 | }
68 |
69 | sec := Cfg.Section("app")
70 | if sec.Key("run_mode").MustString("dev") == "prod" {
71 | macaron.Env = macaron.PROD
72 | }
73 | HttpPort = sec.Key("http_port").MustInt(8091)
74 | Https = sec.Key("https").MustBool()
75 | HttpsCert = sec.Key("https_cert").String()
76 | HttpsKey = sec.Key("https_key").String()
77 |
78 | Langs = Cfg.Section("i18n").Key("langs").Strings(",")
79 | Names = Cfg.Section("i18n").Key("names").Strings(",")
80 |
81 | setGithubCredentials(Cfg.Section("github").Key("client_id").String(), Cfg.Section("github").Key("client_secret").String())
82 | }
83 |
--------------------------------------------------------------------------------
/public/scss/_markdown.scss:
--------------------------------------------------------------------------------
1 | .markdown {
2 | font-size: 15px;
3 | font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
4 | pre {
5 | margin-bottom: 1em;
6 | background-color: #F8F8F8;
7 | border: 0px;
8 | font-size: 13px;
9 | line-height: 19px;
10 | overflow: auto;
11 | padding: 8px 12px;
12 | border-radius: 3px;
13 | code {
14 | margin: 0px;
15 | padding: 0px;
16 | background-color: transparent;
17 | border: medium none;
18 | word-wrap: normal;
19 | max-width: initial;
20 | display: inline;
21 | overflow: initial;
22 | line-height: inherit;
23 | }
24 | }
25 | h1 {
26 | font-size: 60px;
27 | }
28 | h2 {
29 | font-size: 40px;
30 | margin: 10px 0 25px 0;
31 | border-bottom: 1px solid #EEE;
32 | }
33 | h3 {
34 | font-size: 30px;
35 | margin: 15px 0px;
36 | }
37 | h4 {
38 | font-size: 20px;
39 | margin: 10px 0px;
40 | }
41 | a {
42 | color: #4183C4;
43 | }
44 | table {
45 | border-collapse: collapse;
46 | border-spacing: 0px;
47 | display: block;
48 | overflow: auto;
49 | width: 100%;
50 | margin: 0px 0px 9px;
51 | tr {
52 | background-color: #FFF;
53 | border: 1px solid #CCC;
54 | }
55 | td {
56 | border: 1px solid #DDD;
57 | padding: 6px 13px;
58 | }
59 | }
60 | p img {
61 | max-width: 99%;
62 | height: auto;
63 | margin: 0 auto;
64 | display: block;
65 | }
66 | blockquote {
67 | border-left: 4px solid #ddd;
68 | margin-bottom: 16px;
69 | p {
70 | font-size: 14px;
71 | padding: 5px 15px;
72 | color: #777;
73 | }
74 | }
75 | }
76 |
77 | .docs-markdown {
78 | .anchor-wrap {
79 | margin-top: -50px;
80 | padding-top: 50px;
81 | }
82 |
83 | h1 a.anchor,
84 | h2 a.anchor,
85 | h3 a.anchor,
86 | h4 a.anchor,
87 | h5 a.anchor,
88 | h6 a.anchor {
89 | text-decoration:none;
90 | line-height:1;
91 | padding-left:0;
92 | margin-left:5px;
93 | top:15%;
94 | }
95 |
96 | a span.octicon {
97 | font-size: 16px;
98 | font-family: "FontAwesome";
99 | line-height: 1;
100 | display: inline-block;
101 | text-decoration: none;
102 | -webkit-font-smoothing: antialiased;
103 | }
104 |
105 | a span.octicon-link {
106 | display: none;
107 | color: #000;
108 | }
109 |
110 | a span.octicon-link:before {
111 | content: "\f0c1";
112 | }
113 |
114 | h1:hover .octicon-link,
115 | h2:hover .octicon-link,
116 | h3:hover .octicon-link,
117 | h4:hover .octicon-link,
118 | h5:hover .octicon-link,
119 | h6:hover .octicon-link {
120 | display:inline-block
121 | }
122 | }
--------------------------------------------------------------------------------
/modules/log/log.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknown
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package log
16 |
17 | import (
18 | "fmt"
19 | "os"
20 | "time"
21 | )
22 |
23 | const (
24 | PREFIX = "[Gogs Web]"
25 | TIME_FORMAT = "06-01-02 15:04:05"
26 | )
27 |
28 | var (
29 | LEVEL_FLAGS = [...]string{"DEBUG", " INFO", " WARN", "ERROR", "FATAL"}
30 | )
31 |
32 | const (
33 | DEBUG = iota
34 | INFO
35 | WARNING
36 | ERROR
37 | FATAL
38 | )
39 |
40 | func Print(level int, format string, args ...interface{}) {
41 | switch level {
42 | case DEBUG:
43 | fmt.Printf("%s \033[36m%s\033[0m [\033[34m%s\033[0m] %s\n",
44 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
45 | fmt.Sprintf(format, args...))
46 | case INFO:
47 | fmt.Printf("%s \033[36m%s\033[0m [\033[32m%s\033[0m] %s\n",
48 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
49 | fmt.Sprintf(format, args...))
50 | case WARNING:
51 | fmt.Printf("%s \033[36m%s\033[0m [\033[33m%s\033[0m] %s\n",
52 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
53 | fmt.Sprintf(format, args...))
54 | case ERROR:
55 | fmt.Printf("%s \033[36m%s\033[0m [\033[31m%s\033[0m] %s\n",
56 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
57 | fmt.Sprintf(format, args...))
58 | case FATAL:
59 | fmt.Printf("%s \033[36m%s\033[0m [\033[35m%s\033[0m] %s\n",
60 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
61 | fmt.Sprintf(format, args...))
62 | os.Exit(1)
63 | default:
64 | fmt.Printf("%s %s %s %s\n",
65 | PREFIX, time.Now().Format(TIME_FORMAT), LEVEL_FLAGS[level],
66 | fmt.Sprintf(format, args...))
67 | }
68 | }
69 |
70 | func Debug(format string, args ...interface{}) {
71 | Print(DEBUG, format, args...)
72 | }
73 |
74 | func Warn(format string, args ...interface{}) {
75 | Print(WARNING, format, args...)
76 | }
77 |
78 | func Info(format string, args ...interface{}) {
79 | Print(INFO, format, args...)
80 | }
81 |
82 | func Error(format string, args ...interface{}) {
83 | Print(ERROR, format, args...)
84 | }
85 |
86 | func Fatal(format string, args ...interface{}) {
87 | Print(FATAL, format, args...)
88 | }
89 |
--------------------------------------------------------------------------------
/routers/gogs.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | package routers
16 |
17 | import (
18 | "io"
19 | "os"
20 | "path"
21 | "strings"
22 |
23 | "github.com/Unknwon/macaron"
24 | "github.com/macaron-contrib/i18n"
25 |
26 | "github.com/gogits/gogsweb/models"
27 | )
28 |
29 | func GogsHome(ctx *macaron.Context) {
30 | ctx.Data["IsPageHome"] = true
31 | ctx.HTML(200, "home_gogs", ctx.Data)
32 | }
33 |
34 | func Donate(ctx *macaron.Context, locale i18n.Locale) {
35 | ctx.Data["Link"] = "/donate"
36 | df := models.GetDoc("gogs", "donate", locale.Lang)
37 | ctx.Data["Data"] = string(df.Data)
38 | ctx.HTML(200, "page", ctx.Data)
39 | }
40 |
41 | func docs(ctx *macaron.Context, locale i18n.Locale, name string) {
42 | docRoot := models.GetDocByLocale(name, locale.Lang)
43 | if docRoot == nil {
44 | docRoot = models.GetDocByLocale(name, "en-US")
45 | }
46 |
47 | link := strings.TrimPrefix(ctx.Params("*"), "/")
48 | link = strings.TrimSuffix(link, ".html")
49 | link = strings.TrimSuffix(link, ".md")
50 | ctx.Data["Link"] = "/docs/" + link
51 |
52 | var doc *models.DocNode
53 | if len(link) == 0 {
54 | ctx.Redirect("/docs/intro/")
55 | return
56 | }
57 |
58 | doc, _ = docRoot.GetNodeByLink(link)
59 | if doc == nil {
60 | doc, _ = docRoot.GetNodeByLink(link + "/")
61 | }
62 | if doc == nil {
63 | ctx.Error(404)
64 | return
65 | }
66 |
67 | ctx.Data["DocRoot"] = docRoot
68 | ctx.Data["Doc"] = doc
69 | ctx.Data["Title"] = doc.Name
70 | ctx.Data["Data"] = doc.GetContent()
71 | ctx.HTML(200, "document_"+name, ctx.Data)
72 | }
73 |
74 | func GogsDocs(ctx *macaron.Context, locale i18n.Locale) {
75 | docs(ctx, locale, "gogs")
76 | }
77 |
78 | func docsStatic(ctx *macaron.Context, name string) {
79 | if len(ctx.Params(":all")) > 0 {
80 | f, err := os.Open(path.Join("docs", name, "images", ctx.Params(":all")))
81 | if err != nil {
82 | ctx.JSON(500, map[string]interface{}{
83 | "error": err.Error(),
84 | })
85 | return
86 | }
87 | defer f.Close()
88 |
89 | _, err = io.Copy(ctx.RW(), f)
90 | if err != nil {
91 | ctx.JSON(500, map[string]interface{}{
92 | "error": err.Error(),
93 | })
94 | return
95 | }
96 | return
97 | }
98 | ctx.Error(404)
99 | }
100 |
101 | func GogsStatic(ctx *macaron.Context) {
102 | docsStatic(ctx, "gogs")
103 | }
104 |
--------------------------------------------------------------------------------
/public/scss/_home.scss:
--------------------------------------------------------------------------------
1 | body {
2 | background: #FFF;
3 | }
4 | #logo {
5 | display: none
6 | }
7 | nav {
8 | text-align: center;
9 | }
10 | h1 {
11 | font-size: 98px;
12 | }
13 | h2 {
14 | font-size: 56px;
15 | }
16 | #home-link {
17 | display: none;
18 | }
19 | #home-logo {
20 | max-width: 250px;
21 | margin-top: 30px;
22 | margin-right: 50px;
23 | float: left;
24 | }
25 | #promo-area {
26 | padding-bottom: 50px;
27 | padding-top: 0;
28 | }
29 | #promo-area h1,
30 | #promo-area h2 {
31 | text-shadow: 0 2px 1px rgba(0, 0, 0, .5);
32 | }
33 | #promo-area {
34 | background: #428BCA;
35 | color: #FFF;
36 | }
37 | #promo-container {
38 | margin-left: 300px;
39 | }
40 | .points {
41 | color: #666;
42 | }
43 | .points b {
44 | color: #000;
45 | font-size: 20px;
46 | display: inline-block;
47 | }
48 | .points .fa {
49 | color: #D9453D;
50 | /*#2585D1;*/
51 | font-size: 52px;
52 | margin-right: 10px;
53 | vertical-align: middle;
54 | }
55 | .carousel {
56 | position: relative;
57 | background: #E0E0E0;
58 | max-height: 400px;
59 | width: 100%;
60 | white-space: nowrap;
61 | padding: 0;
62 | }
63 | .carousel .images {
64 | overflow-x: auto;
65 | width: 100%;
66 | text-align: center;
67 | }
68 | .carousel img {
69 | max-height: 400px;
70 | margin-right: 5px;
71 | z-index: 1;
72 | }
73 | .carousel .fader {
74 | height: 100%;
75 | background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
76 | background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 1)));
77 | background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
78 | background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
79 | background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
80 | background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%);
81 | filter: "progid: DXImageTransform.Microsoft.gradient(startColorstr='#001e5799', endColorstr='#e0e0e0', GradientType=1)";
82 | width: 10%;
83 | z-index: 2;
84 | position: absolute;
85 | right: 0;
86 | top: 0;
87 | }
88 | .ribbon {
89 | background: #FFFDE0;
90 | border-top: 1px solid #FDF48B;
91 | border-bottom: 1px solid #FDF48B;
92 | margin-top: 20px;
93 | }
94 | #clientele {
95 | img {
96 | max-height: 50px;
97 | background: #FFF;
98 | padding: 10px;
99 | border: 1px solid #CCC;
100 | border-radius: 5px;
101 | }
102 | a:hover {
103 | text-decoration: none;
104 | img {
105 | border-color: #428BCA;
106 | }
107 | }
108 | }
109 | @media (max-width: 860px) {
110 | #home-logo {
111 | margin-top: 75px;
112 | max-width: 200px;
113 | }
114 | #promo-container {
115 | margin-left: 250px;
116 | }
117 | }
118 | @media (max-width: 767px) {
119 | .grid-33:not(:first-child).points {
120 | margin-top: 50px;
121 | }
122 | .carousel {
123 | max-height: 300px;
124 | }
125 | }
126 | @media(max-width: 640px) {
127 | #promo-area {
128 | text-align: center;
129 | }
130 | #home-logo {
131 | float: none;
132 | margin: 0 auto;
133 | display: block;
134 | }
135 | #promo-container {
136 | margin-left: 0;
137 | }
138 | }
139 | .nav-macaron {
140 | background: #191A1B;
141 | a {
142 | color: #FFFFFF;
143 | &:hover {
144 | color: #B6D1DD;
145 | }
146 | }
147 | }
--------------------------------------------------------------------------------
/gogsweb.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | // An open source project for official documentation website of Gogs.
16 | package main
17 |
18 | import (
19 | "fmt"
20 | "html/template"
21 | "net/http"
22 | "strings"
23 |
24 | "github.com/Unknwon/macaron"
25 | "github.com/macaron-contrib/i18n"
26 | "github.com/macaron-contrib/switcher"
27 |
28 | "github.com/gogits/gogsweb/models"
29 | "github.com/gogits/gogsweb/modules/base"
30 | "github.com/gogits/gogsweb/modules/log"
31 | "github.com/gogits/gogsweb/modules/setting"
32 | "github.com/gogits/gogsweb/routers"
33 | )
34 |
35 | const APP_VER = "0.3.2.0808"
36 |
37 | var funcMap = map[string]interface{}{
38 | "dict": base.Dict,
39 | "str2html": base.Str2html,
40 | }
41 |
42 | func newGogsInstance() *macaron.Macaron {
43 | m := macaron.Classic()
44 |
45 | // Middlewares.
46 | m.Use(macaron.Renderer(macaron.RenderOptions{
47 | Funcs: []template.FuncMap{funcMap},
48 | }))
49 | m.Use(i18n.I18n(i18n.Options{
50 | Langs: setting.Langs,
51 | Names: setting.Names,
52 | Redirect: true,
53 | }))
54 |
55 | // Routers.
56 | m.Get("/", routers.GogsHome)
57 | m.Get("/docs", routers.GogsDocs)
58 | m.Get("/docs/images/:all", routers.GogsStatic)
59 | m.Get("/docs/*", routers.GogsDocs)
60 | m.Get("/donate", routers.Donate)
61 |
62 | return m
63 | }
64 |
65 | func newMacaronInstance() *macaron.Macaron {
66 | m := macaron.Classic()
67 |
68 | // Middlewares.
69 | m.Use(macaron.Renderer(macaron.RenderOptions{
70 | Funcs: []template.FuncMap{funcMap},
71 | }))
72 | m.Use(i18n.I18n(i18n.Options{
73 | Langs: setting.Langs,
74 | Names: setting.Names,
75 | Redirect: true,
76 | }))
77 |
78 | // Routers.
79 | m.Get("/", routers.MacaronDocs)
80 | m.Get("/docs", routers.MacaronDocs)
81 | m.Get("/docs/images/:all", routers.MacaronStatic)
82 | m.Get("/docs/*", routers.MacaronDocs)
83 |
84 | return m
85 | }
86 |
87 | func main() {
88 | log.Info("Gogs Web %s", APP_VER)
89 | log.Info("Run Mode: %s", strings.Title(macaron.Env))
90 |
91 | models.InitModels()
92 |
93 | m1 := newGogsInstance()
94 | m2 := newMacaronInstance()
95 | hs := switcher.NewHostSwitcher()
96 | hs.Set("gogs.io", m1)
97 | hs.Set("macaron.gogs.io", m2)
98 |
99 | var err error
100 |
101 | // In dev mode, listen two ports just for convenience.
102 | if macaron.Env == macaron.DEV {
103 | // Gogs.
104 | listenAddr := fmt.Sprintf("0.0.0.0:%d", setting.HttpPort)
105 | log.Info("Listen: http://%s", listenAddr)
106 | go http.ListenAndServe(listenAddr, m1)
107 |
108 | // Macaron.
109 | listenAddr = fmt.Sprintf("0.0.0.0:%d", setting.HttpPort+1)
110 | log.Info("Listen: http://%s", listenAddr)
111 | err = http.ListenAndServe(listenAddr, m2)
112 | } else {
113 | schema := "http"
114 | if setting.Https {
115 | schema = "https"
116 | }
117 | listenAddr := fmt.Sprintf("0.0.0.0:%d", setting.HttpPort)
118 | log.Info("Listen: %v://%s", schema, listenAddr)
119 | if setting.Https {
120 | err = http.ListenAndServeTLS(listenAddr, setting.HttpsCert, setting.HttpsKey, hs)
121 | } else {
122 | err = http.ListenAndServe(listenAddr, hs)
123 | }
124 | }
125 | if err != nil {
126 | log.Fatal("Fail to start server: %v", err)
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/templates/home_gogs.tmpl:
--------------------------------------------------------------------------------
1 | {{template "gogs/head" .}}
2 | {{template "gogs/navbar" .}}
3 |
4 |
23 |
24 |
25 |
26 |
27 |
28 |
{{.i18n.Tr "easy_install"}}
29 |
{{.i18n.Tr "easy_install_desc" | str2html}}
30 |
31 |
32 |
33 |
{{.i18n.Tr "cross_platform"}}
34 |
{{.i18n.Tr "cross_platform_desc" | str2html}}
35 |
36 |
37 |
38 |
{{.i18n.Tr "lightweight"}}
39 |
{{.i18n.Tr "lightweight_desc" | str2html}}
40 |
41 |
42 |
43 |
{{.i18n.Tr "opensource"}}
44 |
{{.i18n.Tr "opensource_desc" | str2html}}
45 |
46 |
47 |
48 |
49 |
50 | {{.i18n.Tr "screenshots"}}
51 |
52 |
53 |
54 | {{.i18n.Tr "scroll"}}
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | {{.i18n.Tr "get_started"}}
75 |
76 |
93 |
94 |
95 |
96 | {{.i18n.Tr "who_are_use"}}
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
129 |
130 |
131 | {{template "gogs/footer" .}}
--------------------------------------------------------------------------------
/models/press.go:
--------------------------------------------------------------------------------
1 | // Copyright 2013 Beego Web Authors
2 | // Copyright 2014 Unknwon
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
5 | // not use this file except in compliance with the License. You may obtain
6 | // a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | // License for the specific language governing permissions and limitations
14 | // under the License.
15 |
16 | package models
17 |
18 | import (
19 | "bufio"
20 | "bytes"
21 | "fmt"
22 | "io"
23 | "io/ioutil"
24 | "os"
25 | "path/filepath"
26 | "sort"
27 | "strconv"
28 | "strings"
29 | "time"
30 |
31 | "github.com/Unknwon/com"
32 | )
33 |
34 | type DocList []*DocNode
35 |
36 | func (s DocList) Len() int { return len(s) }
37 | func (s DocList) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
38 | func (s DocList) Less(i, j int) bool { return s[i].Sort < s[j].Sort }
39 |
40 | type DocNode struct {
41 | root bool
42 | IsDir bool
43 | Path string
44 | RelPath string
45 | FileRelPath string
46 | FilePath string
47 | Date time.Time
48 | Name string
49 | Sort int
50 | Link string
51 | Docs DocList
52 | dirs map[string]*DocNode
53 | Root *DocRoot
54 | Parent *DocNode
55 | }
56 |
57 | func (d *DocNode) SortDocs() {
58 | sort.Sort(d.Docs)
59 | }
60 |
61 | func (d *DocNode) HasContent() bool {
62 | return len(d.FilePath) > 0
63 | }
64 |
65 | func (d *DocNode) GetContent() string {
66 | if !d.HasContent() {
67 | return ""
68 | }
69 |
70 | body, err := ioutil.ReadFile(d.FilePath)
71 | if err != nil {
72 | return ""
73 | }
74 |
75 | if i := bytes.Index(body, []byte("---")); i != -1 {
76 | body = body[i+3:]
77 | if i = bytes.Index(body, []byte("---")); i != -1 {
78 | body = body[i+3:]
79 | i = 0
80 | m := 0
81 | mFor:
82 | for {
83 | if len(body) > 0 {
84 | if body[0] == ' ' || body[0] == '\n' {
85 | if body[0] == '\n' {
86 | m += 1
87 | }
88 | if m == 2 {
89 | break mFor
90 | }
91 | } else {
92 | break mFor
93 | }
94 | body = body[1:]
95 | } else {
96 | break mFor
97 | }
98 | }
99 |
100 | return string(markdown(body))
101 | }
102 | }
103 |
104 | return ""
105 | }
106 |
107 | type DocRoot struct {
108 | Wd string
109 | Path string
110 | Doc *DocNode
111 | links map[string]*DocNode
112 | }
113 |
114 | func (d *DocRoot) GetNodeByLink(link string) (*DocNode, bool) {
115 | n, ok := d.links[link]
116 | return n, ok
117 | }
118 |
119 | func (d *DocRoot) walkParse() error {
120 | var err error
121 | if d.Path, err = filepath.Abs(d.Path); err != nil {
122 | return err
123 | }
124 |
125 | defer func() {
126 | if err == nil {
127 | d.sortAll(d.Doc)
128 | }
129 | }()
130 |
131 | err = filepath.Walk(d.Path, d.walk)
132 | return err
133 | }
134 |
135 | func (d *DocRoot) sortAll(node *DocNode) {
136 | for _, n := range node.Docs {
137 | if n.IsDir {
138 | d.sortAll(n)
139 | }
140 | }
141 | node.SortDocs()
142 | }
143 |
144 | func (d *DocRoot) makeDirNode(path string) error {
145 | relPath, _ := filepath.Rel(d.Path, path)
146 |
147 | var docDir *DocNode
148 |
149 | if d.Doc == nil {
150 | d.Doc = new(DocNode)
151 | d.Doc.dirs = make(map[string]*DocNode)
152 | docDir = d.Doc
153 |
154 | } else {
155 | list := strings.Split(relPath, string(filepath.Separator))
156 | node := d.Doc
157 | for _, p := range list {
158 | if n, ok := node.dirs[p]; ok {
159 | node = n
160 | } else {
161 | n = new(DocNode)
162 | n.dirs = make(map[string]*DocNode)
163 | n.Parent = node
164 | node.Docs = append(node.Docs, n)
165 | node.dirs[p] = n
166 | node = n
167 | }
168 | }
169 |
170 | docDir = node
171 | }
172 |
173 | docDir.Root = d
174 | docDir.Path = path
175 | docDir.RelPath = relPath
176 | docDir.IsDir = true
177 |
178 | return nil
179 | }
180 |
181 | func (d *DocRoot) getDirNode(path string) *DocNode {
182 | node := d.Doc
183 | list := strings.Split(path, string(filepath.Separator))
184 | for _, p := range list {
185 | if n, ok := node.dirs[p]; ok {
186 | node = n
187 | }
188 | }
189 | return node
190 | }
191 |
192 | func (d *DocRoot) makeFileNode(path string) error {
193 | file, err := os.Open(path)
194 | if err != nil {
195 | return err
196 | }
197 | defer file.Close()
198 |
199 | relPath, _ := filepath.Rel(d.Path, path)
200 | relPath = strings.Replace(relPath, "\\", "/", -1)
201 |
202 | docDir := d.getDirNode(filepath.Dir(relPath))
203 |
204 | var bingo bool
205 | var doc *DocNode
206 | rd := bufio.NewReader(file)
207 | no := 0
208 | for {
209 | line, _, err := rd.ReadLine()
210 | if err == io.EOF {
211 | break
212 | }
213 |
214 | if no > 3 && !bingo {
215 | break
216 | }
217 |
218 | if no > 20 && bingo {
219 | return fmt.Errorf("document %s not contained ended tag `---`", path)
220 | }
221 |
222 | data := string(bytes.TrimSpace(line))
223 |
224 | if len(data) == 3 && data == "---" {
225 |
226 | if bingo {
227 | if doc.root {
228 | if len(docDir.FilePath) > 0 {
229 | return fmt.Errorf("node %s has a document %s, can not replicate by %s",
230 | docDir.Path, docDir.FilePath, path)
231 | }
232 |
233 | docDir.Name = doc.Name
234 | docDir.Date = doc.Date
235 | docDir.Link = doc.Link
236 | docDir.Sort = doc.Sort
237 |
238 | mFor:
239 | for {
240 | l, _, er := rd.ReadLine()
241 | if er != nil {
242 | break mFor
243 | }
244 | if len(bytes.TrimSpace(l)) > 0 {
245 | docDir.FilePath = path
246 | break mFor
247 | }
248 | }
249 |
250 | if len(docDir.Link) == 0 {
251 | docDir.Link = docDir.RelPath + "/"
252 | }
253 |
254 | docDir.FileRelPath = relPath
255 |
256 | doc = docDir
257 | } else {
258 | doc.RelPath = relPath
259 | doc.FilePath = path
260 | if len(doc.Link) == 0 {
261 | // doc.Link = doc.RelPath
262 | doc.Link = strings.TrimSuffix(doc.RelPath, filepath.Ext(doc.RelPath))
263 | }
264 |
265 | docDir.Docs = append(docDir.Docs, doc)
266 | }
267 |
268 | if dc, ok := d.links[doc.Link]; ok {
269 | return fmt.Errorf("document %s's link %s is already used by %s", path, doc.Link, dc.Path)
270 | }
271 |
272 | d.links[doc.Link] = doc
273 |
274 | break
275 | }
276 |
277 | doc = new(DocNode)
278 | doc.Path = path
279 | doc.Root = d
280 | doc.Parent = docDir
281 |
282 | bingo = true
283 | }
284 |
285 | if bingo {
286 | parts := strings.SplitN(data, ":", 2)
287 | if len(parts) == 2 {
288 | name := strings.TrimSpace(parts[0])
289 | value := strings.TrimSpace(parts[1])
290 | switch name {
291 | case "root":
292 | doc.root, _ = strconv.ParseBool(value)
293 | case "name":
294 | doc.Name = value
295 | case "date":
296 | doc.Date, err = com.DateParse(value, "Y-m-d H:i")
297 | if err != nil {
298 | return err
299 | }
300 | case "link":
301 | doc.Link = value
302 | case "sort":
303 | n, _ := strconv.ParseInt(value, 10, 64)
304 | doc.Sort = int(n)
305 | }
306 | }
307 | }
308 | }
309 |
310 | return nil
311 | }
312 |
313 | func (d *DocRoot) walk(path string, info os.FileInfo, err error) error {
314 | if err != nil {
315 | return filepath.SkipDir
316 | }
317 |
318 | if !info.IsDir() && info.Size() == 0 {
319 | return nil
320 | }
321 |
322 | if info.IsDir() {
323 | if err := d.makeDirNode(path); err != nil {
324 | return err
325 | }
326 | } else {
327 | return d.makeFileNode(path)
328 | }
329 |
330 | return nil
331 | }
332 |
333 | func ParseDocs(path string) (*DocRoot, error) {
334 | root := new(DocRoot)
335 | root.Path = path
336 | root.links = make(map[string]*DocNode)
337 |
338 | if err := root.walkParse(); err == nil {
339 | return root, err
340 | } else {
341 | return nil, err
342 | }
343 | }
344 |
--------------------------------------------------------------------------------
/public/scss/_common.scss:
--------------------------------------------------------------------------------
1 | /* Eric Meyer's Reset CSS v2.0 */
2 |
3 | html,
4 | body,
5 | div,
6 | span,
7 | applet,
8 | object,
9 | iframe,
10 | h1,
11 | h2,
12 | h3,
13 | h4,
14 | h5,
15 | h6,
16 | p,
17 | blockquote,
18 | pre,
19 | a,
20 | abbr,
21 | acronym,
22 | address,
23 | big,
24 | cite,
25 | code,
26 | del,
27 | dfn,
28 | em,
29 | img,
30 | ins,
31 | kbd,
32 | q,
33 | s,
34 | samp,
35 | small,
36 | strike,
37 | sub,
38 | sup,
39 | tt,
40 | var,
41 | b,
42 | u,
43 | i,
44 | center,
45 | dl,
46 | dt,
47 | dd,
48 | ol,
49 | ul,
50 | li,
51 | fieldset,
52 | form,
53 | label,
54 | legend,
55 | caption,
56 | tfoot,
57 | article,
58 | aside,
59 | canvas,
60 | details,
61 | embed,
62 | figure,
63 | figcaption,
64 | footer,
65 | header,
66 | hgroup,
67 | menu,
68 | nav,
69 | output,
70 | ruby,
71 | section,
72 | summary,
73 | time,
74 | mark,
75 | audio,
76 | video {
77 | border: 0;
78 | font-size: 100%;
79 | font: inherit;
80 | vertical-align: baseline;
81 | margin: 0;
82 | padding: 0
83 | }
84 | article,
85 | aside,
86 | details,
87 | figcaption,
88 | figure,
89 | footer,
90 | header,
91 | hgroup,
92 | menu,
93 | nav,
94 | section {
95 | display: block
96 | }
97 | body {
98 | line-height: 1
99 | }
100 | ol,
101 | ul {
102 | list-style: none
103 | }
104 | blockquote,
105 | q {
106 | quotes: none
107 | }
108 | blockquote:before,
109 | blockquote:after,
110 | q:before,
111 | q:after {
112 | content: none
113 | }
114 | table {
115 | border-collapse: collapse;
116 | border-spacing: 0
117 | }
118 | body {
119 | font: normal 18px/1.4em 'Lato', sans-serif, Microsoft Yahei;
120 | background: #EFEFEF;
121 | }
122 | a {
123 | color: #D9453D;
124 | text-decoration: none;
125 | }
126 | a:hover {
127 | color: #FF635A;
128 | text-decoration: underline;
129 | }
130 | b {
131 | font-weight: bold;
132 | }
133 | p {
134 | margin: 1em 0;
135 | }
136 | p:first-child {
137 | margin-top: 0;
138 | }
139 | nav,
140 | main {
141 | -webkit-box-sizing: border-box;
142 | -moz-box-sizing: border-box;
143 | -o-box-sizing: border-box;
144 | box-sizing: border-box;
145 | }
146 | nav {
147 | z-index: 2;
148 | padding: 10px 25px;
149 | background: #428BCA;
150 | color: #FFF;
151 | }
152 | #logo {
153 | max-height: 65px;
154 | vertical-align: middle;
155 | margin-right: 50px;
156 | }
157 | #menu-link {
158 | display: none;
159 | }
160 | nav a {
161 | display: inline-block;
162 | padding: 20px;
163 | color: #C8E0FF;
164 | transition: color .2s;
165 | }
166 | nav a:hover {
167 | color: #FFF;
168 | text-decoration: none;
169 | }
170 | iframe {
171 | width: 100px;
172 | height: 1.5em;
173 | vertical-align: middle;
174 | margin-bottom: 15px;
175 | }
176 | #lang {
177 | float: right;
178 | margin-top: 24px;
179 | }
180 | h1,
181 | h2 {
182 | font-family: 'PT Sans Narrow', sans-serif;
183 | line-height: 1.25em;
184 | }
185 | h1 {
186 | font-size: 54px;
187 | font-weight: bold;
188 | }
189 | h2 {
190 | font-size: 40px;
191 | margin-bottom: .5em;
192 | }
193 | main {
194 | position: relative;
195 | z-index: 1;
196 | }
197 | main section {
198 | padding: 50px 0;
199 | }
200 | main > .grid-container:first-child {
201 | margin: 30px auto;
202 | }
203 | .side-nav {
204 | font-size: 14px;
205 | line-height: 1em;
206 | }
207 | .side-nav ol,
208 | .side-nav ul {
209 | list-style-type: none;
210 | }
211 | .side-nav li.group {
212 | margin-left: 0;
213 | }
214 | .side-nav .section {
215 | font-weight: bold;
216 | color: #666;
217 | margin-top: 1em;
218 | }
219 | .content {
220 | background: #FFF;
221 | box-shadow: 0 0 5px rgba(0, 0, 0, .3);
222 | }
223 | article {
224 | padding: 3%;
225 | }
226 | button,
227 | .button,
228 | input[type=button] {
229 | padding: 10px 25px;
230 | border-radius: 5px;
231 | color: #FFF;
232 | margin-right: 10px;
233 | margin-top: 5px;
234 | margin-bottom: 5px;
235 | display: inline-block;
236 | transition: background .2s;
237 | }
238 | button:hover,
239 | .button:hover,
240 | input[type=button]:hover {
241 | color: #FFF;
242 | text-decoration: none;
243 | }
244 | .blue {
245 | background: #428BCA;
246 | }
247 | .blue:hover {
248 | background: #539CDB;
249 | }
250 | .darkblue {
251 | background: #285370;
252 | }
253 | .darkblue:hover {
254 | background: #276996;
255 | }
256 | .green {
257 | background: #65AD4E;
258 | }
259 | .green:hover {
260 | background: #71BF57;
261 | }
262 | .red {
263 | background: #DB3F36;
264 | }
265 | .red:hover {
266 | background: #C4362E;
267 | }
268 | .clear {
269 | border: 0;
270 | padding: 0;
271 | margin: 0;
272 | clear: both;
273 | }
274 | code {
275 | font-size: 13px;
276 | font-family: 'Monaco', monospace;
277 | padding: 3px 5px;
278 | background-color: rgba(0,0,0,0.05);
279 | border-radius: 3px;
280 | }
281 | ul,
282 | ol {
283 | margin: .5em 0;
284 | }
285 | ul:first-child,
286 | ol:first-child {
287 | margin-top: 0;
288 | }
289 | ul {
290 | list-style-type: disc;
291 | }
292 | ol {
293 | list-style-type: decimal;
294 | }
295 | li {
296 | margin-left: 2em;
297 | }
298 | .scroll-help {
299 | font-size: 18px;
300 | text-align: center;
301 | margin-bottom: .25em;
302 | color: #AAA;
303 | font-style: italic;
304 | }
305 | .scroll-help .fa {
306 | margin: 0 10px;
307 | }
308 | .nowrap {
309 | white-space: nowrap;
310 | }
311 | .text-left {
312 | text-align: left;
313 | }
314 | .text-center {
315 | text-align: center;
316 | }
317 | .text-right {
318 | text-align: right;
319 | }
320 | .hide-on-wide {
321 | display: none;
322 | }
323 | .block {
324 | display: block;
325 | }
326 | footer {
327 | padding: 50px 0;
328 | background: #222;
329 | color: #DDD;
330 | font-size: 16px;
331 | }
332 | footer .block {
333 | color: #DDD;
334 | }
335 | footer .white {
336 | color: #DDD;
337 | }
338 | footer a.white:hover {
339 | color: #FFF;
340 | text-decoration: none;
341 | }
342 | footer img {
343 | vertical-align: middle;
344 | }
345 | footer .button {
346 | font-size: 18px;
347 | }
348 | #footer-col-2 {
349 | text-align: center;
350 | }
351 | #footer-col-3 {
352 | text-align: right;
353 | }
354 | .social-media a {
355 | display: inline-block;
356 | border-radius: 2px;
357 | padding: 3px 8px;
358 | text-decoration: none;
359 | color: #FFF;
360 | font-size: 18px;
361 | text-align: center;
362 | margin: 0 3px;
363 | }
364 | .social-media .github {
365 | background: #AAA;
366 | }
367 | .social-media .github:hover {
368 | background: #CCC;
369 | }
370 | .social-media .twitter {
371 | background: #00ACED;
372 | }
373 | .social-media .twitter:hover {
374 | background: #21C2FF;
375 | }
376 | .social-media .google {
377 | background: #C03D20;
378 | }
379 | .social-media .google:hover {
380 | background: #D56060;
381 | }
382 | .social-media .weibo {
383 | background: #3B5998;
384 | }
385 | .social-media .weibo:hover {
386 | background: #4C70BA;
387 | }
388 | .sep {
389 | width: 30%;
390 | max-width: 250px;
391 | border: 0;
392 | background: none;
393 | border-top: 1px dotted #AAA;
394 | margin: 35px auto;
395 | }
396 | @media (max-width: 1200px) {
397 | h2 {
398 | font-size: 36px;
399 | }
400 | main section {
401 | padding: 35px 0;
402 | }
403 | }
404 | @media (max-width: 860px) {
405 | #logo {
406 | margin-right: 15px;
407 | }
408 | nav a {
409 | font-size: 14px;
410 | padding: 20px 10px;
411 | }
412 | footer {
413 | font-size: 14px;
414 | }
415 | }
416 | @media (max-width: 767px) {
417 | #get-started-buttons {
418 | text-align: center !important;
419 | }
420 | footer div {
421 | text-align: center !important;
422 | }
423 | footer .button {
424 | padding: 5px 10px;
425 | margin-top: 20px;
426 | font-size: 14px;
427 | }
428 | #footer-col-1 {
429 | margin-bottom: 20px;
430 | }
431 | #footer-col-2 {
432 | text-align: center;
433 | }
434 | #footer-col-3 {
435 | text-align: right;
436 | }
437 | article {
438 | margin-top: 50px;
439 | }
440 | }
441 | @media (min-width: 651px) {
442 | #wide-nav {
443 | display: inline-block !important;
444 | }
445 | }
446 | @media (max-width: 650px) {
447 | #logo {
448 | float: left;
449 | }
450 | nav {
451 | text-align: right !important;
452 | }
453 | nav a {
454 | font-size: 16px;
455 | }
456 | #menu-link {
457 | display: inline-block;
458 | }
459 | #lang {
460 | float: none;
461 | }
462 | #wide-nav {
463 | display: none;
464 | }
465 | #wide-nav a {
466 | text-align: left;
467 | display: block;
468 | padding: 8px;
469 | border-bottom: 1px solid #5DA2CF;
470 | }
471 | h1 {
472 | font-size: 42px;
473 | }
474 | h2 {
475 | font-size: 32px;
476 | }
477 | article {
478 | font-size: 16px;
479 | }
480 | .hide-on-wide {
481 | display: inline-block;
482 | }
483 | }
484 | #disqus_thread {
485 | margin-top: 20px;
486 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
--------------------------------------------------------------------------------
/models/models.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Unknwon
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may
4 | // not use this file except in compliance with the License. You may obtain
5 | // a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 | // License for the specific language governing permissions and limitations
13 | // under the License.
14 |
15 | // Package models is for loading and updating documentation files.
16 | package models
17 |
18 | import (
19 | "bytes"
20 | "encoding/json"
21 | "errors"
22 | "os"
23 | "path"
24 | "strings"
25 | "sync"
26 | "time"
27 |
28 | "github.com/Unknwon/com"
29 | "github.com/Unknwon/macaron"
30 | "github.com/robfig/cron"
31 | "github.com/russross/blackfriday"
32 |
33 | "github.com/gogits/gogsweb/modules/log"
34 | "github.com/gogits/gogsweb/modules/setting"
35 | )
36 |
37 | var (
38 | docs = make(map[string]map[string]*DocRoot)
39 | )
40 |
41 | type oldDocNode struct {
42 | Sha string
43 | Path string
44 | Type string
45 | }
46 |
47 | // docTrees descriables a documentation file structure tree.
48 | type docTree struct {
49 | Tree []oldDocNode
50 | }
51 |
52 | var docTrees = map[string]*docTree{}
53 |
54 | type docFile struct {
55 | Title string
56 | Data []byte
57 | }
58 |
59 | var (
60 | docLock = &sync.RWMutex{}
61 | docMaps = map[string]map[string]*docFile{}
62 | )
63 |
64 | func GetDocByLocale(name, lang string) *DocRoot {
65 | return docs[name][lang]
66 | }
67 |
68 | func InitModels() {
69 | for _, app := range setting.Apps {
70 | parseDocs(app.Name)
71 | initDocMap(app.Name)
72 | }
73 |
74 | if macaron.Env == macaron.DEV {
75 | return
76 | }
77 |
78 | c := cron.New()
79 | c.AddFunc("0 */5 * * * *", checkFileUpdates)
80 | c.Start()
81 |
82 | if needCheckUpdate() {
83 | checkFileUpdates()
84 | setting.Cfg.Section("app").Key("update_check_time").SetValue(com.ToStr(time.Now().Unix()))
85 | if err := setting.Cfg.SaveTo(setting.CFG_CUSTOM_PATH); err != nil {
86 | log.Error("Fail to save settings: %v", err)
87 | }
88 | }
89 | }
90 |
91 | func parseDocs(name string) {
92 | if docs[name] == nil {
93 | docs[name] = make(map[string]*DocRoot)
94 | }
95 |
96 | for _, lang := range setting.Langs {
97 | root, err := ParseDocs(path.Join("docs", name, lang))
98 | if err != nil {
99 | log.Error("Fail to parse docs: %v", err)
100 | }
101 |
102 | if root != nil {
103 | docs[name][lang] = root
104 | }
105 | }
106 | }
107 |
108 | func needCheckUpdate() bool {
109 | // Does not have record for check update.
110 | stamp, err := setting.Cfg.Section("app").Key("update_check_time").Int64()
111 | if err != nil {
112 | return true
113 | }
114 |
115 | for _, app := range setting.Apps {
116 | if !com.IsFile("conf/docTree_" + app.Name + ".json") {
117 | return true
118 | }
119 | }
120 |
121 | return time.Unix(stamp, 0).Add(5 * time.Minute).Before(time.Now())
122 | }
123 |
124 | func initDocMap(name string) {
125 | docTrees[name] = &docTree{}
126 | treeName := "conf/docTree_" + name + ".json"
127 | isConfExist := com.IsFile(treeName)
128 | if isConfExist {
129 | f, err := os.Open(treeName)
130 | if err != nil {
131 | log.Error("Fail to open '%s': %v", treeName, err)
132 | return
133 | }
134 | defer f.Close()
135 |
136 | d := json.NewDecoder(f)
137 | if err = d.Decode(docTrees[name]); err != nil {
138 | log.Error("Fail to decode '%s': %v", treeName, err)
139 | return
140 | }
141 | } else {
142 | // Generate 'docTree'.
143 | docTrees[name].Tree = append(docTrees[name].Tree, oldDocNode{Path: ""})
144 | }
145 |
146 | docLock.Lock()
147 | defer docLock.Unlock()
148 |
149 | docMap := make(map[string]*docFile)
150 |
151 | for _, l := range setting.Langs {
152 | os.MkdirAll(path.Join("docs", name, l), os.ModePerm)
153 | for _, v := range docTrees[name].Tree {
154 | var fullName string
155 | if isConfExist {
156 | fullName = v.Path
157 | } else {
158 | fullName = l + "/" + v.Path
159 | }
160 |
161 | docMap[fullName] = getFile(path.Join("docs", name, fullName))
162 | }
163 | }
164 |
165 | docMaps[name] = docMap
166 | }
167 |
168 | // loadFile returns []byte of file data by given path.
169 | func loadFile(filePath string) ([]byte, error) {
170 | f, err := os.Open(filePath)
171 | if err != nil {
172 | return []byte(""), errors.New("Fail to open file: " + err.Error())
173 | }
174 |
175 | fi, err := f.Stat()
176 | if err != nil {
177 | return []byte(""), errors.New("Fail to get file information: " + err.Error())
178 | }
179 |
180 | d := make([]byte, fi.Size())
181 | f.Read(d)
182 | return d, nil
183 | }
184 |
185 | type CustomRender struct {
186 | blackfriday.Renderer
187 | }
188 |
189 | var (
190 | tab = []byte("\t")
191 | spaces = []byte(" ")
192 | )
193 |
194 | func (cr *CustomRender) BlockCode(out *bytes.Buffer, text []byte, lang string) {
195 | var tmp bytes.Buffer
196 | cr.Renderer.BlockCode(&tmp, text, lang)
197 | out.Write(bytes.Replace(tmp.Bytes(), tab, spaces, -1))
198 | }
199 |
200 | func markdown(raw []byte) []byte {
201 | htmlFlags := 0
202 | htmlFlags |= blackfriday.HTML_USE_XHTML
203 | htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
204 | htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
205 | htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
206 | htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
207 | htmlFlags |= blackfriday.HTML_COMPLETE_PAGE
208 |
209 | renderer := &CustomRender{
210 | Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""),
211 | }
212 |
213 | // set up the parser
214 | extensions := 0
215 | extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
216 | extensions |= blackfriday.EXTENSION_TABLES
217 | extensions |= blackfriday.EXTENSION_FENCED_CODE
218 | extensions |= blackfriday.EXTENSION_AUTOLINK
219 | extensions |= blackfriday.EXTENSION_STRIKETHROUGH
220 | extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK
221 | extensions |= blackfriday.EXTENSION_SPACE_HEADERS
222 | extensions |= blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
223 |
224 | body := blackfriday.Markdown(raw, renderer, extensions)
225 | return body
226 | }
227 |
228 | func getFile(filePath string) *docFile {
229 | if strings.Contains(filePath, "images") ||
230 | len(strings.Split(filePath, "/")) <= 3 {
231 | return nil
232 | }
233 |
234 | df := &docFile{}
235 | p, err := loadFile(filePath + ".md")
236 | if err != nil {
237 | log.Error("Fail to load MD file: %v", err)
238 | return nil
239 | }
240 |
241 | // Parse and render.
242 | s := string(p)
243 | i := strings.Index(s, "\n")
244 | if i > -1 {
245 | // Has title.
246 | df.Title = strings.TrimSpace(
247 | strings.Replace(s[:i+1], "#", "", -1))
248 | if len(s) >= i+2 {
249 | df.Data = []byte(strings.TrimSpace(s[i+2:]))
250 | }
251 | } else {
252 | df.Data = p
253 | }
254 |
255 | df.Data = markdown(df.Data)
256 | return df
257 | }
258 |
259 | // GetDoc returns 'docFile' by given name and language version.
260 | func GetDoc(app, fullName, lang string) *docFile {
261 | filePath := path.Join("docs", app, lang, fullName)
262 |
263 | if macaron.Env == macaron.DEV {
264 | return getFile(filePath)
265 | }
266 |
267 | docLock.RLock()
268 | defer docLock.RUnlock()
269 | return docMaps[app][lang+"/"+fullName]
270 | }
271 |
272 | var checkTicker *time.Ticker
273 |
274 | func checkTickerTimer(checkChan <-chan time.Time) {
275 | for {
276 | <-checkChan
277 | checkFileUpdates()
278 | }
279 | }
280 |
281 | type rawFile struct {
282 | name string
283 | rawURL string
284 | data []byte
285 | }
286 |
287 | func (rf *rawFile) Name() string {
288 | return rf.name
289 | }
290 |
291 | func (rf *rawFile) RawUrl() string {
292 | return rf.rawURL
293 | }
294 |
295 | func (rf *rawFile) Data() []byte {
296 | return rf.data
297 | }
298 |
299 | func (rf *rawFile) SetData(p []byte) {
300 | rf.data = p
301 | }
302 |
303 | func checkFileUpdates() {
304 | log.Debug("Checking file updates")
305 |
306 | type tree struct {
307 | AppName, ApiUrl, RawUrl, TreeName, Prefix string
308 | }
309 |
310 | trees := make([]*tree, len(setting.Apps))
311 | for i, app := range setting.Apps {
312 | trees[i] = &tree{
313 | AppName: app.Name,
314 | ApiUrl: "https://api.github.com/repos/" + app.RepoName + "/git/trees/master?recursive=1&" + setting.GithubCred,
315 | RawUrl: "https://raw.github.com/" + app.RepoName + "/master/",
316 | TreeName: "conf/docTree_" + app.Name + ".json",
317 | Prefix: "docs/" + app.Name + "/",
318 | }
319 | }
320 |
321 | for _, tree := range trees {
322 | var tmpTree struct {
323 | Tree []*oldDocNode
324 | }
325 |
326 | if err := com.HttpGetJSON(httpClient, tree.ApiUrl, &tmpTree); err != nil {
327 | log.Error("Fail to get trees: %v", err)
328 | return
329 | }
330 |
331 | var saveTree struct {
332 | Tree []*oldDocNode
333 | }
334 | saveTree.Tree = make([]*oldDocNode, 0, len(tmpTree.Tree))
335 |
336 | // Compare SHA.
337 | files := make([]com.RawFile, 0, len(tmpTree.Tree))
338 | for _, node := range tmpTree.Tree {
339 | // Skip non-md files and "README.md".
340 | if node.Type != "blob" || (!strings.HasSuffix(node.Path, ".md") &&
341 | !strings.Contains(node.Path, "images") &&
342 | !strings.HasSuffix(node.Path, ".json")) ||
343 | strings.HasPrefix(strings.ToLower(node.Path), "readme") {
344 | continue
345 | }
346 |
347 | name := strings.TrimSuffix(node.Path, ".md")
348 |
349 | if checkSHA(tree.AppName, name, node.Sha, tree.Prefix) {
350 | log.Info("Need to update: %s", name)
351 | files = append(files, &rawFile{
352 | name: name,
353 | rawURL: tree.RawUrl + node.Path,
354 | })
355 | }
356 |
357 | saveTree.Tree = append(saveTree.Tree, &oldDocNode{
358 | Path: name,
359 | Sha: node.Sha,
360 | })
361 | // For save purpose, reset name.
362 | node.Path = name
363 | }
364 |
365 | // Fetch files.
366 | if err := com.FetchFiles(httpClient, files, nil); err != nil {
367 | log.Error("Fail to fetch files: %v", err)
368 | return
369 | }
370 |
371 | // Update data.
372 | for _, f := range files {
373 | os.MkdirAll(path.Join(tree.Prefix, path.Dir(f.Name())), os.ModePerm)
374 | suf := ".md"
375 | if strings.Contains(f.Name(), "images") ||
376 | strings.HasSuffix(f.Name(), ".json") {
377 | suf = ""
378 | }
379 | fw, err := os.Create(tree.Prefix + f.Name() + suf)
380 | if err != nil {
381 | log.Error("Fail to open file: %v", err)
382 | continue
383 | }
384 |
385 | _, err = fw.Write(f.Data())
386 | fw.Close()
387 | if err != nil {
388 | log.Error("Fail to write data: %v", err)
389 | continue
390 | }
391 | }
392 |
393 | // Save documentation information.
394 | f, err := os.Create(tree.TreeName)
395 | if err != nil {
396 | log.Error("Fail to save data: %v", err)
397 | return
398 | }
399 |
400 | e := json.NewEncoder(f)
401 | err = e.Encode(&saveTree)
402 | if err != nil {
403 | log.Error("Fail to encode data: %v", err)
404 | return
405 | }
406 | f.Close()
407 | }
408 |
409 | log.Debug("Finish check file updates")
410 | for _, app := range setting.Apps {
411 | parseDocs(app.Name)
412 | initDocMap(app.Name)
413 | }
414 | }
415 |
416 | // checkSHA returns true if the documentation file need to update.
417 | func checkSHA(app, name, sha, prefix string) bool {
418 | var tree docTree
419 |
420 | if strings.HasPrefix(prefix, "docs/") {
421 | tree = *docTrees[app]
422 | }
423 |
424 | for _, v := range tree.Tree {
425 | if v.Path == name {
426 | // Found.
427 | if v.Sha != sha {
428 | // Need to update.
429 | return true
430 | }
431 | return false
432 | }
433 | }
434 | // Not found.
435 | return true
436 | }
437 |
--------------------------------------------------------------------------------
/public/js/prettify.js:
--------------------------------------------------------------------------------
1 | !function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
2 | (function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
3 | b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
10 | q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
11 | /^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+
12 | s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
13 | q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
14 | c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
19 | O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
20 | Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
21 | V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]+/],["dec",/^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
22 | /^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^