-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathmanifest-parser.go
138 lines (125 loc) · 3.29 KB
/
manifest-parser.go
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
package vueglue
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
)
type manifestNode struct {
key string
nodeType reflect.Kind
value reflect.Value
children []*manifestNode
}
type manifestTarget struct {
File string `json:"file"`
Source string `json:"src"`
IsEntry bool `json:"isEntry"`
Imports []string `json:"imports"`
CSS []string `json:"css"`
Nodes []*manifestNode
}
func (n *manifestNode) subKey(key string) *manifestNode {
if len(n.children) == 0 {
return nil
}
for _, leaf := range n.children {
if leaf.key == key {
return leaf
}
}
return nil
}
// @see https://yourbasic.org/golang/json-example/
func (m *manifestTarget) parseWithoutReflection(jsonData []byte) (*VueGlue, error) {
var v interface{}
json.Unmarshal(jsonData, &v)
topNode := manifestNode{
key: "top",
}
m.Nodes = append(m.Nodes, &topNode)
m.siftCollections(&topNode, "", "", v)
// Get entry point
entry := (*manifestNode)(nil)
glue := &VueGlue{}
for _, leaf := range topNode.children {
if leaf.subKey("isEntry") != nil {
entry = leaf
glue.MainModule = leaf.subKey("file").value.String()
break
}
}
if entry == nil {
return nil, ErrNoEntryPoint
}
imports := entry.subKey("imports")
if imports == nil || len(imports.children) == 0 {
// return nil, errors.New("expected code to have js dependencies")
// turns out this will become optional as of Vite 2.9, so:
} else {
for _, child := range imports.children {
// these have a level of indirection for some reason
deref := topNode.subKey(child.value.String())
if deref == nil {
return nil, ErrNoInputFile
}
item := deref.subKey("file")
if item == nil {
return nil, ErrManifestBadlyFormed
}
glue.Imports = append(glue.Imports, item.value.String())
}
}
css := entry.subKey("css")
if css == nil || len(css.children) == 0 {
// not an error, since CSS is optional
return glue, nil
}
for _, child := range css.children {
glue.CSSModule = append(glue.CSSModule, child.value.String())
}
return glue, nil
}
func (m *manifestTarget) siftCollections(leaf *manifestNode, indent, key string, v interface{}) {
data, ok := v.(map[string]interface{})
if ok {
leaf.nodeType = reflect.Map
for k, v := range data {
child := &manifestNode{
key: k,
}
leaf.children = append(leaf.children, child)
m.processInterface(child, indent, k, v)
}
} else if arrayData, ok := v.([]interface{}); ok {
leaf.nodeType = reflect.Slice
for i, v := range arrayData {
child := &manifestNode{}
leaf.children = append(leaf.children, child)
m.processInterface(child, indent, strconv.Itoa(i), v)
}
} else {
m.processInterface(leaf, indent, key, v)
}
}
// call this for recurisve structures.
func (m *manifestTarget) processInterface(leaf *manifestNode, indent, k string, v interface{}) {
// Cover types we know we get in JSON
switch v := v.(type) {
case string:
leaf.nodeType = reflect.String
leaf.value = reflect.ValueOf(v)
case float64:
leaf.nodeType = reflect.Float64
leaf.value = reflect.ValueOf(v)
case bool:
leaf.nodeType = reflect.Bool
leaf.value = reflect.ValueOf(v)
case []interface{}:
m.siftCollections(leaf, indent+" ", k, v)
case map[string]interface{}:
m.siftCollections(leaf, indent+" ", k, v)
default:
fmt.Printf("%s %s ?? %T (unknown)", indent, k, v)
}
}