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

Ability to name-space from multiple files? #17

Open
dillonbheadley opened this issue Aug 26, 2016 · 7 comments
Open

Ability to name-space from multiple files? #17

dillonbheadley opened this issue Aug 26, 2016 · 7 comments
Labels

Comments

@dillonbheadley
Copy link

Hi there!
Is it possible to have multiple metafiles pointing to a single file? For example:
index.html is the "host file". index.html.meta.json is generic metadata. index.html.books.meta.jsonwould be found under the books key for the index.html file. Does that make sense?

@Ajedi32
Copy link
Owner

Ajedi32 commented Aug 26, 2016

Right now there's no functionality for namespacing metadata under a single key like that. I guess I could build in a function similar to the namespace option in metalsmith-matters. Then you'd be able to accomplish that by using multiple copies of this plugin in succession, like so:

{
  "frontmatter": false,
  "plugins": [
    {"metalsmith-metafiles": {}},
    {"metalsmith-metafiles": {
      "postfix": ".books.meta",
      "namespace": "books"
    }},
    // Other plugins...
  ]
}

@dillonbheadley
Copy link
Author

Hmmm interesting... I don't like how you would have to manually declare each namespace though.
I had thrown together a simple plugin to do something similar with a markdown file:

var metaMarkdown = function(files, metalsmith, done) {
    // works like: target.metaname.meta.md
    Object.keys(files).forEach(function(file){
        var basename = path.basename(file);
        var dirname = path.dirname(file);
        if (basename.indexOf('.meta.') > -1) {
            var metaFile = files[file];
            var targetFile = basename.split('.meta.')[0];
            var metaName = targetFile.split('.')[1] || '';
            targetFile = targetFile.split('.')[0];

            dirname == "." ? dirname = "" : '';
            var hostFile = files[dirname+targetFile+".jade"];

            if (hostFile) {
                hostFile.page = hostFile.page || {};
                for (set in metaFile) {
                    if (metaName) {
                        hostFile.page[metaName] = hostFile.page[metaName] || {};
                        hostFile.page[metaName][set] = metaFile[set]
                    } else {
                        hostFile.page[set] = metaFile[set]
                    }
                }
                delete files[file];
                Object.assign(files[dirname+targetFile+".jade"], hostFile)
            }
        }
    });

    done();
};

this looks for a matching base name and adds the parsed file as a key. So in index.html, index.meta.md:

---
title: This is a test
---

# Some content

would be available as page.title and page.content. And index.hero.meta.md:

---
title: I'm the hero
---
## Hero content

Is available as page.hero.title and page.hero.content.

Kind of makes a Markdown CMS of sorts...

I've set it up just to work with .jade files via markdown-in-place. Could be fleshed out a bit. Thoughts?

@Ajedi32
Copy link
Owner

Ajedi32 commented Aug 29, 2016

Actually now that I think about it, you could do this with a custom parser:

var metafiles = require('metalsmith-metafiles');
var yaml = require('js-yaml');

Metalsmith(__dirname)
  .frontmatter(false)
  .use(metafiles({
    parsers: {
      ".json": false, // Disable using JSON metadata files
      ".yaml": function(content, options) { // Custom parser
        let metadata = yaml.safeLoad(content, {filename: options.path});

        // Find namespace based on `options.path`

        return {[namespace]: metadata}
      },
    }
  }))
  .use(/* Other plugin */)
  .build(function(err) {
    if (err) throw err;
  });

@dillonbheadley
Copy link
Author

That's great! Could I also use Markdown files with a custom parser like that?

@Ajedi32
Copy link
Owner

Ajedi32 commented Aug 30, 2016

In theory, yes. Note though that metalsmith-metafiles parsers can't access metadata added to the meta files, only their contents, so if you want to include attributes from frontmatter you'd have to run metalsmith-metafiles before parsing the frontmatter (e.g. disable the built-in frontmatter parsing) and have your custom parser parse the frontmatter itself.

@dillonbheadley
Copy link
Author

Ah I see. Ok good to know.
I've started testing this out and I'm getting this error:
Could not find main file index.jade.hero for metadata file index.jade.hero.meta.md

Seems like it won't take a file with another name segment in it.

@Ajedi32
Copy link
Owner

Ajedi32 commented Aug 31, 2016

Oh, darn. Yeah you're right; I should have realized that would happen. Not sure why I didn't. The names of the metadata files are fixed...

To be honest, your use case seems to be a bit outside the scope of what metalsmith-metafiles was originally intended to do. I can't really see myself adding functionality to support this natively, but I am open to adding options to expand the flexibility of metalsmith-metafiles to make it possible for you to use metalsmith-metafiles to do this yourself.

My current thought is to add support for some kind of custom matcher object for metadata files, so you could then implement this functionality yourself. Basically I'd be letting you specify your own MetafileMatcher class (with some changes to simplify the API). Does that sound reasonable to you?

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

No branches or pull requests

2 participants