refactor: Remove pkg/help (#25)
The help package has been moved to its own repository at Snider/help. This commit removes the local copy of the package from this repository and updates the dependencies. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
|
|
@ -1,22 +0,0 @@
|
|||
:root {
|
||||
--md-primary-fg-color: #00aaff;
|
||||
--md-primary-fg-color--light: #00aaff;
|
||||
--md-primary-fg-color--dark: #00aaff;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] {
|
||||
--md-default-fg-color: hsla(0, 0%, 100%, 0.7);
|
||||
--md-default-fg-color--light: hsla(0, 0%, 100%, 0.54);
|
||||
--md-default-fg-color--lighter: hsla(0, 0%, 100%, 0.32);
|
||||
--md-default-fg-color--lightest: hsla(0, 0%, 100%, 0.12);
|
||||
|
||||
--md-default-bg-color: #0d0d0d;
|
||||
--md-default-bg-color--light: #1a1a1a;
|
||||
--md-default-bg-color--lighter: #333333;
|
||||
--md-default-bg-color--lightest: #4f4f4f;
|
||||
|
||||
--md-code-fg-color: hsla(0, 0%, 100%, 0.7);
|
||||
--md-code-bg-color: #1a1a1a;
|
||||
|
||||
--md-accent-fg-color: #00aaff;
|
||||
}
|
||||
116
pkg/help/help.go
|
|
@ -1,116 +0,0 @@
|
|||
package help
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/Snider/Core/pkg/core"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
//go:embed all:public/*
|
||||
var helpStatic embed.FS
|
||||
|
||||
// Options holds configuration for the help service.
|
||||
type Options struct{}
|
||||
|
||||
// Service manages the in-app help system.
|
||||
type Service struct {
|
||||
*core.Runtime[Options]
|
||||
config core.Config
|
||||
display core.Display
|
||||
assets embed.FS
|
||||
}
|
||||
|
||||
// newHelpService contains the common logic for initialising a Service struct.
|
||||
func newHelpService() (*Service, error) {
|
||||
return &Service{
|
||||
assets: helpStatic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// New is the constructor for static dependency injection.
|
||||
// It creates a Service instance without initialising the core.Runtime field.
|
||||
// Dependencies are passed directly here.
|
||||
func New() (*Service, error) {
|
||||
s, err := newHelpService()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Register is the constructor for dynamic dependency injection (used with core.WithService).
|
||||
// It creates a Service instance and initialises its core.Runtime field.
|
||||
// Dependencies are injected during ServiceStartup.
|
||||
func Register(c *core.Core) (any, error) {
|
||||
s, err := newHelpService()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.Runtime = core.NewRuntime(c, Options{})
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// HandleIPCEvents processes IPC messages, including injecting dependencies on startup.
|
||||
func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error {
|
||||
switch m := msg.(type) {
|
||||
case core.ActionServiceStartup:
|
||||
return s.ServiceStartup(context.Background(), application.ServiceOptions{})
|
||||
default:
|
||||
c.App.Logger.Error("Help: Unknown message type", "type", fmt.Sprintf("%T", m))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServiceStartup is called when the app starts, after dependencies are injected.
|
||||
func (s *Service) ServiceStartup(context.Context, application.ServiceOptions) error {
|
||||
s.Core().App.Logger.Info("Help service started")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Show displays the help window.
|
||||
func (s *Service) Show() error {
|
||||
if s.display == nil {
|
||||
return fmt.Errorf("display service not initialized")
|
||||
}
|
||||
if s.Core() == nil {
|
||||
return fmt.Errorf("core runtime not initialized")
|
||||
}
|
||||
msg := map[string]any{
|
||||
"action": "display.open_window",
|
||||
"name": "help",
|
||||
"options": map[string]any{
|
||||
"Title": "Help",
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
},
|
||||
}
|
||||
|
||||
return s.Core().ACTION(msg)
|
||||
}
|
||||
|
||||
// ShowAt displays a specific section of the help documentation.
|
||||
func (s *Service) ShowAt(anchor string) error {
|
||||
if s.display == nil {
|
||||
return fmt.Errorf("display service not initialized")
|
||||
}
|
||||
if s.Core() == nil {
|
||||
return fmt.Errorf("core runtime not initialized")
|
||||
}
|
||||
msg := map[string]any{
|
||||
"action": "display.open_window",
|
||||
"name": "help",
|
||||
"options": map[string]any{
|
||||
"Title": "Help",
|
||||
"Width": 800,
|
||||
"Height": 600,
|
||||
"URL": fmt.Sprintf("/#%s", anchor),
|
||||
},
|
||||
}
|
||||
return s.Core().ACTION(msg)
|
||||
}
|
||||
|
||||
// Ensure Service implements the core.Help interface.
|
||||
var _ core.Help = (*Service)(nil)
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
package help
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/pkg/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// MockDisplay is a mock implementation of the core.Display interface.
|
||||
type MockDisplay struct {
|
||||
ShowCalled bool
|
||||
}
|
||||
|
||||
func (m *MockDisplay) Show() error {
|
||||
m.ShowCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockDisplay) ShowAt(anchor string) error {
|
||||
m.ShowCalled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockDisplay) Hide() error { return nil }
|
||||
func (m *MockDisplay) HideAt(anchor string) error { return nil }
|
||||
func (m *MockDisplay) OpenWindow(opts ...core.WindowOption) error { return nil }
|
||||
|
||||
// MockCore is a mock implementation of the *core.Core type.
|
||||
type MockCore struct {
|
||||
Core *core.Core
|
||||
ActionCalled bool
|
||||
ActionMsg core.Message
|
||||
}
|
||||
|
||||
// ACTION matches the signature required by RegisterAction.
|
||||
func (m *MockCore) ACTION(c *core.Core, msg core.Message) error {
|
||||
m.ActionCalled = true
|
||||
m.ActionMsg = msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupService(t *testing.T) (*Service, *MockCore, *MockDisplay) {
|
||||
s, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
app := application.New(application.Options{})
|
||||
c, err := core.New(core.WithWails(app))
|
||||
assert.NoError(t, err)
|
||||
mockCore := &MockCore{Core: c}
|
||||
mockDisplay := &MockDisplay{}
|
||||
|
||||
s.Runtime = core.NewRuntime(c, Options{})
|
||||
s.display = mockDisplay
|
||||
// Register our mock handler. When the real s.Core().ACTION is called,
|
||||
// our mock handler will be executed.
|
||||
c.RegisterAction(mockCore.ACTION)
|
||||
|
||||
return s, mockCore, mockDisplay
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
s, err := New()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, s)
|
||||
}
|
||||
|
||||
func TestShow(t *testing.T) {
|
||||
s, mockCore, _ := setupService(t)
|
||||
|
||||
err := s.Show()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, mockCore.ActionCalled)
|
||||
|
||||
msg, ok := mockCore.ActionMsg.(map[string]any)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "display.open_window", msg["action"])
|
||||
assert.Equal(t, "help", msg["name"])
|
||||
}
|
||||
|
||||
func TestShowAt(t *testing.T) {
|
||||
s, mockCore, _ := setupService(t)
|
||||
|
||||
err := s.ShowAt("test-anchor")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, mockCore.ActionCalled)
|
||||
|
||||
msg, ok := mockCore.ActionMsg.(map[string]any)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "display.open_window", msg["action"])
|
||||
assert.Equal(t, "help", msg["name"])
|
||||
|
||||
opts, ok := msg["options"].(map[string]any)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "/#test-anchor", opts["URL"])
|
||||
}
|
||||
|
||||
func TestHandleIPCEvents_ServiceStartup(t *testing.T) {
|
||||
s, _, _ := setupService(t)
|
||||
err := s.HandleIPCEvents(s.Core(), core.ActionServiceStartup{})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
site_name: Core.Help
|
||||
site_url: https://dappco.re
|
||||
repo_url: https://github.com/Snider/Core
|
||||
edit_uri: edit/main/docs/src/
|
||||
docs_dir: src
|
||||
nav:
|
||||
- Overview: index.md
|
||||
- Core: core/index.md
|
||||
- Config: core/config.md
|
||||
- Crypt: core/crypt.md
|
||||
- Display: core/display.md
|
||||
- Help: core/help.md
|
||||
- IO: core/io.md
|
||||
- Workspace: core/workspace.md
|
||||
|
||||
copyright: Core © EUPL-1.2 — 2024 to ∞ and beyond
|
||||
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
# Palette toggle for dark mode
|
||||
- scheme: slate
|
||||
primary: blue
|
||||
accent: blue
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Switch to light mode
|
||||
|
||||
# Palette toggle for light mode
|
||||
- scheme: default
|
||||
primary: blue
|
||||
accent: blue
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Switch to dark mode
|
||||
|
||||
font:
|
||||
text: "Roboto"
|
||||
code: "Roboto Mono"
|
||||
language: en
|
||||
icon:
|
||||
repo: fontawesome/brands/git-alt
|
||||
edit: material/pencil
|
||||
view: material/eye
|
||||
|
||||
features:
|
||||
- navigation.instant
|
||||
- navigation.tracking
|
||||
- navigation.tabs
|
||||
- navigation.indexes
|
||||
- navigation.expand
|
||||
- navigation.sections
|
||||
- navigation.path
|
||||
- navigation.top
|
||||
- search.suggest
|
||||
- search.highlight
|
||||
- search.share
|
||||
- content.tabs.link
|
||||
- content.code.copy
|
||||
|
||||
extra:
|
||||
generator: false
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/Snider/Core
|
||||
- icon: fontawesome/solid/globe
|
||||
link: https://dappco.re
|
||||
|
||||
extra_css:
|
||||
- assets/stylesheets/extra.css
|
||||
|
||||
|
||||
plugins:
|
||||
- offline:
|
||||
- privacy:
|
||||
- group:
|
||||
enabled: !ENV CI
|
||||
plugins:
|
||||
- git-revision-date-localized:
|
||||
type: timeago
|
||||
enable_creation_date: true
|
||||
fallback_to_build_date: true
|
||||
tz: Europe/London
|
||||
- git-committers:
|
||||
- group:
|
||||
enabled: !ENV INSIDERS
|
||||
plugins:
|
||||
- optimise
|
||||
- search:
|
||||
lang:
|
||||
- en
|
||||
|
||||
markdown_extensions:
|
||||
- abbr
|
||||
- admonition
|
||||
- attr_list
|
||||
- def_list
|
||||
- footnotes
|
||||
- meta
|
||||
- toc:
|
||||
permalink: true
|
||||
- tables
|
||||
- md_in_html
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
line_spans: __span
|
||||
pygments_lang_class: true
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences:
|
||||
custom_fences:
|
||||
- name: mermaid
|
||||
class: mermaid
|
||||
format: !!python/name:pymdownx.superfences.fence_code_format
|
||||
- pymdownx.betterem
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
|
|
@ -1 +0,0 @@
|
|||
mkdocs-material
|
||||
|
Before Width: | Height: | Size: 2.1 MiB |
|
Before Width: | Height: | Size: 695 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 756 B |
|
Before Width: | Height: | Size: 582 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
|
@ -1,78 +0,0 @@
|
|||
---
|
||||
title: Core.Help
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
Core is an opinionated framework for building Go desktop apps with Wails, providing a small set of focused modules you can mix into your app. It ships with sensible defaults and a demo app that doubles as in‑app help.
|
||||
|
||||
- Site: [https://dappco.re](https://dappco.re)
|
||||
- Repo: [https://github.com/Snider/Core](https://github.com/Snider/Core)
|
||||
|
||||
## Modules
|
||||
|
||||
- Core — framework bootstrap and service container
|
||||
- Core.Config — app and UI state persistence
|
||||
- Core.Crypt — keys, encrypt/decrypt, sign/verify
|
||||
- Core.Display — windows, tray, window state
|
||||
- Core.Help — in‑app help and deep‑links
|
||||
- Core.IO — local/remote filesystem helpers
|
||||
- Core.Workspace — projects and paths
|
||||
|
||||
## Quick start
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
core "github.com/Snider/Core"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := core.New(
|
||||
core.WithServiceLock(),
|
||||
)
|
||||
wailsApp := application.NewWithOptions(&application.Options{
|
||||
Bind: []interface{}{app},
|
||||
})
|
||||
wailsApp.Run()
|
||||
}
|
||||
```
|
||||
|
||||
## Services
|
||||
```go
|
||||
package demo
|
||||
|
||||
import (
|
||||
core "github.com/Snider/Core"
|
||||
)
|
||||
|
||||
// Register your service
|
||||
func Register(c *core.Core) error {
|
||||
return c.RegisterService("demo", &Demo{core: c})
|
||||
}
|
||||
```
|
||||
|
||||
## Display example
|
||||
```go
|
||||
package display
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// Open a window on startup
|
||||
func (d *API) ServiceStartup(ctx context.Context, _ application.ServiceOptions) error {
|
||||
d.OpenWindow(
|
||||
OptName("main"),
|
||||
OptHeight(900),
|
||||
OptWidth(1280),
|
||||
OptURL("/"),
|
||||
OptTitle("Core"),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
See the left nav for detailed pages on each module.
|
||||
|
|
@ -1,367 +0,0 @@
|
|||
[data-md-color-scheme="lethean"] {
|
||||
--md-primary-fg-color: #0F131C;
|
||||
}
|
||||
|
||||
.hero-section {
|
||||
background: linear-gradient(135deg, #0F131C 0%, #1a237e 100%);
|
||||
color: white;
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.hero-content h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
color: white;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 2rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.hero-badges {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.badge {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 20px;
|
||||
margin: 0 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
display: inline-block;
|
||||
background: #4A90E2;
|
||||
color: white;
|
||||
padding: 0.8rem 2rem;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: background 0.3s, transform 0.3s;
|
||||
}
|
||||
|
||||
.cta-button:hover {
|
||||
background: #357ABD;
|
||||
color: white;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.cta-button.secondary {
|
||||
background: transparent;
|
||||
border: 2px solid #4A90E2;
|
||||
color: #4A90E2;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 0.2rem;
|
||||
padding: 0.2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 1.0rem;
|
||||
border: 2px solid #e2e8f0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .feature-card {
|
||||
background: #2d3748;
|
||||
border-color: #4a5568;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.feature-card img {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
margin: 1rem 0;
|
||||
color: #0F131C;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .feature-card h3 {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.get-started {
|
||||
color: #4A90E2;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.benefits-section {
|
||||
background: #f5f5f5;
|
||||
padding: 0.4rem 0.2rem;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.benefits-section h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-top: 0.8rem;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .benefits-section {
|
||||
background: #1a202c;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 0.2rem;
|
||||
padding: 0.2rem;
|
||||
margin: 0.2rem auto;
|
||||
}
|
||||
|
||||
.benefit-card {
|
||||
background: white;
|
||||
padding: 0.5rem;
|
||||
border-radius: 8px;
|
||||
border: 2px solid #e2e8f0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .benefit-card {
|
||||
background: #2d3748;
|
||||
border-color: #4a5568;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.roadmap-section {
|
||||
padding: 0.4rem 0.2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2rem;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
background: white;
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
border: 2px solid #e2e8f0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
position: relative;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.timeline-item.completed {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .timeline-item {
|
||||
background: #2d3748;
|
||||
border-color: #4a5568;
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.timeline-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.timeline-marker {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.timeline-item.planning .timeline-marker {
|
||||
background: #718096;
|
||||
}
|
||||
|
||||
.timeline-item.in-progress .timeline-marker {
|
||||
background: #4A90E2;
|
||||
}
|
||||
|
||||
.timeline-item.completed .timeline-marker {
|
||||
background: #48BB78;
|
||||
}
|
||||
|
||||
.timeline-item ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timeline-item li {
|
||||
margin: 0.5rem 0;
|
||||
padding-left: 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timeline-item li::before {
|
||||
content: "";
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.timeline-item li.planned::before {
|
||||
background: #718096;
|
||||
}
|
||||
|
||||
.timeline-item li.active::before {
|
||||
background: #4A90E2;
|
||||
}
|
||||
|
||||
.timeline-item li.completed::before {
|
||||
background: #48BB78;
|
||||
}
|
||||
|
||||
.timeline-item li ul {
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.timeline-item li ul li {
|
||||
font-size: 0.9rem;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
.timeline-item li ul li::before {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #a0aec0;
|
||||
}
|
||||
|
||||
.timeline-item li ul li a {
|
||||
color: #4A90E2;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.timeline-item li ul li a:hover {
|
||||
color: #357ABD;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .timeline-item li ul li a {
|
||||
color: #63b3ed;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .timeline-item li ul li a:hover {
|
||||
color: #90cdf4;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 0.8rem;
|
||||
color: #718096;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="slate"] .date {
|
||||
color: #a0aec0;
|
||||
}
|
||||
|
||||
.cta-section {
|
||||
background: #0F131C;
|
||||
color: white;
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.community-section {
|
||||
padding: 4rem 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.community-links {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
justify-content: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.community-link {
|
||||
color: #4A90E2;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.community-link:hover {
|
||||
color: #357ABD;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-content h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.timeline-item.completed {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.community-links {
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
version: '3'
|
||||
|
||||
tasks:
|
||||
default:
|
||||
cmds:
|
||||
- task: dev
|
||||
desc: "Start the development server."
|
||||
|
||||
install:
|
||||
cmds:
|
||||
- pip install -r requirements.txt
|
||||
desc: "Install documentation dependencies."
|
||||
status:
|
||||
- test -f requirements.txt
|
||||
|
||||
dev:
|
||||
run: always
|
||||
cmds:
|
||||
- mkdocs serve -o -c -w src -w mkdocs.yml
|
||||
desc: "Start the live-reloading documentation server."
|
||||
sources:
|
||||
- mkdocs.yml
|
||||
- "src/**/*"
|
||||
- "src/**/*.css"
|
||||
generates:
|
||||
- "public/**/*"
|
||||
|
||||
build:
|
||||
cmds:
|
||||
- mkdocs build --clean -d public
|
||||
desc: "Build the static documentation site."
|
||||
|
||||
deploy:
|
||||
desc: "Deploy the documentation to GitHub Pages."
|
||||
cmds:
|
||||
- mkdocs gh-deploy --force
|
||||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/Snider/Core/pkg/core"
|
||||
"github.com/Snider/Core/pkg/crypt"
|
||||
"github.com/Snider/Core/pkg/display"
|
||||
"github.com/Snider/Core/pkg/help"
|
||||
"github.com/Snider/Core/pkg/i18n"
|
||||
"github.com/Snider/Core/pkg/workspace"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
|
|
@ -21,7 +20,6 @@ type Runtime struct {
|
|||
Core *core.Core
|
||||
Config *config.Service
|
||||
Display *display.Service
|
||||
Help *help.Service
|
||||
Crypt *crypt.Service
|
||||
I18n *i18n.Service
|
||||
Workspace *workspace.Service
|
||||
|
|
@ -37,7 +35,7 @@ func NewWithFactories(app *application.App, factories map[string]ServiceFactory)
|
|||
core.WithWails(app),
|
||||
}
|
||||
|
||||
for _, name := range []string{"config", "display", "help", "crypt", "i18n", "workspace"} {
|
||||
for _, name := range []string{"config", "display", "crypt", "i18n", "workspace"} {
|
||||
factory, ok := factories[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("service %s factory not provided", name)
|
||||
|
|
@ -65,10 +63,6 @@ func NewWithFactories(app *application.App, factories map[string]ServiceFactory)
|
|||
if !ok {
|
||||
return nil, fmt.Errorf("display service has unexpected type")
|
||||
}
|
||||
helpSvc, ok := services["help"].(*help.Service)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("help service has unexpected type")
|
||||
}
|
||||
cryptSvc, ok := services["crypt"].(*crypt.Service)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("crypt service has unexpected type")
|
||||
|
|
@ -87,7 +81,6 @@ func NewWithFactories(app *application.App, factories map[string]ServiceFactory)
|
|||
Core: coreInstance,
|
||||
Config: configSvc,
|
||||
Display: displaySvc,
|
||||
Help: helpSvc,
|
||||
Crypt: cryptSvc,
|
||||
I18n: i18nSvc,
|
||||
Workspace: workspaceSvc,
|
||||
|
|
@ -101,7 +94,6 @@ func New(app *application.App) (*Runtime, error) {
|
|||
return NewWithFactories(app, map[string]ServiceFactory{
|
||||
"config": func() (any, error) { return config.New() },
|
||||
"display": func() (any, error) { return display.New() },
|
||||
"help": func() (any, error) { return help.New() },
|
||||
"crypt": func() (any, error) { return crypt.New() },
|
||||
"i18n": func() (any, error) { return i18n.New() },
|
||||
"workspace": func() (any, error) { return workspace.New() },
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/Snider/Core/pkg/config"
|
||||
"github.com/Snider/Core/pkg/crypt"
|
||||
"github.com/Snider/Core/pkg/display"
|
||||
"github.com/Snider/Core/pkg/help"
|
||||
"github.com/Snider/Core/pkg/i18n"
|
||||
"github.com/Snider/Core/pkg/runtime"
|
||||
"github.com/Snider/Core/pkg/workspace"
|
||||
|
|
@ -30,7 +29,6 @@ func TestNew(t *testing.T) {
|
|||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
|
|
@ -41,7 +39,6 @@ func TestNew(t *testing.T) {
|
|||
assert.NotNil(t, rt.Core)
|
||||
assert.NotNil(t, rt.Config)
|
||||
assert.NotNil(t, rt.Display)
|
||||
assert.NotNil(t, rt.Help)
|
||||
assert.NotNil(t, rt.Crypt)
|
||||
assert.NotNil(t, rt.I18n)
|
||||
assert.NotNil(t, rt.Workspace)
|
||||
|
|
@ -53,7 +50,6 @@ func TestNew(t *testing.T) {
|
|||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return nil, errors.New("crypt service failed") },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
|
|
@ -67,7 +63,6 @@ func TestNew(t *testing.T) {
|
|||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return "not a display service", nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
|
|
@ -81,7 +76,6 @@ func TestNew(t *testing.T) {
|
|||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
|
|
|
|||