return function(config) local fmt = string.format -------------------------------- -- -- basics -- -------------------------------- function Set(array, transform) if type(array) ~= 'table' then return nil end local transform = transform or function(x) return x end local set = {} for _, element in ipairs(array) do set[transform(element)] = true end return set end function set_tostring(set) local str = '[empty]' for element in pairs(set) do if str == '[empty]' then str = tostring(element) else str = str .. '; '.. tostring(element) end end return str end function add_end_slash(str) if type(str) ~= 'string' then return nil end if string.match(str, '/$') then return str end return str .. '/' end function strip_end_slash(str) if string.match(str, '/$') then return string.sub(str, 1, #str-1) end return str end function setup(config) argent.log('debug', 'begin setup') argent.config = { site_directory = add_end_slash(config.site_directory) or 'site/', output_directory = add_end_slash(config.output_directory) or 'public/', layout_directory = add_end_slash(config.layout_directory) or nil, plugin_directory = add_end_slash(config.layout_directory) or nil, exclude = Set(config.exclude, strip_end_slash) or {}, include = Set(config.include, strip_end_slash) or {}, keep = Set(config.keep, strip_end_slash) or {}, noprocess = Set(config.noprocess, strip_end_slash) or {}, rss_include = Set(config.rss_include, strip_end_slash) or {}, } argent.log('info', fmt('site directory: %s', argent.config.site_directory)) argent.log('info', fmt('output directory: %s', argent.config.output_directory)) argent.log('info', fmt('layout directory: %s', tostring(argent.config.layout_directory))) argent.log('info', fmt('plugin directory: %s', tostring(argent.config.plugin_directory))) argent.log('info', 'exclusions: '..set_tostring(argent.config.exclude)) argent.log('info', 'inclusions: '..set_tostring(argent.config.include)) argent.log('info', 'files to keep: '..set_tostring(argent.config.keep)) argent.log('info', 'noprocess: '..set_tostring(argent.config.noprocess)) argent.log('info', 'rss files: '..set_tostring(argent.config.rss_include)) if argent.config.plugin_directory then package.path = argent.config.plugin_directory..'?.lua;'..package.path end argent.log('debug', 'end setup') end function is_dotfile(filename) if string.match(filename, '^%.') then return true end return false end function directory_exists(directory, parent) local directory = directory or '' local parent = parent or '' local dirs = argent.scanDirectory(argent.config.output_directory..parent) for _, dir in ipairs(dirs) do if strip_end_slash(directory) == dir then return true end end return false end function output_directory_exists() local dirs = argent.scanDirectory('./') for _, dir in ipairs(dirs) do if add_end_slash(dir) == argent.config.output_directory then return true end end return false end -------------------------------- -- -- obliterating -- -------------------------------- function obliterate_file(file, parent) if argent.config.keep[file] then argent.log('debug', fmt('retaining file %q', file)) return true end argent.log('debug', fmt('removing file %q', file)) os.remove(argent.config.output_directory..parent..file) return false end function obliterate_dir(dir, parent) if argent.config.keep[strip_end_slash(dir)] then argent.log('debug', fmt('retaining directory %q', dir)) return true end argent.log('debug', fmt('obliterating files in %q', parent..dir)) return obliterate_directory(dir, parent) end function obliterate_directory(dirname, parent) local dirname = add_end_slash(dirname) or '' local parent = parent or '' if argent.config.keep[dirname] then return true end local keep_self = (dirname == '') local dirs, files = argent.scanDirectory(argent.config.output_directory..parent..dirname) for _, file in ipairs(files) do keep_self = obliterate_file(file, parent..dirname) or keep_self end for _, dir in ipairs(dirs) do if dir ~= '.' and dir ~= '..' then keep_self = obliterate_dir(dir, parent..dirname) or keep_self end end if not keep_self then os.remove(argent.config.output_directory..parent..dirname) return false else return true end end -------------------------------- -- -- processing -- -------------------------------- function process_file(filename, parent) if (is_dotfile(filename) and not argent.config.include[filename]) or argent.config.exclude[filename] then return end if string.match(filename, '%.lua$') and not argent.config.noprocess[filename] then process_lua_file(filename, parent) else argent.copyFile( argent.config.site_directory..parent..filename, argent.config.output_directory..parent..filename ) end end function process_lua_file(filename, parent) local success, result = pcall(loadfile(argent.config.site_directory..parent..filename)) if not success then print('WARNING: '..result) return end print(filename, result) end function process_dir(directory, parent) if (is_dotfile(directory) and not argent.config.include[strip_end_slash(directory)]) or argent.config.exclude[strip_end_slash(directory)] then return end if not directory_exists(directory, parent) then argent.createDirectory(argent.config.output_directory..parent..directory) end process_directory(directory, parent) end function process_directory(directory, parent) local directory = add_end_slash(directory) or '' local parent = add_end_slash(parent) or '' local dirs, files = argent.scanDirectory(argent.config.site_directory..parent..directory) for _, file in ipairs(files) do process_file(file, parent..directory) end for _, dir in ipairs(dirs) do if dir ~= '.' and dir ~= '..' then process_dir(dir, parent..directory) end end end -------------------------------- -- -- putting it all together -- -------------------------------- setup(config) if not output_directory_exists() then argent.createDirectory(argent.config.output_directory) else obliterate_directory() end process_directory() end