jnordberg / wintersmith

A flexible static site generator
http://wintersmith.io/
MIT License
3.5k stars 334 forks source link

Plugin chaining #144

Open AndersDJohnson opened 11 years ago

AndersDJohnson commented 11 years ago

Is there a way to compose multiple content plugins, e.g. pass some resource through multiple plugin handlers, or is it essentialy first match wins based on the glob patterns from registerContentPlugin()?

AndersDJohnson commented 11 years ago

Ah, it looks like multiple plugins aren't supported? I think that might be an interesting feature to consider adding. It would allow for more composable plugins (think UNIX philosophy).

jnordberg commented 11 years ago

Yeah, this is definitely something i want to have.. but not at the expense of adding too much complexity to the plugin system. The UNIX philosophy only gets you so far, the problem is how do the compositing

Suggestions welcome :) Anyone know of a SSG or similar with an elegant solution to this problem?

fidian commented 11 years ago

I was just about to request this sort of thing myself - a series of preprocessors or postprocessors that could be registered. Right now, I want to embed AsciiMath markup in my markdown files, but I don't want to have client-side translation to MathML or HTML. Instead, I'd like the generated HTML to have MathML and I can load a library to switch that to standard HTML if needed in the browser. So the ideal preprocessor here would load up the page data, modify the contents (rip out AsciiMath and insert MathML) then pass on to the default markdown plugin.

fkrauthan commented 11 years ago

What about the concept of Capistrano each plugin can define after which plugin it should run? The Minifier could say it needs to run after Coffeescript, Typescript, Less Compiler. Or we can define a attribute like pluginOrder: ["Template", "Minifier"] or something like that.

anthony-o commented 11 years ago

Or perhaps more a system like web.xml declaration from the Java world : one could define the order in the config.json ...

gordonbrander commented 10 years ago

One API that can work rather nicely for this sort of thing is chaining file extensions to specify parser and order of execution. E.g.: script.coffee.min.

ghost commented 10 years ago

I wonder if a style similar to gulp might be cool here… maybe instead of using config files, it could use a wintersmithfile.js file that would bring in plugins via require. Then you could use a syntax similar to the following to give fine-grained control:

var ws = require('wintersmith');
var browserify = require('wintersmith-browserify');
var vulcanize = require('wintersmith-vulcanize');
var other = require('wintersmith-other');

ws.contents().pipe(ws.applyTemplate()).pipe(ws.contentTree());

ws.finalContentTree('**/*.js').pipe(browserify()).pipe(other()).pipe(ws.out());
ws.finalContentTree('**/*.html').pipe(vulcanize()).pipe(ws.out());

That syntax could probably be designed better, but hopefully you get the gist of what I'm saying :)

fkrauthan commented 10 years ago

I really like that idea :+1:

AndersDJohnson commented 10 years ago

@wprl A la metalsmith?

ghost commented 10 years ago

Oh, interesting. I had not seen metalsmith. Something very similar to that, but using streams is what I was going for…

dtinth commented 9 years ago

I came across this issue when I want to use Stylus with Autoprefixer. I’ve solved this by creating a gulp plugin adaptor. I called it vinylsmith.

With vinylsmith, you can create Wintersmith plugins that pipes files through a series of Gulp plugins very easily like this:

vinylsmith = require 'vinylsmith'

stylus   = require 'gulp-stylus'
pleeease = require 'gulp-pleeease'
rev      = require 'rev'

module.exports = (env, callback) ->

  env.registerContentPlugin 'styles', '**/*.styl',
    vinylsmith(env)
      .pipe(stylus, 'include css': true)   # compile stylus
      .pipe(pleeease)                      # autoprefix, minify
      .pipe(rev)                           # asset-hashing

  callback()

Now your main.styl will get compiled into main-1682966244.css, postprocessed and minified with pleeease, and filename hashed with gulp-rev.

fidian commented 9 years ago

Composing a plugin from others seems like a good solution for a one-off project. The drawback I see is that I'd have to make a new Wintersmith plugin for every combination of things that I'd like. If I have two different projects and they have different requirements, I'd have to make two different plugins. The plugins I generate wouldn't be as useful for friends because they may want an extra processing step or for the order/options to be changed.

dtinth commented 9 years ago

That’s true. But just as different project uses different gulpfile.js, so I think it is the same with Wintersmith. Different static sites have different requirements for processing pipeline.

If creating such plugin is painless, then I think it wouldn’t be a problem if each static site has their own plugin. In fact, this is what I am doing with vinylsmith: to make creating Wintersmith plugin as trivial as writing a gulpfile, so that each static site can have its own plugin.

fkrauthan commented 9 years ago

Why don't implement such a plugin grouping/pipeline within wintersmith? Creating a way to chain multiple plugins and export that as an "virtual" plugin that can be applied to pages?