Skip to content

Commit

Permalink
feat!: add global configuration for mermaid and update options (#560)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfcere authored Nov 20, 2024
1 parent 620b366 commit 3d68dc6
Show file tree
Hide file tree
Showing 14 changed files with 1,589 additions and 290 deletions.
47 changes: 41 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,15 +347,50 @@ Using `markdown` component and/or directive, you will be able to use the `mermai
</markdown>
```

Optionally, you can specify mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) using `mermaidOptions` property.
#### Global configuration

You can provide a global configuration for mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) to use across your application with the `mermaidOptions` in the `MarkdownModuleConfig` either with `provideMarkdown` provide-function for standalone components or `MarkdownModule.forRoot()` for module configuration.

##### Using the `provideMarkdown` function

```typescript
provideMarkdown({
mermaidOptions: {
provide: MERMAID_OPTIONS,
useValue: {
darkMode: true,
look: 'handDrawn',
...
},
},
}),
```

##### Using the `MarkdownModule` import

```typescript
MarkdownModule.forRoot({
mermaidOptions: {
provide: MERMAID_OPTIONS,
useValue: {
darkMode: true,
look: 'handDrawn',
...
},
},
}),
```

#### Component configuration

Additionally, you can specify mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) on component directly using `mermaidOptions` property.

```typescript
import { MermaidAPI } from 'ngx-markdown';

public options: MermaidAPI.Config = {
fontFamily: '"trebuchet ms", verdana, arial, sans-serif',
logLevel: MermaidAPI.LogLevel.Info,
theme: MermaidAPI.Theme.Dark,
public options: MermaidAPI.MermaidConfig = {
darkMode: true,
look: 'handDrawn',
...
};
```
Expand Down Expand Up @@ -842,7 +877,7 @@ export interface MarkdownPipeOptions {
katex?: boolean;
katexOptions?: KatexOptions;
mermaid?: boolean;
mermaidOptions?: MermaidAPI.Config;
mermaidOptions?: MermaidAPI.MermaidConfig;
markedOptions?: MarkedOptions;
disableSanitizer?: boolean;
}
Expand Down
15 changes: 11 additions & 4 deletions demo/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ApplicationConfig, SecurityContext } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideRouter, withInMemoryScrolling } from '@angular/router';
import { gfmHeadingId } from 'marked-gfm-heading-id';
import { CLIPBOARD_OPTIONS, MARKED_OPTIONS, provideMarkdown } from 'ngx-markdown';
import { CLIPBOARD_OPTIONS, MARKED_OPTIONS, MERMAID_OPTIONS, provideMarkdown } from 'ngx-markdown';
import { appRoutes } from '@app/app-routes';
import { markedOptionsFactory } from '@app/marked-options-factory';
import { AnchorService } from '@shared/anchor/anchor.service';
Expand All @@ -22,15 +22,22 @@ export const appConfig: ApplicationConfig = {
),
provideMarkdown({
loader: HttpClient,
clipboardOptions: {
provide: CLIPBOARD_OPTIONS,
useValue: { buttonComponent: ClipboardButtonComponent },
},
markedOptions: {
provide: MARKED_OPTIONS,
useFactory: markedOptionsFactory,
deps: [AnchorService],
},
markedExtensions: [gfmHeadingId()],
clipboardOptions: {
provide: CLIPBOARD_OPTIONS,
useValue: { buttonComponent: ClipboardButtonComponent },
mermaidOptions: {
provide: MERMAID_OPTIONS,
useValue: {
darkMode: true,
look: 'handDrawn',
},
},
sanitize: SecurityContext.NONE,
}),
Expand Down
4 changes: 2 additions & 2 deletions demo/src/app/bindings/bindings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h2 id="variable-binding">Variable Binding</h2>

<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<mat-form-field appearance="fill" color="accent" fxFlex.gt-sm="calc(50% - 8px)">
<textarea matInput [(ngModel)]="markdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="markdown"></textarea>
</mat-form-field>

<markdown [data]="markdown" fxFlex.gt-sm="calc(50% - 8px)"></markdown>
Expand Down Expand Up @@ -66,7 +66,7 @@ <h2 id="pipe-usage">Pipe Usage</h2>

<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<mat-form-field appearance="fill" color="accent" fxFlex.gt-sm="calc(50% - 8px)">
<textarea matInput [(ngModel)]="typescriptMarkdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="typescriptMarkdown"></textarea>
</mat-form-field>

<div [innerHTML]="typescriptMarkdown | language : 'typescript' | markdown | async" fxFlex.gt-sm="calc(50% - 8px)"></div>
Expand Down
51 changes: 41 additions & 10 deletions demo/src/app/plugins/plugins.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ <h2 id="emoji">Emoji plugin</h2>

<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<mat-form-field appearance="fill" color="accent" fxFlex.gt-sm="calc(50% - 8px)">
<textarea matInput [(ngModel)]="emojiMarkdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="emojiMarkdown"></textarea>
</mat-form-field>

<markdown [data]="emojiMarkdown" emoji fxFlex.gt-sm="calc(50% - 8px)"></markdown>
Expand Down Expand Up @@ -308,7 +308,7 @@ <h2 id="katex">KaTeX plugin</h2>

<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<mat-form-field appearance="fill" color="accent" fxFlex.gt-sm="calc(50% - 8px)">
<textarea matInput [(ngModel)]="katexMarkdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="katexMarkdown"></textarea>
</mat-form-field>

<markdown [data]="katexMarkdown" katex fxFlex.gt-sm="calc(50% - 8px)"></markdown>
Expand Down Expand Up @@ -367,23 +367,54 @@ <h2 id="mermaid">Mermaid plugin</h2>

<div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px">
<mat-form-field appearance="fill" color="accent" fxFlex.gt-sm="calc(50% - 8px)">
<textarea matInput [(ngModel)]="mermaidMarkdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="mermaidMarkdown"></textarea>
</mat-form-field>

<markdown [data]="mermaidMarkdown" mermaid [mermaidOptions]="mermaidOptions" fxFlex.gt-sm="calc(50% - 8px)"></markdown>
<markdown [data]="mermaidMarkdown" mermaid [mermaidOptions]="mermaidOptions" fxLayoutAlign="center center" fxFlex.gt-sm="calc(50% - 8px)"></markdown>
</div>

<markdown ngPreserveWhitespaces>
Optionally, you can specify mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) using `mermaidOptions` property.
#### Global configuration

**example.component.ts**
You can provide a global configuration for mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) to use across your application with the `mermaidOptions` in the `MarkdownModuleConfig` either with `provideMarkdown` provide-function for standalone components or `MarkdownModule.forRoot()` for module configuration.

```typescript
// using the `provideMarkdown` function
provideMarkdown(&#123;
mermaidOptions: &#123;
provide: MERMAID_OPTIONS,
useValue: &#123;
darkMode: true,
look: 'handDrawn',
...
&#125;,
&#125;,
&#125;),

// using the `MarkdownModule` import
MarkdownModule.forRoot(&#123;
mermaidOptions: &#123;
provide: MERMAID_OPTIONS,
useValue: &#123;
darkMode: true,
look: 'handDrawn',
...
&#125;,
&#125;,
&#125;),
```

#### Component configuration

Additionally, you can specify mermaid [configuration options](https://mermaid.js.org/config/schema-docs/config.html#mermaid-config-properties) on component directly using `mermaidOptions` property.

**example.component.ts**
```typescript
import &#123; MermaidAPI &#125; from 'ngx-markdown';

public options: MermaidAPI.Config = &#123;
fontFamily: '"trebuchet ms", verdana, arial, sans-serif',
logLevel: MermaidAPI.LogLevel.Info,
theme: MermaidAPI.Theme.Dark,
public options: MermaidAPI.MermaidConfig = &#123;
darkMode: true,
look: 'handDrawn',
...
&#125;;
```
Expand Down
4 changes: 2 additions & 2 deletions demo/src/app/plugins/plugins.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ graph TD;
C-->D;
\`\`\``;

mermaidOptions: MermaidAPI.Config = {
mermaidOptions: MermaidAPI.MermaidConfig = {
fontFamily: 'inherit',
theme: MermaidAPI.Theme.Dark,
theme: 'dark',
};

headings: Element[] | undefined;
Expand Down
2 changes: 1 addition & 1 deletion demo/src/app/rerender/rerender.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ <h2 id="example">Example</h2>
</mat-form-field>

<mat-form-field appearance="fill" color="accent" fxFlex>
<textarea matInput [(ngModel)]="markdown"></textarea>
<textarea matInput cdkTextareaAutosize="true" [(ngModel)]="markdown"></textarea>
</mat-form-field>
</div>

Expand Down
2 changes: 1 addition & 1 deletion lib/src/markdown.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ describe('MarkdownComponent', () => {
} as TemplateRef<unknown>,
};
const katexOptions: KatexOptions = { displayMode: true };
const mermaidOptions: MermaidAPI.Config = { darkMode: true };
const mermaidOptions: MermaidAPI.MermaidConfig = { darkMode: true };

spyOn(markdownService, 'parse').and.returnValue(parsed);
spyOn(markdownService, 'render');
Expand Down
2 changes: 1 addition & 1 deletion lib/src/markdown.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class MarkdownComponent implements OnChanges, AfterViewInit, OnDestroy {
get mermaid(): boolean { return this._mermaid; }
set mermaid(value: boolean) { this._mermaid = this.coerceBooleanProperty(value); }

@Input() mermaidOptions: MermaidAPI.Config | undefined;
@Input() mermaidOptions: MermaidAPI.MermaidConfig | undefined;

// Plugin - lineHighlight
@Input()
Expand Down
9 changes: 4 additions & 5 deletions lib/src/markdown.module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import { MARKED_EXTENSIONS } from './marked-extensions';
import { MARKED_OPTIONS, MarkedOptions } from './marked-options';

@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'host-comp',
selector: 'markdown-host',
template: `
<div *ngIf="src; else dataTemplate">
<markdown [src]="src"></markdown>
Expand Down Expand Up @@ -57,7 +56,7 @@ describe('MarkdownModule', () => {
MarkdownModule.forRoot({
markedOptions: {
provide: MARKED_OPTIONS,
useValue: 'mockMarkedOptions',
useValue: {},
},
}),
],
Expand Down Expand Up @@ -182,7 +181,7 @@ describe('MarkdownModule', () => {
MarkdownModule.forRoot({
markedOptions: {
provide: MARKED_OPTIONS,
useValue: 'mockMarkedOptions',
useValue: {},
},
}),
],
Expand Down Expand Up @@ -226,7 +225,7 @@ describe('MarkdownModule', () => {
MarkdownModule.forRoot({
markedOptions: {
provide: MARKED_OPTIONS,
useValue: 'mockMarkedOptions',
useValue: {},
},
}),
],
Expand Down
25 changes: 22 additions & 3 deletions lib/src/markdown.module.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import { CommonModule } from '@angular/common';
import { ModuleWithProviders, NgModule, Provider, SecurityContext } from '@angular/core';
import { InjectionToken, ModuleWithProviders, NgModule, Provider, SecurityContext } from '@angular/core';
import { MarkedExtension } from 'marked';
import { ClipboardButtonComponent } from './clipboard-button.component';
import { CLIPBOARD_OPTIONS } from './clipboard-options';
import { LanguagePipe } from './language.pipe';
import { MarkdownComponent } from './markdown.component';
import { MarkdownPipe } from './markdown.pipe';
import { MARKED_OPTIONS } from './marked-options';
import { MERMAID_OPTIONS } from './mermaid-options';
import { provideMarkdown } from './provide-markdown';

type InjectionTokenType<T extends InjectionToken<any>> = T extends InjectionToken<infer R> ? R : unknown;

interface TypedValueProvider<T extends InjectionToken<any>> {
provide: T;
useValue: InjectionTokenType<T>;
};

interface TypedFactoryProvider<T extends InjectionToken<any>> {
provide: T;
useFactory: (...args: any[]) => InjectionTokenType<T>;
deps?: any[];
};

type TypedProvider<T extends InjectionToken<any>> = TypedValueProvider<T> | TypedFactoryProvider<T>;

// having a dependency on `HttpClientModule` within a library
// breaks all the interceptors from the app consuming the library
// here, we explicitely ask the user to pass a provider with
// their own instance of `HttpClientModule`
export interface MarkdownModuleConfig {
loader?: Provider;
clipboardOptions?: Provider;
markedOptions?: Provider;
clipboardOptions?: TypedProvider<typeof CLIPBOARD_OPTIONS>;
markedOptions?: TypedProvider<typeof MARKED_OPTIONS>;
markedExtensions?: MarkedExtension[];
mermaidOptions?: TypedProvider<typeof MERMAID_OPTIONS>;
sanitize?: SecurityContext;
}

Expand Down
16 changes: 8 additions & 8 deletions lib/src/markdown.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,11 +608,11 @@ describe('MarkdownService', () => {
container.append(elementOne);
container.append(elementTwo);

const defaultOptions: MermaidAPI.Config = { startOnLoad: false };
const defaultOptions: MermaidAPI.MermaidConfig = { startOnLoad: false };
const mermaidElements = container.querySelectorAll<HTMLElement>('.mermaid');

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand All @@ -634,15 +634,15 @@ describe('MarkdownService', () => {
const container = document.createElement('div');
container.append(element);

const providedOptions: MermaidAPI.Config = {
const providedOptions: MermaidAPI.MermaidConfig = {
startOnLoad: false,
darkMode: true,
};

const mermaidElements = container.querySelectorAll<HTMLElement>('.mermaid');

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand All @@ -660,7 +660,7 @@ describe('MarkdownService', () => {
const container = document.createElement('div');

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand All @@ -686,7 +686,7 @@ describe('MarkdownService', () => {
const container = document.createElement('div');

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand Down Expand Up @@ -723,7 +723,7 @@ describe('MarkdownService', () => {
container.append(element);

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand Down Expand Up @@ -774,7 +774,7 @@ describe('MarkdownService', () => {
container.append(mermaidElement);

window['mermaid'] = {
initialize: (options: MermaidAPI.Config) => {},
initialize: (options: MermaidAPI.MermaidConfig) => {},
run: (runOptions: MermaidAPI.RunOptions) => {},
};

Expand Down
Loading

0 comments on commit 3d68dc6

Please sign in to comment.