From 97e76593c2dc71474b8c1a7d7816bf98063f68be Mon Sep 17 00:00:00 2001 From: Benjamin Lupton Date: Wed, 2 Jan 2013 20:44:33 +0800 Subject: [PATCH] v6.21.0. Improvement. Bugfix. - v6.21.0 January 2, 2013 - Cleanup focused around loading, parsing, and writing of files and documents - Added - `DocPad::flowDocument` - `DocPad::loadDocument` - `exists` attribute on `File` model - Fixed - `Document::writeSource` --- CONTRIBUTING.md | 2 +- History.md | 8 ++ LICENSE.txt | 2 +- README.md | 2 +- package.json | 2 +- src/lib/docpad.coffee | 81 ++++++++++++++++--- src/lib/models/document.coffee | 32 +++++--- src/lib/models/file.coffee | 88 +++++++++++++-------- test/out-expected/attributes-nolayout.txt | 1 + test/out-expected/attributes-withlayout.txt | 2 + 10 files changed, 160 insertions(+), 60 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bf9bf588..e7a3c0da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ ## Support 1. Use the GitHub Issues only for development tasks and bug reports -1. For anything else (questions, support, etc) use our [Official Support Channels](http://bevry.me/support) +1. For anything else (questions, support, etc) use our [Official Support Channels](http://docpad.org/support) 1. With bug reports, be sure to specify: 1. Your docpad version `docpad --version` 1. Your node version `node --version` diff --git a/History.md b/History.md index 7cd956e0..b44f44ec 100755 --- a/History.md +++ b/History.md @@ -1,5 +1,13 @@ ## History +- v6.21.0 January 2, 2013 + - Cleanup focused around loading, parsing, and writing of files and documents + - Added + - `DocPad::flowDocument` + - `DocPad::loadDocument` + - `exists` attribute on `File` model + - Fixed `Document::writeSource` + - v6.20.1 December 24, 2012 - Fixed `File::writeSource` - Thanks to [ashnur](https://github.com/ashnur) for [pull request #381](https://github.com/bevry/docpad/pull/381) diff --git a/LICENSE.txt b/LICENSE.txt index 13cd6ab2..d71eb8b1 100755 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ (The MIT License) -Copyright (c) 2012 Bevry Pty Ltd +Copyright (c) 2012+ Bevry Pty Ltd Copyright (c) 2011 Benjamin Lupton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 5ffa27b7..0abf6691 100755 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ You can discover the version history inside the [History.md](https://github.com/ ## License Licensed under the incredibly [permissive](http://en.wikipedia.org/wiki/Permissive_free_software_licence) [MIT License](http://creativecommons.org/licenses/MIT/) -
Copyright © 2012 [Bevry Pty Ltd](http://bevry.me) +
Copyright © 2012+ [Bevry Pty Ltd](http://bevry.me)
Copyright © 2011 [Benjamin Lupton](http://balupton.com) diff --git a/package.json b/package.json index 66952ab4..06d1ce11 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "docpad", - "version": "6.20.1", + "version": "6.21.0", "description": "DocPad is a language agnostic document management system. This means you write your website as documents, in whatever language you wish, and DocPad will handle the compiling, templates and layouts for you. For static documents it will generate static files, for dynamic documents it'll re-render them on each request. You can utilise DocPad by itself, or use it as a module your own custom system. It's pretty cool, and well worth checking out. We love it.", "homepage": "https://github.com/bevry/docpad", "installUrl": "http://docpad.org/install", diff --git a/src/lib/docpad.coffee b/src/lib/docpad.coffee index 6aca3fb5..60633086 100755 --- a/src/lib/docpad.coffee +++ b/src/lib/docpad.coffee @@ -1383,7 +1383,7 @@ class DocPad extends EventEmitterEnhanced }) .on('add', (model) -> docpad.log('debug', util.format(locale.addingDocument, model.attributes.fullPath)) - _.defaults(model.attributes,{ + model.setDefaults({ isDocument: true render: true write: true @@ -1397,7 +1397,7 @@ class DocPad extends EventEmitterEnhanced }) .on('add', (model) -> docpad.log('debug', util.format(locale.addingFile, model.attributes.fullPath)) - _.defaults(model.attributes,{ + model.setDefaults({ isFile: true render: false write: true @@ -1411,7 +1411,7 @@ class DocPad extends EventEmitterEnhanced }) .on('add', (model) -> docpad.log('debug', util.format(locale.addingLayout, model.attributes.fullPath)) - _.defaults(model.attributes,{ + model.setDefaults({ isLayout: true render: false write: false @@ -1443,7 +1443,9 @@ class DocPad extends EventEmitterEnhanced }) .on('add', (model) -> docpad.log('debug', util.format(locale.addingStylesheet, model.attributes.fullPath)) - model.attributes.referencesOthers = true + model.setDefaults({ + referencesOthers: true + }) ) ) @@ -2701,58 +2703,115 @@ class DocPad extends EventEmitterEnhanced # --------------------------------- # Render - # Load and Render a Document + # Flow through a Document # next(err,document) - loadAndRenderDocument: (document,opts,next) -> + flowDocument: (document,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) + + # Flow balUtil.flow( object: document - action: 'load contextualize render' + action: opts.action args: [opts] next: (err) -> - result = document.getOutContent() - return next(err,result,document) + return next?(err,document) ) + + # Chain + @ + + # Load a Document + # next(err,document) + loadDocument: (document,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) + opts.action or= 'load contextualize' + + # Flow + @flowDocument(document, opts, next) + + # Chain + @ + + # Load and Render a Document + # next(err,document) + loadAndRenderDocument: (document,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) + opts.action or= 'load contextualize render' + + # Flow + @flowDocument document, opts, (err) -> + result = document.getOutContent() + return next?(err,result,document) + + # Chain @ # Render Document # next(err,result) renderDocument: (document,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) + + # Render document.render(opts,next) + + # Chain @ # Render Path # next(err,result) renderPath: (path,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) attributes = balUtil.extend({ fullPath: path },opts.attributes) + + # Handle document = @ensureDocument(attributes) @loadAndRenderDocument(document,opts,next) + + # Chain @ # Render Data # next(err,result) renderData: (content,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) attributes = balUtil.extend({ filename: opts.filename data: content },opts.attributes) + + # Handle document = @createDocument(attributes) @loadAndRenderDocument(document,opts,next) + + # Chain @ # Render Text # Doesn't extract meta information, or render layouts # next(err,result) renderText: (text,opts,next) -> + # Prepare + [opts,next] = balUtil.extractOptsAndCallback(opts,next) + opts.actions ?= ['renderExtensions','renderDocument'] attributes = balUtil.extend({ filename: opts.filename data: text body: text content: text },opts.attributes) + + # Handle document = @createDocument(attributes) - opts.actions ?= ['renderExtensions','renderDocument'] + + # Flow balUtil.flow( object: document action: 'normalize contextualize render' @@ -2761,6 +2820,8 @@ class DocPad extends EventEmitterEnhanced result = document.getOutContent() return next(err,result,document) ) + + # Chain @ # Render Action diff --git a/src/lib/models/document.coffee b/src/lib/models/document.coffee index 2c8671cc..da3293e1 100755 --- a/src/lib/models/document.coffee +++ b/src/lib/models/document.coffee @@ -138,13 +138,13 @@ class DocumentModel extends FileModel switch parser when 'cson', 'coffee', 'coffeescript', 'coffee-script' CSON = require('cson') unless CSON - meta = CSON.parseSync(header) - @meta.set(meta) + metaData = CSON.parseSync(header) + meta.set(metaData) when 'yaml' YAML = require('yamljs') unless YAML - meta = YAML.parse(header) - @meta.set(meta) + metaData = YAML.parse(header) + meta.set(metaData) else err = new Error("Unknown meta parser: #{parser}") @@ -166,26 +166,28 @@ class DocumentModel extends FileModel ) # Correct data format - metaDate = @meta.get('date') + metaDate = meta.get('date') if metaDate metaDate = new Date(metaDate) - @meta.set({date:metaDate}) + meta.set({date:metaDate}) # Correct ignore - ignored = @meta.get('ignored') or @meta.get('ignore') or @meta.get('skip') or @meta.get('draft') or (@meta.get('published') is false) - @meta.set({ignored:true}) if ignored + ignored = meta.get('ignored') or meta.get('ignore') or meta.get('skip') or meta.get('draft') or (meta.get('published') is false) + meta.set({ignored:true}) if ignored # Handle urls - metaUrls = @meta.get('urls') - metaUrl = @meta.get('url') + metaUrls = meta.get('urls') + metaUrl = meta.get('url') @addUrl(metaUrls) if metaUrls @addUrl(metaUrl) if metaUrl # Apply meta to us - @set(@meta.toJSON()) + @set(meta.toJSON()) # Next next() + + # Chain @ # Normalize data @@ -612,10 +614,12 @@ class DocumentModel extends FileModel writeSource: (next) -> # Prepare file = @ + meta = @getMeta() CSON = require('cson') unless CSON + # Fetch fullPath = @get('fullPath') - content = @get('content') + content = (@getContent() or '').toString() parser = 'cson' seperator = '---' @@ -623,7 +627,9 @@ class DocumentModel extends FileModel file.log 'debug', "Writing the source file: #{fullPath}" # Adjust - header = CSON.stringifySync(@meta.toJSON()) + metaData = meta.toJSON() + console.log({metaData}) + header = CSON.stringifySync(metaData) content = body = content.replace(/^\s+/,'') source = "#{seperator} #{parser}\n#{header}\n#{seperator}\n\n#{body}" diff --git a/src/lib/models/file.coffee b/src/lib/models/file.coffee index 37d961f7..c87b5e63 100755 --- a/src/lib/models/file.coffee +++ b/src/lib/models/file.coffee @@ -109,6 +109,9 @@ class FileModel extends Model # The date object for when this document was last modified mtime: null + # Does the file actually exist on the file system + exists: null + # --------------------------------- # Content variables @@ -284,26 +287,38 @@ class FileModel extends Model initialize: (attrs,opts) -> # Prepare {outDirPath,stat,data,meta} = opts - if attrs.data? - data = attrs.data - delete attrs.data - delete @attributes.data + + # Special + @outDirPath = outDirPath if outDirPath + + # Defaults defaults = extensions: [] urls: [] id: @cid - # Apply - @outDirPath = outDirPath if outDirPath - @setData(data) if data + # Stat if stat @setStat(stat) else defaults.ctime = new Date() defaults.mtime = new Date() + + # Defaults @set(defaults) + # Data + if attrs.data? + data = attrs.data + delete attrs.data + delete @attributes.data + if data + @setData(data) + # Meta + if attrs.meta? + @setMeta(attrs.meta) + delete attrs.meta if meta @setMeta(meta) @@ -328,6 +343,7 @@ class FileModel extends Model # Prepare {opts,next} = @getActionArgs(opts,next) file = @ + exists = opts.exists ? false # Normalize fullPath = @get('fullPath') @@ -349,44 +365,50 @@ class FileModel extends Model return next(err) if err return next(null,file.buffer) - # Read the data if it is set - tasks.push (complete) -> - data = file.getData() - if data - buffer = new Buffer(data) - file.setBuffer(buffer) - return tasks.exit() - else - return complete() + # If data is set, use that as the buffer + data = file.getData() + if data + buffer = new Buffer(data) + file.setBuffer(buffer) + + # If stat is set, use that + if opts.stat + file.setStat(opts.stat) + + # If buffer is set, use that + if opts.buffer + file.setBuffer(opts.buffer) # Stat the file and cache the result tasks.push (complete) -> - # Check for override stat - if opts.stat - file.setBuffer(opts.stat) - return complete() - # Otherwise fetch new stat - balUtil.stat fullPath, (err,fileStat) -> - return complete(err) if err - file.setStat(fileStat) + if fullPath and exists and opts.stat? is false + return balUtil.stat fullPath, (err,fileStat) -> + return complete(err) if err + file.setStat(fileStat) + return complete() + else return complete() # Read the file and cache the result tasks.push (complete) -> - # Check for override buffer - if opts.buffer - file.setBuffer(opts.buffer) - return complete() - # Otherwise fetch new buffer - balUtil.readFile fullPath, (err,buffer) -> - return complete(err) if err - file.setBuffer(buffer) + if fullPath and exists and opts.buffer? is false + return balUtil.readFile fullPath, (err,buffer) -> + return complete(err) if err + file.setBuffer(buffer) + return complete() + else return complete() # Run the tasks - tasks.sync() + if fullPath + balUtil.exists fullPath, (_exists) -> + exists = _exists + file.set({exists:true}) + tasks.async() + else + tasks.async() # Chain @ diff --git a/test/out-expected/attributes-nolayout.txt b/test/out-expected/attributes-nolayout.txt index a83de191..2f2a3d47 100755 --- a/test/out-expected/attributes-nolayout.txt +++ b/test/out-expected/attributes-nolayout.txt @@ -7,6 +7,7 @@ "contentType": "application/octet-stream", "dynamic": false, "encoding": "utf8", + "exists": true, "extension": "coffee", "extensions": [ "txt", diff --git a/test/out-expected/attributes-withlayout.txt b/test/out-expected/attributes-withlayout.txt index 1429cde5..59965900 100755 --- a/test/out-expected/attributes-withlayout.txt +++ b/test/out-expected/attributes-withlayout.txt @@ -58,6 +58,7 @@ text JSON.stringify(sortedAttrs,null,'\\t')", "contentType": "application/octet-stream", "dynamic": false, "encoding": "utf8", + "exists": true, "extension": "coffee", "extensions": [ "txt", @@ -149,6 +150,7 @@ text JSON.stringify(sortedAttrs,null,'\\t')", "contentType": "application/octet-stream", "dynamic": false, "encoding": "utf8", + "exists": true, "extension": "coffee", "extensions": [ "txt",