diff --git a/package-lock.json b/package-lock.json
index 04a6d1fc99..891bf63b1d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7329,6 +7329,23 @@
}
}
},
+ "babel-loader-exclude-node-modules-except": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/babel-loader-exclude-node-modules-except/-/babel-loader-exclude-node-modules-except-1.0.3.tgz",
+ "integrity": "sha512-UEHoSzivswrRu3bb7UIVpY0g1kBnZvuU/2oXrRBhggjQOqW2HBCp6FsvuNc8ZupBUh+zClKxw8jxwuqZTSapwQ==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "2.0.0"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true
+ }
+ }
+ },
"babel-messages": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
@@ -27323,6 +27340,11 @@
"integrity": "sha512-1CxDIZmCQ3vA0GGnkdMQqxUXVm3xXAFmglPYRS1hr37LzSg22TC7QAWOT38OmdUvMEs/rqcnkFoAsqvzdiluDg==",
"dev": true
},
+ "tributejs": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/tributejs/-/tributejs-5.1.3.tgz",
+ "integrity": "sha512-B5CXihaVzXw+1UHhNFyAwUTMDk1EfoLP5Tj1VhD9yybZ1I8DZJEv8tZ1l0RJo0t0tk9ZhR8eG5tEsaCvRigmdQ=="
+ },
"trim": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
@@ -28233,6 +28255,22 @@
}
}
},
+ "vue-input-contenteditable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/vue-input-contenteditable/-/vue-input-contenteditable-1.0.1.tgz",
+ "integrity": "sha512-qjJ9xZOyO6eQm0z7kwermcfGQcxAaSqf60PTQ2p5G+AZY32/wQRlu8WAHLnW3VMmTA5Y5TdT+liOW09Mg1RcHA==",
+ "requires": {
+ "core-js": "^2.6.11",
+ "vue": "^2.6.12"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
+ "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
+ }
+ }
+ },
"vue-jest": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/vue-jest/-/vue-jest-3.0.7.tgz",
diff --git a/package.json b/package.json
index e8e10d276d..4db7f06957 100644
--- a/package.json
+++ b/package.json
@@ -50,10 +50,12 @@
"linkifyjs": "~2.1.9",
"md5": "^2.2.1",
"regenerator-runtime": "^0.13.5",
+ "tributejs": "^5.1.3",
"v-click-outside": "^3.0.1",
"v-tooltip": "^2.0.3",
"vue": "^2.6.11",
"vue-color": "^2.7.1",
+ "vue-input-contenteditable": "^1.0.1",
"vue-multiselect": "^2.1.6",
"vue-visible": "^1.0.2",
"vue2-datepicker": "^3.6.2"
@@ -72,6 +74,7 @@
"babel-eslint": "^10.1.0",
"babel-jest": "^26.3.0",
"babel-loader": "^8.1.0",
+ "babel-loader-exclude-node-modules-except": "^1.0.3",
"css-loader": "^3.5.2",
"cypress": "^5.0.0",
"cypress-visual-regression": "^1.5.0",
diff --git a/src/components/RichContenteditable/RichContenteditable.vue b/src/components/RichContenteditable/RichContenteditable.vue
new file mode 100644
index 0000000000..2a4171d3b9
--- /dev/null
+++ b/src/components/RichContenteditable/RichContenteditable.vue
@@ -0,0 +1,301 @@
+
+
+
+
+### General description
+
+This component displays contenteditable div with automated @ autocompletion [at].
+
+### Examples
+
+```vue
+
+
+
+ {{ message }}
+
+
+
+```
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/RichContenteditable/index.js b/src/components/RichContenteditable/index.js
new file mode 100644
index 0000000000..5b3e36ebae
--- /dev/null
+++ b/src/components/RichContenteditable/index.js
@@ -0,0 +1,25 @@
+/**
+ * @copyright Copyright (c) 2020 John Molakvoæ
+ *
+ * @author John Molakvoæ
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+import RichContenteditable from './RichContenteditable'
+
+export default RichContenteditable
diff --git a/src/components/index.js b/src/components/index.js
index 6f9fed7d92..0ecaa1d763 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -56,6 +56,7 @@ import Multiselect from './Multiselect'
import MultiselectTags from './MultiselectTags'
import Popover from './Popover'
import PopoverMenu from './PopoverMenu'
+import RichContenteditable from './RichContenteditable'
import SettingsSection from './SettingsSection'
import UserBubble from './UserBubble'
@@ -95,6 +96,7 @@ export {
MultiselectTags,
Popover,
PopoverMenu,
+ RichContenteditable,
SettingsSection,
UserBubble,
}
diff --git a/webpack.common.js b/webpack.common.js
index 611ebf04e6..51668b2d11 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -3,14 +3,13 @@ const gettextParser = require('gettext-parser')
const glob = require('glob')
const md5 = require('md5')
const path = require('path')
-const StyleLintPlugin = require('stylelint-webpack-plugin')
-const { VueLoaderPlugin } = require('vue-loader')
-
-const IconfontPlugin = require('iconfont-plugin-webpack')
const { DefinePlugin } = require('webpack')
-
+const { VueLoaderPlugin } = require('vue-loader')
+const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except')
+const IconfontPlugin = require('iconfont-plugin-webpack')
const nodeExternals = require('webpack-node-externals')
+const StyleLintPlugin = require('stylelint-webpack-plugin')
// scope variable
// fallback for cypress testing
@@ -121,7 +120,9 @@ module.exports = {
{
test: /\.js$/,
loader: 'babel-loader',
- exclude: /node_modules/,
+ exclude: BabelLoaderExcludeNodeModulesExcept([
+ 'tributejs',
+ ]),
},
{
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/i,