assemble / assemble-permalinks

Permalinks plugin for assemble (0.6+)
MIT License
5 stars 2 forks source link

Should the permalink not be used when rendering? #2

Open rparree opened 8 years ago

rparree commented 8 years ago

I might misunderstand how permalinks should work in when using app.dest

app.create("blog")
    .use(permalink('foo/:name.html'));

app.blogs('./src/templates/blog-pages/**');
var post = app.blogs.getView('src/templates/blog-pages/archive/yadayadayada.hbs');

console.log("out",post.data.permalink ) // shows correctly foo/yadayadayada.html

return app.toStream("blogs")
    .pipe(app.renderFile('*'))
    .pipe(extname())
    .pipe(app.dest('./build/public/blog'));

The value of post.data.permalink is indeed foo/yadayadayada.html, but the file is written into archive/yadayadayada.html

jonschlinkert commented 8 years ago

I'm still working on it, but in the meantime try using a function for dest so you can customize the output. You might be able to do something like:

return app.toStream("blogs")
    .pipe(app.renderFile('*'))
    .pipe(extname())
    .pipe(app.dest(dest('./build/public/blog')));

function dest(dir) {
  return function(file) {
    file.base = path.join(dir, path.dirname(file.data.permalink));
    file.path = file.data.permalink;
    return file.base;
  }
}

you might need to play around with it. I'd like to get it working so that you don't need to do that - but only if I can do it without creating some weird abstraction that ends up making it more confusing

rparree commented 8 years ago

OK great, i'll look into this tomorrow. Looks promising. Would it perhaps be an idea to make permalinks a gulp plugin for these kind of situations:

return app.toStream("blogs")
    .pipe(app.renderFile('*'))
    .pipe(extname())
    .pipe(permalink(....))
    .pipe(app.dest('./build/public/blog'));

That feels kind of natural like rename and extname?

jonschlinkert commented 8 years ago

The main challenge there is that permalinks actually need context from views, front-matter, assemble options and so on. Gulp plugins just wouldn't be the right way to handle it I think, because of the amount of assemble code that would need to be there for it to work.

rparree commented 8 years ago

For refercence to othe users, this is eventually my solution

app.create("blog")
        .use(permalink(':first(categories)/:name.html', {
            first: function (arr) {
                return arr[0];
            }
        }));

and the tail of the gulp pipe with the dest function

   ...
  .pipe(flatten())
  .pipe(app.dest(dest('./build/public/blog')));

    function dest(dir) {
        return function (file) {
            return path.join(dir, path.dirname(file.data.permalink));
        }
    }
jonschlinkert commented 8 years ago

nice thanks! would you want to do a pr to add that to the assemble-permalinks readme? Or I can add it the next time I make edits

rparree commented 8 years ago

Will do.

stefanwalther commented 8 years ago

Hi @rparree ,

could you please post the full code you have, I am struggling in getting the link between

creating a collection

app.create("pages")
        .use(permalinks(':first(categories)/:name.html', {
            first: function (arr) {
                return arr[0];
            }
        }));

and then using the plugin in the collection:

app.src( "pages/**/*.md")
    .on( 'err', console.log )
    .pipe( app.renderFile() )
    .on( 'err', console.log )
    .pipe( debug( {title: "pages:"} ) )
    .pipe( extname() )
    .pipe( app.dest( "./dest/pages" ) )

Permalinks in never called, so what I am missing is instead of using an app.src I should probably pass a glob to the collection pages and then render it, but can nowhere find how to do that.

doowb commented 8 years ago

@stefanwalther you can load the pages onto the collection after creating it by doing this:

app.pages('pages/**/*.md');

Then you can push the loaded pages into the stream with the .toStream method instead of .src:

app.toStream('pages')
    .on( 'err', console.log )
    .pipe( app.renderFile() )
    .on( 'err', console.log )
    .pipe( debug( {title: "pages:"} ) )
    .pipe( extname() )
    .pipe( app.dest( "./dest/pages" ) );
jonschlinkert commented 8 years ago

was just going to comment something similar. Using src like that isn't using the pages collection.

jonschlinkert commented 8 years ago

@stefanwalther I just pushed up 0.3.0, try reinstalling with npm i assemble-permalinks@latest -D

See the pipeline plugin example. You can also do what I'm doing with posts, e.g.:

var posts = app.create('posts')
  .use(permalink('actual/:name/index.html'));

app.task('site', function() {
  // loads views onto `posts`, and all plugins will run against posts
  return posts.src('*.js')
    .pipe(posts.permalink())
    .pipe(posts.dest('.'));
});
rparree commented 8 years ago

Notice i am using a helper function (dest) inside the last pipe, which uses the permalink value to create the correct filename:

  .pipe(app.dest(dest('./build/public/blog')));

    function dest(dir) {
        return function (file) {
            return path.join(dir, path.dirname(file.data.permalink));
        }
    }
stefanwalther commented 8 years ago

@jonschlinkert, thx, will try it immediately.

stefanwalther commented 8 years ago

Hi @jonschlinkert, @doowb & @rparree,

this is the solution which works for me (using the latest version). I had to use gulp-rename to rename the file to "index.html". Absolutely not sure if this is the right way, but it works ;-)

var pagesDef = base.config.collections[0];

    base.app.create("pages")
        .use(permalinks(':name/index.html')); // <== index.html doesn't make a difference here, have to use gulp-rename

    base.app.task( "content:pages", ["load"], function () {
        return base.app.pages.src( pagesDef.src)
            .on( 'err', console.log )
            .pipe( base.app.renderFile() )
            .on( 'err', console.log )
            .pipe( extname() )
            .pipe( rename({
                basename: "index"
            }))
            .pipe( base.app.dest( dest(pagesDef.dest) ) )
            .pipe( debug( {title: "pages:"} ) )
    } );

    function dest(dir) {
        return function (file) {
            return path.join(dir, path.dirname(file.data.permalink));
        }
    }

Result: image

Using @jonschlinkert's example didn't work, files were generated correctly, all fine, but layout handling, etc. did not work. Maybe the layout's need to be loaded always after loading a collection - But that's actually done with the task dependency in my example above?!

Your feedback? Trying to figure out more and more concepts of assemble, so thankful for every feedback. Don't be gentle to me ;-)

Regards Stefan

jonschlinkert commented 8 years ago

but layout handling, etc. did not work

hmm, did you move the app.permalink() into the pipeline after app.renderFile() and extname() but before dest()?

It might just be a bug. More details will help if you want to create another issue. It would be nice to not have to do all that extra config

stefanwalther commented 8 years ago

You can find the working code here: https://github.com/stefanwalther/assemble-scaffold/blob/master/lib/tasks/content-static.js