ngx-markdown-pages 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -0
- package/fesm2022/ngx-markdown-pages.mjs +81 -0
- package/fesm2022/ngx-markdown-pages.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/markdown-page.component.d.ts +11 -0
- package/lib/markdown-pages.config.d.ts +10 -0
- package/lib/markdown-pages.routes.d.ts +3 -0
- package/package.json +26 -0
- package/public-api.d.ts +4 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# ngx-markdown-pages
|
|
2
|
+
|
|
3
|
+
An Angular library for rendering markdown files as routable pages. Built on top of [ngx-markdown](https://github.com/jfcere/ngx-markdown).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install ngx-markdown-pages ngx-markdown marked
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Call `provideMarkdownPages()` in your application providers:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { provideMarkdownPages } from 'ngx-markdown-pages';
|
|
17
|
+
|
|
18
|
+
bootstrapApplication(AppComponent, {
|
|
19
|
+
providers: [
|
|
20
|
+
provideMarkdownPages(),
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
To enable the clipboard copy button on code blocks:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
provideMarkdownPages({ clipboard: true })
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Routing
|
|
32
|
+
|
|
33
|
+
Define your markdown pages with `markdownPageRoutes()`:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { markdownPageRoutes } from 'ngx-markdown-pages';
|
|
37
|
+
|
|
38
|
+
const routes: Routes = [
|
|
39
|
+
...markdownPageRoutes([
|
|
40
|
+
{ path: 'getting-started', markdownFile: 'assets/docs/getting-started.md' },
|
|
41
|
+
{ path: 'api-reference', markdownFile: 'assets/docs/api-reference.md' },
|
|
42
|
+
]),
|
|
43
|
+
];
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Each route renders a `MarkdownPageComponent` that loads and displays the specified markdown file. Heading anchor links with smooth scrolling are handled automatically.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, ElementRef, Component } from '@angular/core';
|
|
3
|
+
import { provideMarkdown, MARKED_OPTIONS, MarkdownComponent } from 'ngx-markdown';
|
|
4
|
+
import { Renderer } from 'marked';
|
|
5
|
+
import { ActivatedRoute, Router } from '@angular/router';
|
|
6
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
7
|
+
import { map } from 'rxjs';
|
|
8
|
+
|
|
9
|
+
const MARKDOWN_PAGES_OPTIONS = new InjectionToken('MARKDOWN_PAGES_OPTIONS', { factory: () => ({}) });
|
|
10
|
+
function provideMarkdownPages(options) {
|
|
11
|
+
return [
|
|
12
|
+
{ provide: MARKDOWN_PAGES_OPTIONS, useValue: options ?? {} },
|
|
13
|
+
...provideMarkdown({
|
|
14
|
+
markedOptions: {
|
|
15
|
+
provide: MARKED_OPTIONS,
|
|
16
|
+
useFactory: () => {
|
|
17
|
+
const renderer = new Renderer();
|
|
18
|
+
renderer.heading = ({ text, depth }) => {
|
|
19
|
+
const slug = text
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.replace(/<[^>]*>/g, '')
|
|
22
|
+
.replace(/[^\w\s-]/g, '')
|
|
23
|
+
.replace(/\s+/g, '-');
|
|
24
|
+
return `<h${depth} id="${slug}">${text}</h${depth}>`;
|
|
25
|
+
};
|
|
26
|
+
return { renderer };
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class MarkdownPageComponent {
|
|
34
|
+
route = inject(ActivatedRoute);
|
|
35
|
+
router = inject(Router);
|
|
36
|
+
el = inject((ElementRef));
|
|
37
|
+
options = inject(MARKDOWN_PAGES_OPTIONS);
|
|
38
|
+
markdownSrc = toSignal(this.route.data.pipe(map((data) => data['markdownFile'])), { initialValue: '' });
|
|
39
|
+
onClick(event) {
|
|
40
|
+
const anchor = event.target.closest('a');
|
|
41
|
+
const href = anchor?.getAttribute('href');
|
|
42
|
+
if (!href?.startsWith('#'))
|
|
43
|
+
return;
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
const fragment = href.substring(1);
|
|
46
|
+
this.router.navigate([], { relativeTo: this.route, fragment }).then(() => {
|
|
47
|
+
document.getElementById(fragment)?.scrollIntoView({ behavior: 'smooth' });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: MarkdownPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
51
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.19", type: MarkdownPageComponent, isStandalone: true, selector: "mdp-markdown-page", host: { listeners: { "click": "onClick($event)" } }, ngImport: i0, template: `<markdown [src]="markdownSrc()" [disableSanitizer]="true" [clipboard]="options.clipboard ?? false" />`, isInline: true, dependencies: [{ kind: "component", type: MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }] });
|
|
52
|
+
}
|
|
53
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: MarkdownPageComponent, decorators: [{
|
|
54
|
+
type: Component,
|
|
55
|
+
args: [{
|
|
56
|
+
selector: 'mdp-markdown-page',
|
|
57
|
+
standalone: true,
|
|
58
|
+
imports: [MarkdownComponent],
|
|
59
|
+
template: `<markdown [src]="markdownSrc()" [disableSanitizer]="true" [clipboard]="options.clipboard ?? false" />`,
|
|
60
|
+
host: { '(click)': 'onClick($event)' },
|
|
61
|
+
}]
|
|
62
|
+
}] });
|
|
63
|
+
|
|
64
|
+
function markdownPageRoutes(config) {
|
|
65
|
+
return config.map(({ path, markdownFile }) => ({
|
|
66
|
+
path,
|
|
67
|
+
component: MarkdownPageComponent,
|
|
68
|
+
data: { markdownFile },
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*
|
|
73
|
+
* Public API Surface of ngx-markdown-pages
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Generated bundle index. Do not edit.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
export { MarkdownPageComponent, markdownPageRoutes, provideMarkdownPages };
|
|
81
|
+
//# sourceMappingURL=ngx-markdown-pages.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-markdown-pages.mjs","sources":["../../src/lib/markdown-pages.config.ts","../../src/lib/markdown-page.component.ts","../../src/lib/markdown-pages.routes.ts","../../src/public-api.ts","../../src/ngx-markdown-pages.ts"],"sourcesContent":["import { InjectionToken, Provider } from '@angular/core';\nimport { provideMarkdown, MARKED_OPTIONS } from 'ngx-markdown';\nimport { Renderer } from 'marked';\n\nexport interface MarkdownPageConfig {\n path: string;\n markdownFile: string;\n}\n\nexport interface MarkdownPagesOptions {\n clipboard?: boolean;\n}\n\nexport const MARKDOWN_PAGES_OPTIONS = new InjectionToken<MarkdownPagesOptions>(\n 'MARKDOWN_PAGES_OPTIONS',\n { factory: () => ({}) }\n);\n\nexport function provideMarkdownPages(options?: MarkdownPagesOptions): Provider[] {\n return [\n { provide: MARKDOWN_PAGES_OPTIONS, useValue: options ?? {} },\n ...provideMarkdown({\n markedOptions: {\n provide: MARKED_OPTIONS,\n useFactory: () => {\n const renderer = new Renderer();\n renderer.heading = ({ text, depth }) => {\n const slug = text\n .toLowerCase()\n .replace(/<[^>]*>/g, '')\n .replace(/[^\\w\\s-]/g, '')\n .replace(/\\s+/g, '-');\n return `<h${depth} id=\"${slug}\">${text}</h${depth}>`;\n };\n return { renderer };\n },\n },\n }),\n ];\n}\n","import { Component, ElementRef, inject } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { map } from 'rxjs';\nimport { MarkdownComponent } from 'ngx-markdown';\nimport { MARKDOWN_PAGES_OPTIONS } from './markdown-pages.config';\n\n@Component({\n selector: 'mdp-markdown-page',\n standalone: true,\n imports: [MarkdownComponent],\n template: `<markdown [src]=\"markdownSrc()\" [disableSanitizer]=\"true\" [clipboard]=\"options.clipboard ?? false\" />`,\n host: { '(click)': 'onClick($event)' },\n})\nexport class MarkdownPageComponent {\n private route = inject(ActivatedRoute);\n private router = inject(Router);\n private el = inject(ElementRef<HTMLElement>);\n protected options = inject(MARKDOWN_PAGES_OPTIONS);\n\n markdownSrc = toSignal(\n this.route.data.pipe(map((data) => data['markdownFile'] as string)),\n { initialValue: '' }\n );\n\n onClick(event: MouseEvent) {\n const anchor = (event.target as HTMLElement).closest('a');\n const href = anchor?.getAttribute('href');\n if (!href?.startsWith('#')) return;\n\n event.preventDefault();\n const fragment = href.substring(1);\n this.router.navigate([], { relativeTo: this.route, fragment }).then(() => {\n document.getElementById(fragment)?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n}\n","import { Route } from '@angular/router';\nimport { MarkdownPageComponent } from './markdown-page.component';\nimport { MarkdownPageConfig } from './markdown-pages.config';\n\nexport function markdownPageRoutes(config: MarkdownPageConfig[]): Route[] {\n return config.map(({ path, markdownFile }) => ({\n path,\n component: MarkdownPageComponent,\n data: { markdownFile },\n }));\n}\n","/*\n * Public API Surface of ngx-markdown-pages\n */\n\nexport type { MarkdownPageConfig, MarkdownPagesOptions } from './lib/markdown-pages.config';\nexport { provideMarkdownPages } from './lib/markdown-pages.config';\nexport { MarkdownPageComponent } from './lib/markdown-page.component';\nexport { markdownPageRoutes } from './lib/markdown-pages.routes';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class MarkdownPageComponent {
|
|
3
|
+
private route;
|
|
4
|
+
private router;
|
|
5
|
+
private el;
|
|
6
|
+
protected options: import("./markdown-pages.config").MarkdownPagesOptions;
|
|
7
|
+
markdownSrc: import("@angular/core").Signal<string>;
|
|
8
|
+
onClick(event: MouseEvent): void;
|
|
9
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MarkdownPageComponent, never>;
|
|
10
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MarkdownPageComponent, "mdp-markdown-page", never, {}, {}, never, never, true, never>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InjectionToken, Provider } from '@angular/core';
|
|
2
|
+
export interface MarkdownPageConfig {
|
|
3
|
+
path: string;
|
|
4
|
+
markdownFile: string;
|
|
5
|
+
}
|
|
6
|
+
export interface MarkdownPagesOptions {
|
|
7
|
+
clipboard?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const MARKDOWN_PAGES_OPTIONS: InjectionToken<MarkdownPagesOptions>;
|
|
10
|
+
export declare function provideMarkdownPages(options?: MarkdownPagesOptions): Provider[];
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ngx-markdown-pages",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@angular/common": "^19.2.0",
|
|
6
|
+
"@angular/core": "^19.2.0",
|
|
7
|
+
"@angular/router": "^19.2.0",
|
|
8
|
+
"ngx-markdown": "^19.0.0",
|
|
9
|
+
"marked": "^15.0.0"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"tslib": "^2.3.0"
|
|
13
|
+
},
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"module": "fesm2022/ngx-markdown-pages.mjs",
|
|
16
|
+
"typings": "index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
"./package.json": {
|
|
19
|
+
"default": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./index.d.ts",
|
|
23
|
+
"default": "./fesm2022/ngx-markdown-pages.mjs"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/public-api.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { MarkdownPageConfig, MarkdownPagesOptions } from './lib/markdown-pages.config';
|
|
2
|
+
export { provideMarkdownPages } from './lib/markdown-pages.config';
|
|
3
|
+
export { MarkdownPageComponent } from './lib/markdown-page.component';
|
|
4
|
+
export { markdownPageRoutes } from './lib/markdown-pages.routes';
|