kalamuna / metalsmith-jstransformer

Metalsmith JSTransformers Plugin
http://npm.im/metalsmith-jstransformer
MIT License
7 stars 9 forks source link

How to get equivalent configuration as with metalsmith-layouts? #33

Closed lunelson closed 4 years ago

lunelson commented 6 years ago

So, I'm hoping to switch to this plugin from metalsmith-layouts because I've read that it might be faster, but right now I'm just getting blank outputs.

My current build uses metalsmith-markdown followed by metalsmith-layouts like this:

.use(markdown())
.use(
  layouts({
    engine: 'pug',
    default: 'default.pug',
    directory: 'templates',
    pattern: '**/*.html',
    pretty: true,
    ...pugOptions
  })
)

...and what I've tried so far with this plugin is this:

.use(
  jstransformer({
    pattern: '**',
    layoutPattern: 'templates',
    defaultLayout: 'default.pug',
    engineOptions: {
      pug: { pretty: true, ...pugOptions }
    },
    engineLocals: {
      pug: pugOptions
    }
  })
)

But with that config, markdown content is processed where it exists but the pug layouts are not being applied. FYI, content filenames look like this; they each have a layout key in which I indicate which pug file to pick up.

company_de.md
company_en.md
contact_de.md
contact_en.md
imprint_de.md
imprint_en.md

Any hints?

Sidebar: the pugLocals variable is imported from another file where I prep the pug options and locals as one object, including keys such as basedir which is necessary for includes and extends, and several helper functions. Which also raises the related question: how should I configure engineOptions and engineLocals for pug, which normally takes both options and locals in one object?

RobLoach commented 6 years ago

Layoutpattern needs to be a wildcard I think. Default layout needs to be relative from the src root.

May be faster because it caches the layouts, can't make that promise without some benchmarks, however.

lunelson commented 6 years ago

OK I've been looking through the source; I think the problem for me is that this plugin relies on the layout files being within the source tree parsed by the metalsmith .source() method. I'm tempted to fork this and see if I can make it work with an external directory—it seems there's a metalsmith.dir method—because that configuration won't work with my setup. My source folder results from a data-dump from datoCMS and gets wiped out each time it updates, so my locale and layout files have to be siblings of the source dir rather than children

RobLoach commented 6 years ago

You could also try running something similar to metalsmith-assets to bring in the layouts prior to running this plugin.

metalsmith-jstranformer makes use of the layout's frontmatter, which is why the layouts are expected to be in the source directory.

layoutPattern: templates/**
defaultLayout: templates/default.pug

Doc update: https://github.com/RobLoach/metalsmith-jstransformer/pull/34

The other thing we could do is have an option to trigger metalsmith-assets if a layoutsExternal boolean is true.

lunelson commented 6 years ago

Yes, seeing the source of metalsmith-assets confirmed what I was thinking; I noticed that there are methods metalsmith.path and also metalsmith._directory that seemed like they would do the job and the -assets plugin lays that out pretty clearly

My suggestion is that the layouts path be evaluated like this:

  1. if the path matches files already in the source tree, great
  2. otherwise, if it starts with a / treat it as an absolute path from the root dir, and load the layouts there, pushing them on to the files array
  3. or if it is relative, including starting with a ./ or ../, calculate it relative to source dir and load the layouts from there, pushing them on to the files array

... and then continue processing

Would you include metalsmith-assets as a dependency then, or just lift its internals?

kenhoff commented 6 years ago

For anyone still playing around with this, I had a vaguely similar problem. The layout files need to be part of the metalsmith files object when jstransformer is called - if you're using metalsmith-branch or something, you'll need to glob match the layout files in question as well.

e.g., this will not work:

Metalsmith(__dirname)
    .use(branch().pattern(["posts/**/*.md"])
        .use(jstransformer({
        defaultLayout: "layouts/post.pug"
    })))

but this will work:

Metalsmith(__dirname)
    .use(branch().pattern(["posts/**/*.md", "layouts/**"])
        .use(jstransformer({
        defaultLayout: "layouts/post.pug"
    })))

Cheers!

RobLoach commented 6 years ago

Didn't know of metalsmith-branch, looks like a great plugin!