読み込みが終了しない場合は、しばらく待つか、リロードを行なってください。
If loading does not finish, wait for a while or reload.
エンジニア向けの情報を発信するブログです。
どなたでも発信できます。
お好きに利用していただれば幸いです。
20240517追記
quill.jsのversion2.0がリリースされてたでおいぃぃぃぃ!!
https://quilljs.com/
変更履歴
20230320
reactのsizeのselectの箇所にwarningが発生していたので修正しました
20230827
reactでQuillのimportが抜けていたので追加しました
20230827追記
githubに公開しました。デモはこちら
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>quillテスト</title>
<!-- 👇 Quill.jsと必要なcssファイルをcdnでインポート -->
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
</head>
<body>
<style>
/* 👇 見やすいように中央寄せに整える */
#app-container {
margin: 0 auto;
width: 50%;
margin-top: 20vh;
}
</style>
<div id="app-container">
html
<!-- 👇 quillを適用する要素の上にこんな感じで要素を組むとツールバーになる -->
<!-- 詳細は https://quilljs.com/docs/modules/toolbar/ -->
<div id="toolbar">
<span class="ql-formats">
<select class="ql-size">
<option value="small"></option>
<option selected></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span class="ql-formats">
<button class="ql-code-block"></button>
</span>
</div>
<!-- 👇 quillを適用する要素 -->
<div id="app"></div>
</div>
<script>
// 👇 quillを作成する 👇 quillの対象になる要素のid
const quill = new Quill('#app', {
// 👇 snow -> 入力モード bubble -> 参照(?)モード
theme: 'snow',
modules: {
toolbar: {
// 👇 quillのツールバーはこいつですよid
container: '#toolbar',
}
},
// 👇 quillで適用する装飾のホワイトリスト(よくわからない方はありなしでツールバーのボタンをぽちぽちするのだ!)
formats: [
'size', 'code-block',
]
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>quillテスト</title>
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
<!-- 👇 font-awesomeインポート -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
</head>
<body>
<style>
#app-container {
margin: 0 auto;
width: 50%;
margin-top: 20vh;
}
</style>
<div id="app-container">
html
<div id="toolbar">
<span class="ql-formats">
<select class="ql-size">
<option value="small"></option>
<option selected></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span class="ql-formats">
<button class="ql-code-block"></button>
</span>
<!-- 👇 button追加 -->
<span class="ql-formats">
<!-- 👇 class名の命名規則はすぐ下の"クリック時の挙動を定義する"のcode-block内のコメントアウトを読むのだ! -->
<button class="ql-addDivBlot">
<!-- 👇 font-awesomeじゃなくても良い(気になる方は調べてみるのだ!) -->
<i class="fa-sharp fa-solid fa-square-check"></i>
</button>
</span>
</div>
<div id="app"></div>
</div>
<script>
const quill = new Quill('#app', {
theme: 'snow',
modules: {
toolbar: {
container: '#toolbar',
}
},
formats: [
'size', 'code-block',
]
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>quillテスト</title>
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
</head>
<body>
<style>
#app-container {
margin: 0 auto;
width: 50%;
margin-top: 20vh;
}
</style>
<div id="app-container">
html
<div id="toolbar">
<span class="ql-formats">
<select class="ql-size">
<option value="small"></option>
<option selected></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span class="ql-formats">
<button class="ql-code-block"></button>
</span>
<span class="ql-formats">
<button class="ql-addDivBlot">
<i class="fa-sharp fa-solid fa-square-check"></i>
</button>
</span>
</div>
<div id="app"></div>
</div>
<script>
const quill = new Quill('#app', {
theme: 'snow',
modules: {
toolbar: {
container: '#toolbar',
// 👇 handlersにql-"クラス名"に対応するfunction名を登録する
handlers: {
'addDivBlot': funcAddDivBlot,
}
}
},
formats: [
'size', 'code-block',
]
});
// 👇 handlersに登録したfunctionを定義する
function funcAddDivBlot () {
// 👇 一旦デバッグ用でこんな感じにしておく
console.log('hello beginner engineer!');
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>quillテスト</title>
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
</head>
<body>
<style>
#app-container {
margin: 0 auto;
width: 50%;
margin-top: 20vh;
}
</style>
<div id="app-container">
html
<div id="toolbar">
<span class="ql-formats">
<select class="ql-size">
<option value="small"></option>
<option selected></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span class="ql-formats">
<button class="ql-code-block"></button>
</span>
<span class="ql-formats">
<button class="ql-addDivBlot">
<i class="fa-sharp fa-solid fa-square-check"></i>
</button>
</span>
</div>
<div id="app"></div>
</div>
<script>
// 👇 BlockEmbedなるものをQuillから取得(これ以外にもimportできますが、どこを参照してimportして良いのか未だによくわかってないのでネットサーフィンを駆使して探し出すのだ!)
const BlockEmbed = Quill.import('blots/block/embed');
// 👇 insertしたい要素のclassを取得した親を継承して定義
class DivBlot extends BlockEmbed {
// 👇 おまじない
static create (value) {
console.log(value);
// 👇 おまじないでnodeを取得
let node = super.create();
// 👇 nodeを返す(insertされる要素になります)
return node;
}
}
// 👇 このblot(?)の名前は"div_blot"です(formatに登録する名前)
DivBlot.blotName = 'div_blot';
// 👇 このblot(?)のタグは"div"です("div" -> <div></div> "divdiv" -> <divdiv></divdiv>)
DivBlot.tagName = 'div';
// 👇 このblot(?)のclass名は"engineer_blog"です
DivBlot.className = 'engineer_blog';
// 👇 Quillにこのblotを登録します(もうよくわからん! > ヾ(*・∀・)/)
Quill.register(DivBlot);
const quill = new Quill('#app', {
theme: 'snow',
modules: {
toolbar: {
container: '#toolbar',
handlers: {
'addDivBlot': funcAddDivBlot,
}
}
},
formats: [
// 👇 insertしたい要素名を登録
'size', 'code-block', 'div_blot',
]
});
function funcAddDivBlot () {
// 👇 selectionなるものをquillから取得 👇 おまじない
const selection = quill.getSelection(true);
// 👇 キャレットが当たっている位置を取得
let cursor_index = selection.index;
// 👇 embedを挿入します 👇 キャレットの位置に👇 div_blotの要素(format)を 👇 {}の引数を与えます
quill.insertEmbed(cursor_index, 'div_blot', {text: "BeginnerEngineerBlog\nよろしくお願いします。"});
// 👇 キャレットの位置を挿入した要素の一つ後ろに移動します
quill.setSelection(cursor_index + 1);
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>quillテスト</title>
<script src="https://cdn.quilljs.com/1.3.7/quill.js"></script>
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css">
</head>
<body>
<style>
#app-container {
margin: 0 auto;
width: 50%;
margin-top: 20vh;
}
</style>
<div id="app-container">
html
<div id="toolbar">
<span class="ql-formats">
<select class="ql-size">
<option value="small"></option>
<option selected></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span class="ql-formats">
<button class="ql-code-block"></button>
</span>
<span class="ql-formats">
<button class="ql-addDivBlot">
<i class="fa-sharp fa-solid fa-square-check"></i>
</button>
</span>
</div>
<div id="app"></div>
</div>
<script>
const BlockEmbed = Quill.import('blots/block/embed');
class DivBlot extends BlockEmbed {
static create (value) {
let node = super.create();
// 👇 好きなようにカスタマイズ
node.style.display = 'flex';
let img = document.createElement('img');
img.src = 'https://begien.com/image/beginner_engineer_blog.png';
img.alt = 'begien.com';
img.style.width = '50%';
img.style.height = 'auto';
node.appendChild(img);
let span = document.createElement('span');
span.style.display = 'flex';
span.style.alignItems = 'center';
span.innerText = value.text;
node.appendChild(span);
return node;
}
}
DivBlot.blotName = 'div_blot';
DivBlot.tagName = 'div';
DivBlot.className = 'engineer_blog';
Quill.register(DivBlot);
const quill = new Quill('#app', {
theme: 'snow',
modules: {
toolbar: {
container: '#toolbar',
handlers: {
'addDivBlot': funcAddDivBlot,
}
}
},
formats: [
'size', 'code-block', 'div_blot',
]
});
function funcAddDivBlot () {
const selection = quill.getSelection(true);
let cursor_index = selection.index;
quill.insertEmbed(cursor_index, 'div_blot', {text: "BeginnerEngineerBlog\nよろしくお願いします。"});
quill.setSelection(cursor_index + 1);
}
</script>
</body>
</html>
import './App.css';
import {useState} from 'react';
// 👇 react-quillを使うためのモジュールをimport
import ReactQuill, {Quill} from 'react-quill';
import 'react-quill/dist/quill.snow.css';
// 👇 fontawesomeの導入はこちらがわかりやすいのだ! https://qiita.com/stin_dev/items/5755e14805e60718620c
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faSquareCheck } from '@fortawesome/free-regular-svg-icons';
const formats = [
'code-block',
'size',
'div_blot',
];
function CustomIcon () {
return (
<FontAwesomeIcon icon={faSquareCheck} />
);
}
const modules = {
toolbar: {
container: "#toolbar",
handlers: {
"addDivBlot": funcAddDivBlot,
}
},
};
const BlockEmbed = Quill.import('blots/block/embed');
class DivBlot extends BlockEmbed {
static create (value) {
let node = super.create();
node.style.display = 'flex';
let img = document.createElement('img');
img.src = 'https://begien.com/image/BeginnerEngineerBlogTopImage.png';
img.alt = 'begien.com';
img.style.width = '50%';
img.style.height = 'auto';
node.appendChild(img);
let span = document.createElement('span');
span.style.display = 'flex';
span.style.alignItems = 'center';
span.innerText = value.text;
node.appendChild(span);
return node;
}
}
DivBlot.blotName = 'div_blot';
DivBlot.tagName = 'div';
DivBlot.className = 'beginner_engineer';
Quill.register(DivBlot, true);
function funcAddDivBlot () {
const quill = this.quill;
const selection = quill.getSelection(true);
let cursor_index = selection.index;
quill.insertEmbed(cursor_index, 'div_blot', {text: "BeginnerEngineerBlog\nよろしくお願いします。"});
quill.setSelection(cursor_index + 1);
}
function App() {
let app_style = {
margin: '0 auto',
width: '50%',
marginTop: '20vh',
};
const [value, setValue] = useState('');
return (
<div className="App" style={app_style}>
<div style={{textAlign: 'left'}}>react</div>
<QuillToolbar
/>
<ReactQuill
theme="snow"
value={value}
onChange={setValue}
modules={modules}
formats={formats}
/>
</div>
);
}
function QuillToolbar (props) {
return (
<div id="toolbar" style={{display: 'flex'}}>
<span className="ql-formats">
<select className="ql-size" defaultValue="normal">
<option value="small"></option>
<option value="normal"></option>
<option value="large"></option>
<option value="huge"></option>
</select>
</span>
<span className="ql-formats">
<button className="ql-code-block"></button>
</span>
<span className="ql-formats">
<button className="ql-addDivBlot">
<CustomIcon />
</button>
</span>
</div>
);
}
export default App;
20240517追記
冒頭に述べましたがversion2.0がリリースされました!🎉
今の所このサイトではversion2.0にアップデートしようと思ったのですがcode-blockが表示されずアップデートは諦めています(´・ω・`)
これからquill.jsを利用しようかと思っている方は2.0の利用をおすすめします!