石墨文档快捷格式插件

石墨文档快捷键格式应用,石墨文档格式刷,点击左下角小窗口来使用

当前为 2022-03-20 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         石墨文档快捷格式插件
// @namespace    QQ421566927
// @version      0.4
// @description  石墨文档快捷键格式应用,石墨文档格式刷,点击左下角小窗口来使用
// @resource     layuiCss https://www.layuicdn.com/layui-v2.5.7/css/layui.css
// @resource     layDate https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/css/modules/laydate/default/laydate.css?v=5.0.9
// @resource     layerCss https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/css/modules/layer/default/layer.css?v=3.1.1
// @resource     codeCss https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/css/modules/code.css
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/layui.all.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/mousetrap/1.6.5/mousetrap.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/mousetrap/1.6.5/plugins/record/mousetrap-record.min.js
// @require      https://cdn.bootcss.com/store.js/1.3.20/store.min.js
// @match        https://shimo.im/docs/*
// @grant        GM_log
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceURL
// @license MIT
// ==/UserScript==
(function() {
  'use strict';

  var defaultData = [
    {
      "key": "shimo_format_1",
      "value": {
        "name": "默认黑字",
        "content":"",
        "format": "<span class=\"ql-author-45317226\" style=\"color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);color: #000000;\">预览</span>",
        "hotkey": "ctrl+0",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_2",
      "value": {
        "name": "红字删除线",
        "content":"",
        "format": "<s style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</s>",
        "hotkey": "ctrl+1",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_3",
      "value": {
        "name": "蓝字加粗",
        "content":"",
        "format": "<strong style=\"color: rgb(25, 67, 156);color: #19439c;\">预览</strong>",
        "hotkey": "ctrl+2",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_4",
      "value": {
        "name": "绿字加粗",
        "content":"",
        "format": "<strong style=\"color: rgb(28, 114, 49);color: #1c7231;\">预览</strong>",
        "hotkey": "ctrl+3",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_5",
      "value": {
        "name": "①",
        "content":"①",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+1",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_6",
      "value": {
        "name": "②",
        "content":"②",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+2",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_7",
      "value": {
        "name": "③",
        "content":"③",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+3",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_8",
      "value": {
        "name": "④",
        "content":"④",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+4",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_9",
      "value": {
        "name": "⑤",
        "content":"⑤",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+5",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_10",
      "value": {
        "name": "⑥",
        "content":"⑥",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+6",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_11",
      "value": {
        "name": "⑦",
        "content":"⑦",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+7",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_12",
      "value": {
        "name": "⑧",
        "content":"⑧",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+8",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_13",
      "value": {
        "name": "⑨",
        "content":"⑨",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+9",
        "isDefault": true
      }
    },
    {
      "key": "shimo_format_14",
      "value": {
        "name": "⑩",
        "content":"⑩",
        "format": "<strong style=\"color: rgb(255, 0, 0);color: #ff0000;\">预览</strong>",
        "hotkey": "alt+0",
        "isDefault": true
      }
    }
  ]

  var layuiCss_CssSrc = GM_getResourceText ("layuiCss");
  var layDate_CssSrc = GM_getResourceText ("layDate");
  var layerCss_CssSrc = GM_getResourceText ("layerCss");
  var codeCss_CssSrc = GM_getResourceText ("codeCss");
  GM_addStyle (layuiCss_CssSrc);
  GM_addStyle (layDate_CssSrc);
  GM_addStyle (layerCss_CssSrc);
  GM_addStyle (codeCss_CssSrc);

  var style = document.createElement("style");
  style.type = "text/css";
  var text = document.createTextNode(".layui-layer-ico{background: url('https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/css/modules/layer/default/icon.png') no-repeat;}@font-face {font-family: layui-icon;src: url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.eot?v=256');src: url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.eot?v=256#iefix') format('embedded-opentype'),url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.woff2?v=256') format('woff2'),url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.woff?v=256') format('woff'),url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.ttf?v=256')format('truetype'),url('https://www.layuicdn.com/layui-v2.5.7/font/iconfont.svg?v=256#layui-icon') format('svg')}");
  style.appendChild(text);
  var head = document.getElementsByTagName("head")[0];
  head.appendChild(style);

  //全局变量
  var canCopy = false
  var tempNumber = 0
  var isRecord = false
  var hotKeyList = []
  var keyPrefix = 'shimo_format_'
  var isPaste = false


  var getRecordData = function () {
    var formatData = []

    if(!store.get(keyPrefix+'1')){
      defaultData.forEach(function (item) {
        store.set(item.key, item.value)
      })
    }

    store.forEach(function(key, val) {
      if(key.indexOf(keyPrefix) != -1){
        val.number = key.split('_')[2]
        formatData[val.number] = val
        if(val.hotkey != ''){
          hotKeyList[val.hotkey] = val
        }
      }
    })
    return formatData
  }

  var setRecordData = function (number,name,content,format,hotkey,isDefault) {
    var formatData = {
      name:name,
      content:content,
      format:format,
      hotkey:hotkey,
      isDefault:isDefault
    }
    store.set(keyPrefix+number, formatData)
  }

  var getInsertNumber = function () {
    var numberList = []

    store.forEach(function(key, val) {
      if(key.indexOf(keyPrefix) != -1){
        var splitRes = key.split('_')
        if(splitRes.length == 3){
          numberList.push(splitRes[2])
        }
      }
    })

    if(numberList.length > 0){
      var n = Math.max.apply(null, numberList);
      return n + 1
    }else{
      return 1
    }
  }

  var getBaseRowData = function (item) {
    var row =  '<div name="p_data_row_'+item.number+'" isdefault="'+item.isDefault+'" class="layui-row" style="font-size: 16px;margin-left:-160px;padding-left: 50px;">\n' +
        '    <div class="layui-col-sm2">\n' +
        '     &nbsp;'  +
        '    </div>\n' +
        '    <div class="layui-col-sm1" style="text-align: right;">\n' +
        '     名称:'  +
        '    </div>\n' +
        '    <div class="layui-col-sm2">\n' +
        '       <input type="text" style="width: 90px;" value="'+item.name+'" name="p_data_name" autocomplete="off" placeholder="请输入名称" class="layui-input-inline">\n' +
        '    </div>\n' +
        '    <div class="layui-col-sm1" style="text-align: center;margin-left:-30px;">\n' +
        '        <a name="p_data_record" href="javascript:void(0)"><i class="layui-icon layui-icon-radio" style="font-size: 19px; color: #1E9FFF;padding-top: 3px"></i></a>\n' +
        '    </div>\n' +
        '    <div class="layui-col-sm1">\n' +
        '        <span name="p_data_preview">'+item.format+'</span>\n' +
        '    </div>\n' +
        '    <div class="layui-col-sm2">\n' +
        '       <input type="text" style="width: 90px;" value="'+item.content+'" name="p_data_content" autocomplete="off" placeholder="替换文字" class="layui-input-inline">\n' +
        '    </div>\n' +
        '    <div class="layui-col-sm2" name="p_data_quike" style="padding-top: 2px;">\n' +
        '        <input  style="width: 130px;font-size: 16px;" value="'+item.hotkey+'"  type="text" name="title" lay-verify="title" autocomplete="off" placeholder="录制快捷键" class="layui-input-inline" disabled>\n' +
        '    </div>\n' +
        '    <div class="layui-col-sm1" style="padding-left: 20px;">\n' +
        '        <a name="p_data_brush" href="javascript:void(0)"><i class="layui-icon layui-icon-fonts-clear" style="font-size: 19px; color: #1E9FFF;padding-top: 3px"></i></a>\n' +
        '        <a name="p_data_del" href="javascript:void(0)"><i class="layui-icon layui-icon-delete" style="font-size: 19px; color: #1E9FFF;padding-top: 3px"></i></a>\n' +
        '    </div>\n' +
        '</div>'

    return row

  }

  var render = function () {
    var htmlStr = ''
    var addDataButton = '<div class="layui-col-md12" style="text-align: center;margin-top: 4%"><button name="p_data_add_button" type="button" style="background-color: #5c5c5c;" class="layui-btn"><i class="layui-icon">&#xe608;</i> 添加</button></div>'
    var dataRes = getRecordData()

    dataRes.forEach(function (item) {
      var tempHtml = getBaseRowData(item)
      htmlStr += tempHtml
    })
    htmlStr += addDataButton
    return htmlStr
  }

  var getRowNum = function(el){
    var prent = $(el).parents('div[name^="p_data_row_"]')
    var num = prent.attr('name').split('_')[3]
    return num
  }

  //记忆窗口
  var setWindow = function(layero,type){
    var top = $(layero).css('top').replace('px','')
    var left = $(layero).css('left').replace('px','')
    var height = $(layero).css('height').replace('px','')
    var width = $(layero).css('width').replace('px','')

    if(type == 'moveWindow'){
      store.set('layer_window_top',parseInt(top) == 0 ? 1 : parseInt(top))
      store.set('layer_window_left',parseInt(left) == 0 ? 1 : parseInt(left))
    }

    if(type == 'reSize'){
      store.set('layer_window_height',height)
      store.set('layer_window_width',width)
    }
  }

  var replaceSelection = function(replaceText) {
    if (window.getSelection) {
      var selecter = window.getSelection();
      var range = selecter.getRangeAt(0);
      let textEl = document.createRange().createContextualFragment(replaceText).children;
      console.log(textEl)
      selecter.removeAllRanges()
      selecter.empty();
      range.deleteContents()
      range.insertNode(textEl[0]);
    } else if (document.selection) {//ie
      var selecter = document.selection.createRange();
      selecter.select();
      selecter.pasteHTML(replaceText);
    }
  }


  layui.use('layer', function(){
    var $ = layui.jquery
    var active = {
      setTop: function(firstOpen = false){
        var that = this;
        //多窗口模式,层叠置顶
        var top = store.get('layer_window_top')  ?  store.get('layer_window_top') : '280'
        var left = store.get('layer_window_left')  ?  store.get('layer_window_left') : '900'
        var width = store.get('layer_window_width') ? store.get('layer_window_width')+'px' : '700px'
        var height = store.get('layer_window_height') ? store.get('layer_window_height')+'px' : '530px'
        layer.open({
          id:'p_data_all'
          ,type: 1 //此处以iframe举例
          ,title: '快捷格式插件'
          ,area: [ width,height]
          ,shade: 0
          ,maxmin: true
          ,closeBtn: false
          ,offset: [
            top
            ,left
          ]
          ,content: render()
          ,yes: function(){
            $(that).click();
          }
          ,btn2: function(){
            layer.closeAll();
          }
          ,zIndex: layer.zIndex
          ,success: function(layero){
            layer.setTop(layero);
            if(firstOpen){
              setTimeout(function () {
                $('.layui-layer-min').click()
              },1000)
            }
          },
          moveEnd: function(layero){
            setWindow(layero,'moveWindow')
          },
          resizing: function(layero){
            setWindow(layero,'reSize');
          },
        });
      },
      msg:function (msg) {
        layer.msg(msg)
      }
    };
    active.setTop(true)

    //监听部分
    //添加按钮
    $(document).on('click',':button[name="p_data_add_button"]',function () {
      var number =  getInsertNumber()
      setRecordData(number,'','','预览','',false)
      $('#p_data_all').html(render())
    })

    //名称输入框监听
    $(document).on('blur',':input[name="p_data_name"]',function () {
      var input_name = $(this).val()
      var num = getRowNum(this)
      var cur = store.get(keyPrefix+num)
      setRecordData(num,input_name,cur.content,cur.format,cur.hotkey,cur.isDefault)
      layer.msg('保存成功',{zIndex:layer.zIndex})
    })

    //内容输入框监听
    $(document).on('blur',':input[name="p_data_content"]',function () {
      var input_content = $(this).val()
      var num = getRowNum(this)
      var cur = store.get(keyPrefix+num)
      setRecordData(num,cur.name,input_content,cur.format,cur.hotkey,cur.isDefault)
      layer.msg('保存成功',{zIndex:layer.zIndex})
    })

    //录制
    $(document).on('click','a[name="p_data_record"]',function () {
      canCopy = true
      tempNumber  = getRowNum(this)
      layer.msg('请选中文本格式后使用 Ctrl+C 录入格式',{zIndex:layer.zIndex})
    })

    //快捷键
    $(document).on('click','div[name="p_data_quike"]',function () {
      isRecord = true
      layer.msg('请输入快捷键',{zIndex:layer.zIndex})
      tempNumber = getRowNum(this)
    })

    //删除
    $(document).on('click','a[name="p_data_del"]',function () {
      var prent = $(this).parents('div[name^="p_data_row_"]')
      if($(prent).attr('isdefault') == 'true'){
        layer.msg('默认配置不可删除!',{zIndex:layer.zIndex})
        return false;
      }
      var num = prent.attr('name').split('_')[3]
      store.remove(keyPrefix+num)
      $('#p_data_all').html(render())
      layer.msg('删除成功',{zIndex:layer.zIndex})
    })


    //单机刷子
    $(document).on('click','a[name="p_data_brush"]',function () {
      let allData = getRecordData()
      var itemEl = $(this).parent().parent()
      var elIndex = ($('#p_data_all div').index(itemEl)/9)+1
      console.log(elIndex)
      layer.msg('请选中需要应用的文字',{zIndex:layer.zIndex})
      var brushOver = false
      //$textElem是指编辑器可编辑区域(详情请查看源码)
      $('div.ql-editor.notranslate').on('mouseup', e => {
        if(brushOver == false){
          brushOver = true
          // document.querySelector('.ql-clean.ql-toolbar-widget').click()
          var selection = window.getSelection() || document.getSelection() || document.selection.createRange();
          console.log(selection)
          console.log(selection.text)
          var item = allData[elIndex]
          if(item.content == ""){
            var selectionStr = window.getSelection().toString()
          }else{
            var strLen = window.getSelection().toString().length
            var selectionStr = ""
            for (var i=0;i<strLen;i++){
              selectionStr += item.content
            }
          }
          var copyStr = item.format.replace('>预览</','>'+selectionStr+'</')
          replaceSelection(copyStr)
        }
      })
    })

  });

  document.addEventListener('paste', function (event) {
    if(isPaste){
      isPaste = false
      layer.msg('应用成功!',{zIndex:layer.zIndex})
    }
  })

  document.addEventListener('copy', function (event) {
    if(canCopy){
      var clipboardData = event.clipboardData || window.clipboardData;
      var res =  clipboardData.getData('text/html');
      canCopy = false
      var el = $($(res).children()[0])
      var elHtml = el.prop('innerHTML')
      if($(elHtml).length >1){
        elHtml = $($(elHtml)[0]).prop('outerHTML')
        elText = $($(elHtml)[0]).text()
      }else{
        var elText = $($(res).children()[0]).text()
      }

      var resHtml = elHtml.replace('>'+elText+'</','>预览</')

      if(elText == elHtml){
        resHtml = "<span class=\"ql-author-45317226\">预览</span>"
      }

      var cur = store.get(keyPrefix+tempNumber)
      setRecordData(tempNumber,cur.name,cur.content,resHtml,cur.hotkey,cur.isDefault)
      $('#p_data_all').html(render())
      layer.msg('格式录制成功!',{zIndex:layer.zIndex})
    }
  });


  $(document).keydown(function(event){
    Mousetrap.record(function(sequence) {
      var keyStr = sequence.join(' ')

      if(keyStr == 'ctrl+shift+m'){
        store.remove('layer_window_top')
        store.remove('layer_window_left')
        store.remove('layer_window_height')
        store.remove('layer_window_width')
        layer.msg('重置窗口成功,请刷新页面',{zIndex:layer.zIndex})
      }

      if(isRecord){
        isRecord = false
        var num = tempNumber
        var cur = store.get(keyPrefix+num)
        let allData = getRecordData()
        let isRepeat = false;
        allData.forEach(function (item) {
          if(item.number != num && item.hotkey == keyStr){
            isRepeat = true
          }
        })

        if(isRepeat){
          layer.msg('错误!!快捷键已经存在!!! 快捷键:'+keyStr,{zIndex:layer.zIndex})
          return false;
        }

        setRecordData(num,cur.name,cur.content,cur.format,keyStr,cur.isDefault)
        $('#p_data_all').html(render())
        layer.msg('录制成功:'+keyStr,{zIndex:layer.zIndex})
      }else{
        if(hotKeyList[keyStr] != undefined){
          var item = hotKeyList[keyStr]
          var selection = window.getSelection() || document.getSelection() || document.selection.createRange();
          var selectionStr = selection.toString()
          if(item.content != ''){
            selectionStr = item.content
          }else if(selectionStr == ''){
            selectionStr = '&#65279;'
          }

          if(item.format == '预览'){
            // var copyStr = selectionStr
            layer.msg(item.hotkey+' 还没有录制格式呢!',{zIndex:layer.zIndex})
            return false
          }else{
            var copyStr = item.format.replace('>预览</','>'+selectionStr+'</')
          }


          var originRange = selection.getRangeAt(0)

          var beforeLast = $('body').children().last()
          var text = $(copyStr).appendTo('body')
          console.log(text)
          if (document.body.createTextRange) {
            var range = document.body.createTextRange();
            range.moveToElementText(text);
            range.select();
          } else if (window.getSelection) {
            var selection = window.getSelection();
            var range = document.createRange();
            range.selectNodeContents(text[0]);
            selection.removeAllRanges();
            selection.addRange(range);
          }

          document.execCommand('Copy','false',null);

          $(beforeLast).nextAll().remove()

          selection.removeAllRanges();
          selection.addRange(originRange)
          isPaste = true
          // var tempStr = item.content != '' ? "内容:'"+item.content+"' 已复制" : '格式:'+item.name+'已处理完成'
          // layer.msg(tempStr+',使用 Ctrl+V 应用',{zIndex:layer.zIndex})

          // document.querySelector('.ql-clean.ql-toolbar-widget').click()
          if(item.content == ""){
            var selectionStr = window.getSelection().toString()
          }else{
            var strLen = window.getSelection().toString().length
            var selectionStr = ""
            if(strLen == 0){
              strLen = 1
            }
            for (var i=0;i<strLen;i++){
              selectionStr += item.content
            }
          }
          var copyStr = item.format.replace('>预览</','>'+selectionStr+'</')
          console.log(copyStr)
          replaceSelection(copyStr)
          layer.msg(item.name+' 快捷键格式应用成功!',{zIndex:layer.zIndex})

          //
          // if (selectStr.trim() != "") {
          //
          // }else{
          //   var tempStr = item.content != '' ? "内容:'"+item.content+"' 已复制" : '格式:'+item.name+'已处理完成'
          //   layer.msg(tempStr+',使用 Ctrl+V 应用',{zIndex:layer.zIndex})
          // }

        }

      }
    });
  });
})();