var io = use('cellfs') function hashify(fn) { var hash = {} return function(arg) { var key = arg if (hash[key] == null) hash[key] = fn(arg) return hash[key] } } // Merge of the old resources.js and packer.js functionalities var Resources = {} // Recognized resource extensions Resources.scripts = ["js"] Resources.images = ["qoi", "png", "gif", "jpg", "jpeg", "ase", "aseprite"] Resources.sounds = ["wav", "flac", "mp3", "qoa"] Resources.fonts = ["ttf"] Resources.lib = [".so", ".dll", ".dylib"] // Helper function: get extension from path in lowercase (e.g., "image.png" -> "png") function getExtension(path) { var last = null replace(path, ".", function(m,pos) { last = pos return m }) if (last == null) return null return lower(text(path, last + 1)) } // Return true if ext is in at least one of the recognized lists function isRecognizedExtension(ext) { if (!ext) return false if (search(Resources.scripts, ext) != null) return true if (search(Resources.images, ext) != null) return true if (search(Resources.sounds, ext) != null) return true if (search(Resources.fonts, ext) != null) return true if (search(Resources.lib, '.' + ext) != null) return true // for .so or .dll return false } function find_in_path(filename, exts = []) { if (!is_text(filename)) return null if (search(filename, '.') != null) { var candidate = filename // possibly need "/" ? if (io.exists(candidate) && !io.is_directory(candidate)) return candidate return null } // Only check extensions if exts is provided and not empty if (length(exts) > 0) { var cand = null arrfor(exts, function(ext) { var candidate = filename + '.' + ext if (io.exists(candidate) && !io.is_directory(candidate)){ cand = candidate return true } }, null, true) if (cand != null) return cand } else { // Fallback to extensionless file only if no extensions are specified var candidate = filename if (io.exists(candidate) && !io.is_directory(candidate)) return candidate } return null } // Return a canonical path (the real directory plus the path) Resources.canonical = function(file) { return io.realdir(file) + file } // The resource finders Resources.find_image = hashify(function(file) { return find_in_path(file, Resources.images) }) Resources.find_sound = hashify(function(file) { return find_in_path(file, Resources.sounds) }) Resources.find_script = hashify(function(file) { return find_in_path(file, Resources.scripts) }) Resources.find_font = hashify(function(file) { return find_in_path(file, Resources.fonts) }) // .prosperonignore reading helper function read_ignore(dir) { var path = dir + '/.prosperonignore' var patterns = [] if (io.exists(path)) { var lines = array(io.slurp(path), '\n') arrfor(lines, function(line) { line = trim(line) if (!line || starts_with(line, '#')) return push(patterns, line) }) } return patterns } // Return a list of recognized files in the directory (and subdirectories), // skipping those matched by .prosperonignore. Directory paths are skipped. Resources.getAllFiles = function(dir = "") { var patterns = read_ignore(dir) var all = io.globfs(patterns, dir) var results = [] arrfor(all, function(f) { var fullPath = dir + '/' + f try { var st = io.stat(fullPath) // skip directories (filesize=0) or unrecognized extension if (!st.filesize) return var ext = getExtension(f) if (!isRecognizedExtension(ext)) return push(results, fullPath) } catch(e) {} }) return results } // Categorize files by resource type Resources.gatherStats = function(filePaths) { var stats = { scripts:0, images:0, sounds:0, fonts:0, lib:0, other:0, total:length(filePaths) } arrfor(filePaths, function(path) { var ext = getExtension(path) if (find(Resources.scripts, ext) != null) { stats.scripts++ return } if (find(Resources.images, ext) != null) { stats.images++ return } if (find(Resources.sounds, ext) != null) { stats.sounds++ return } if (find(Resources.fonts, ext) != null) { stats.fonts++ return } stats.other++ }) return stats } return Resources