Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

permalinks not finding front matter #5

Open
rparree opened this issue Apr 2, 2016 · 5 comments
Open

permalinks not finding front matter #5

rparree opened this issue Apr 2, 2016 · 5 comments

Comments

@rparree
Copy link

rparree commented Apr 2, 2016

I am in the process of creating a docker image for my site. During the process i am upgrading as much as i can (node 4.4.2 , assemble: ~0.16.0, assemble-permalinks: 0.3.1).

However now the permalinks no longer find data from the front matter data:

The code

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

Now throws an error that it can't find categories.

/home/foo/bar/app/build.js:202
    if (err) throw err
             ^

ReferenceError: categories is not defined
    at eval (engine.templateSources[1]:9:17)
    at Engine.render (/home/foo/bar/main/edc4it-web/app/node_modules/assemble-permalinks/node_modules/placeholders/node_modules/expand/node_modules/engine/index.js:315:27)
    at render (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/node_modules/placeholders/node_modules/expand/index.js:139:24)
    at resolveString (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/node_modules/placeholders/node_modules/expand/index.js:40:15)
    at resolve (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/node_modules/placeholders/node_modules/expand/index.js:14:16)
    at interpolate (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/node_modules/placeholders/index.js:23:12)
    at View.<anonymous> (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/index.js:72:31)
    at View.plugin (/home/foo/bar/main/zoo/app/node_modules/assemble-permalinks/index.js:86:29)
    at View.use (/home/foo/bar/main/zoo/app/node_modules/assemble-core/node_modules/templates/node_modules/base-plugins/index.js:94:18)
    at Views.<anonymous> (/home/foo/bar/main/zoo/app/node_modules/assemble-core/node_modules/templates/node_modules/base-plugins/index.js:69:13)
@assemblebot
Copy link

@rparree Thanks for the issue! If you're reporting a bug, please be sure to include:

  • The version of assemble you are using.
  • Your assemblefile.js (This can be in a gist)
  • The commandline output. (Screenshot or gist is fine)
  • What you expected to happen instead.

@doowb
Copy link
Member

doowb commented Apr 13, 2016

@rparree sorry for missing this before.

This plugin will use view.data, but that needs to be populated first. In assemble there is built-in onLoad middleware that will parse the frontmatter and add it to view.data, but this happens after the plugins are added.

When the permalinks plugin is given a pattern, it tries to execute immediately (on the view) so the data hasn't been loaded yet.

There are a couple of ways to use this to ensure the data is present when creating the permalink:

  • Add plugin to collection without a pattern and use the pipeline plugin to create the permalink
app.create('blog')
  .use(permalink({
    first: function (arr) {
      return arr ? arr[0] : "";
    }
  }));

app.toStream('blog')
  .pipe(app.permalink('blog/:first(categories)/:name.html'));
  • Add plugin to collection without a pattern and use a custom pipeline plugin to create the permalink using the view's permalink method
app.create('blog')
  .use(permalink({
    first: function (arr) {
      return arr ? arr[0] : "";
    }
  }));

app.toStream('blog')
  .pipe(through.obj(function(file, enc, next) {
    file.permalink('blog/:first(categories)/:name.html'));
    next(null, file);
  }));

The differences between these are that the app.permalinks() pipeline plugin updates the file.dest property with the permalink after it's created and the file.permalink() method does not. If you just want to calculate the permalink for use in templates when rendering (data.permalink property), then use the second approach. If you've already rendered and just want to change the dest to the permalink structure, use the first approach.

You might also want to take a look at what we're doing in the assemble docs. We're using a custom plugin (view-events) to bubble up the permalink event to an application level handler called onPermalink where we merge the app data onto the view data. There is a little work around going on because of the frontmatter loading so it looks a little more complicated. I'm working on cleaning this up so there isn't so much code. I'll post back here when that's done and it might be a better solution for you also.

@doowb
Copy link
Member

doowb commented Apr 14, 2016

@rparree I updated this plugin so that it makes use of the onLoad middleware to ensure that frontmatter is loaded before attempting to create the permalink.

I am getting "TypeError: app.permalink is not a function".

Sorry, the app.permalink pipeline plugin method will only be available on app if you use this as an app plugin: e.g. app.use(permalink()).

If you use it on a collection: app.create('blog').use(permalink()) then you'll need to use the method from the collection: app.blog.permalink().

Let me know if this is working for you. I've updated the assemblefile.js in the assemble docs to use this plugin on a collection.

@rparree
Copy link
Author

rparree commented May 2, 2016

The following seems to work, but i now have another problem (see underneath the code)

app.create("blog")
    .use(permalinks({
        first: function (arr) {
            return arr ? arr[0] : ""
        }
    }));

app.blogs(['./src/templates/blog-pages/**', '!./src/templates/blog-pages/index*']);

function dest(dir) {
        return function (file) {
            var s = path.join(dir, path.dirname(file.data.permalink) + "/");
            return s;
        }
    }

 app.toStream("blogs")
        .pipe(flatten())
        .pipe(app.permalink('blog/:first(categories)/:name.html'))
        .pipe(app.renderFile('*'))
        .pipe(extname())
        .pipe(app.dest(dest("./build/public/blog")));

In another file (in its own collection) i used to create links to the blog pages, but after a few (32 to be exact) the value the value of permalinks in the helper below is undefined

// absurl
module.exports =  function(basedir){
    return function(context){
        return "/" + context.data.permalink
    }
};

The helper absurl is used like

{{#each blogs  }}

        <a href="{{absurl .}}" >
            <div class="grid-item {{#each data.categories}} cat-{{this}} {{/each}}"
                 data-date="{{formatDate data.date 'YYYYMMDD'}}" data-categories="{{data.categories}}">

                <span class="title">{{data.title}}</span></div></a>

{{/each}}

An example rendered result is:

<!-- above also all working correctly-->
<a href="/blog/web/get-familiar-with-backbone-js.html" >
    <div class="grid-item  cat-web "
         data-date="20130920" data-categories="web">

        <span class="title">Get Familiar with Backbone.js</span></div></a>


<a href="/undefined" >
    <div class="grid-item  cat-java "
         data-date="20140408" data-categories="java">

        <span class="title">Glassfish - Commercial to Open Source</span></div></a>

<!-- all below have "undefined" -->

@rparree
Copy link
Author

rparree commented May 2, 2016

Never mind the last problem, async problem. Solved it by processing the index after the articles have completed:

app.build('assemble-blog', function (err) {
    if (err) throw err;
    app.build('assemble-blog-index', function (err) {
        if (err) throw err
    });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants