返回 DeepSeek-Reasonix
render.go
根目录 / tools / desktopinventory / render.go
1 package main
2
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "strings"
8 )
9
10 var classLabel = map[class]string{
11 classKeepBusiness: "keep-business (保留业务实现)",
12 classMigrateHost: "migrate-host (迁移宿主实现)",
13 classDeleteShell: "delete-shell (删除旧壳专用实现)",
14 }
15
16 var kindTitle = map[string]string{
17 kindCommand: "Desktop commands (Go `App` methods bound to the UI)",
18 kindNativeCall: "Native toolkit calls in Go",
19 kindEvent: "Events emitted by Go",
20 kindFrontendNative: "Frontend native bridge uses",
21 kindFrontendEvent: "Frontend event subscriptions",
22 kindCSSMarker: "Shell CSS markers",
23 kindPersistence: "Persisted desktop files",
24 kindShellFile: "Shell-specific Go files",
25 kindArtifact: "Release artifacts",
26 kindCIJob: "CI and release jobs",
27 }
28
29 // migrationBaseline is the deliberately frozen main-v2 checkpoint. Do not
30 // derive it from checkout refs: shallow CI clones and synthetic PR merge
31 // commits have different histories despite containing identical source files.
32 // Advance this checkpoint explicitly when integrating another mainline baseline.
33 const migrationBaseline = "fa018e4109268c912063c8cc619302fccdb57d74"
34
35 func build(root string) (*inventory, error) {
36 inv := &inventory{Baseline: migrationBaseline}
37 if err := scanGo(root, inv); err != nil {
38 return nil, err
39 }
40 if err := scanFrontend(root, inv); err != nil {
41 return nil, err
42 }
43 if err := scanSources(root, inv); err != nil {
44 return nil, err
45 }
46 inv.Entries = inv.sorted()
47 return inv, nil
48 }
49
50 func render(inv *inventory) (markdown, jsonOut []byte, err error) {
51 jsonOut, err = json.MarshalIndent(inv, "", " ")
52 if err != nil {
53 return nil, nil, err
54 }
55 jsonOut = append(jsonOut, '\n')
56
57 var b bytes.Buffer
58 fmt.Fprintf(&b, "# Desktop shell migration inventory\n\n")
59 fmt.Fprintf(&b, "Generated by `go run ./tools/desktopinventory` from baseline `%s`. Do not edit; `-check` fails when this file is stale.\n\n", inv.Baseline)
60 fmt.Fprintf(&b, "Every entry carries one class: `keep-business` keeps its Go implementation and crosses the new host RPC unchanged, `migrate-host` moves its native step to the Electron host behind the contract, `delete-shell` left with the retired Wails/WebView2/WebKitGTK shell (none remain).\n\n")
61 counts := inv.counts()
62 fmt.Fprintf(&b, "| Kind | keep-business | migrate-host | delete-shell | total |\n| --- | ---: | ---: | ---: | ---: |\n")
63 total := 0
64 for _, kind := range kindOrder {
65 c := counts[kind]
66 sum := c[classKeepBusiness] + c[classMigrateHost] + c[classDeleteShell]
67 total += sum
68 fmt.Fprintf(&b, "| %s | %d | %d | %d | %d |\n", kind, c[classKeepBusiness], c[classMigrateHost], c[classDeleteShell], sum)
69 }
70 fmt.Fprintf(&b, "| **all** | | | | **%d** |\n", total)
71 for _, kind := range kindOrder {
72 fmt.Fprintf(&b, "\n## %s\n\n| Name | Detail | Location | Class | New owner |\n| --- | --- | --- | --- | --- |\n", kindTitle[kind])
73 for _, e := range inv.Entries {
74 if e.Kind != kind {
75 continue
76 }
77 fmt.Fprintf(&b, "| `%s` | %s | %s | %s | %s |\n", e.Name, cell(e.Detail), cell(e.Location), classLabel[e.Class], cell(e.Owner))
78 }
79 }
80 return b.Bytes(), jsonOut, nil
81 }
82
83 func cell(s string) string {
84 s = strings.ReplaceAll(s, "|", "\\|")
85 s = strings.ReplaceAll(s, "\n", " ")
86 if s == "" {
87 return ""
88 }
89 if strings.ContainsAny(s, "()*<>") {
90 return "`" + strings.ReplaceAll(s, "`", "'") + "`"
91 }
92 return s
93 }
94
94 lines GO