-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
404 changed files
with
247,988 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
.idea | ||
.idea | ||
zmdocs_darwin_amd64 | ||
zmdocs_linux_amd64 | ||
zmdocs_windows_amd64.exe |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,10 @@ | ||
module "github.com/zyra/docs" | ||
module github.com/zyra/zmdocs | ||
|
||
go 1.12 | ||
|
||
require ( | ||
github.com/russross/blackfriday v2.0.0+incompatible | ||
github.com/sirupsen/logrus v1.4.2 | ||
github.com/urfave/cli v1.22.1 | ||
gopkg.in/yaml.v2 v2.2.5 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= | ||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | ||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk= | ||
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= | ||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= | ||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= | ||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= | ||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= | ||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | ||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= | ||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= | ||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | ||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= | ||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= | ||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
package zmdocs | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"github.com/russross/blackfriday" | ||
"github.com/sirupsen/logrus" | ||
"github.com/zyra/zmdocs/templates" | ||
"gopkg.in/yaml.v2" | ||
"html/template" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
) | ||
|
||
type basePage struct { | ||
Name string `yaml:"name"` | ||
Path string `yaml:"path"` | ||
SourceFile string `yaml:"source"` | ||
Template string `yaml:"template"` | ||
AddToMenu bool `yaml:"addToMenu"` | ||
MenuGroup string `yaml:"menuGroup"` | ||
EditOnGithub bool `yaml:"editOnGithub"` | ||
} | ||
|
||
type Page struct { | ||
basePage `yaml:",inline"` | ||
Title string `yaml:"title,omitempty"` | ||
} | ||
|
||
type PagePattern struct { | ||
basePage `yaml:",inline"` | ||
SourceGlob string `yaml:"sourceGlob"` | ||
Pattern string `yaml:"pattern"` | ||
} | ||
|
||
type Template struct { | ||
Name string `yaml:"name"` | ||
SourceFile string `yaml:"source"` | ||
} | ||
|
||
type MenuItem struct { | ||
Name string `yaml:"name"` // name is required if group == true | ||
Title string `yaml:"title"` // menu item title | ||
Link string `yaml:"link"` // menu item link (optional) | ||
Items []*MenuItem `yaml:"items"` // sub menu items (optional) | ||
Group bool `yaml:"group"` // whether this is a group heading | ||
Active bool `yaml:"-"` | ||
} | ||
|
||
type ParserConfig struct { | ||
RootDir string `yaml:"rootDir"` // root directory of project, defaults to the config file directory if initialized with NewParserFromConfig | ||
OutDir string `yaml:"outDir"` | ||
Pages []*Page `yaml:"pages"` // list of pages to render | ||
AutoPages []*PagePattern `yaml:"pagePatterns"` // list of patterns to derive pages from | ||
Templates []*Template `yaml:"templates"` // list of template files | ||
MenuItems []*MenuItem `yaml:"menuItems"` // menu items | ||
SiteTitle string `yaml:"siteTitle"` | ||
Description string `yaml:"description"` | ||
Repo string `yaml:"repo"` | ||
} | ||
|
||
type File struct { | ||
basePage | ||
Title string | ||
} | ||
|
||
type Parser struct { | ||
Config *ParserConfig | ||
Files []*File | ||
Logger *logrus.Logger | ||
} | ||
|
||
func NewParser(config *ParserConfig) *Parser { | ||
l := logrus.New() | ||
|
||
l.SetFormatter(&logrus.TextFormatter{ | ||
ForceColors: true, | ||
EnvironmentOverrideColors: true, | ||
FullTimestamp: true, | ||
QuoteEmptyFields: true, | ||
}) | ||
|
||
if os.Getenv("ZMDOCS_DEBUG") == "true" { | ||
l.SetLevel(logrus.DebugLevel) | ||
} else { | ||
l.SetLevel(logrus.InfoLevel) | ||
} | ||
|
||
p := Parser{ | ||
Config: config, | ||
Files: make([]*File, 0), | ||
Logger: l, | ||
} | ||
|
||
return &p | ||
} | ||
|
||
func NewParserFromConfig(configPath string) (*Parser, error) { | ||
var config ParserConfig | ||
|
||
if data, err := ioutil.ReadFile(configPath); err != nil { | ||
return nil, fmt.Errorf("unabel to read config file: %s", err.Error()) | ||
} else if err := yaml.Unmarshal(data, &config); err != nil { | ||
return nil, fmt.Errorf("unable to parse config: %s", err.Error()) | ||
} | ||
|
||
config.RootDir = filepath.Dir(configPath) | ||
config.OutDir = filepath.Join(config.RootDir, config.OutDir) | ||
|
||
return NewParser(&config), nil | ||
} | ||
|
||
func (p *Parser) LoadSourceFiles() error { | ||
p.Logger.Info("loading source files") | ||
|
||
p.Logger.Debug("Loading static files") | ||
if err := p.loadStaticFiles(); err != nil { | ||
return err | ||
} | ||
p.Logger.Debug("Done loading static files") | ||
|
||
p.Logger.Debug("Loading glob files") | ||
if err := p.loadGlobFiles(); err != nil { | ||
return err | ||
} | ||
p.Logger.Debug("Done loading glob files") | ||
|
||
return nil | ||
} | ||
|
||
func (p *Parser) loadStaticFiles() error { | ||
for _, pg := range p.Config.Pages { | ||
g := filepath.Join(p.Config.RootDir, pg.SourceFile) | ||
|
||
file := File{ | ||
basePage: *&pg.basePage, | ||
Title: pg.Title, | ||
} | ||
|
||
file.SourceFile = g | ||
|
||
p.Files = append(p.Files, &file) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (p *Parser) loadGlobFiles() error { | ||
for i, ap := range p.Config.AutoPages { | ||
g := filepath.Join(p.Config.RootDir, ap.SourceGlob) | ||
|
||
p.Logger.WithFields(logrus.Fields{ | ||
"pattern": ap.Pattern, | ||
"absPath": g, | ||
}).Debug("processing page pattern") | ||
|
||
if patternMatches, err := GetPatternMatches(g, ap.Pattern); err != nil { | ||
return fmt.Errorf("unable to process page pattern #%d: %s", i, err.Error()) | ||
} else { | ||
p.Logger.WithFields(logrus.Fields{ | ||
"pattern": ap.Pattern, | ||
}).Debugf("found %d matches", len(patternMatches)) | ||
|
||
for _, pm := range patternMatches { | ||
if file, err := GetFileForPatternMatch(ap, pm); err != nil { | ||
return fmt.Errorf("unable to process file %s: \n\t%s", pm.Path, err.Error()) | ||
} else { | ||
p.Files = append(p.Files, file) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
type RenderContext struct { | ||
Title string | ||
SiteTitle string | ||
Description string | ||
MenuItems []*MenuItem | ||
Content template.HTML | ||
OutDir string | ||
OutFile string | ||
} | ||
|
||
func (p *Parser) Render() error { | ||
menuItems := p.Config.MenuItems | ||
rndCtxs := make([]*RenderContext, 0) | ||
|
||
for _, f := range p.Files { | ||
if fc, err := ioutil.ReadFile(f.SourceFile); err != nil { | ||
return err | ||
} else { | ||
exts := blackfriday.WithExtensions(blackfriday.CommonExtensions | blackfriday.AutoHeadingIDs | blackfriday.Autolink | blackfriday.Footnotes) | ||
rndOpts := blackfriday.HTMLRendererParameters{ | ||
Flags: blackfriday.CommonHTMLFlags | blackfriday.FootnoteReturnLinks, | ||
} | ||
rnd := blackfriday.NewHTMLRenderer(rndOpts) | ||
|
||
o := blackfriday.Run(fc, exts, blackfriday.WithRenderer(rnd)) | ||
|
||
if f.Title == "" { | ||
mp := blackfriday.New(exts, blackfriday.WithRenderer(rnd)) | ||
|
||
a := mp.Parse(fc) | ||
it := a.FirstChild | ||
for it != nil && f.Title == "" { | ||
if it.Type == blackfriday.Heading && it.Level == 1 && it.FirstChild != nil && it.FirstChild.Type == blackfriday.Text { | ||
f.Title = string(it.FirstChild.Literal) | ||
} | ||
|
||
it = it.Next | ||
} | ||
} | ||
|
||
outDir := filepath.Join(p.Config.RootDir, "docs", f.Path) | ||
outFile := filepath.Join(outDir, "index.html") | ||
|
||
ctx := RenderContext{ | ||
Title: f.Title, | ||
Content: template.HTML(o), | ||
OutDir: outDir, | ||
OutFile: outFile, | ||
} | ||
|
||
rndCtxs = append(rndCtxs, &ctx) | ||
|
||
menuItem := MenuItem{ | ||
Name: f.Name, | ||
Title: f.Title, | ||
Link: f.Path, | ||
} | ||
|
||
if f.AddToMenu { | ||
if f.MenuGroup != "" { | ||
for _, mit := range menuItems { | ||
if mit.Group && mit.Name == f.MenuGroup { | ||
if mit.Items == nil { | ||
mit.Items = make([]*MenuItem, 0) | ||
} | ||
|
||
mit.Items = append(mit.Items, &menuItem) | ||
} | ||
} | ||
} else { | ||
menuItems = append(menuItems, &menuItem) | ||
} | ||
} | ||
} | ||
} | ||
|
||
var baseTemplateStr string | ||
|
||
for _, t := range p.Config.Templates { | ||
if t.Name == "base" { | ||
baseTemplatePath := filepath.Join(p.Config.RootDir, t.SourceFile) | ||
baseTemplateData, err := ioutil.ReadFile(baseTemplatePath) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
baseTemplateStr = string(baseTemplateData) | ||
} | ||
} | ||
|
||
if baseTemplateStr == "" { | ||
baseTemplateStr = templates.BaseTemplate | ||
} | ||
|
||
baseTemplate, err := template.New("").Parse(baseTemplateStr) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, ctx := range rndCtxs { | ||
ctx.SiteTitle = p.Config.SiteTitle | ||
ctx.Description = p.Config.Description | ||
ctx.MenuItems = menuItems | ||
|
||
for _, mit := range menuItems { | ||
if mit.Group { | ||
for _, cmit := range mit.Items { | ||
cmit.Active = cmit.Title == ctx.Title | ||
} | ||
} else if mit.Title == ctx.Title { | ||
mit.Active = true | ||
} else { | ||
mit.Active = false | ||
} | ||
} | ||
|
||
buff := bytes.NewBuffer(make([]byte, 0)) | ||
|
||
if err := baseTemplate.Execute(buff, ctx); err != nil { | ||
return err | ||
} | ||
|
||
ctx.Content = template.HTML(buff.String()) | ||
|
||
if err := os.MkdirAll(ctx.OutDir, 0755); err != nil { | ||
return err | ||
} | ||
|
||
if err := ioutil.WriteFile(ctx.OutFile, []byte(ctx.Content), 0644); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.