├── .babelrc
├── .gitignore
├── .npmignore
├── CONTRIBUTING.md
├── README.md
├── bower.json
├── demo
├── .gitkeep
├── index.html
└── screenshot.png
├── dist
├── index.html
├── quill-inline-comment.css
└── quill-inline-comment.js
├── package-lock.json
├── package.json
├── src
├── module-inline-comment.js
├── quill-inline-comment.js
└── scss
│ ├── base.scss
│ └── core
│ ├── _styles.scss
│ └── _variables.scss
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | { "presets": ["es2015"] }
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 |
4 | .DS_Store
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Building
4 |
5 | To build __quill-inline-comment__, run the following command:
6 |
7 | ```npm run build```
8 |
9 | ## Testing
10 |
11 | Still need to add testing
12 |
13 | ## Releases
14 |
15 | Still need to come up with release schemes
16 |
17 | ## Maintainers
18 |
19 | __@yeminhtut__
20 | __@himynameistimli__
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quill Inline Comment
2 | Module extension for [Quill.js](https://github.com/quilljs/quill) that handles inline comment like medium.
3 |
4 | #### This module is still in active development
5 |
6 | ## Usage
7 | ### Webpack/ES6
8 |
9 | ```javascript
10 | const toolbarOptions = {
11 | container: [
12 | ['bold', 'italic', 'underline', 'strike'],
13 | ['comment'],
14 | ],
15 | handlers: {'comment': function() {}}
16 | }
17 | const quill = new Quill(editor, {
18 | // ...
19 | modules: {
20 | // ...
21 | toolbar: toolbarOptions,
22 | inline_comment: true
23 | }
24 | });
25 | ```
26 |
27 | ## Contributing
28 |
29 | Please check out our [contributing guidelines](CONTRIBUTING.md).
30 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "quill-inline-comment",
3 | "version": "0.0.1",
4 | "description": "Quill Extension for Inline Comment Like Medium",
5 | "main": "webpack.config.js",
6 | "authors": [
7 | "contentco"
8 | ],
9 | "license": "MIT",
10 | "keywords": [
11 | "content",
12 | "emoji",
13 | "quill",
14 | "editor"
15 | ],
16 | "homepage": "https://github.com/contentco/quill-inline-comment",
17 | "ignore": [
18 | "**/.*",
19 | "node_modules",
20 | "bower_components",
21 | "test",
22 | "tests"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/demo/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/contentco/quill-inline-comment/b2247a66ff3490e5c0b4e24aa76436c6de36ac44/demo/.gitkeep
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
31 |
32 |
33 |
37 |
38 |
39 |
Debug
40 |
41 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/demo/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/contentco/quill-inline-comment/b2247a66ff3490e5c0b4e24aa76436c6de36ac44/demo/screenshot.png
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
31 |
32 |
33 |
37 |
38 |
39 |
Debug
40 |
41 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/dist/quill-inline-comment.css:
--------------------------------------------------------------------------------
1 | body{background:#fff}#quill-editor{position:relative}.inline-comment{background-color:#fff;border:1px solid #ccc;box-shadow:0 0 5px #ddd;color:#444;padding:5px 12px;white-space:nowrap}.commentText{border:none;display:block;resize:none}.commentText:focus{outline:none}.inline-comment-bottom{margin-top:15px;text-align:right}.annotation{background:#a5caf2}
--------------------------------------------------------------------------------
/dist/quill-inline-comment.js:
--------------------------------------------------------------------------------
1 | !function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=2)}([function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e){var t=document.getElementById("inline-comment"),n=document.getElementById("inline-comment-mask");t?(t.remove(),n.remove()):c(e)}function c(e){var t=e.getSelection();if(!(e.getText(t.index,t.length).length<1)){var n=e.getBounds(t.index),o=document.createElement("div");o.id="inline-comment-mask",o.style.width="100%",o.style.height="100%",o.style.top="0px",o.style.position="fixed",o.style.display="block";var r=document.createElement("div");r.id="inline-comment",r.classList.add("inline-comment"),e.container.appendChild(r),e.container.appendChild(o),r.style.position="absolute",r.innerHTML='',r.style.left=n.left-250+"px",n.left+250'})}return a(e,[{key:"commentEventHanlder",value:function(){l(this.quill)}}]),e}();Quill.register("modules/inline_comment",d)},function(e,t){},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var r=n(1),i=(o(r),n(0));o(i)}]);
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "quill-inline-comment",
3 | "version": "0.0.9",
4 | "description": "Quill Extension for Inline Comment",
5 | "main": "webpack.config.js",
6 | "devDependencies": {
7 | "babel-core": "^6.24.1",
8 | "babel-loader": "^6.4.1",
9 | "babel-preset-env": "^1.5.1",
10 | "babel-preset-es2015": "^6.24.1",
11 | "css-loader": "^0.27.3",
12 | "extract-text-webpack-plugin": "^2.1.0",
13 | "file-loader": "^0.11.2",
14 | "node-sass": "^4.5.3",
15 | "sass-loader": "^6.0.5",
16 | "uglifyjs-webpack-plugin": "^0.4.3",
17 | "url-loader": "^0.5.9",
18 | "webpack": "^2.6.1",
19 | "webpack-dev-server": "^2.4.5"
20 | },
21 | "scripts": {
22 | "test": "npm test",
23 | "build": "webpack"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/contentco/quill-inline-comment.git"
28 | },
29 | "keywords": [
30 | "content",
31 | "quill",
32 | "editor"
33 | ],
34 | "author": "contentco",
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/contentco/quill-inline-comment/issues"
38 | },
39 | "homepage": "https://github.com/contentco/quill-inline-comment#readme",
40 | "dependencies": {
41 | "babel": "^6.23.0",
42 | "preact": "^7.2.1",
43 | "quill": "^1.2.4"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/module-inline-comment.js:
--------------------------------------------------------------------------------
1 | let Inline = Quill.import('blots/inline');
2 |
3 | class CommentBlot extends Inline {
4 | static create(commentText) {
5 | const node = super.create();
6 | node.dataset.comment = commentText.comment;
7 | if (commentText.id) {
8 | node.dataset.id = commentText.id;
9 | }
10 | if (commentText.resolved) {
11 | node.dataset.resolved = commentText.resolved;
12 | }
13 |
14 | return node;
15 | }
16 | static formats(node) {
17 | return node.dataset;
18 | }
19 | format(name, value) {
20 | super.format(name, value);
21 | }
22 | }
23 |
24 | CommentBlot.blotName = "comment";
25 | CommentBlot.tagName = "SPAN";
26 | CommentBlot.className = "annotation";
27 |
28 | Quill.register({
29 | 'formats/comment': CommentBlot
30 | });
31 |
32 |
33 | class GrammlyBlot extends Inline {
34 | static create(commentText) {
35 | const node = super.create();
36 |
37 | return node;
38 | }
39 | static formats(node) {
40 | return node.dataset;
41 | }
42 | format(name, value) {
43 | super.format(name, value);
44 | }
45 | }
46 |
47 | GrammlyBlot.blotName = "grammer";
48 | GrammlyBlot.tagName = "SPAN";
49 | GrammlyBlot.className = "gr_";
50 |
51 | Quill.register({
52 | 'formats/grammer': GrammlyBlot
53 | });
54 |
55 | class InlineComment {
56 | constructor(quill){
57 | this.quill = quill;
58 | this.toolbar = quill.getModule('toolbar');
59 | if (typeof this.toolbar != 'undefined')
60 | this.toolbar.addHandler('comment', this.commentEventHanlder);
61 |
62 | var commentBtns = document.getElementsByClassName('ql-comment');
63 | if (commentBtns) {
64 | [].slice.call( commentBtns ).forEach(function ( commentBtn ) {
65 | commentBtn.innerHTML = '';
66 | });
67 | };
68 | }
69 |
70 | commentEventHanlder() {
71 | let quill = this.quill;
72 | checkDialogExist(quill);
73 | }
74 | }
75 |
76 | function checkDialogExist(quill){
77 | let commentToolTip = document.getElementById("inline-comment");
78 | let commentMask = document.getElementById("inline-comment-mask");
79 | if (commentToolTip) {
80 | commentToolTip.remove();
81 | commentMask.remove();
82 | }
83 | else{
84 | createCommentDialog(quill);
85 | }
86 | }
87 |
88 | function createCommentDialog(quill) {
89 | let range = quill.getSelection();
90 | let text = quill.getText(range.index, range.length);
91 | if (text.length < 1) {
92 | return;
93 | }
94 | const atSignBounds = quill.getBounds(range.index);
95 | let containerMask = document.createElement('div');
96 | containerMask.id="inline-comment-mask";
97 | containerMask.style.width = "100%";
98 | containerMask.style.height = "100%";
99 | containerMask.style.top = "0px";
100 | containerMask.style.position = "fixed";
101 | containerMask.style.display = "block";
102 |
103 | let container = document.createElement('div');
104 | container.id = 'inline-comment';
105 | container.classList.add('inline-comment');
106 | quill.container.appendChild(container);
107 | quill.container.appendChild(containerMask);
108 | container.style.position = "absolute";
109 | container.innerHTML = '';
110 |
111 |
112 | container.style.left = (atSignBounds.left - 250)+ "px";
113 |
114 | if (atSignBounds.left + 250 < quill.container.clientWidth) {
115 | container.style.left = (atSignBounds.left)+ "px";
116 | }
117 |
118 | container.style.top = 10 + atSignBounds.top + atSignBounds.height + "px";
119 | container.style.zIndex = 80;
120 | document.querySelector('.commentText').focus();
121 |
122 | let inlineCancel = document.querySelector('.inline-cancel');
123 | let commentToolTip = document.querySelector('.inline-comment');
124 |
125 | inlineCancel.addEventListener('click',function(){
126 | commentToolTip.style.display = "none";
127 | containerMask.style.display = "none";
128 | });
129 |
130 | let inlineSend = document.querySelector('.inline-send');
131 |
132 | inlineSend.addEventListener('click',function(){
133 | // var commentId = 1;
134 | // var commentStatus = 'resolved';
135 | const commentObj = {};
136 | let commentText = document.querySelector('.commentText').value;
137 | commentObj.comment = commentText;
138 | if (typeof(commentId) !== 'undefined') {
139 | commentObj.id= commentId;
140 | }
141 | if (typeof(commentStatus) !== 'undefined') {
142 | commentObj.resolved= commentStatus;
143 | }
144 | commentToolTip.remove();
145 | containerMask.remove();
146 | //quill.format('comment', commentObj);
147 | quill.format('comment', commentObj);
148 | });
149 |
150 | }
151 |
152 | Quill.register('modules/inline_comment', InlineComment);
153 |
--------------------------------------------------------------------------------
/src/quill-inline-comment.js:
--------------------------------------------------------------------------------
1 | import css from './scss/base.scss';
2 | import InlineComment from '../src/module-inline-comment';
--------------------------------------------------------------------------------
/src/scss/base.scss:
--------------------------------------------------------------------------------
1 | @import 'core/styles';
--------------------------------------------------------------------------------
/src/scss/core/_styles.scss:
--------------------------------------------------------------------------------
1 | @import 'core/variables'; /* sass-loader doesnt like absolute imports*/
2 | body {
3 | background: $white;
4 | }
5 | #quill-editor {
6 | position: relative;
7 | }
8 | .inline-comment{
9 | background-color: #fff;
10 | border: 1px solid #ccc;
11 | box-shadow: 0 0 5px #ddd;
12 | color: #444;
13 | padding: 5px 12px;
14 | white-space: nowrap;
15 | }
16 | .commentText{
17 | border: none;
18 | display: block;
19 | resize: none;
20 | }
21 | .commentText:focus{
22 | outline: none;
23 | }
24 | .inline-comment-bottom{
25 | margin-top: 15px;
26 | text-align: right;
27 | }
28 | .annotation{
29 | background: #a5caf2;
30 | }
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/scss/core/_variables.scss:
--------------------------------------------------------------------------------
1 | $white: #FFF;
2 | $blue: #0366d6;
3 | $cyan: #2D9EE0;
4 | $light-blue: #84a8cc;
5 | $light-gray: #ddd;
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
3 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
4 |
5 | // const autoprefixer = requre('autoprefixer');
6 |
7 | const config = {
8 | entry: './src/quill-inline-comment.js',
9 | output: {
10 | path: path.resolve(__dirname, 'dist'),
11 | filename: 'quill-inline-comment.js'
12 | },
13 | devServer: {
14 | contentBase: path.join(__dirname),
15 | compress: true,
16 | port: 9000
17 | },
18 | module: {
19 | rules: [
20 | {
21 | test: /\.scss$/,
22 | use: ExtractTextPlugin.extract({
23 | use: [{
24 | loader: 'css-loader',
25 | options: {
26 | minimize: true || {/* CSSNano Options */}
27 | }
28 | }, {
29 | loader: 'sass-loader',
30 | }]
31 | }),
32 | },
33 | {
34 | test: /\.js$/,
35 | include: [
36 | path.resolve(__dirname, "src/")
37 | ],
38 | exclude: /(node_modules)/,
39 | use: {
40 | loader: 'babel-loader',
41 | options: {
42 | presets: [['es2015', {modules: false}],]
43 | }
44 | }
45 | },
46 | {
47 | test: /\.png$/,
48 | loader: "file-loader"
49 | },
50 | {
51 | test: /\.(png|woff|woff2|eot|ttf|svg)$/,
52 | loader: 'url-loader?limit=100000'
53 | }
54 | ]
55 | },
56 | plugins: [
57 | new ExtractTextPlugin('quill-inline-comment.css'),
58 | new UglifyJSPlugin({
59 | compress: {
60 | warnings: false,
61 | screw_ie8: true,
62 | conditionals: true,
63 | unused: true,
64 | comparisons: true,
65 | sequences: true,
66 | dead_code: true,
67 | evaluate: true,
68 | join_vars: true,
69 | if_return: true
70 | },
71 | output: {
72 | comments: false
73 | }
74 | }),
75 | ]
76 | };
77 |
78 | module.exports = config;
79 |
--------------------------------------------------------------------------------