Etherpad/外掛:修訂版本之間的差異
出自福留子孫
(未顯示2位用戶所作出之25次版本) | |||
第 1 行: | 第 1 行: | ||
− | [[分類: | + | [[分類:Etherpad]] |
第 5 行: | 第 5 行: | ||
<videoflash>-pCNSqZF1dw</videoflash> | <videoflash>-pCNSqZF1dw</videoflash> | ||
[https://www.youtube.com/watch?v=-pCNSqZF1dw 寫出第一個Etherpad外掛] | [https://www.youtube.com/watch?v=-pCNSqZF1dw 寫出第一個Etherpad外掛] | ||
+ | ===步驟=== | ||
+ | *可將 setting.json 中 "minify" 的設定由 true 改成 false ,方便 debug | ||
+ | *創造 plugins 資料夾(舉例 ep_previewimages) | ||
+ | *在資料夾中新增 packages.json ,裡面打此外掛的基本資訊(名字 作者 版本 描述 貢獻者 運行引擎),無涉外掛運用([https://etherpad.org/doc/latest/#index_plugins 範例(搜尋Package definition)])<br/> 其中 name 為外掛的名字, version 為外掛版本, description 為外掛介紹, author 為外掛作者, contributors 為貢獻者名單, dependencies 為寫程式所依賴的工具包, engines 為運行引擎。 | ||
+ | <pre>{ | ||
+ | "name": "ep_PLUGINNAME", | ||
+ | "version": "0.0.1", | ||
+ | "description": "DESCRIPTION", | ||
+ | "author": "USERNAME (REAL NAME) <MAIL@EXAMPLE.COM>", | ||
+ | "contributors": [], | ||
+ | "dependencies": {"MODULE": "0.3.20"}, | ||
+ | "engines": {"node": ">=12.13.0"} | ||
+ | }</pre> | ||
+ | :以 ep_previewimages 中的 packages.json 為例: | ||
+ | <pre>{ | ||
+ | "name":"ep_previewimages", | ||
+ | "description":"Image previewer, paste the URL of an image or upload an image using ep_fileupload", | ||
+ | "version":"0.0.13", | ||
+ | "author":"johnyma22 (John McLear) <john@mclear.co.uk>", | ||
+ | "contributors":[], | ||
+ | "dependencies":{}, | ||
+ | "repository":{"type":"git","url":"https://github.com/JohnMcLear/ep_previewimages.git"}, | ||
+ | "engines":{"node":"*"} | ||
+ | }</pre> | ||
+ | *在資料夾中新增 ep.json ,裡面打外掛的函式介紹([https://etherpad.org/doc/latest/#index_plugins 範例(搜尋Plugin definition)]) <br/>其中 name 為外掛名字, hook 及 client hook 中會寫出外掛使用的函式及位置。 | ||
+ | <pre>{ | ||
+ | "parts":[ | ||
+ | { | ||
+ | "name":"nameThisPartHoweverYouWant", | ||
+ | "hooks":{ | ||
+ | "authenticate":"ep_<plugin>/<file>:functionName1", | ||
+ | "expressCreateServer":ep_<plugin>/<file>:functionName2" | ||
+ | }, | ||
+ | "client_hooks":{"acePopulateDOMLine":"ep_<plugin>/<file>:functionName3"} | ||
+ | } | ||
+ | ] | ||
+ | }</pre> | ||
+ | :以 ep_previewimages 中的 ep.json 為例: | ||
+ | <pre>{ | ||
+ | "parts":[ | ||
+ | { | ||
+ | "name":"ep_previewimages", | ||
+ | "client_hooks":{ | ||
+ | "aceGetFilterStack":"ep_previewimages/static/js/index:aceGetFilterStack", | ||
+ | "aceCreateDomLine":"ep_previewimages/static/js/index:aceCreateDomLine" | ||
+ | } | ||
+ | } | ||
+ | ] | ||
+ | }</pre> | ||
+ | *最後寫出 index.js 裡面使用 javascript 語法寫出所需要的函式。 | ||
+ | ====可用函式解說:==== | ||
+ | 在解說 index.js 之前,先介紹一些其中可以用的函式: | ||
+ | #Etherpad 中,「ACE」是「Asynchronous Collaborative Editing」(非同步協同編輯)的縮寫。Etherpad 使用 ACE 來實現多人實時協同編輯功能。外掛中的 ace 前綴指的是與 Etherpad 的協同編輯引擎相關的功能或操作。 | ||
+ | #exports 物件, Node.js 的原生物件,用來定義模組的公開介面,也就是透過「require」引入模組後,可以訪問的屬性或方法。<br/>如「exports.aceGetFilterStack = function(name, context){...} 」是 Etherpad ep_previewimages 外掛的方法,載入此外掛後。就可以使用此方法來過濾出文本中匹配的行。 | ||
+ | #特定含義函式引數: | ||
+ | #*name(名稱):這個參數代表了觸發這個函數的鉤子(hook)名稱。在調用函式中,開發者一般不需要對 name 參數進行操作,但有時候這個參數可以用於區分不同的鉤子。 | ||
+ | #*args(參數):這個參數是一個物件,包含了與該鉤子相關的數據。在 aceCreateDomLine 函式的例子中, args 物件包含了與 DOM 行相關的資訊,如 CSS 類別名稱(args.cls)。開發者可以通過操作這些參數來自定義外掛的行為。 | ||
+ | #*context:物件,其屬性和方法可能會因具體的外掛鉤子(hook)而有所不同。但通常會與當前 Etherpad 外掛操作的上下文信息相關。在這個例子中,context 物件包含一個名為 「linestylefilter」的屬性,它提供了一個方法「getRegexpFilter(...)」來創建正規表示式過濾器。「linestylefilter」是 Etherpad 中一個用於處理文檔「行」樣式的組件,它可以讓外掛開發者更方便地為文檔中的文本添加樣式。 | ||
+ | #context.linestylefilter.getRegexpFilter(第一參數,第二參數),造一個正規表示式過濾器,造好後添加到過濾器堆疊中,並在處理 Etherpad 文檔時使用。 | ||
+ | #:第一個參數:一個正則表達式物件,用於指定要在文本中匹配的模式。如:「new RegExp("http.+((\.[pP][nN][gG])|(\.[jJ][pP][gG])|(\.[gG][iI][fF])|(\.[jJ][pP][eE][gG])|(\.[bB][mM][pP])|(\.[sS][vV][gG]))","g")」 | ||
+ | #:第二個參數:一個字串,用於指定「與匹配到的文本相關聯」的樣式名。如:"image"。 | ||
+ | |||
+ | ====找出圖片 URL:==== | ||
+ | <pre>// 定義名為 aceGetFilterStack 的插件函數,該函數接收兩個參數:name 和 context | ||
+ | exports.aceGetFilterStack = function (name, context) { | ||
+ | // 返回一個過濾器陣列 | ||
+ | return [ | ||
+ | // 使用 context.linestylefilter.getRegexpFilter 函數創建一個正則表達式過濾器 | ||
+ | context.linestylefilter.getRegexpFilter( | ||
+ | // 定義要匹配的正則表達式,該表達式匹配圖片 URL | ||
+ | new RegExp( | ||
+ | "http.+((\.[pP][nN][gG])|(\.[jJ][pP][gG])|(\.[gG][iI][fF])|(\.[jJ][pP][eE][gG])|(\.[bB][mM][pP])|(\.[sS][vV][gG]))", | ||
+ | "g" | ||
+ | ), | ||
+ | // 為匹配到的圖片 URL 指定一個樣式名稱,這裡使用 'image' | ||
+ | "image" | ||
+ | ), | ||
+ | ]; | ||
+ | };</pre> | ||
+ | #函式 aceGetFilterStack 傳回一個過濾器陣列,該陣列包含一個正規表示式過濾器。 | ||
+ | #這個正規表示式過濾器用於匹配圖片 URL,並為匹配到的 URL 添加一個樣式名稱(這裡是 'image')。 | ||
+ | ====產生 img 標籤:==== | ||
+ | <pre>// 定義名為 aceCreateDomLine 的外掛函式,該函式接收兩個參數:name 和 args | ||
+ | exports.aceCreateDomLine = function (name, args) { | ||
+ | // 檢查 args.cls 中是否包含 'image',即是否為圖片 URL | ||
+ | if (args.cls.indexOf("image") > -1) { | ||
+ | // 定義一個變數 src,用於存儲圖片 URL | ||
+ | var src; | ||
+ | |||
+ | // 使用正則表達式替換 args.cls 中的圖片 URL | ||
+ | cls = args.cls.replace(/(^| )image:(\S+)/g, function (x0, space, image) { | ||
+ | // 將圖片 URL 設置為 src | ||
+ | src = image; | ||
+ | // 返回一個新的 CSS class,格式為 'image image_URL' | ||
+ | return space + "image image_" + image; | ||
+ | }); | ||
+ | |||
+ | // 返回一個 DOM 行描述物件的陣列,其中包含圖片元素及其樣式 | ||
+ | // 注意:這裡的額外 span 包裹器是必需的,用於避免在圖片 URL 之後輸入文字時出現錯誤 | ||
+ | return [ | ||
+ | { | ||
+ | cls: cls, | ||
+ | extraOpenTags: | ||
+ | '<span style="display:block;"><img src="' + | ||
+ | src + | ||
+ | '" style="max-width:100%" /></span>', | ||
+ | extraCloseTags: "", | ||
+ | }, | ||
+ | ]; | ||
+ | } | ||
+ | };</pre> | ||
+ | #函式 aceCreateDomLine 首先檢查 args.cls 是否包含 'image'。 | ||
+ | #如果是圖片 URL,則將 URL 設置為變數 src。 | ||
+ | #替換 args.cls 中的圖片 URL,生成一個新的 CSS class,格式為 'image image_URL'。 | ||
+ | #返回一個 DOM 行描述物件的陣列,其中包含圖片元素及其樣式。 | ||
+ | #這裡使用一個額外的 span 元素包裹圖片,以避免在圖片 URL 之後輸入文字時出現錯誤。 | ||
+ | ==如何寫出外掛== | ||
+ | 首先要了解外掛結構,如下所示 | ||
+ | <pre>ep_<plugin>/ | ||
+ | ├ .github/ | ||
+ | ├ static/ | ||
+ | │ ├ css/ ◄─ static .css files | ||
+ | │ ├ images/ ◄─ static image files | ||
+ | │ └ js/ | ||
+ | │ └ index.js ◄─ static client-side code | ||
+ | ├ locales/ | ||
+ | │ └ en.json ◄─ English (US) strings | ||
+ | ├ LICENSE.md | ||
+ | ├ README.md | ||
+ | ├ ep.json ◄─ Etherpad plugin definition | ||
+ | └ package.json | ||
+ | </pre> | ||
+ | 重點是以下幾個檔案 | ||
+ | #package.json:此為外掛資訊,包括: | ||
+ | ##名字、版本、描述、作者、關鍵字:比較簡單,單純打字即可,可參考previewimages,previewtable或[https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin Github教學] | ||
+ | ##license:基本上使用"Apache2" | ||
+ | ##repository:'''<span style='color:red'>很重要</span>''',請登入github或其他可以產生.git檔的網站製作並給出URL | ||
+ | ##運行引擎:node | ||
+ | #ep.json:此為外掛使用之外掛機制,包括: | ||
+ | ##名字:單純打字 | ||
+ | ##使用外掛插件名字(index.js中function) | ||
+ | #README.md:讀我檔案 | ||
+ | #LICENSE.md:Apache執照 | ||
+ | #locales:不同語言翻譯檔案 | ||
+ | #static/js/index.js:正式程式,可與chatGPT合作,或是參考如何寫[https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin Github教學] | ||
+ | ===寫好上述後的安裝步驟=== | ||
+ | #基本上ep.json,index.js可以按照教學一步一步做,不過package.json建議可以使用[https://gist.github.com/lisandi/4a09acf2be3eb23722f30d49d1b5c8c5 ep_run.sh]檔案協助撰寫,比較不會有問題。 | ||
+ | #通常下一步會出問題,請先做好幾件事情 | ||
+ | ##將寫好的在本機端進行測試 | ||
+ | ##務必上傳自己的github,(其實剛剛package.json就有需要),連結後.git檔案資料夾就會出現 | ||
+ | ##若是確認無誤 可以使用npm publish上傳到網路上 | ||
+ | #寫好的外掛若是直接放到node_modules中,並不會運行,要使用 npm install安裝才有用,寫法如下 | ||
+ | #*npm install path/to/ep_plugins | ||
+ | #*若是安裝沒問題,就可以直接使用外掛 | ||
+ | |||
+ | ===自用外掛介紹=== | ||
+ | #ep_previewtable | ||
+ | #*此為第一個自己寫出的etherpad外掛,大部分是參考ep_previewimages,以下進行程式介紹 | ||
+ | ##ep.json:除名字外,寫了index.js中兩個function的名字。 | ||
+ | ##package.json:主要為外掛資訊,留的是芸伍的資訊,有問題可詢問芸伍 | ||
+ | ##index.js,大部分仿照previewimages寫法,先標記特殊字元,再來增加HTML碼 | ||
+ | ==參考網站== | ||
+ | #[https://www.youtube.com/watch?v=-pCNSqZF1dw 寫出第一個Etherpad外掛] | ||
+ | #[https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin Github教學] | ||
+ | #[https://docs.npmjs.com/creating-a-package-json-file package.json教學] | ||
+ | #[https://jsonlint.com/ 判斷json格式] |
2024年2月6日 (二) 16:18的最新修訂版本
可參考以下影片
寫出第一個Etherpad外掛步驟
- 可將 setting.json 中 "minify" 的設定由 true 改成 false ,方便 debug
- 創造 plugins 資料夾(舉例 ep_previewimages)
- 在資料夾中新增 packages.json ,裡面打此外掛的基本資訊(名字 作者 版本 描述 貢獻者 運行引擎),無涉外掛運用(範例(搜尋Package definition))
其中 name 為外掛的名字, version 為外掛版本, description 為外掛介紹, author 為外掛作者, contributors 為貢獻者名單, dependencies 為寫程式所依賴的工具包, engines 為運行引擎。
{ "name": "ep_PLUGINNAME", "version": "0.0.1", "description": "DESCRIPTION", "author": "USERNAME (REAL NAME) <MAIL@EXAMPLE.COM>", "contributors": [], "dependencies": {"MODULE": "0.3.20"}, "engines": {"node": ">=12.13.0"} }
- 以 ep_previewimages 中的 packages.json 為例:
{ "name":"ep_previewimages", "description":"Image previewer, paste the URL of an image or upload an image using ep_fileupload", "version":"0.0.13", "author":"johnyma22 (John McLear) <john@mclear.co.uk>", "contributors":[], "dependencies":{}, "repository":{"type":"git","url":"https://github.com/JohnMcLear/ep_previewimages.git"}, "engines":{"node":"*"} }
- 在資料夾中新增 ep.json ,裡面打外掛的函式介紹(範例(搜尋Plugin definition))
其中 name 為外掛名字, hook 及 client hook 中會寫出外掛使用的函式及位置。
{ "parts":[ { "name":"nameThisPartHoweverYouWant", "hooks":{ "authenticate":"ep_<plugin>/<file>:functionName1", "expressCreateServer":ep_<plugin>/<file>:functionName2" }, "client_hooks":{"acePopulateDOMLine":"ep_<plugin>/<file>:functionName3"} } ] }
- 以 ep_previewimages 中的 ep.json 為例:
{ "parts":[ { "name":"ep_previewimages", "client_hooks":{ "aceGetFilterStack":"ep_previewimages/static/js/index:aceGetFilterStack", "aceCreateDomLine":"ep_previewimages/static/js/index:aceCreateDomLine" } } ] }
- 最後寫出 index.js 裡面使用 javascript 語法寫出所需要的函式。
可用函式解說:
在解說 index.js 之前,先介紹一些其中可以用的函式:
- Etherpad 中,「ACE」是「Asynchronous Collaborative Editing」(非同步協同編輯)的縮寫。Etherpad 使用 ACE 來實現多人實時協同編輯功能。外掛中的 ace 前綴指的是與 Etherpad 的協同編輯引擎相關的功能或操作。
- exports 物件, Node.js 的原生物件,用來定義模組的公開介面,也就是透過「require」引入模組後,可以訪問的屬性或方法。
如「exports.aceGetFilterStack = function(name, context){...} 」是 Etherpad ep_previewimages 外掛的方法,載入此外掛後。就可以使用此方法來過濾出文本中匹配的行。 - 特定含義函式引數:
- name(名稱):這個參數代表了觸發這個函數的鉤子(hook)名稱。在調用函式中,開發者一般不需要對 name 參數進行操作,但有時候這個參數可以用於區分不同的鉤子。
- args(參數):這個參數是一個物件,包含了與該鉤子相關的數據。在 aceCreateDomLine 函式的例子中, args 物件包含了與 DOM 行相關的資訊,如 CSS 類別名稱(args.cls)。開發者可以通過操作這些參數來自定義外掛的行為。
- context:物件,其屬性和方法可能會因具體的外掛鉤子(hook)而有所不同。但通常會與當前 Etherpad 外掛操作的上下文信息相關。在這個例子中,context 物件包含一個名為 「linestylefilter」的屬性,它提供了一個方法「getRegexpFilter(...)」來創建正規表示式過濾器。「linestylefilter」是 Etherpad 中一個用於處理文檔「行」樣式的組件,它可以讓外掛開發者更方便地為文檔中的文本添加樣式。
- context.linestylefilter.getRegexpFilter(第一參數,第二參數),造一個正規表示式過濾器,造好後添加到過濾器堆疊中,並在處理 Etherpad 文檔時使用。
- 第一個參數:一個正則表達式物件,用於指定要在文本中匹配的模式。如:「new RegExp("http.+((\.[pP][nN][gG])|(\.[jJ][pP][gG])|(\.[gG][iI][fF])|(\.[jJ][pP][eE][gG])|(\.[bB][mM][pP])|(\.[sS][vV][gG]))","g")」
- 第二個參數:一個字串,用於指定「與匹配到的文本相關聯」的樣式名。如:"image"。
找出圖片 URL:
// 定義名為 aceGetFilterStack 的插件函數,該函數接收兩個參數:name 和 context exports.aceGetFilterStack = function (name, context) { // 返回一個過濾器陣列 return [ // 使用 context.linestylefilter.getRegexpFilter 函數創建一個正則表達式過濾器 context.linestylefilter.getRegexpFilter( // 定義要匹配的正則表達式,該表達式匹配圖片 URL new RegExp( "http.+((\.[pP][nN][gG])|(\.[jJ][pP][gG])|(\.[gG][iI][fF])|(\.[jJ][pP][eE][gG])|(\.[bB][mM][pP])|(\.[sS][vV][gG]))", "g" ), // 為匹配到的圖片 URL 指定一個樣式名稱,這裡使用 'image' "image" ), ]; };
- 函式 aceGetFilterStack 傳回一個過濾器陣列,該陣列包含一個正規表示式過濾器。
- 這個正規表示式過濾器用於匹配圖片 URL,並為匹配到的 URL 添加一個樣式名稱(這裡是 'image')。
產生 img 標籤:
// 定義名為 aceCreateDomLine 的外掛函式,該函式接收兩個參數:name 和 args exports.aceCreateDomLine = function (name, args) { // 檢查 args.cls 中是否包含 'image',即是否為圖片 URL if (args.cls.indexOf("image") > -1) { // 定義一個變數 src,用於存儲圖片 URL var src; // 使用正則表達式替換 args.cls 中的圖片 URL cls = args.cls.replace(/(^| )image:(\S+)/g, function (x0, space, image) { // 將圖片 URL 設置為 src src = image; // 返回一個新的 CSS class,格式為 'image image_URL' return space + "image image_" + image; }); // 返回一個 DOM 行描述物件的陣列,其中包含圖片元素及其樣式 // 注意:這裡的額外 span 包裹器是必需的,用於避免在圖片 URL 之後輸入文字時出現錯誤 return [ { cls: cls, extraOpenTags: '<span style="display:block;"><img src="' + src + '" style="max-width:100%" /></span>', extraCloseTags: "", }, ]; } };
- 函式 aceCreateDomLine 首先檢查 args.cls 是否包含 'image'。
- 如果是圖片 URL,則將 URL 設置為變數 src。
- 替換 args.cls 中的圖片 URL,生成一個新的 CSS class,格式為 'image image_URL'。
- 返回一個 DOM 行描述物件的陣列,其中包含圖片元素及其樣式。
- 這裡使用一個額外的 span 元素包裹圖片,以避免在圖片 URL 之後輸入文字時出現錯誤。
如何寫出外掛
首先要了解外掛結構,如下所示
ep_<plugin>/ ├ .github/ ├ static/ │ ├ css/ ◄─ static .css files │ ├ images/ ◄─ static image files │ └ js/ │ └ index.js ◄─ static client-side code ├ locales/ │ └ en.json ◄─ English (US) strings ├ LICENSE.md ├ README.md ├ ep.json ◄─ Etherpad plugin definition └ package.json
重點是以下幾個檔案
- package.json:此為外掛資訊,包括:
- 名字、版本、描述、作者、關鍵字:比較簡單,單純打字即可,可參考previewimages,previewtable或Github教學
- license:基本上使用"Apache2"
- repository:很重要,請登入github或其他可以產生.git檔的網站製作並給出URL
- 運行引擎:node
- ep.json:此為外掛使用之外掛機制,包括:
- 名字:單純打字
- 使用外掛插件名字(index.js中function)
- README.md:讀我檔案
- LICENSE.md:Apache執照
- locales:不同語言翻譯檔案
- static/js/index.js:正式程式,可與chatGPT合作,或是參考如何寫Github教學
寫好上述後的安裝步驟
- 基本上ep.json,index.js可以按照教學一步一步做,不過package.json建議可以使用ep_run.sh檔案協助撰寫,比較不會有問題。
- 通常下一步會出問題,請先做好幾件事情
- 將寫好的在本機端進行測試
- 務必上傳自己的github,(其實剛剛package.json就有需要),連結後.git檔案資料夾就會出現
- 若是確認無誤 可以使用npm publish上傳到網路上
- 寫好的外掛若是直接放到node_modules中,並不會運行,要使用 npm install安裝才有用,寫法如下
- npm install path/to/ep_plugins
- 若是安裝沒問題,就可以直接使用外掛
自用外掛介紹
- ep_previewtable
- 此為第一個自己寫出的etherpad外掛,大部分是參考ep_previewimages,以下進行程式介紹
- ep.json:除名字外,寫了index.js中兩個function的名字。
- package.json:主要為外掛資訊,留的是芸伍的資訊,有問題可詢問芸伍
- index.js,大部分仿照previewimages寫法,先標記特殊字元,再來增加HTML碼