l0bsterssg

node.js static responsive blog post generator
Log | Files | Refs | README

common.js (6167B)


      1 exports.alphasort = alphasort
      2 exports.alphasorti = alphasorti
      3 exports.setopts = setopts
      4 exports.ownProp = ownProp
      5 exports.makeAbs = makeAbs
      6 exports.finish = finish
      7 exports.mark = mark
      8 exports.isIgnored = isIgnored
      9 exports.childrenIgnored = childrenIgnored
     10 
     11 function ownProp (obj, field) {
     12   return Object.prototype.hasOwnProperty.call(obj, field)
     13 }
     14 
     15 var path = require("path")
     16 var minimatch = require("minimatch")
     17 var isAbsolute = require("path-is-absolute")
     18 var Minimatch = minimatch.Minimatch
     19 
     20 function alphasorti (a, b) {
     21   return a.toLowerCase().localeCompare(b.toLowerCase())
     22 }
     23 
     24 function alphasort (a, b) {
     25   return a.localeCompare(b)
     26 }
     27 
     28 function setupIgnores (self, options) {
     29   self.ignore = options.ignore || []
     30 
     31   if (!Array.isArray(self.ignore))
     32     self.ignore = [self.ignore]
     33 
     34   if (self.ignore.length) {
     35     self.ignore = self.ignore.map(ignoreMap)
     36   }
     37 }
     38 
     39 // ignore patterns are always in dot:true mode.
     40 function ignoreMap (pattern) {
     41   var gmatcher = null
     42   if (pattern.slice(-3) === '/**') {
     43     var gpattern = pattern.replace(/(\/\*\*)+$/, '')
     44     gmatcher = new Minimatch(gpattern, { dot: true })
     45   }
     46 
     47   return {
     48     matcher: new Minimatch(pattern, { dot: true }),
     49     gmatcher: gmatcher
     50   }
     51 }
     52 
     53 function setopts (self, pattern, options) {
     54   if (!options)
     55     options = {}
     56 
     57   // base-matching: just use globstar for that.
     58   if (options.matchBase && -1 === pattern.indexOf("/")) {
     59     if (options.noglobstar) {
     60       throw new Error("base matching requires globstar")
     61     }
     62     pattern = "**/" + pattern
     63   }
     64 
     65   self.silent = !!options.silent
     66   self.pattern = pattern
     67   self.strict = options.strict !== false
     68   self.realpath = !!options.realpath
     69   self.realpathCache = options.realpathCache || Object.create(null)
     70   self.follow = !!options.follow
     71   self.dot = !!options.dot
     72   self.mark = !!options.mark
     73   self.nodir = !!options.nodir
     74   if (self.nodir)
     75     self.mark = true
     76   self.sync = !!options.sync
     77   self.nounique = !!options.nounique
     78   self.nonull = !!options.nonull
     79   self.nosort = !!options.nosort
     80   self.nocase = !!options.nocase
     81   self.stat = !!options.stat
     82   self.noprocess = !!options.noprocess
     83   self.absolute = !!options.absolute
     84 
     85   self.maxLength = options.maxLength || Infinity
     86   self.cache = options.cache || Object.create(null)
     87   self.statCache = options.statCache || Object.create(null)
     88   self.symlinks = options.symlinks || Object.create(null)
     89 
     90   setupIgnores(self, options)
     91 
     92   self.changedCwd = false
     93   var cwd = process.cwd()
     94   if (!ownProp(options, "cwd"))
     95     self.cwd = cwd
     96   else {
     97     self.cwd = path.resolve(options.cwd)
     98     self.changedCwd = self.cwd !== cwd
     99   }
    100 
    101   self.root = options.root || path.resolve(self.cwd, "/")
    102   self.root = path.resolve(self.root)
    103   if (process.platform === "win32")
    104     self.root = self.root.replace(/\\/g, "/")
    105 
    106   // TODO: is an absolute `cwd` supposed to be resolved against `root`?
    107   // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
    108   self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd)
    109   if (process.platform === "win32")
    110     self.cwdAbs = self.cwdAbs.replace(/\\/g, "/")
    111   self.nomount = !!options.nomount
    112 
    113   // disable comments and negation in Minimatch.
    114   // Note that they are not supported in Glob itself anyway.
    115   options.nonegate = true
    116   options.nocomment = true
    117 
    118   self.minimatch = new Minimatch(pattern, options)
    119   self.options = self.minimatch.options
    120 }
    121 
    122 function finish (self) {
    123   var nou = self.nounique
    124   var all = nou ? [] : Object.create(null)
    125 
    126   for (var i = 0, l = self.matches.length; i < l; i ++) {
    127     var matches = self.matches[i]
    128     if (!matches || Object.keys(matches).length === 0) {
    129       if (self.nonull) {
    130         // do like the shell, and spit out the literal glob
    131         var literal = self.minimatch.globSet[i]
    132         if (nou)
    133           all.push(literal)
    134         else
    135           all[literal] = true
    136       }
    137     } else {
    138       // had matches
    139       var m = Object.keys(matches)
    140       if (nou)
    141         all.push.apply(all, m)
    142       else
    143         m.forEach(function (m) {
    144           all[m] = true
    145         })
    146     }
    147   }
    148 
    149   if (!nou)
    150     all = Object.keys(all)
    151 
    152   if (!self.nosort)
    153     all = all.sort(self.nocase ? alphasorti : alphasort)
    154 
    155   // at *some* point we statted all of these
    156   if (self.mark) {
    157     for (var i = 0; i < all.length; i++) {
    158       all[i] = self._mark(all[i])
    159     }
    160     if (self.nodir) {
    161       all = all.filter(function (e) {
    162         var notDir = !(/\/$/.test(e))
    163         var c = self.cache[e] || self.cache[makeAbs(self, e)]
    164         if (notDir && c)
    165           notDir = c !== 'DIR' && !Array.isArray(c)
    166         return notDir
    167       })
    168     }
    169   }
    170 
    171   if (self.ignore.length)
    172     all = all.filter(function(m) {
    173       return !isIgnored(self, m)
    174     })
    175 
    176   self.found = all
    177 }
    178 
    179 function mark (self, p) {
    180   var abs = makeAbs(self, p)
    181   var c = self.cache[abs]
    182   var m = p
    183   if (c) {
    184     var isDir = c === 'DIR' || Array.isArray(c)
    185     var slash = p.slice(-1) === '/'
    186 
    187     if (isDir && !slash)
    188       m += '/'
    189     else if (!isDir && slash)
    190       m = m.slice(0, -1)
    191 
    192     if (m !== p) {
    193       var mabs = makeAbs(self, m)
    194       self.statCache[mabs] = self.statCache[abs]
    195       self.cache[mabs] = self.cache[abs]
    196     }
    197   }
    198 
    199   return m
    200 }
    201 
    202 // lotta situps...
    203 function makeAbs (self, f) {
    204   var abs = f
    205   if (f.charAt(0) === '/') {
    206     abs = path.join(self.root, f)
    207   } else if (isAbsolute(f) || f === '') {
    208     abs = f
    209   } else if (self.changedCwd) {
    210     abs = path.resolve(self.cwd, f)
    211   } else {
    212     abs = path.resolve(f)
    213   }
    214 
    215   if (process.platform === 'win32')
    216     abs = abs.replace(/\\/g, '/')
    217 
    218   return abs
    219 }
    220 
    221 
    222 // Return true, if pattern ends with globstar '**', for the accompanying parent directory.
    223 // Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
    224 function isIgnored (self, path) {
    225   if (!self.ignore.length)
    226     return false
    227 
    228   return self.ignore.some(function(item) {
    229     return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
    230   })
    231 }
    232 
    233 function childrenIgnored (self, path) {
    234   if (!self.ignore.length)
    235     return false
    236 
    237   return self.ignore.some(function(item) {
    238     return !!(item.gmatcher && item.gmatcher.match(path))
    239   })
    240 }