@iqs/react-summernote
v2.3.13
Published
Summernote (Super simple WYSIWYG editor) adaptation for react http://summernote.org
Downloads
45
Readme
React SummerNote
React SummerNote 是一個 React 版本的 WYSIWYG 的 rich text editor,基於 SummerNote 建構
Stable Version:
v2.3.13
版本修改紀錄:Changelog
Online Demo
上面連結是一個 React SummerNote 的基本展示
Package Dependencies
React SummerNote 依賴以下套件
必要套件
react
: ^16.8.6react-dom
: ^16.8.6prop-types
: ^15.7.2
第三方套件
bootstrap
: ^4.6.2popper.js
: ^1.16.1summernote
: ^0.8.18jquery
: ^3.6.1store
: ^2.0.12
Install
必要依賴安裝
npm i bootstrap popper.js summernote jquery store --save
安裝 React SummerNote
npm i @iqs/react-summernote --save
設定 Webpack
使 jQuery, store 可以在 Component 中被存取,而不需額外 import
{
...,
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
store: "store",
})
]
}
Super simple to use
import React from 'react'
import { render } from 'react-dom'
import SummerNote from 'react-summernote'
import 'react-summernote/dist/main.css'
// 自動載入必要套件
SummerNote.ImportCode()
render(
<SummerNote value="Default value"
options={{
lang: 'en',
height: 350,
dialogsInBody: true,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['fontname', ['fontname']],
['para', ['ul', 'ol', 'paragraph']],
// plugin
["table", ["jTable", "jMerge", "jBackcolor", "jBorderColor", "jAlign", "jTableInfo", "jWidthHeightReset"]],
['insert', ['link', 'picture', 'video']],
['view', ['fullscreen', 'codeview']],
//["anchor",["anchor", "toc", "markAnchor", "editAnchor"]]
]
}}
onChange={e => console.log(e)}
/>
, document.getElementById('root')
)
options.toolbar
- Insert
picture
: open image dialoglink
: open link dialogvideo
: open video dialogtable
: insert a tablehr
: insert a horizontal rule
- Font Style
fontname
: set font familyfontsize
: set font sizecolor
: set foreground and background colorforecolor
: set foreground colorbackcolor
: set background colorbold
: toggle font weightitalic
: toggle italicunderline
: toggle underlinestrikethrough
: toggle strikethroughsuperscript
: toggle superscriptsubscript
: toggle subscriptclear
: clear font style
- Paragraph style
style
: format selected blockol
: toggle ordered listul
: toggle unordered listparagraph
: dropdown for paragraph alignheight
: set line height
- Misc
fullscreen
: toggle fullscreen editing modecodeview
: toggle wysiwyg and html editing modeundo
: undoredo
: redohelp
: open help dialog
- Table (Plugin)
jTable
: 表格欄位長寬縮放jMerge
: 框選後合併 celljBackcolor
: cell 的背景色jBorderColor
: 整個表格 border 顏色jAlign
: cell 的對齊方式jTableInfo
: 調整整個 table 的 marginjWidthHeightReset
: 重設 cell 寬高
options
設置 options
props,即可設置客製化功能與 UI 顯示
summernote deep-dive
更詳細的設定方式,可以參閱上面的官方說明
Control Editor
下面簡單示範如何使用新版 API 控制編輯器 (version > v2.0.0
)
import React, { Component } from 'react'
import SummerNote from './SummerNote'
class App extends Component {
constructor(props) {
super(props)
this.editor = React.createRef()
}
componentDidMount(){
const editor = this.editor.current
editor.focus() // 焦點設置在 editor 上
editor.isEmpty() // 編輯器內容是否為空
editor.reset() // 清除編輯器所有內容
editor.disable() // 使編輯器禁止輸入
editor.enable() // 使編輯器可以輸入
editor.insertImage() // 插入圖片 (詳情可參考下一個段落)
editor.insertNode(/* html node */) // 插入 HTML 節點
editor.insertText('') // 插入純文字
}
render() {
return (<SummerNote ref={this.editor}/>)
}
}
Upload Image
自訂上傳圖片的方法,複製圖片(剪貼簿中)貼上編輯器時,就會觸發該方法
import React, { Component } from 'react'
import SummerNote from './SummerNote'
class App extends Component {
constructor(props) {
super(props)
this.editor = React.createRef();
}
onImageUpload = file => {
let image = file[0]
this.editor.current.insertImage('https://i.imgur.com/JOOEENx.png', ($image) => {
$image.css("width", Math.floor($image.width() / 2));
$image.attr("title", image.name);
})
}
render() {
return (<SummerNote onImageUpload={this.onImageUpload} ref={this.editor}/>)
}
}
Paste from Office Word
貼上 Word 內容時,SummerNote 會解析剪貼簿中的 rtf 內容,解析後會自動將 <img>
部分轉換成 base64 格式的圖片資源,這些 <img>
都會被加上 class .zap-img-uploading
,可以在使用 jQuery 進行後續處理
import React, { Component } from 'react'
import SummerNote from './SummerNote'
function onImagePasteFromWord($imgs) {
// $imgs collect imgs from this pasting action
$imgs.removeClass('zap-img-uploading')
}
class App extends Component {
render() {
return (<SummerNote onImagePasteFromWord={onChange} />)
}
}
Paste from Office Excel
貼上 Excel 內容時,SummerNote 會解析剪貼簿中的 HTML 內容,解析後會自動將樣式附加進去,但目前不支援包含 Excel 中的圖片,需額外逐一手動複製貼上
自行 import 必要依賴
如果專案也有使用 Bootstrap 等套件,不希望重複引用,可以自行引入必要依賴
// 自動載入必要套件
//SummerNote.ImportCode()
// 以下為必要依賴,可以自行在您的專案中引入 (須注意順序)
require('bootstrap/dist/css/bootstrap.min.css')
require('bootstrap/js/dist/modal')
require('bootstrap/js/dist/dropdown')
require('bootstrap/js/dist/tooltip')
require('bootstrap/js/dist/tab')
require('summernote/dist/summernote-bs4.css')
require('summernote/dist/summernote-bs4.min.js')
require('react-summernote/plugin/custom/summernote-patch-dom')
require('react-summernote/plugin/custom/summernote-patch-handle')
summernote-patch-dom
: 用於修復字體、字型等樣式無法正常套用到框選範圍內的所有節點。因官方尚未發布涵蓋 Summernote PR#4472 的版本,故在此使用 plugin 覆寫dom.walkPoint
,dom.nextPointWithEmptyNode
目前 Summernote 版本
0.8.18
,待官方發佈新版本後可移除此 plugin
summernote-patch-handle
: 用於修復圖片顯示框位置偏移。因官方尚未發布涵蓋 Summernote PR#4283 的版本,故在此使用 plugin 覆寫modules.handle.update
目前 Summernote 版本
0.8.18
,待官方發佈新版本後可移除此 plugin
Plugin
從 2.0.4
的版本開始,引入了 table plugin,可針對 table 元素進行更多操作
require('react-summernote/plugin/summernote-ext-table')
require('react-summernote/plugin/summernote-ext-table.css')
其他 Plugin
若要自行引入 plugin 可參考 Plugin 介紹
如果 Plugin 無法載入
請嘗試引用 src/plugin
裡面的 plugin
以 table plugin 為例
require('@iqs/react-summernote/src/plugin/misc/summernote-ext-table')
require('@iqs/react-summernote/src/plugin/misc/summernote-ext-table.css')
XSS 白名單
summernote 包含一個原始碼的 xss 過濾機制,規則如下:
/<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi
在 options
中修改內建白名單,即可客製化保留部分 tag 不被過濾
<SummerNote value="Default value"
options={{
height: 350,
toolbar: [
['view', ['fullscreen', 'codeview']],
],
// 白名單
codeviewFilterRegex: /<\/*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|ilayer|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|t(?:itle|extarea)|xml)[^>]*?>/gi,
// 白名單
codeviewFilter: true, // 是否開啟白名單過濾
codeviewIframeFilter: false // 是否開啟 iframe src 網址過濾
}}
/>
, document.getElementById('root')
更多詳細設定可以參閱官方文件
嵌入影片
以下是依據 Summernote 0.8.18 videoDialog 整理出已知的有效網址
YouTube
- YouTube 網域 + 路徑 + id
https://youtube.com/embed/Dm_BrGu1sHM
- YouTube 網域 + 路徑 + id + 時戳
https://www.youtube.com/watch?v=Dm_BrGu1sHM&t=300
https://m.youtube.com/v/Dm_BrGu1sHM?t=300
- 網址附帶的其他參數需放在時戳之後
https://m.youtube.com/v/Dm_BrGu1sHM?t=300&si=YsiSA_iLcKJMtDVq
| 網域 | 路徑 | id | 時戳 |
| ---------------------------------------------------------- | ------------------------------------------------------------ | ---------- | ------------------------------------------------------ |
| youtube.com/
www.youtube.com/
m.youtube.com/
| embed/
v/
watch?v=
watch?
(任意字元)&v=
| (11個字元) | ?t=
(任意字元) &t=
(任意字元) t=
(任意字元) |
- Instagram 網域 + 路徑 + id
https://www.instagram.com/p/Cy8sEXrv9xu
- 網址附帶的其他參數需放在 id 之後
https://www.instagram.com/p/Cy8sEXrv9xu?igshid=MzRlODBiNWFlZA==
| 網域 | 路徑 | id |
| ---------------------------------------- | ---- | ---------- |
| www.instagram.com/
instagram.com/
| p/
| (任意字元) |
優酷
- 優酷網域 + 路徑 +
id_
+ id +.html
https://v.youku.com/v_show/id_XNTA3MzUyMTUyMA==.html
- 網址附帶的其他參數需放在
.html
之後https://v.youku.com/v_show/id_XNTA3MzUyMTUyMA==.html?spm=a2hja.14919748_WEBHOME_NEW.drawer15.d_zj1_4&s=efbfbd4a46efbfbd5975&scm=20140719.manual.19594.show_efbfbd4a46efbfbd5975
| 網域 | 路徑 | 前綴 | id | 後綴 |
| -------------- | --------- | ----- | ------------------------------- | ------- |
| v.youku.com/
| v_show/
| id_
| (至少一個任意字元)(零或數個=
) | .html
|
DailyMotion
- DailyMotion網域 + 路徑 + id
https://www.dailymotion.com/video/x8pi9hp
| 網域 | 路徑 | id | 參數 |
| ---------------------- | -------------------- | -------------------------------------- | ------------------------------------------------------ |
| www.dailymotion.com/
| video/
hub/
| (至少一個非_
的字元)(多個非#
的字元) | (零組或一組 (#video=
)(至少一個非 _
或 &
的字元)) |
For contributor
Setup Node
node
: v16.20.2npm
: v8.19.4
以 nvm 安裝
nvm install v16.20.2
nvm use v16.20.2
Install Dependencies
安裝依賴套件
npm ci
依據package-lock.json
安裝套件
npm ci
NPM Scripts
npm 有準備以下指令,分別說明如下,如果您也想貢獻程式碼,可以參考使用:
npm run build
:用於打包整個套件,輸出到dist
目錄下的一個main.js
檔案,用於發布新的套件版本npm run web
:以src/start.js
為起始,打包出一個 demo 網站,輸出到docs
,並且使用 production 產品模式執行,用於發布成 Repo 的 Page 網站npm run dev
:以src/start.js
為起始,打包出一個 demo 網站,輸出到docs
,並且使用 dev 開發模式執行,用於發布成 Repo 的 Page 網站npm run test
:啟動一個webpack-dev-server
,以src/test.js
為起始,用於測試直接引用打包 (build) 後的 summernote ,觀察引用打包後的程式執行起來是否有問題npm start
:開發人員主要模式,啟動一個webpack-dev-server
,以src/start.js
為起始,用於測試原始程式執行起來是否有問題,並開發新功能
Commit Message
可使用 vscode extension Commit Message Editor 編輯 Commit Message
- 依據 Conventional Commits (中文版)
- Type 必填,選對修改事項類型,不清楚選哪種可依據 Angular CONTRIBUTING - Commit Message Format
- Title 必填,概述修改事項 (Short description)
- Scope 可選,目前未定義
- Body 可選,可描寫變更的內容
- Footer 可選,可寫 commit 簽署者資訊
Code Structure
Summernote.jsx
Summernote 連結器,與原生 Summernote 對接
App.jsx
引入使用 Summernote Component,DEMO 呈現依賴此檔案設定
ImportCode.js
ImportCode 會引入所有 Plugin,若有新增 Plugin 需要在此引入
module.exports = function () {
// ...
require('../plugin/custom/summernote-custom-style')
}
SummernotePlugin
@iqs/react-summernote: v2.2.20
開始
src/components/SummernotePlugin.jsx: 可在使用 React-Summernote 時匯入自定義的 Button 或 Plugin
src/components/SummernotePlugin.d.ts: 設定 Summernote Types
import SummerNote, { SummernotePlugin } from '@iqs/react-summernote'
Methods
SummernotePlugin.createSummernoteButton
SummernotePlugin.createSummernotePlugin
Types
- global
$.summernote
SummernotePlugin.createSummernotePlugin
SummernotePlugin.SummernotePluginClass
SummernotePlugin.SummernotePluginFunction
SummernotePlugin.createSummernoteButton
SummernotePlugin.SummernoteContext
- ...
Plugin
Plugin 目錄架構由 Awesome Summernote 訂定,IQS 自己寫的都放在 src/plugin/custom/
檔案名稱以 summernote-
開頭,Plugin 名稱、按鈕名稱以 小駝峰 命名
有新增 Plugin 記得更新文件 src/plugin/README.md
For maintainer
上版 DEMO 網站流程
iq-service-inc.github.io/react-summernote
push 到 master 分支
觸發 Github Workflow Deploy Master Branch to Github Pages
待 Workflow 完成即上版完成
發佈 npm 套件流程
修改 README.md 版本號
修改 package.json 版本號
更新 CHANGELOG.md
push 到 master 分支
- 選擇新 Tag
- 標題為 Tag
- 內容貼 CHANGELOG
- 內容最後附上差異比對連結
- e.g.
**Full Changelog**: https://github.com/iq-service-inc/react-summernote/compare/v2.2.19...v2.2.20
觸發 Github Workflow Publish Package to npmjs
待 Workflow 完成即發佈完成
For repo admins
.github/workflows/ 存放所有 Github Workflows
Deploy Master Branch to Github Pages: 自動部署 Pages
Publish Package to npmjs: 發佈 npm 套件
若發布流程失敗,出現
404 Not Found - PUT https://registry.npmjs.org/@iqs%2freact-summernote - Not found
等訊息,可能是 Token 無效或過期
License
The MIT License (MIT)
Copyright (c) 2023 Zap