使用chrome extension解决gitlab在线编辑时输入中文出现错乱的问题

先上一张gif效果图:

gitlab-chrome-input-bug.gif

我们团队内部搭建了gitlab作为代码托管,目前的版本是GitLab Community Edition 8.17.5 9a564a8,在升级到这个版本时,发现在chrome下,在线编辑无法正常输入中文了,出现如上动图的错乱效果,而在firefox是正常的。

一开始怀疑是chrome更新版本后的问题,但是github的在线编辑是正常的,后来通过chrome开发者工具debug,发现是gitlab使用的在线编辑器有问题。无论gitlab还是github,这种在线编辑代码都是借助于一些web编辑器实现的,比如aceeditor,而这里gitlab用的正是aceeditor,因此第一时间跑去aceeditor官网,嗯,人家的是正常的。所以gitlab出现这种问题的原因就是aceeditor编辑器的版本在新版chrome下的bug。

找到问题源头,解决办法也就有眉目了:

  • 直接更新GitLab Community Edition版本到最新版,看看官方是否更换了aceeditor编辑器的版本解决了这个问题。

  • 升级gitlab,可能会担心升级过程会不会有什么新问题,特别是大版本更新就更要慎重。既然这样,那就直接自己在现版本手动去更新aceeditor编辑器,理论上找到gitlab的安装,找到编辑器的相关文件,替换成新的版本。前提是你要摸索清gitlab的目录结构,完整替换编辑器版本。听起来有点麻烦,而且也有一定风险~

  • 这里介绍另一种思路,通过chrome extension在打开编辑页时替换编辑器。这种不是治本的方案,但感觉也是一种思路,刚好团队本身有一个在用从chrome插件,所以把解决方案放进现有的插件即可。这个方案可能适用性和参考意义不大,但这种思路说不定能给到你一些新的想法呢

下面详细说下第三种方案的操作细节:
(涉及到chrome extension的相关细节,这里就不详细描述,默认你拥有chrome extension的开发能力)

下载最新版的aceeditor编辑器

这一步很简单,直接去官网下载即可aceeditor,然后把编辑器的相关文件放到chrome插件下,比如:

|--src  //插件源码
|    |--js
|    |    |--lib
|    |    |    |--src-min-noconflict  //aceeditor

到时候打包插件时会一起打包的。

加载编辑器文件

什么时候去加载新版的编辑器文件呢?因为我们只需要在gitlab编辑界面才用到,所以通过URL匹配来识别当前是编辑界面,然后再去加载aceeditor相关文件。另外还可以根据当前的编辑文件类型,来加载对应的编辑器文件,然后再通过chrome.tabs.executeScript来实现。

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    // when complete
    if (changeInfo.status === 'complete') {

        if(/https:\/\/(你的系统域名)\/.+\/(edit|blob)\/.+/ig.test(tab.url)){
            var newurl = tab.url.replace('(你的系统域名)',''),
                r_file_suffix = /((?!(\.|\/))[\s\S])+\.([a-z]+)/ig;
            newurl.match(r_file_suffix);
            var file_suffix = RegExp.$3,
                jsFiles = [
                '/js/lib/jquery-2.1.3.min.js',
                '/js/lib/src-min-noconflict/ace.js'
                ];
            //根据文件类型
            switch(file_suffix){
                case 'js':
                jsFiles.push('/js/lib/src-min-noconflict/mode-javascript.js');
                break;
                case 'tmpl':
                jsFiles.push('/js/lib/src-min-noconflict/mode-html.js');
                break;
                case 'md':
                jsFiles.push('/js/lib/src-min-noconflict/mode-markdown.js');
                break;
                default :
                jsFiles.push('/js/lib/src-min-noconflict/mode-'+ file_suffix +'.js');
            }
            //替换编辑器以及保存等逻辑
            jsFiles.push('/js/fixgitlabinput.js');

            chrome.tabs.executeScript(tabId, {
                code: 'var injected = window.octotreeInjected; window.octotreeInjected = true; injected;',
                runAt: 'document_start'
            }, function (res) {

                var cssFiles = ['/css/fixgitlabedit.css'];

                eachTask([function (cb) {
                  return eachItem(cssFiles, inject('insertCSS'), cb);
                }, function (cb) {
                  return eachItem(jsFiles, inject('executeScript'), cb);
                }]);

                function inject(fn) {
                  return function (file, cb) {
                    chrome.tabs[fn](tabId, { file: file, runAt: 'document_start' }, cb);
                  };
                }
            });
        }
    }
});

替换操作

加载到编辑器文件,那最后一步就是进行编辑器替换,以及新编辑器的初始化,最后还要在保存时把新编辑器的内容提交。
这些逻辑放进了单独js文件fixgitlabinput.js处理。
这里我选择通过插入一个新的按钮来进行新编辑器的切换:

var fix_btn = '<span class="fix-btn" id="js-fix-btn">中文编辑</span>';
$('body').append(fix_btn);

当点击这个按钮时,会做两件事:
(1)根据当前地址,获取目前编辑文件的内容
(2)把获取到的文件内容用新的编辑器初始化,并隐藏旧版的编辑器,显示新版的编辑器

var fix_btn = '<a href="#fixgitlabedit" class="fix-btn" id="js-fix-btn">中文编辑</a>';
$('body').append(fix_btn);

if(location.hash == '#fixgitlabedit'){
     //传入当前地址和文件类型
    fixeditor(curhref, file_mode);
    $('#js-fix-btn').hide();
}

function fixeditor(curhref, file_mode){
    //隐藏旧的编辑器
    $('#editor').hide();

    var fix_div = '<pre id="js-fix-editor" class="fix-editor"><pre>',
        new_editor,
        $old_editor_par = $('#editor').parent();
    // 插入新的编辑器
    $old_editor_par.append(fix_div);

    var $form_actions = $('form .form-actions');

    //隐藏旧的保存按钮
    $form_actions.find('.btn.commit-btn.js-commit-button.btn-create').hide();
    var new_submit_btn = '<button name="button" class="btn btn-create new-submit-btn">Commit Changes</button>';

    //插入新的保存按钮
    $form_actions.prepend(new_submit_btn);

    //保存操作
    $form_actions.on('click', '.new-submit-btn', function(e){
        if($(this).hasClass('disabled')){return;}
        e.preventDefault();
        $(this).addClass('disabled');
        //获取编辑器的内容,aceeditor提供的方法
        var new_val = new_editor.getValue();
        $('#file-content').val(new_val);
        $("form.form-horizontal.js-quick-submit.js-requires-input.js-edit-blob-form")[0].submit();
    })

    // 根据当前地址获取文件内容
    getHttpRequest(curhref, function(data){
        var r_editor_text = /\<pre class="js-edit-mode-pane" id="editor"\>([\s\S]*)\<\/pre\>/igm;
        data.match(r_editor_text);
        var editor_text = RegExp.$1;
        $old_editor_par.find('#js-fix-editor').html(editor_text);
        //获取编辑器的内容,aceeditor提供的方法
        new_editor = ace.edit("js-fix-editor");
        new_editor.session.setMode("ace/mode/"+file_mode);
    });
}

function getHttpRequest(href, callback){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", href, true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState == 4) {
        var data = xhr.responseText;
        typeof callback == 'function' && callback(data);
      }
    }
    xhr.send();
}

到这里,就可以正常输入中文并保存了,对于没有接触chrome插件开发的人来说可能比较麻烦,so,就当新想法的折腾呗~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339