mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
refactor(examples): pre-parse frontmatter via scripts/examplegen (#9514)
* refactor(examples): pre-parse frontmatter via scripts/examplegen This removes 2 MB from the slim binary. Ref: #9380
This commit is contained in:
committed by
GitHub
parent
6fc1f5276d
commit
a1025f92af
@@ -0,0 +1,144 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/parser/pageparser"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
)
|
||||
|
||||
const (
|
||||
examplesDir = "examples"
|
||||
examplesSrc = "examples.go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
fset := token.NewFileSet()
|
||||
src, err := parser.ParseFile(fset, filepath.Join(examplesDir, examplesSrc), nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var paths []string
|
||||
for _, comment := range src.Comments {
|
||||
for _, line := range comment.List {
|
||||
if s, ok := parseEmbedTag(line.Text); ok && !strings.HasSuffix(s, ".json") {
|
||||
paths = append(paths, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var examples []codersdk.TemplateExample
|
||||
files := os.DirFS(examplesDir)
|
||||
for _, name := range paths {
|
||||
dir, err := fs.Stat(files, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !dir.IsDir() {
|
||||
continue
|
||||
}
|
||||
exampleID := dir.Name()
|
||||
// Each one of these is a example!
|
||||
readme, err := fs.ReadFile(files, path.Join(name, "README.md"))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("example %q does not contain README.md", exampleID)
|
||||
}
|
||||
|
||||
frontMatter, err := pageparser.ParseFrontMatterAndContent(bytes.NewReader(readme))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse example %q front matter: %w", exampleID, err)
|
||||
}
|
||||
|
||||
nameRaw, exists := frontMatter.FrontMatter["name"]
|
||||
if !exists {
|
||||
return xerrors.Errorf("example %q front matter does not contain name", exampleID)
|
||||
}
|
||||
|
||||
name, valid := nameRaw.(string)
|
||||
if !valid {
|
||||
return xerrors.Errorf("example %q name isn't a string", exampleID)
|
||||
}
|
||||
|
||||
descriptionRaw, exists := frontMatter.FrontMatter["description"]
|
||||
if !exists {
|
||||
return xerrors.Errorf("example %q front matter does not contain name", exampleID)
|
||||
}
|
||||
|
||||
description, valid := descriptionRaw.(string)
|
||||
if !valid {
|
||||
return xerrors.Errorf("example %q description isn't a string", exampleID)
|
||||
}
|
||||
|
||||
tags := []string{}
|
||||
tagsRaw, exists := frontMatter.FrontMatter["tags"]
|
||||
if exists {
|
||||
tagsI, valid := tagsRaw.([]interface{})
|
||||
if !valid {
|
||||
return xerrors.Errorf("example %q tags isn't a slice: type %T", exampleID, tagsRaw)
|
||||
}
|
||||
for _, tagI := range tagsI {
|
||||
tag, valid := tagI.(string)
|
||||
if !valid {
|
||||
return xerrors.Errorf("example %q tag isn't a string: type %T", exampleID, tagI)
|
||||
}
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
}
|
||||
|
||||
var icon string
|
||||
iconRaw, exists := frontMatter.FrontMatter["icon"]
|
||||
if exists {
|
||||
icon, valid = iconRaw.(string)
|
||||
if !valid {
|
||||
return xerrors.Errorf("example %q icon isn't a string", exampleID)
|
||||
}
|
||||
}
|
||||
|
||||
examples = append(examples, codersdk.TemplateExample{
|
||||
ID: exampleID,
|
||||
Name: name,
|
||||
Description: description,
|
||||
Icon: icon,
|
||||
Tags: tags,
|
||||
Markdown: string(frontMatter.Content),
|
||||
|
||||
// URL is set by examples/examples.go.
|
||||
})
|
||||
}
|
||||
|
||||
w := os.Stdout
|
||||
|
||||
_, err = fmt.Fprint(w, "// Code generated by examplegen. DO NOT EDIT.\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
return enc.Encode(examples)
|
||||
}
|
||||
|
||||
func parseEmbedTag(s string) (string, bool) {
|
||||
if !strings.HasPrefix(s, "//go:embed") {
|
||||
return "", false
|
||||
}
|
||||
return strings.TrimSpace(strings.TrimPrefix(s, "//go:embed")), true
|
||||
}
|
||||
Reference in New Issue
Block a user