Make more idomatic

This commit is contained in:
ViViDboarder 2018-01-05 22:05:24 -08:00
parent 6f8135ce6b
commit 70ac28bb2f
6 changed files with 158 additions and 57 deletions

View File

@ -4,9 +4,11 @@ default: all
.PHONY: all .PHONY: all
all: package-apex package-vf package-lightning all: package-apex package-vf package-lightning
docset-gen: vendor:
dep ensure dep ensure
go build -x -o docset-gen ./SFDashC/
docset-gen: vendor
go build -i -x -o docset-gen ./SFDashC/
.PHONY: run-apex .PHONY: run-apex
run-apex: clean-index docset-gen run-apex: clean-index docset-gen
@ -55,3 +57,10 @@ clean: clean-index clean-package clean-archive
.PHONY: clean-build .PHONY: clean-build
clean-build: clean-build:
rm -fr ./build rm -fr ./build
.PHONY: clean-vendor
clean-vendor:
rm -fr ./vendor
.PHONY: clean-all
clean-all: clean clean-build clean-vendor

View File

@ -9,12 +9,14 @@ Everything is wrapped with a Makefile and can be completely built by simply exec
That's it! That's it!
It will generate 3 docsets: Salesforce Apex, Salesforce Visualforce, and Salesforce Combined It will generate 3 docsets: Salesforce Apex, Salesforce Visualforce, and Salesforce Lightning
Dependencies Dependencies
------------ ------------
Currently these are not auto resolved. You must install the following: All dependencies are being managed by [dep](https://github.com/golang/dep). Dep must be installed for the vendor folder to be built.
* github.com/coopernurse/gorp To Do
* github.com/mattn/go-sqlite3 -----
- [ ] Now that new `ForceCascadeType` is available, some of the entries in `./SFDashC/supportedtypes.go` can be simplified

View File

@ -11,6 +11,7 @@ import (
var dbmap *gorp.DbMap var dbmap *gorp.DbMap
var dbName = "docSet.dsidx" var dbName = "docSet.dsidx"
// InitDb will initialize a new instance of a sqlite db for indexing
func InitDb(buildDir string) *gorp.DbMap { func InitDb(buildDir string) *gorp.DbMap {
dbPath := filepath.Join(buildDir, dbName) dbPath := filepath.Join(buildDir, dbName)
err := os.MkdirAll(filepath.Dir(dbPath), 0755) err := os.MkdirAll(filepath.Dir(dbPath), 0755)
@ -32,13 +33,14 @@ func InitDb(buildDir string) *gorp.DbMap {
return dbmap return dbmap
} }
func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) { // SaveSearchIndex will index a particular entry into the sqlite3 database
if entry.LinkAttr.Href == "" || entryType == nil { func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
if entry.LinkAttr.Href == "" || !entryType.IsValidType() {
return return
} }
relLink := entry.GetContentFilepath(toc, false) relLink := entry.GetContentFilepath(toc, false)
name := entry.CleanTitle(*entryType) name := entry.CleanTitle(entryType)
if entryType.ShowNamespace && len(entryHierarchy) > 0 { if entryType.ShowNamespace && len(entryHierarchy) > 0 {
// Show namespace for methods // Show namespace for methods
name = entryHierarchy[len(entryHierarchy)-1] + "." + name name = entryHierarchy[len(entryHierarchy)-1] + "." + name
@ -50,6 +52,8 @@ func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType *SupportedType
Path: relLink, Path: relLink,
} }
dbmap.Insert(&si) err := dbmap.Insert(&si)
ExitIfError(err)
LogDebug("%s is indexed as a %s", entry.Text, entryType.TypeName) LogDebug("%s is indexed as a %s", entry.Text, entryType.TypeName)
} }

View File

@ -46,7 +46,9 @@ func getTOC(locale string, deliverable string) (toc *AtlasTOC, err error) {
ExitIfError(err) ExitIfError(err)
// Read the downloaded JSON // Read the downloaded JSON
defer resp.Body.Close() defer func() {
ExitIfError(resp.Body.Close())
}()
contents, err := ioutil.ReadAll(resp.Body) contents, err := ioutil.ReadAll(resp.Body)
ExitIfError(err) ExitIfError(err)
@ -91,7 +93,9 @@ func saveMainContent(toc *AtlasTOC) {
ofile, err := os.Create(filePath) ofile, err := os.Create(filePath)
ExitIfError(err) ExitIfError(err)
defer ofile.Close() defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString( _, err = ofile.WriteString(
"<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" + "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
content, content,
@ -100,6 +104,7 @@ func saveMainContent(toc *AtlasTOC) {
} }
} }
// saveContentVersion will retrieve the version number from the TOC and save that to a text file
func saveContentVersion(toc *AtlasTOC) { func saveContentVersion(toc *AtlasTOC) {
filePath := fmt.Sprintf("%s-version.txt", toc.Deliverable) filePath := fmt.Sprintf("%s-version.txt", toc.Deliverable)
// Prepend build dir // Prepend build dir
@ -110,15 +115,20 @@ func saveContentVersion(toc *AtlasTOC) {
ofile, err := os.Create(filePath) ofile, err := os.Create(filePath)
ExitIfError(err) ExitIfError(err)
defer ofile.Close() defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString(toc.Version.DocVersion) _, err = ofile.WriteString(toc.Version.DocVersion)
ExitIfError(err) ExitIfError(err)
} }
// downloadCSS will download a CSS file using the CSS base URL
func downloadCSS(fileName string, wg *sync.WaitGroup) { func downloadCSS(fileName string, wg *sync.WaitGroup) {
downloadFile(cssBaseURL+"/"+fileName, fileName, wg) downloadFile(cssBaseURL+"/"+fileName, fileName, wg)
} }
// downloadFile will download n aribtrary file to a given file path
// It will also handle throttling if a WaitGroup is provided
func downloadFile(url string, fileName string, wg *sync.WaitGroup) { func downloadFile(url string, fileName string, wg *sync.WaitGroup) {
if wg != nil { if wg != nil {
defer wg.Done() defer wg.Done()
@ -131,11 +141,15 @@ func downloadFile(url string, fileName string, wg *sync.WaitGroup) {
ofile, err := os.Create(filePath) ofile, err := os.Create(filePath)
ExitIfError(err) ExitIfError(err)
defer ofile.Close() defer func() {
ExitIfError(ofile.Close())
}()
response, err := http.Get(url) response, err := http.Get(url)
ExitIfError(err) ExitIfError(err)
defer response.Body.Close() defer func() {
ExitIfError(response.Body.Close())
}()
_, err = io.Copy(ofile, response.Body) _, err = io.Copy(ofile, response.Body)
ExitIfError(err) ExitIfError(err)
@ -146,27 +160,43 @@ func downloadFile(url string, fileName string, wg *sync.WaitGroup) {
} }
} }
func getEntryType(entry TOCEntry) (*SupportedType, error) { // getEntryType will return an entry type that should be used for a given entry and it's parent's type
func getEntryType(entry TOCEntry, parentType SupportedType) (SupportedType, error) {
if parentType.ForceCascadeType {
return parentType.CreateChildType(), nil
}
childType, err := lookupEntryType(entry)
if err != nil && parentType.CascadeType {
childType = parentType.CreateChildType()
err = nil
}
return childType, err
}
// lookupEntryType returns the matching SupportedType for a given entry or returns an error
func lookupEntryType(entry TOCEntry) (SupportedType, error) {
for _, t := range SupportedTypes { for _, t := range SupportedTypes {
if entry.IsType(t) { if entry.IsType(t) {
return &t, nil return t, nil
} }
} }
return nil, NewTypeNotFoundError(entry) return SupportedType{}, NewTypeNotFoundError(entry)
} }
// processEntryReference downloads html and indexes a toc item // processEntryReference downloads html and indexes a toc item
func processEntryReference(entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) { func processEntryReference(entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
LogDebug("Processing: %s", entry.Text) LogDebug("Processing: %s", entry.Text)
throttle <- 1 throttle <- 1
wg.Add(1) wg.Add(1)
go downloadContent(entry, toc, &wg) go downloadContent(entry, toc, &wg)
if entryType == nil { if entryType.ShouldSkipIndex() {
LogDebug("No entry type for %s. Cannot index", entry.Text)
} else if entryType.IsContainer || entryType.IsHidden {
LogDebug("%s is a container or is hidden. Do not index", entry.Text) LogDebug("%s is a container or is hidden. Do not index", entry.Text)
} else if !entryType.IsValidType() {
LogDebug("No entry type for %s. Cannot index", entry.Text)
} else { } else {
SaveSearchIndex(dbmap, entry, entryType, toc) SaveSearchIndex(dbmap, entry, entryType, toc)
} }
@ -176,33 +206,23 @@ func processEntryReference(entry TOCEntry, entryType *SupportedType, toc *AtlasT
var entryHierarchy []string var entryHierarchy []string
// processChildReferences iterates through all child toc items, cascading types, and indexes them // processChildReferences iterates through all child toc items, cascading types, and indexes them
func processChildReferences(entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) { func processChildReferences(entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
if entryType != nil && entryType.PushName { if entryType.PushName {
entryHierarchy = append(entryHierarchy, entry.CleanTitle(*entryType)) entryHierarchy = append(entryHierarchy, entry.CleanTitle(entryType))
} }
for _, child := range entry.Children { for _, child := range entry.Children {
LogDebug("Reading child: %s", child.Text) LogDebug("Reading child: %s", child.Text)
var err error var err error
var childType *SupportedType var childType SupportedType
// Skip anything without an HTML page // Skip anything without an HTML page
if child.LinkAttr.Href != "" { if child.LinkAttr.Href != "" {
childType, err = getEntryType(child) childType, err = getEntryType(child, entryType)
if childType == nil && entryType != nil && (entryType.IsContainer || entryType.CascadeType) { if err == nil {
// No child type, and parent is set to cascade processEntryReference(child, childType, toc)
LogDebug("Parent was container or cascade, using parent type of %s", entryType.TypeName) } else {
childType = entryType
childType.IsContainer = false
} else if childType != nil && entryType != nil {
// We didn't cascade in full, but some features are still hereditary
if entryType.IsHidden {
childType.IsHidden = true
}
}
if childType == nil && err != nil {
WarnIfError(err) WarnIfError(err)
} }
processEntryReference(child, childType, toc)
} else { } else {
LogDebug("%s has no link. Skipping", child.Text) LogDebug("%s has no link. Skipping", child.Text)
} }
@ -212,7 +232,7 @@ func processChildReferences(entry TOCEntry, entryType *SupportedType, toc *Atlas
} }
LogDebug("Done processing children for %s", entry.Text) LogDebug("Done processing children for %s", entry.Text)
if entryType != nil && entryType.PushName { if entryType.PushName {
entryHierarchy = entryHierarchy[:len(entryHierarchy)-1] entryHierarchy = entryHierarchy[:len(entryHierarchy)-1]
} }
} }
@ -244,7 +264,9 @@ func downloadContent(entry TOCEntry, toc *AtlasTOC, wg *sync.WaitGroup) {
} }
header += "<style>body { padding: 15px; }</style>" header += "<style>body { padding: 15px; }</style>"
defer ofile.Close() defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString( _, err = ofile.WriteString(
header + content.Content, header + content.Content,
) )
@ -286,8 +308,8 @@ func main() {
// Download each entry // Download each entry
for _, entry := range toc.TOCEntries { for _, entry := range toc.TOCEntries {
entryType, err := getEntryType(entry) entryType, err := lookupEntryType(entry)
if entryType != nil && err == nil { if err == nil {
processEntryReference(entry, entryType, toc) processEntryReference(entry, entryType, toc)
} }
processChildReferences(entry, entryType, toc) processChildReferences(entry, entryType, toc)

View File

@ -78,10 +78,6 @@ type SupportedType struct {
TypeName string TypeName string
// Not sure... // Not sure...
AppendParents bool AppendParents bool
// Indicates that this just contains other nodes and we don't want to index this node
IsContainer bool
// Indicates that this and all nodes underneith should be hidden
IsHidden bool
// Skip trimming of suffix from title // Skip trimming of suffix from title
NoTrim bool NoTrim bool
// Not sure... // Not sure...
@ -90,8 +86,15 @@ type SupportedType struct {
PushName bool PushName bool
// Should a namspace be prefixed to the database entry // Should a namspace be prefixed to the database entry
ShowNamespace bool ShowNamespace bool
// Should cascade type downwards // Indicates that this just contains other nodes and we don't want to index this node
// This is not hereditary
IsContainer bool
// Indicates that this and all nodes underneith should be hidden
IsHidden bool
// Should cascade type downwards unless the child has it's own type
CascadeType bool CascadeType bool
// Should cascade type downwards, even if children have their own type
ForceCascadeType bool
} }
// Sqlite Struct // Sqlite Struct
@ -103,17 +106,17 @@ type SearchIndex struct {
Path string `db:path` Path string `db:path`
} }
// matchesTitle returns true if the title matches that of the specified type
func (suppType SupportedType) matchesTitle(title string) bool { func (suppType SupportedType) matchesTitle(title string) bool {
match := false match := false
if suppType.TitlePrefix != "" { match = match || (suppType.TitlePrefix != "" &&
match = match || strings.HasPrefix(title, suppType.TitlePrefix) strings.HasPrefix(title, suppType.TitlePrefix))
} match = match || (suppType.TitleSuffix != "" &&
if suppType.TitleSuffix != "" { strings.HasSuffix(title, suppType.TitleSuffix))
match = match || strings.HasSuffix(title, suppType.TitleSuffix)
}
return match return match
} }
// matchesID returns true if the ID matches that of the specified type
func (suppType SupportedType) matchesID(id string) bool { func (suppType SupportedType) matchesID(id string) bool {
if suppType.ID != "" && suppType.ID == id { if suppType.ID != "" && suppType.ID == id {
return true return true
@ -124,6 +127,22 @@ func (suppType SupportedType) matchesID(id string) bool {
return false return false
} }
// CreateChildType returns a child type inheriting the current type
func (suppType SupportedType) CreateChildType() SupportedType {
// Reset values that do not cascade
suppType.IsContainer = false
return suppType
}
func (suppType SupportedType) ShouldSkipIndex() bool {
return suppType.IsContainer || suppType.IsHidden
}
// IsValidType returns whether or not this is a valid type
func (suppType SupportedType) IsValidType() bool {
return suppType.TypeName != ""
}
// IsType indicates that the TOCEntry is of a given SupportedType // IsType indicates that the TOCEntry is of a given SupportedType
// This is done by checking the suffix of the entry text // This is done by checking the suffix of the entry text
func (entry TOCEntry) IsType(t SupportedType) bool { func (entry TOCEntry) IsType(t SupportedType) bool {
@ -173,14 +192,15 @@ func (entry TOCEntry) GetContent(toc *AtlasTOC) (content *TOCContent, err error)
toc.Version.DocVersion, toc.Version.DocVersion,
) )
// fmt.Println(url)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return return
} }
// Read the downloaded JSON // Read the downloaded JSON
defer resp.Body.Close() defer func() {
ExitIfError(resp.Body.Close())
}()
contents, err := ioutil.ReadAll(resp.Body) contents, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
return return

View File

@ -19,6 +19,43 @@ var SupportedTypes = []SupportedType{
ID: "apex_intro_get_started", ID: "apex_intro_get_started",
CascadeType: true, CascadeType: true,
}, },
SupportedType{
TypeName: "Guide",
ID: "pages_flows_customize_runtime_ui",
},
SupportedType{
TypeName: "Guide",
ID: "pages_quick_start_controller_shell",
},
SupportedType{
TypeName: "Guide",
ID: "pages_email_custom_controller",
},
SupportedType{
TypeName: "Guide",
IDPrefix: "apex_qs_",
CascadeType: true,
},
SupportedType{
TypeName: "Guide",
ID: "apex_process_plugin_using",
},
SupportedType{
TypeName: "Guide",
ID: "apex_platform_cache_builder",
},
SupportedType{
TypeName: "Guide",
ID: "apex_classes_restful_http_testing_httpcalloutmock",
},
SupportedType{
TypeName: "Guide",
ID: "apex_classes_namespaces_and_invoking_methods",
},
SupportedType{
TypeName: "Guide",
ID: "apex_classes_schema_namespace_using",
},
// Apex types // Apex types
SupportedType{ SupportedType{
TypeName: "Method", TypeName: "Method",
@ -48,6 +85,13 @@ var SupportedTypes = []SupportedType{
AppendParents: true, AppendParents: true,
ShowNamespace: false, ShowNamespace: false,
}, },
SupportedType{
TypeName: "Interface",
TitleSuffix: "Global Interface",
PushName: true,
AppendParents: true,
ShowNamespace: false,
},
SupportedType{ SupportedType{
TypeName: "Interface", TypeName: "Interface",
TitleSuffix: "Interface", TitleSuffix: "Interface",