UNPKG

catlogjs

Version:

Static site generator, translate human readable text format(such as markdown) into html, with a lot of other functions

290 lines (257 loc) 8.23 kB
fs = require 'fs-extra' path = require 'path' _ = require 'underscore' program = require 'commander' inquirer = require 'inquirer' colors = require 'colors' moment = require 'moment' async = require 'async' temp = require 'temp' server = require '../lib/server' directory = require '../lib/directory' parser = require '../lib/parser' render = require '../lib/render.coffee' colors.setTheme({ silly: 'rainbow' input: 'grey' verbose: 'cyan' prompt: 'grey' info: 'green' data: 'grey' help: 'cyan' warn: 'yellow' debug: 'blue' error: 'red' }) import_settings = (to='.') -> to = path.resolve to top = directory.root to, "settings.json" if top is null # check if directory valid console.log 'use `catlog init [to]` to initialize project directory'.error process.exit() global_settings = require '../assets/settings' local_settings = require path.join(top, 'settings.json') local_settings = _.clone _.defaults local_settings, global_settings # reset as relative path local_settings.source = path.join top, local_settings.source local_settings.destination = path.join top, local_settings.destination local_settings.theme_path = path.join top, "themes" local_settings.plugin_path = path.join top, "plugins" # asset_url default to base_url local_settings.asset_url = local_settings.base_url return local_settings create_post = (src, to, callback) -> if (src) console.log "Original markdown file #{src}" content = fs.readFileSync src, 'utf8' settings = import_settings to categories = fs.readdirSync settings.source newCategory = 'Add new category' categories.push newCategory questions = [ { type: 'input' name: 'name' message: 'write your article name' } { type: 'list' name: 'category' message: 'choose article category' choices: categories } { type: 'input' name: 'category' message: 'input new category name' validate: (value) -> value.length isnt 0 filter: (category) -> fs.mkdirSync path.join(settings.source, category) return category when: (answers) -> return answers.category is newCategory } { type: 'input' name: 'title' message: 'input new permalink title' validate: (value) -> value.length isnt 0 } { type: 'input' name: 'author' message: 'input author name' default: settings.author } ] inquirer.prompt questions, (answers) -> # meta data title = answers.title name = answers.name category = answers.category author = answers.author date = moment().format 'YYYY-MM-DD' time = moment().format 'HH:mm:ss' meta = """ { "name": "#{name}", "date": "#{date}", "time": "#{time}", "author": "#{author}" } """ basename = path.join settings.source, category, title fs.mkdirSync basename fs.writeFileSync path.join(basename, 'meta.json'), meta, 'utf8' fs.writeFileSync path.join(basename, 'index.md'), content or '', 'utf8' console.log 'created a new article directory below contents folder.'.prompt console.log "edit article in #{settings.source}/#{category}/#{title}/index.md".prompt callback and callback() cmd_init = (to='.', options) -> init = -> global_settings = require '../assets/settings' assets = path.resolve __dirname, '../assets' to = path.resolve to src = path.join to, global_settings.source dest = path.join to, global_settings.destination console.log 'creates site skeleton structure'.info if not fs.existsSync(src) fs.mkdirSync(src) console.log 'copying default blog content'.info fs.copy "#{assets}/assets/examples", "#{src}/examples" else console.log "#{src} exist, leave without touch".warn if not fs.existsSync(dest) fs.mkdirSync(dest) else console.log "#{dest} exist, leave without touch".warn assets = [ ["#{assets}/plugins", "#{to}/plugins"] ["#{assets}/themes", "#{to}/themes"] ["#{assets}/settings.json", "#{to}/settings.json"] ] for asset in assets if not fs.existsSync asset[1] console.log "copy #{asset[1]}".info fs.copy asset[0], asset[1] else console.log "#{asset[1]} exist, leave without touch".warn try if not fs.readdirSync(to).length or options.force init() else # directory not empty inquirer.prompt { type: 'confirm' name: 'ifProcess' message: 'Current directory not empty, do you really want to process?' default: false }, (answers) -> if answers.ifProcess init() catch err console.log "Directory not exit".error cmd_publish = (to) -> create_post '', to, -> process.stdin.destroy() build = (settings, callback) -> parser.parse settings, (env) -> render.render env cmd_build = (to='.', args) -> settings = import_settings to if args.assetUrl settings.asset_url = args.assetUrl console.log 'copying theme'.info fs.copy "#{settings.theme_path}", "#{settings.destination}/themes", -> console.log 'parse markdown'.info settings.auto = args.auto parser.parse settings, (env) -> console.log 'render html'.info render.render env # static file server if args.server isnt undefined if typeof args.server is 'boolean' port = settings.port else port = args.server server.run {path: settings.destination, port: port} # auto build if args.auto watch settings.source, {followSymLinks: true}, -> build settings cmd_preview = (to='.', args) -> temp.mkdir 'catlog', (err, dirPath) -> console.log "create temp directory #{dirPath}".info settings = import_settings to settings.destination = dirPath settings.base_url = '/' # local server always use root console.log 'copy theme'.info fs.copy "#{settings.theme_path}", "#{settings.destination}/themes", -> settings.auto = args.auto console.log 'parse markdown'.info parser.parse settings, (env) -> console.log 'render markdown'.info render.render env # static file server if args.server isnt undefined and typeof args.server isnt 'boolean' port = args.server else port = settings.port server.run {path: settings.destination, port: port} # auto build if args.auto watch settings.source, {followSymLinks: true}, -> build settings cmd_migrate = (from, to) -> srcs = directory.list from, (src) -> fs.statSync(src).isFile() and path.extname(src) is '.md' async.eachSeries srcs, ((src, callback) -> create_post src, to, callback ), -> process.stdin.destroy() cmd_help = (cmd) -> if cmd command = _.find program.commands, (command) -> command._name is cmd command.outputHelp() else program.help() program .version(require('../package.json').version) program .command('init [to]') .description('initialize project, create new directory before initialize') .option('-f --force', 'force initialize on directory not empty') .action(cmd_init) program .command('publish [to]') .description('publish new article') .action(cmd_publish) program .command('preview [to]') .description('preview generated html files') .option('-s --server [port]', 'start local server') .option('-a --auto', 'watch for file change and auto update') .action(cmd_preview) program .command('build [to]') .description('build html files') .option('-u --asset-url [url]', 'use self defined asset url') .option('-s --server [port]', 'start local server') .option('-a --auto', 'watch for file change and auto update') .action(cmd_build) program .command('migrate <from> [to]') .description('migrate exist markdown file into project') .action(cmd_migrate) program .command('help [cmd]') .description('display command description') .action(cmd_help) program .command('*') .description('unknown') .action(program.help) program.parse process.argv if program.args.length is 0 program.help()