From 1261320c32bdafc949d7f88a3b8c6aa1555c7a02 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Wed, 19 Jun 2024 20:14:29 +0200 Subject: [PATCH 01/11] save --- misc/docs-linter/errors.go | 9 +++ misc/docs-linter/jsx.go | 50 +++++++++++++ misc/docs-linter/links.go | 111 +++++++++++++++++++++++++++++ misc/docs-linter/main.go | 139 ++++++------------------------------- 4 files changed, 190 insertions(+), 119 deletions(-) create mode 100644 misc/docs-linter/errors.go create mode 100644 misc/docs-linter/jsx.go create mode 100644 misc/docs-linter/links.go diff --git a/misc/docs-linter/errors.go b/misc/docs-linter/errors.go new file mode 100644 index 00000000000..d6d6ac098e8 --- /dev/null +++ b/misc/docs-linter/errors.go @@ -0,0 +1,9 @@ +package main + +import "errors" + +var ( + errEmptyPath = errors.New("you need to pass in a path to scan") + err404Link = errors.New("link returned a 404") + errFound404Links = errors.New("found links resulting in a 404 response status") +) diff --git a/misc/docs-linter/jsx.go b/misc/docs-linter/jsx.go new file mode 100644 index 00000000000..bbcfc6ffc14 --- /dev/null +++ b/misc/docs-linter/jsx.go @@ -0,0 +1,50 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "os" +) + +func lintJSX(filesToAnalyze []string, ctx context.Context) error { + file, err := os.Open(filesToAnalyze) + if err != nil { + return err + } + + cleanup := func() error { + if closeErr := file.Close(); closeErr != nil { + return fmt.Errorf("unable to gracefully close file, %w", closeErr) + } + return nil + } + + return cleanup() +} + +func findJSXTags(filePath string) (map[string]string, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, err + } + + cleanup := func() error { + if closeErr := file.Close(); closeErr != nil { + return fmt.Errorf("unable to gracefully close file, %w", closeErr) + } + return nil + } + + scanner := bufio.NewScanner(file) + jsxTags := make(map[string]string) + + // Scan file line by line + for scanner.Scan() { + line := scanner.Text() + + jsxTags[url] = filePath + } + + return jsxTags, cleanup() +} diff --git a/misc/docs-linter/links.go b/misc/docs-linter/links.go new file mode 100644 index 00000000000..8ab96eba50f --- /dev/null +++ b/misc/docs-linter/links.go @@ -0,0 +1,111 @@ +package main + +import ( + "bufio" + "bytes" + "context" + "fmt" + "golang.org/x/sync/errgroup" + "io" + "mvdan.cc/xurls/v2" + "net/http" + "strings" + "sync" +) + +func lintLinks(map[string]string, ctx context.Context) error { + + // Filter links by prefix & ignore localhost + var validUrls []string + for url := range urlFileMap { + // Look for http & https only + if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { + // Ignore localhost + if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { + validUrls = append(validUrls, url) + } + } + } + + // Setup parallel checking for links + g, _ := errgroup.WithContext(ctx) + + var ( + lock sync.Mutex + notFoundUrls []string + ) + + for _, url := range validUrls { + url := url + g.Go(func() error { + if err := checkUrl(url); err != nil { + lock.Lock() + notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, urlFileMap[url])) + lock.Unlock() + } + + return nil + }) + } + + if err := g.Wait(); err != nil { + return err + } + + // Print out the URLs that returned a 404 along with the file names + if len(notFoundUrls) > 0 { + for _, result := range notFoundUrls { + fmt.Println(result) + } + + return errFound404Links + } + + fmt.Println("No broken links were found.") + + return nil +} + +// extractUrls extracts URLs from a file and maps them to the file +func extractUrls(fileContent []byte) []string { + scanner := bufio.NewScanner(bytes.NewReader(fileContent)) + urls := make([]string, 0) + + // Scan file line by line + for scanner.Scan() { + line := scanner.Text() + + // Extract links + rxStrict := xurls.Strict() + url := rxStrict.FindString(line) + + // Check for empty links and skip them + if url == " " || len(url) == 0 { + continue + } + + urls = append(urls, url) + } + + return urls +} + +// checkUrl checks if a URL is a 404 +func checkUrl(url string) error { + // Attempt to retrieve the HTTP header + resp, err := http.Get(url) + if err != nil || resp.StatusCode == http.StatusNotFound { + return err404Link + } + + // Ensure the response body is closed properly + cleanup := func(Body io.ReadCloser) error { + if err := Body.Close(); err != nil { + return fmt.Errorf("could not close response properly: %w", err) + } + + return nil + } + + return cleanup(resp.Body) +} diff --git a/misc/docs-linter/main.go b/misc/docs-linter/main.go index 029b2bf387a..b2eb33c29e7 100644 --- a/misc/docs-linter/main.go +++ b/misc/docs-linter/main.go @@ -1,26 +1,13 @@ package main import ( - "bufio" "context" - "errors" "flag" "fmt" "github.com/gnolang/gno/tm2/pkg/commands" - "golang.org/x/sync/errgroup" - "io" - "mvdan.cc/xurls/v2" - "net/http" "os" "path/filepath" "strings" - "sync" -) - -var ( - errEmptyPath = errors.New("you need to pass in a path to scan") - err404Link = errors.New("link returned a 404") - errFound404Links = errors.New("found links resulting in a 404 response status") ) type cfg struct { @@ -34,7 +21,8 @@ func main() { commands.Metadata{ Name: "docs-linter", ShortUsage: "docs-linter [flags]", - ShortHelp: "Finds broken 404 links in the .md files in the given folder & subfolders", + ShortHelp: `Lints the .md files in the given folder & subfolders. +Checks for 404 links, as well as improperly escaped JSX tags.`, }, cfg, func(ctx context.Context, args []string) error { @@ -58,71 +46,40 @@ func execLint(cfg *cfg, ctx context.Context) error { return errEmptyPath } - fmt.Println("Linting docs/") + fmt.Println("Linting...") + // Find docs files to lint mdFiles, err := findFilePaths(cfg.docsPath) if err != nil { return fmt.Errorf("error finding .md files: %w", err) } - urlFileMap := make(map[string]string) + // Extract URLs from docs files + fileUrlMap := make(map[string][]string) + fileJSXMap := make(map[string][]string) + for _, filePath := range mdFiles { - // Extract URLs from each file - urls, err := extractUrls(filePath) + fileContents, err := os.ReadFile(filePath) if err != nil { - fmt.Printf("Error extracting URLs from file: %s, %v", filePath, err) - continue + return err } - // For each url, save what file it was found in - for url, file := range urls { - urlFileMap[url] = file - } - } - - // Filter links by prefix & ignore localhost - var validUrls []string - for url := range urlFileMap { - // Look for http & https only - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - // Ignore localhost - if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { - validUrls = append(validUrls, url) - } - } - } - - // Setup parallel checking for links - g, _ := errgroup.WithContext(ctx) - - var ( - lock sync.Mutex - notFoundUrls []string - ) - for _, url := range validUrls { - url := url - g.Go(func() error { - if err := checkUrl(url); err != nil { - lock.Lock() - notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, urlFileMap[url])) - lock.Unlock() - } + // pass it to jsx extractor + // save jsx map - return nil - }) + // Extract and save URLs from each file + urls := extractUrls(fileContents) + fileUrlMap[filePath] = urls } - if err := g.Wait(); err != nil { + // lint JSX tags + if err = lintJSX(fileJSXMap, ctx); err != nil { return err } - // Print out the URLs that returned a 404 along with the file names - if len(notFoundUrls) > 0 { - for _, result := range notFoundUrls { - fmt.Println(result) - } - - return errFound404Links + // lint links + if err = lintLinks(fileUrlMap, ctx); err != nil { + return err } return nil @@ -160,59 +117,3 @@ func findFilePaths(startPath string) ([]string, error) { return filePaths, nil } - -// extractUrls extracts URLs from a file and maps them to the file -func extractUrls(filePath string) (map[string]string, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, err - } - - cleanup := func() error { - if closeErr := file.Close(); closeErr != nil { - return fmt.Errorf("unable to gracefully close file, %w", closeErr) - } - return nil - } - - scanner := bufio.NewScanner(file) - urls := make(map[string]string) - - // Scan file line by line - for scanner.Scan() { - line := scanner.Text() - - // Extract links - rxStrict := xurls.Strict() - url := rxStrict.FindString(line) - - // Check for empty links and skip them - if url == " " || len(url) == 0 { - continue - } - - urls[url] = filePath - } - - return urls, cleanup() -} - -// checkUrl checks if a URL is a 404 -func checkUrl(url string) error { - // Attempt to retrieve the HTTP header - resp, err := http.Get(url) - if err != nil || resp.StatusCode == http.StatusNotFound { - return err404Link - } - - // Ensure the response body is closed properly - cleanup := func(Body io.ReadCloser) error { - if err := Body.Close(); err != nil { - return fmt.Errorf("could not close response properly: %w", err) - } - - return nil - } - - return cleanup(resp.Body) -} From 75b4cd7e58abd0f65af2481d86701a8aeb2cfdbb Mon Sep 17 00:00:00 2001 From: leohhhn Date: Wed, 19 Jun 2024 20:57:24 +0200 Subject: [PATCH 02/11] expand linter --- misc/docs-linter/jsx.go | 30 +++++++++++------------ misc/docs-linter/links.go | 50 ++++++++++++++++++++++++--------------- misc/docs-linter/main.go | 11 +++++---- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/misc/docs-linter/jsx.go b/misc/docs-linter/jsx.go index bbcfc6ffc14..369eb37742c 100644 --- a/misc/docs-linter/jsx.go +++ b/misc/docs-linter/jsx.go @@ -8,19 +8,20 @@ import ( ) func lintJSX(filesToAnalyze []string, ctx context.Context) error { - file, err := os.Open(filesToAnalyze) - if err != nil { - return err - } - - cleanup := func() error { - if closeErr := file.Close(); closeErr != nil { - return fmt.Errorf("unable to gracefully close file, %w", closeErr) - } - return nil - } - - return cleanup() + //file, err := os.Open(filesToAnalyze) + //if err != nil { + // return err + //} + // + //cleanup := func() error { + // if closeErr := file.Close(); closeErr != nil { + // return fmt.Errorf("unable to gracefully close file, %w", closeErr) + // } + // return nil + //} + // + //return cleanup() + return nil } func findJSXTags(filePath string) (map[string]string, error) { @@ -41,9 +42,6 @@ func findJSXTags(filePath string) (map[string]string, error) { // Scan file line by line for scanner.Scan() { - line := scanner.Text() - - jsxTags[url] = filePath } return jsxTags, cleanup() diff --git a/misc/docs-linter/links.go b/misc/docs-linter/links.go index 8ab96eba50f..d44fef68bb1 100644 --- a/misc/docs-linter/links.go +++ b/misc/docs-linter/links.go @@ -13,16 +13,19 @@ import ( "sync" ) -func lintLinks(map[string]string, ctx context.Context) error { - +func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { // Filter links by prefix & ignore localhost - var validUrls []string - for url := range urlFileMap { - // Look for http & https only - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - // Ignore localhost - if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { - validUrls = append(validUrls, url) + validUrls := make(map[string][]string) + + for file, urls := range fileUrlMap { + file := file + for _, url := range urls { + // Look for http & https only + if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { + // Ignore localhost + if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { + validUrls[file] = append(validUrls[file], url) + } } } } @@ -35,17 +38,26 @@ func lintLinks(map[string]string, ctx context.Context) error { notFoundUrls []string ) - for _, url := range validUrls { - url := url - g.Go(func() error { - if err := checkUrl(url); err != nil { - lock.Lock() - notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, urlFileMap[url])) - lock.Unlock() - } + for filePath, urls := range validUrls { + filePath := filePath - return nil - }) + if len(urls) != 0 { + println("extracted for: " + filePath) + fmt.Println(urls) + } + + for _, url := range urls { + url := url + g.Go(func() error { + if err := checkUrl(url); err != nil { + lock.Lock() + notFoundUrls = append(notFoundUrls, fmt.Sprintf(">>> %s (found in file: %s)", url, filePath)) + lock.Unlock() + } + + return nil + }) + } } if err := g.Wait(); err != nil { diff --git a/misc/docs-linter/main.go b/misc/docs-linter/main.go index b2eb33c29e7..bcc52fd2dc1 100644 --- a/misc/docs-linter/main.go +++ b/misc/docs-linter/main.go @@ -56,7 +56,7 @@ func execLint(cfg *cfg, ctx context.Context) error { // Extract URLs from docs files fileUrlMap := make(map[string][]string) - fileJSXMap := make(map[string][]string) + //fileJSXMap := make(map[string][]string) for _, filePath := range mdFiles { fileContents, err := os.ReadFile(filePath) @@ -69,13 +69,14 @@ func execLint(cfg *cfg, ctx context.Context) error { // Extract and save URLs from each file urls := extractUrls(fileContents) + fileUrlMap[filePath] = urls } - // lint JSX tags - if err = lintJSX(fileJSXMap, ctx); err != nil { - return err - } + //// lint JSX tags + //if err = lintJSX(fileJSXMap, ctx); err != nil { + // return err + //} // lint links if err = lintLinks(fileUrlMap, ctx); err != nil { From df52d23ff43de13e06cc6edbf5f98eb9a285840c Mon Sep 17 00:00:00 2001 From: leohhhn Date: Wed, 19 Jun 2024 21:01:16 +0200 Subject: [PATCH 03/11] rm println & update docs --- docs/reference/network-config.md | 2 +- docs/reference/tm2-js-client/Provider/json-rpc-provider.md | 2 +- misc/docs-linter/links.go | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/reference/network-config.md b/docs/reference/network-config.md index 0da179e8f17..7902ec5e7f6 100644 --- a/docs/reference/network-config.md +++ b/docs/reference/network-config.md @@ -9,7 +9,7 @@ id: network-config | Portal Loop | https://rpc.gno.land:443 | `portal-loop` | | Testnet 4 | upcoming | upcoming | | Testnet 3 | https://rpc.test3.gno.land:443 | `test3` | -| Staging | http://rpc.staging.gno.land:26657 | `staging` | +| Staging | http://rpc.staging.gno.land:36657 | `staging` | ### WebSocket endpoints All networks follow the same pattern for websocket connections: diff --git a/docs/reference/tm2-js-client/Provider/json-rpc-provider.md b/docs/reference/tm2-js-client/Provider/json-rpc-provider.md index 50d816e89f9..b7700e1d97c 100644 --- a/docs/reference/tm2-js-client/Provider/json-rpc-provider.md +++ b/docs/reference/tm2-js-client/Provider/json-rpc-provider.md @@ -17,6 +17,6 @@ Creates a new instance of the JSON-RPC Provider #### Usage ```ts -new JSONRPCProvider('http://staging.gno.land:26657'); +new JSONRPCProvider('http://staging.gno.land:36657'); // provider is created ``` diff --git a/misc/docs-linter/links.go b/misc/docs-linter/links.go index d44fef68bb1..10d4edea2cf 100644 --- a/misc/docs-linter/links.go +++ b/misc/docs-linter/links.go @@ -40,12 +40,6 @@ func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { for filePath, urls := range validUrls { filePath := filePath - - if len(urls) != 0 { - println("extracted for: " + filePath) - fmt.Println(urls) - } - for _, url := range urls { url := url g.Go(func() error { From 5330649769fbe819ed39f28f84fbf2ecfa63ddbe Mon Sep 17 00:00:00 2001 From: leohhhn Date: Wed, 19 Jun 2024 21:01:49 +0200 Subject: [PATCH 04/11] add comment --- misc/docs-linter/main_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/docs-linter/main_test.go b/misc/docs-linter/main_test.go index ceb87fefeda..fb7ae089455 100644 --- a/misc/docs-linter/main_test.go +++ b/misc/docs-linter/main_test.go @@ -26,6 +26,7 @@ func TestEmptyPathError(t *testing.T) { } func TestExtractLinks(t *testing.T) { + // todo rewrite t.Parallel() // Generate temporary source dir From 114e96d5de6312e322651fabd7a4bff9948d2eb9 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Thu, 20 Jun 2024 15:13:36 +0200 Subject: [PATCH 05/11] sav --- docs/concepts/proof-of-contribution.md | 2 + docs/overview.md | 2 +- docs/reference/gnoclient/client.md | 40 ++++++++++---------- misc/docs-linter/jsx.go | 52 ++++++++------------------ misc/docs-linter/main.go | 26 ++++++++----- 5 files changed, 56 insertions(+), 66 deletions(-) diff --git a/docs/concepts/proof-of-contribution.md b/docs/concepts/proof-of-contribution.md index 5446fa83a69..c855b3db8ed 100644 --- a/docs/concepts/proof-of-contribution.md +++ b/docs/concepts/proof-of-contribution.md @@ -24,6 +24,7 @@ Presentation: https://github.com/gnolang/workshops/tree/main/presentations/2023- ## High-level schema +``` ____ ____ ____ __ _ __ __ _ / __ \_________ ____ / __/ ____ / __/ _________ ____ / /______(_) /_ __ __/ /_(_)___ ____ _____ / /_/ / ___/ __ \/ __ \/ /_ / __ \/ /_ / ___/ __ \/ __ \/ __/ ___/ / __ \/ / / / __/ / __ \/ __ \/ ___/ @@ -55,6 +56,7 @@ Presentation: https://github.com/gnolang/workshops/tree/main/presentations/2023- ^ | | | +---------------user TXs can publish and call contracts--------------------+ +``` ## Components diff --git a/docs/overview.md b/docs/overview.md index 0ded72e06e2..a4e425a1d2f 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -14,7 +14,7 @@ version of the Go programming language called Gno. ### Key Features and Technology -1. **Interpreted Gno**: Gno.land utilizes the Gno programming language, which is based on Go. It is executed +1**Interpreted Gno**: Gno.land utilizes the Gno programming language, which is based on Go. It is executed through a specialized virtual machine called the GnoVM, purpose-built for blockchain development with built-in determinism and a modified standard library. While Gno shares similarities with Go in terms of syntax, it currently lacks go routine support. However, this feature is diff --git a/docs/reference/gnoclient/client.md b/docs/reference/gnoclient/client.md index 0fbef3f5f93..7606e83d1e0 100644 --- a/docs/reference/gnoclient/client.md +++ b/docs/reference/gnoclient/client.md @@ -4,7 +4,7 @@ id: client # Client -## type [Client]() +## type [Client](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client.go#L8-L11) `Client` provides an interface for interacting with the blockchain. It is the main struct of the `gnoclient` package, exposing all APIs used to communicate with a @@ -17,7 +17,7 @@ type Client struct { } ``` -### func \(\*Client\) [AddPackage]() +### func \(\*Client\) [AddPackage](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L236) ```go func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.ResultBroadcastTxCommit, error) @@ -25,7 +25,7 @@ func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.Resul `AddPackage` executes one or more [AddPackage](#type-msgaddpackage) calls on the blockchain. -### func \(\*Client\) [Block]() +### func \(\*Client\) [Block](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L131) ```go func (c *Client) Block(height int64) (*ctypes.ResultBlock, error) @@ -33,7 +33,7 @@ func (c *Client) Block(height int64) (*ctypes.ResultBlock, error) `Block` gets the latest block at height, if any. Height must be larger than 0. -### func \(\*Client\) [BlockResult]() +### func \(\*Client\) [BlockResult](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L150) ```go func (c *Client) BlockResult(height int64) (*ctypes.ResultBlockResults, error) @@ -41,7 +41,7 @@ func (c *Client) BlockResult(height int64) (*ctypes.ResultBlockResults, error) `BlockResult` gets the block results at height, if any. Height must be larger than 0. -### func \(\*Client\) [LatestBlockHeight]() +### func \(\*Client\) [LatestBlockHeight](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L168) ```go func (c *Client) LatestBlockHeight() (int64, error) @@ -49,7 +49,7 @@ func (c *Client) LatestBlockHeight() (int64, error) `LatestBlockHeight` gets the latest block height on the chain. -### func \(\*Client\) [Call]() +### func \(\*Client\) [Call](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L62) ```go func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTxCommit, error) @@ -57,7 +57,7 @@ func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTx `Call` executes a one or more [MsgCall](#type-msgcall) calls on the blockchain. -### func \(\*Client\) [Send]() +### func \(\*Client\) [Send](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L182) ```go func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTxCommit, error) @@ -65,7 +65,7 @@ func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTx `Send` executes one or more [MsgSend](#type-msgsend) calls on the blockchain. -### func \(\*Client\) [Run]() +### func \(\*Client\) [Run](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L118) ```go func (c *Client) Run(cfg BaseTxCfg, msgs ...MsgRun) (*ctypes.ResultBroadcastTxCommit, error) @@ -73,7 +73,7 @@ func (c *Client) Run(cfg BaseTxCfg, msgs ...MsgRun) (*ctypes.ResultBroadcastTxCo `Run` executes a one or more MsgRun calls on the blockchain. -### func \(\*Client\) [QEval]() +### func \(\*Client\) [QEval](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L108) ```go func (c *Client) QEval(pkgPath string, expression string) (string, *ctypes.ResultABCIQuery, error) @@ -83,7 +83,7 @@ func (c *Client) QEval(pkgPath string, expression string) (string, *ctypes.Resul The `pkgPath` should include the prefix like `gno.land/`. The expression is usually a function call like `Render("")`. -### func \(*Client\) [Query]() +### func \(*Client\) [Query](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L22) ```go func (c *Client) Query(cfg QueryCfg) (*ctypes.ResultABCIQuery, error) @@ -91,7 +91,7 @@ func (c *Client) Query(cfg QueryCfg) (*ctypes.ResultABCIQuery, error) `Query` performs a generic query on the blockchain. -### func \(*Client\) [QueryAccount]() +### func \(*Client\) [QueryAccount](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L39) ```go func (c *Client) QueryAccount(addr crypto.Address) (*std.BaseAccount, *ctypes.ResultABCIQuery, error) @@ -99,7 +99,7 @@ func (c *Client) QueryAccount(addr crypto.Address) (*std.BaseAccount, *ctypes.Re `QueryAccount` retrieves account information for a given address. -### func \(*Client\) [QueryAppVersion]() +### func \(*Client\) [QueryAppVersion](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L65) ```go func (c *Client) QueryAppVersion() (string, *ctypes.ResultABCIQuery, error) @@ -107,7 +107,7 @@ func (c *Client) QueryAppVersion() (string, *ctypes.ResultABCIQuery, error) `QueryAppVersion` retrieves information about the Gno.land app version. -### func \(*Client\) [Render]() +### func \(*Client\) [Render](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L85) ```go func (c *Client) Render(pkgPath string, args string) (string, *ctypes.ResultABCIQuery, error) @@ -115,10 +115,10 @@ func (c *Client) Render(pkgPath string, args string) (string, *ctypes.ResultABCI `Render` calls the Render function for pkgPath with optional args. The `pkgPath` should include the prefix like `gno.land/`. This is similar to using a browser -URL `/:` where `` doesn't have the prefix like +URL `/:` doesn't have the prefix like `gno.land/`. -## type [BaseTxCfg]() +## type [BaseTxCfg](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L27-L33) `BaseTxCfg` defines the base transaction configuration, shared by all message types. @@ -133,7 +133,7 @@ type BaseTxCfg struct { } ``` -## type [MsgAddPackage]() +## type [MsgAddPackage](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L59-L59) `MsgAddPackage` \- syntax sugar for `vm.MsgAddPackage`. @@ -144,7 +144,7 @@ type MsgAddPackage struct { } ``` -## type [MsgCall]() +## type [MsgCall](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L36-L41) `MsgCall` \- syntax sugar for `vm.MsgCall`. @@ -157,7 +157,7 @@ type MsgCall struct { } ``` -## type [MsgRun]() +## type [MsgRun](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L50-L53) `MsgRun` \- syntax sugar for `vm.MsgRun`. @@ -168,7 +168,7 @@ type MsgRun struct { } ``` -## type [MsgSend]() +## type [MsgSend](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L44-L47) `MsgSend` \- syntax sugar for `bank.MsgSend`. @@ -179,7 +179,7 @@ type MsgSend struct { } ``` -## type [QueryCfg]() +## type [QueryCfg](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L15-L19) `QueryCfg` contains configuration options for performing ABCI queries. diff --git a/misc/docs-linter/jsx.go b/misc/docs-linter/jsx.go index 369eb37742c..60ee2f6619b 100644 --- a/misc/docs-linter/jsx.go +++ b/misc/docs-linter/jsx.go @@ -1,48 +1,28 @@ package main import ( - "bufio" "context" - "fmt" - "os" + "regexp" ) -func lintJSX(filesToAnalyze []string, ctx context.Context) error { - //file, err := os.Open(filesToAnalyze) - //if err != nil { - // return err - //} - // - //cleanup := func() error { - // if closeErr := file.Close(); closeErr != nil { - // return fmt.Errorf("unable to gracefully close file, %w", closeErr) - // } - // return nil - //} - // - //return cleanup() - return nil -} +func extractJSX(fileContent []byte) []string { + text := string(fileContent) -func findJSXTags(filePath string) (map[string]string, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, err - } + // Remove code blocks + reCodeBlocks := regexp.MustCompile("(?s)```.*?```") + contentNoCodeBlocks := reCodeBlocks.ReplaceAllString(text, "") - cleanup := func() error { - if closeErr := file.Close(); closeErr != nil { - return fmt.Errorf("unable to gracefully close file, %w", closeErr) - } - return nil - } + // Remove inline code + reInlineCode := regexp.MustCompile("`[^`]*`") + contentNoInlineCode := reInlineCode.ReplaceAllString(contentNoCodeBlocks, "") - scanner := bufio.NewScanner(file) - jsxTags := make(map[string]string) + // Extract JSX/HTML elements + reJSXHTML := regexp.MustCompile("(?s)<[^>]+>") - // Scan file line by line - for scanner.Scan() { - } + return reJSXHTML.FindAllString(contentNoInlineCode, -1) +} - return jsxTags, cleanup() +func lintJSX(fileUrlMap map[string][]string, ctx context.Context) error { + + return nil } diff --git a/misc/docs-linter/main.go b/misc/docs-linter/main.go index bcc52fd2dc1..6ea89e921e7 100644 --- a/misc/docs-linter/main.go +++ b/misc/docs-linter/main.go @@ -54,11 +54,13 @@ func execLint(cfg *cfg, ctx context.Context) error { return fmt.Errorf("error finding .md files: %w", err) } - // Extract URLs from docs files - fileUrlMap := make(map[string][]string) - //fileJSXMap := make(map[string][]string) + // Make storage maps for tokens to analyze + //fileUrlMap := make(map[string][]string) + fileJSXMap := make(map[string][]string) + // Extract tokens from files for _, filePath := range mdFiles { + // Read file content once and pass it to linters fileContents, err := os.ReadFile(filePath) if err != nil { return err @@ -66,22 +68,28 @@ func execLint(cfg *cfg, ctx context.Context) error { // pass it to jsx extractor // save jsx map + fileJSXMap[filePath] = extractJSX(fileContents) - // Extract and save URLs from each file - urls := extractUrls(fileContents) + // Execute URL extractor + //fileUrlMap[filePath] = extractUrls(fileContents) + + if len(fileJSXMap[filePath]) != 0 { + fmt.Println(filePath, fileJSXMap[filePath]) + } - fileUrlMap[filePath] = urls } + // Run linters + //// lint JSX tags //if err = lintJSX(fileJSXMap, ctx); err != nil { // return err //} // lint links - if err = lintLinks(fileUrlMap, ctx); err != nil { - return err - } + //if err = lintLinks(fileUrlMap, ctx); err != nil { + // return err + //} return nil } From 881c3e7ee2d4db0952578e426b3ad1b23db88a90 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Thu, 20 Jun 2024 19:35:10 +0200 Subject: [PATCH 06/11] fix docs, fix linter --- docs/gno-tooling/cli/gnodev.md | 38 ++-- docs/overview.md | 2 +- docs/reference/gno-js-client/gno-provider.md | 2 +- docs/reference/gno-js-client/gno-wallet.md | 2 +- docs/reference/gnoclient/client.md | 192 ------------------- docs/reference/gnoclient/gnoclient.md | 11 +- docs/reference/gnoclient/signer.md | 86 --------- misc/docs-linter/errors.go | 8 +- misc/docs-linter/jsx.go | 32 +++- misc/docs-linter/links.go | 68 +++---- misc/docs-linter/main.go | 43 +++-- 11 files changed, 119 insertions(+), 365 deletions(-) delete mode 100644 docs/reference/gnoclient/client.md delete mode 100644 docs/reference/gnoclient/signer.md diff --git a/docs/gno-tooling/cli/gnodev.md b/docs/gno-tooling/cli/gnodev.md index 184eb92f721..ae637e64c64 100644 --- a/docs/gno-tooling/cli/gnodev.md +++ b/docs/gno-tooling/cli/gnodev.md @@ -8,13 +8,13 @@ Gnodev allows for quick and efficient development of Gno code. By watching your development directory, gnodev detects changes in your Gno code, reflecting them in the state of the node immediately. Gnodev also runs a -local instance of `gnoweb`, allowing you to see the rendering of your Gno code instantly. +local instance of `gnoweb`, allowing you to see the rendering of your Gno code instantly. ## Features - **In-Memory Node**: Gnodev starts an in-memory node, and automatically loads the **examples** folder and any user-specified paths. - **Web Interface Server**: Gnodev automatically starts a `gnoweb` server on -[`localhost:8888`](https://localhost:8888). + [`localhost:8888`](https://localhost:8888). - **Balances and Keybase Customization**: Users can set account balances, load them from a file, or add new accounts via a flag. - **Hot Reload**: Gnodev monitors the **examples** folder, as well as any folder specified as an argument for @@ -120,20 +120,20 @@ While `gnodev` is running, the following shortcuts are available: ### Options -| Flag | Effect | -|---------------------|---------------------------------------------------------------------| -| --minimal | Start `gnodev` without loading the examples folder. | -| --no-watch | Disable hot reload. | -| --add-account | Pre-add account(s) in the form `[=]` | -| --balances-file | Load a balance for the user(s) from a balance file. | -| --chain-id | Set node ChainID | -| --deploy-key | Default key name or Bech32 address for uploading packages. | -| --home | Set the path to load user's Keybase. | -| --max-gas | Set the maximum gas per block | -| --no-replay | Do not replay previous transactions upon reload | -| --node-rpc-listener | listening address for GnoLand RPC node | -| --root | gno root directory | -| --server-mode | disable interaction, and adjust logging for server use. | -| --verbose | enable verbose output for development | -| --web-listener | web server listening address | -| --web-help-remote | web server help page's remote addr - default to | +| Flag | Effect | +|---------------------|-----------------------------------------------------------------------| +| --minimal | Start `gnodev` without loading the examples folder. | +| --no-watch | Disable hot reload. | +| --add-account | Pre-add account(s) in the form `[=]` | +| --balances-file | Load a balance for the user(s) from a balance file. | +| --chain-id | Set node ChainID | +| --deploy-key | Default key name or Bech32 address for uploading packages. | +| --home | Set the path to load user's Keybase. | +| --max-gas | Set the maximum gas per block | +| --no-replay | Do not replay previous transactions upon reload | +| --node-rpc-listener | listening address for GnoLand RPC node | +| --root | gno root directory | +| --server-mode | disable interaction, and adjust logging for server use. | +| --verbose | enable verbose output for development | +| --web-listener | web server listening address | +| --web-help-remote | web server help page's remote addr - default to \ | diff --git a/docs/overview.md b/docs/overview.md index a4e425a1d2f..0ded72e06e2 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -14,7 +14,7 @@ version of the Go programming language called Gno. ### Key Features and Technology -1**Interpreted Gno**: Gno.land utilizes the Gno programming language, which is based on Go. It is executed +1. **Interpreted Gno**: Gno.land utilizes the Gno programming language, which is based on Go. It is executed through a specialized virtual machine called the GnoVM, purpose-built for blockchain development with built-in determinism and a modified standard library. While Gno shares similarities with Go in terms of syntax, it currently lacks go routine support. However, this feature is diff --git a/docs/reference/gno-js-client/gno-provider.md b/docs/reference/gno-js-client/gno-provider.md index a5248349d35..df808106cc3 100644 --- a/docs/reference/gno-js-client/gno-provider.md +++ b/docs/reference/gno-js-client/gno-provider.md @@ -39,7 +39,7 @@ Fetches public facing function signatures * `height` **number** the height for querying. If omitted, the latest height is used (optional, default `0`) -Returns **Promise** +Returns **Promise** #### Usage diff --git a/docs/reference/gno-js-client/gno-wallet.md b/docs/reference/gno-js-client/gno-wallet.md index 7f7c44cd9b0..247c3d52878 100644 --- a/docs/reference/gno-js-client/gno-wallet.md +++ b/docs/reference/gno-js-client/gno-wallet.md @@ -63,7 +63,7 @@ Deploys the specified package / realm #### Parameters * `gnoPackage` **MemPackage** the package / realm to be deployed -* `funds` **Map** the denomination -> value map for funds +* `funds` **Map** the denomination -> value map for funds * `fee` **TxFee** the custom transaction fee, if any Returns **Promise** diff --git a/docs/reference/gnoclient/client.md b/docs/reference/gnoclient/client.md deleted file mode 100644 index 7606e83d1e0..00000000000 --- a/docs/reference/gnoclient/client.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -id: client ---- - -# Client - -## type [Client](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client.go#L8-L11) - -`Client` provides an interface for interacting with the blockchain. It is the main -struct of the `gnoclient` package, exposing all APIs used to communicate with a -Gno.land chain. - -```go -type Client struct { - Signer Signer // Signer for transaction authentication - RPCClient rpcclient.Client // RPC client for blockchain communication -} -``` - -### func \(\*Client\) [AddPackage](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L236) - -```go -func (c *Client) AddPackage(cfg BaseTxCfg, msgs ...MsgAddPackage) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`AddPackage` executes one or more [AddPackage](#type-msgaddpackage) calls on the blockchain. - -### func \(\*Client\) [Block](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L131) - -```go -func (c *Client) Block(height int64) (*ctypes.ResultBlock, error) -``` - -`Block` gets the latest block at height, if any. Height must be larger than 0. - -### func \(\*Client\) [BlockResult](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L150) - -```go -func (c *Client) BlockResult(height int64) (*ctypes.ResultBlockResults, error) -``` - -`BlockResult` gets the block results at height, if any. Height must be larger than 0. - -### func \(\*Client\) [LatestBlockHeight](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L168) - -```go -func (c *Client) LatestBlockHeight() (int64, error) -``` - -`LatestBlockHeight` gets the latest block height on the chain. - -### func \(\*Client\) [Call](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L62) - -```go -func (c *Client) Call(cfg BaseTxCfg, msgs ...MsgCall) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Call` executes a one or more [MsgCall](#type-msgcall) calls on the blockchain. - -### func \(\*Client\) [Send](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L182) - -```go -func (c *Client) Send(cfg BaseTxCfg, msgs ...MsgSend) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Send` executes one or more [MsgSend](#type-msgsend) calls on the blockchain. - -### func \(\*Client\) [Run](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L118) - -```go -func (c *Client) Run(cfg BaseTxCfg, msgs ...MsgRun) (*ctypes.ResultBroadcastTxCommit, error) -``` - -`Run` executes a one or more MsgRun calls on the blockchain. - -### func \(\*Client\) [QEval](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L108) - -```go -func (c *Client) QEval(pkgPath string, expression string) (string, *ctypes.ResultABCIQuery, error) -``` - -`QEval` evaluates the given expression with the realm code at `pkgPath`. -The `pkgPath` should include the prefix like `gno.land/`. The expression is -usually a function call like `Render("")`. - -### func \(*Client\) [Query](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L22) - -```go -func (c *Client) Query(cfg QueryCfg) (*ctypes.ResultABCIQuery, error) -``` - -`Query` performs a generic query on the blockchain. - -### func \(*Client\) [QueryAccount](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L39) - -```go -func (c *Client) QueryAccount(addr crypto.Address) (*std.BaseAccount, *ctypes.ResultABCIQuery, error) -``` - -`QueryAccount` retrieves account information for a given address. - -### func \(*Client\) [QueryAppVersion](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L65) - -```go -func (c *Client) QueryAppVersion() (string, *ctypes.ResultABCIQuery, error) -``` - -`QueryAppVersion` retrieves information about the Gno.land app version. - -### func \(*Client\) [Render](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L85) - -```go -func (c *Client) Render(pkgPath string, args string) (string, *ctypes.ResultABCIQuery, error) -``` - -`Render` calls the Render function for pkgPath with optional args. The `pkgPath` -should include the prefix like `gno.land/`. This is similar to using a browser -URL `/:` doesn't have the prefix like -`gno.land/`. - -## type [BaseTxCfg](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L27-L33) - -`BaseTxCfg` defines the base transaction configuration, shared by all message -types. - -```go -type BaseTxCfg struct { - GasFee string // Gas fee - GasWanted int64 // Gas wanted - AccountNumber uint64 // Account number - SequenceNumber uint64 // Sequence number - Memo string // Memo -} -``` - -## type [MsgAddPackage](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L59-L59) - -`MsgAddPackage` \- syntax sugar for `vm.MsgAddPackage`. - -```go -type MsgAddPackage struct { - Package *std.MemPackage // Package to add - Deposit string // Coin deposit -} -``` - -## type [MsgCall](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L36-L41) - -`MsgCall` \- syntax sugar for `vm.MsgCall`. - -```go -type MsgCall struct { - PkgPath string // Package path - FuncName string // Function name - Args []string // Function arguments - Send string // Send amount -} -``` - -## type [MsgRun](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L50-L53) - -`MsgRun` \- syntax sugar for `vm.MsgRun`. - -```go -type MsgRun struct { - Package *std.MemPackage // Package to run - Send string // Send amount -} -``` - -## type [MsgSend](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_txs.go#L44-L47) - -`MsgSend` \- syntax sugar for `bank.MsgSend`. - -```go -type MsgSend struct { - ToAddress crypto.Address // Send to address - Send string // Send amount -} -``` - -## type [QueryCfg](https://github.com/gnolang/gno/blob/master/gno.land/pkg/gnoclient/client_queries.go#L15-L19) - -`QueryCfg` contains configuration options for performing ABCI queries. - -```go -type QueryCfg struct { - Path string // Query path - Data []byte // Query data - rpcclient.ABCIQueryOptions // ABCI query options -} -``` \ No newline at end of file diff --git a/docs/reference/gnoclient/gnoclient.md b/docs/reference/gnoclient/gnoclient.md index f5baa9fc03a..5b9a9f5d43e 100644 --- a/docs/reference/gnoclient/gnoclient.md +++ b/docs/reference/gnoclient/gnoclient.md @@ -22,4 +22,13 @@ your Go code To add Gnoclient to your Go project, run the following command: ```bash go get github.com/gnolang/gno/gno.land/pkg/gnoclient -``` \ No newline at end of file +``` + +## Reference documentation & usage + +To see the full reference documentation for the `gnoclient` package, we recommend +visiting the [`gnoclient godoc page`](https://gnolang.github.io/gno/github.com/gnolang/gno@v0.0.0/gno.land/pkg/gnoclient.html). + +For a tutorial on how to use the `gnoclient` package, check out +["How to connect a Go app to Gno.land"](../../how-to-guides/connecting-from-go.md.) + diff --git a/docs/reference/gnoclient/signer.md b/docs/reference/gnoclient/signer.md deleted file mode 100644 index 75c69a9f7c2..00000000000 --- a/docs/reference/gnoclient/signer.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -id: signer ---- - -# Signer - -`Signer` is an interface that provides functionality for signing transactions. -The signer can be created from a local keybase, or from a bip39 mnemonic phrase. - -Useful types and functions when using the `Signer` can be found below. - -## type [Signer]() - -`Signer` provides an interface for signing transactions. - -```go -type Signer interface { - Sign(SignCfg) (*std.Tx, error) // Signs a transaction and returns a signed tx ready for broadcasting. - Info() keys.Info // Returns key information, including the address. - Validate() error // Checks whether the signer is properly configured. -} -``` - -## type [SignCfg]() - -`SignCfg` provides the signing configuration, containing the unsigned transaction -data, account number, and account sequence. - -```go -type SignCfg struct { - UnsignedTX std.Tx - SequenceNumber uint64 - AccountNumber uint64 -} -``` - -## type [SignerFromKeybase]() - -`SignerFromKeybase` represents a signer created from a Keybase. - -```go -type SignerFromKeybase struct { - Keybase keys.Keybase // Stores keys in memory or on disk - Account string // Account name or bech32 format - Password string // Password for encryption - ChainID string // Chain ID for transaction signing -} -``` - -### func \(SignerFromKeybase\) [Info]() - -```go -func (s SignerFromKeybase) Info() keys.Info -``` - -`Info` gets keypair information. - -### func \(SignerFromKeybase\) [Sign]() - -```go -func (s SignerFromKeybase) Sign(cfg SignCfg) (*std.Tx, error) -``` - -`Sign` implements the Signer interface for SignerFromKeybase. - -### func \(SignerFromKeybase\) [Validate]() - -```go -func (s SignerFromKeybase) Validate() error -``` - -`Validate` checks if the signer is properly configured. - -## func [SignerFromBip39]() - -```go -func SignerFromBip39(mnemonic string, chainID string, passphrase string, account uint32, index uint32) (Signer, error) -``` - -`SignerFromBip39` creates a `Signer` from an in-memory keybase with a single default -account, derived from the given mnemonic. -This can be useful in scenarios where storing private keys in the filesystem -isn't feasible, or for generating a signer for testing. - -> Using `keys.NewKeyBaseFromDir()` to get a keypair from local storage is -recommended where possible, as it is more secure. \ No newline at end of file diff --git a/misc/docs-linter/errors.go b/misc/docs-linter/errors.go index d6d6ac098e8..8702f6f7de9 100644 --- a/misc/docs-linter/errors.go +++ b/misc/docs-linter/errors.go @@ -3,7 +3,9 @@ package main import "errors" var ( - errEmptyPath = errors.New("you need to pass in a path to scan") - err404Link = errors.New("link returned a 404") - errFound404Links = errors.New("found links resulting in a 404 response status") + errEmptyPath = errors.New("you need to pass in a path to scan") + err404Link = errors.New("link returned a 404") + errFound404Links = errors.New("found links resulting in a 404 response status") + errFoundUnescapedJSXTags = errors.New("found unescaped JSX tags") + errFoundLintItems = errors.New("found items that need linting") ) diff --git a/misc/docs-linter/jsx.go b/misc/docs-linter/jsx.go index 60ee2f6619b..50b16d842c0 100644 --- a/misc/docs-linter/jsx.go +++ b/misc/docs-linter/jsx.go @@ -2,7 +2,9 @@ package main import ( "context" + "fmt" "regexp" + "strings" ) func extractJSX(fileContent []byte) []string { @@ -17,12 +19,38 @@ func extractJSX(fileContent []byte) []string { contentNoInlineCode := reInlineCode.ReplaceAllString(contentNoCodeBlocks, "") // Extract JSX/HTML elements - reJSXHTML := regexp.MustCompile("(?s)<[^>]+>") + reJSX := regexp.MustCompile("(?s)<[^>]+>") - return reJSXHTML.FindAllString(contentNoInlineCode, -1) + matches := reJSX.FindAllString(contentNoInlineCode, -1) + + filteredMatches := make([]string, 0) + // Ignore HTML comments and escaped JSX + for _, m := range matches { + if !strings.Contains(m, "!--") && !strings.Contains(m, "\\>") { + filteredMatches = append(filteredMatches, m) + } + } + + return filteredMatches } func lintJSX(fileUrlMap map[string][]string, ctx context.Context) error { + found := false + for filePath, tags := range fileUrlMap { + filePath := filePath + for _, tag := range tags { + if !found { + fmt.Println("Tags that need checking:") + found = true + } + + fmt.Printf(">>> %s (found in file: %s)\n", tag, filePath) + } + } + + if found { + return errFoundUnescapedJSXTags + } return nil } diff --git a/misc/docs-linter/links.go b/misc/docs-linter/links.go index 10d4edea2cf..41b90207aa5 100644 --- a/misc/docs-linter/links.go +++ b/misc/docs-linter/links.go @@ -13,23 +13,38 @@ import ( "sync" ) -func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { - // Filter links by prefix & ignore localhost - validUrls := make(map[string][]string) +// extractUrls extracts URLs from a file and maps them to the file +func extractUrls(fileContent []byte) []string { + scanner := bufio.NewScanner(bytes.NewReader(fileContent)) + urls := make([]string, 0) - for file, urls := range fileUrlMap { - file := file - for _, url := range urls { - // Look for http & https only - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - // Ignore localhost - if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { - validUrls[file] = append(validUrls[file], url) - } + // Scan file line by line + for scanner.Scan() { + line := scanner.Text() + + // Extract links + rxStrict := xurls.Strict() + url := rxStrict.FindString(line) + + // Check for empty links and skip them + if url == " " || len(url) == 0 { + continue + } + + // Look for http & https only + if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { + // Ignore localhost + if !strings.Contains(url, "localhost") && !strings.Contains(url, "127.0.0.1") { + urls = append(urls, url) } } } + return urls +} + +func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { + // Filter links by prefix & ignore localhost // Setup parallel checking for links g, _ := errgroup.WithContext(ctx) @@ -38,7 +53,7 @@ func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { notFoundUrls []string ) - for filePath, urls := range validUrls { + for filePath, urls := range fileUrlMap { filePath := filePath for _, url := range urls { url := url @@ -60,6 +75,7 @@ func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { // Print out the URLs that returned a 404 along with the file names if len(notFoundUrls) > 0 { + fmt.Println("Links that need checking:") for _, result := range notFoundUrls { fmt.Println(result) } @@ -67,35 +83,9 @@ func lintLinks(fileUrlMap map[string][]string, ctx context.Context) error { return errFound404Links } - fmt.Println("No broken links were found.") - return nil } -// extractUrls extracts URLs from a file and maps them to the file -func extractUrls(fileContent []byte) []string { - scanner := bufio.NewScanner(bytes.NewReader(fileContent)) - urls := make([]string, 0) - - // Scan file line by line - for scanner.Scan() { - line := scanner.Text() - - // Extract links - rxStrict := xurls.Strict() - url := rxStrict.FindString(line) - - // Check for empty links and skip them - if url == " " || len(url) == 0 { - continue - } - - urls = append(urls, url) - } - - return urls -} - // checkUrl checks if a URL is a 404 func checkUrl(url string) error { // Attempt to retrieve the HTTP header diff --git a/misc/docs-linter/main.go b/misc/docs-linter/main.go index 6ea89e921e7..035170ca5ae 100644 --- a/misc/docs-linter/main.go +++ b/misc/docs-linter/main.go @@ -5,6 +5,7 @@ import ( "flag" "fmt" "github.com/gnolang/gno/tm2/pkg/commands" + "golang.org/x/sync/errgroup" "os" "path/filepath" "strings" @@ -46,7 +47,12 @@ func execLint(cfg *cfg, ctx context.Context) error { return errEmptyPath } - fmt.Println("Linting...") + absPath, err := filepath.Abs(cfg.docsPath) + if err != nil { + return fmt.Errorf("error getting absolute path for docs folder: %w", err) + } + + fmt.Printf("Linting %s...\n", absPath) // Find docs files to lint mdFiles, err := findFilePaths(cfg.docsPath) @@ -55,8 +61,8 @@ func execLint(cfg *cfg, ctx context.Context) error { } // Make storage maps for tokens to analyze - //fileUrlMap := make(map[string][]string) - fileJSXMap := make(map[string][]string) + fileUrlMap := make(map[string][]string) // file path > [urls] + fileJSXMap := make(map[string][]string) // file path > [JSX items] // Extract tokens from files for _, filePath := range mdFiles { @@ -66,31 +72,28 @@ func execLint(cfg *cfg, ctx context.Context) error { return err } - // pass it to jsx extractor - // save jsx map fileJSXMap[filePath] = extractJSX(fileContents) // Execute URL extractor - //fileUrlMap[filePath] = extractUrls(fileContents) - - if len(fileJSXMap[filePath]) != 0 { - fmt.Println(filePath, fileJSXMap[filePath]) - } - + fileUrlMap[filePath] = extractUrls(fileContents) } - // Run linters + // Run linters in parallel + g, _ := errgroup.WithContext(ctx) - //// lint JSX tags - //if err = lintJSX(fileJSXMap, ctx); err != nil { - // return err - //} + g.Go(func() error { + return lintJSX(fileJSXMap, ctx) + }) - // lint links - //if err = lintLinks(fileUrlMap, ctx); err != nil { - // return err - //} + g.Go(func() error { + return lintLinks(fileUrlMap, ctx) + }) + + if err := g.Wait(); err != nil { + return errFoundLintItems + } + fmt.Println("Lint complete, no issues found.") return nil } From d6bafd82ac0059d9dfca6a3487c5eeaf78ef3686 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Thu, 20 Jun 2024 19:42:27 +0200 Subject: [PATCH 07/11] save --- misc/docs-linter/main_test.go | 46 ----------------------------------- 1 file changed, 46 deletions(-) diff --git a/misc/docs-linter/main_test.go b/misc/docs-linter/main_test.go index fb7ae089455..d18fb07e94b 100644 --- a/misc/docs-linter/main_test.go +++ b/misc/docs-linter/main_test.go @@ -25,52 +25,6 @@ func TestEmptyPathError(t *testing.T) { assert.ErrorIs(t, execLint(cfg, ctx), errEmptyPath) } -func TestExtractLinks(t *testing.T) { - // todo rewrite - t.Parallel() - - // Generate temporary source dir - sourceDir, err := os.MkdirTemp(".", "sourceDir") - require.NoError(t, err) - t.Cleanup(removeDir(t, sourceDir)) - - // Create mock files with random links - mockFiles := map[string]string{ - "file1.md": "This is a test file with a link: https://example.com.\nAnother link: http://example.org.", - "file2.md": "Markdown content with a link: https://example.com/page.", - "file3.md": "Links in a list:\n- https://example.com/item1\n- https://example.org/item2", - } - - for fileName, content := range mockFiles { - filePath := filepath.Join(sourceDir, fileName) - err := os.WriteFile(filePath, []byte(content), 0644) - require.NoError(t, err) - } - - // Expected URLs and their corresponding files - expectedUrls := map[string]string{ - "https://example.com": filepath.Join(sourceDir, "file1.md"), - "http://example.org": filepath.Join(sourceDir, "file1.md"), - "https://example.com/page": filepath.Join(sourceDir, "file2.md"), - "https://example.com/item1": filepath.Join(sourceDir, "file3.md"), - "https://example.org/item2": filepath.Join(sourceDir, "file3.md"), - } - - // Extract URLs from each file in the sourceDir - for fileName := range mockFiles { - filePath := filepath.Join(sourceDir, fileName) - extractedUrls, err := extractUrls(filePath) - require.NoError(t, err) - - // Verify that the extracted URLs match the expected URLs - for url, expectedFile := range expectedUrls { - if expectedFile == filePath { - require.Equal(t, expectedFile, extractedUrls[url], "URL: %s not correctly mapped to file: %s", url, expectedFile) - } - } - } -} - func TestFindFilePaths(t *testing.T) { t.Parallel() From 5f3f44ac0cc74b7b58038614a67f3783538419de Mon Sep 17 00:00:00 2001 From: leohhhn Date: Thu, 20 Jun 2024 19:44:11 +0200 Subject: [PATCH 08/11] fix jsx --- docs/gno-tooling/cli/gnodev.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/gno-tooling/cli/gnodev.md b/docs/gno-tooling/cli/gnodev.md index ae637e64c64..44874e2277f 100644 --- a/docs/gno-tooling/cli/gnodev.md +++ b/docs/gno-tooling/cli/gnodev.md @@ -120,20 +120,20 @@ While `gnodev` is running, the following shortcuts are available: ### Options -| Flag | Effect | -|---------------------|-----------------------------------------------------------------------| -| --minimal | Start `gnodev` without loading the examples folder. | -| --no-watch | Disable hot reload. | -| --add-account | Pre-add account(s) in the form `[=]` | -| --balances-file | Load a balance for the user(s) from a balance file. | -| --chain-id | Set node ChainID | -| --deploy-key | Default key name or Bech32 address for uploading packages. | -| --home | Set the path to load user's Keybase. | -| --max-gas | Set the maximum gas per block | -| --no-replay | Do not replay previous transactions upon reload | -| --node-rpc-listener | listening address for GnoLand RPC node | -| --root | gno root directory | -| --server-mode | disable interaction, and adjust logging for server use. | -| --verbose | enable verbose output for development | -| --web-listener | web server listening address | -| --web-help-remote | web server help page's remote addr - default to \ | +| Flag | Effect | +|---------------------|----------------------------------------------------------------------| +| --minimal | Start `gnodev` without loading the examples folder. | +| --no-watch | Disable hot reload. | +| --add-account | Pre-add account(s) in the form `[=]` | +| --balances-file | Load a balance for the user(s) from a balance file. | +| --chain-id | Set node ChainID | +| --deploy-key | Default key name or Bech32 address for uploading packages. | +| --home | Set the path to load user's Keybase. | +| --max-gas | Set the maximum gas per block | +| --no-replay | Do not replay previous transactions upon reload | +| --node-rpc-listener | listening address for GnoLand RPC node | +| --root | gno root directory | +| --server-mode | disable interaction, and adjust logging for server use. | +| --verbose | enable verbose output for development | +| --web-listener | web server listening address | +| --web-help-remote | web server help page's remote addr - default to | From edbc349ac24faa40e5138a3aca38002b2400011c Mon Sep 17 00:00:00 2001 From: leohhhn Date: Thu, 20 Jun 2024 19:45:13 +0200 Subject: [PATCH 09/11] typo --- docs/gno-tooling/cli/gnodev.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/gno-tooling/cli/gnodev.md b/docs/gno-tooling/cli/gnodev.md index 44874e2277f..c641a986a4e 100644 --- a/docs/gno-tooling/cli/gnodev.md +++ b/docs/gno-tooling/cli/gnodev.md @@ -120,20 +120,20 @@ While `gnodev` is running, the following shortcuts are available: ### Options -| Flag | Effect | -|---------------------|----------------------------------------------------------------------| -| --minimal | Start `gnodev` without loading the examples folder. | -| --no-watch | Disable hot reload. | -| --add-account | Pre-add account(s) in the form `[=]` | -| --balances-file | Load a balance for the user(s) from a balance file. | -| --chain-id | Set node ChainID | -| --deploy-key | Default key name or Bech32 address for uploading packages. | -| --home | Set the path to load user's Keybase. | -| --max-gas | Set the maximum gas per block | -| --no-replay | Do not replay previous transactions upon reload | -| --node-rpc-listener | listening address for GnoLand RPC node | -| --root | gno root directory | -| --server-mode | disable interaction, and adjust logging for server use. | -| --verbose | enable verbose output for development | -| --web-listener | web server listening address | -| --web-help-remote | web server help page's remote addr - default to | +| Flag | Effect | +|---------------------|-----------------------------------------------------------------------| +| --minimal | Start `gnodev` without loading the examples folder. | +| --no-watch | Disable hot reload. | +| --add-account | Pre-add account(s) in the form `[=]` | +| --balances-file | Load a balance for the user(s) from a balance file. | +| --chain-id | Set node ChainID | +| --deploy-key | Default key name or Bech32 address for uploading packages. | +| --home | Set the path to load user's Keybase. | +| --max-gas | Set the maximum gas per block | +| --no-replay | Do not replay previous transactions upon reload | +| --node-rpc-listener | listening address for GnoLand RPC node | +| --root | gno root directory | +| --server-mode | disable interaction, and adjust logging for server use. | +| --verbose | enable verbose output for development | +| --web-listener | web server listening address | +| --web-help-remote | web server help page's remote addr - defaults to | From 56c725528b61fb40a764712dab8c033f726f3644 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Fri, 21 Jun 2024 11:58:31 +0200 Subject: [PATCH 10/11] add test --- misc/docs-linter/main_test.go | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/misc/docs-linter/main_test.go b/misc/docs-linter/main_test.go index d18fb07e94b..5fe48b50b4e 100644 --- a/misc/docs-linter/main_test.go +++ b/misc/docs-linter/main_test.go @@ -25,6 +25,56 @@ func TestEmptyPathError(t *testing.T) { assert.ErrorIs(t, execLint(cfg, ctx), errEmptyPath) } +func TestExtractLinks(t *testing.T) { + t.Parallel() + + // Create mock file content with random links + mockFileContent := `# Lorem Ipsum +Lorem ipsum dolor sit amet, +[consectetur](https://example.org) +adipiscing elit. Vivamus lacinia odio +vitae [vestibulum vestibulum](http://localhost:3000). +Cras [vel ex](http://192.168.1.1) et +turpis egestas luctus. Nullam +[eleifend](https://www.wikipedia.org) +nulla ac [blandit tempus](https://gitlab.org). +## Valid Links Here are some valid links: +- [Mozilla](https://mozilla.org) +- [Valid URL](https://valid-url.net) +- [Another Valid URL](https://another-valid-url.info) +- [Valid Link](https://valid-link.edu) +` + + // Expected URLs + expectedUrls := []string{ + "https://example.org", + "http://192.168.1.1", + "https://www.wikipedia.org", + "https://gitlab.org", + "https://mozilla.org", + "https://valid-url.net", + "https://another-valid-url.info", + "https://valid-link.edu", + } + + // Extract URLs from each file in the sourceDir + extractedUrls := extractUrls([]byte(mockFileContent)) + c + if len(expectedUrls) != len(extractedUrls) { + t.Fatal("Did not extract correct amount of URLs") + } + + sort.Strings(extractedUrls) + sort.Strings(expectedUrls) + + for i, u := range expectedUrls { + if u != extractedUrls[i] { + t.Fatalf("expected to get %s, got %s", u, extractedUrls[i]) + } + } + +} + func TestFindFilePaths(t *testing.T) { t.Parallel() From d2c81e9977710e94e6c24dbb92468989c585d4e2 Mon Sep 17 00:00:00 2001 From: leohhhn Date: Fri, 21 Jun 2024 12:20:54 +0200 Subject: [PATCH 11/11] add jsx test --- misc/docs-linter/main_test.go | 56 +++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/misc/docs-linter/main_test.go b/misc/docs-linter/main_test.go index 5fe48b50b4e..27393236215 100644 --- a/misc/docs-linter/main_test.go +++ b/misc/docs-linter/main_test.go @@ -59,20 +59,66 @@ nulla ac [blandit tempus](https://gitlab.org). // Extract URLs from each file in the sourceDir extractedUrls := extractUrls([]byte(mockFileContent)) - c + if len(expectedUrls) != len(extractedUrls) { - t.Fatal("Did not extract correct amount of URLs") + t.Fatal("did not extract correct amount of URLs") } sort.Strings(extractedUrls) sort.Strings(expectedUrls) for i, u := range expectedUrls { - if u != extractedUrls[i] { - t.Fatalf("expected to get %s, got %s", u, extractedUrls[i]) - } + require.Equal(t, u, extractedUrls[i]) } +} + +func TestExtractJSX(t *testing.T) { + t.Parallel() + + // Create mock file content with random JSX tags + mockFileContent := ` +#### Usage + +### getFunctionSignatures + +Fetches public facing function signatures + +#### Parameters + +Returns **Promise** + +# test text from gnodev.md + +#### Usage +### evaluateExpression +Evaluates any expression in readonly mode and returns the results + +#### Parameters + +Returns **Promise** +` + + // Expected JSX tags + expectedTags := []string{ + "", + "", + "", + } + + // Extract JSX tags from the mock file content + extractedTags := extractJSX([]byte(mockFileContent)) + + if len(expectedTags) != len(extractedTags) { + t.Fatal("did not extract the correct amount of JSX tags") + } + + sort.Strings(extractedTags) + sort.Strings(expectedTags) + + for i, tag := range expectedTags { + require.Equal(t, tag, extractedTags[i]) + } } func TestFindFilePaths(t *testing.T) {