shortcodes
shortcodes enhances your markdown content with interactive Angular components. Works with static site generator scully and ngx-markdown.
Getting Started
Installation
First, install the library using npm or yarn
npm i @notiz/shortcodes
# or
yarn add @notiz/shortcodes
Next, import ShortcodeModule
in your content module and wrap your markdown content (<scully-content></scully-content>
or <markdown></markdown>
) with the shortcodes
or scullyShortcodes
directive. The shortcodes
directive is responsible to render the shortcodes correctly.
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ShortcodeModule } from '@notiz/shortcodes';
import { BlogRoutingModule } from './blog-routing.module';
import { BlogComponent } from './blog.component';
@NgModule({
declarations: [BlogComponent],
imports: [
CommonModule,
BlogRoutingModule,
ShortcodeModule
],
})
export class BlogModule {}
Scully
You need to setup a Angular Scully Project first. If you don't know how, read the blog post Jamstack with Angular and Scully or consolidate the scully docs.
Add ScullyLibModule
to your module.
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
+import { ScullyLibModule } from '@scullyio/ng-lib';
import { ShortcodeModule } from '@notiz/shortcodes';
import { BlogRoutingModule } from './blog-routing.module';
import { BlogComponent } from './blog.component';
@NgModule({
declarations: [BlogComponent],
imports: [
CommonModule,
BlogRoutingModule,
ShortcodeModule,
+ ScullyLibModule
],
})
export class BlogModule {}
Wrap scully-content
with the scullyShortcodes
directive.
import { Component } from '@angular/core';
@Component({
selector: 'app-blog',
template: `
<div scullyShortcodes>
<scully-content></scully-content>
</div>
`,
})
export class BlogComponent {}
Next, add the provided Scully Plugin to your Scully Configuration
import { ScullyConfig } from '@scullyio/scully';
import './node_modules/@notiz/shortcodes/scully';
export const config: ScullyConfig = {
projectRoot: './src',
projectName: 'app',
outDir: './dist/static',
routes: {
'/:slug': {
type: 'contentFolder',
slug: {
folder: './docs',
},
+ postRenderers: ['shortcodes'],
},
}
};
ngx-markdown
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
+import { MarkdownModule } from 'ngx-markdown';
+import { HttpClient, HttpClientModule } from '@angular/common/http';
import { ShortcodeModule } from '@notiz/shortcodes';
import { BlogRoutingModule } from './blog-routing.module';
import { BlogComponent } from './blog.component';
@NgModule({
declarations: [BlogComponent],
imports: [
CommonModule,
BlogRoutingModule,
ShortcodeModule,
+ HttpClientModule,
+ MarkdownModule.forRoot({ loader: HttpClient }),
],
})
export class BlogModule {}
Wrap markdown
with the shortcodes
directive.
import { Component } from '@angular/core';
@Component({
selector: 'app-blog',
template: `
<div shortcodes>
<markdown [src]="..."></markdown>
</div>
`,
})
export class BlogComponent {}
Usage
A shortcode is a normal Angular component containing any templates (from buttons, images to charts), styles, animations and much more.
Shortcode component
Let's create an Angular note
component to use as shortcode. In this example, the component is styled with Tailwind CSS utility classes and using material icons.
import { Component, HostBinding, Input } from '@angular/core';
@Component({
selector: 'app-note',
template: `
<i
class="material-icons-outlined mt-2"
[ngClass]="{
'text-green-700': type === 'success',
'text-red-700': type === 'danger'
}"
>
{{ type === 'success' ? 'info' : 'dangerous' }}
</i>
<div
[ngClass]="{
'text-green-700': type === 'success',
'text-red-700': type === 'danger'
}"
>
<ng-content></ng-content>
</div>
`,
})
export class NoteComponent {
@HostBinding('class')
get class(): string {
return `flex space-x-5 border-l-4 rounded-md p-4 ${
this.type === 'success'
? 'border-green-700 bg-green-50'
: 'border-red-700 bg-red-50'
}`;
}
@Input() type: 'success' | 'danger' = 'success';
}
Register the shortcode component in the ShortcodeModule
in your app.module.ts
. This allows to lazy load each shortcode component, similar to the RouterModule
.
import { NgModule } from '@angular/core';
import { ShortcodeModule } from '@notiz/shortcodes';
@NgModule({
...
imports: [
ShortcodeModule.forRoot([
{
shortcode: 'demos',
loadChildren: () =>
import('./demos/demos.module').then((m) => m.DemosModule),
}
]),
],
...
})
export class AppModule {}
Lastly, register the shortcode component with a name in your component.module.ts
. The name will be used in your markdown files.
import { NgModule } from '@angular/core';
import { ShortcodeModule, Shortcodes } from '@notiz/shortcodes';
import { NoteComponent } from './note.component';
const shortcodes: Shortcodes = [
{ shortcode: 'note', component: NoteComponent },
];
@NgModule({
imports: [ShortcodeModule.forChild(shortcodes)],
declarations: [NoteComponent],
})
export class DemosModule {}
Use your shortcode in your content
Now you are ready to use your shortcode in your markdown content. Add a div
with shortcode="path/shortcodeName"
to specify your shortcode component. The content will replace the <ng-content></ng-content>
inside the note
component.
<div shortcode="demos/note">
# This is a note!
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Input's are possible too, add them after the shortcode
on your div
.
<div shortcode="demos/note" type="danger">
# This is a note!
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
Result
This is a note!
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
note
shortcode with input type="danger"
This is a note!
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.