UNPKG

html-pages

Version:

Simple development HTTP Server for file serving and directory listing made by a Designer. Use it for hacking your HTML/JavaScript/CSS files but not for deploying your final site.

188 lines (156 loc) 4.48 kB
// Native const path = require('path'); // Packages const pathType = require('path-type'); const filesize = require('filesize'); const fs = require('fs-promise'); const coroutine = require('bluebird').coroutine; const _ = require('lodash'); const moment = require('moment'); // Ours const pkg = require('../package'); const prepareView = require('./view'); // Functions const parseListItem = function (item, fu) { if (_.isUndefined(item)) { item = {}; } if (!_.isObject(item.stats)) { item.stats = {}; } if (_.isUndefined(item.stats.size)) { item.stats.size = '—'; } if (_.isUndefined(item.stats.date)) { item.stats.date = ''; } if (_.isUndefined(item.type)) { item.type = 'parent'; } item.iconIsStructure = true; if (item.type === 'parent') { item.iconPath = fu.getIconFromFileName(null, null, null, true); } else if (item.type === 'dir') { item.iconPath = fu.getIconFromFileName(item.name, item.ext, true); } else { item.iconPath = fu.getIconFromFileName(item.base, item.ext); item.iconIsStructure = false; } return item; }; module.exports = coroutine( function * (port, current, dir, fu) { let filesRaw = []; const subPath = path.relative(current, dir); if (!fs.existsSync(dir)) { return false; } filesRaw = yield fs.readdir(dir); let files = []; for (const file of filesRaw) { const filePath = path.resolve(dir, file); const details = path.parse(filePath); details.title = details.base; details.stats = {}; if (pathType.isDirectorySync(filePath)) { details.base += '/'; details.type = 'dir'; details.stats.size = '—'; } else { details.ext = details.ext.split('.')[1] || ''; details.type = 'file'; } details.relative = path.join(subPath, details.base); if (fu.isNotIgnoredPath(details.relative)) { const fileStats = yield fs.stat(filePath); if (!_.isString(details.stats.size)) { details.stats.sizeRaw = fileStats.size; details.stats.size = filesize(fileStats.size, { round: 1, spacer: ' ', standard: 'jedec' }); } details.stats.time = moment(fileStats.mtime).format('X'); details.stats.date = moment(fileStats.mtime).format( 'DD-MMM-YYYY HH:mm' ); details.stats.birthtime = moment(fileStats.birthtime).format( 'DD-MMM-YYYY HH:mm' ); files.push(details); } } const directory = path.join(path.basename(current), subPath); const pathParts = directory.split(path.sep); let hasParent = false; if (dir.indexOf(current + '/') > -1) { const directoryPath = [...pathParts]; // Remove first element directoryPath.shift(); hasParent = parseListItem({ type: 'parent', base: 'Parent Directory', relative: path.join(...directoryPath, '..'), title: path.join(...pathParts.slice(0, -2), '/') }, fu); } // Parse each file and update information files = _.chain(files) .filter(file => { return _.isObject(file); }) .map(file => { return parseListItem(file, fu); }) .sortBy(file => { return file.name.toLowerCase(); }) .sortBy(file => { // Always show directories first and than the files return file.type === 'dir' ? 2 : 3; }) .value(); const render = prepareView(); const paths = []; for (const part in pathParts) { if (!{}.hasOwnProperty.call(pathParts, part)) { continue; } let before = 0; const parents = []; while (before <= part) { parents.push(pathParts[before]); before++; } parents.shift(); paths.push({ name: pathParts[part], url: parents.join('/') }); } const details = { structure: { name: pkg.title, description: pkg.description, link: pkg.npmJsLink, assetDir: process.env.ASSET_DIR, directory }, author: { username: pkg.author.name, link: pkg.author.url }, breadcrumb: paths, json: JSON.stringify({ layout: global.options.layout, parent: hasParent, files, paths }) }; global.options.layout = false; return render(details); } );