onreadystatechange / blogs

主要记录项目中的重难点,以及如何攻克,有一定的借鉴意义,主要写在Issues
3 stars 0 forks source link

编辑器复制粘贴核心代码 #3

Open onreadystatechange opened 5 years ago

onreadystatechange commented 5 years ago
 destroy() {
    //取消注册事件
    document.removeEventListener('keydown', this.keydown);
    document.removeEventListener('keyup', this.keyup);
    document.removeEventListener('paste', this.paste);
    this.eventType = '';
    document.removeEventListener('cut', this.cut);
    document.removeEventListener('copy', this.copy);
  }

  afterRegistration() {
    //注册事件
    document.addEventListener('keydown', this.keydown);
    document.addEventListener('keyup', this.keyup);
    document.addEventListener('paste', this.paste);
    this.eventType = '';
    document.addEventListener('cut', this.cut);
    document.addEventListener('copy', this.copy);
  }
  copy = e => {
    e.preventDefault();
    e.clipboardData.setData('text/ipresst', 'ipresst');
    this.eventType = 'copy';
  };
  cut = e => {
    e.preventDefault();
    e.clipboardData.setData('text/ipresst', 'ipresst');
    this.eventType = 'cut';
  };
  paste = event => {
    var items = event.clipboardData && event.clipboardData.items;
    let file = '';
    let temp = '';
    let html = '';
    //判断event事件源 主要为过滤block为text的编辑模式
    if (
      !(
        (event.target || event.srcElement).tagName === 'P' ||
        (event.target || event.srcElement).tagName === 'TEXTAREA' ||
        (event.target || event.srcElement).tagName === 'INPUT'
      )
    ) {
      //判断是否外部粘贴
      if (event.clipboardData.getData('text/ipresst') !== 'ipresst') {
        //粘贴图片
        if (items && items.length && items[0].type.indexOf('image') !== -1) {
          // 检索剪切板items
          file = items[0].getAsFile();

          this.editor.emitter.emit('uploadImage', file);
          //粘贴文本
        } else if (
          items &&
          items.length &&
          items[0].type.indexOf('plain') !== -1
        ) {
          //转义html script 防止xss
          temp = event.clipboardData.getData('text/plain');
          temp = xssUtil.unhtmlForUrl(temp);
          //空内容不显示
          if (temp.trim().length > 0) {
            this.editor.editor_state
              .getCurrentSection()
              .block_manager.addElement({
                type: 'text',
                value: { text: temp }
              });
          }
          //复制html 主要是复制其他网页的图片
        } else if (
          items &&
          items.length &&
          items[0].type.indexOf('html') !== -1
        ) {
          html = event.clipboardData.getData('text/html');
          //匹配图片(g表示匹配所有结果i表示区分大小写)
          var imgReg = html.match(/<img.*?(?:>|\/>)/gi);
          //匹配src属性
          var srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i;
          for (var i = 0; i < imgReg.length; i++) {
            var src = imgReg[i].match(srcReg); //获取图片地址
            if (src[1]) {
              //console.log('已匹配的图片地址' + (i + 1) + ':' + src[1]);
              html = src[1];
            }
          }
          this.editor.editor_state
            .getCurrentSection()
            .block_manager.addElement({
              type: 'image',
              value: { src: html }
            });
        }
      } else {
        //内部粘贴
        //执行编辑器自己的粘贴
        this.editor.emitter.emit('invokePasteBlocks');
      }
      //行为记录  粘贴文件
      userActionRecord.public.pasted();
    }
  };
onreadystatechange commented 5 years ago

防止XSS前端代码实现

export const xssUtil = {
  /**
   * 将url中的html字符转义, 仅转义  ', ", <, > 四个字符
   * xss转义
   * @param  { String } str 需要转义的字符串
   * @param  { RegExp } reg 自定义的正则
   * @return { String }     转义后的字符串
   */
  unhtmlForUrl: function(str, reg) {
    return str
      ? str.replace(reg || /[<">']/g, function(a) {
        return {
          '<': '&lt;',
          '&': '&amp;',
          '"': '&quot;',
          '>': '&gt;',
          '\'': '&#39;'
        }[a];
      })
      : '';
  },
  /**
   * 将str中的转义字符还原成html字符
   * @see UE.utils.unhtml(String);
   * @method html
   * @param { String } str 需要逆转义的字符串
   * @return { String } 逆转义后的字符串
   * @example
   * ```javascript
   *
   * var str = '&lt;body&gt;&amp;&lt;/body&gt;';
   *
   * //output: <body>&</body>
   * console.log( UE.utils.html( str ) );
   *
   * ```
   */
  html: function(str) {
    return str
      ? str.replace(/&((g|l|quo)t|amp|#39|nbsp);/g, function(m) {
        return {
          '&lt;': '<',
          '&amp;': '&',
          '&quot;': '"',
          '&gt;': '>',
          '&#39;': '\'',
          '&nbsp;': ' '
        }[m];
      })
      : '';
  }
};