From 24ed2d0f542fa0929e7f210a17b3d53647700cf7 Mon Sep 17 00:00:00 2001 From: Bart van Oort Date: Mon, 26 Jul 2021 23:14:24 +0200 Subject: [PATCH] Implements a script to generate Hugo .md content files for every rule and category that `mllint` has. --- docs/gh-pages/.gitignore | 5 + docs/gh-pages/scripts/clean-docs.sh | 10 ++ docs/gh-pages/scripts/generate-docs.go | 141 +++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 docs/gh-pages/.gitignore create mode 100755 docs/gh-pages/scripts/clean-docs.sh create mode 100644 docs/gh-pages/scripts/generate-docs.go diff --git a/docs/gh-pages/.gitignore b/docs/gh-pages/.gitignore new file mode 100644 index 0000000..51b665a --- /dev/null +++ b/docs/gh-pages/.gitignore @@ -0,0 +1,5 @@ +/content/docs/categories/* +!/content/docs/categories/_index.md + +/content/docs/rules/* +!/content/docs/rules/_index.md diff --git a/docs/gh-pages/scripts/clean-docs.sh b/docs/gh-pages/scripts/clean-docs.sh new file mode 100755 index 0000000..ae2c4b2 --- /dev/null +++ b/docs/gh-pages/scripts/clean-docs.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd $(dirname $0) +cd ../content/docs + +cd categories +find . ! -name '_index.md' -type f -exec rm -f {} + + +cd ../rules +find . ! -name '_index.md' -type f -exec rm -f {} + diff --git a/docs/gh-pages/scripts/generate-docs.go b/docs/gh-pages/scripts/generate-docs.go new file mode 100644 index 0000000..5aeb524 --- /dev/null +++ b/docs/gh-pages/scripts/generate-docs.go @@ -0,0 +1,141 @@ +package main + +import ( + "fmt" + "os" + "path" + "runtime" + + "github.com/bvobart/mllint/api" + "github.com/bvobart/mllint/categories" + "github.com/bvobart/mllint/linters" + "github.com/bvobart/mllint/utils" +) + +// This script will use mllint's source code to build Markdown files that contain documentation for each of mllint's rules and categories. +// These Markdown files will be placed in `../content/docs/categories` and `../content/docs/rules` +func main() { + docspath := findDocsPath() + if !utils.FolderExists(docspath) { + panic(fmt.Errorf("Wtf, folder '%s' does not exist...", docspath)) + } + + ccf := categoryContentFactory{} + ccf.GenerateDocs(docspath) + + rcf := ruleContentFactory{} + rcf.GenerateDocs(docspath) +} + +// Returns the equivalent of '../content/docs' relative to this script. +func findDocsPath() string { + _, scriptPath, _, _ := runtime.Caller(0) //nolint:dogsled + return path.Join(path.Dir(path.Dir(scriptPath)), "content", "docs") +} + +//--------------------------------------------------------------------------------------- + +type categoryContentFactory struct{} + +func (ccf categoryContentFactory) GenerateDocs(docspath string) { + checkErr := func(err error) { + if err != nil { + panic(err) + } + } + + for _, cat := range categories.All { + output, err := ccf.createOutputFile(docspath, cat) + checkErr(err) + defer output.Close() + + _, err = output.WriteString(ccf.buildHeader(cat)) + checkErr(err) + _, err = output.WriteString(ccf.buildContent(cat)) + checkErr(err) + } +} + +func (ccf categoryContentFactory) createOutputFile(docspath string, cat api.Category) (*os.File, error) { + outputPath := path.Join(docspath, "categories", cat.Slug) + ".md" + output, err := os.Create(outputPath) + if err != nil { + return nil, fmt.Errorf("failed to create output file for category %s at %s: %w", cat.Name, outputPath, err) + } + return output, nil +} + +func (ccf categoryContentFactory) buildHeader(cat api.Category) string { + return fmt.Sprintf(`--- +title: "Category — %s" +description: "- `+"`%s`"+`" +weight: 9 +showtoc: false +--- + +`, cat.Name, cat.Slug) +} + +func (ccf categoryContentFactory) buildContent(cat api.Category) string { + return cat.Description +} + +//--------------------------------------------------------------------------------------- + +type ruleContentFactory struct{} + +func (rcf ruleContentFactory) GenerateDocs(docspath string) { + checkErr := func(err error) { + if err != nil { + panic(err) + } + } + + for cat, linter := range linters.ByCategory { + for _, rule := range linter.Rules() { + output, err := rcf.createOutputFile(docspath, rule) + checkErr(err) + defer output.Close() + + _, err = output.WriteString(rcf.buildHeader(rule, cat)) + checkErr(err) + _, err = output.WriteString(rcf.buildContent(rule)) + checkErr(err) + } + } +} + +func (rcf ruleContentFactory) createOutputFile(docspath string, rule *api.Rule) (*os.File, error) { + outputPath := path.Join(docspath, "rules", rule.Slug) + ".md" + + // create dir for the rule if it doesn't exist yet + if outputDir := path.Dir(outputPath); !utils.FolderExists(outputDir) { + err := os.MkdirAll(outputDir, 0755) + if err != nil { + return nil, err + } + } + + output, err := os.Create(outputPath) + if err != nil { + return nil, fmt.Errorf("failed to create output file for rule %s at %s: %w", rule.Name, outputPath, err) + } + return output, nil +} + +func (rcf ruleContentFactory) buildHeader(rule *api.Rule, cat api.Category) string { + return fmt.Sprintf(`--- +title: "Rule — %s — %s" +description: | + - `+"`%s`"+` + - `+"`weight: %.1f`"+` +weight: 9 +showtoc: false +--- + +`, cat.Name, rule.Name, rule.Slug, rule.Weight) +} + +func (rcf ruleContentFactory) buildContent(rule *api.Rule) string { + return rule.Details +}