-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnew.go
More file actions
158 lines (128 loc) 路 3.75 KB
/
Copy pathnew.go
File metadata and controls
158 lines (128 loc) 路 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package pub
import (
"errors"
"fmt"
"os"
"path/filepath"
"github.com/goccy/go-yaml"
)
const (
BookConfigFileName = "pub.yml"
BookChaptersConfigFileName = "nav.yml"
BookAssetsDirName = "assets"
BookChaptersDirName = "chapters"
)
func NewBook(inputPath string) (Book, error) {
var book Book
if err := book.SetInputPath(inputPath); err != nil {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
if err := unmarshalFromYAMLFile(filepath.Join(book.InputPath, BookConfigFileName), &book); err != nil {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
assets, err := newAssets(filepath.Join(book.InputPath, BookAssetsDirName))
if err != nil {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
book.Assets = assets
if len(book.Content.Raw) == 0 {
raw, err := os.ReadFile(filepath.Join(book.InputPath, "index.md"))
if err != nil && !errors.Is(err, os.ErrNotExist) {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
book.Content.Raw = raw
}
chapters, err := newChapters(book.InputPath, &book)
if err != nil {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
book.Chapters = chapters
if err := book.EnsureValid(); err != nil {
return book, fmt.Errorf("[BOOK] \"%s\": %w", inputPath, err)
}
return book, nil
}
func newAssets(inputPath string) ([]Asset, error) {
var assets []Asset
items, err := os.ReadDir(inputPath)
if err != nil {
return nil, err
}
for _, item := range items {
if item.IsDir() {
continue
}
// TODO: properly create asset (detecting mime type format, etc.)
asset := Asset{
Objects: []AssetDescriptor{
{
Name: item.Name(),
},
},
}
assets = append(assets, asset)
}
return assets, nil
}
func newChapters(booksDir string, book *Book) ([]Chapter, error) {
var chapters []Chapter
if err := unmarshalFromYAMLFile(filepath.Join(booksDir, BookChaptersConfigFileName), &chapters); err != nil {
return chapters, err
}
var allChapters []*Chapter
for i := range chapters {
chapter := &chapters[i]
if err := decodeChapter(chapter, book, filepath.Join(booksDir, BookChaptersDirName)); err != nil {
return chapters, err
}
allChapters = append(allChapters, chapter)
allChapters = append(allChapters, chapter.Subchapters()...)
}
for i := range allChapters {
chapter := allChapters[i]
if i-1 >= 0 {
chapter.Previous = allChapters[i-1]
}
if i+1 < len(allChapters) {
chapter.Next = allChapters[i+1]
}
}
return chapters, nil
}
func decodeChapter(chapter *Chapter, book *Book, chaptersDir string) error {
if err := chapter.SetBook(book); err != nil {
return fmt.Errorf("[CHAPTER] \"%s\": %w", chapter.InputPath, err)
}
if chapter.InputPath == "" && chapter.ContentFileName != "" {
if err := chapter.SetInputPath(filepath.Join(chaptersDir, chapter.ContentFileName)); err != nil {
return fmt.Errorf("[CHAPTER] \"%s\": %w", chapter.ContentFileName, err)
}
}
if chapter.InputPath != "" {
raw, err := os.ReadFile(chapter.InputPath)
if err != nil {
return fmt.Errorf("[CHAPTER] \"%s\": %w", chapter.InputPath, err)
}
chapter.Content.Raw = raw
}
for i := range chapter.Subchapters() {
subchapter := chapter.Subchapters()[i]
if err := decodeChapter(subchapter, book, chaptersDir); err != nil {
return err
}
}
if err := chapter.EnsureValid(); err != nil {
return fmt.Errorf("[CHAPTER] \"%s\": %w", chapter.InputPath, err)
}
return nil
}
func unmarshalFromYAMLFile(inputPath string, m any) error {
data, err := os.ReadFile(inputPath)
if err != nil {
return fmt.Errorf("parsing \"%s\": %w", filepath.Base(inputPath), err)
}
if err := yaml.Unmarshal(data, m); err != nil {
return fmt.Errorf("parsing \"%s\": %w", filepath.Base(inputPath), err)
}
return nil
}