From a9d6ef78b5be767618a942863159ee1dc10a69f4 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Tue, 25 Nov 2025 15:58:57 -0500 Subject: [PATCH] selectable releases --- .github/workflows/release.yml | 97 ++++++--- FlexLove.lua | 8 +- README.md | 30 +++ RELEASE.md | 87 ++++---- docs/MODULE_DEPENDENCIES.md | 251 +++++++++++++++++++++++ modules/ModuleLoader.lua | 5 +- scripts/create-profile-packages.sh | 206 +++++++++++++++++++ testing/__tests__/module_loader_test.lua | 11 +- 8 files changed, 615 insertions(+), 80 deletions(-) create mode 100644 docs/MODULE_DEPENDENCIES.md create mode 100755 scripts/create-profile-packages.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e63409f..083beb8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,6 +74,7 @@ jobs: run: | chmod +x scripts/generate_docs.sh chmod +x scripts/create-release.sh + chmod +x scripts/create-profile-packages.sh chmod +x scripts/archive-docs.sh - 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 push origin HEAD:main || echo "Nothing to push" - - name: Create release package + - name: Create release packages run: | - # Run release script non-interactively (auto-confirm overwrite) - echo "y" | ./scripts/create-release.sh || ./scripts/create-release.sh - # Verify files were created + # Create all 4 profile packages + ./scripts/create-profile-packages.sh + + # Verify all packages were created VERSION="${{ steps.version.outputs.version }}" - if [ ! -f "releases/flexlove-v${VERSION}.zip" ]; then - echo "Error: Release zip was not created" - exit 1 - fi - if [ ! -f "releases/flexlove-v${VERSION}.zip.sha256" ]; then - echo "Error: Checksum file was not created" - exit 1 - fi - echo "✓ Release package created successfully" + for profile in minimal slim default full; do + if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip" ]; then + echo "Error: ${profile} profile package was not created" + exit 1 + fi + if [ ! -f "releases/flexlove-${profile}-v${VERSION}.zip.sha256" ]; then + echo "Error: ${profile} checksum file was not created" + exit 1 + fi + done + echo "✓ All profile packages created successfully" - name: Upload release artifacts uses: actions/upload-artifact@v4 with: name: release-assets path: | - 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 + releases/flexlove-*-v${{ steps.version.outputs.version }}.zip.sha256 docs/api.html retention-days: 90 @@ -143,13 +147,19 @@ jobs: name: release-assets path: ./ - - name: Extract checksum for release notes - id: checksum + - name: Extract checksums for release notes + id: checksums run: | VERSION="${{ steps.version.outputs.version }}" - CHECKSUM=$(cat "releases/flexlove-v${VERSION}.zip.sha256" | cut -d ' ' -f 1) - echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT - echo "Checksum: $CHECKSUM" + MINIMAL_CHECKSUM=$(cat "releases/flexlove-minimal-v${VERSION}.zip.sha256" | cut -d ' ' -f 1) + SLIM_CHECKSUM=$(cat "releases/flexlove-slim-v${VERSION}.zip.sha256" | cut -d ' ' -f 1) + 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 id: prerelease @@ -167,41 +177,58 @@ jobs: id: release_notes run: | VERSION="${{ steps.version.outputs.version }}" - CHECKSUM="${{ steps.checksum.outputs.checksum }}" 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 - 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 - 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 flexlove/FlexLove.lua ./ ``` ## Verification - Verify the download integrity using SHA256: + Verify download integrity using SHA256: ```bash - shasum -a 256 -c flexlove-v${{ steps.version.outputs.version }}.zip.sha256 + shasum -a 256 -c flexlove--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 - 📚 [View Documentation](https://mikefreno.github.io/FlexLove/) + 📚 [View Full Documentation](https://mikefreno.github.io/FlexLove/) ## What's Included + Each package contains: - `FlexLove.lua` - Main library file - - `modules/` - All required module files + - `modules/` - Profile-specific module files - `LICENSE` - MIT License - - `README.md` + - `README.md` - Profile-specific readme ## Requirements @@ -220,8 +247,14 @@ jobs: name: FlexLöve v${{ steps.version.outputs.version }} body_path: release_notes.md files: | - releases/flexlove-v${{ steps.version.outputs.version }}.zip - releases/flexlove-v${{ steps.version.outputs.version }}.zip.sha256 + releases/flexlove-minimal-v${{ steps.version.outputs.version }}.zip + 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 }} draft: false env: diff --git a/FlexLove.lua b/FlexLove.lua index 375ecc0..579e600 100644 --- a/FlexLove.lua +++ b/FlexLove.lua @@ -3,15 +3,11 @@ local function req(name) return require(modulePath .. "modules." .. name) end --- Load ErrorHandler first (required for ModuleLoader) ---@type ErrorHandler local ErrorHandler = req("ErrorHandler") - --- Load ModuleLoader local ModuleLoader = req("ModuleLoader") ModuleLoader.init({ ErrorHandler = ErrorHandler }) --- Helper function for safe module loading local function safeReq(name, isOptional) return ModuleLoader.safeRequire(modulePath .. "modules." .. name, isOptional) end @@ -373,7 +369,7 @@ function flexlove.beginFrame() end elem:_cleanup() end - + for _, element in ipairs(flexlove._currentFrameElements) do if not element.parent then cleanupChildren(element) @@ -428,7 +424,7 @@ function flexlove.endFrame() stateUpdate[k] = v end end - + stateUpdate._focused = element._focused stateUpdate._cursorPosition = element._cursorPosition stateUpdate._selectionStart = element._selectionStart diff --git a/README.md b/README.md index 3a2c511..5565ba9 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,36 @@ function love.draw() 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 📚 **[View Full API Documentation](https://mikefreno.github.io/FlexLove/api.html)** diff --git a/RELEASE.md b/RELEASE.md index d5ea8f0..b4f2fab 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -23,8 +23,8 @@ This interactive script will: After pushing the tag, GitHub Actions automatically: - Archives previous documentation - Generates new documentation -- Creates release package with SHA256 checksums -- Publishes GitHub release with download assets +- Creates 4 build profile packages (minimal, slim, default, full) with SHA256 checksums +- Publishes GitHub release with all profile packages ### 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. -## 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 -./scripts/create-release.sh +./scripts/create-profile-packages.sh ``` -Output files: -- `releases/flexlove-v{version}.zip` -- `releases/flexlove-v{version}.zip.sha256` +Output files (for version 0.3.0): +- `releases/flexlove-minimal-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 Local Package +### Verify Local Packages ```bash cd releases -shasum -a 256 -c flexlove-v0.3.0.zip.sha256 -# Expected: flexlove-v0.3.0.zip: OK +shasum -a 256 -c flexlove-*-v0.3.0.zip.sha256 +# Expected: All packages report OK ``` ## Release Checklist @@ -124,11 +126,11 @@ shasum -a 256 -c flexlove-v0.3.0.zip.sha256 - [ ] Version updated in `FlexLove.lua` - [ ] Documentation regenerated (`./scripts/generate_docs.sh`) - [ ] Changes committed and pushed -- [ ] Release package created (`./scripts/create-release.sh`) -- [ ] Checksum verified (`shasum -a 256 -c *.sha256`) -- [ ] Release package tested +- [ ] Profile packages created (`./scripts/create-profile-packages.sh`) +- [ ] All checksums verified (`cd releases && shasum -a 256 -c *.sha256`) +- [ ] All profile packages tested - [ ] Git tag created and pushed -- [ ] GitHub release published with zip and checksum files +- [ ] GitHub release published with all 4 profile packages and checksums ## Versioning @@ -142,61 +144,72 @@ Example: `0.2.0` → `0.2.1` (bug fix) or `0.3.0` (new feature) ## 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:** - `FlexLove.lua` - Main library -- `modules/` - All module files +- `modules/` - Profile-specific module files only - `LICENSE` - License terms -- `README.md` - Installation instructions +- `README.md` - Profile-specific installation instructions +- `themes/` - (default and full profiles only) ❌ **Not included:** - `docs/` - Documentation (hosted on GitHub Pages) - `examples/` - Example code (available in repository) - `testing/` - Test suite -- `themes/` - Theme examples - 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. ## 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) -The checksum is automatically generated when running `./scripts/create-release.sh`: +The checksums are automatically generated when running `./scripts/create-profile-packages.sh`: ```bash -./scripts/create-release.sh -# Creates: -# - releases/flexlove-v0.3.0.zip -# - releases/flexlove-v0.3.0.zip.sha256 +./scripts/create-profile-packages.sh +# Creates 4 profile packages with checksums: +# - releases/flexlove-minimal-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 -shasum -a 256 -c flexlove-v0.3.0.zip.sha256 -# Output: flexlove-v0.3.0.zip: OK +shasum -a 256 -c flexlove-*-v0.3.0.zip.sha256 +# Output: All packages report OK ``` ### For End Users (Downloading Release) -After downloading a release from GitHub: +After downloading your chosen profile from GitHub: ```bash -# Download both files: -# - flexlove-v0.3.0.zip -# - flexlove-v0.3.0.zip.sha256 - -# Verify integrity -shasum -a 256 -c flexlove-v0.3.0.zip.sha256 +# Example: Verify the default profile +shasum -a 256 -c flexlove-default-v0.3.0.zip.sha256 # 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` -**Windows:** Use `certutil -hashfile flexlove-v0.3.0.zip SHA256` and compare manually +**Windows:** Use `certutil -hashfile flexlove--v0.3.0.zip SHA256` and compare manually ## Automated Releases (Future) diff --git a/docs/MODULE_DEPENDENCIES.md b/docs/MODULE_DEPENDENCIES.md new file mode 100644 index 0000000..34e720f --- /dev/null +++ b/docs/MODULE_DEPENDENCIES.md @@ -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 diff --git a/modules/ModuleLoader.lua b/modules/ModuleLoader.lua index 91a7ebb..426250c 100644 --- a/modules/ModuleLoader.lua +++ b/modules/ModuleLoader.lua @@ -89,8 +89,9 @@ local function createNullObject(moduleName) return function() return {} end end - -- Return nil for unknown properties (allows safe property access) - return nil + -- For any unknown method, return a no-op function that accepts any arguments + -- This allows safe method calls on stub objects (e.g., Performance:startFrame()) + return function() return stub end end, -- Make function calls safe (in case the stub itself is called) diff --git a/scripts/create-profile-packages.sh b/scripts/create-profile-packages.sh new file mode 100755 index 0000000..26180b2 --- /dev/null +++ b/scripts/create-profile-packages.sh @@ -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" diff --git a/testing/__tests__/module_loader_test.lua b/testing/__tests__/module_loader_test.lua index a0d53db..1b0fd39 100644 --- a/testing/__tests__/module_loader_test.lua +++ b/testing/__tests__/module_loader_test.lua @@ -110,11 +110,16 @@ function TestModuleLoader:test_stub_has_safe_clearCache_method() lu.assertIsTable(result) 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) - lu.assertIsNil(stub.unknownProperty) - lu.assertIsNil(stub.anotherUnknownProperty) + -- Unknown properties should return no-op functions for safe method calls + lu.assertIsFunction(stub.unknownProperty) + lu.assertIsFunction(stub.anotherUnknownProperty) + + -- Calling unknown methods should not error + stub:unknownMethod() + stub:anotherUnknownMethod("arg1", "arg2") end function TestModuleLoader:test_stub_callable_returns_itself()