百度編輯器(Ueditor)最新版(1.4.3.3)插入錨點失敗原因分析及BUG修複

来源:http://www.cnblogs.com/nerd/archive/2016/07/14/5671793.html
-Advertisement-
Play Games

用百度編輯器——Ueditor(版本1.4.3.3,2016-05-18日上線)插入錨點的時候,每次總是失敗,百思不得其解。通過分析Ueditor的代碼ueditor.all.js,可以看出Ueditor插入錨點的過程,實際上是一個img標簽和a標簽相互轉換的過程,其代碼如下: 'anchor':{ ...


用百度編輯器——Ueditor(版本1.4.3.3,2016-05-18日上線)插入錨點的時候,每次總是失敗,百思不得其解。通過分析Ueditor的代碼ueditor.all.js,可以看出Ueditor插入錨點的過程,實際上是一個img標簽和a標簽相互轉換的過程,其代碼如下: 

'anchor':{
   //cmd:命令字元串,name:錨點名稱
   execCommand:function (cmd, name) {
                  var range = this.selection.getRange(),img = range.getClosedNode();
                  if (img && img.getAttribute('anchorname')) {
                      if (name) {
                          img.setAttribute('anchorname', name);
                      } else {
                          range.setStartBefore(img).setCursor();
                          domUtils.remove(img);
                      }
                  } else {
                      if (name) {
                          //只在選區的開始插入
                          var anchor = this.document.createElement('img');
                          range.collapse(true);
                          domUtils.setAttributes(anchor,{
                              'anchorname':name,
                              'class':'anchorclass'
                          });
                          range.insertNode(anchor).setStartAfter(anchor).setCursor(false,true);
                      }
                  } 
                           ……

分析上述代碼,插入錨點的過程實際上在Ueditor中顯示的時候其實是插入了一個圖片(img元素),設置該img的anchorname屬性為插入錨點的名字。生成的HTML代碼形如”<img class='anchorclass' anchorname='title_01'>“其中“title_01”即為錨點的名字。代碼看起來是沒有問題的,筆者也多次使用alert調試,運行過程中是可以得到錨點的名稱‘name’的值的,但是在編輯器中查看源代碼的時候始終沒有anchorname屬性,於是筆者手動在得到的img標簽中寫入anchorname的屬性值,結果切換到顯示界面又切換回HTML界面後,該屬性依然丟失,真可謂百思不得其解。接著查看針對插入錨節點時的輸入規則(inputRule)和輸出規則(outputRule)部分的代碼,可以清晰的瞭解到輸出時Ueditor會將擁有anchorname屬性的img節點變成a(超級鏈接)節點,並將該img的anchorname屬性值作為'a'的name屬性值,這樣就完成了一個圖像錨像一個真正錨的變換,代碼如下:

outputRule: function(root){
          utils.each(root.getNodesByTagName('img'),function(a){
              var val;
              if(val = a.getAttr('anchorname')){
                  a.tagName = 'a';
                  a.setAttr({
                      anchorname : '',
                      name : val,
                      'class' : ''
                  })
              }
          })
      },

而輸入的時候使用的輸入規則(inputRule),是當用戶直接在其HTML源碼界面中輸入錨節點的代碼(比如:”<a name="title_01"></a>“)時,當用戶切換到顯示界面的時候,系統會自動將該錨點轉換成圖片錨,該圖片節點(img節點)的class="anchorclass",anchorname="title_01"(上述錨節點的name屬性值),代碼如下:

inputRule:function(root){
           utils.each(root.getNodesByTagName('a'),function(a){
               var val;
               if((val = a.getAttr('name')) && !a.getAttr('href')){
                   a.tagName = 'img';
                   a.setAttr({
                       anchorname :a.getAttr('name'),
                       'class' : 'anchorclass'
                   });
                   a.setAttr('name')
               }
           })
       },

這樣用戶看起來就有一個錨的圖片在剛纔插入錨的地方,而保存的時候仍然會使用outputRule,將該圖片變成一個真正的錨。

代碼的實現看起來一點問題也沒有,可是為什麼就是插入不了錨呢(實質上是在img節點中,無論如何也插入不了anchorname屬性,這點我在官網也嘗試過,也不行,可以說結結實實是個BUG)。

正當我以為該問題無解的時候,我突然發現原來在使用Ueditor的時候,除了引入了Ueditor.all.js外還引入了一個配置文件Ueditor.config.js,我覺得看看這個文件的代碼,這一下,終於被我找到了原因所在。原來在這個配置文件中定義了每個HTML標簽的過濾規則,也就是某個HTML標簽只能有哪些屬性,所以當我們加入其他屬性的時候是會被編輯器過濾掉的,比如我給img添加的achorename屬性(也就是上述程式在講錨轉換成圖片的時候要插入的屬性),因為在img的屬性過濾的白名單中是沒有該屬性的,所以照成了插入的失敗,也照成了編輯器插入錨節點時出現的BUG。同樣,筆者還發現在‘a’標簽的白名單中是沒有‘name’屬性的,也就是編輯器預設情況下是不能插入錨點的,將上述兩個屬性加入到配置文件中,問題得解,可以自由的插入任何錨節點了。下麵附上修改後的img和a標簽的白名單:

// xss 過濾是否開啟,inserthtml等操作

,xssFilterRules: true

//input xss過濾

,inputXssFilter: true

//output xss過濾

,outputXssFilter: true

// xss過濾白名單 名單來源: https://raw.githubusercontent.com/leizongmin

/js-xss/master/lib/default.js

,whitList: {

a:      ['target', 'href', 'title', 'class', 'style','name'],

……

img:    ['src', 'alt', 'title', 'width', 'height', 'id', '_src', 

          'loadingclass', 'class','anchorname']

當然還有其他的一些白名單,由於和本主題無關就不再一一羅列。以上就是我解決Ueditor插入錨點BUG的過程,也許您有更好的方法,請給我留言,謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言:本篇主要針對資料庫的操作,在這裡不適用hibernate或者mybatis,用最原始的JDBC進行講解,通過瞭解這些原理以後更容易理解和學習hibernate或mybatis。 1:jdbc的簡單操作 首先需要下載jdbc驅動的jar包 如果不想下載在C:\Program Files (x86 ...
  • 對於這個月,我主要是在學堂線上上學習MOOC。鄧老師講的很好 !!!這個月,我主要學習數據結構,還不時的到學校OJ上出出題。(PS:我也是學校OJ上的管理員)今天學校停電了。。。OJ管理系統都關了。。。我只好在家開著電腦邊聽歌邊刷清華北大OJ上的簡單題。。。因為難題實在不會。。。暴力我估計都會超時。 ...
  • 總是以為自己瞭解了測試驅動開發,其實做起來和瞭解根本不是一回事。原來覺得代碼清晰得很,後來試驗了一下才知道那是自己的錯覺。這次,讓我們拋卻Eclipse的自動補全功能,來一場真正的測試驅動開發吧。 項目描述:這是一個很簡單的項目,目標是掃描磁碟上所有特定格式的文件,將其路徑存儲下來,通過程式可以快捷 ...
  • ...
  • 槽和普通成員函數一樣,可以是虛函數、被重載,可以是公有、私有、保護的。它可以被其它C++成員函數調用。 槽連接了信號,當發射這個信號時,槽會被自動調用。 連接函數: bool QObject::connect ( const QObject * sender, const char * signal ...
  • 一、概念 生產者與消費者問題是一個金典的多線程協作的問題.生產者負責生產產品,並將產品存放到倉庫;消費者從倉庫中獲取產品並消費。當倉庫滿時,生產者必須停止生產,直到倉庫有位置存放產品;當倉庫空時,消費者必須停止消費,直到倉庫中有產品。 解決生產者/消費者問題主要用到如下幾個技術:1.用線程模擬生產者 ...
  • 1. 從官網下載最新版Python 3.X 後安裝;由於Mac OS X EI Capitan中預設已經集成了 Python 2.7,因此需要在Terminal中輸入 Python3 來檢測是否安裝成功,使用Python命令預設調用的是Python 2.7。 2. 安裝pip;從官網頁面下載get- ...
  • function myBrowser() { var userAgent = navigator.userAgent; //取得瀏覽器的userAgent字元串 var isOpera = userAgent.indexOf("Opera") > -1; //判斷是否Opera瀏覽器 var isI ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...