Skip to content

Commit

Permalink
refactor: redesign faq page
Browse files Browse the repository at this point in the history
  • Loading branch information
aofei committed Mar 13, 2020
1 parent c068b0b commit 8e4128b
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If you're using the [goproxy.cn](https://goproxy.cn) as your Go module proxy.
Then you need to know in order to improve caching and serving latencies, new
revisions may not show up right away. If you want new revision to be immediately
available in the [goproxy.cn](https://goproxy.cn), then first make sure there is
a semantically versioned tag for this revision in the source repository. Then
explicitly request that tagged version via `go get module@version`. After couple
of minutes for caches to expire, the `go` command will see that tagged version.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If you're using the [goproxy.cn](https://goproxy.cn) as your Go module proxy.
Then you need to know whenever possible, Goproxy China aims to cache content in
order to avoid breaking builds for people that depend on your module, so this
bad release may still be available in the [goproxy.cn](https://goproxy.cn) even
if it is not available at the origin. The same situation applies if you delete
your entire repository. We suggest creating a new release and encouraging people
to use that one instead.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
如果你正在使用 [goproxy.cn](https://goproxy.cn) 作为你的 Go 模块代理,那么你需要知道为了改善缓存和服务等待时间,新修改可能不会立即出现。如果你希望新修改立即出现在 [goproxy.cn](https://goproxy.cn) 中,则首先确保在源库中有此修改的语义化版本的标签,接着通过 `go get module@version` 来显式地请求那个发行版。在几分钟过后缓存过期,`go` 命令就能看到那个发行版了。
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
如果你正在使用 [goproxy.cn](https://goproxy.cn) 作为你的 Go 模块代理,那么你需要知道为了避免依赖你的模块的人的构建被破坏,Goproxy 中国会尽可能地缓存内容。因此,即使一个发行版在源库中已经不存在了,但它在 [goproxy.cn](https://goproxy.cn) 中却仍然有可能继续存在。如果你删除了你的整个库,则情况相同。我们建议你创建一个新的发行版并鼓励人们使用它,而不是移除一个已发布的。
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/air-gases/logger v0.15.2
github.com/air-gases/redirector v0.15.2
github.com/aofei/air v0.15.2
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/fsnotify/fsnotify v1.4.9
github.com/goproxy/goproxy v0.0.0-20200313105010-b21e3112b7d3
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/robfig/cron/v3 v3.0.1
Expand All @@ -22,4 +22,5 @@ require (
github.com/tdewolff/minify/v2 v2.7.3 // indirect
github.com/tidwall/gjson v1.6.0
github.com/tidwall/pretty v1.0.1 // indirect
github.com/yuin/goldmark v1.1.25
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25 h1:isv+Q6HQAmmL2Ofcmg8QauBmDPlUUnSoNhEcC940Rds=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
Expand Down
149 changes: 148 additions & 1 deletion handler/faq.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,166 @@
package handler

import (
"bytes"
"html/template"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"sync"

"github.com/aofei/air"
"github.com/fsnotify/fsnotify"
"github.com/goproxy/goproxy.cn/base"
"github.com/goproxy/goproxy.cn/model"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/extension"
)

var (
// faqs is the frequently asked questions.
faqs = map[string][]model.QA{}

// parseFAQsOnce is used to guarantee that the `parseFAQs` will only be
// called once.
parseFAQsOnce sync.Once
)

func init() {
faqsWatcher, err := fsnotify.NewWatcher()
if err != nil {
base.Logger.Fatal().Err(err).
Msg("failed to build faq watcher")
} else if err := faqsWatcher.Add("faqs"); err != nil {
base.Logger.Fatal().Err(err).
Msg("failed to watch faq directory")
}

if err := filepath.Walk(
"faqs",
func(p string, fi os.FileInfo, err error) error {
if fi == nil || !fi.IsDir() {
return err
}

return faqsWatcher.Add(p)
},
); err != nil {
base.Logger.Fatal().Err(err).
Msg("failed to watch faq directory")
}

go func() {
done := make(chan struct{})
base.Air.AddShutdownJob(func() {
close(done)
})

for {
select {
case <-faqsWatcher.Events:
parseFAQsOnce = sync.Once{}
case err := <-faqsWatcher.Errors:
base.Logger.Error().Err(err).
Msg("faq watcher error")
case <-done:
return
}
}
}()

base.Air.BATCH(getHeadMethods, "/faq", hFaqPage)
}

// hFaqPage handles requests to get FAQ page.
func hFaqPage(req *air.Request, res *air.Response) error {
parseFAQsOnce.Do(parseFAQs)

qas, ok := faqs[req.LocalizedString("FAQ")]
if !ok {
qas = faqs["FAQ"]
}

return res.Render(map[string]interface{}{
"PageTitle": req.LocalizedString("FAQ"),
"CanonicalPath": "/faq",
"IsFAQPage": true,
}, req.LocalizedString("faq.html"), "layouts/default.html")
"QAs": qas,
}, "faq.html", "layouts/default.html")
}

// parseFAQs parses frequently asked questions.
func parseFAQs() {
var dirs []string
if err := filepath.Walk(
"faqs",
func(p string, fi os.FileInfo, err error) error {
if fi == nil || !fi.IsDir() {
return err
}

dirs = append(dirs, p)

return nil
},
); err != nil {
return
}

gm := goldmark.New(goldmark.WithExtensions(extension.GFM))

nfaqs := make(map[string][]model.QA, len(dirs))
for _, dir := range dirs {
var qas []model.QA
if err := filepath.Walk(
dir,
func(p string, fi os.FileInfo, err error) error {
if fi == nil || fi.IsDir() {
return err
}

ext := filepath.Ext(p)
if ext != ".md" {
return err
}

b, err := ioutil.ReadFile(p)
if err != nil {
return err
}

var buf bytes.Buffer
if err := gm.Convert(b, &buf); err != nil {
return err
}

qas = append(qas, model.QA{
Question: strings.TrimSuffix(
filepath.Base(p),
ext,
),
Answer: template.HTML(buf.String()),
})

return nil
},
); err != nil {
return
}

sort.Slice(qas, func(i, j int) bool {
return qas[i].Question < qas[j].Question
})

for i := range qas {
q := qas[i].Question
q = q[strings.Index(q, "-")+1:]
qas[i].Question = q
}

nfaqs[filepath.Base(dir)] = qas
}

faqs = nfaqs
}
6 changes: 5 additions & 1 deletion locales/en-US.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
"Back to top" = "Back to top"
"Contact" = "Contact"
"FAQ" = "FAQ"
"Goproxy China is now trying to collect as many questions as possible about the problems Gophers have when working with Go moduels and try to give the best answers. By doing this, we believe we can better help everyone use Go moduels." = "Goproxy China is now trying to collect as many questions as possible about the problems Gophers have when working with Go moduels and try to give the best answers. By doing this, we believe we can better help everyone use Go moduels."
"Goproxy China" = "Goproxy China"
"If you can't find the answer to the question you want to ask below, you can always post your question by clicking the \"New Question\" button below. Please pay attention to follow the issue template we have prepared for you, that will help us better answer your question." = "If you can't find the answer to the question you want to ask below, you can always post your question by clicking the \"New Question\" button below. Please pay attention to follow the issue template we have prepared for you, that will help us better answer your question."
"Index" = "Index"
"New Question" = "New Question"
"Qiniu Cloud, Inc." = "Qiniu Cloud, Inc."
"Status" = "Status"
"Table of Contents" = "Table of Contents"
"The most trusted Go module proxy in China." = "The most trusted Go module proxy in China."
"faq.html" = "faq.html"
"https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.md&title=Question%3A+" = "https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.md&title=Question%3A+"
"index.html" = "index.html"
6 changes: 5 additions & 1 deletion locales/zh-CN.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
"Back to top" = "返回顶部"
"Contact" = "联系我们"
"FAQ" = "常见问题"
"Goproxy China is now trying to collect as many questions as possible about the problems Gophers have when working with Go moduels and try to give the best answers. By doing this, we believe we can better help everyone use Go moduels." = "Goproxy 中国现在正试图尽可能多地收集各种关于大家在使用 Go 模块时所遇见的问题并尽力给出最棒的解答。通过这样做,我们相信我们可以更好地帮助大家去使用 Go 模块。"
"Goproxy China" = "Goproxy 中国"
"If you can't find the answer to the question you want to ask below, you can always post your question by clicking the \"New Question\" button below. Please pay attention to follow the issue template we have prepared for you, that will help us better answer your question." = "如果你无法在下方找到你想要问的问题的解答,那么可以随时通过点击下方的“新建问题”按钮来发表你的问题。请注意遵循我们为你准备好的 Issue 模版,那样可以帮助我们更好地解答你的问题。"
"Index" = "首页"
"New Question" = "新建问题"
"Qiniu Cloud, Inc." = "七牛云"
"Status" = "状态页"
"Table of Contents" = "目录"
"The most trusted Go module proxy in China." = "中国最可靠的 Go 模块代理。"
"faq.html" = "faq.zh-CN.html"
"https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.md&title=Question%3A+" = "https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.zh-CN.md&title=问题:"
"index.html" = "index.zh-CN.html"
9 changes: 9 additions & 0 deletions model/qa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package model

import "html/template"

// QA is the question and answer model.
type QA struct {
Question string
Answer template.HTML
}
36 changes: 17 additions & 19 deletions templates/faq.html
Original file line number Diff line number Diff line change
@@ -1,58 +1,56 @@
<div class="jumbotron">
<div class="container text-center">
<h1 class="brand display-3">FAQ</h1>
<h1 class="brand display-3">{{locstr "FAQ"}}</h1>
</div>
</div>

<div class="container">
<div class="row">
<div class="col-md">
<p>Goproxy China is now trying to collect as many questions as possible about the problems Gophers have when working with Go moduels and try to give the best answers. By doing this, we believe we can better help everyone use Go moduels.</p>
<p>If you can't find the answer to the question you want to ask below, feel free to post your question <a href="https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.md&title=Question%3A+" target="_blank">here</a>. Please pay attention to follow the issue template we have prepared for you, that will help us better answer your question.</p>
<p>{{locstr "Goproxy China is now trying to collect as many questions as possible about the problems Gophers have when working with Go moduels and try to give the best answers. By doing this, we believe we can better help everyone use Go moduels."}}</p>
<p>{{locstr "If you can't find the answer to the question you want to ask below, you can always post your question by clicking the \"New Question\" button below. Please pay attention to follow the issue template we have prepared for you, that will help us better answer your question."}}</p>
</div>
</div>

<div class="row text-center">
<div class="col-md">
<a class="btn btn-outline-warning btn-lg" href="{{locstr "https://github.com/goproxy/goproxy.cn/issues/new?assignees=&labels=&template=question-consultation.md&title=Question%3A+"}}" role="button">{{locstr "New Question"}}</a>
</div>
</div>

<hr>

<div class="row">
<div class="col-md">
<h2>Table of Contents</h2>
<h2 id="Table of Contents"><a class="font-weight-bold text-info" href="#Table of Contents">Table of Contents</a></h2>
<h2 id="{{locstr "Table of Contents"}}"><a class="font-weight-bold text-info" href="#{{locstr "Table of Contents"}}">{{locstr "Table of Contents"}}</a></h2>
</div>
</div>

<div class="row">
<div class="col-md">
<ul>
<li><a href="#I committed a new revision to a repository, why isn't it showing up when I run go get -u or go list -m -versions?">I committed a new revision to a repository, why isn't it showing up when I run go get -u or go list -m -versions?</a></li>
<li><a href="#I removed a bad release from my repository but it still appears, what should I do?">I removed a bad release from my repository but it still appears, what should I do?</a></li>
{{range .QAs}}
<li><a href="#{{.Question}}">{{.Question}}</a></li>
{{end}}
</ul>
</div>
</div>

<hr>

<div class="row">
<div class="col-md">
<p id="I committed a new revision to a repository, why isn't it showing up when I run go get -u or go list -m -versions?"><a class="font-weight-bold text-info" href="#I committed a new revision to a repository, why isn't it showing up when I run go get -u or go list -m -versions?">I committed a new revision to a repository, why isn't it showing up when I run go get -u or go list -m -versions?</a></p>
</div>
</div>
{{range .QAs}}

<div class="row">
<div class="col-md">
<p>If you're using the <a href="https://goproxy.cn">goproxy.cn</a> as your Go module proxy. Then you need to know in order to improve caching and serving latencies, new revisions may not show up right away. If you want new revision to be immediately available in the <a href="https://goproxy.cn">goproxy.cn</a>, then first make sure there is a semantically versioned tag for this revision in the source repository. Then explicitly request that tagged version via <code>go get module@version</code>. After couple of minutes for caches to expire, the <code>go</code> command will see that tagged version.</p>
<p id="{{.Question}}"><a class="font-weight-bold text-info" href="#{{.Question}}">{{.Question}}</a></p>
</div>
</div>

<div class="row">
<div class="col-md">
<p id="I removed a bad release from my repository but it still appears, what should I do?"><a class="font-weight-bold text-info" href="#I removed a bad release from my repository but it still appears, what should I do?">I removed a bad release from my repository but it still appears, what should I do?</a></p>
<p>{{.Answer}}</p>
</div>
</div>

<div class="row">
<div class="col-md">
<p>If you're using the <a href="https://goproxy.cn">goproxy.cn</a> as your Go module proxy. Then you need to know whenever possible, Goproxy China aims to cache content in order to avoid breaking builds for people that depend on your module, so this bad release may still be available in the <a href="https://goproxy.cn">goproxy.cn</a> even if it is not available at the origin. The same situation applies if you delete your entire repository. We suggest creating a new release and encouraging people to use that one instead.</p>
</div>
</div>
{{end}}
</div>
57 changes: 0 additions & 57 deletions templates/faq.zh-CN.html

This file was deleted.

0 comments on commit 8e4128b

Please sign in to comment.