All files index.js

100% Statements 41/41
100% Branches 17/17
100% Functions 8/8
100% Lines 38/38
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 941x 1x 1x             11x 11x 11x     11x     11x 11x 14x 14x 14x     14x 1x 1x       13x 10x       13x       11x 11x 11x 11x                   15x 2x       13x 1x       12x 12x             11x 11x     11x 1x     11x     15x     10x 1x       11x 10x      
const match = require('multimatch')
const isUtf8 = require('is-utf8')
const getTransformer = require('./get-transformer')
 
/**
 * Engine
 */
 
function render({ filename, files, metadata, engineOptions }) {
  return new Promise(resolve => {
    const [base, ...extensions] = filename.split('.')
    const file = files[filename]
 
    // Stringify file contents
    file.contents = file.contents.toString()
 
    // Go through all extensions
    const extLength = extensions.length
    for (let i = 0; i < extLength; i += 1) {
      const ext = extensions.pop()
      const transform = getTransformer(ext)
      const locals = Object.assign({}, metadata, file)
 
      // Stop if the current extension can't be transformed
      if (!transform) {
        extensions.push(ext)
        break
      }
 
      // If this is the last extension, replace it with a new one
      if (extensions.length === 0) {
        extensions.push(transform.outputFormat)
      }
 
      // Transform the contents
      file.contents = transform.render(file.contents, engineOptions, locals).body
    }
 
    // Store results and delete old file
    file.contents = Buffer.from(file.contents)
    files[[base, ...extensions].join('.')] = file // eslint-disable-line no-param-reassign
    delete files[filename] // eslint-disable-line no-param-reassign
    return resolve()
  })
}
 
/**
 * Validate
 */
 
function validate({ filename, files }) {
  // Files without an extension cannot be processed
  if (!filename.includes('.')) {
    return false
  }
 
  // Files that are not utf8 are ignored
  if (!isUtf8(files[filename].contents)) {
    return false
  }
 
  // Files without an applicable jstransformer are ignored
  const extension = filename.split('.').pop()
  return getTransformer(extension)
}
 
/**
 * Plugin
 */
 
module.exports = ({ pattern = '**', engineOptions = {} } = {}) => (files, metalsmith, done) => {
  const metadata = metalsmith.metadata()
 
  // Check whether the pattern option is valid
  if (!(typeof pattern === 'string' || Array.isArray(pattern))) {
    done(new Error('invalid pattern, the pattern option should be a string or array.'))
  }
 
  const matchedFiles = match(Object.keys(files), pattern)
 
  // Filter files by validity
  const validFiles = matchedFiles.filter(filename => validate({ filename, files }))
 
  // Let the user know when there are no files to process, usually caused by missing jstransformer
  if (validFiles.length === 0) {
    done(new Error('no files to process, check whether you have a jstransformer installed.'))
  }
 
  // Map all files that should be processed to an array of promises and call done when finished
  Promise.all(validFiles.map(filename => render({ filename, files, metadata, engineOptions })))
    .then(() => done())
    .catch(/* istanbul ignore next */ error => done(error))
}