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

Target

Select target project
  • oss/utilities/documentation-manager
1 result
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.
DocMan is a binary file that must be stored in a directory.
The files can be found [here](http://download.schukai.com/tools/docman/).
For Linux, the execution bit must still be set.
```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
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'
### Awsome Boxes
* [Awesomebox](https://ftp.gwdg.de/pub/ctan/graphics/awesomebox/awesomebox.pdf)
### Circled numbers
[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
The parameter `path` specifies the path.
### Help
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 |
#### Configuration
### 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
docman privacy print --path=example/
```
### Help
### Output of requirements
There is help on the command line for each individual command.
```bash
docman requirements print --path=example/ --column=ID --column=
docman --help
```
The output is then of the type:
| 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
### create PDF
```bash
docman changelog print --path=example/
```
The output is then of the type:
```
### 01.05.2022
- Requirement (R2)
### 24.01.2022
- Requirement (R1)
docman document pdf --config pathto/config.yaml
```
### 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
......@@ -383,3 +222,16 @@ Individual LaTeX commands can be looked up here:
- Version 1.0
- 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() {
}
type DocumentDefinition struct {
SourcePath string `long:"path" short:"p"`
DateFormat string `long:"date-format" short:"d"`
Add DocumentAddDefinition `command:"add" alias:"a"`
Build DocumentBuildDefinition `command:"build" alias:"b"`
PDF DocumentPDFDefinition `command:"pdf"`
SourcePath string `long:"path" short:"p"`
DateFormat string `long:"date-format" short:"d"`
Add DocumentAddDefinition `command:"add" alias:"a"`
HTML DocumentHTMLDefinition `command:"html" alias:"h"`
PDF DocumentPDFDefinition `command:"pdf"`
}
func initDocument(command *flags.Command) {
......
......@@ -20,13 +20,27 @@ Title: New Document
Keywords:
- documentation
References:
- https://www.example.com/
# Abbreviation of the document
Abbreviation:
# First and last name of the authors as a list
Author:
Authors:
- null
Version: 1.0
Created: %%CREATED%%
Last Update: %%CREATED%%
Language: en
# Which level of the document is this?
Level: 1
...
## {{ .Title }}
......
......@@ -5,83 +5,69 @@ import (
"gitlab.schukai.com/oss/utilities/documentation-manager/document"
"gitlab.schukai.com/oss/utilities/documentation-manager/environment"
"gitlab.schukai.com/oss/utilities/documentation-manager/translations"
"os"
"path"
"path/filepath"
"strings"
"time"
)
const documentBuildSymbol = "document-build"
const documentHTMLSymbol = "document-html"
func init() {
h := environment.Handler{
Init: initDocumentBuild,
Execute: runDocumentBuild,
Init: initDocumentHTML,
Execute: runDocumentHTML,
}
environment.Handlers.Executor[documentBuildSymbol] = h
environment.Handlers.Executor[documentHTMLSymbol] = h
}
type DocumentBuildDefinition struct {
Template string `long:"template" short:"t"`
Output string `long:"output" short:"o"`
Format string `long:"format" short:"f" choice:"html" choice:"pdf" default:"html" `
type DocumentHTMLDefinition struct {
SinglePage bool `long:"single-page" short:"s"`
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) {
const text = "Builds the documentation"
func initDocumentHTML(command *flags.Command) {
const text = "Build the documentation as PDF"
command.ShortDescription = translations.T.Sprintf(text)
command.LongDescription = translations.T.Sprintf(text)
for _, opt := range command.Options() {
switch opt.LongName {
case "template":
opt.Description = translations.T.Sprintf("template for the new document")
case "html-template":
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":
opt.Description = translations.T.Sprintf("directory in which the finished documentation is to be written")
case "format":
opt.Description = translations.T.Sprintf("format of the finished documentation")
opt.Description = translations.T.Sprintf("filename for the new document")
case "verbose":
opt.Description = translations.T.Sprintf("verbose output")
case "single-page":
opt.Description = translations.T.Sprintf("single page output")
}
}
}
func buildDocumentation(name string) {
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)
}
func runDocumentHTML(command *flags.Command) {
template := environment.State.GetDocumentTemplate(definition.Document.Build.Template)
if template == "" {
template = newDocumentTemplate
env := document.BuildHtmlEnvironment{
DateFormat: environment.State.GetDocumentDateFormat(definition.Document.DateFormat),
SourcePath: environment.State.GetDocumentPath(definition.Document.SourcePath),
OutputPath: environment.State.GetDocumentHTMLOutputPath(definition.Document.PDF.OutputPath),
}
date := time.Now().Format(environment.State.GetDocumentDateFormat(definition.Document.DateFormat))
template = strings.Replace(template, "%%CREATED%%", date, -1)
env.Templates.HTML = environment.State.GetHTMLHTMLTemplatePath(definition.Document.HTML.HTMLTemplate)
env.Verbose = definition.Document.HTML.Verbose
env.SinglePage = environment.State.GetHTMLSinglePageState(definition.Document.HTML.SinglePage)
err := os.WriteFile(path, []byte(template), 0644)
checkError(err)
document.BuildHTML(env)
}
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)
if environment.State.HasErrorsWarningsOrMessages() {
environment.PrintMessages()
}
}
......@@ -34,12 +34,12 @@ func initDocumentPDF(command *flags.Command) {
for _, opt := range command.Options() {
switch opt.LongName {
case "template":
opt.Description = translations.T.Sprintf("template for the new document")
case "latex-template":
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":
opt.Description = translations.T.Sprintf("filename for the new document")
case "format":
opt.Description = translations.T.Sprintf("format of the finished documentation")
case "verbose":
opt.Description = translations.T.Sprintf("verbose output")
}
......
package document
import (
"fmt"
)
type BuildEnvironment struct {
SourcePath string
DateFormat string
}
func Build(env BuildEnvironment) error {
dateFormat = env.DateFormat
definitions, err := getFiles(env.SourcePath)
if err != nil {
return err
}
fmt.Println(definitions)
return nil
}
//func Build(env BuildEnvironment) error {
// dateFormat = env.DateFormat
//
// definitions, err := getFiles(env.SourcePath)
// if err != nil {
// return err
// }
// fmt.Println(definitions)
// return nil
//}
......@@ -22,4 +22,5 @@ type document struct {
LastUpdate LocaleTime `yaml:"Last Update"`
Language string `yaml:"Language"`
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 (
"strings"
)
var kbdMapping = map[string]string{
var kbdMappingToLatex = map[string]string{
"ctrl": "\\LKeyStrg",
"tux": "\\LKeyTux",
"win": "\\LKeyWin",
......@@ -36,7 +36,7 @@ var kbdMapping = map[string]string{
"pgdown": "\\LKeyPgDown",
}
func convertCircledNumbers(content string) string {
func convertCircledNumbersToLatex(content string) string {
circleMap := map[string]string{
"➊": "\\large\\libertineGlyph{uni2776}\\normalsize",
......@@ -68,7 +68,7 @@ func convertCircledNumbers(content string) string {
return content
}
func replaceKbd(content string) string {
func replaceKbdToLatex(content string) string {
regEx := regexp.MustCompile(`(?P<match><kbd[^>]*>(?P<key>[^<]*)</kbd>)`)
......@@ -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 {
runes := []rune(result["key"])
for _, k := range runes {
......@@ -99,5 +99,5 @@ func replaceKbd(content string) string {
}
return content
}
......@@ -51,11 +51,11 @@ func NewPdfDataset(env BuildPdfEnvironment) (*PdfDataset, error) {
text, s2Map := utils.MaskCodeBlocks(text, mapFiles[key].relSourcePath, 1)
text = convertHeadlines(text, mapFiles[key].level, mapFiles[key].textMeta.meta.Level)
text = convertAwesomeBoxes(text)
text = convertAwesomeBoxesToLatex(text)
text = convertImages(text, mapFiles[key].baseDir)
text = convertCircledNumbers(text)
text = replaceKbd(text)
text = replaceRelativeLinks(text, mapFiles[key], mapFiles)
text = convertCircledNumbersToLatex(text)
text = replaceKbdToLatex(text)
text = replaceRelativeLinksToLatex(text, mapFiles[key], mapFiles)
text = utils.InsertCodeBlocks(text, s2Map)
text = utils.InsertCodeBlocks(text, s1Map)
......@@ -90,7 +90,7 @@ func BuildPDF(env BuildPdfEnvironment) error {
}
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)
......@@ -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
content = "\\hypertarget{" + label + "}{ } \n" + strings.TrimSpace(content) + "\n"
......@@ -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
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)+))`)
......@@ -314,7 +251,7 @@ func convertAwesomeBoxes(content string) string {
}
lines := result["lines"]
lines = convertAwesomeBoxesMarkdown(lines)
lines = convertAwesomeBoxesMarkdownWithPandoc(lines)
c += "\n" + lines + "\n" //+escapeLatexSpecialChars(result["lastline"])) + "\n"
awesomebox := `\begin{` + boxtype + `block}` + c + "\n" + `\end{` + boxtype + `block}`
......@@ -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)))
return output
}
......@@ -374,104 +311,3 @@ func escapeLatexSpecialChars(content string) string {
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
import (
"github.com/kelseyhightower/envconfig"
"context"
"github.com/sethvargo/go-envconfig"
"gopkg.in/yaml.v3"
"os"
"os/user"
......@@ -13,21 +14,36 @@ const configFileName = "config.yaml"
type Configuration struct {
Document struct {
Path string `yaml:"Path" envconfig:"PATH"`
DateFormat string `yaml:"DateFormat" envconfig:"DATE_FORMAT"`
Path string `yaml:"Path" env:"PATH"`
Version string `yaml:"Version" env:"VERSION"`
DateFormat string `yaml:"DateFormat" env:"DATE_FORMAT"`
Add struct {
Template string `yaml:"Template" envconfig:"NEW_TEMPLATE"`
Template string `yaml:"Template" env:"NEW_TEMPLATE"`
}
Build struct {
//Path string `yaml:"Path" envconfig:"BUILD_PATH"`
//Path string `yaml:"Path" env:"BUILD_PATH"`
} `yaml:"Build"`
PDF struct {
Output string `yaml:"Output" envconfig:"PDF_OUTPUT"`
Teplates struct {
Latex string `yaml:"Latex" envconfig:"PDF_LATEX_TEMPLATE"`
Markdown string `yaml:"Markdown" envconfig:"PDF_MARKDOWN_TEMPLATE"`
Output string `yaml:"Output" env:"PDF_OUTPUT"`
Templates struct {
Latex string `yaml:"Latex" env:"PDF_LATEX_TEMPLATE"`
Markdown string `yaml:"Markdown" env:"PDF_MARKDOWN_TEMPLATE"`
} `yaml:"Templates"`
} `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"`
}
......@@ -61,21 +77,37 @@ func InitConfiguration(configPath string) {
usr, err := user.Current()
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()
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{}
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)
for _, path := range []string{
configPath,
current,
current1,
current2,
userConfig,
"/etc/" + State.info.Mnemonic + "/" + configFileName} {
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 {
return arg
}
if e.configuration.Document.PDF.Teplates.Latex != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Teplates.Latex)
if e.configuration.Document.PDF.Templates.Latex != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Templates.Latex)
}
return ""
......@@ -21,8 +21,8 @@ func (e *stateStruct) GetPDFMarkdownTemplatePath(arg string) string {
return arg
}
if e.configuration.Document.PDF.Teplates.Markdown != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Teplates.Markdown)
if e.configuration.Document.PDF.Templates.Markdown != "" {
return e.sanityConfigPath(e.configuration.Document.PDF.Templates.Markdown)
}
return ""
......
......@@ -3,22 +3,29 @@ module gitlab.schukai.com/oss/utilities/documentation-manager
go 1.18
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/jessevdk/go-flags v1.5.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/sethvargo/go-envconfig v0.8.0
golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/go-chi/chi/v5 v5.0.7 // indirect
github.com/go-chi/docgen v1.2.0 // 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
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.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/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
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.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.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
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
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/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/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/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.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/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
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
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-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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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
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/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-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/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/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/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/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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......
File added