Skip to content

Commit

Permalink
add provideMarkdocOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
marcjulian committed Nov 17, 2023
1 parent 43f984e commit 00a6831
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 28 deletions.
53 changes: 49 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,13 @@ Import `Markdoc` into your component and use `<markdoc></markdoc>` in your templ

```ts
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Markdoc } from '@notiz/ngx-markdoc';

@Component({
selector: 'app-docs',
standalone: true,
imports: [Markdoc],
template: `
<markdoc #markdoc src="assets/md/docs/getting-started.md"></markdoc>
`,
template: ` <markdoc src="assets/md/docs/getting-started.md"></markdoc> `,
})
export class DocsComponent {}
```
Expand All @@ -59,3 +56,51 @@ export class DocsComponent {}
```html
<markdoc src="assets/md/example.md"></markdoc>
```

## Options

Use `provideMarkdocOptions` to optionally pass a Markdoc configuration options.

```ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';

import { provideMarkdocOptions } from '@notiz/ngx-markdoc';
import { Config, Node, Tag } from '@markdoc/markdoc';

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
provideMarkdocOptions({
config: {
tags: {
figure: {
selfClosing: true,
attributes: {
src: { type: String, required: true },
alt: { type: String, required: true },
caption: { type: String, required: true },
},
transform: (node: Node, config: Config) => {
const { src, alt, caption } = node.transformAttributes(config);
const imageTag = new Tag('img', { src, alt });
const captionTag = new Tag('figcaption', {}, [caption]);
return new Tag('figure', {}, [imageTag, captionTag]);
},
},
},
},
}),
],
};
```

Now you can use `{% figure %}` tag in your Markdown file

```md
{% figure src="https://images.unsplash.com/photo-1610296669228-602fa827fc1f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1675&q=80" alt="Pelican nebulae mosaic" caption="Pelican nebulae mosaic" /%}
```
8 changes: 0 additions & 8 deletions projects/ngx-markdoc/src/lib/config.ts

This file was deleted.

1 change: 1 addition & 0 deletions projects/ngx-markdoc/src/lib/extensions/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './figure.markdoc';
export * from './heading.markdoc';
export * from './image.markdoc';
export * from './toc.markdoc';
25 changes: 21 additions & 4 deletions projects/ngx-markdoc/src/lib/markdoc.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import MarkdocRenderer, {
Tag,
} from '@markdoc/markdoc';
import * as yaml from 'js-yaml';
import { defaultConfig } from './config';
import { MARKDOC_CONFIG } from './provide-markdoc-options';

@Component({
selector: 'markdoc, [markdoc]',
Expand All @@ -31,11 +31,25 @@ import { defaultConfig } from './config';
export class Markdoc implements OnChanges, AfterViewInit {
private element = inject(ElementRef<HTMLElement>);
private http = inject(HttpClient);
private _defaultConfig = inject(MARKDOC_CONFIG, { optional: true });

private get defaultConfig(): Config {
return this._defaultConfig ?? {};
}

@Input() content: string | undefined;
@Input() src: string | undefined;

@Input() config: Config | undefined;
private _config: Config | undefined;
@Input()
public get config(): Config | undefined {
return this._config;
}
public set config(value: Config | undefined) {
this._config = value
? { ...this.defaultConfig, ...value }
: this.defaultConfig;
}

private _contentNode: RenderableTreeNode | undefined;
/**
Expand Down Expand Up @@ -80,6 +94,10 @@ export class Markdoc implements OnChanges, AfterViewInit {
}
@Output() frontmatterChange = new EventEmitter<Record<string, any>>();

constructor() {
this.config = this.defaultConfig;
}

ngOnChanges(changes: SimpleChanges): void {
if (this.content != undefined) {
this.render(this.content);
Expand Down Expand Up @@ -142,10 +160,9 @@ export class Markdoc implements OnChanges, AfterViewInit {
const variables = { ...(config?.variables || {}), markdoc };

const nodes = {
...defaultConfig.nodes,
...(config?.nodes || {}),
};
return { ...config, tags: { ...defaultConfig.tags }, nodes, variables };
return { ...config, tags: { ...config?.tags }, nodes, variables };
}

private loadFrontmatter(ast: Node) {
Expand Down
29 changes: 29 additions & 0 deletions projects/ngx-markdoc/src/lib/provide-markdoc-options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
EnvironmentProviders,
InjectionToken,
makeEnvironmentProviders,
} from '@angular/core';
import { Config } from '@markdoc/markdoc';
import { figure, heading, image } from './extensions';

export const MARKDOC_CONFIG = new InjectionToken<Config>('MARKDOC_CONFIG');

export interface MarkdocOptions {
config?: Config;
}

const defaultConfig: Config = {
nodes: { heading, image },
tags: { figure },
};

export function provideMarkdocOptions(
markdocOptions?: MarkdocOptions,
): EnvironmentProviders {
return makeEnvironmentProviders([
{
provide: MARKDOC_CONFIG,
useValue: markdocOptions?.config ?? defaultConfig,
},
]);
}
2 changes: 1 addition & 1 deletion projects/ngx-markdoc/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './lib/extensions';
export * from './lib/config';
export * from './lib/markdoc.component';
export * from './lib/provide-markdoc-options';
14 changes: 14 additions & 0 deletions src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import { provideRouter, withInMemoryScrolling } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { provideClientHydration } from '@angular/platform-browser';
import {
figure,
heading,
image,
provideMarkdocOptions,
} from '@notiz/ngx-markdoc';
import { Config, Node, Tag } from '@markdoc/markdoc';
import { markdocExample } from './markdoc-example';

export const appConfig: ApplicationConfig = {
providers: [
Expand All @@ -15,5 +23,11 @@ export const appConfig: ApplicationConfig = {
),
provideHttpClient(withFetch()),
provideClientHydration(),
provideMarkdocOptions({
config: {
nodes: { heading, image },
tags: { figure, markdocExample },
},
}),
],
};
13 changes: 13 additions & 0 deletions src/app/markdoc-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Schema, Tag } from '@markdoc/markdoc';

export const markdocExample: Schema = {
render: 'pre',
attributes: {},
transform(node, config) {
console.log('test');
const attributes = node.transformAttributes(config);
const { content, language } = node.children[0].attributes;

return new Tag('pre', { ...attributes, language }, [content]);
},
};
14 changes: 6 additions & 8 deletions src/app/pages/landing.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { Markdoc } from '@notiz/ngx-markdoc';
import { Prose } from '../components/prose.component';
import { Hero } from '../components/hero.component';

@Component({
selector: 'app-landing',
standalone: true,
imports: [Hero, Prose, Markdoc, AsyncPipe],
template: `
<hero></hero>
Expand Down Expand Up @@ -34,13 +36,9 @@ import { Hero } from '../components/hero.component';
</div>
</div>
`,
styles: [],
standalone: true,
imports: [Hero, Prose, Markdoc, AsyncPipe],
})
export class LandingComponent implements OnInit {
example$ = this.http.get('assets/md/example.md', { responseType: 'text' });
constructor(private http: HttpClient) {}
export class LandingComponent {
private http = inject(HttpClient);

ngOnInit(): void {}
example$ = this.http.get('assets/md/example.md', { responseType: 'text' });
}
56 changes: 53 additions & 3 deletions src/assets/md/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ import { Markdoc } from '@notiz/ngx-markdoc';
selector: 'app-docs',
standalone: true,
imports: [Markdoc],
template: `
<markdoc #markdoc src="assets/md/docs/getting-started.md"></markdoc>
`,
template: ` <markdoc src="assets/md/docs/getting-started.md"></markdoc> `,
})
export class DocsComponent {}
```
Expand All @@ -63,3 +61,55 @@ export class DocsComponent {}
```html
<markdoc src="assets/md/example.md"></markdoc>
```

## Options

Use `provideMarkdocOptions` to optionally pass a Markdoc configuration options.

```ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';

import { provideMarkdocOptions } from '@notiz/ngx-markdoc';
import { Config, Node, Tag } from '@markdoc/markdoc';

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
provideMarkdocOptions({
config: {
tags: {
figure: {
selfClosing: true,
attributes: {
src: { type: String, required: true },
alt: { type: String, required: true },
caption: { type: String, required: true },
},
transform: (node: Node, config: Config) => {
const { src, alt, caption } = node.transformAttributes(config);
const imageTag = new Tag('img', { src, alt });
const captionTag = new Tag('figcaption', {}, [caption]);
return new Tag('figure', {}, [imageTag, captionTag]);
},
},
},
},
}),
],
};
```

Now you can use `{% figure %}` tag in your Markdown file

{% markdocExample %}

```md
{% figure src="https://images.unsplash.com/photo-1610296669228-602fa827fc1f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1675&q=80" alt="Pelican nebulae mosaic" caption="Pelican nebulae mosaic" /%}
```

{% /markdocExample %}

0 comments on commit 00a6831

Please sign in to comment.