返回 DeepSeek-Reasonix
frontend.go
根目录 / tools / desktopinventory / frontend.go
1 package main
2
3 import (
4 "fmt"
5 "io/fs"
6 "path/filepath"
7 "regexp"
8 "sort"
9 "strings"
10 )
11
12 var (
13 runtimeUseRe = regexp.MustCompile(`\b(?:window\.runtime|runtime|rt)[!?]?\.(EventsOn|EventsOff|BrowserOpenURL|WindowSet[A-Za-z]+|WindowGet[A-Za-z]+|WindowIsMaximised|Clipboard[A-Za-z]+|OnFileDrop[A-Za-z]*)\b`)
14 goBindingRe = regexp.MustCompile(`window\.go\??\.main\??\.App`)
15 eventsOnRe = regexp.MustCompile(`(?:EventsOn|events\.on)\(\s*("([^"]+)"|` + "`([^`]+)`" + `)`)
16 draggableRe = regexp.MustCompile(`--reasonix-draggable`)
17 dropTargetRe = regexp.MustCompile(`data-native-drop-target`)
18 frontendGlobRe = regexp.MustCompile(`\.(ts|tsx|css|html)$`)
19 )
20
21 var frontendNativeOwner = map[string]string{
22 "EventsOn": "desktopHost().events.on",
23 "BrowserOpenURL": "native.openExternal → host shell.openExternal",
24 "ClipboardSetText": "native.clipboardWriteText",
25 "ClipboardGetText": "native.clipboardReadText",
26 "WindowSetSystemDefaultTheme": "native.setWindowTheme(system)",
27 "WindowSetLightTheme": "native.setWindowTheme(light)",
28 "WindowSetDarkTheme": "native.setWindowTheme(dark)",
29 "WindowSetBackgroundColour": "native.setWindowBackground",
30 "WindowGetSize": "native.getWindowBounds",
31 "WindowGetPosition": "native.getWindowBounds",
32 "WindowIsMaximised": "native.getWindowBounds",
33 "OnFileDrop": "native.onFilesDropped (HTML5 drop + getPathForFile)",
34 "OnFileDropOff": "native.onFilesDropped unsubscribe",
35 }
36
37 func scanFrontend(root string, inv *inventory) error {
38 base := filepath.Join(root, "desktop", "frontend")
39 var files []string
40 err := filepath.WalkDir(filepath.Join(base, "src"), func(path string, d fs.DirEntry, err error) error {
41 if err != nil {
42 return err
43 }
44 if d.IsDir() {
45 if d.Name() == "__tests__" || d.Name() == "__fixtures__" || d.Name() == "generated" {
46 return filepath.SkipDir
47 }
48 return nil
49 }
50 if frontendGlobRe.MatchString(d.Name()) {
51 files = append(files, path)
52 }
53 return nil
54 })
55 if err != nil {
56 return err
57 }
58 files = append(files, filepath.Join(base, "index.html"))
59 sort.Strings(files)
60
61 native := map[string]string{}
62 events := map[string]string{}
63 for _, path := range files {
64 text, err := readFile(root, mustRel(root, path))
65 if err != nil {
66 return err
67 }
68 rel := mustRel(root, path)
69 for i, line := range strings.Split(text, "\n") {
70 loc := fmt.Sprintf("%s:%d", rel, i+1)
71 for _, m := range runtimeUseRe.FindAllStringSubmatch(line, -1) {
72 key := "window.runtime." + m[1]
73 if _, seen := native[key]; !seen {
74 native[key] = loc
75 }
76 }
77 if goBindingRe.MatchString(line) {
78 if _, seen := native["window.go.main.App"]; !seen {
79 native["window.go.main.App"] = loc
80 }
81 }
82 for _, m := range eventsOnRe.FindAllStringSubmatch(line, -1) {
83 name := m[2]
84 if name == "" {
85 name = m[3]
86 }
87 if _, seen := events[name]; !seen {
88 events[name] = loc
89 }
90 }
91 }
92 if draggableRe.MatchString(text) {
93 inv.add(entry{Kind: kindCSSMarker, Name: "--reasonix-draggable", Location: rel, Class: classKeepBusiness, Owner: "rewritten to -webkit-app-region by scripts/shell-css.mjs for the Electron bundle"})
94 }
95 if dropTargetRe.MatchString(text) {
96 inv.add(entry{Kind: kindCSSMarker, Name: "data-native-drop-target", Location: rel, Class: classKeepBusiness, Owner: "native.onFilesDropped (HTML5 drop + getPathForFile)"})
97 }
98 }
99 for name, loc := range native {
100 owner := "desktopHost() adapter (AppBindings proxy over desktop/invoke)"
101 if method, ok := strings.CutPrefix(name, "window.runtime."); ok {
102 owner = frontendNativeOwner[method]
103 if owner == "" {
104 owner = "desktopHost().native (unmapped)"
105 }
106 }
107 inv.add(entry{Kind: kindFrontendNative, Name: name, Location: loc, Class: classMigrateHost, Owner: owner})
108 }
109 for name, loc := range events {
110 inv.add(entry{Kind: kindFrontendEvent, Name: name, Location: loc, Class: classKeepBusiness, Owner: "desktopHost().events.on, same payload"})
111 }
112 return nil
113 }
114
115 func mustRel(root, path string) string {
116 rel, err := filepath.Rel(root, path)
117 if err != nil {
118 return path
119 }
120 return filepath.ToSlash(rel)
121 }
122
122 lines GO