mirror of
https://github.com/ViViDboarder/docset-sfdc.git
synced 2024-11-14 17:36:34 +00:00
Make more idomatic
This commit is contained in:
parent
6f8135ce6b
commit
70ac28bb2f
13
Makefile
13
Makefile
@ -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
|
||||
|
10
README.md
10
README.md
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user