selectable releases
This commit is contained in:
97
.github/workflows/release.yml
vendored
97
.github/workflows/release.yml
vendored
@@ -74,6 +74,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
chmod +x scripts/generate_docs.sh
|
chmod +x scripts/generate_docs.sh
|
||||||
chmod +x scripts/create-release.sh
|
chmod +x scripts/create-release.sh
|
||||||
|
chmod +x scripts/create-profile-packages.sh
|
||||||
chmod +x scripts/archive-docs.sh
|
chmod +x scripts/archive-docs.sh
|
||||||
|
|
||||||
- name: Archive previous documentation version
|
- name: Archive previous documentation version
|
||||||
@@ -111,29 +112,32 @@ jobs:
|
|||||||
git commit -m "Archive previous documentation and generate v${{ steps.version.outputs.version }} docs [skip ci]" || echo "No changes to commit"
|
git commit -m "Archive previous documentation and generate v${{ steps.version.outputs.version }} docs [skip ci]" || echo "No changes to commit"
|
||||||
git push origin HEAD:main || echo "Nothing to push"
|
git push origin HEAD:main || echo "Nothing to push"
|
||||||
|
|
||||||
- name: Create release package
|
- name: Create release packages
|
||||||
run: |
|
run: |
|
||||||
# Run release script non-interactively (auto-confirm overwrite)
|
# Create all 4 profile packages
|
||||||
echo "y" | ./scripts/create-release.sh || ./scripts/create-release.sh
|
./scripts/create-profile-packages.sh
|
||||||
# Verify files were created
|
|
||||||
|
# Verify all packages were created
|
||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
if [ ! -f "releases/flexlove-v${VERSION}.zip" ]; then
|
for profile in minimal slim default full; do
|
||||||
echo "Error: Release zip was not created"
|
if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip" ]; then
|
||||||
exit 1
|
echo "Error: ${profile} profile package was not created"
|
||||||
fi
|
exit 1
|
||||||
if [ ! -f "releases/flexlove-v${VERSION}.zip.sha256" ]; then
|
fi
|
||||||
echo "Error: Checksum file was not created"
|
if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip.sha256" ]; then
|
||||||
exit 1
|
echo "Error: ${profile} checksum file was not created"
|
||||||
fi
|
exit 1
|
||||||
echo "✓ Release package created successfully"
|
fi
|
||||||
|
done
|
||||||
|
echo "✓ All profile packages created successfully"
|
||||||
|
|
||||||
- name: Upload release artifacts
|
- name: Upload release artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-assets
|
name: release-assets
|
||||||
path: |
|
path: |
|
||||||
releases/flexlove-v${{ steps.version.outputs.version }}.zip
|
releases/flexlove-*-v${{ steps.version.outputs.version }}.zip
|
||||||
releases/flexlove-v${{ steps.version.outputs.version }}.zip.sha256
|
releases/flexlove-*-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
docs/api.html
|
docs/api.html
|
||||||
retention-days: 90
|
retention-days: 90
|
||||||
|
|
||||||
@@ -143,13 +147,19 @@ jobs:
|
|||||||
name: release-assets
|
name: release-assets
|
||||||
path: ./
|
path: ./
|
||||||
|
|
||||||
- name: Extract checksum for release notes
|
- name: Extract checksums for release notes
|
||||||
id: checksum
|
id: checksums
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
CHECKSUM=$(cat "releases/flexlove-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
MINIMAL_CHECKSUM=$(cat "releases/flexlove-minimal-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT
|
SLIM_CHECKSUM=$(cat "releases/flexlove-slim-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
echo "Checksum: $CHECKSUM"
|
DEFAULT_CHECKSUM=$(cat "releases/flexlove-default-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
FULL_CHECKSUM=$(cat "releases/flexlove-full-v${VERSION}.zip.sha256" | cut -d ' ' -f 1)
|
||||||
|
|
||||||
|
echo "minimal=$MINIMAL_CHECKSUM" >> $GITHUB_OUTPUT
|
||||||
|
echo "slim=$SLIM_CHECKSUM" >> $GITHUB_OUTPUT
|
||||||
|
echo "default=$DEFAULT_CHECKSUM" >> $GITHUB_OUTPUT
|
||||||
|
echo "full=$FULL_CHECKSUM" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Check if pre-release
|
- name: Check if pre-release
|
||||||
id: prerelease
|
id: prerelease
|
||||||
@@ -167,41 +177,58 @@ jobs:
|
|||||||
id: release_notes
|
id: release_notes
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
CHECKSUM="${{ steps.checksum.outputs.checksum }}"
|
|
||||||
cat > release_notes.md << 'EOF'
|
cat > release_notes.md << 'EOF'
|
||||||
|
## Build Profiles
|
||||||
|
|
||||||
|
FlexLöve is now available in 4 different build profiles to optimize bundle size for your needs:
|
||||||
|
|
||||||
|
| Profile | Size | Description | Package |
|
||||||
|
|---------|------|-------------|---------|
|
||||||
|
| **Minimal** | ~60% | Core functionality only | `flexlove-minimal-v${{ steps.version.outputs.version }}.zip` |
|
||||||
|
| **Slim** | ~80% | + Animation and Image support | `flexlove-slim-v${{ steps.version.outputs.version }}.zip` |
|
||||||
|
| **Default** | ~95% | + Theme and Blur effects | `flexlove-default-v${{ steps.version.outputs.version }}.zip` |
|
||||||
|
| **Full** | 100% | All modules including debugging tools | `flexlove-full-v${{ steps.version.outputs.version }}.zip` |
|
||||||
|
|
||||||
|
**Choose the profile that matches your needs!** See the [Build Profiles Documentation](https://github.com/${{ github.repository }}/blob/main/docs/BUILD_PROFILES.md) for detailed module listings.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Download `flexlove-v${{ steps.version.outputs.version }}.zip` and extract to your LÖVE2D project:
|
Download your preferred profile package and extract to your LÖVE2D project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
unzip flexlove-v${{ steps.version.outputs.version }}.zip
|
# Example: Install the default profile
|
||||||
|
unzip flexlove-default-v${{ steps.version.outputs.version }}.zip
|
||||||
cp -r flexlove/modules ./
|
cp -r flexlove/modules ./
|
||||||
cp flexlove/FlexLove.lua ./
|
cp flexlove/FlexLove.lua ./
|
||||||
```
|
```
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
Verify the download integrity using SHA256:
|
Verify download integrity using SHA256:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
shasum -a 256 -c flexlove-v${{ steps.version.outputs.version }}.zip.sha256
|
shasum -a 256 -c flexlove-<profile>-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
```
|
```
|
||||||
|
|
||||||
**SHA256 Checksum:**
|
**SHA256 Checksums:**
|
||||||
```
|
```
|
||||||
${{ steps.checksum.outputs.checksum }}
|
Minimal: ${{ steps.checksums.outputs.minimal }}
|
||||||
|
Slim: ${{ steps.checksums.outputs.slim }}
|
||||||
|
Default: ${{ steps.checksums.outputs.default }}
|
||||||
|
Full: ${{ steps.checksums.outputs.full }}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
📚 [View Documentation](https://mikefreno.github.io/FlexLove/)
|
📚 [View Full Documentation](https://mikefreno.github.io/FlexLove/)
|
||||||
|
|
||||||
## What's Included
|
## What's Included
|
||||||
|
|
||||||
|
Each package contains:
|
||||||
- `FlexLove.lua` - Main library file
|
- `FlexLove.lua` - Main library file
|
||||||
- `modules/` - All required module files
|
- `modules/` - Profile-specific module files
|
||||||
- `LICENSE` - MIT License
|
- `LICENSE` - MIT License
|
||||||
- `README.md`
|
- `README.md` - Profile-specific readme
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -220,8 +247,14 @@ jobs:
|
|||||||
name: FlexLöve v${{ steps.version.outputs.version }}
|
name: FlexLöve v${{ steps.version.outputs.version }}
|
||||||
body_path: release_notes.md
|
body_path: release_notes.md
|
||||||
files: |
|
files: |
|
||||||
releases/flexlove-v${{ steps.version.outputs.version }}.zip
|
releases/flexlove-minimal-v${{ steps.version.outputs.version }}.zip
|
||||||
releases/flexlove-v${{ steps.version.outputs.version }}.zip.sha256
|
releases/flexlove-minimal-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
|
releases/flexlove-slim-v${{ steps.version.outputs.version }}.zip
|
||||||
|
releases/flexlove-slim-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
|
releases/flexlove-default-v${{ steps.version.outputs.version }}.zip
|
||||||
|
releases/flexlove-default-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
|
releases/flexlove-full-v${{ steps.version.outputs.version }}.zip
|
||||||
|
releases/flexlove-full-v${{ steps.version.outputs.version }}.zip.sha256
|
||||||
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
|
prerelease: ${{ steps.prerelease.outputs.is_prerelease }}
|
||||||
draft: false
|
draft: false
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -3,15 +3,11 @@ local function req(name)
|
|||||||
return require(modulePath .. "modules." .. name)
|
return require(modulePath .. "modules." .. name)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Load ErrorHandler first (required for ModuleLoader)
|
|
||||||
---@type ErrorHandler
|
---@type ErrorHandler
|
||||||
local ErrorHandler = req("ErrorHandler")
|
local ErrorHandler = req("ErrorHandler")
|
||||||
|
|
||||||
-- Load ModuleLoader
|
|
||||||
local ModuleLoader = req("ModuleLoader")
|
local ModuleLoader = req("ModuleLoader")
|
||||||
ModuleLoader.init({ ErrorHandler = ErrorHandler })
|
ModuleLoader.init({ ErrorHandler = ErrorHandler })
|
||||||
|
|
||||||
-- Helper function for safe module loading
|
|
||||||
local function safeReq(name, isOptional)
|
local function safeReq(name, isOptional)
|
||||||
return ModuleLoader.safeRequire(modulePath .. "modules." .. name, isOptional)
|
return ModuleLoader.safeRequire(modulePath .. "modules." .. name, isOptional)
|
||||||
end
|
end
|
||||||
@@ -373,7 +369,7 @@ function flexlove.beginFrame()
|
|||||||
end
|
end
|
||||||
elem:_cleanup()
|
elem:_cleanup()
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, element in ipairs(flexlove._currentFrameElements) do
|
for _, element in ipairs(flexlove._currentFrameElements) do
|
||||||
if not element.parent then
|
if not element.parent then
|
||||||
cleanupChildren(element)
|
cleanupChildren(element)
|
||||||
@@ -428,7 +424,7 @@ function flexlove.endFrame()
|
|||||||
stateUpdate[k] = v
|
stateUpdate[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
stateUpdate._focused = element._focused
|
stateUpdate._focused = element._focused
|
||||||
stateUpdate._cursorPosition = element._cursorPosition
|
stateUpdate._cursorPosition = element._cursorPosition
|
||||||
stateUpdate._selectionStart = element._selectionStart
|
stateUpdate._selectionStart = element._selectionStart
|
||||||
|
|||||||
30
README.md
30
README.md
@@ -65,6 +65,36 @@ function love.draw()
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Build Profiles
|
||||||
|
|
||||||
|
FlexLöve supports optional modules to reduce bundle size for different use cases. Simply exclude module files you don't need - the library handles missing modules gracefully with null-object stubs.
|
||||||
|
|
||||||
|
### Available Profiles
|
||||||
|
|
||||||
|
- **Minimal (~60%)** - Core functionality only (layouts, basic elements, text)
|
||||||
|
- **Slim (~80%)** - Adds animations and image support
|
||||||
|
- **Default (~95%)** - Adds themes, blur effects, and gestures
|
||||||
|
- **Full (100%)** - Everything including performance monitoring
|
||||||
|
|
||||||
|
### Example: Minimal Build
|
||||||
|
|
||||||
|
For a lightweight build, exclude these optional module files:
|
||||||
|
```
|
||||||
|
modules/Animation.lua
|
||||||
|
modules/Theme.lua
|
||||||
|
modules/Blur.lua
|
||||||
|
modules/ImageRenderer.lua
|
||||||
|
modules/ImageScaler.lua
|
||||||
|
modules/ImageCache.lua
|
||||||
|
modules/NinePatch.lua
|
||||||
|
modules/GestureRecognizer.lua
|
||||||
|
modules/Performance.lua
|
||||||
|
```
|
||||||
|
|
||||||
|
The library automatically detects missing modules and provides safe no-op stubs. No code changes needed!
|
||||||
|
|
||||||
|
📖 **See [BUILD_PROFILES.md](./docs/BUILD_PROFILES.md) and [MODULE_DEPENDENCIES.md](./docs/MODULE_DEPENDENCIES.md) for detailed information.**
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
📚 **[View Full API Documentation](https://mikefreno.github.io/FlexLove/api.html)**
|
📚 **[View Full API Documentation](https://mikefreno.github.io/FlexLove/api.html)**
|
||||||
|
|||||||
87
RELEASE.md
87
RELEASE.md
@@ -23,8 +23,8 @@ This interactive script will:
|
|||||||
After pushing the tag, GitHub Actions automatically:
|
After pushing the tag, GitHub Actions automatically:
|
||||||
- Archives previous documentation
|
- Archives previous documentation
|
||||||
- Generates new documentation
|
- Generates new documentation
|
||||||
- Creates release package with SHA256 checksums
|
- Creates 4 build profile packages (minimal, slim, default, full) with SHA256 checksums
|
||||||
- Publishes GitHub release with download assets
|
- Publishes GitHub release with all profile packages
|
||||||
|
|
||||||
### Example Usage
|
### Example Usage
|
||||||
|
|
||||||
@@ -99,24 +99,26 @@ git push && git push origin v0.3.0
|
|||||||
|
|
||||||
Once you push the tag, the automated workflow handles everything else.
|
Once you push the tag, the automated workflow handles everything else.
|
||||||
|
|
||||||
## Local Release Package (Optional)
|
## Local Release Packages (Optional)
|
||||||
|
|
||||||
To create a local release package without GitHub Actions:
|
To create local release packages without GitHub Actions:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./scripts/create-release.sh
|
./scripts/create-profile-packages.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Output files:
|
Output files (for version 0.3.0):
|
||||||
- `releases/flexlove-v{version}.zip`
|
- `releases/flexlove-minimal-v0.3.0.zip` + `.sha256`
|
||||||
- `releases/flexlove-v{version}.zip.sha256`
|
- `releases/flexlove-slim-v0.3.0.zip` + `.sha256`
|
||||||
|
- `releases/flexlove-default-v0.3.0.zip` + `.sha256`
|
||||||
|
- `releases/flexlove-full-v0.3.0.zip` + `.sha256`
|
||||||
|
|
||||||
### Verify Local Package
|
### Verify Local Packages
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd releases
|
cd releases
|
||||||
shasum -a 256 -c flexlove-v0.3.0.zip.sha256
|
shasum -a 256 -c flexlove-*-v0.3.0.zip.sha256
|
||||||
# Expected: flexlove-v0.3.0.zip: OK
|
# Expected: All packages report OK
|
||||||
```
|
```
|
||||||
|
|
||||||
## Release Checklist
|
## Release Checklist
|
||||||
@@ -124,11 +126,11 @@ shasum -a 256 -c flexlove-v0.3.0.zip.sha256
|
|||||||
- [ ] Version updated in `FlexLove.lua`
|
- [ ] Version updated in `FlexLove.lua`
|
||||||
- [ ] Documentation regenerated (`./scripts/generate_docs.sh`)
|
- [ ] Documentation regenerated (`./scripts/generate_docs.sh`)
|
||||||
- [ ] Changes committed and pushed
|
- [ ] Changes committed and pushed
|
||||||
- [ ] Release package created (`./scripts/create-release.sh`)
|
- [ ] Profile packages created (`./scripts/create-profile-packages.sh`)
|
||||||
- [ ] Checksum verified (`shasum -a 256 -c *.sha256`)
|
- [ ] All checksums verified (`cd releases && shasum -a 256 -c *.sha256`)
|
||||||
- [ ] Release package tested
|
- [ ] All profile packages tested
|
||||||
- [ ] Git tag created and pushed
|
- [ ] Git tag created and pushed
|
||||||
- [ ] GitHub release published with zip and checksum files
|
- [ ] GitHub release published with all 4 profile packages and checksums
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|
||||||
@@ -142,61 +144,72 @@ Example: `0.2.0` → `0.2.1` (bug fix) or `0.3.0` (new feature)
|
|||||||
|
|
||||||
## What Gets Released
|
## What Gets Released
|
||||||
|
|
||||||
The release package includes **only** the files needed to use FlexLöve:
|
FlexLöve is released as **4 separate profile packages**, each optimized for different use cases:
|
||||||
|
|
||||||
|
### Profile Packages
|
||||||
|
|
||||||
|
Each profile package includes:
|
||||||
|
|
||||||
✅ **Included:**
|
✅ **Included:**
|
||||||
- `FlexLove.lua` - Main library
|
- `FlexLove.lua` - Main library
|
||||||
- `modules/` - All module files
|
- `modules/` - Profile-specific module files only
|
||||||
- `LICENSE` - License terms
|
- `LICENSE` - License terms
|
||||||
- `README.md` - Installation instructions
|
- `README.md` - Profile-specific installation instructions
|
||||||
|
- `themes/` - (default and full profiles only)
|
||||||
|
|
||||||
❌ **Not included:**
|
❌ **Not included:**
|
||||||
- `docs/` - Documentation (hosted on GitHub Pages)
|
- `docs/` - Documentation (hosted on GitHub Pages)
|
||||||
- `examples/` - Example code (available in repository)
|
- `examples/` - Example code (available in repository)
|
||||||
- `testing/` - Test suite
|
- `testing/` - Test suite
|
||||||
- `themes/` - Theme examples
|
|
||||||
- Development tools
|
- Development tools
|
||||||
|
|
||||||
|
### Package Sizes
|
||||||
|
|
||||||
|
| Profile | Modules | Approximate Size |
|
||||||
|
|---------|---------|------------------|
|
||||||
|
| **Minimal** | 16 core modules | ~60% of full |
|
||||||
|
| **Slim** | 21 modules | ~80% of full |
|
||||||
|
| **Default** | 23 modules + themes | ~95% of full |
|
||||||
|
| **Full** | 24 modules + themes | 100% |
|
||||||
|
|
||||||
Users who want examples, documentation source, or development tools should clone the full repository.
|
Users who want examples, documentation source, or development tools should clone the full repository.
|
||||||
|
|
||||||
## Checksum Verification
|
## Checksum Verification
|
||||||
|
|
||||||
Every release includes a SHA256 checksum file for security verification.
|
Every profile package includes a SHA256 checksum file for security verification.
|
||||||
|
|
||||||
### For Developers (Creating Release)
|
### For Developers (Creating Release)
|
||||||
|
|
||||||
The checksum is automatically generated when running `./scripts/create-release.sh`:
|
The checksums are automatically generated when running `./scripts/create-profile-packages.sh`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./scripts/create-release.sh
|
./scripts/create-profile-packages.sh
|
||||||
# Creates:
|
# Creates 4 profile packages with checksums:
|
||||||
# - releases/flexlove-v0.3.0.zip
|
# - releases/flexlove-minimal-v0.3.0.zip + .sha256
|
||||||
# - releases/flexlove-v0.3.0.zip.sha256
|
# - releases/flexlove-slim-v0.3.0.zip + .sha256
|
||||||
|
# - releases/flexlove-default-v0.3.0.zip + .sha256
|
||||||
|
# - releases/flexlove-full-v0.3.0.zip + .sha256
|
||||||
|
|
||||||
# Verify before publishing
|
# Verify all packages before publishing
|
||||||
cd releases
|
cd releases
|
||||||
shasum -a 256 -c flexlove-v0.3.0.zip.sha256
|
shasum -a 256 -c flexlove-*-v0.3.0.zip.sha256
|
||||||
# Output: flexlove-v0.3.0.zip: OK
|
# Output: All packages report OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### For End Users (Downloading Release)
|
### For End Users (Downloading Release)
|
||||||
|
|
||||||
After downloading a release from GitHub:
|
After downloading your chosen profile from GitHub:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Download both files:
|
# Example: Verify the default profile
|
||||||
# - flexlove-v0.3.0.zip
|
shasum -a 256 -c flexlove-default-v0.3.0.zip.sha256
|
||||||
# - flexlove-v0.3.0.zip.sha256
|
|
||||||
|
|
||||||
# Verify integrity
|
|
||||||
shasum -a 256 -c flexlove-v0.3.0.zip.sha256
|
|
||||||
|
|
||||||
# If OK, safe to use
|
# If OK, safe to use
|
||||||
unzip flexlove-v0.3.0.zip
|
unzip flexlove-default-v0.3.0.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
**macOS/Linux:** Use `shasum -a 256 -c`
|
**macOS/Linux:** Use `shasum -a 256 -c`
|
||||||
**Windows:** Use `certutil -hashfile flexlove-v0.3.0.zip SHA256` and compare manually
|
**Windows:** Use `certutil -hashfile flexlove-<profile>-v0.3.0.zip SHA256` and compare manually
|
||||||
|
|
||||||
## Automated Releases (Future)
|
## Automated Releases (Future)
|
||||||
|
|
||||||
|
|||||||
251
docs/MODULE_DEPENDENCIES.md
Normal file
251
docs/MODULE_DEPENDENCIES.md
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
# FlexLöve Module Dependencies
|
||||||
|
|
||||||
|
This document provides a comprehensive overview of module dependencies in FlexLöve, helping you understand which modules are required and which are optional.
|
||||||
|
|
||||||
|
## Dependency Graph
|
||||||
|
|
||||||
|
### Core Required Modules
|
||||||
|
|
||||||
|
These modules are **always required** and cannot be excluded:
|
||||||
|
|
||||||
|
```
|
||||||
|
FlexLove.lua
|
||||||
|
├── ErrorHandler (error logging & handling)
|
||||||
|
├── ModuleLoader (safe module loading)
|
||||||
|
├── BuildProfile (profile management)
|
||||||
|
├── utils (utility functions & enums)
|
||||||
|
├── Units (unit parsing & resolution)
|
||||||
|
│ └── requires: Context, ErrorHandler
|
||||||
|
├── Context (global state & viewport)
|
||||||
|
├── StateManager (immediate mode state persistence)
|
||||||
|
├── Color (color utilities)
|
||||||
|
│ └── requires: ErrorHandler
|
||||||
|
├── InputEvent (input event abstraction)
|
||||||
|
├── TextEditor (text input handling)
|
||||||
|
├── LayoutEngine (flexbox layout calculations)
|
||||||
|
│ └── requires: ErrorHandler, Performance (optional)
|
||||||
|
├── Renderer (canvas rendering)
|
||||||
|
├── EventHandler (event routing & callbacks)
|
||||||
|
│ └── requires: ErrorHandler, Performance (optional), InputEvent, utils
|
||||||
|
├── ScrollManager (scroll behavior)
|
||||||
|
├── Element (UI element primitives)
|
||||||
|
│ └── requires: ALL core modules + optional modules
|
||||||
|
├── RoundedRect (rounded rectangle rendering)
|
||||||
|
└── Grid (grid layout utilities)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optional Modules
|
||||||
|
|
||||||
|
These modules can be excluded to reduce bundle size:
|
||||||
|
|
||||||
|
#### Animation Module
|
||||||
|
```
|
||||||
|
Animation
|
||||||
|
├── requires: ErrorHandler, Color
|
||||||
|
├── used by: Element (for animations)
|
||||||
|
└── size impact: ~15% of total
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- `element.animation` property
|
||||||
|
- `FlexLove.Animation` API
|
||||||
|
- Transition effects
|
||||||
|
- Keyframe animations
|
||||||
|
|
||||||
|
#### Image Modules
|
||||||
|
```
|
||||||
|
ImageRenderer
|
||||||
|
├── requires: ErrorHandler, utils
|
||||||
|
└── used by: Element (for image rendering)
|
||||||
|
|
||||||
|
ImageScaler
|
||||||
|
├── requires: ErrorHandler
|
||||||
|
└── used by: ImageRenderer
|
||||||
|
|
||||||
|
ImageCache
|
||||||
|
└── used by: Element (for image caching)
|
||||||
|
|
||||||
|
NinePatch
|
||||||
|
├── requires: ErrorHandler
|
||||||
|
└── used by: Element (for 9-patch rendering)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- `element.image` property
|
||||||
|
- `element.imageFit` property
|
||||||
|
- `element.imageRepeat` property
|
||||||
|
- 9-patch image support
|
||||||
|
- Image caching
|
||||||
|
|
||||||
|
#### Theme Module
|
||||||
|
```
|
||||||
|
Theme
|
||||||
|
├── requires: ErrorHandler, Color, utils
|
||||||
|
└── used by: Element (for theming)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- `FlexLove.Theme` API
|
||||||
|
- `element.theme` property
|
||||||
|
- `element.themeComponent` property
|
||||||
|
- Preset theme styles
|
||||||
|
- Theme-based component styling
|
||||||
|
|
||||||
|
#### Blur Module
|
||||||
|
```
|
||||||
|
Blur
|
||||||
|
└── used by: Element (for backdrop blur effects)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- `element.backdropBlur` property
|
||||||
|
- Glassmorphic effects
|
||||||
|
|
||||||
|
#### Performance Module
|
||||||
|
```
|
||||||
|
Performance
|
||||||
|
├── requires: ErrorHandler
|
||||||
|
└── used by: LayoutEngine, EventHandler, FlexLove
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- `FlexLove._Performance` API
|
||||||
|
- Performance HUD (F3 toggle)
|
||||||
|
- Performance monitoring
|
||||||
|
- Frame timing metrics
|
||||||
|
- Memory profiling
|
||||||
|
|
||||||
|
#### GestureRecognizer Module
|
||||||
|
```
|
||||||
|
GestureRecognizer
|
||||||
|
└── used by: Element (for gesture detection)
|
||||||
|
```
|
||||||
|
|
||||||
|
**What you lose:**
|
||||||
|
- Touch gesture recognition
|
||||||
|
- Swipe detection
|
||||||
|
- Pinch/zoom gestures
|
||||||
|
- Multi-touch support
|
||||||
|
|
||||||
|
## Module Loading Order
|
||||||
|
|
||||||
|
FlexLöve loads modules in this order:
|
||||||
|
|
||||||
|
1. **ErrorHandler** - Must be loaded first for error reporting
|
||||||
|
2. **ModuleLoader** - Loads modules safely with null-object fallbacks
|
||||||
|
3. **BuildProfile** - Registers and manages build profiles
|
||||||
|
4. **Core modules** - Required for basic functionality
|
||||||
|
5. **Optional modules** - Loaded with `ModuleLoader.safeRequire()`
|
||||||
|
|
||||||
|
## Profile-Specific Dependencies
|
||||||
|
|
||||||
|
### Minimal Profile (~70%)
|
||||||
|
Only includes core required modules. No optional dependencies.
|
||||||
|
|
||||||
|
### Slim Profile (~80%)
|
||||||
|
Adds image, animation, gesture support:
|
||||||
|
- Animation
|
||||||
|
- ImageRenderer
|
||||||
|
- ImageScaler
|
||||||
|
- ImageCache
|
||||||
|
- GestureRecognizer
|
||||||
|
|
||||||
|
### Default Profile (~95%)
|
||||||
|
Adds theme and visual effects:
|
||||||
|
- All Slim modules
|
||||||
|
- Theme
|
||||||
|
- NinePatch
|
||||||
|
- Blur
|
||||||
|
|
||||||
|
### Full Profile (100%)
|
||||||
|
Includes all modules:
|
||||||
|
- All Default modules
|
||||||
|
- Performance
|
||||||
|
|
||||||
|
## Checking Module Availability
|
||||||
|
|
||||||
|
You can check if a module is loaded at runtime:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local ModuleLoader = require("modules.ModuleLoader")
|
||||||
|
|
||||||
|
-- Check if Animation is available
|
||||||
|
if ModuleLoader.isModuleLoaded("modules.Animation") then
|
||||||
|
-- Use Animation module
|
||||||
|
local anim = FlexLove.Animation.new({ ... })
|
||||||
|
else
|
||||||
|
-- Animation not available, use fallback
|
||||||
|
print("Animation module not loaded")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependency Injection Pattern
|
||||||
|
|
||||||
|
FlexLöve uses dependency injection to handle optional modules:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
-- In Element.lua
|
||||||
|
function Element.init(deps)
|
||||||
|
-- Core dependencies (required)
|
||||||
|
Element._utils = deps.utils
|
||||||
|
Element._ErrorHandler = deps.ErrorHandler
|
||||||
|
|
||||||
|
-- Optional dependencies (may be null objects)
|
||||||
|
Element._Animation = deps.Animation -- May be a no-op stub
|
||||||
|
Element._Theme = deps.Theme -- May be a no-op stub
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
If a module is missing, `ModuleLoader` returns a **null object** that:
|
||||||
|
- Has the same method names as the real module
|
||||||
|
- Returns safe default values
|
||||||
|
- Prevents crashes from missing dependencies
|
||||||
|
|
||||||
|
## Custom Build Profiles
|
||||||
|
|
||||||
|
You can create custom profiles with specific module combinations:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local BuildProfile = require("modules.BuildProfile")
|
||||||
|
|
||||||
|
-- Register a custom profile
|
||||||
|
BuildProfile.register({
|
||||||
|
name = "my-game",
|
||||||
|
description = "Custom profile for my game",
|
||||||
|
size = 75,
|
||||||
|
modules = {
|
||||||
|
-- Core modules (required)
|
||||||
|
"utils", "Units", "Context", "StateManager",
|
||||||
|
"ErrorHandler", "Color", "InputEvent", "TextEditor",
|
||||||
|
"LayoutEngine", "Renderer", "EventHandler",
|
||||||
|
"ScrollManager", "Element", "RoundedRect", "Grid",
|
||||||
|
|
||||||
|
-- Optional: Add Animation but not Theme
|
||||||
|
"Animation",
|
||||||
|
"ImageRenderer",
|
||||||
|
"ImageScaler",
|
||||||
|
"ImageCache",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Set active profile
|
||||||
|
BuildProfile.setActive("my-game")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Start with Default Profile** - Use the default profile unless you have specific bundle size requirements
|
||||||
|
|
||||||
|
2. **Profile Before Optimizing** - Measure your actual bundle size before excluding modules
|
||||||
|
|
||||||
|
3. **Test Without Optional Modules** - If excluding modules, test thoroughly to ensure no features break
|
||||||
|
|
||||||
|
4. **Use ModuleLoader Checks** - Always check if optional modules are loaded before using them
|
||||||
|
|
||||||
|
5. **Document Your Profile** - If creating a custom profile, document which features are disabled
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [BUILD_PROFILES.md](./BUILD_PROFILES.md) - Detailed profile information
|
||||||
|
- [README.md](../README.md) - Getting started guide
|
||||||
|
- [ModuleLoader.lua](../modules/ModuleLoader.lua) - Source code for module loading
|
||||||
@@ -89,8 +89,9 @@ local function createNullObject(moduleName)
|
|||||||
return function() return {} end
|
return function() return {} end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Return nil for unknown properties (allows safe property access)
|
-- For any unknown method, return a no-op function that accepts any arguments
|
||||||
return nil
|
-- This allows safe method calls on stub objects (e.g., Performance:startFrame())
|
||||||
|
return function() return stub end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- Make function calls safe (in case the stub itself is called)
|
-- Make function calls safe (in case the stub itself is called)
|
||||||
|
|||||||
206
scripts/create-profile-packages.sh
Executable file
206
scripts/create-profile-packages.sh
Executable file
@@ -0,0 +1,206 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${BLUE}FlexLöve Profile Package Builder${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
VERSION=$(grep -m 1 "_VERSION" FlexLove.lua | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
echo -e "${RED}Error: Could not extract version from FlexLove.lua${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Version detected: ${VERSION}${NC}"
|
||||||
|
|
||||||
|
# Create releases directory if it doesn't exist
|
||||||
|
RELEASE_DIR="releases"
|
||||||
|
if [ ! -d "$RELEASE_DIR" ]; then
|
||||||
|
echo -e "${YELLOW}Creating releases directory...${NC}"
|
||||||
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to get profile description
|
||||||
|
get_description() {
|
||||||
|
case "$1" in
|
||||||
|
minimal) echo "Core modules only - smallest bundle size (~60%)" ;;
|
||||||
|
slim) echo "Minimal + Animation and Image support (~80%)" ;;
|
||||||
|
default) echo "Slim + Theme and Blur (~95%)" ;;
|
||||||
|
full) echo "All modules including debugging tools (100%)" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to get modules for a profile
|
||||||
|
get_modules() {
|
||||||
|
case "$1" in
|
||||||
|
minimal)
|
||||||
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua ModuleLoader.lua"
|
||||||
|
;;
|
||||||
|
slim)
|
||||||
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua ModuleLoader.lua"
|
||||||
|
;;
|
||||||
|
default)
|
||||||
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua ModuleLoader.lua"
|
||||||
|
;;
|
||||||
|
full)
|
||||||
|
echo "utils.lua Units.lua Context.lua StateManager.lua ErrorHandler.lua Color.lua InputEvent.lua TextEditor.lua LayoutEngine.lua Renderer.lua EventHandler.lua ScrollManager.lua Element.lua RoundedRect.lua Grid.lua GestureRecognizer.lua Animation.lua NinePatch.lua ImageRenderer.lua ImageScaler.lua ImageCache.lua Theme.lua Blur.lua Performance.lua ModuleLoader.lua"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build each profile
|
||||||
|
for profile in minimal slim default full; do
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Building ${profile} profile...${NC}"
|
||||||
|
description=$(get_description "$profile")
|
||||||
|
echo -e "${BLUE}${description}${NC}"
|
||||||
|
|
||||||
|
OUTPUT_FILE="${RELEASE_DIR}/flexlove-${profile}-v${VERSION}.zip"
|
||||||
|
CHECKSUM_FILE="${OUTPUT_FILE}.sha256"
|
||||||
|
|
||||||
|
# Remove existing files
|
||||||
|
if [ -f "$OUTPUT_FILE" ] || [ -f "$CHECKSUM_FILE" ]; then
|
||||||
|
echo -e "${YELLOW}Removing existing files...${NC}"
|
||||||
|
[ -f "$OUTPUT_FILE" ] && rm "$OUTPUT_FILE"
|
||||||
|
[ -f "$CHECKSUM_FILE" ] && rm "$CHECKSUM_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create temp directory
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
BUILD_DIR="${TEMP_DIR}/flexlove"
|
||||||
|
|
||||||
|
mkdir -p "$BUILD_DIR/modules"
|
||||||
|
|
||||||
|
echo " → Copying FlexLove.lua"
|
||||||
|
cp FlexLove.lua "$BUILD_DIR/"
|
||||||
|
|
||||||
|
echo " → Copying LICENSE"
|
||||||
|
cp LICENSE "$BUILD_DIR/"
|
||||||
|
|
||||||
|
echo " → Creating README.md"
|
||||||
|
# Create profile-specific README
|
||||||
|
profile_upper=$(echo "${profile}" | awk '{print toupper(substr($0,1,1)) tolower(substr($0,2))}')
|
||||||
|
cat > "$BUILD_DIR/README.md" << EOF
|
||||||
|
# FlexLöve v${VERSION} - ${profile_upper} Profile
|
||||||
|
|
||||||
|
${description}
|
||||||
|
|
||||||
|
This package contains the **${profile}** build profile of FlexLöve.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
unzip flexlove-${profile}-v${VERSION}.zip
|
||||||
|
cp -r flexlove/modules ./
|
||||||
|
cp flexlove/FlexLove.lua ./
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## What's Included
|
||||||
|
|
||||||
|
- **FlexLove.lua** - Main library file
|
||||||
|
- **modules/** - ${profile_upper} profile modules
|
||||||
|
- **LICENSE** - MIT License
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- LÖVE2D 11.0 or higher
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
📚 [View Full Documentation](https://mikefreno.github.io/FlexLove/)
|
||||||
|
|
||||||
|
## Build Profile
|
||||||
|
|
||||||
|
This is the **${profile}** profile. Other profiles available:
|
||||||
|
|
||||||
|
- **minimal** - Core functionality only (~60%)
|
||||||
|
- **slim** - Adds animations and image support (~80%)
|
||||||
|
- **default** - Adds themes and blur effects (~95%)
|
||||||
|
- **full** - All modules including debugging tools (100%)
|
||||||
|
|
||||||
|
Visit the [releases page](https://github.com/mikefreno/FlexLove/releases) to download other profiles.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - see LICENSE file for details.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Copy only the modules for this profile
|
||||||
|
echo " → Copying modules for ${profile} profile"
|
||||||
|
module_list=$(get_modules "$profile")
|
||||||
|
module_count=0
|
||||||
|
for module in $module_list; do
|
||||||
|
if [ -f "modules/$module" ]; then
|
||||||
|
cp "modules/$module" "$BUILD_DIR/modules/"
|
||||||
|
((module_count++))
|
||||||
|
else
|
||||||
|
echo -e "${RED}Warning: Module not found: modules/$module${NC}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo " Copied ${module_count} modules"
|
||||||
|
|
||||||
|
# Copy themes for default and full profiles
|
||||||
|
if [ "$profile" == "default" ] || [ "$profile" == "full" ]; then
|
||||||
|
echo " → Copying themes/"
|
||||||
|
mkdir -p "$BUILD_DIR/themes"
|
||||||
|
|
||||||
|
# Copy README
|
||||||
|
if [ -f "themes/README.md" ]; then
|
||||||
|
cp "themes/README.md" "$BUILD_DIR/themes/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy theme files as .example.lua
|
||||||
|
if [ -f "themes/metal.lua" ]; then
|
||||||
|
cp "themes/metal.lua" "$BUILD_DIR/themes/metal.example.lua"
|
||||||
|
fi
|
||||||
|
if [ -f "themes/space.lua" ]; then
|
||||||
|
cp "themes/space.lua" "$BUILD_DIR/themes/space.example.lua"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create zip archive
|
||||||
|
echo " → Creating zip archive"
|
||||||
|
ABS_OUTPUT_FILE="$(cd "$(dirname "$OUTPUT_FILE")" && pwd)/$(basename "$OUTPUT_FILE")"
|
||||||
|
|
||||||
|
cd "$TEMP_DIR"
|
||||||
|
zip -r -q "flexlove-${profile}-v${VERSION}.zip" flexlove/
|
||||||
|
mv "flexlove-${profile}-v${VERSION}.zip" "$ABS_OUTPUT_FILE"
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
# Generate checksum
|
||||||
|
echo " → Generating SHA256 checksum"
|
||||||
|
cd "$RELEASE_DIR"
|
||||||
|
shasum -a 256 "flexlove-${profile}-v${VERSION}.zip" > "flexlove-${profile}-v${VERSION}.zip.sha256"
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
|
||||||
|
# Report
|
||||||
|
FILE_SIZE=$(du -h "$OUTPUT_FILE" | cut -f1)
|
||||||
|
CHECKSUM=$(cat "$CHECKSUM_FILE" | cut -d ' ' -f 1)
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓ ${profile} profile created${NC}"
|
||||||
|
echo -e " ${BLUE}File:${NC} $OUTPUT_FILE"
|
||||||
|
echo -e " ${BLUE}Size:${NC} $FILE_SIZE"
|
||||||
|
echo -e " ${BLUE}Modules:${NC} ${module_count}"
|
||||||
|
echo -e " ${BLUE}SHA256:${NC} ${CHECKSUM:0:16}..."
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}✓ All profile packages created successfully!${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}Created packages:${NC}"
|
||||||
|
for profile in minimal slim default full; do
|
||||||
|
FILE_SIZE=$(du -h "${RELEASE_DIR}/flexlove-${profile}-v${VERSION}.zip" | cut -f1)
|
||||||
|
echo " - flexlove-${profile}-v${VERSION}.zip (${FILE_SIZE})"
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}Verify checksums:${NC}"
|
||||||
|
echo " cd releases && shasum -a 256 -c flexlove-*-v${VERSION}.zip.sha256"
|
||||||
@@ -110,11 +110,16 @@ function TestModuleLoader:test_stub_has_safe_clearCache_method()
|
|||||||
lu.assertIsTable(result)
|
lu.assertIsTable(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
function TestModuleLoader:test_stub_returns_nil_for_unknown_properties()
|
function TestModuleLoader:test_stub_returns_function_for_unknown_properties()
|
||||||
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
|
local stub = ModuleLoader.safeRequire(modulePath .. "modules.FakeModule", true)
|
||||||
|
|
||||||
lu.assertIsNil(stub.unknownProperty)
|
-- Unknown properties should return no-op functions for safe method calls
|
||||||
lu.assertIsNil(stub.anotherUnknownProperty)
|
lu.assertIsFunction(stub.unknownProperty)
|
||||||
|
lu.assertIsFunction(stub.anotherUnknownProperty)
|
||||||
|
|
||||||
|
-- Calling unknown methods should not error
|
||||||
|
stub:unknownMethod()
|
||||||
|
stub:anotherUnknownMethod("arg1", "arg2")
|
||||||
end
|
end
|
||||||
|
|
||||||
function TestModuleLoader:test_stub_callable_returns_itself()
|
function TestModuleLoader:test_stub_callable_returns_itself()
|
||||||
|
|||||||
Reference in New Issue
Block a user