router
This relates to #214
I would like to propose allowing developers to pass in their own custom components to render
their markdown routes. We still default to the built in MarkdownComponent provided by
Analog.
To achieve that I am proposing to allow to pass a customComponent to the getRoutes function
/**
* Function used to parse list of files and return
* configuration of routes.
*
* @param files
* @param customComponent
* @returns Array of routes
*/
export function getRoutes(files: Files, customComponent?: Type<unknown>) {
const ROUTES = Object.keys(files).sort((a, b) => a.length - b.length);
const routeConfigs = ROUTES.reduce<Route[]>(
(routes: Route[], key: string) => {
const module = key.endsWith('.md')
? buildModule({ _analogContent: files[key] }, customComponent)
: (files[key] as () => Promise<RouteExport>);
...
Then, it is determined if the custom component should be used or the default component from Analog.
function buildModule(
routeMeta: RouteMeta,
customComponent?: Type<unknown>
): () => Promise<RouteExport> {
console.log('customComponent', customComponent);
return customComponent
? () =>
Promise.resolve({
default: customComponent,
routeMeta,
})
: () =>
import('@analogjs/content').then((m) => ({
default: m.MarkdownComponent,
routeMeta,
}));
}
I am not sure what the best way to register this component would be.
Ideally, it could just be passed as the features array here:
export const provideFileRouter = (
...features: (RouterFeatures | Type<unknown>)[]
) => {
const component = features.shift();
return provideRouter(
getAnalogRoutesWithComponent(component as Type<unknown>),
...(features as RouterFeatures[])
);
};
The custom component is to be passed through here:
export function getAnalogRoutesWithComponent(customComponent?: Type<unknown>): Route[] {
return [...getRoutes({ ...FILES, ...CONTENT_FILES }, customComponent)];
}
I think there is probably a bunch of ways to improve this.
Obviously a better way to pass in the component in the config.
Also, making the custom component extend a base class that injects the content, etc.
I just wanted to open this issue to get a conversation going, because I think this could allow for some great customization.
No response
Hi @goetzrobin
Can you give an example where a custom markdown component would be a better fit?
If we need to define a custom shell for the markdown route, we can use the file router "shell" feature:
// routes/about/index.md
# About
About Page
// routes/about.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
@Component({
standalone: true,
imports: [RouterOutlet],
template: `
<p>Before</p>
<router-outlet></router-outlet> <!-- about/index.md content will be rendered here -->
<p>After</p>
`,
})
export default class AboutComponent {}
Hi @markostanimirovic,
I think that actually makes sense.
The use case I was thinking about is:
I want to wrap all my markdown components in the same styling, e.g. add a header/footer, etc.
But I think it might be overcomplicating things as global layouts can be placed in the AppComponent
and if I really wanted specific styling I can add that as you described above.
I am ready to close this issue unless you want to leave it open for someone else to make an argument
Owner Name | analogjs |
Repo Name | analog |
Full Name | analogjs/analog |
Language | TypeScript |
Created Date | 2022-07-06 |
Updated Date | 2023-03-28 |
Star Count | 885 |
Watcher Count | 18 |
Fork Count | 67 |
Issue Count | 33 |
Issue Title | Created Date | Updated Date |
---|