tasks/assemble.js
function(currentPage, assemble, callback) {
    var options = assemble.options;

    grunt.verbose.writeln('Currentpage: ' + currentPage);

    var pageContext = currentPage.data;
    var layout = _.cloneDeep(options.defaultLayout);
    var data = options.data;
    var pages = options.pages;
    var collections = options.collections;
    var context = {};

    grunt.verbose.writeln('Variables loaded');

    try {

      // omit the collections from pageContext when merging
      var pageCollections = _.pick(pageContext, _.keys(collections));
      pageContext = _.omit(pageContext, _.keys(collections));

      options.data = undefined;
      options.pages = undefined;
      options.layout = undefined;
      options.collections = undefined;
      context = _.extend({}, context, assemble.util.filterProperties(options), data, pageContext);
      options.data = data;
      options.pages = pages;
      options.collections = collections;

      // if pageContext contains a layout, use that one instead
      // of the default layout
      if (pageContext && (pageContext.layout || pageContext.layout === false || pageContext.layout === 'none')) {

        var pageLayout = null;

        context = processContext(grunt, context);

        loadLayout(
          context.layout,
          assemble,
          function(err, results) {
            if (!err) {
              pageLayout = results;
            } else {
              grunt.warn(err.message);
            }
          }
        );

        if (pageLayout) {
          layout = pageLayout;
          context.layoutName = pageLayout.layoutName;
          data = _.extend({}, data, pageLayout.data);

        }
      }

      // extend again
      options.pages = undefined;
      options.layout = undefined;
      options.collections = undefined;
      context = _.extend({}, context, assemble.util.filterProperties(options), layout.data, data, pageContext);
      options.data = data;
      options.pages = pages;
      options.collections = collections;

      // add omitted collections back to pageContext
      pageContext = _.merge(pageContext, pageCollections);
      context = processContext(grunt, context);

      // process the current page data
      currentPage.data = processContext(grunt, context, currentPage.data);

      // add the list of pages back to the context so it's available in the templates
      context.pages = pages;
      context.page = currentPage;

      // apply any data for this page to the page object
      context.page = _.extend({}, (context[currentPage.basename] || {}), currentPage.data, context.page);

      // make sure the currentPage assets is used
      context.assets = currentPage.assets;

      // add other page variables to the main context
      context.dirname = path.dirname(currentPage.dest);
      context.absolute = currentPage.dest;
      context.filename = currentPage.filename;
      context.pageName = currentPage.filename; // "pageName" is deprecated, use "pagename" or "filename"
      context.pagename = currentPage.filename;
      context.basename = currentPage.basename;
      context.extname = currentPage.ext;

      context.page.page = injectBody(layout.layout, context.page.page);

      // Run any plugins for the 'render:pre:page' stage
      assemble.plugins.runner('render:pre:page', {
        grunt: grunt,
        assemble: assemble,
        context: context
      })(function() {
        assemble.engine.render(context.page.page, context, function(err, content) {
          if (err) {
            callback(err);
          }
          callback(null, content);
        });
      });

    } catch (err) {
      callback(err);
      return;
    }
  }
function(currentPage, assemble, callback) {
    var options = assemble.options;

    grunt.verbose.writeln('Currentpage: ' + currentPage);

    var pageContext = currentPage.data;
    var layout = _.cloneDeep(options.defaultLayout);
    var data = options.data;
    var pages = options.pages;
    var collections = options.collections;
    var context = {};

    grunt.verbose.writeln('Variables loaded');

    try {

      // omit the collections from pageContext when merging
      var pageCollections = _.pick(pageContext, _.keys(collections));
      pageContext = _.omit(pageContext, _.keys(collections));

      options.data = undefined;
      options.pages = undefined;
      options.layout = undefined;
      options.collections = undefined;
      context = _.extend({}, context, assemble.util.filterProperties(options), data, pageContext);
      options.data = data;
      options.pages = pages;
      options.collections = collections;

      // if pageContext contains a layout, use that one instead
      // of the default layout
      if (pageContext && (pageContext.layout || pageContext.layout === false || pageContext.layout === 'none')) {

        var pageLayout = null;

        context = processContext(grunt, context);

        loadLayout(
          context.layout,
          assemble,
          function(err, results) {
            if (!err) {
              pageLayout = results;
            } else {
              grunt.warn(err.message);
            }
          }
        );

        if (pageLayout) {
          layout = pageLayout;
          context.layoutName = pageLayout.layoutName;
          data = _.extend({}, data, pageLayout.data);

        }
      }

      // extend again
      options.pages = undefined;
      options.layout = undefined;
      options.collections = undefined;
      context = _.extend({}, context, assemble.util.filterProperties(options), layout.data, data, pageContext);
      options.data = data;
      options.pages = pages;
      options.collections = collections;

      // add omitted collections back to pageContext
      pageContext = _.merge(pageContext, pageCollections);
      context = processContext(grunt, context);

      // process the current page data
      currentPage.data = processContext(grunt, context, currentPage.data);

      // add the list of pages back to the context so it's available in the templates
      context.pages = pages;
      context.page = currentPage;

      // apply any data for this page to the page object
      context.page = _.extend({}, (context[currentPage.basename] || {}), currentPage.data, context.page);

      // make sure the currentPage assets is used
      context.assets = currentPage.assets;

      // add other page variables to the main context
      context.dirname = path.dirname(currentPage.dest);
      context.absolute = currentPage.dest;
      context.filename = currentPage.filename;
      context.pageName = currentPage.filename; // "pageName" is deprecated, use "pagename" or "filename"
      context.pagename = currentPage.filename;
      context.basename = currentPage.basename;
      context.extname = currentPage.ext;

      context.page.page = injectBody(layout.layout, context.page.page);

      // Run any plugins for the 'render:pre:page' stage
      assemble.plugins.runner('render:pre:page', {
        grunt: grunt,
        assemble: assemble,
        context: context
      })(function() {
        assemble.engine.render(context.page.page, context, function(err, content) {
          if (err) {
            callback(err);
          }
          callback(null, content);
        });
      });

    } catch (err) {
      callback(err);
      return;
    }
  }
========================================================================== BUILD ==========================================================================