之前有探討過 Parchment 與 Blot,而 Parchment 還有一個屬性器 (Atrributors),今天就來看一下關於 Attributor 的介紹以及使用方式。

Attributor 是另一種更輕量的表示格式的方式。與其對應的就是 DOM attribute。就像 DOM 屬性與節點的關係一樣,屬性也屬於 Blot。在 Inline 或 Block blot 上呼叫 formats() 如果有對應的 DOM 節點以及 DOM 節點 attribute 則將回傳其表示的格式。

Attributor Class

首先我們來看一下 Attributor 的介面:

class Attributor {
  attrName: string;
  keyName: string;
  scope: Scope;
  whitelist: string[];

  constructor(attrName: string, keyName: string, options: AttributorOptions = {});
  add(node: HTMLElement, value: string): boolean;
  canAdd(node: HTMLElement, value: string): boolean;
  remove(node: HTMLElement);
  value(node: HTMLElement);
}

需要留意的地方是,自訂的 attributor 是 instance,而不是像 blot 一樣的 class 定義。與 Blot 相似,我們不會想要從頭開始建立,而是希望使用既有的 attributors 實現,例如基礎屬性器 (base Attributor),類別屬性器 (Class Attributor) 或樣式屬性器 (Style Attributor)。另外我們也可以透過原始碼來看 attributor 的實現,其實沒有很複雜。

Attributor

使用 Attributor 來表示格式:

const width = new Attributor('width', 'width');

Quill.register(width);

const imageNode = document.createElement('img');
width.add(imageNode, '200px');
console.log(imageNode.outerHTML); // Will print <img width="200px">
const value = width.value(imageNode); // Will return 200px
console.log('value', value); 
width.remove(imageNode);
console.log(imageNode.outerHTML) // Will print <img>

可以看到我們直接以 new Attributor() 的方法來新增一個實體化 width 屬性後,以 Quill.register() 註冊 attribute,並且呼叫 add 方法將屬性加到 img DOM 上。然後可以透過 value() 取得目標 DOM 的 width,最後使用 remove()widthimageNode 刪除。

Class Attributor

使用 Class Attributor 的方式來表示格式:

const align = new ClassAttributor('align', 'blot-align');

Quill.register(align);
const node = document.createElement('div');
align.add(node, 'right');
console.log(node.outerHTML); // Will print <div class="blot-align-right"></div>

有別於上一個 new Attributor(),一樣是 new 但後面換成是 ClassAttributor,帶入指定的 DOM attribute 並自訂一個名稱 blot-align,一樣註冊後使用。也能呼叫 add() 將自訂的 class attributor 加到目標 DOM。

Style Attributor

使用 Style Attributor 的方式來表示格式:

const align = new StyleAttributor('align', 'text-align', {
  whitelist: ['right', 'center', 'justify'], // Having no value implies left align
});

Quill.register(align);

const node = document.createElement('div');
align.add(node, 'right');
console.log(node.outerHTML); // Will print <div style="text-align: right;"></div>

這次則是在實體化的時候以 new StyleAttributor 來新增 attributor,一樣是操作 text-align,但這次加上了 whitelist 來表示合法的參數選項。沒有帶入值則代表 left 置左。在註冊之後呼叫 add() 方法並帶入 DOM 以及 align 的參數選項來套用。

小結

今天探討了 Parchment 的另一塊拼圖,Attributor,提供一個文本格式套用的簡易方式。一開始嘗試練習發現奇怪怎麼會出現找不到的錯誤,看了一下 sourcecode 才發現原來實現的方式已經換了,但 Github 的 repositroy README 還是古早的實現方式。這時只能看原始碼才能知道要怎麼使用了。

我們可以透過 Base Atrributor,Class Atrributor,以及 Style Attributor 來實現不同方式的文本樣式套用,並且 Attributor 也提供了幾個方法例如 add()value()remove() 等方法取得與操作對應的 blot 來編輯文本樣式。之後再研究看看如何將 attributor 應用到編輯器中來套用文本樣式。

雜記

連假後上班的第一天,果然精神不是很好,儘管前一晚已經盡量提早躺平,但起床後還是有沒充滿電的感覺,由於台北住處附近不好停車,所以果斷的把車開回宜蘭停放,所以今天早上是從宜蘭搭車到台北,想說國光客運到南港展覽館離上班地點最近,沒想到七點半到轉運站,要能上車得要等到八點整的班次,到辦公室就都九點了,看來如果是從宜蘭到台北的話還要再更早一點到才行了QQ

Reference

文章同步發表於2023 iThome 鐵人賽