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
all: package-apex package-vf package-lightning
docset-gen:
vendor:
dep ensure
go build -x -o docset-gen ./SFDashC/
docset-gen: vendor
go build -i -x -o docset-gen ./SFDashC/
.PHONY: run-apex
run-apex: clean-index docset-gen
@ -55,3 +57,10 @@ clean: clean-index clean-package clean-archive
.PHONY: clean-build
clean-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!
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
------------
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
* github.com/mattn/go-sqlite3
To Do
-----
- [ ] 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 dbName = "docSet.dsidx"
// InitDb will initialize a new instance of a sqlite db for indexing
func InitDb(buildDir string) *gorp.DbMap {
dbPath := filepath.Join(buildDir, dbName)
err := os.MkdirAll(filepath.Dir(dbPath), 0755)
@ -32,13 +33,14 @@ func InitDb(buildDir string) *gorp.DbMap {
return dbmap
}
func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) {
if entry.LinkAttr.Href == "" || entryType == nil {
// SaveSearchIndex will index a particular entry into the sqlite3 database
func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
if entry.LinkAttr.Href == "" || !entryType.IsValidType() {
return
}
relLink := entry.GetContentFilepath(toc, false)
name := entry.CleanTitle(*entryType)
name := entry.CleanTitle(entryType)
if entryType.ShowNamespace && len(entryHierarchy) > 0 {
// Show namespace for methods
name = entryHierarchy[len(entryHierarchy)-1] + "." + name
@ -50,6 +52,8 @@ func SaveSearchIndex(dbmap *gorp.DbMap, entry TOCEntry, entryType *SupportedType
Path: relLink,
}
dbmap.Insert(&si)
err := dbmap.Insert(&si)
ExitIfError(err)
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)
// Read the downloaded JSON
defer resp.Body.Close()
defer func() {
ExitIfError(resp.Body.Close())
}()
contents, err := ioutil.ReadAll(resp.Body)
ExitIfError(err)
@ -91,7 +93,9 @@ func saveMainContent(toc *AtlasTOC) {
ofile, err := os.Create(filePath)
ExitIfError(err)
defer ofile.Close()
defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString(
"<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
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) {
filePath := fmt.Sprintf("%s-version.txt", toc.Deliverable)
// Prepend build dir
@ -110,15 +115,20 @@ func saveContentVersion(toc *AtlasTOC) {
ofile, err := os.Create(filePath)
ExitIfError(err)
defer ofile.Close()
defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString(toc.Version.DocVersion)
ExitIfError(err)
}
// downloadCSS will download a CSS file using the CSS base URL
func downloadCSS(fileName string, wg *sync.WaitGroup) {
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) {
if wg != nil {
defer wg.Done()
@ -131,11 +141,15 @@ func downloadFile(url string, fileName string, wg *sync.WaitGroup) {
ofile, err := os.Create(filePath)
ExitIfError(err)
defer ofile.Close()
defer func() {
ExitIfError(ofile.Close())
}()
response, err := http.Get(url)
ExitIfError(err)
defer response.Body.Close()
defer func() {
ExitIfError(response.Body.Close())
}()
_, err = io.Copy(ofile, response.Body)
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 {
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
func processEntryReference(entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) {
func processEntryReference(entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
LogDebug("Processing: %s", entry.Text)
throttle <- 1
wg.Add(1)
go downloadContent(entry, toc, &wg)
if entryType == nil {
LogDebug("No entry type for %s. Cannot index", entry.Text)
} else if entryType.IsContainer || entryType.IsHidden {
if entryType.ShouldSkipIndex() {
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 {
SaveSearchIndex(dbmap, entry, entryType, toc)
}
@ -176,33 +206,23 @@ func processEntryReference(entry TOCEntry, entryType *SupportedType, toc *AtlasT
var entryHierarchy []string
// processChildReferences iterates through all child toc items, cascading types, and indexes them
func processChildReferences(entry TOCEntry, entryType *SupportedType, toc *AtlasTOC) {
if entryType != nil && entryType.PushName {
entryHierarchy = append(entryHierarchy, entry.CleanTitle(*entryType))
func processChildReferences(entry TOCEntry, entryType SupportedType, toc *AtlasTOC) {
if entryType.PushName {
entryHierarchy = append(entryHierarchy, entry.CleanTitle(entryType))
}
for _, child := range entry.Children {
LogDebug("Reading child: %s", child.Text)
var err error
var childType *SupportedType
var childType SupportedType
// Skip anything without an HTML page
if child.LinkAttr.Href != "" {
childType, err = getEntryType(child)
if childType == nil && entryType != nil && (entryType.IsContainer || entryType.CascadeType) {
// No child type, and parent is set to cascade
LogDebug("Parent was container or cascade, using parent type of %s", entryType.TypeName)
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 {
childType, err = getEntryType(child, entryType)
if err == nil {
processEntryReference(child, childType, toc)
} else {
WarnIfError(err)
}
processEntryReference(child, childType, toc)
} else {
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)
if entryType != nil && entryType.PushName {
if entryType.PushName {
entryHierarchy = entryHierarchy[:len(entryHierarchy)-1]
}
}
@ -244,7 +264,9 @@ func downloadContent(entry TOCEntry, toc *AtlasTOC, wg *sync.WaitGroup) {
}
header += "<style>body { padding: 15px; }</style>"
defer ofile.Close()
defer func() {
ExitIfError(ofile.Close())
}()
_, err = ofile.WriteString(
header + content.Content,
)
@ -286,8 +308,8 @@ func main() {
// Download each entry
for _, entry := range toc.TOCEntries {
entryType, err := getEntryType(entry)
if entryType != nil && err == nil {
entryType, err := lookupEntryType(entry)
if err == nil {
processEntryReference(entry, entryType, toc)
}
processChildReferences(entry, entryType, toc)

View File

@ -78,10 +78,6 @@ type SupportedType struct {
TypeName string
// Not sure...
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
NoTrim bool
// Not sure...
@ -90,8 +86,15 @@ type SupportedType struct {
PushName bool
// Should a namspace be prefixed to the database entry
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
// Should cascade type downwards, even if children have their own type
ForceCascadeType bool
}
// Sqlite Struct
@ -103,17 +106,17 @@ type SearchIndex struct {
Path string `db:path`
}
// matchesTitle returns true if the title matches that of the specified type
func (suppType SupportedType) matchesTitle(title string) bool {
match := false
if suppType.TitlePrefix != "" {
match = match || strings.HasPrefix(title, suppType.TitlePrefix)
}
if suppType.TitleSuffix != "" {
match = match || strings.HasSuffix(title, suppType.TitleSuffix)
}
match = match || (suppType.TitlePrefix != "" &&
strings.HasPrefix(title, suppType.TitlePrefix))
match = match || (suppType.TitleSuffix != "" &&
strings.HasSuffix(title, suppType.TitleSuffix))
return match
}
// matchesID returns true if the ID matches that of the specified type
func (suppType SupportedType) matchesID(id string) bool {
if suppType.ID != "" && suppType.ID == id {
return true
@ -124,6 +127,22 @@ func (suppType SupportedType) matchesID(id string) bool {
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
// This is done by checking the suffix of the entry text
func (entry TOCEntry) IsType(t SupportedType) bool {
@ -173,14 +192,15 @@ func (entry TOCEntry) GetContent(toc *AtlasTOC) (content *TOCContent, err error)
toc.Version.DocVersion,
)
// fmt.Println(url)
resp, err := http.Get(url)
if err != nil {
return
}
// Read the downloaded JSON
defer resp.Body.Close()
defer func() {
ExitIfError(resp.Body.Close())
}()
contents, err := ioutil.ReadAll(resp.Body)
if err != nil {
return

View File

@ -19,6 +19,43 @@ var SupportedTypes = []SupportedType{
ID: "apex_intro_get_started",
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
SupportedType{
TypeName: "Method",
@ -48,6 +85,13 @@ var SupportedTypes = []SupportedType{
AppendParents: true,
ShowNamespace: false,
},
SupportedType{
TypeName: "Interface",
TitleSuffix: "Global Interface",
PushName: true,
AppendParents: true,
ShowNamespace: false,
},
SupportedType{
TypeName: "Interface",
TitleSuffix: "Interface",