Switch remote deploy to vendored source builds

Move remote deployment to a vendored source bundle built on the target host via Docker so redeploys no longer require local cross-compilation or host Go installation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
GitHub Actions
2026-05-08 12:19:18 +08:00
parent bb27566e38
commit c1a0fe2949
1320 changed files with 497125 additions and 11 deletions

10
vendor/github.com/wailsapp/wails/v2/pkg/menu/README.md generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Menus
Menu support is heavily inspired by Electron's approach.
## Features
* Supports Text, Checkbox, Radio, Submenu and Separator
* Radio groups are defined as any number of adjacent radio items
* UTF-8 menu labels
* UTF-8 menu IDs

View File

@@ -0,0 +1,8 @@
package menu
type CallbackData struct {
MenuItem *MenuItem
// ContextData string
}
type Callback func(*CallbackData)

1559
vendor/github.com/wailsapp/wails/v2/pkg/menu/cols.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
package menu
type ContextMenu struct {
ID string
Menu *Menu
}
func NewContextMenu(ID string, menu *Menu) *ContextMenu {
return &ContextMenu{
ID: ID,
Menu: menu,
}
}

View File

@@ -0,0 +1,104 @@
package keys
import (
"fmt"
"strings"
)
// Modifier is actually a string
type Modifier string
const (
// CmdOrCtrlKey represents Command on Mac and Control on other platforms
CmdOrCtrlKey Modifier = "cmdorctrl"
// OptionOrAltKey represents Option on Mac and Alt on other platforms
OptionOrAltKey Modifier = "optionoralt"
// ShiftKey represents the shift key on all systems
ShiftKey Modifier = "shift"
// SuperKey represents Command on Mac and the Windows key on the other platforms
// SuperKey Modifier = "super"
// ControlKey represents the control key on all systems
ControlKey Modifier = "ctrl"
)
var modifierMap = map[string]Modifier{
"cmdorctrl": CmdOrCtrlKey,
"optionoralt": OptionOrAltKey,
"shift": ShiftKey,
//"super": SuperKey,
"ctrl": ControlKey,
}
func parseModifier(text string) (*Modifier, error) {
lowertext := strings.ToLower(text)
result, valid := modifierMap[lowertext]
if !valid {
return nil, fmt.Errorf("'%s' is not a valid modifier", text)
}
return &result, nil
}
// Accelerator holds the keyboard shortcut for a menu item
type Accelerator struct {
Key string
Modifiers []Modifier
}
// Key creates a standard key Accelerator
func Key(key string) *Accelerator {
return &Accelerator{
Key: strings.ToLower(key),
}
}
// CmdOrCtrl creates a 'CmdOrCtrl' Accelerator
func CmdOrCtrl(key string) *Accelerator {
return &Accelerator{
Key: strings.ToLower(key),
Modifiers: []Modifier{CmdOrCtrlKey},
}
}
// OptionOrAlt creates a 'OptionOrAlt' Accelerator
func OptionOrAlt(key string) *Accelerator {
return &Accelerator{
Key: strings.ToLower(key),
Modifiers: []Modifier{OptionOrAltKey},
}
}
// Shift creates a 'Shift' Accelerator
func Shift(key string) *Accelerator {
return &Accelerator{
Key: strings.ToLower(key),
Modifiers: []Modifier{ShiftKey},
}
}
// Control creates a 'Control' Accelerator
func Control(key string) *Accelerator {
return &Accelerator{
Key: strings.ToLower(key),
Modifiers: []Modifier{ControlKey},
}
}
//
//// Super creates a 'Super' Accelerator
//func Super(key string) *Accelerator {
// return &Accelerator{
// Key: strings.ToLower(key),
// Modifiers: []Modifier{SuperKey},
// }
//}
// Combo creates an Accelerator with multiple Modifiers
func Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier) *Accelerator {
result := &Accelerator{
Key: key,
Modifiers: []Modifier{modifier1, modifier2},
}
result.Modifiers = append(result.Modifiers, rest...)
return result
}

View File

@@ -0,0 +1,26 @@
package keys
const (
NSEventModifierFlagShift = 1 << 17 // Set if Shift key is pressed.
NSEventModifierFlagControl = 1 << 18 // Set if Control key is pressed.
NSEventModifierFlagOption = 1 << 19 // Set if Option or Alternate key is pressed.
NSEventModifierFlagCommand = 1 << 20 // Set if Command key is pressed.
)
var macModifierMap = map[Modifier]int{
CmdOrCtrlKey: NSEventModifierFlagCommand,
ControlKey: NSEventModifierFlagControl,
OptionOrAltKey: NSEventModifierFlagOption,
ShiftKey: NSEventModifierFlagShift,
}
func ToMacModifier(accelerator *Accelerator) int {
if accelerator == nil {
return 0
}
result := 0
for _, modifier := range accelerator.Modifiers {
result |= macModifierMap[modifier]
}
return result
}

View File

@@ -0,0 +1,87 @@
package keys
import (
"fmt"
"strconv"
"strings"
"github.com/leaanthony/slicer"
)
var namedKeys = slicer.String([]string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
func parseKey(key string) (string, bool) {
// Lowercase!
key = strings.ToLower(key)
// Check special case
if key == "plus" {
return "+", true
}
// Handle named keys
if namedKeys.Contains(key) {
return key, true
}
// Check we only have a single character
if len(key) != 1 {
return "", false
}
runeKey := rune(key[0])
// This may be too inclusive
if strconv.IsPrint(runeKey) {
return key, true
}
return "", false
}
func Parse(shortcut string) (*Accelerator, error) {
var result Accelerator
// Split the shortcut by +
components := strings.Split(shortcut, "+")
// If we only have one it should be a key
// We require components
if len(components) == 0 {
return nil, fmt.Errorf("no components given to validateComponents")
}
// Keep track of modifiers we have processed
var modifiersProcessed slicer.StringSlicer
// Check components
for index, component := range components {
// If last component
if index == len(components)-1 {
processedkey, validKey := parseKey(component)
if !validKey {
return nil, fmt.Errorf("'%s' is not a valid key", component)
}
result.Key = processedkey
continue
}
// Not last component - needs to be modifier
lowercaseComponent := strings.ToLower(component)
thisModifier, valid := modifierMap[lowercaseComponent]
if !valid {
return nil, fmt.Errorf("'%s' is not a valid modifier", component)
}
// Needs to be unique
if modifiersProcessed.Contains(lowercaseComponent) {
return nil, fmt.Errorf("Modifier '%s' is defined twice for shortcut: %s", component, shortcut)
}
// Save this data
result.Modifiers = append(result.Modifiers, thisModifier)
modifiersProcessed.Add(lowercaseComponent)
}
return &result, nil
}

View File

@@ -0,0 +1,41 @@
package keys
import (
"strings"
"github.com/leaanthony/slicer"
)
var modifierStringMap = map[string]map[Modifier]string{
"windows": {
CmdOrCtrlKey: "Ctrl",
ControlKey: "Ctrl",
OptionOrAltKey: "Alt",
ShiftKey: "Shift",
// SuperKey: "Win",
},
"darwin": {
CmdOrCtrlKey: "Cmd",
ControlKey: "Ctrl",
OptionOrAltKey: "Option",
ShiftKey: "Shift",
// SuperKey: "Cmd",
},
"linux": {
CmdOrCtrlKey: "Ctrl",
ControlKey: "Ctrl",
OptionOrAltKey: "Alt",
ShiftKey: "Shift",
// SuperKey: "Super",
},
}
func Stringify(accelerator *Accelerator, platform string) string {
result := slicer.String()
for _, modifier := range accelerator.Modifiers {
result.Add(modifierStringMap[platform][modifier])
}
result.Deduplicate()
result.Add(strings.ToUpper(accelerator.Key))
return result.Join("+")
}

12
vendor/github.com/wailsapp/wails/v2/pkg/menu/mac.go generated vendored Normal file
View File

@@ -0,0 +1,12 @@
package menu
/*
// DefaultMacMenu returns a default menu including the default
// Application and Edit menus. Use `.Append()` to add to it.
func DefaultMacMenu() *Menu {
return NewMenuFromItems(
AppMenu(),
EditMenu(),
)
}
*/

75
vendor/github.com/wailsapp/wails/v2/pkg/menu/menu.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
package menu
import "github.com/wailsapp/wails/v2/pkg/menu/keys"
type Menu struct {
Items []*MenuItem
}
func NewMenu() *Menu {
return &Menu{}
}
func (m *Menu) Append(item *MenuItem) {
m.Items = append(m.Items, item)
}
// Merge will append the items in the given menu
// into this menu
func (m *Menu) Merge(menu *Menu) {
m.Items = append(m.Items, menu.Items...)
}
// AddText adds a TextMenu item to the menu
func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem {
item := Text(label, accelerator, click)
m.Append(item)
return item
}
// AddCheckbox adds a CheckboxMenu item to the menu
func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
item := Checkbox(label, checked, accelerator, click)
m.Append(item)
return item
}
// AddRadio adds a radio item to the menu
func (m *Menu) AddRadio(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
item := Radio(label, checked, accelerator, click)
m.Append(item)
return item
}
// AddSeparator adds a separator to the menu
func (m *Menu) AddSeparator() {
item := Separator()
m.Append(item)
}
func (m *Menu) AddSubmenu(label string) *Menu {
submenu := NewMenu()
item := SubMenu(label, submenu)
m.Append(item)
return submenu
}
func (m *Menu) Prepend(item *MenuItem) {
m.Items = append([]*MenuItem{item}, m.Items...)
}
func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu {
result := NewMenu()
result.Append(first)
for _, item := range rest {
result.Append(item)
}
return result
}
func (m *Menu) setParent(menuItem *MenuItem) {
for _, item := range m.Items {
item.parent = menuItem
}
}

View File

@@ -0,0 +1,329 @@
package menu
import (
"sync"
"github.com/wailsapp/wails/v2/pkg/menu/keys"
)
// MenuItem represents a menuitem contained in a menu
type MenuItem struct {
// Label is what appears as the menu text
Label string
// Role is a predefined menu type
Role Role
// Accelerator holds a representation of a key binding
Accelerator *keys.Accelerator
// Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu
Type Type
// Disabled makes the item unselectable
Disabled bool
// Hidden ensures that the item is not shown in the menu
Hidden bool
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
Checked bool
// SubMenu contains a list of menu items that will be shown as a submenu
// SubMenu []*MenuItem `json:"SubMenu,omitempty"`
SubMenu *Menu
// Callback function when menu clicked
Click Callback
/*
// Text Colour
RGBA string
// Font
FontSize int
FontName string
// Image - base64 image data
Image string
// MacTemplateImage indicates that on a Mac, this image is a template image
MacTemplateImage bool
// MacAlternate indicates that this item is an alternative to the previous menu item
MacAlternate bool
// Tooltip
Tooltip string
*/
// This holds the menu item's parent.
parent *MenuItem
// Used for locking when removing elements
removeLock sync.Mutex
}
// Parent returns the parent of the menu item.
// If it is a top level menu then it returns nil.
func (m *MenuItem) Parent() *MenuItem {
return m.parent
}
// Append will attempt to append the given menu item to
// this item's submenu items. If this menu item is not a
// submenu, then this method will not add the item and
// simply return false.
func (m *MenuItem) Append(item *MenuItem) bool {
if !m.isSubMenu() {
return false
}
item.parent = m
m.SubMenu.Append(item)
return true
}
// Prepend will attempt to prepend the given menu item to
// this item's submenu items. If this menu item is not a
// submenu, then this method will not add the item and
// simply return false.
func (m *MenuItem) Prepend(item *MenuItem) bool {
if !m.isSubMenu() {
return false
}
item.parent = m
m.SubMenu.Prepend(item)
return true
}
func (m *MenuItem) Remove() {
// Iterate my parent's children
m.Parent().removeChild(m)
}
func (m *MenuItem) removeChild(item *MenuItem) {
m.removeLock.Lock()
for index, child := range m.SubMenu.Items {
if item == child {
m.SubMenu.Items = append(m.SubMenu.Items[:index], m.SubMenu.Items[index+1:]...)
}
}
m.removeLock.Unlock()
}
// InsertAfter attempts to add the given item after this item in the parent
// menu. If there is no parent menu (we are a top level menu) then false is
// returned
func (m *MenuItem) InsertAfter(item *MenuItem) bool {
// We need to find my parent
if m.parent == nil {
return false
}
// Get my parent to insert the item
return m.parent.insertNewItemAfterGivenItem(m, item)
}
// InsertBefore attempts to add the given item before this item in the parent
// menu. If there is no parent menu (we are a top level menu) then false is
// returned
func (m *MenuItem) InsertBefore(item *MenuItem) bool {
// We need to find my parent
if m.parent == nil {
return false
}
// Get my parent to insert the item
return m.parent.insertNewItemBeforeGivenItem(m, item)
}
// insertNewItemAfterGivenItem will insert the given item after the given target
// in this item's submenu. If we are not a submenu,
// then something bad has happened :/
func (m *MenuItem) insertNewItemAfterGivenItem(target *MenuItem,
newItem *MenuItem,
) bool {
if !m.isSubMenu() {
return false
}
// Find the index of the target
targetIndex := m.getItemIndex(target)
if targetIndex == -1 {
return false
}
// Insert element into slice
return m.insertItemAtIndex(targetIndex+1, newItem)
}
// insertNewItemBeforeGivenItem will insert the given item before the given
// target in this item's submenu. If we are not a submenu, then something bad
// has happened :/
func (m *MenuItem) insertNewItemBeforeGivenItem(target *MenuItem,
newItem *MenuItem,
) bool {
if !m.isSubMenu() {
return false
}
// Find the index of the target
targetIndex := m.getItemIndex(target)
if targetIndex == -1 {
return false
}
// Insert element into slice
return m.insertItemAtIndex(targetIndex, newItem)
}
func (m *MenuItem) isSubMenu() bool {
return m.Type == SubmenuType
}
// getItemIndex returns the index of the given target relative to this menu
func (m *MenuItem) getItemIndex(target *MenuItem) int {
// This should only be called on submenus
if !m.isSubMenu() {
return -1
}
// hunt down that bad boy
for index, item := range m.SubMenu.Items {
if item == target {
return index
}
}
return -1
}
// insertItemAtIndex attempts to insert the given item into the submenu at
// the given index
// Credit: https://stackoverflow.com/a/61822301
func (m *MenuItem) insertItemAtIndex(index int, target *MenuItem) bool {
// If index is OOB, return false
if index > len(m.SubMenu.Items) {
return false
}
// Save parent reference
target.parent = m
// If index is last item, then just regular append
if index == len(m.SubMenu.Items) {
m.SubMenu.Items = append(m.SubMenu.Items, target)
return true
}
m.SubMenu.Items = append(m.SubMenu.Items[:index+1], m.SubMenu.Items[index:]...)
m.SubMenu.Items[index] = target
return true
}
func (m *MenuItem) SetLabel(name string) {
if m.Label == name {
return
}
m.Label = name
}
func (m *MenuItem) IsSeparator() bool {
return m.Type == SeparatorType
}
func (m *MenuItem) IsCheckbox() bool {
return m.Type == CheckboxType
}
func (m *MenuItem) Disable() *MenuItem {
m.Disabled = true
return m
}
func (m *MenuItem) Enable() *MenuItem {
m.Disabled = false
return m
}
func (m *MenuItem) OnClick(click Callback) *MenuItem {
m.Click = click
return m
}
func (m *MenuItem) SetAccelerator(acc *keys.Accelerator) *MenuItem {
m.Accelerator = acc
return m
}
func (m *MenuItem) SetChecked(value bool) *MenuItem {
m.Checked = value
if m.Type != RadioType {
m.Type = CheckboxType
}
return m
}
func (m *MenuItem) Hide() *MenuItem {
m.Hidden = true
return m
}
func (m *MenuItem) Show() *MenuItem {
m.Hidden = false
return m
}
func (m *MenuItem) IsRadio() bool {
return m.Type == RadioType
}
func Label(label string) *MenuItem {
return &MenuItem{
Type: TextType,
Label: label,
}
}
// Text is a helper to create basic Text menu items
func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem {
return &MenuItem{
Label: label,
Type: TextType,
Accelerator: accelerator,
Click: click,
}
}
// Separator provides a menu separator
func Separator() *MenuItem {
return &MenuItem{
Type: SeparatorType,
}
}
// Radio is a helper to create basic Radio menu items with an accelerator
func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
return &MenuItem{
Label: label,
Type: RadioType,
Checked: selected,
Accelerator: accelerator,
Click: click,
}
}
// Checkbox is a helper to create basic Checkbox menu items
func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem {
return &MenuItem{
Label: label,
Type: CheckboxType,
Checked: checked,
Accelerator: accelerator,
Click: click,
}
}
// SubMenu is a helper to create Submenus
func SubMenu(label string, menu *Menu) *MenuItem {
result := &MenuItem{
Label: label,
SubMenu: menu,
Type: SubmenuType,
}
menu.setParent(result)
return result
}

View File

@@ -0,0 +1,214 @@
// Package menu provides all the functions and structs related to menus in a Wails application.
// Heavily inspired by Electron (c) 2013-2020 Github Inc.
// Electron License: https://github.com/electron/electron/blob/master/LICENSE
package menu
// Role is a type to identify menu roles
type Role int
// These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h`
const (
AppMenuRole Role = 1
EditMenuRole = 2
WindowMenuRole = 3
// AboutRole Role = "about"
// UndoRole Role = "undo"
// RedoRole Role = "redo"
// CutRole Role = "cut"
// CopyRole Role = "copy"
// PasteRole Role = "paste"
// PasteAndMatchStyleRole Role = "pasteAndMatchStyle"
// SelectAllRole Role = "selectAll"
// DeleteRole Role = "delete"
// MinimizeRole Role = "minimize"
// QuitRole Role = "quit"
// TogglefullscreenRole Role = "togglefullscreen"
// FileMenuRole Role = "fileMenu"
// ViewMenuRole Role = "viewMenu"
// WindowMenuRole Role = "windowMenu"
// HideRole Role = "hide"
// HideOthersRole Role = "hideOthers"
// UnhideRole Role = "unhide"
// FrontRole Role = "front"
// ZoomRole Role = "zoom"
// WindowSubMenuRole Role = "windowSubMenu"
// HelpSubMenuRole Role = "helpSubMenu"
// SeparatorItemRole Role = "separatorItem"
)
/*
// About provides a MenuItem with the About role
func About() *MenuItem {
return &MenuItem{
Role: AboutRole,
}
}
// Undo provides a MenuItem with the Undo role
func Undo() *MenuItem {
return &MenuItem{
Role: UndoRole,
}
}
// Redo provides a MenuItem with the Redo role
func Redo() *MenuItem {
return &MenuItem{
Role: RedoRole,
}
}
// Cut provides a MenuItem with the Cut role
func Cut() *MenuItem {
return &MenuItem{
Role: CutRole,
}
}
// Copy provides a MenuItem with the Copy role
func Copy() *MenuItem {
return &MenuItem{
Role: CopyRole,
}
}
// Paste provides a MenuItem with the Paste role
func Paste() *MenuItem {
return &MenuItem{
Role: PasteRole,
}
}
// PasteAndMatchStyle provides a MenuItem with the PasteAndMatchStyle role
func PasteAndMatchStyle() *MenuItem {
return &MenuItem{
Role: PasteAndMatchStyleRole,
}
}
// SelectAll provides a MenuItem with the SelectAll role
func SelectAll() *MenuItem {
return &MenuItem{
Role: SelectAllRole,
}
}
// Delete provides a MenuItem with the Delete role
func Delete() *MenuItem {
return &MenuItem{
Role: DeleteRole,
}
}
// Minimize provides a MenuItem with the Minimize role
func Minimize() *MenuItem {
return &MenuItem{
Role: MinimizeRole,
}
}
// Quit provides a MenuItem with the Quit role
func Quit() *MenuItem {
return &MenuItem{
Role: QuitRole,
}
}
// ToggleFullscreen provides a MenuItem with the ToggleFullscreen role
func ToggleFullscreen() *MenuItem {
return &MenuItem{
Role: TogglefullscreenRole,
}
}
// FileMenu provides a MenuItem with the whole default "File" menu (Close / Quit)
func FileMenu() *MenuItem {
return &MenuItem{
Role: FileMenuRole,
}
}
*/
// EditMenu provides a MenuItem with the whole default "Edit" menu (Undo, Copy, etc.).
func EditMenu() *MenuItem {
return &MenuItem{
Role: EditMenuRole,
}
}
/*
// ViewMenu provides a MenuItem with the whole default "View" menu (Reload, Toggle Developer Tools, etc.)
func ViewMenu() *MenuItem {
return &MenuItem{
Role: ViewMenuRole,
}
}
*/
// WindowMenu provides a MenuItem with the whole default "Window" menu (Minimize, Zoom, etc.).
// On MacOS currently all options in there won't work if the window is frameless.
func WindowMenu() *MenuItem {
return &MenuItem{
Role: WindowMenuRole,
}
}
// These roles are Mac only
// AppMenu provides a MenuItem with the whole default "App" menu (About, Services, etc.)
func AppMenu() *MenuItem {
return &MenuItem{
Role: AppMenuRole,
}
}
/*
// Hide provides a MenuItem that maps to the hide action.
func Hide() *MenuItem {
return &MenuItem{
Role: HideRole,
}
}
// HideOthers provides a MenuItem that maps to the hideOtherApplications action.
func HideOthers() *MenuItem {
return &MenuItem{
Role: HideOthersRole,
}
}
// UnHide provides a MenuItem that maps to the unHideAllApplications action.
func UnHide() *MenuItem {
return &MenuItem{
Role: UnhideRole,
}
}
// Front provides a MenuItem that maps to the arrangeInFront action.
func Front() *MenuItem {
return &MenuItem{
Role: FrontRole,
}
}
// Zoom provides a MenuItem that maps to the performZoom action.
func Zoom() *MenuItem {
return &MenuItem{
Role: ZoomRole,
}
}
// WindowSubMenu provides a MenuItem with the "Window" submenu.
func WindowSubMenu() *MenuItem {
return &MenuItem{
Role: WindowSubMenuRole,
}
}
// HelpSubMenu provides a MenuItem with the "Help" submenu.
func HelpSubMenu() *MenuItem {
return &MenuItem{
Role: HelpSubMenuRole,
}
}
*/

View File

@@ -0,0 +1,261 @@
package menu
import (
"fmt"
"strconv"
"strings"
)
type TextStyle int
const (
Bold TextStyle = 1 << 0
Faint TextStyle = 1 << 1
Italic TextStyle = 1 << 2
Blinking TextStyle = 1 << 3
Inversed TextStyle = 1 << 4
Invisible TextStyle = 1 << 5
Underlined TextStyle = 1 << 6
Strikethrough TextStyle = 1 << 7
)
type StyledText struct {
Label string
FgCol *Col
BgCol *Col
Style TextStyle
}
func (s *StyledText) Bold() bool {
return s.Style&Bold == Bold
}
func (s *StyledText) Faint() bool {
return s.Style&Faint == Faint
}
func (s *StyledText) Italic() bool {
return s.Style&Italic == Italic
}
func (s *StyledText) Blinking() bool {
return s.Style&Blinking == Blinking
}
func (s *StyledText) Inversed() bool {
return s.Style&Inversed == Inversed
}
func (s *StyledText) Invisible() bool {
return s.Style&Invisible == Invisible
}
func (s *StyledText) Underlined() bool {
return s.Style&Underlined == Underlined
}
func (s *StyledText) Strikethrough() bool {
return s.Style&Strikethrough == Strikethrough
}
var ansiColorMap = map[string]map[string]*Col{
"Normal": {
"30": Cols[0],
"31": Cols[1],
"32": Cols[2],
"33": Cols[3],
"34": Cols[4],
"35": Cols[5],
"36": Cols[6],
"37": Cols[7],
},
"Bold": {
"30": Cols[8],
"31": Cols[9],
"32": Cols[10],
"33": Cols[11],
"34": Cols[12],
"35": Cols[13],
"36": Cols[14],
"37": Cols[15],
},
"Faint": {
"30": Cols[0],
"31": Cols[1],
"32": Cols[2],
"33": Cols[3],
"34": Cols[4],
"35": Cols[5],
"36": Cols[6],
"37": Cols[7],
},
}
func ParseANSI(input string) ([]*StyledText, error) {
var result []*StyledText
invalid := fmt.Errorf("invalid ansi string")
missingTerminator := fmt.Errorf("missing escape terminator 'm'")
invalidTrueColorSequence := fmt.Errorf("invalid TrueColor sequence")
invalid256ColSequence := fmt.Errorf("invalid 256 colour sequence")
index := 0
var currentStyledText *StyledText = &StyledText{}
if len(input) == 0 {
return nil, invalid
}
for {
// Read all chars to next escape code
esc := strings.Index(input, "\033[")
// If no more esc chars, save what's left and return
if esc == -1 {
text := input[index:]
if len(text) > 0 {
currentStyledText.Label = text
result = append(result, currentStyledText)
}
return result, nil
}
label := input[:esc]
if len(label) > 0 {
currentStyledText.Label = label
result = append(result, currentStyledText)
currentStyledText = &StyledText{
Label: "",
FgCol: currentStyledText.FgCol,
BgCol: currentStyledText.BgCol,
Style: currentStyledText.Style,
}
}
input = input[esc:]
// skip
input = input[2:]
// Read in params
endesc := strings.Index(input, "m")
if endesc == -1 {
return nil, missingTerminator
}
paramText := input[:endesc]
input = input[endesc+1:]
params := strings.Split(paramText, ";")
colourMap := ansiColorMap["Normal"]
skip := 0
for index, param := range params {
if skip > 0 {
skip--
continue
}
switch param {
case "0":
// Reset styles
if len(params) == 1 {
if len(currentStyledText.Label) > 0 {
result = append(result, currentStyledText)
currentStyledText = &StyledText{
Label: "",
FgCol: currentStyledText.FgCol,
BgCol: currentStyledText.BgCol,
Style: currentStyledText.Style,
}
continue
}
}
currentStyledText.Style = 0
currentStyledText.FgCol = nil
currentStyledText.BgCol = nil
case "1":
// Bold
colourMap = ansiColorMap["Bold"]
currentStyledText.Style |= Bold
case "2":
// Dim/Feint
colourMap = ansiColorMap["Faint"]
currentStyledText.Style |= Faint
case "3":
// Italic
currentStyledText.Style |= Italic
case "4":
// Underlined
currentStyledText.Style |= Underlined
case "5":
// Blinking
currentStyledText.Style |= Blinking
case "7":
// Inverse
currentStyledText.Style |= Inversed
case "8":
// Invisible
currentStyledText.Style |= Invisible
case "9":
// Strikethrough
currentStyledText.Style |= Strikethrough
case "30", "31", "32", "33", "34", "35", "36", "37":
currentStyledText.FgCol = colourMap[param]
case "40", "41", "42", "43", "44", "45", "46", "47":
currentStyledText.BgCol = colourMap[param]
case "38", "48":
if len(params)-index < 2 {
return nil, invalid
}
// 256 colours
if params[index+1] == "5" {
skip = 2
colIndexText := params[index+2]
colIndex, err := strconv.Atoi(colIndexText)
if err != nil {
return nil, invalid256ColSequence
}
if colIndex < 0 || colIndex > 255 {
return nil, invalid256ColSequence
}
if param == "38" {
currentStyledText.FgCol = Cols[colIndex]
continue
}
currentStyledText.BgCol = Cols[colIndex]
continue
}
// we must have 4 params left
if len(params)-index < 4 {
return nil, invalidTrueColorSequence
}
if params[index+1] != "2" {
return nil, invalidTrueColorSequence
}
var r, g, b uint8
ri, err := strconv.Atoi(params[index+2])
if err != nil {
return nil, invalidTrueColorSequence
}
gi, err := strconv.Atoi(params[index+3])
if err != nil {
return nil, invalidTrueColorSequence
}
bi, err := strconv.Atoi(params[index+4])
if err != nil {
return nil, invalidTrueColorSequence
}
if bi > 255 || gi > 255 || ri > 255 {
return nil, invalidTrueColorSequence
}
if bi < 0 || gi < 0 || ri < 0 {
return nil, invalidTrueColorSequence
}
r = uint8(ri)
g = uint8(gi)
b = uint8(bi)
skip = 4
colvalue := fmt.Sprintf("#%02x%02x%02x", r, g, b)
if param == "38" {
currentStyledText.FgCol = &Col{Hex: colvalue, Rgb: Rgb{r, g, b}}
continue
}
currentStyledText.BgCol = &Col{Hex: colvalue}
default:
return nil, invalid
}
}
}
}

42
vendor/github.com/wailsapp/wails/v2/pkg/menu/tray.go generated vendored Normal file
View File

@@ -0,0 +1,42 @@
package menu
// TrayMenu are the options
type TrayMenu struct {
// Label is the text we wish to display in the tray
Label string
// Image is the name of the tray icon we wish to display.
// These are read up during build from <projectdir>/trayicons and
// the filenames are used as IDs, minus the extension
// EG: <projectdir>/trayicons/main.png can be referenced here with "main"
// If the image is not a filename, it will be treated as base64 image data
Image string
// MacTemplateImage indicates that on a Mac, this image is a template image
MacTemplateImage bool
// Text Colour
RGBA string
// Font
FontSize int
FontName string
// Tooltip
Tooltip string
// Callback function when menu clicked
// Click Callback `json:"-"`
// Disabled makes the item unselectable
Disabled bool
// Menu is the initial menu we wish to use for the tray
Menu *Menu
// OnOpen is called when the Menu is opened
OnOpen func()
// OnClose is called when the Menu is closed
OnClose func()
}

17
vendor/github.com/wailsapp/wails/v2/pkg/menu/type.go generated vendored Normal file
View File

@@ -0,0 +1,17 @@
package menu
// Type of the menu item
type Type string
const (
// TextType is the text menuitem type
TextType Type = "Text"
// SeparatorType is the Separator menuitem type
SeparatorType Type = "Separator"
// SubmenuType is the Submenu menuitem type
SubmenuType Type = "Submenu"
// CheckboxType is the Checkbox menuitem type
CheckboxType Type = "Checkbox"
// RadioType is the Radio menuitem type
RadioType Type = "Radio"
)

View File

@@ -0,0 +1,13 @@
package menu
/*
// DefaultWindowsMenu returns a default menu including the default
// Application and Edit menus. Use `.Append()` to add to it.
func DefaultWindowsMenu() *Menu {
return NewMenuFromItems(
FileMenu(),
EditMenu(),
WindowMenu(),
)
}
*/