solidusjs / solidus

A simple server that generates pages from JSON and Templates
MIT License
28 stars 7 forks source link

View reusability - DEPRECATED #107

Closed joanniclaborde closed 9 years ago

joanniclaborde commented 10 years ago

Fixes #106.

Preprocessors

A new site config file is introduced: /preprocessors.js. Instead of specifying the resources and preprocessors to use in each template directly, all that information is moved to this new config file. Also, resources are now part of preprocessors.

This file is basically a map between a view an a preprocessor. A preprocessor is an object with two (optional) properties: resources (object of resources) and process (function that receives and returns the current context).

/preprocessors.js

module.exports = {
  'page.hbs': function() {
    return {
      resources: {
        stuff: "http://stuff.com/stuff"
      },
      process: function(context) {
        context.stuff = true;
        return context;
      }
    };
  },

  'partial.hbs': function() {
    return require('./preprocessors/partial.js');
  }
}

Each preprocessor can also be moved to a separate file in the /preprocessors directory. Each preprocessor file will later be accessible by the client application, so it can request its resources and run its process function dynamically.

/preprocessors/partial.js

module.exports.resources = {
  tweets: "http://twitter.com/tweets"
}

module.exports.process = function(context) {
  context.first_tweets = resources.tweets[0];
  return context;
}

Resource endpoint

The client app is now able to retrieve a resource directly, without going through a page rendering, with the new /api/resource.json?url=... route. The resource will be fetched just like if it was requested through a preprocessor, with the right security and caching.

<script>
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", '/api/resource.json?url=' + encodeURIComponent('http://something.com'), false);
xmlHttp.send(null);
var context = {resources: {something: JSON.parse(xmlHttp.responseText)}};
var partial = Handlebars.partials['partial'](context);
document.write(partial);
</script>
joanniclaborde commented 10 years ago

Future grunt task to bundle the preprocessors:

    browserify: {
      preprocessors: {
        files: {
          'assets/compiled/preprocessors.js': '!*', // We don't need an entry point
        },
        options: {
          require: grunt.file.expand('./preprocessors/**/*.js')
        }
      }
    },
joanniclaborde commented 10 years ago

Views can be used by the client app (templates were already available through templates.js), and now preprocessors and resources too. What is missing is a nice helper library for the resources and preprocessors, but this should go in a different issue I think.

joanniclaborde commented 10 years ago

Also, the tests could use a good clean up someday...

joanniclaborde commented 10 years ago

Having looked at @pushred's use of this new feature, I suggest some modifications.

Server

Moving preprocessors into separate shared modules is not very useful for small tasks. We could instead support multiple preprocessors.js-like files:

/preprocessors/index.js

module.exports = {
  'index.hbs': function() {
    return {
      resources: {...},
      process: function(context) {...}
    };
  },
  'news.hbs': function() {...}
}

/preprocessors/events.js

var tool = require('../lib/tool.js');
module.exports = {
  'events/index.hbs': function() {
    return {
      resources: {...},
      process: function(context) {
        context.something = tool(...);
        return context;
      }
    };
  },
  'events/recent.hbs': function() {...},
  'events/{id}.hbs': function() {...}
}

etc.

Basically all the files in /preprocessors would be combined. Shared modules would need to be moved somewhere else, like /lib.

Client

Instead of asking the dev to deal with templates, resources and preprocessors separately, some utility functions should be used to replicate the server behaviours.

var view = solidus.getView('events/{id}.hbs');

// Render the view as a partial, will use the resources and preprocessor defined on the server
var html = view.render({id: 123});

// Or change the resources and preprocessor before rendering
view.resources.new_one = 'http://...';
view.process = function(context) {
  context.something = context.resources.new_one.description;
  return context;
};
var html = view.render({id: 123});

Thoughts?

localjo commented 10 years ago

I was discussing with @pushred that we need a way of defining a preprocessor that applies to every template using globs. The ability to do that would be especially useful for Clique Tools migrations, such as https://github.com/SparkartGroupInc/cliquehere.com/pull/1 where there are are multiple preprocessors that need to be included for each template: https://github.com/SparkartGroupInc/cliquehere.com/blob/migration/preprocessors/global.js

pushred commented 9 years ago

After #109 is released this should be rebased on top for use in migration projects

joanniclaborde commented 9 years ago

Did you mean #116? This PR is old, not sure we need it any more...