Skip to content

instance-oom/ngx-markdown-editor

Repository files navigation

ngx-markdown-editor

Angular markdown editor based on ace editor

npm version npm GitHub license GitHub stars GitHub issues codesandbox.io

Online Demo

Usage

Installation

Install dependencies from npm repository:

npm i ace-builds bootstrap font-awesome

Install ngx-markdown-editor from npm repository:

npm i ngx-markdown-editor

Add the assets、styles and scripts in angular.json:

{
  ...
  "architect": {
    "build": {
      "options": {
        ...
        "assets": [
          {
            "glob": "**/*",
            "input": "node_modules/ace-builds/src-min",
            "output": "./assets/ace-builds/"
          }
        ],
        "styles": [
          "node_modules/bootstrap/dist/css/bootstrap.min.css",
          "node_modules/font-awesome/css/font-awesome.min.css",
          "node_modules/ngx-markdown-editor/assets/highlight.js/agate.min.css"
        ],
        "scripts": [
          "node_modules/ngx-markdown-editor/assets/highlight.js/highlight.min.js",
          "node_modules/ngx-markdown-editor/assets/marked.min.js"
        ]
        ...
      }
    }
  }
  ...    
}

Add ace.js in index.html

<html>
  <head>
    <script src="/assets/ace-builds/ace.js"></script>
  </head>
  <body></body>
</html>
<=2.5.0

Install dependencies from npm repository:
npm i brace bootstrap font-awesome

Install ngx-markdown-editor from npm repository:

npm i ngx-markdown-editor

Add the styles and scripts in angular.json:

{
  ...
  "architect": {
    "build": {
      "options": {
        ...
        "styles": [
          "node_modules/bootstrap/dist/css/bootstrap.min.css",
          "node_modules/font-awesome/css/font-awesome.min.css",
          "node_modules/ngx-markdown-editor/assets/highlight.js/agate.min.css"
        ],
        "scripts": [
          "node_modules/ngx-markdown-editor/assets/highlight.js/highlight.min.js",
          "node_modules/ngx-markdown-editor/assets/marked.min.js"
        ]
        ...
      }
    }
  }
  ...    
}

Import brace in polyfills.ts

import 'brace';
import 'brace/mode/markdown';

Sample

import { LMarkdownEditorModule } from 'ngx-markdown-editor';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule, // make sure FormsModule is imported to make ngModel work
    LMarkdownEditorModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
<md-editor name="Content" 
  [upload]="doUpload" 
  [preRender]="preRenderFunc" 
  [postRender]="postRenderFunc"
  [(ngModel)]="content" 
  [height]="'200px'" 
  [mode]="mode" 
  [options]="options" 
  (onEditorLoaded)="onEditorLoaded($event)"
  (onPreviewDomChanged)="onPreviewDomChanged($event)"
  required 
  maxlength="500">
  <slot custom-btns></slot>
</md-editor>

Options

  • ngModel: markdown original content
  • height: editor height
  • hideToolbar: hide toolbar, default is false
  • mode: editor | preview, default is editor
  • options: other settings for editor
    {  
      showPreviewPanel?: boolean    // Show preview panel, Default is true
      showBorder?: boolean          // Show editor component's border. Default is true
      hideIcons?: Array<string>     // ['Bold', 'Italic', 'Heading', 'Reference', 'Link', 'Image', 'Ul', 'Ol', 'Code', 'TogglePreview', 'FullScreen']. Default is empty
      usingFontAwesome5?: boolean   // Using font awesome with version 5, Default is false
      fontAwesomeVersion?: '4' | '5' | '6'   // FontAwesome Version, 4/5/6, default is 4
      scrollPastEnd?: number        // The option for ace editor. Default is 0
      enablePreviewContentClick?: boolean  // Allow user fire the click event on the preview panel, like href etc. Default is false
      resizable?: boolean           // Allow resize the editor
      markedjsOpt?: MarkedjsOption  // The markedjs option, see https://marked.js.org/#/USING_ADVANCED.md#options
      customRender?: {              // Custom markedjs render
        image?: Function     // Image Render
        table?: Function     // Table Render
        code?: Function      // Code Render
        listitem?: Function  // Listitem Render
      },
      customIcons?: {               // Custom icons in toolbar, default using font-awesome 4.x
        Bold?: CustomIcon;
        Italic?: CustomIcon;
        Heading?: CustomIcon;
        Reference?: CustomIcon;
        Link?: CustomIcon;
        Image?: CustomIcon;
        UnorderedList?: CustomIcon;
        OrderedList?: CustomIcon;
        CodeBlock?: CustomIcon;
        ShowPreview?: CustomIcon;
        HidePreview?: CustomIcon;
        FullScreen?: CustomIcon;
        CheckBox_UnChecked?: CustomIcon;
        CheckBox_Checked?: CustomIcon;
      };
      placeholder?: string
    }
  • upload(Function): For #24, upload file by yourself
    constructor() {
      this.doUpload = this.doUpload.bind(this);  // This is very important.
    }
    
    doUpload(files: Array<File>): Promise<Array<UploadResult>> {
      // do upload file by yourself
      return Promise.resolve([{ name: 'xxx', url: 'xxx.png', isImg: true }]);
    }
    
    interface UploadResult {
      isImg: boolean
      name: string
      url: string
    }
  • preRender(Function): For #13, this will not effect ngModel's value, just rendered value
    preRenderFunc(content: string) {
      return content.replace(/something/g, 'new value'); // must return a string
    }
  • postRender(Function): Change the html souce code generated by marked before update the dom
    postRenderFunc(content: string) {
      return content.replace(/something/g, 'new value'); // must return a string
    }
  • required: for form validate
  • maxlength: for form validate

Tips: For Function input, please call bind at constructor to assign correct this pointer

Event

  • onEditorLoaded: EventEmitter<AceEditor> Fires when the ace editor loaded.
  • onPreviewDomChanged: EventEmitter<HTMLElement> Fires when the preview dom updated