ferron

[ARCHIVED] Ferron is a fast and simple static website generator made with Lua.
Log | Files | Refs | Submodules | README | LICENSE

file-utils.lua (6801B)


      1 -- fileutils.lua
      2 local fileutils = {}
      3 local fileutilsmeta = {
      4   __call = function(self, key, vars)
      5     print(key)
      6   end
      7 }
      8 
      9 local json = require 'dkjson'
     10 local lfs = require 'lfs'
     11 local mimetypes = require 'mimetypes'
     12 local config = require 'ferron.config'
     13 local tb = require 'ferron.utilities.table-utils'
     14 
     15 --- Returns non-directory portion of a pathname
     16 -- @name getbasename
     17 -- @param filepath a pathname to a file
     18 -- @return a string that represents the filename portion of pathname
     19 function fileutils.getbasename(filepath)
     20   return string.gsub(filepath, '(.*/)(.*)', '%2')
     21 end
     22 
     23 --- Check if the pathname target is a file
     24 -- @name isFile
     25 -- @param filepath a pathname to a file
     26 -- @return if true the filepath param, else false
     27 function fileutils.isFile(filepath)
     28   if lfs.attributes(filepath)
     29     and lfs.attributes(filepath).mode == 'file'
     30   then
     31     return filepath
     32   end
     33 
     34   return false
     35 end
     36 
     37 --- Check if the pathname target is a directory
     38 -- @name isDirectory
     39 -- @param filepath a pathname to a directory
     40 -- @return if true the filepath param, else false
     41 function fileutils.isDirectory(filepath)
     42   if lfs.attributes(filepath)
     43     and lfs.attributes(filepath).mode == 'directory'
     44   then
     45     return filepath
     46   end
     47 
     48   return false
     49 end
     50 
     51 function fileutils.isNotDotDirectory(dirname)
     52   if dirname ~= '.'
     53     and dirname ~= '..'
     54     and dirname ~= '.git'
     55   then
     56     return dirname
     57   end
     58 
     59   return false
     60 end
     61 
     62 --- Check if the pathname target is a markdown file
     63 -- @name isMarkdown
     64 -- @param filepath a pathname to a file
     65 -- @return if true the filepath param, else false
     66 function fileutils.isMarkdown(filepath)
     67   if fileutils.isFile(filepath)
     68     and (mimetypes.guess(filepath) == 'text/x-markdown'
     69            or fileutils.getextension(filepath) == '.md')
     70   then
     71       return filepath
     72   end
     73 
     74   return false
     75 end
     76 
     77 --- Check if the pathname target is a JavaScript file
     78 -- @name isJS
     79 -- @param filepath a pathname to a file
     80 -- @return if true the filepath param, else false
     81 function fileutils.isJS(filepath)
     82   if fileutils.isFile(filepath)
     83     and (mimetypes.guess(filepath) == 'text/javascript'
     84            or fileutils.getextension(filepath) == '.js')
     85   then
     86       return filepath
     87   end
     88 
     89   return false
     90 end
     91 
     92 --- Check if the pathname target is a markdown file named index
     93 -- @name isIndex
     94 -- @param filepath a pathname to a file
     95 -- @return if true the filepath param, else false
     96 function fileutils.isIndex(filepath)
     97   if fileutils.isMarkdown(filepath)
     98     and fileutils.getbasename(filepath) == 'index.md'
     99   then
    100     return filepath
    101   end
    102 
    103   return false
    104 end
    105 --- Check if the pathname target is a markdown file but not named
    106 --- index
    107 -- @name isNotIndex
    108 -- @param filepath a pathname to a file
    109 -- @return if true the filepath param, else false
    110 function fileutils.isNotIndex(filepath)
    111   if fileutils.isMarkdown(filepath)
    112     and not fileutils.isIndex(filepath)
    113   then
    114     return filepath
    115   end
    116 
    117   return false
    118 end
    119 
    120 function fileutils.isNonTextual(filepath)
    121   return (
    122     tb.hasvalue(config.mimetypes, mimetypes.guess(filepath)) and true or false
    123   )
    124 end
    125 
    126 -- getlastmodified
    127 function fileutils.getlastupdateddate(filelist)
    128   return math.max(table.unpack(tb.map(
    129     function(fl)
    130       if fileutils.isFile(fl) then
    131         return lfs.attributes(fl).modification
    132       end
    133     end,
    134     filelist
    135   )))
    136 end
    137 
    138 -- getdirtree
    139 function fileutils.getdirtree(dir)
    140   assert(dir and dir ~= '', 'directory parameter is missing or empty')
    141 
    142   if string.sub(dir, -1) == '/' then
    143     dir = string.sub(dir, 1, -2)
    144   end
    145 
    146   local function yieldtree(dir)
    147     for entry in lfs.dir(dir) do
    148       if entry ~= '.' and entry ~= '..' then
    149         entry = dir..'/'..entry
    150 
    151         local attr = lfs.attributes(entry)
    152 
    153         coroutine.yield(entry,attr)
    154 
    155         if attr.mode == 'directory' then
    156           yieldtree(entry)
    157         end
    158       end
    159     end
    160   end
    161 
    162   return coroutine.wrap(function() yieldtree(dir) end)
    163 end
    164 
    165 -- mkdir
    166 function fileutils.mkdir(path)
    167   local sep, pStr = package.config:sub(1, 1), ''
    168 
    169   for dir in path:gmatch('[^' .. sep .. ']+') do
    170     pStr = pStr .. sep .. dir
    171 
    172     lfs.mkdir(lfs.currentdir() .. pStr)
    173   end
    174 end
    175 
    176 -- pullfilecontent
    177 function fileutils.pullfilecontent(pathtofile)
    178   local file = assert(io.open(pathtofile, 'r'))
    179 	local content = file:read '*a'
    180 
    181 	file:close()
    182 
    183 	return content
    184 end
    185 
    186 -- pushfilecontent
    187 function fileutils.pushfilecontent(pathtofile, data)
    188   local file = io.open(pathtofile, 'w+')
    189 
    190   file:write(data)
    191 	file:close()
    192 
    193   return assert(fileutils.isFile(pathtofile))
    194 end
    195 
    196 function fileutils.getrelpath(file, contentdir)
    197   return file:sub((contentdir):len() + 1)
    198 end
    199 
    200 function fileutils.sethtmlpath(folder, htmldir)
    201   return htmldir .. folder
    202 end
    203 
    204 function fileutils.removeextension(file)
    205   return file:match('(.+)%..*')
    206 end
    207 
    208 function fileutils.getextension(file)
    209   return file:match('^.+(%..+)$')
    210 end
    211 
    212 function fileutils.getplainname(file)
    213   return fileutils.removeextension(file):match('^.+/(.+)$')
    214 end
    215 
    216 function fileutils.getdirname(file)
    217   return file:match('(.*/)')
    218 end
    219 
    220 function fileutils.getrellink(file, contentdir)
    221   local relpath = fileutils.getrelpath(file, contentdir)
    222 
    223   return (
    224     fileutils.getplainname(file) ~= 'index'
    225       and fileutils.removeextension(relpath) .. '.html'
    226       or fileutils.getdirname(relpath)
    227   )
    228 end
    229 
    230 function fileutils.getpermalink(file, sitedata)
    231   return sitedata.config.baseurl .. (fileutils.getrellink(file, sitedata.content))
    232 end
    233 
    234 function fileutils.setpageid(file, sitedata)
    235   local domainname = sitedata.config.domainname
    236   local date = fileutils.getpageconf(file).date
    237   local relpath = fileutils.getrelpath(file, sitedata.content)
    238 
    239   return 'tag:' .. domainname .. ',' .. date .. ':' .. relpath
    240 end
    241 
    242 function fileutils.getpageconf(pagepath)
    243   local conflua = fileutils.isFile(fileutils.removeextension(pagepath) .. '.lua')
    244   local confjson = fileutils.isFile(fileutils.removeextension(pagepath) .. '.json')
    245   local pageconf
    246 
    247   if conflua then
    248     package.path = package.path .. ';' .. fileutils.getdirname(conflua) .. '/?.lua'
    249     pageconf = require(fileutils.getplainname(conflua))
    250   elseif confjson then
    251     pageconf = json.decode(fileutils.pullfilecontent(confjson))
    252   else
    253     pageconf = {
    254       title = fileutils.getplainname(pagepath):gsub('%W',' '):gsub("^%l", string.upper),
    255       date = os.date('%Y-%m-%d', lfs.attributes(pagepath).modification),
    256       datetime = os.date('%H:%M:%S', lfs.attributes(pagepath).modification),
    257     }
    258   end
    259 
    260   return pageconf
    261 end
    262 
    263 function fileutils.shorturlencode(num)
    264   local alphabet = '23456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ_'
    265 	local base = alphabet:len()
    266 	local str = ''
    267 
    268 	while num > 0 do
    269 		str = string.sub(alphabet, num % base, num % base) .. str
    270 		num = math.floor(num / base)
    271 	end
    272 
    273 	return str
    274 end
    275 
    276 -- Export `fileutils` module
    277 return setmetatable(fileutils, fileutilsmeta)