#!/usr/bin/env nu # Development workflow script use ../config/build.config.nu use build.nu build_page use utils.nu * use optimize-html.nu * use optimize-css.nu * use optimize-svg.nu * # Development server with auto-rebuild def main [ --port(-p): int = 8080 # Development server port --watch(-w) # Enable file watching --no-browser(-n) # Don't open browser automatically --verbose(-v) # Verbose output ] { let config = (load_config) print "๐Ÿš€ Starting development environment..." # Initial build print "๐Ÿ“ฆ Building development version..." try { build_page --dev } catch { print "โŒ Build failed" return } if $watch { # Start server and file watcher with better server detection start_dev_server_with_watch $config $port $no_browser $verbose } else { # Start development server only start_dev_server $config.dist_dir $port $no_browser } } # File watcher for auto-rebuild def start_file_watcher [config: record, verbose: bool] { print "๐Ÿ‘๏ธ Starting file watcher..." let watch_files = [ $"($config.src_dir)/index.html", $"($config.css_src)/modules/*.css", $"($config.css_src)/main.css", $"($config.css_src)/svg-data.css", $"($config.svg_src)/*.svg" ] # Expand glob patterns let expanded_files = ($watch_files | each { |pattern| if ($pattern | str contains "*") { glob $pattern } else { [$pattern] } } | flatten | where ($it | path exists)) print $"๐Ÿ“‚ Watching ($expanded_files | length) files for changes..." # Watch in background job watch_files $expanded_files { |files| print "\n๐Ÿ”„ Files changed!" print "๐Ÿ”จ Rebuilding..." # Quick development build try { build_page --dev print "โœ… Rebuild completed" } catch { print "โŒ Rebuild failed" } } } # Start development server def start_dev_server [directory: string, port: int, no_browser: bool] { print $"๐ŸŒ Starting development server..." print $"๐Ÿ“ Serving: ($directory)" print $"๐Ÿ”— URL: http://localhost:($port)" if not $no_browser { # Try to open browser (platform-specific) try { if ($nu.os-info.name == "macos") { open $"http://localhost:($port)" } else if ($nu.os-info.name == "linux") { xdg-open $"http://localhost:($port)" } else if ($nu.os-info.name == "windows") { start $"http://localhost:($port)" } } catch { print $"๐Ÿ’ก Open http://localhost:($port) in your browser" } } # Start simple HTTP server serve_dev $port $directory } # Start development server with file watching def start_dev_server_with_watch [config: record, port: int, no_browser: bool, verbose: bool] { print $"๐ŸŒ Starting development server with file watching..." print $"๐Ÿ“ Serving: ($config.dist_dir)" print $"๐Ÿ”— URL: http://localhost:($port)" # Check what HTTP servers are available let has_simple_server = (which simple-http-server | length) > 0 let has_python3 = (which python3 | length) > 0 let has_python = (which python | length) > 0 if $has_simple_server or $has_python3 or $has_python { print "" print "๐Ÿš€ Starting HTTP server in background..." # Start HTTP server in background let server_cmd = if $has_simple_server { print " Using simple-http-server (recommended)" $"cd ($config.dist_dir) && simple-http-server --port ($port) --index" } else if $has_python3 { print " Using Python3 HTTP server" $"cd ($config.dist_dir) && python3 -m http.server ($port)" } else { print " Using Python2 HTTP server" $"cd ($config.dist_dir) && python -m SimpleHTTPServer ($port)" } # Start server in background using shell try { ^bash -c $"($server_cmd) > /dev/null 2>&1 &" print $"๐Ÿ“ก HTTP server started on port ($port)" } catch { |err| print $"โŒ Failed to start server: ($err.msg)" print " Try starting manually:" print $" ($server_cmd)" } if not $no_browser { print "๐ŸŒ Opening browser..." # Try to open browser (platform-specific) without delay to avoid Ctrl+C issues try { if ($nu.os-info.name == "macos") { open $"http://localhost:($port)" } else if ($nu.os-info.name == "linux") { xdg-open $"http://localhost:($port)" } else if ($nu.os-info.name == "windows") { start $"http://localhost:($port)" } } catch { print $"๐Ÿ’ก Manually open http://localhost:($port) in your browser" } } print "๐Ÿ‘๏ธ File watcher will now monitor for changes..." print $"๐ŸŒ Server running at: http://localhost:($port)" print "" print "๐Ÿ’ก Usage:" print " โ€ข Files will auto-rebuild when changed" print " โ€ข Press Ctrl+C to stop (error message is normal)" print $" โ€ข Cleanup server when done: nu scripts/dev.nu cleanup ($port)" print "" # Start file watcher - let it run until interrupted # The error message on Ctrl+C is normal Nushell behavior start_file_watcher $config $verbose } else { print "โŒ No HTTP server found." print " Install one of the following:" print " - simple-http-server: cargo install basic-http-server" print " - Python: Install via system package manager" print $" Then restart the development server." # Still run file watcher for builds start_file_watcher $config $verbose } } # Quick development build def "main build" [] { print "๐Ÿ”จ Quick development build..." try { build_page --dev print "โœ… Build completed" } catch { |err| print $"โŒ Build failed: ($err)" } } # Clean development build def "main clean" [] { let config = (load_config) print "๐Ÿงน Cleaning development build..." if ($config.dist_dir | path exists) { rm -rf $config.dist_dir } print "โœ… Clean completed" } # Development build with analysis def "main analyze" [] { print "๐Ÿ“Š Building with analysis..." try { build_page --dev --analyze --verbose print "โœ… Analysis completed" } catch { |err| print $"โŒ Analysis failed: ($err)" } } # Lint and validate source files def "main lint" [] { let config = (load_config) print "๐Ÿ” Linting source files..." # Validate HTML let html_file = $"($config.src_dir)/index.html" if ($html_file | path exists) { let html_content = (open $html_file) let validation = (validate_html_structure $html_content) if $validation.valid_structure { print "โœ… HTML structure is valid" } else { print "โŒ HTML structure issues found:" if not $validation.has_doctype { print " - Missing DOCTYPE" } if not $validation.has_title { print " - Missing title tag" } if not $validation.has_head { print " - Missing head section" } if not $validation.has_body { print " - Missing body tag" } } } # Validate CSS modules let css_modules = (glob $"($config.css_src)/modules/*.css") print $"๐ŸŽจ Checking ($css_modules | length) CSS modules..." $css_modules | each { |css_file| let css_content = (open $css_file) let analysis = (analyze_css $css_content) print $" ($css_file | path basename): ($analysis.size_bytes) bytes, ($analysis.rule_lines) rules" # Check for common issues if ($css_content | str contains "!important") { print $" โš ๏ธ Contains !important declarations" } if ($css_content | str contains "position: absolute") and (($css_content | str length) > 500) { print $" โš ๏ธ Heavy use of absolute positioning" } } # Validate SVG files let svg_files = (glob $"($config.svg_src)/*.svg") print $"๐Ÿ–ผ๏ธ Checking ($svg_files | length) SVG files..." $svg_files | each { |svg_file| let svg_content = (open $svg_file) let validation = (validate_svg $svg_content) if $validation.valid { print $" โœ… ($svg_file | path basename): Valid" } else { print $" โŒ ($svg_file | path basename): Invalid SVG" } } print "๐Ÿ” Lint completed" } # Preview production build locally def "main preview" [--port(-p): int = 8080] { print "๐Ÿ“ฆ Building production version for preview..." try { build_page --clean --verbose --analyze let config = (load_config) print "๐ŸŒ Starting preview server..." serve_dev $port $config.dist_dir } catch { |err| print $"โŒ Preview failed: ($err)" } } # Cleanup development server processes def cleanup_dev_server [port: int] { print "๐Ÿงน Cleaning up background processes..." # Kill any servers running on this port let cleanup_commands = [ $"pkill -f 'http.server ($port)'", $"pkill -f 'simple-http-server.*--port ($port)'", $"pkill -f 'SimpleHTTPServer ($port)'", $"lsof -ti:($port) | xargs kill -9" ] $cleanup_commands | each { |cmd| try { ^bash -c $cmd } catch { # Ignore errors - process might not exist null } } print "โœ… Cleanup completed" } # Manual cleanup command def "main cleanup" [port?: int = 8080] { cleanup_dev_server $port } # Development help def "main help" [] { print "๐Ÿ› ๏ธ Development Commands:" print "========================" print " nu scripts/dev.nu - Start development server with file watching" print " nu scripts/dev.nu build - Quick development build" print " nu scripts/dev.nu clean - Clean development build" print " nu scripts/dev.nu analyze - Build with file size analysis" print " nu scripts/dev.nu lint - Lint and validate source files" print " nu scripts/dev.nu preview - Preview production build locally" print " nu scripts/dev.nu cleanup - Manually stop background servers" print " nu scripts/dev.nu help - Show this help" print "" print "Options:" print " --port, -p - Development server port (default: 8080)" print " --watch, -w - Enable file watching for auto-rebuild" print " --no-browser, -n - Don't open browser automatically" print " --verbose, -v - Verbose output" print "" print "Examples:" print " nu scripts/dev.nu --watch --port 3000" print " nu scripts/dev.nu preview --port 8080" print " nu scripts/dev.nu analyze" }