2017-06-07 06:20:53 +02:00
|
|
|
package example
|
2017-06-05 15:57:47 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2017-06-07 06:20:53 +02:00
|
|
|
"strings"
|
2017-06-05 15:57:47 +02:00
|
|
|
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
|
|
"github.com/kataras/iris/core/errors"
|
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
|
|
"github.com/russross/blackfriday"
|
|
|
|
)
|
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
// Parse will try to parse and return all examples.
|
|
|
|
// The input parameter "branch" is used to build
|
|
|
|
// the raw..iris-contrib/examples/$branch/
|
|
|
|
// but it should be the same with
|
|
|
|
// the kataras/iris/$branch/ for consistency.
|
|
|
|
func Parse(branch string) (examples []Example, err error) {
|
|
|
|
var (
|
|
|
|
contentsURL = "https://raw.githubusercontent.com/iris-contrib/examples/" + branch
|
|
|
|
tableOfContents = "Table of contents"
|
|
|
|
sanitizeMarkdown = true
|
|
|
|
)
|
2017-06-05 15:57:47 +02:00
|
|
|
|
|
|
|
// get the raw markdown
|
2017-06-07 06:20:53 +02:00
|
|
|
readmeURL := contentsURL + "/README.md"
|
|
|
|
res, err := http.Get(readmeURL)
|
2017-06-05 15:57:47 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
markdownContents, err := ioutil.ReadAll(res.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert it to html
|
|
|
|
htmlContents := &bytes.Buffer{}
|
|
|
|
htmlContentsFromMarkdown := blackfriday.MarkdownCommon(markdownContents)
|
|
|
|
|
|
|
|
if len(htmlContentsFromMarkdown) == 0 {
|
|
|
|
return nil, errors.New("empty html")
|
|
|
|
}
|
|
|
|
|
|
|
|
if sanitizeMarkdown {
|
|
|
|
markdownContents = bluemonday.UGCPolicy().SanitizeBytes(markdownContents)
|
|
|
|
}
|
|
|
|
|
|
|
|
htmlContents.Write(htmlContentsFromMarkdown)
|
|
|
|
// println("html contents: " + htmlContents.String())
|
|
|
|
// get the document from the html
|
|
|
|
readme, err := goquery.NewDocumentFromReader(htmlContents)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
// or with just one line (but may break if we add another h2,
|
|
|
|
// so I will do it with the hard and un-readable way for now)
|
2017-06-05 15:57:47 +02:00
|
|
|
// readme.Find("h2").First().NextAllFiltered("ul").Children().Text()
|
|
|
|
|
|
|
|
// find the header of Table Of Contents, we will need it to take its
|
|
|
|
// next ul, which should be the examples list.
|
|
|
|
var tableOfContentsHeader *goquery.Selection
|
|
|
|
readme.Find("h2").EachWithBreak(func(_ int, n *goquery.Selection) bool {
|
|
|
|
if nodeContents := n.Text(); nodeContents == tableOfContents {
|
|
|
|
tableOfContentsHeader = n
|
|
|
|
return false // break
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
|
|
|
|
if tableOfContentsHeader == nil {
|
|
|
|
return nil, errors.New("table of contents not found using: " + tableOfContents)
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the list of the examples
|
2017-06-07 06:20:53 +02:00
|
|
|
tableOfContentsUL := tableOfContentsHeader.NextFiltered("ul")
|
2017-06-05 15:57:47 +02:00
|
|
|
if tableOfContentsUL == nil {
|
|
|
|
return nil, errors.New("table of contents list not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
// iterate over categories example's <a href ...>...</a>
|
|
|
|
tableOfContentsUL.Children().EachWithBreak(func(_ int, li *goquery.Selection) bool {
|
|
|
|
exampleHrefLink := li.Children().First()
|
|
|
|
if exampleHrefLink == nil {
|
|
|
|
err = errors.New("example link href is nil, source: " + li.Text())
|
|
|
|
return false // break on first failure
|
|
|
|
}
|
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
name := exampleHrefLink.Text()
|
2017-06-05 15:57:47 +02:00
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
sourcelink, _ := li.Find("a").First().Attr("href")
|
|
|
|
hasChildren := !strings.HasSuffix(sourcelink, ".go")
|
2017-06-05 15:57:47 +02:00
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
example := Example{
|
|
|
|
Name: name,
|
|
|
|
DataSource: contentsURL + "/" + sourcelink,
|
|
|
|
HasChildren: hasChildren,
|
|
|
|
HasNotChildren: !hasChildren,
|
2017-06-05 15:57:47 +02:00
|
|
|
}
|
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
// search for sub examples
|
|
|
|
if hasChildren {
|
|
|
|
li.Find("ul").Children().EachWithBreak(func(_ int, liExample *goquery.Selection) bool {
|
|
|
|
name := liExample.Text()
|
|
|
|
liHref := liExample.Find("a").First()
|
|
|
|
sourcelink, ok := liHref.Attr("href")
|
|
|
|
if !ok {
|
|
|
|
err = errors.New(name + "'s source couldn't be found")
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
subExample := Example{
|
|
|
|
Name: name,
|
|
|
|
DataSource: contentsURL + "/" + sourcelink,
|
|
|
|
}
|
|
|
|
|
|
|
|
example.Children = append(example.Children, subExample)
|
|
|
|
return true
|
|
|
|
})
|
2017-06-05 15:57:47 +02:00
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
}
|
2017-06-05 15:57:47 +02:00
|
|
|
|
2017-06-07 06:20:53 +02:00
|
|
|
examples = append(examples, example)
|
2017-06-05 15:57:47 +02:00
|
|
|
return true
|
|
|
|
})
|
2017-06-07 06:20:53 +02:00
|
|
|
return examples, err
|
2017-06-05 15:57:47 +02:00
|
|
|
}
|