pngwn / MDsveX

A markdown preprocessor for Svelte.
https://mdsvex.pngwn.io
MIT License
2.38k stars 102 forks source link

File-based layouts #230

Open furudean opened 3 years ago

furudean commented 3 years ago

A common MDsveX use case is to use it to render blog posts in Svelte Kit. When creating layouts for these pages, you have to dig into the MDsveX config to bind the layout to a specific file. This becomes more complex when you consider the case with multiple layouts, where each .svx file would have to specify its layout in the front matter.

Svelte Kit has engineered up a solution for regular page layouts, by using a specific file name $layout.svelte __layout.svelte to bind to the layout for that route. It would be great to have MDsveX implement something similar for its layouts. This would greatly simplify configuration for the most common use cases.

pngwn commented 3 years ago

Do you imagine this working in the same way that $layout does? In that the layout file stored in that folder will be used by the mdsvex files in that folder?

furudean commented 3 years ago

That's what I had in mind -- it seems like an obvious compliment to Svelte Kit's router. I'm open to other suggestions though!

pngwn commented 3 years ago

I shall have a think about it, there are a few challenges as I want mdsvex to run in a browser environment where needed. It currently does this today with a few caveats (and I've broken the browser build) but I'd like to fix that. Layouts were one of the reasons the whole feature set did not work in browser so this is a good opportunity to address that.

There are also some issues with how svelte includes/ ignored files in the routes folder. We'll need some way to work around that. It ignored _ prepended files so that is one possibility but the ergonomics aren't great.

I shall have a think! Thanks for filing an issue!

kosayoda commented 3 years ago

I'd like to point out https://github.com/sveltejs/kit/issues/1149, which talks about making the layout and parameter prefixes more accessible and convenient for shells and editors.

If you do decide and manage to go with this, please keep that in mind and consider that $ gets expanded in the shell, making it a rather cumbersome character to have in a filename.

furudean commented 3 years ago

@kosayoda I think that issue is still on ice. We'd like to go and fix tooling which doesn't support the current syntax before making a big change like that. It seems we couldn't agree on what characters to use anyway :P

caesar commented 3 years ago

Even if "file-based layouts" is not added (in the sense mentioned above where it would work like $layout does for SvelteKit), it would be useful to have a config option to specify that a certain layout should be used for all files in a certain directory (or matching a certain glob), instead of having to explicitly specify the layout in the frontmatter of every page.

pngwn commented 3 years ago

@caesar That is already possible. Look at that few paragraphs of this section: https://mdsvex.com/docs#named-layouts

caesar commented 3 years ago

Thanks @pngwn, I'd somehow missed that paragraph!

ngxingyu commented 3 years ago

Just discovered that the layout files for mdsvex doesn't support typescript (It resulted in a ParseError: Unexpected token) but using javascript works perfectly.

pngwn commented 3 years ago

Yeah. See #116 for details.

furudean commented 3 years ago

@kosayoda Svelte Kit now uses double underscores for special files, i.e. __layout.svelte as a solution to your problem.

Those files are technically reserved for Svelte Kit so I'm not sure if MDsveX is allowed to use it in any case.

pngwn commented 3 years ago

I don't even think it would be possible. I believe double underscore prepended files are reserved names, for possible future use. Using that prefix would throw an error, I think.

furudean commented 3 years ago

Yeah, if a file based layout was implemented it would probably need to have its own prefix/suffix on top of being a private module.

Just throwing some ideas out there:

  1. _layout.svelte — Short and simple, but too generic? There is nothing that indicates this file belongs to MDsveX.
  2. _layout.svx — Like above, but uses the configured extension for MDsveX files to match the layout file. This has some weird semantics where it seems like markdown would be supported inside the layout itself, should it?
  3. _mdsvex_layout.svelte — The file name for matching a layout would be hard coded (and configurable).
furudean commented 3 years ago

Probably overthinking this a bit. Option 1 and 2 are effectively the same. There is no reason that the file should just have the name _layout.svelte

So really it is two separate questions that are sort of related to each other:

  1. What is the file name for the MDSveX layout? _layout, _mdsvex_layout or something else?
  2. Should the extension be .svelte or .svx?
caesar commented 3 years ago
2. Should the extension be `.svelte` or  `.svx`?

I'd say you should be able to use either, and the file would be parsed according to the normal rules like any other component (so the former would be a standard Svelte component, and the latter would be an mdsvex component).

pngwn commented 3 years ago

Could always do _layout.mdsvex.svelte or something too.

furudean commented 3 years ago

Could always do _layout.mdsvex.svelte or something too.

There's a weird edge case here if you customize your extension (like I did) to .md.svelte. The result would be _layout.md.svelte.svelte.

pngwn commented 3 years ago

Classic.

Looks like a bug though.

shedali commented 3 years ago

I think this is related - I was looking for a way to pass markdown frontmatter values to layouts and landed here. This was pretty powerful mdsvex feature when I used it with sapper as every markdown file could dictate theme, SEO, scripts etc.

An ugly temp workaround for sveltekit might look like this

jnskender commented 2 years ago

Because the load function is only available to page and layout components this makes it very difficult to have access to server side fetching for a markdown page.

Not sure what a current work around would be but +1 for supporting file-based layouts in mdsvex to reduce confusion.

jnskender commented 2 years ago

I think this is related - I was looking for a way to pass markdown frontmatter values to layouts and landed here. This was pretty powerful mdsvex feature when I used it with sapper as every markdown file could dictate theme, SEO, scripts etc.

An ugly temp workaround for sveltekit might look like this

Yeah I can't decide how to workaround this. I need a layout file so that I can have access to the load function. Your workaround would have me reading the file system twice to process the front matter.

Otherwise you can pass a __layout.svelte component to as a valid layout but it causes "two" renders.