lepus

    A modern desktop application framework based on web technologies.

    webview
    desktop
    app
    framework
    Download zip
    Version
    0.1.9
    License
    Apache-2.0
    Last updated
    7 hours ago
    Downloads
    56

    #Lepus

    Lepus is a desktop application toolkit for MoonBit.

    It provides:

    • a native MoonBit application host
    • a WebView-based rendering runtime
    • a plugin system for exposing platform features to frontend code
    • a MoonBit CLI for scaffolding and local workflows

    #Status

    Lepus is still in an early stage.

    What is already in this repository:

    What is not finished yet:

    • many plugins are still example-backed or placeholders
    • dev and build are still being expanded
    • packaging and distribution are not production-ready yet

    #Quick Start

    #Requirements

    You need:

    • moon
    • a native toolchain that can build MoonBit native targets
    • a local environment where the bundled webview library can be loaded

    Check your environment:

    moon run --target native cli/lepus -- doctor

    #Run an Example

    Run the basic example:

    moon run --target native examples/hello

    Run a plugin example:

    moon run --target native examples/dialog

    #Create a New App

    moon run --target native cli/lepus -- init my-app

    #API

    The current top-level API is centered around:

    • WindowConfig::new(...)
    • App::new(main_window, plugins?)
    • App::with_windows(windows, plugins?)
    • App::add_window(config)

    Minimal app:

    ///|
    async fn main {
    let main_window = @lepus.WindowConfig::new(
    title="Hello Lepus",
    html=(
    #|<!doctype html>
    #|<html><body><h1>Hello Lepus</h1></body></html>,
    ),
    )
    @lepus.App(main_window).run()
    }

    Plugin-enabled app:

    ///|
    async fn main {
    let main_window = @lepus.WindowConfig::new(
    title="Dialog Example",
    html=@lepus_plugin_support.example_html("dialog", "Dialog Plugin Example"),
    )
    @lepus.App(main_window, plugins=[@lepus_plugin_dialog.plugin()]).run()
    }

    Window customization example:

    ///|
    async fn main {
    let window = @lepus.WindowConfig::new(
    title="Custom Window",
    frameless=true,
    transparent=true,
    title_bar_style=1, // hidden
    title_bar_overlay=true, // overlay controls
    html="<div class='lepus-titlebar'>Drag me</div>",
    )
    @lepus.App(window).run()
    }

    #Plugins

    Plugins live in plugins/.

    Each plugin package exports:

    • plugin()

    Each example installs plugins through:

    • plugins=[@lepus_plugin_x.plugin()]

    The current plugin status matrix is in PLUGINS.md.

    #Repository Layout

    . ├── cli/lepus/ # CLI implementation ├── examples/ # runnable native examples ├── plugins/ # official plugin packages ├── webview/ # WebView runtime and bridge ├── lepus.mbt # top-level Lepus API ├── moon.pkg # root package definition └── moon.mod

    #Development

    Useful commands:

    moon check moon test --target native -p lepus-apps/lepus/webview moon info && moon fmt

    CLI help:

    moon run --target native cli/lepus -- --help

    #License

    App

    pub struct App {
    windows : Array[WindowConfig]
    plugins : Array[
    Plugin
    ]
    }

    App::add_window

    fn App::add_window(self : App, config : WindowConfig) -> Unit

    App::new

    App::run

    async fn App::run(self : App, window_index? : Int) -> Unit

    App::window_count

    fn App::window_count(self : App) -> Int

    App::with_windows

    fn App::with_windows(windows : Array[WindowConfig], plugins? : Array[
    Plugin
    ]) -> App

    MemoryFile

    pub struct MemoryFile {
    path : String
    content : Bytes
    } derive(Eq, Hash, ToJson,
    Debug
    ,
    FromJson
    )

    MemoryFile::equal

    fn MemoryFile::equal(MemoryFile, MemoryFile) -> Bool

    MemoryFile::from_bytes

    fn MemoryFile::from_bytes(path : String, content : Bytes) -> MemoryFile

    MemoryFile::from_string

    fn MemoryFile::from_string(path : String, content : String) -> MemoryFile

    MemoryFile::hash

    fn MemoryFile::hash(self : MemoryFile) -> Int

    MemoryFile::hash_combine

    fn MemoryFile::hash_combine(MemoryFile, Hasher) -> Unit

    MemoryFile::not_equal

    fn MemoryFile::not_equal(x : MemoryFile, y : MemoryFile) -> Bool

    MemoryFile::to_json

    fn MemoryFile::to_json(MemoryFile) -> Json

    MemorySource

    pub struct MemorySource {
    entry : String
    files : Array[MemoryFile]
    } derive(Eq, Hash, ToJson,
    Debug
    ,
    FromJson
    )

    MemorySource::MemorySource

    #alias(new, deprecated="Use `MemorySource()` instead")
    fn MemorySource::MemorySource(files : Array[MemoryFile], entry? : String) -> MemorySource

    MemorySource::equal

    MemorySource::hash

    fn MemorySource::hash(self : MemorySource) -> Int

    MemorySource::hash_combine

    fn MemorySource::hash_combine(MemorySource, Hasher) -> Unit

    MemorySource::not_equal

    fn MemorySource::not_equal(x : MemorySource, y : MemorySource) -> Bool

    MemorySource::to_json

    Source

    pub(all) enum Source {
    Url(String)
    Local(String)
    Memory(MemorySource)
    } derive(Eq, Hash, ToJson,
    Debug
    ,
    FromJson
    )

    Source::equal

    fn Source::equal(Source, Source) -> Bool

    Source::hash

    fn Source::hash(self : Source) -> Int

    Source::hash_combine

    fn Source::hash_combine(Source, Hasher) -> Unit

    Source::html

    fn Source::html(html : String) -> Source

    Source::not_equal

    fn Source::not_equal(x : Source, y : Source) -> Bool

    Source::to_json

    fn Source::to_json(Source) -> Json

    Source::to_repr

    Source::zip

    fn Source::zip(zip : Bytes) -> Source raise

    TitleBarStyle

    pub enum TitleBarStyle {
    Default
    Hidden
    } derive(Eq, Hash, ToJson,
    Debug
    ,
    FromJson
    )

    TitleBarStyle::equal

    TitleBarStyle::hash

    fn TitleBarStyle::hash(self : TitleBarStyle) -> Int

    TitleBarStyle::hash_combine

    fn TitleBarStyle::hash_combine(TitleBarStyle, Hasher) -> Unit

    TitleBarStyle::not_equal

    fn TitleBarStyle::not_equal(x : TitleBarStyle, y : TitleBarStyle) -> Bool

    TitleBarStyle::to_json

    Window

    pub struct Window {
    config : WindowConfig
    plugins : Array[
    Plugin
    ]
    }

    Window::Window

    #alias(new, deprecated="Use `Window()` instead")
    fn Window::Window(title? : String, width? : Int, height? : Int, debug? : Int, devtools? : Bool, frameless? : Bool, resizable? : Bool, always_on_top? : Bool, transparent? : Bool, title_bar_style? : TitleBarStyle, title_bar_overlay? : Bool, traffic_light_position? : (Int, Int), source? : Source, plugins? : Array[
    Plugin
    ]) -> Window

    Window::navigate

    fn Window::navigate(self : Window, url : String) -> Window

    Window::run

    async fn Window::run(self : Window) -> Unit

    Window::set_source

    fn Window::set_source(self : Window, source : Source) -> Window

    WindowConfig

    pub struct WindowConfig {
    title : String
    width : Int
    height : Int
    debug : Int
    devtools : Bool
    frameless : Bool
    resizable : Bool
    always_on_top : Bool
    transparent : Bool
    title_bar_style : TitleBarStyle
    title_bar_overlay : Bool
    traffic_light_position : (Int, Int)
    source : Source?
    } derive(Eq, Hash, ToJson,
    Debug
    ,
    FromJson
    )

    WindowConfig::equal

    WindowConfig::hash

    fn WindowConfig::hash(self : WindowConfig) -> Int

    WindowConfig::hash_combine

    fn WindowConfig::hash_combine(WindowConfig, Hasher) -> Unit

    WindowConfig::navigate

    fn WindowConfig::navigate(self : WindowConfig, url : String) -> WindowConfig

    WindowConfig::new

    fn WindowConfig::new(title? : String, width? : Int, height? : Int, debug? : Int, devtools? : Bool, frameless? : Bool, resizable? : Bool, always_on_top? : Bool, transparent? : Bool, title_bar_style? : TitleBarStyle, title_bar_overlay? : Bool, traffic_light_position? : (Int, Int), source? : Source) -> WindowConfig

    WindowConfig::not_equal

    fn WindowConfig::not_equal(x : WindowConfig, y : WindowConfig) -> Bool

    WindowConfig::set_source

    fn WindowConfig::set_source(self : WindowConfig, source : Source) -> WindowConfig

    WindowConfig::to_json