From 503190496449ea2995d167e34e2e870b98b4e8fa Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 3 Jan 2024 16:12:58 +0800 Subject: [PATCH] Add asset path replacement in JavaScript and TypeScript code --- sui/core/build.go | 75 +++++++++++++++++++++++++++----------- sui/core/compile.go | 42 ++++++++++++++++----- sui/core/types.go | 1 + sui/storages/local/page.go | 4 +- 4 files changed, 90 insertions(+), 32 deletions(-) diff --git a/sui/core/build.go b/sui/core/build.go index e92bade0..340cae3f 100644 --- a/sui/core/build.go +++ b/sui/core/build.go @@ -3,6 +3,7 @@ package core import ( "bufio" "fmt" + "path/filepath" "regexp" "strings" @@ -43,11 +44,17 @@ func (page *Page) Build(option *BuildOption) (*goquery.Document, []string, error doc.Selection.Find("head").AppendHtml(style) // Add Script - script, err := page.BuildScript(option) + code, scripts, err := page.BuildScript(option) if err != nil { warnings = append(warnings, err.Error()) } - doc.Selection.Find("body").AppendHtml(script) + if scripts != nil { + for _, script := range scripts { + doc.Selection.Find("body").AppendHtml("\n" + `` + "\n") + } + } + doc.Selection.Find("body").AppendHtml(code) + return doc, warnings, nil } @@ -89,7 +96,7 @@ func (page *Page) BuildForImport(option *BuildOption, slots map[string]interface warnings = append(warnings, err.Error()) } - script, err := page.BuildScript(option) + code, _, err := page.BuildScript(option) if err != nil { warnings = append(warnings, err.Error()) } @@ -108,7 +115,7 @@ func (page *Page) BuildForImport(option *BuildOption, slots map[string]interface // Replace the slots html, _ = Data(data).ReplaceUse(slotRe, html) - return html, style, script, warnings, nil + return html, style, code, warnings, nil } func (page *Page) parse(doc *goquery.Document, option *BuildOption, warnings []string) error { @@ -267,8 +274,12 @@ func (page *Page) BuildStyle(option *BuildOption) (string, error) { } code := page.Codes.CSS.Code + + // Replace the assets if !option.IgnoreAssetRoot { - code = strings.ReplaceAll(page.Codes.CSS.Code, "@assets", option.AssetRoot) + code = AssetsRe.ReplaceAllStringFunc(code, func(match string) string { + return strings.ReplaceAll(match, "@assets", option.AssetRoot) + }) } if option.Namespace != "" { @@ -282,43 +293,65 @@ func (page *Page) BuildStyle(option *BuildOption) (string, error) { return "", err } - return fmt.Sprintf("\n", res), nil + return fmt.Sprintf("\n", res), nil } // BuildScript build the script -func (page *Page) BuildScript(option *BuildOption) (string, error) { +func (page *Page) BuildScript(option *BuildOption) (string, []string, error) { if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" { - return "", nil + return "", nil, nil } if page.Codes.TS.Code != "" { - res, err := page.CompileTS([]byte(page.Codes.TS.Code), false) + code, scripts, err := page.CompileTS([]byte(page.Codes.TS.Code), false) if err != nil { - return "", err + return "", nil, err + } + + // Replace the assets + if !option.IgnoreAssetRoot { + code = AssetsRe.ReplaceAllFunc(code, func(match []byte) []byte { + return []byte(strings.ReplaceAll(string(match), "@assets", option.AssetRoot)) + }) + + if scripts != nil { + for i, script := range scripts { + scripts[i] = filepath.Join(option.AssetRoot, script) + } + } } if option.Namespace == "" { - return fmt.Sprintf("\n", res), nil + return fmt.Sprintf("\n", code), scripts, nil } - return fmt.Sprintf("\n", option.Namespace, addTabToEachLine(string(res))), nil + return fmt.Sprintf("\n", option.Namespace, addTabToEachLine(string(code))), scripts, nil } - code := page.Codes.JS.Code - if !option.IgnoreAssetRoot { - code = strings.ReplaceAll(page.Codes.JS.Code, "@assets", option.AssetRoot) - } - - res, err := page.CompileJS([]byte(code), false) + code, scripts, err := page.CompileJS([]byte(page.Codes.JS.Code), false) if err != nil { - return "", err + return "", nil, err + } + + // Replace the assets + if !option.IgnoreAssetRoot { + code = AssetsRe.ReplaceAllFunc(code, func(match []byte) []byte { + return []byte(strings.ReplaceAll(string(match), "@assets", option.AssetRoot)) + }) + + if scripts != nil { + for i, script := range scripts { + scripts[i] = filepath.Join(option.AssetRoot, script) + } + } } if option.Namespace == "" { - return fmt.Sprintf("\n", res), nil + return fmt.Sprintf("\n", code), scripts, nil } - return fmt.Sprintf("\n", option.Namespace, addTabToEachLine(string(res))), nil + + return fmt.Sprintf("\n", option.Namespace, addTabToEachLine(string(code))), scripts, nil } func addTabToEachLine(input string, prefix ...string) string { diff --git a/sui/core/compile.go b/sui/core/compile.go index d5dd7718..0c2cc37f 100644 --- a/sui/core/compile.go +++ b/sui/core/compile.go @@ -8,6 +8,13 @@ import ( "github.com/yaoapp/kun/log" ) +var quoteRe = "'\"`" +var importRe = regexp.MustCompile(`import\s*\t*\n*[^;]*;`) // import { foo, bar } from 'hello'; ... +var importAssetsRe = regexp.MustCompile(`import\s*\t*\n*\s*['"]@assets\/([^'"]+)['"];`) // import '@assets/foo.js'; or import "@assets/foo.js"; + +// AssetsRe is the regexp for assets +var AssetsRe = regexp.MustCompile(`[` + quoteRe + `]@assets\/([^` + quoteRe + `]+)[` + quoteRe + `]`) // '@assets/foo.js' or "@assets/foo.js" or `@assets/foo` + // Compile the page func (page *Page) Compile(option *BuildOption) (string, error) { @@ -52,18 +59,36 @@ func (page *Page) Compile(option *BuildOption) (string, error) { } // CompileJS compile the javascript -func (page *Page) CompileJS(source []byte, minify bool) ([]byte, error) { - jsCode := regexp.MustCompile(`import\s+.*;`).ReplaceAllString(string(source), "") +func (page *Page) CompileJS(source []byte, minify bool) ([]byte, []string, error) { + scripts := []string{} + matches := importAssetsRe.FindAll(source, -1) + for _, match := range matches { + assets := AssetsRe.FindStringSubmatch(string(match)) + if len(assets) > 1 { + scripts = append(scripts, assets[1]) + } + } + jsCode := importRe.ReplaceAllString(string(source), "") if minify { minified, err := transform.MinifyJS(jsCode) - return []byte(minified), err + return []byte(minified), scripts, err } - return []byte(jsCode), nil + return []byte(jsCode), scripts, nil } // CompileTS compile the typescript -func (page *Page) CompileTS(source []byte, minify bool) ([]byte, error) { - tsCode := regexp.MustCompile(`import\s+.*;`).ReplaceAllString(string(source), "") +func (page *Page) CompileTS(source []byte, minify bool) ([]byte, []string, error) { + + scripts := []string{} + matches := importAssetsRe.FindAll(source, -1) + for _, match := range matches { + assets := AssetsRe.FindStringSubmatch(string(match)) + if len(assets) > 1 { + scripts = append(scripts, assets[1]) + } + } + + tsCode := importRe.ReplaceAllString(string(source), "") if minify { jsCode, err := transform.TypeScript(string(tsCode), api.TransformOptions{ Target: api.ESNext, @@ -71,12 +96,11 @@ func (page *Page) CompileTS(source []byte, minify bool) ([]byte, error) { MinifyIdentifiers: true, MinifySyntax: true, }) - - return []byte(jsCode), err + return []byte(jsCode), scripts, err } jsCode, err := transform.TypeScript(string(tsCode), api.TransformOptions{Target: api.ESNext}) - return []byte(jsCode), err + return []byte(jsCode), scripts, err } // CompileCSS compile the css diff --git a/sui/core/types.go b/sui/core/types.go index 3f0ecd34..390e7e6a 100644 --- a/sui/core/types.go +++ b/sui/core/types.go @@ -244,6 +244,7 @@ type PageConfig struct { // PageSetting is the struct for the page setting type PageSetting struct { Title string `json:"title,omitempty"` + Guard string `json:"guard,omitempty"` Description string `json:"description,omitempty"` SEO *PageSEO `json:"seo,omitempty"` } diff --git a/sui/storages/local/page.go b/sui/storages/local/page.go index 21cbafc1..f16a423f 100644 --- a/sui/storages/local/page.go +++ b/sui/storages/local/page.go @@ -629,7 +629,7 @@ func (page *Page) AssetScript() (*core.Asset, error) { return nil, err } - jsCode, err := page.CompileTS(tsCode, false) + jsCode, _, err := page.CompileTS(tsCode, false) if err != nil { return nil, err } @@ -647,7 +647,7 @@ func (page *Page) AssetScript() (*core.Asset, error) { return nil, err } - jsCode, err = page.CompileJS(jsCode, false) + jsCode, _, err = page.CompileJS(jsCode, false) if err != nil { return nil, err }