程序员的资源宝库

网站首页 > gitee 正文

Angular 项目中引入 editor.md

sanyeah 2024-04-09 19:57:38 gitee 5 ℃ 0 评论

版本介绍

本项目由 @angular/cli@13.1.2 生成 Angular 13.1.0 ,引入的是 editor.md v1.5.0 版本。

文件目录

项目根目录
    ├── src
    │   ├── ...
    │   └── assets
    │       ├── ...
    │       └── plugins
	│       	├── jquery.min.js
	│       	├── require.min.js
	│       	├── sea.js
	│       	├── seajs-main.js
    │       	├── zepto.min.js
	│       	└── editormd
	

editormd 文件目录大致为

此目录是由官网直接在下来的压缩包解压后,对部分文件做了删减

引入

index.html 中只引入了核心样式以及脚本文件

  <link rel="stylesheet" href="assets/plugins/editormd/css/editormd.min.css">
  <link rel="stylesheet" href="assets/plugins/editormd/css/editormd.preview.min.css">
  <script type="text/javascript" src="assets/plugins/jquery.min.js"></script>
  <script defer type="text/javascript" src="assets/plugins/editormd/editormd.min.js"></script>

注册组件

import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { AfterViewInit, OnDestroy, Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
declare const editormd: any;

@Component({
  selector: 'app-editor-md',
  template: `<div [id]="editorMdId"><textarea [placeholder]="placeholder" [(ngModel)]="editorContent"></textarea></div>`,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => EditorMdComponent),
      multi: true
    }
  ]
})
export class EditorMdComponent implements AfterViewInit, OnDestroy, ControlValueAccessor {
  editorMdId: string = '';
  editorContent: string = '';

  @Input() theme: string = 'twilight'; // editor.md的样式主题,对应 editormd/lib/codemirror/theme
  @Input() disabled: boolean = false;
  @Input() watch: boolean = true; // 实时预览
  @Input() defaulted: 'markdown' | 'html' = 'markdown';
  @Input() placeholder: string = '请输入内容(支持markdown格式)';
  @Output() loaded = new EventEmitter<boolean>();
  @Output() changed = new EventEmitter<string>()
  // editormd 对象
  private markdownEditor: any;

  private editorCustomConfig = {
    width: '100%',
    height: 640,
    path: 'assets/plugins/editormd/lib/', // editor.md的支持插件存放位置
    fontSize: '14px',
    codeFold: true,
    syncScrolling: true,
    saveHTMLToTextarea: true, // 保存 HTML 到 Textarea
    searchReplace: true,
    htmlDecode: 'style,script,iframe|on*', // 开启 HTML 标签解析,为了安全性,默认不开启
    toolbar: true, // 工具栏
    toolbarIcons: function () {
      // 自定义工具栏
      // return editormd.toolbarModes["mini"]; // full, simple, mini
      return ["undo",
        "redo",
        "|",
        "bold",
        "del",
        "italic",
        "quote",
        "ucwords",
        "uppercase",
        "lowercase",
        "|",
        "h1",
        "h2",
        "h3",
        "h4",
        "h5",
        "h6",
        "|",
        "list-ul",
        "list-ol",
        "hr",
        "|",
        "link",
        "reference-link",
        "image",
        "code",
        "preformatted-text",
        "code-block",
        "table",
        "datetime",
        "html-entities",
        "pagebreak",
        "|",
        "watch",
        "preview",
        "fullscreen",
        "clear",
        "search",];
    },
    previewCodeHighlight: true, // 关闭预览 HTML 的代码块高亮,默认开启
    emoji: false, // 是否支持表情
    taskList: true, // 是否支持任务列表
    tocm: false, // Using [TOCM]
    // tex: false, // 开启科学公式TeX语言支持,默认关闭
    // flowChart: false, // 开启流程图支持,默认关闭
    // sequenceDiagram: false, // 开启时序/序列图支持,默认关闭,
    dialogLockScreen: true, // 设置弹出层对话框不锁屏,全局通用,默认为true
    dialogShowMask: true, // 设置弹出层对话框显示透明遮罩层,全局通用,默认为true
    dialogDraggable: true, // 设置弹出层对话框不可拖动,全局通用,默认为true
    dialogMaskOpacity: 0.45, // 设置透明遮罩层的透明度,全局通用,默认值为0.1
    dialogMaskBgColor: '#000', // 设置透明遮罩层的背景颜色,全局通用,默认为#fff
    imageUpload: true, // 是否支持图片本地上传
    imageFormats: ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp'], // 支持的图片格式
    imageUploadURL: '/fileOSS/editoruploader', // 上传附件的服务路径
  };
  private onChange = (_: any) => { };
  private onTouched = () => { };

  constructor() {
    this.editorMdId = `MD${this.generateId(6, 16)}`;
  }

  ngAfterViewInit() {
    this.editorStartup();
  }

  ngOnDestroy() {
    if (this.markdownEditor) {
      this.markdownEditor.editor.remove();
    }
  }

  writeValue(obj: string): void {
    this.editorContent = obj;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  private editorStartup(): void {
    this.createEditor(this.editorCustomConfig);
  }

  private createEditor(editorConfig: any): void {
    const that = this;
    that.markdownEditor = editormd(that.editorMdId, {
      ...editorConfig,
      watch: that.disabled ? true : that.watch,
      theme: that.theme,
      previewTheme: that.theme,
      editorTheme: that.theme,
      readOnly: that.disabled,
      placeholder: that.placeholder,
      onload: function () {
        that.loaded.emit(true);
        // 防止渲染为空的情况
        if (that.editorContent) {
          this.setMarkdown(that.editorContent);
        }
        if (that.disabled) {
          this.previewing();
        }
        // this.resize("100%", 640);
        // this.fullscreen();
        // this.watch().fullscreen();
        // this.width("100%");
        // this.height(480);
      },
      onchange: function () {
        if (that.defaulted == 'html') {
          that.onChange(this.getHTML());
          that.changed.emit(this.getHTML());
        } else {
          that.onChange(this.getMarkdown());
          that.changed.emit(this.getMarkdown());
        }
      },
    });
  }
  /**
   * ID生成器
   * @param len 生成的ID的长度
   * @param radix 生成的ID的混淆器长度
   * @returns 
   */
  private generateId(len: number, radix: number) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    var uuid = [],
      i;
    radix = radix || chars.length;

    if (len) {
      // Compact form
      for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
    } else {
      // rfc4122, version 4 form
      var r;
      // rfc4122 requires these characters
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
      uuid[14] = '4';
      // Fill in random data.  At i==19 set the high bits of clock sequence as
      // per rfc4122, sec. 4.1.5
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | (Math.random() * 16);
          uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
        }
      }
    }
    return uuid.join('');
  }
}

结语

以上代码便是 editor.md 的一个简单封装,简单的使用就可以是 <app-editor-md placeholder="请输入内容" [(ngModel)]="content"></app-editor-md> ,如非不需要form表单绑定,可以再行变更。

如有问题,还请提出,我会及时改正。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表