Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • oss/utilities/documentation-manager
1 result
Select Git revision
Show changes
Commits on Source (4)
Showing
with 1296 additions and 408 deletions
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="document build html" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="documentation-manager" />
<working_directory value="$PROJECT_DIR$/development/examples/example3/" />
<parameters value="document html --config=config/web.yaml" />
<kind value="DIRECTORY" />
<directory value="$PROJECT_DIR$/application/source" />
<filePath value="$PROJECT_DIR$" />
<output_directory value="$PROJECT_DIR$/deployment/build" />
<method v="2" />
</configuration>
</component>
\ No newline at end of file
...@@ -7,15 +7,14 @@ This tool helps to manage documentation written in Markdown. ...@@ -7,15 +7,14 @@ This tool helps to manage documentation written in Markdown.
DocMan is a binary file that must be stored in a directory. DocMan is a binary file that must be stored in a directory.
The files can be found [here](http://download.schukai.com/tools/docman/). The files can be found [here](http://download.schukai.com/tools/docman/).
For Linux, the execution bit must still be set.
```bash ```bash
chmod u+x docman wget -O ~/.local/bin/docman https://download.schukai.com/tools/docman/docman-linux-amd64
## For Linux, the execution bit must still be set.
chmod u+x ~/.local/bin/docman
``` ```
## Developments ## Developments
To search the source code for new texts, you have to go to the source directory and To search the source code for new texts, you have to go to the source directory and
...@@ -33,11 +32,8 @@ kpsepath mf | sed -e 's/:/\n/g' ...@@ -33,11 +32,8 @@ kpsepath mf | sed -e 's/:/\n/g'
### Awsome Boxes ### Awsome Boxes
* [Awesomebox](https://ftp.gwdg.de/pub/ctan/graphics/awesomebox/awesomebox.pdf) * [Awesomebox](https://ftp.gwdg.de/pub/ctan/graphics/awesomebox/awesomebox.pdf)
### Circled numbers ### Circled numbers
[compsymb-1qyb3zd.pdf](https://math.uoregon.edu/wp-content/uploads/2014/12/compsymb-1qyb3zd.pdf) [compsymb-1qyb3zd.pdf](https://math.uoregon.edu/wp-content/uploads/2014/12/compsymb-1qyb3zd.pdf)
...@@ -97,202 +93,45 @@ Finally, we look for the configuration in the `/etc/documentations-manager/confi ...@@ -97,202 +93,45 @@ Finally, we look for the configuration in the `/etc/documentations-manager/confi
The parameter `path` specifies the path. The parameter `path` specifies the path.
### Help #### Configuration
There is help on the command line for each individual command.
```bash
docman --help
```
### New Document
A new document can be created with the command `add`.
```bash
docman documents add --name=path/to/document.md
```
A completely new file with a structure is created.
The parameter `--name` specifies the name of the document.
The name can be either the file name or the absolute path.
the ending .md is always appended.
All available fields are listed in the new file.
### Output a PDF
A pdf can be created using the following command:
```bash
docman overview \
print \
--path=requirement/documents \
--column=ID \
--column=Title \
--template=template/schukai.md \
--latex-template-path=requirement/template/schukai.latex \
--output=report.pdf \
--format=pdf
```
In this case the markdown files in the path `requirement/documents` are read.
A table with all requirements is created in the file and the two columns
`ID` and `Title` are used. Additional columns can be added using additional options `--column`.
File `template/schukai.md` is used as a template.
The LaTeX template `requirement/template/schukai.latex` is used for the design of the pdf.
The output format is PDF and the filename of the pdf document is `report.pdf`.
You can use a complete directory or a subdirectory as the path.
### Output of the tasks
```bash
docman tasks print --path=examples/
```
The output is then of the type:
| AUFGABE | BIS | ERLEDIGT | DATEI |
| -------------------------- | ----- | ---------- | -------------------- |
| das ist das erste todo 1 | — | — | ./req1/001-1425.md |
### Output of the items ```yaml
## DOCMAN_PATH
Path: /home/user/documents
## DOCMAN_DATE_FORMAT
DateFormat:
Add:
## DOCMAN_NEW_TEMPLATE
Template:
PDF:
## DOCMAN_PDF_OUTPUT
Output:
Teplates:
## DOCMAN_PDF_LATEX_TEMPLATE
Latex:
## DOCMAN_PDF_MARKDOWN_TEMPLATE
Markdown:
```bash
docman requirements print --path examples/ --column ID --column Title
``` ```
The output is then of the type:
| ID | TITEL |
| ---- | ---------------- |
| A1 | My requirement |
More columns can be added with `--column`.
### Output of privacy
```bash ### Help
docman privacy print --path=example/
```
### Output of requirements There is help on the command line for each individual command.
```bash ```bash
docman requirements print --path=example/ --column=ID --column= docman --help
``` ```
The output is then of the type: ### create PDF
| ID | GRUPPE | NAME | TYP | BESCHREIBUNG | BIS | ERLEDIGT | AM | VON | DATEI |
| -------------------- | -------- | -------------------------- | ------ | -------------- | ------------ | ---------- | ------------ | ----- | ---------------------- |
| 23423-Beistellung1 | A1 | Beistellung eines Bildes | Bild | Großes Logo | 2022-12-12 | ✓ | 2022-12-01 | Me | ./req1/002/002-01.md |
### Output changelog
```bash ```bash
docman changelog print --path=example/ docman document pdf --config pathto/config.yaml
```
The output is then of the type:
```
### 01.05.2022
- Requirement (R2)
### 24.01.2022
- Requirement (R1)
``` ```
### Output report
```
requirements report --grouped-by ID
```
This command produces two tables:
| Anforderung | Gesch | TIME SPENT |
| ------------- | ------- | --------- |
| ID1 | 40 | 1 |
| ID2 | 40 | 1 |
| ID3 | 40 | 1 |
| ID4 | 40 | 1 |
| ID5 | 40 | 2 |
| ID6 | 40 | 2 |
| ID7 | 40 | 2 |
| ID8 | 40 | 2 |
| ID9 | 40 | 2 |
| ID10 | 40 | 2 |
| ID11 | 40 | 3 |
| ID12 | 40 | 3 |
| ID13 | 40 | 3 |
| ID14 | 40 | 3 |
| ID15 | 40 | 3 |
| ID16 | 40 | 3 |
| ID17 | 40 | 3 |
| ID18 | 40 | 4 |
| ID19 | 40 | 4 |
| ID20 | 40 | 4 |
| ID21 | 40 | 4 |
| ID22 | 40 | 5 |
| ID23 | 40 | 5 |
| ID24 | 40 | 6 |
| ID25 | 40 | 6 |
1) Groups all estimates and adds up the estimate and the booked times. This allows you to see how much time you have
spent.
| KEY | PLANNED VALUE | TIME SPENT | RATIO |
| :---- | --------------- | ------------ | ------- |
| ID1 | 1000 | 75h0m0s | 7.50 |
2) This table shows for each plan value the hours needed, the mean, the variance and the standard deviation.
| PLAN VALUE | TIME SPENT | MEAN | VARIANCE | STANDARD DEVIATION |
| ------------ | ------------ | ------ | ---------- | -------------------- |
| 40 | 75h0m0s | 3.00 | 2.08 | 1.44 |
On average, we needed 3 hours in the example.
However, we needed 6 hours for 2 requirements.
The variance, or standard deviation, gives us a measure of how accurate we are.
The smaller the standard deviation, the better.
So what decision can we derive? If a new requirement is estimated at
40, the hours offered should be between 3 and 5.
### Sync with Gitlab
You can synchronize the issues of a document with a Gitlab server.
```bash
docman gitlab sync --path=example/
```
If no ID is defined in the document, an issue is created,
```yaml
issues:
- gitlab:
title: "Issue 1"
```
otherwise the data is updated.
```yaml
issues:
- gitlab:
id: 1
```
## Structure ## Structure
...@@ -383,3 +222,16 @@ Individual LaTeX commands can be looked up here: ...@@ -383,3 +222,16 @@ Individual LaTeX commands can be looked up here:
- Version 1.0 - Version 1.0
- takeover of the code from reqman - takeover of the code from reqman
## License # Credits
- Unsplash - https://unsplash.com/
- Icons Font Face - https://fontawesome.com/
- jQuery - http://www.jquery.com/
- Bootstrap 4 - http://getbootstrap.com/
- Highlight Js - https://highlightjs.org/
- jQuery easing - http://gsgd.co.uk/sandbox/jquery/easing/
- Magnific Popup - http://dimsemenov.com/plugins/magnific-popup/
- iDocs-Template - https://github.com/harnishdesign/iDocs
- Eisvogel LaTeX-Template - https://github.com/Wandmalfarbe/pandoc-latex-template
...@@ -19,11 +19,11 @@ func init() { ...@@ -19,11 +19,11 @@ func init() {
} }
type DocumentDefinition struct { type DocumentDefinition struct {
SourcePath string `long:"path" short:"p"` SourcePath string `long:"path" short:"p"`
DateFormat string `long:"date-format" short:"d"` DateFormat string `long:"date-format" short:"d"`
Add DocumentAddDefinition `command:"add" alias:"a"` Add DocumentAddDefinition `command:"add" alias:"a"`
Build DocumentBuildDefinition `command:"build" alias:"b"` HTML DocumentHTMLDefinition `command:"html" alias:"h"`
PDF DocumentPDFDefinition `command:"pdf"` PDF DocumentPDFDefinition `command:"pdf"`
} }
func initDocument(command *flags.Command) { func initDocument(command *flags.Command) {
......
...@@ -20,13 +20,27 @@ Title: New Document ...@@ -20,13 +20,27 @@ Title: New Document
Keywords: Keywords:
- documentation - documentation
References:
- https://www.example.com/
# Abbreviation of the document
Abbreviation:
# First and last name of the authors as a list # First and last name of the authors as a list
Author: Authors:
- null - null
Version: 1.0
Created: %%CREATED%% Created: %%CREATED%%
Last Update: %%CREATED%% Last Update: %%CREATED%%
Language: en
# Which level of the document is this?
Level: 1
... ...
## {{ .Title }} ## {{ .Title }}
......
...@@ -5,83 +5,69 @@ import ( ...@@ -5,83 +5,69 @@ import (
"gitlab.schukai.com/oss/utilities/documentation-manager/document" "gitlab.schukai.com/oss/utilities/documentation-manager/document"
"gitlab.schukai.com/oss/utilities/documentation-manager/environment" "gitlab.schukai.com/oss/utilities/documentation-manager/environment"
"gitlab.schukai.com/oss/utilities/documentation-manager/translations" "gitlab.schukai.com/oss/utilities/documentation-manager/translations"
"os"
"path"
"path/filepath"
"strings"
"time"
) )
const documentBuildSymbol = "document-build" const documentHTMLSymbol = "document-html"
func init() { func init() {
h := environment.Handler{ h := environment.Handler{
Init: initDocumentBuild, Init: initDocumentHTML,
Execute: runDocumentBuild, Execute: runDocumentHTML,
} }
environment.Handlers.Executor[documentBuildSymbol] = h environment.Handlers.Executor[documentHTMLSymbol] = h
} }
type DocumentBuildDefinition struct { type DocumentHTMLDefinition struct {
Template string `long:"template" short:"t"` SinglePage bool `long:"single-page" short:"s"`
Output string `long:"output" short:"o"`
Format string `long:"format" short:"f" choice:"html" choice:"pdf" default:"html" ` HTMLTemplate string `long:"html-template" short:"h"`
MarkdownTemplate string `long:"markdown-template" short:"m"`
OutputPath string `long:"output" short:"o"`
Verbose bool `long:"verbose" short:"v"`
} }
func initDocumentBuild(command *flags.Command) { func initDocumentHTML(command *flags.Command) {
const text = "Builds the documentation" const text = "Build the documentation as PDF"
command.ShortDescription = translations.T.Sprintf(text) command.ShortDescription = translations.T.Sprintf(text)
command.LongDescription = translations.T.Sprintf(text) command.LongDescription = translations.T.Sprintf(text)
for _, opt := range command.Options() { for _, opt := range command.Options() {
switch opt.LongName { switch opt.LongName {
case "template": case "html-template":
opt.Description = translations.T.Sprintf("template for the new document") opt.Description = translations.T.Sprintf("html template for the new document")
case "markdown-template":
opt.Description = translations.T.Sprintf("markdown template for the new document")
case "output": case "output":
opt.Description = translations.T.Sprintf("directory in which the finished documentation is to be written") opt.Description = translations.T.Sprintf("filename for the new document")
case "format": case "verbose":
opt.Description = translations.T.Sprintf("format of the finished documentation") opt.Description = translations.T.Sprintf("verbose output")
case "single-page":
opt.Description = translations.T.Sprintf("single page output")
} }
} }
} }
func buildDocumentation(name string) { func runDocumentHTML(command *flags.Command) {
root := environment.State.GetDocumentPath(definition.Document.SourcePath)
path := path.Join(root, name)
fileExtension := filepath.Ext(path)
if fileExtension == "" {
path += ".md"
} else if fileExtension != ".md" {
environment.ExitWithError(1, "file extension %s is not supported", fileExtension)
}
template := environment.State.GetDocumentTemplate(definition.Document.Build.Template) env := document.BuildHtmlEnvironment{
DateFormat: environment.State.GetDocumentDateFormat(definition.Document.DateFormat),
if template == "" { SourcePath: environment.State.GetDocumentPath(definition.Document.SourcePath),
template = newDocumentTemplate OutputPath: environment.State.GetDocumentHTMLOutputPath(definition.Document.PDF.OutputPath),
} }
date := time.Now().Format(environment.State.GetDocumentDateFormat(definition.Document.DateFormat)) env.Templates.HTML = environment.State.GetHTMLHTMLTemplatePath(definition.Document.HTML.HTMLTemplate)
template = strings.Replace(template, "%%CREATED%%", date, -1) env.Verbose = definition.Document.HTML.Verbose
env.SinglePage = environment.State.GetHTMLSinglePageState(definition.Document.HTML.SinglePage)
err := os.WriteFile(path, []byte(template), 0644) document.BuildHTML(env)
checkError(err)
} if environment.State.HasErrorsWarningsOrMessages() {
environment.PrintMessages()
func runDocumentBuild(command *flags.Command) { }
document.Build(document.BuildEnvironment{
DateFormat: environment.State.GetDocumentDateFormat(definition.Document.DateFormat),
SourcePath: environment.State.GetDocumentPath(definition.Document.SourcePath),
})
// buildDocumentation(name)
} }
...@@ -34,12 +34,12 @@ func initDocumentPDF(command *flags.Command) { ...@@ -34,12 +34,12 @@ func initDocumentPDF(command *flags.Command) {
for _, opt := range command.Options() { for _, opt := range command.Options() {
switch opt.LongName { switch opt.LongName {
case "template": case "latex-template":
opt.Description = translations.T.Sprintf("template for the new document") opt.Description = translations.T.Sprintf("latex template for the new document")
case "markdown-template":
opt.Description = translations.T.Sprintf("md template for the new document")
case "output": case "output":
opt.Description = translations.T.Sprintf("filename for the new document") opt.Description = translations.T.Sprintf("filename for the new document")
case "format":
opt.Description = translations.T.Sprintf("format of the finished documentation")
case "verbose": case "verbose":
opt.Description = translations.T.Sprintf("verbose output") opt.Description = translations.T.Sprintf("verbose output")
} }
......
package document package document
import (
"fmt"
)
type BuildEnvironment struct { type BuildEnvironment struct {
SourcePath string SourcePath string
DateFormat string DateFormat string
} }
func Build(env BuildEnvironment) error { //func Build(env BuildEnvironment) error {
dateFormat = env.DateFormat // dateFormat = env.DateFormat
//
definitions, err := getFiles(env.SourcePath) // definitions, err := getFiles(env.SourcePath)
if err != nil { // if err != nil {
return err // return err
} // }
fmt.Println(definitions) // fmt.Println(definitions)
return nil // return nil
} //}
...@@ -22,4 +22,5 @@ type document struct { ...@@ -22,4 +22,5 @@ type document struct {
LastUpdate LocaleTime `yaml:"Last Update"` LastUpdate LocaleTime `yaml:"Last Update"`
Language string `yaml:"Language"` Language string `yaml:"Language"`
Level int `yaml:"Level"` Level int `yaml:"Level"`
ID string `yaml:"ID"`
} }
package document
import (
"bytes"
"crypto/md5"
"encoding/base64"
"fmt"
"github.com/PuerkitoBio/goquery"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
"github.com/tdewolff/minify/v2"
minHTML "github.com/tdewolff/minify/v2/html"
"gitlab.schukai.com/oss/utilities/documentation-manager/environment"
"gitlab.schukai.com/oss/utilities/documentation-manager/translations"
"gitlab.schukai.com/oss/utilities/documentation-manager/utils"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"text/template"
"time"
)
type BuildHtmlEnvironment struct {
SourcePath string
DateFormat string
OutputPath string
Verbose bool
SinglePage bool
Templates struct {
HTML string
}
}
type HtmlDocument struct {
ID string
Content string
*SourceFile
}
type DocumentNode struct {
Level int
ID string
Title string
}
type SinglePageHtmlDataset struct {
Documents []HtmlDocument
CreatedFormat string // date format
Meta struct {
Title string
ShortTitle string
Description string
Keywords string
Language string
}
Version string
DocumentTree *Tree[DocumentNode]
TOC []DocumentNode
}
func BuildHTML(env BuildHtmlEnvironment) error {
if env.SinglePage {
return renderSinglePageHtml(env)
}
return renderMultiPageHtml(env)
}
func getSingleHtmlOutputFile(env BuildHtmlEnvironment) string {
output := env.OutputPath
if env.DateFormat != "" {
dateFormat = env.DateFormat
}
if !filepath.IsAbs(output) {
pwd := os.Getenv("PWD")
output = path.Clean(path.Join(pwd, output))
}
if output == "" {
environment.ExitWithError(2, "the output option must be specified")
}
fileInfo, err := os.Stat(output)
if err != nil {
if !os.IsNotExist(err) {
environment.ExitWithError(2, "cannot stat output file", err.Error())
}
} else {
if fileInfo.IsDir() {
output = path.Join(output, "index.html")
}
}
return output
}
func renderSinglePageHtml(env BuildHtmlEnvironment) error {
output := getSingleHtmlOutputFile(env)
t := environment.ReadTemplate(env.Templates.HTML)
p, err := template.New("HTML").Parse(t)
checkError(err)
d, err := NewHTMLDataset(env)
checkError(err)
buf := new(bytes.Buffer)
err = p.Execute(buf, d)
checkError(err)
m := minify.New()
m.AddFunc("text/html", minHTML.Minify)
out := new(bytes.Buffer)
err = m.Minify("text/html", out, buf)
checkError(err)
err = ioutil.WriteFile(output, out.Bytes(), 0644)
checkError(err)
return nil
}
func renderMultiPageHtml(env BuildHtmlEnvironment) error {
environment.ExitWithError(2, "not implemented")
return nil
}
func buildTree(body string) *Tree[DocumentNode] {
buf := new(bytes.Buffer)
buf.Write([]byte(body))
doc, err := goquery.NewDocumentFromReader(buf)
if err != nil {
log.Fatal(err)
}
obj := newTree[DocumentNode]()
ptr := obj
doc.Find("h1,h2,h3,h4").Each(func(k int, s *goquery.Selection) {
e := s.Get(0)
t := []rune(e.DataAtom.String())
l := t[1:len(t)]
i, err := strconv.Atoi(string(l))
checkError(err)
currentLevel := ptr.getLevel()
aID, found := s.Attr("id")
if !found {
aID = "rel-" + e.DataAtom.String()
}
payload := DocumentNode{
Level: i,
ID: aID,
Title: s.Text(),
}
if currentLevel == i {
ptr = ptr.appendAndGet()
ptr.setPayload(payload)
return
}
if currentLevel < i {
ptr = ptr.down(i)
ptr.setPayload(payload)
return
}
ptr = ptr.up(i)
ptr = ptr.appendAndGet()
ptr.setPayload(payload)
})
return obj
}
func getHtmlImages(content string, absolute string) (string, map[string]string) {
regEx := regexp.MustCompile(`(?P<match>\!\[(?P<label>[^]]*)\]\((?P<path>[^)]*)\))`)
matches := regEx.FindAllStringSubmatch(content, -1)
if matches == nil {
return content, nil
}
m := map[string]string{}
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
if utils.IsUrl(result["path"]) {
continue
}
if filepath.IsAbs(result["path"]) {
continue
}
p := filepath.Join(absolute, result["path"])
path := path.Clean(p)
fc, err := ioutil.ReadFile(path)
if err != nil {
continue
}
data := "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(fc)
hash := fmt.Sprintf("%x", md5.Sum([]byte(data)))
m[hash] = data
content = strings.Replace(content, result["match"], "!["+result["label"]+"]("+hash+")", -1)
}
return content, m
}
func replaceImages(content string, images map[string]string) string {
for k, v := range images {
content = strings.Replace(content, k, v, -1)
}
return content
}
func NewHTMLDataset(env BuildHtmlEnvironment) (*SinglePageHtmlDataset, error) {
files, err := getFiles(env.SourcePath)
if err != nil {
return nil, err
}
mapFiles, keys := buildFileMap(files)
d := &SinglePageHtmlDataset{}
d.Meta.Language = environment.State.GetHTMLMetaLanguage("")
d.Meta.Title = environment.State.GetHTMLMetaTitle("")
d.Meta.ShortTitle = environment.State.GetHTMLMetaShortTitle("")
d.Meta.Description = environment.State.GetHTMLMetaDescription("")
d.Meta.Keywords = environment.State.GetHTMLMetaKeywords("")
d.Version = environment.State.GetHTMLVersion("")
docs := []string{}
for _, key := range keys {
text := mapFiles[key].textMeta.text
text, s1Map := utils.MaskCodeBlocks(text, mapFiles[key].relSourcePath, 3)
text, s2Map := utils.MaskCodeBlocks(text, mapFiles[key].relSourcePath, 1)
text = convertHeadlines(text, mapFiles[key].level, mapFiles[key].textMeta.meta.Level)
text, boxMap := convertAwesomeBoxesToHTML(text)
text, imgMap := getHtmlImages(text, mapFiles[key].baseDir)
text = replaceRelativeLinksToHTML(text, mapFiles[key], mapFiles)
text = utils.InsertCodeBlocks(text, s2Map)
text = utils.InsertCodeBlocks(text, s1Map)
text = createHtmlFromMarkdown(text)
text = replaceImages(text, imgMap)
text = replaceAwesomeBoxes(text, boxMap)
id := mapFiles[key].textMeta.meta.ID
if id == "" {
id = mapFiles[key].hash
}
doc := HtmlDocument{
ID: id,
Content: text,
}
doc.SourceFile = mapFiles[key]
d.Documents = append(d.Documents, doc)
docs = append(docs, strings.TrimSpace(doc.Content))
}
d.DocumentTree = buildTree(strings.Join(docs, "\n"))
d.TOC = []DocumentNode{}
d.DocumentTree.recursiveIterate(func(t *Tree[DocumentNode]) {
if t.getLevel() == 0 {
return
}
d.TOC = append(d.TOC, t.Payload)
})
format := environment.State.GetDocumentDateFormat("")
now := time.Now()
d.CreatedFormat = now.Format(format)
if env.Verbose {
fmt.Println(d.Documents)
}
return d, nil
}
func convertAwesomeBoxesToHTML(content string) (string, map[string]string) {
regEx := regexp.MustCompile(`(?m)(?P<matches>!!!\s*(?P<type>[^\s]+)\s+?(?P<title>[^\n]*)\n(?P<lines>(?P<lastline>[[:blank:]]+[^\n]+\n)+))`)
matches := regEx.FindAllStringSubmatch(content, -1)
if matches == nil {
return content, nil
}
s := map[string]string{}
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
boxtype := "note"
switch {
case utils.Contains([]string{"notebox", "note", "info"}, result["type"]):
boxtype = "primary"
case utils.Contains([]string{"tipbox", "tip", "hint"}, result["type"]):
boxtype = "secondary"
case utils.Contains([]string{"warningbox", "warning", "warn"}, result["type"]):
boxtype = "warning"
case utils.Contains([]string{"cautionbox", "caution", "danger"}, result["type"]):
boxtype = "danger"
case utils.Contains([]string{"importantbox", "important"}, result["type"]):
boxtype = "danger"
}
c := "<div class=\"alert alert-" + boxtype + "\" role=\"" + boxtype + "\">"
if result["title"] != "" {
c += "<strong class=\"alert-heading\">" + utils.TrimQuotes(result["title"]) + "</strong><br>"
}
lines := result["lines"]
c += lines
c += "</div>"
hash := fmt.Sprintf("box%x", md5.Sum([]byte(c)))
s[hash] = c
content = strings.Replace(content, result["matches"], "\n"+hash+"\n", 1)
}
return content, s
}
func replaceAwesomeBoxes(content string, boxMap map[string]string) string {
for k, v := range boxMap {
content = strings.Replace(content, k, v, -1)
}
return content
}
func replaceRelativeLinksToHTML(content string, f *SourceFile, fileMap SourceFileMap) string {
label := "link_" + f.hash
content = "<div id=\"" + label + "\"></div>\n" + strings.TrimSpace(content) + "\n"
regEx := regexp.MustCompile(`(?:^|[^!])(?P<match>\[(?P<label>[^]]*)\]\((?P<path>[^)]*)\))`)
matches := regEx.FindAllStringSubmatch(content, -1)
if matches == nil {
return content
}
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
if filepath.IsAbs(result["path"]) {
continue
}
if utils.IsUrl(result["path"]) {
continue
}
d := filepath.Dir(f.relSourcePath)
p := filepath.Join(d, result["path"])
p = strings.Split(p, "#")[0]
ext := filepath.Ext(p)
if ext != ".md" && ext != ".markdown" {
environment.State.AddWarning(translations.T.Sprintf("file extension %s, in file %s, not supported for relative links", ext, f.absSourcePath))
continue
}
s := fileMap.findByRelativePath(p)
if s == nil {
environment.State.AddWarning(translations.T.Sprintf("relative path %s, in file %s, cannot be resolved", result["path"], f.absSourcePath))
continue
}
replace := "<a href=\"#link_" + s.hash + "\">" + result["label"] + "</a>"
content = strings.Replace(content, result["match"], replace, -1)
}
return content
}
func createHtmlFromMarkdown(text string) string {
htmlFlags := html.CommonFlags | html.HrefTargetBlank
opts := html.RendererOptions{
AbsolutePrefix: "",
FootnoteAnchorPrefix: "",
FootnoteReturnLinkContents: "",
CitationFormatString: "",
HeadingIDPrefix: "rel-",
HeadingIDSuffix: "",
Title: "",
CSS: "",
Icon: "",
Head: nil,
Flags: htmlFlags,
RenderNodeHook: nil,
Comments: nil,
Generator: "",
}
renderer := html.NewRenderer(opts)
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
parser := parser.NewWithExtensions(extensions)
bytes := []byte(text)
html := markdown.ToHTML(bytes, parser, renderer)
return string(html)
}
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"strings" "strings"
) )
var kbdMapping = map[string]string{ var kbdMappingToLatex = map[string]string{
"ctrl": "\\LKeyStrg", "ctrl": "\\LKeyStrg",
"tux": "\\LKeyTux", "tux": "\\LKeyTux",
"win": "\\LKeyWin", "win": "\\LKeyWin",
...@@ -36,7 +36,7 @@ var kbdMapping = map[string]string{ ...@@ -36,7 +36,7 @@ var kbdMapping = map[string]string{
"pgdown": "\\LKeyPgDown", "pgdown": "\\LKeyPgDown",
} }
func convertCircledNumbers(content string) string { func convertCircledNumbersToLatex(content string) string {
circleMap := map[string]string{ circleMap := map[string]string{
"➊": "\\large\\libertineGlyph{uni2776}\\normalsize", "➊": "\\large\\libertineGlyph{uni2776}\\normalsize",
...@@ -68,7 +68,7 @@ func convertCircledNumbers(content string) string { ...@@ -68,7 +68,7 @@ func convertCircledNumbers(content string) string {
return content return content
} }
func replaceKbd(content string) string { func replaceKbdToLatex(content string) string {
regEx := regexp.MustCompile(`(?P<match><kbd[^>]*>(?P<key>[^<]*)</kbd>)`) regEx := regexp.MustCompile(`(?P<match><kbd[^>]*>(?P<key>[^<]*)</kbd>)`)
...@@ -85,7 +85,7 @@ func replaceKbd(content string) string { ...@@ -85,7 +85,7 @@ func replaceKbd(content string) string {
} }
} }
r, ok := kbdMapping[strings.ToLower(result["key"])] r, ok := kbdMappingToLatex[strings.ToLower(result["key"])]
if !ok { if !ok {
runes := []rune(result["key"]) runes := []rune(result["key"])
for _, k := range runes { for _, k := range runes {
...@@ -99,5 +99,5 @@ func replaceKbd(content string) string { ...@@ -99,5 +99,5 @@ func replaceKbd(content string) string {
} }
return content return content
} }
...@@ -51,11 +51,11 @@ func NewPdfDataset(env BuildPdfEnvironment) (*PdfDataset, error) { ...@@ -51,11 +51,11 @@ func NewPdfDataset(env BuildPdfEnvironment) (*PdfDataset, error) {
text, s2Map := utils.MaskCodeBlocks(text, mapFiles[key].relSourcePath, 1) text, s2Map := utils.MaskCodeBlocks(text, mapFiles[key].relSourcePath, 1)
text = convertHeadlines(text, mapFiles[key].level, mapFiles[key].textMeta.meta.Level) text = convertHeadlines(text, mapFiles[key].level, mapFiles[key].textMeta.meta.Level)
text = convertAwesomeBoxes(text) text = convertAwesomeBoxesToLatex(text)
text = convertImages(text, mapFiles[key].baseDir) text = convertImages(text, mapFiles[key].baseDir)
text = convertCircledNumbers(text) text = convertCircledNumbersToLatex(text)
text = replaceKbd(text) text = replaceKbdToLatex(text)
text = replaceRelativeLinks(text, mapFiles[key], mapFiles) text = replaceRelativeLinksToLatex(text, mapFiles[key], mapFiles)
text = utils.InsertCodeBlocks(text, s2Map) text = utils.InsertCodeBlocks(text, s2Map)
text = utils.InsertCodeBlocks(text, s1Map) text = utils.InsertCodeBlocks(text, s1Map)
...@@ -90,7 +90,7 @@ func BuildPDF(env BuildPdfEnvironment) error { ...@@ -90,7 +90,7 @@ func BuildPDF(env BuildPdfEnvironment) error {
} }
if output == "" { if output == "" {
environment.ExitWithError(2, "if the type is pdf, the output option must be specified") environment.ExitWithError(2, "the output option must be specified")
} }
fileInfo, err := os.Stat(output) fileInfo, err := os.Stat(output)
...@@ -135,7 +135,7 @@ func BuildPDF(env BuildPdfEnvironment) error { ...@@ -135,7 +135,7 @@ func BuildPDF(env BuildPdfEnvironment) error {
} }
func replaceRelativeLinks(content string, f *SourceFile, fileMap SourceFileMap) string { func replaceRelativeLinksToLatex(content string, f *SourceFile, fileMap SourceFileMap) string {
label := "link_" + f.hash label := "link_" + f.hash
content = "\\hypertarget{" + label + "}{ } \n" + strings.TrimSpace(content) + "\n" content = "\\hypertarget{" + label + "}{ } \n" + strings.TrimSpace(content) + "\n"
...@@ -207,71 +207,8 @@ end ...@@ -207,71 +207,8 @@ end
} }
type foundedTitleInfoStruct struct {
level int
match string
title string
}
type foundedTitleInfo []foundedTitleInfoStruct
func convertHeadlines(content string, level, startLevel int) string {
d := 0
info, smallestLevelInTheDoc := calculateLevel(content)
if startLevel == 0 {
d = level - smallestLevelInTheDoc
} else {
d = startLevel - smallestLevelInTheDoc
}
if d < 0 {
d = 0
}
for _, i := range info {
fill := strings.Repeat("#", d+i.level)
nw := fill + " " + i.title + "\n"
content = strings.Replace(content, i.match, nw, 1)
}
return content
}
func calculateLevel(content string) (foundedTitleInfo, int) {
regEx := regexp.MustCompile(`(?m)^(?P<match>(?P<level>#+)\s+(?P<title>[^\n]*))`)
matches := regEx.FindAllStringSubmatch(content, -1)
info := foundedTitleInfo{}
if matches == nil {
return info, -1
}
smallestLevelInTheDoc := 999
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
info = append(info, foundedTitleInfoStruct{
level: len(result["level"]),
match: result["match"],
title: result["title"],
})
if len(result["level"]) < smallestLevelInTheDoc {
smallestLevelInTheDoc = len(result["level"])
}
}
return info, smallestLevelInTheDoc
}
// https://ftp.gwdg.de/pub/ctan/graphics/awesomebox/awesomebox.pdf // https://ftp.gwdg.de/pub/ctan/graphics/awesomebox/awesomebox.pdf
func convertAwesomeBoxes(content string) string { func convertAwesomeBoxesToLatex(content string) string {
regEx := regexp.MustCompile(`(?m)(?P<matches>!!!\s*(?P<type>[^\s]+)\s+?(?P<title>[^\n]*)\n(?P<lines>(?P<lastline>[[:blank:]]+[^\n]+\n)+))`) regEx := regexp.MustCompile(`(?m)(?P<matches>!!!\s*(?P<type>[^\s]+)\s+?(?P<title>[^\n]*)\n(?P<lines>(?P<lastline>[[:blank:]]+[^\n]+\n)+))`)
...@@ -314,7 +251,7 @@ func convertAwesomeBoxes(content string) string { ...@@ -314,7 +251,7 @@ func convertAwesomeBoxes(content string) string {
} }
lines := result["lines"] lines := result["lines"]
lines = convertAwesomeBoxesMarkdown(lines) lines = convertAwesomeBoxesMarkdownWithPandoc(lines)
c += "\n" + lines + "\n" //+escapeLatexSpecialChars(result["lastline"])) + "\n" c += "\n" + lines + "\n" //+escapeLatexSpecialChars(result["lastline"])) + "\n"
awesomebox := `\begin{` + boxtype + `block}` + c + "\n" + `\end{` + boxtype + `block}` awesomebox := `\begin{` + boxtype + `block}` + c + "\n" + `\end{` + boxtype + `block}`
...@@ -327,7 +264,7 @@ func convertAwesomeBoxes(content string) string { ...@@ -327,7 +264,7 @@ func convertAwesomeBoxes(content string) string {
} }
func convertAwesomeBoxesMarkdown(content string) string { func convertAwesomeBoxesMarkdownWithPandoc(content string) string {
output := runInlinePandoc(escapeLatexSpecialChars(utils.TrimLines(content))) output := runInlinePandoc(escapeLatexSpecialChars(utils.TrimLines(content)))
return output return output
} }
...@@ -374,104 +311,3 @@ func escapeLatexSpecialChars(content string) string { ...@@ -374,104 +311,3 @@ func escapeLatexSpecialChars(content string) string {
return result return result
} }
func convertImages(content string, absolute string) string {
regEx := regexp.MustCompile(`(?P<match>\!\[(?P<label>[^]]*)\]\((?P<path>[^)]*)\))`)
matches := regEx.FindAllStringSubmatch(content, -1)
if matches == nil {
return content
}
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
if utils.IsUrl(result["path"]) {
continue
}
if filepath.IsAbs(result["path"]) {
continue
}
p := filepath.Join(absolute, result["path"])
path := path.Clean(p)
content = strings.Replace(content, result["match"], "!["+result["label"]+"]("+path+")", -1)
}
return content
}
//func convertTemplateLogo(content string, absolute string) string {
// todoRegEx := regexp.MustCompile(`(?m)^(?P<match>logo:\s*"?(?P<path>[^"\n]*)"?\s*)$`)
//
// matches := todoRegEx.FindAllStringSubmatch(content, -1)
// if matches == nil {
// return content
// }
//
// for _, match := range matches {
// result := make(map[string]string)
// for i, name := range todoRegEx.SubexpNames() {
// if i != 0 && name != "" {
// result[name] = match[i]
// }
// }
//
// if filepath.IsAbs(result["path"]) {
// continue
// }
//
// path := path.Clean(absolute + "/" + result["path"])
// content = strings.Replace(content, result["match"], "logo: \""+path+"\"", -1)
//
// }
//
// return content
//}
//func convertTemplateLatexLogo(content string, absolute string) string {
// todoRegEx := regexp.MustCompile(`(?m)(?P<match>\\includegraphics[^{]*\{(?P<path>[^}]*)\})`)
//
// matches := todoRegEx.FindAllStringSubmatch(content, -1)
// if matches == nil {
// return content
// }
//
// for _, match := range matches {
// result := make(map[string]string)
// for i, name := range todoRegEx.SubexpNames() {
// if i != 0 && name != "" {
// result[name] = match[i]
// }
// }
//
// if filepath.IsAbs(result["path"]) {
// continue
// }
//
// path := path.Clean(absolute + "/" + result["path"])
// a := strings.Replace(result["match"], result["path"], path, -1)
//
// content = strings.Replace(content, result["match"], a, -1)
//
// }
//
// return content
//}
//
//func convertTemplateImages(content string, absolute string) string {
// content = convertTemplateLogo(content, absolute)
// content = convertTemplateLatexLogo(content, absolute)
//
// return content
//
//}
package document
import "fmt"
type Tree[T any] struct {
Level int
Children []*Tree[T]
Parent *Tree[T]
Payload T
}
func newTree[T any]() *Tree[T] {
return &Tree[T]{}
}
func (t *Tree[T]) traverseAndInitLevel(level int) {
t.Level = level
for _, child := range t.Children {
child.traverseAndInitLevel(level + 1)
}
}
func (t *Tree[T]) addChild(child *Tree[T]) {
t.Children = append(t.Children, child)
child.Parent = t
t.getRoot().traverseAndInitLevel(0)
}
func (t *Tree[T]) addChildren(children []*Tree[T]) {
for _, child := range children {
t.addChild(child)
child.Parent = t
}
t.getRoot().traverseAndInitLevel(0)
}
func (t *Tree[T]) getChildren() []*Tree[T] {
return t.Children
}
func (t *Tree[T]) getLevel() int {
return t.Level
}
func (t *Tree[T]) getParent() *Tree[T] {
return t.Parent
}
func (t *Tree[T]) getRoot() *Tree[T] {
if t.Parent == nil {
return t
}
return t.Parent.getRoot()
}
func (t *Tree[T]) getPayload() T {
return t.Payload
}
func (t *Tree[T]) setPayload(payload T) {
t.Payload = payload
}
func (t *Tree[T]) getPayloadAsString() string {
return fmt.Sprintf("%v", t.Payload)
}
func (t *Tree[T]) appendAndGet() *Tree[T] {
parent := t.getParent()
if parent == nil {
parent = t
}
n := newTree[T]()
parent.addChild(n)
return n
}
func (t *Tree[T]) up(level int) *Tree[T] {
if level > t.getLevel() {
panic("level>t.getLevel()")
}
if level == t.getLevel() {
return t
}
return t.Parent.up(level)
}
func (t *Tree[T]) recursiveIterate(f func(*Tree[T])) {
f(t)
for _, child := range t.Children {
child.recursiveIterate(f)
}
}
func (t *Tree[T]) down(level int) *Tree[T] {
if level < t.Level {
panic("level < t.Level")
}
if t.Level == level {
return t
}
if t.Children == nil {
t.addChild(newTree[T]())
return t.down(level)
}
return t.Children[len(t.Children)-1].down(level)
}
//func (t *Tree[T]) getSubTree() []Tree {
// return t.getSubTreeWithLevel(t.Level)
//}
//
//func (t *Tree[T]) getSubTreeWithLevel(level int) []Tree {
// if t.Level == level {
// return []Tree{*t}
// }
// var result []Tree
// for _, child := range t.Children {
// result = append(result, child.getSubTreeWithLevel(level)...)
// }
// return result
//}
package document
import "testing"
func TestParseList(t *testing.T) {
obj := newTree[int]()
ptr := obj
list := []int{3, 4, 4, 6, 1, 2}
for _, i := range list {
currentLevel := ptr.getLevel()
if currentLevel == i {
ptr = ptr.appendAndGet()
continue
}
if currentLevel < i {
ptr = ptr.down(i)
} else {
ptr = ptr.up(i)
}
}
if ptr.getLevel() != 2 {
t.Error("ptr.getLevel() != 6")
}
count := 0
obj.recursiveIterate(func(t *Tree[int]) {
count++
})
if count != 8 {
t.Error("count != 7")
}
}
func TestParseList2(t *testing.T) {
obj := newTree[int]()
ptr := obj
list := []int{1, 2, 3, 2, 3, 2, 3}
for _, i := range list {
currentLevel := ptr.getLevel()
if currentLevel == i {
ptr = ptr.appendAndGet()
continue
}
if currentLevel < i {
ptr = ptr.down(i)
continue
}
ptr = ptr.up(i)
ptr = ptr.appendAndGet()
}
if ptr.getLevel() != 3 {
t.Error("ptr.getLevel() != 3")
}
count := 0
obj.recursiveIterate(func(t *Tree[int]) {
count++
})
if count != 8 {
t.Error("count != 8")
}
}
func TestRecursiveIterator(t *testing.T) {
obj := newTree[int]()
sub := newTree[int]()
sub.addChild(newTree[int]())
obj.addChild(sub)
count := 0
obj.recursiveIterate(func(t *Tree[int]) {
count++
})
if count != 3 {
t.Error("count != 3")
}
}
func TestGetGuaranteedChild2(t *testing.T) {
obj := newTree[int]()
if obj.down(6).getLevel() != 6 {
t.Error("obj.getGuaranteedNode(6).getLevel() != 6")
}
}
func TestGetGuaranteedChild(t *testing.T) {
obj := newTree[int]()
c1 := newTree[int]()
c11 := newTree[int]()
c111 := newTree[int]()
c1111 := newTree[int]()
c1112 := newTree[int]()
c111.addChild(c1111)
c111.addChild(c1112)
c11.addChild(c111)
c1.addChild(c11)
obj.addChild(c1)
if obj.down(1).getLevel() != 1 {
t.Error("obj.getGuaranteedNode(1).getLevel() != 1")
}
if obj.down(2).getLevel() != 2 {
t.Error("obj.getGuaranteedNode(2).getLevel() != 2")
}
if obj.down(3).getLevel() != 3 {
t.Error("obj.getGuaranteedNode(3).getLevel() != 3")
}
if obj.down(6).getLevel() != 6 {
t.Error("obj.getGuaranteedNode(6).getLevel() != 6")
}
}
func TestTreeAddChild(t *testing.T) {
tree := newTree[int]()
tree.addChild(newTree[int]())
tree.addChild(newTree[int]())
tree.addChild(newTree[int]())
if len(tree.getChildren()) != 3 {
t.Error("Tree.getChildren() != 3")
}
}
func TestTreeAddChildren(t *testing.T) {
obj := newTree[int]()
obj.addChildren([]*Tree[int]{newTree[int](), newTree[int](), newTree[int]()})
if len(obj.getChildren()) != 3 {
t.Error("Tree.getChildren() != 3")
}
}
func TestTreeGetParent(t *testing.T) {
obj := newTree[int]()
obj.addChild(newTree[int]())
if obj.getChildren()[0].getParent() != obj {
t.Error("Tree.getChildren()[0].getParent() != obj")
}
}
func TestTreeGetRoot(t *testing.T) {
obj := newTree[int]()
sub := newTree[int]()
sub.addChild(newTree[int]())
obj.addChild(sub)
if obj.getChildren()[0].getChildren()[0].getRoot() != obj {
t.Error("Tree.getChildren()[0].getChildren()[0].getRoot() != obj")
}
}
//func TestTreeGetSubTree(t *testing.T) {
//
// obj := newTree()
//
// sub := newTree()
// sub.addChild(newTree())
//
// obj.addChild(sub)
//
// if len(obj.getChildren()[0].getSubTree()) != 1 {
// t.Error("Tree.getChildren()[0].getSubTree() != 1")
// }
//
//}
package document
import (
"gitlab.schukai.com/oss/utilities/documentation-manager/utils"
"path"
"path/filepath"
"regexp"
"strings"
)
type foundedTitleInfoStruct struct {
level int
match string
title string
}
type foundedTitleInfo []foundedTitleInfoStruct
func convertHeadlines(content string, level, startLevel int) string {
d := 0
info, smallestLevelInTheDoc := calculateLevel(content)
if startLevel == 0 {
d = level - smallestLevelInTheDoc
} else {
d = startLevel - smallestLevelInTheDoc
}
if d < 0 {
d = 0
}
for _, i := range info {
fill := strings.Repeat("#", d+i.level)
nw := fill + " " + i.title + "\n"
content = strings.Replace(content, i.match, nw, 1)
}
return content
}
func calculateLevel(content string) (foundedTitleInfo, int) {
regEx := regexp.MustCompile(`(?m)^(?P<match>(?P<level>#+)\s+(?P<title>[^\n]*))`)
matches := regEx.FindAllStringSubmatch(content, -1)
info := foundedTitleInfo{}
if matches == nil {
return info, -1
}
smallestLevelInTheDoc := 999
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
info = append(info, foundedTitleInfoStruct{
level: len(result["level"]),
match: result["match"],
title: result["title"],
})
if len(result["level"]) < smallestLevelInTheDoc {
smallestLevelInTheDoc = len(result["level"])
}
}
return info, smallestLevelInTheDoc
}
func convertImages(content string, absolute string) string {
regEx := regexp.MustCompile(`(?P<match>\!\[(?P<label>[^]]*)\]\((?P<path>[^)]*)\))`)
matches := regEx.FindAllStringSubmatch(content, -1)
if matches == nil {
return content
}
for _, match := range matches {
result := make(map[string]string)
for i, name := range regEx.SubexpNames() {
if i != 0 && name != "" {
result[name] = match[i]
}
}
if utils.IsUrl(result["path"]) {
continue
}
if filepath.IsAbs(result["path"]) {
continue
}
p := filepath.Join(absolute, result["path"])
path := path.Clean(p)
content = strings.Replace(content, result["match"], "!["+result["label"]+"]("+path+")", -1)
}
return content
}
package environment package environment
import ( import (
"github.com/kelseyhightower/envconfig" "context"
"github.com/sethvargo/go-envconfig"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"os" "os"
"os/user" "os/user"
...@@ -13,21 +14,36 @@ const configFileName = "config.yaml" ...@@ -13,21 +14,36 @@ const configFileName = "config.yaml"
type Configuration struct { type Configuration struct {
Document struct { Document struct {
Path string `yaml:"Path" envconfig:"PATH"` Path string `yaml:"Path" env:"PATH"`
DateFormat string `yaml:"DateFormat" envconfig:"DATE_FORMAT"` Version string `yaml:"Version" env:"VERSION"`
DateFormat string `yaml:"DateFormat" env:"DATE_FORMAT"`
Add struct { Add struct {
Template string `yaml:"Template" envconfig:"NEW_TEMPLATE"` Template string `yaml:"Template" env:"NEW_TEMPLATE"`
} }
Build struct { Build struct {
//Path string `yaml:"Path" envconfig:"BUILD_PATH"` //Path string `yaml:"Path" env:"BUILD_PATH"`
} `yaml:"Build"` } `yaml:"Build"`
PDF struct { PDF struct {
Output string `yaml:"Output" envconfig:"PDF_OUTPUT"` Output string `yaml:"Output" env:"PDF_OUTPUT"`
Teplates struct { Templates struct {
Latex string `yaml:"Latex" envconfig:"PDF_LATEX_TEMPLATE"` Latex string `yaml:"Latex" env:"PDF_LATEX_TEMPLATE"`
Markdown string `yaml:"Markdown" envconfig:"PDF_MARKDOWN_TEMPLATE"` Markdown string `yaml:"Markdown" env:"PDF_MARKDOWN_TEMPLATE"`
} `yaml:"Templates"` } `yaml:"Templates"`
} `yaml:"PDF"` } `yaml:"PDF"`
HTML struct {
Output string `yaml:"Output" env:"HTML_OUTPUT"`
SinglePage bool `yaml:"SinglePage" env:"HTML_SINGLEPAGE"`
Templates struct {
HTML string `yaml:"HTML" env:"HTML_HTML_TEMPLATE"`
} `yaml:"Templates"`
Meta struct {
Title string `yaml:"Title" env:"HTML_TITLE"`
ShortTitle string `yaml:"Short-Title" env:"HTML_SHORT_TITLE"`
Description string `yaml:"Description" env:"HTML_DESCRIPTION"`
Keywords string `yaml:"Keywords" env:"HTML_KEYWORDS"`
Language string `yaml:"Language" env:"HTML_LANGUAGE"`
} `yaml:"Meta"`
} `yaml:"HTML"`
} `yaml:"Document"` } `yaml:"Document"`
} }
...@@ -61,21 +77,37 @@ func InitConfiguration(configPath string) { ...@@ -61,21 +77,37 @@ func InitConfiguration(configPath string) {
usr, err := user.Current() usr, err := user.Current()
if err == nil { if err == nil {
userConfig = usr.HomeDir + "/.config/" + State.info.Mnemonic + "/" + configFileName userConfig = path.Join(usr.HomeDir, ".config", State.info.Mnemonic, configFileName)
} }
var current1 string
var current2 string
current, err := os.Getwd() current, err := os.Getwd()
if err == nil { if err == nil {
current = current + "/" + configFileName current1 = path.Join(current, configFileName)
}
if err == nil {
current2 = path.Join(current, ".config", configFileName)
}
if !path.IsAbs(configPath) {
configPath = path.Join(current, configPath)
} }
State.configuration = &Configuration{} State.configuration = &Configuration{}
err = envconfig.Process(strings.ToUpper(State.info.Mnemonic), State.configuration)
ctx := context.Background()
l := envconfig.PrefixLookuper(strings.ToUpper(State.info.Mnemonic)+"_", envconfig.OsLookuper())
err = envconfig.ProcessWith(ctx, State.configuration, l)
checkError(err) checkError(err)
for _, path := range []string{ for _, path := range []string{
configPath, configPath,
current, current1,
current2,
userConfig, userConfig,
"/etc/" + State.info.Mnemonic + "/" + configFileName} { "/etc/" + State.info.Mnemonic + "/" + configFileName} {
if checkAndInitConfiguration(path) { if checkAndInitConfiguration(path) {
......
package environment
func (e *stateStruct) GetHTMLOutputPath() string {
return e.sanityConfigPath(e.configuration.Document.HTML.Output)
}
func (e *stateStruct) GetHTMLHTMLTemplatePath(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Templates.HTML != "" {
return e.sanityConfigPath(e.configuration.Document.HTML.Templates.HTML)
}
return ""
}
func (e *stateStruct) GetHTMLSinglePageState(arg bool) bool {
if arg {
return arg
}
return e.configuration.Document.HTML.SinglePage
}
func (e *stateStruct) GetHTMLMetaTitle(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Meta.Title != "" {
return e.configuration.Document.HTML.Meta.Title
}
return "documentation"
}
func (e *stateStruct) GetHTMLMetaShortTitle(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Meta.ShortTitle != "" {
return e.configuration.Document.HTML.Meta.ShortTitle
}
return "documentation"
}
func (e *stateStruct) GetHTMLMetaLanguage(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Meta.Language != "" {
return e.configuration.Document.HTML.Meta.Language
}
return "en"
}
func (e *stateStruct) GetHTMLMetaDescription(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Meta.Description != "" {
return e.configuration.Document.HTML.Meta.Description
}
return ""
}
func (e *stateStruct) GetHTMLMetaKeywords(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Meta.Keywords != "" {
return e.configuration.Document.HTML.Meta.Keywords
}
return ""
}
func (e *stateStruct) GetHTMLVersion(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.Version != "" {
return e.configuration.Document.Version
}
return ""
}
func (e *stateStruct) GetDocumentHTMLOutputPath(arg string) string {
if arg != "" {
return arg
}
if e.configuration.Document.HTML.Output != "" {
return e.sanityConfigPath(e.configuration.Document.HTML.Output)
}
return ""
}
...@@ -9,8 +9,8 @@ func (e *stateStruct) GetPDFLatexTemplatePath(arg string) string { ...@@ -9,8 +9,8 @@ func (e *stateStruct) GetPDFLatexTemplatePath(arg string) string {
return arg return arg
} }
if e.configuration.Document.PDF.Teplates.Latex != "" { if e.configuration.Document.PDF.Templates.Latex != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Teplates.Latex) return e.sanityConfigPath(e.configuration.Document.PDF.Templates.Latex)
} }
return "" return ""
...@@ -21,8 +21,8 @@ func (e *stateStruct) GetPDFMarkdownTemplatePath(arg string) string { ...@@ -21,8 +21,8 @@ func (e *stateStruct) GetPDFMarkdownTemplatePath(arg string) string {
return arg return arg
} }
if e.configuration.Document.PDF.Teplates.Markdown != "" { if e.configuration.Document.PDF.Templates.Markdown != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Teplates.Markdown) return e.sanityConfigPath(e.configuration.Document.PDF.Templates.Markdown)
} }
return "" return ""
......
...@@ -3,22 +3,29 @@ module gitlab.schukai.com/oss/utilities/documentation-manager ...@@ -3,22 +3,29 @@ module gitlab.schukai.com/oss/utilities/documentation-manager
go 1.18 go 1.18
require ( require (
github.com/PuerkitoBio/goquery v1.8.0
github.com/evanw/esbuild v0.14.49
github.com/gomarkdown/markdown v0.0.0-20220627144906-e9a81102ebeb
github.com/gookit/color v1.5.1 github.com/gookit/color v1.5.1
github.com/jessevdk/go-flags v1.5.0 github.com/jessevdk/go-flags v1.5.0
github.com/kelseyhightower/envconfig v1.4.0 github.com/kelseyhightower/envconfig v1.4.0
github.com/sethvargo/go-envconfig v0.8.0
golang.org/x/text v0.3.7 golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/go-chi/chi/v5 v5.0.7 // indirect github.com/go-chi/chi/v5 v5.0.7 // indirect
github.com/go-chi/docgen v1.2.0 // indirect github.com/go-chi/docgen v1.2.0 // indirect
github.com/go-chi/httprate v0.5.3 // indirect github.com/go-chi/httprate v0.5.3 // indirect
github.com/gomarkdown/markdown v0.0.0-20220627144906-e9a81102ebeb // indirect github.com/tdewolff/minify/v2 v2.12.0 // indirect
github.com/tdewolff/parse/v2 v2.6.1 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect go.uber.org/zap v1.21.0 // indirect
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d // indirect golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
) )
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/evanw/esbuild v0.14.49 h1:jpZ/ut75socKiFF2XWSzjTAVAQP7IkRvrkLFaIb/Ueg=
github.com/evanw/esbuild v0.14.49/go.mod h1:GG+zjdi59yh3ehDn4ZWfPcATxjPDUH53iU4ZJbp7dkY=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
...@@ -22,12 +32,22 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa ...@@ -22,12 +32,22 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sethvargo/go-envconfig v0.8.0 h1:AcmdAewSFAc7pQ1Ghz+vhZkilUtxX559QlDuLLiSkdI=
github.com/sethvargo/go-envconfig v0.8.0/go.mod h1:Iz1Gy1Sf3T64TQlJSvee81qDhf7YIlt8GMUX6yyNFs0=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/tdewolff/minify/v2 v2.12.0 h1:ZyvMKeciyR3vzJrK/oHyBcSmpttQ/V+ah7qOqTZclaU=
github.com/tdewolff/minify/v2 v2.12.0/go.mod h1:8mvf+KglD7XurfvvFZDUYvVURy6bA/r0oTvmakXMnyg=
github.com/tdewolff/parse/v2 v2.6.1 h1:RIfy1erADkO90ynJWvty8VIkqqKYRzf2iLp8ObG174I=
github.com/tdewolff/parse/v2 v2.6.1/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
...@@ -48,6 +68,10 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn ...@@ -48,6 +68,10 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0=
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
...@@ -56,16 +80,22 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w ...@@ -56,16 +80,22 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220702020025-31831981b65f h1:xdsejrW/0Wf2diT5CPp3XmKUNbr7Xvw8kYilQ+6qjRY= golang.org/x/sys v0.0.0-20220702020025-31831981b65f h1:xdsejrW/0Wf2diT5CPp3XmKUNbr7Xvw8kYilQ+6qjRY=
golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......
File added