喜報!Fluent Editor 開源富文字迎來了第一位貢獻者!

Kagol發表於2024-09-01

你好,我是 Kagol,個人公眾號:前端開源星球

2024年8月20日,剛開源一週的富文字 Fluent Editor 迎來了第一位貢獻者:zzxming

1 Bug 描述

zzxming 同學修復了 Fluent Editor 富文字表格模組的一個隱藏 Bug:

fix: table module can't save background color #10

缺陷描述:透過表格右鍵選單設定單元格背景色之後,生成的 delta 中缺失單元格背景色資訊,導致透過 setContents 方法設定的富文字表格單元格丟失了背景色。

這樣描述可能比較繞口,zzxming 同學非常貼心地做了一個 Demo 用於復現該問題:

最小可復現 Demo

2 Bug 復現步驟

第一步:在表格單元格中右鍵,給單元格設定一個背景色。

第二步:透過 editor.getContents() 獲取到的對應的 delta。

const delta = {  
    "ops": [  
        {  
            "attributes": {  
                "table-col": {  
                    "width": "100"  
                }  
            },  
            "insert": "\n"  
        },  
        {  
            "attributes": {  
                "table-cell-line": {  
                    "rowspan": "1",  
                    "colspan": "1",  
                    "row": "row-xapy",  
                    "cell": "cell-e89w"  
                },  
                "row": "row-xapy",  
                "cell": "cell-e89w",  
                "rowspan": "1",  
                "colspan": "1"  
            },  
            "insert": "\n"  
        }  
    ]  
}

可以看到 delta 沒有攜帶單元格背景色資訊。

第三步:將 delta 透過 setContents 方法回填到富文字中,單元格沒有背景色。

editor.setContents(delta)

3 解決方案

修改檔案:packages/fluent-editor/src/table/formats/table.ts

修復該問題主要分成以下步驟:

  • 把 delta 中的 cell-bg 設定到 qlbt-cell-line 節點的 data-cell-bg 屬性中
  • 從 qlbt-cell-line 節點中拿到 data-cell-bg 的值,回填到單元格背景色
  • 將 DOM 節點中的 data-cell-bg 值,儲存到 delta 中

3.1 將 delta 中 cell-bg 資訊設定到 DOM 節點中

將 delta 資訊設定到 DOM 節點中,一般是在 blot 的 static create 方法中進行。

static create(value) {
  const node = super.create(value);

  ...

-  CELL_ATTRIBUTES.forEach((attrName) => {
-  node.setAttribute(`data-${attrName}`, value[attrName] || CELL_DEFAULT[attrName]);
+  [...CELL_ATTRIBUTES, 'cell-bg'].forEach((attrName) => {
+    const keyValue = value[attrName] || CELL_DEFAULT[attrName];
+    keyValue && node.setAttribute(`data-${attrName}`, keyValue);
  });

  ...

  return node;
}

先從 delta(value) 中拿到 cell-bg 資訊,然後設定到 DOM 節點的 data-cell-bg 屬性中。

value 的結構:

{
  rowspan: '1',
  colspan: '1',
  row: 'row-xapy',
  cell: 'cell-e89w',
  cell-bg: '#ffff00'
}

3.2 回填 cell-bg 到單元格背景色

zzxming 同學不僅修復了這個 Bug,還做了一個小重構,將設定單元格背景色這個功能抽成了一個函式 setCellBg,並且加了詳細的註釋,點贊👍

/** this method is for TableCellLine to change cell background color 
 *  if use `format('cell-bg', value)` will loop trigger 
 *  TableCellLine.optimize -> TableCell.format -> TableCellLine.optimize ...
 */
setCellBg(value?: string) {
  if (value) {
    this.domNode.style.backgroundColor = value
  } else {
    this.domNode.style.backgroundColor = 'initial'
  }
}

在 TableCellLine 類的 optimize 方法中呼叫該函式,以便把 delta 中的 cell-bg 顏色設定到表格單元格。

3.3 將 cell-bg 資訊儲存到 delta 中

將 DOM 的資訊儲存到 delta 中,一般是在 blot 的 static format 方法中進行。

在 TableCellLine 類的 static format 方法中呼叫了 reduceFormats 函式,給該函式傳入 cell-bg 資訊。

static formats(domNode) {
  const formats = {};
  if (formats['list']) {
    formats['list'] = domNode.classList.item(0);
  }
-  return reduceFormats(domNode, formats);
+  return reduceFormats(domNode, formats, ['cell-bg']);
}

在 reduceFormats 中獲取到 DOM 中的 data-cell-bg,並設定到 delta 資料中。

- function reduceFormats(domNode, formats) {
-   return CELL_ATTRIBUTES.concat(CELL_IDENTITY_KEYS).reduce((tableFormats, attribute) => {
+ function reduceFormats(domNode:HTMLElement, formats:Record<string, any>, extraFormat: string[] = []) {
+   return [...CELL_ATTRIBUTES, ...CELL_IDENTITY_KEYS, ...extraFormat].reduce((tableFormats, attribute) => {
    if (domNode.hasAttribute(`data-${attribute}`)) {
      tableFormats[attribute] = domNode.getAttribute(`data-${attribute}`) || undefined;
    }
    return tableFormats;
  }, formats);
}

該問題已解決,可以透過以下連結進行驗證:

  • https://stackblitz.com/edit/vitejs-vite-cakzv5?file=src%2FApp.vue

詳見 zzxming 同學提交的 PR:

fix: table module can't save background color #10

3.4 最佳化點

這裡其實有個最佳化點(歡迎 PR 👏):

目前 zzxming 同學在 static create 和 reduceFormats 方法中傳入 cell-bg 都是直接增加的,其實可以放到 CELL_ATTRIBUTES 常量陣列中,合理利用現有的程式碼😋。

- export const CELL_ATTRIBUTES = ['rowspan', 'colspan'];
+ export const CELL_ATTRIBUTES = ['rowspan', 'colspan', 'cell-bg'];

感謝 zzxming 同學對 Fluent Editor 的貢獻,目前已釋出 v3.18.3 版本,歡迎朋友們使用 Fluent Editor,感興趣也歡迎一起參與共建。

往期文章推薦:

  • Fluent Editor:一個基於 Quill 2.0 的富文字編輯器,功能強大、開箱即用!
  • 重回鐵王座!時隔5年!Quill 2.0 終於釋出啦
  • 深入淺出 Quill 系列之使用篇1:Quill 基本使用和配置
  • 深入淺出 Quill 系列之使用篇2:透過 Quill API 實現對編輯器內容的完全控制
  • 深入淺出 Quill 系列之原理篇1:現代富文字編輯器 Quill 的模組化機制
  • 深入淺出 Quill 系列之原理篇2:現代富文字編輯器 Quill 的內容渲染機制
  • 深入淺出 Quill 系列之實踐篇1:如何將龍插入到編輯器中?
  • 深入淺出 Quill 系列之實踐篇2:整個貪吃蛇遊戲到編輯器裡玩兒吧
  • 深入淺出 Quill 系列之選型篇:Quill 富文字編輯器的實踐

聯絡我們

GitHub:https://github.com/opentiny/tiny-vue(歡迎 Star ⭐)

官網:https://opentiny.design/tiny-vue

B站:https://space.bilibili.com/15284299

個人部落格:https://kagol.github.io/blogs

小助手微信:opentiny-official

公眾號:OpenTiny

相關文章