Fix the bug in real-time rendering mode

This commit is contained in:
Max 2024-09-10 16:29:15 +08:00
parent 0a21780473
commit fb6518e91f
7 changed files with 174 additions and 86 deletions

File diff suppressed because one or more lines are too long

View file

@ -256,13 +256,37 @@ func (script ScriptNode) ComponentHTML(ns string) string {
return "<script " + strings.Join(attrs, " ") + "></script>"
}
source := fmt.Sprintf(`function %s(){%s};`, script.Component, script.Source)
source := script.Source
if !strings.Contains(script.Source, "function "+script.Component) {
source = fmt.Sprintf(`function %s(){%s};`, script.Component, script.Source)
}
if script.Component == "" {
return "<script " + strings.Join(attrs, " ") + ">\n" + script.Source + "\n</script>"
}
return "<script " + strings.Join(attrs, " ") + ">\n" + source + "\n</script>"
}
// AttrOr return the attribute value or the default value
func (script ScriptNode) AttrOr(key string, or string) string {
for _, attr := range script.Attrs {
if attr.Key == key {
return attr.Val
}
}
return or
}
// AttrOr return the attribute value or the default value
func (style StyleNode) AttrOr(key string, or string) string {
for _, attr := range style.Attrs {
if attr.Key == key {
return attr.Val
}
}
return or
}
// HTML return the html of the style node
func (style StyleNode) HTML() string {
attrs := []string{

View file

@ -50,27 +50,19 @@ const initScriptTmpl = `
} catch (e) { console.log('init data error:', e); }
document.addEventListener("DOMContentLoaded", function () {
try {
document.querySelectorAll("[s\\:ready]").forEach(function (element) {
const method = element.getAttribute("s:ready");
const cn = element.getAttribute("s:cn");
if (method && typeof window[cn] === "function") {
try {
new window[cn](element);
} catch (e) {
const message = e.message || e || "An error occurred";
console.error(` + "`[SUI] ${cn} Error: ${message}`" + `);
}
document.querySelectorAll("[s\\:ready]").forEach(function (element) {
const method = element.getAttribute("s:ready");
const cn = element.getAttribute("s:cn");
if (method && typeof window[cn] === "function") {
try {
new window[cn](element);
} catch (e) {
const message = e.message || e || "An error occurred";
console.error(` + "`[SUI] ${cn} Error: ${message}`" + `);
}
});
} catch (e) {}
try {
__sui_event_init(document.body);
} catch (e) {
const message = e.message || e || "An error occurred";
console.error(` + "`[SUI] ${cn} Error: ${message}`" + `);
}
}
});
__sui_event_init(document.body);
});
%s
`

View file

@ -65,6 +65,42 @@ func (parser *TemplateParser) parseJitComponent(sel *goquery.Selection) {
}
parser.parseElementComponent(comsel)
sel.ReplaceWithSelection(comsel)
if len(comp.scripts) == 0 && len(comp.styles) == 0 {
return
}
if parser.context == nil {
parser.context = &ParserContext{
scripts: []ScriptNode{},
styles: []StyleNode{},
scriptMaps: map[string]bool{},
styleMaps: map[string]bool{},
}
}
// Add the scripts
if comp.scripts != nil {
for _, script := range comp.scripts {
if parser.context.scriptMaps[script.Component] {
continue
}
script.Parent = "head"
parser.context.scriptMaps[script.Component] = true
parser.context.scripts = append(parser.context.scripts, script)
}
}
// Add the styles
if comp.styles != nil {
for _, style := range comp.styles {
if parser.context.styleMaps[style.Component] {
continue
}
parser.context.styles = append(parser.context.styles, style)
parser.context.styleMaps[style.Component] = true
}
}
}
func (parser *TemplateParser) newJitComponentSel(sel *goquery.Selection, comp *JitComponent) (*goquery.Selection, error) {
@ -325,6 +361,15 @@ func (parser *TemplateParser) addScripts(sel *goquery.Selection, scripts []Scrip
continue
}
}
src := script.AttrOr("src", "")
if src != "" {
query := fmt.Sprintf(`script[src="%s"]`, src)
if sel.Find(query).Length() > 0 {
continue
}
}
sel.AppendHtml(script.ComponentHTML(script.Namespace))
}
}

View file

@ -31,6 +31,10 @@ type TemplateParser struct {
// ParserContext parser context for the template
type ParserContext struct {
scriptMaps map[string]bool // parsed components
styleMaps map[string]bool // parsed styles
scripts []ScriptNode // scripts
styles []StyleNode // styles
}
// Mapping mapping for the template
@ -147,6 +151,17 @@ func (parser *TemplateParser) Render(html string) (string, error) {
head.AppendHtml(headInjectionScript(data))
parser.addScripts(head, parser.filterScripts("head", parser.scripts))
parser.addStyles(head, parser.styles)
// Append the just-in-time components
if parser.context != nil {
if parser.context.scripts != nil && len(parser.context.scripts) > 0 {
parser.addScripts(head, parser.filterScripts("head", parser.context.scripts))
}
if parser.context.scripts != nil && len(parser.context.styles) > 0 {
parser.addStyles(head, parser.context.styles)
}
}
}
// Append the data to the body
@ -158,6 +173,11 @@ func (parser *TemplateParser) Render(html string) (string, error) {
}
body.AppendHtml(bodyInjectionScript(data, parser.debug()))
parser.addScripts(body, parser.filterScripts("body", parser.scripts))
// Append the just-in-time components
if parser.context != nil && len(parser.context.scripts) > 0 {
parser.addScripts(body, parser.filterScripts("body", parser.context.scripts))
}
}
// For editor
@ -340,6 +360,7 @@ func (parser *TemplateParser) parseElementComponent(sel *goquery.Selection) {
setError(sel, err)
}
parser.sequence = compParser.sequence + 1
parser.context = compParser.context
}

View file

@ -71,11 +71,12 @@ func ComponentName(name string, hash ...bool) string {
name = strings.ReplaceAll(name, "[", "_")
name = strings.ReplaceAll(name, "]", "_")
cn := fmt.Sprintf("comp_%s", name)
if len(hash) > 0 && hash[0] {
h := fnv.New64a()
h.Write([]byte(cn))
return fmt.Sprintf("cn_%x", h.Sum64())
}
// Keep the component name | hash will be supported later
// if len(hash) > 0 && hash[0] {
// h := fnv.New64a()
// h.Write([]byte(cn))
// return fmt.Sprintf("cn_%x", h.Sum64())
// }
return cn
}

View file

@ -204,6 +204,11 @@ function __sui_event_init(elm: Element) {
}
const component = eventElm.closest(`[s\\:cn=${cn}]`);
if (typeof window[cn] !== "function") {
console.error(`[SUI] Component ${cn} not found`, eventElm);
return;
}
// @ts-ignore
const comp = new window[cn](component);
const handler = comp[bind];