diff --git a/package-lock.json b/package-lock.json index d597b30628b53ba076f5b3085493f3d10e2a5a1c..5f39dbee276a51b9372a1517a72c26cd2aa9dab7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3186,7 +3186,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -8776,6 +8775,14 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "requires": { + "uc.micro": "^1.0.1" + } + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -8968,6 +8975,25 @@ "resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.1.tgz", "integrity": "sha512-QQ/iKiM43DM9+aujTL45Iz5o7gDeSFmy4LPl3HZmNcwCE++NxGazf+yFpY+wCb+YS23sDa1ghpo3zrNFOcHlow==" }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -8985,6 +9011,11 @@ "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", "dev": true }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -12110,8 +12141,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.17.0", @@ -12632,6 +12662,15 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "textarea-markdown": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/textarea-markdown/-/textarea-markdown-1.3.1.tgz", + "integrity": "sha512-1rCSrFwnRE++oM5NT+t7GEbT647geFVPcnhD4y0gSwpIKIpWwy7UbBCTowt7pum+CZB2Hv5niNmO54bP+wyjMA==", + "requires": { + "markdown-it": "^8.4.0", + "whatwg-fetch": "^2.0.3" + } + }, "thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -12899,6 +12938,11 @@ "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "uglify-js": { "version": "3.4.10", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", @@ -14169,6 +14213,11 @@ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", diff --git a/package.json b/package.json index f9767b05d6eff392d7bdc1ae6e4c72dc56220735..e28623c0db2883316c4e62b115bf9773f70e4760 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "register-service-worker": "^1.7.1", "rxjs": "^6.6.7", "sortablejs": "^1.14.0", + "textarea-markdown": "^1.3.1", "vue": "^2.6.11", "vue-multiselect": "~2.1.6", "vue-router": "^3.5.3", diff --git a/src/components/Project/Detail/ProjectHeader.vue b/src/components/Project/Detail/ProjectHeader.vue index 610e46a06da6166f87938f102fec0172b3b5093c..c9588d7a414bf0bace02235f02b105b7fb50b144 100644 --- a/src/components/Project/Detail/ProjectHeader.vue +++ b/src/components/Project/Detail/ProjectHeader.vue @@ -51,7 +51,14 @@ {{ project.title }} </h1> <div class="sub header"> - {{ project.description }} + <!-- {{ project.description }} --> + <div id="preview" /> + <textarea + id="editor" + v-model="project.description" + data-preview="#preview" + hidden + /> </div> </div> @@ -158,6 +165,7 @@ </template> <script> +import TextareaMarkdown from 'textarea-markdown'; import { mapState, mapGetters, mapMutations } from 'vuex'; @@ -213,6 +221,11 @@ export default { }, + mounted() { + let textarea = document.querySelector('textarea'); + new TextareaMarkdown(textarea); + }, + methods: { ...mapMutations('modals', [ 'OPEN_PROJECT_MODAL' @@ -290,6 +303,11 @@ export default { } } +#preview { + max-height: 10em; + overflow: scroll; +} + @media screen and (max-width: 767px) { .middle.aligned.column { text-align: center; diff --git a/src/components/Projects/ProjectsListItem.vue b/src/components/Projects/ProjectsListItem.vue index fe3e4d4e908ed04287a73b0e99a2c57f616d1c44..1059a36c29463f8528fb450f0137b0c571f18757 100644 --- a/src/components/Projects/ProjectsListItem.vue +++ b/src/components/Projects/ProjectsListItem.vue @@ -21,7 +21,16 @@ {{ project.title }} </router-link> <div class="description"> - <p>{{ project.description }}</p> + <textarea + :id="`editor-${project.slug}`" + :value="project.description" + :data-preview="`#preview-${project.slug}`" + hidden + /> + <div + :id="`preview-${project.slug}`" + class="preview" + /> </div> <div class="meta top"> <span class="right floated"> @@ -74,6 +83,7 @@ </template> <script> +import TextareaMarkdown from 'textarea-markdown'; import { mapState } from 'vuex'; @@ -100,6 +110,11 @@ export default { }, }, + mounted() { + let textarea = document.getElementById(`editor-${this.project.slug}`); + new TextareaMarkdown(textarea); + }, + methods: { refreshId() { const crypto = window.crypto || window.msCrypto; @@ -112,6 +127,11 @@ export default { </script> <style lang="less" scoped> +.preview { + max-height: 10em; + overflow: scroll; + margin-bottom: 0.8em; +} .description { p { diff --git a/src/views/Project/ProjectEdit.vue b/src/views/Project/ProjectEdit.vue index 0e788f3f84a33b747d170945eb5d315fef982b37..b36976a70387053c06941516c006205576a03a8b 100644 --- a/src/views/Project/ProjectEdit.vue +++ b/src/views/Project/ProjectEdit.vue @@ -91,14 +91,26 @@ </ul> </div> </div> - <div class="field"> - <label for="description">Description</label> - <textarea - v-model="form.description" - name="description" - rows="5" - /> - <!-- {{ form.description.errors }} --> + <div class="two fields"> + <div class="field"> + <label for="description">Description</label> + <textarea + id="editor" + v-model="form.description" + data-preview="#preview" + name="description" + rows="5" + /> + <!-- {{ form.description.errors }} --> + </div> + <div class="field"> + <label for="preview">Aperçu</label> + <div + id="preview" + class="description preview" + name="preview" + /> + </div> </div> <div class="ui horizontal divider"> @@ -248,6 +260,8 @@ import axios from '@/axios-client.js'; import Dropdown from '@/components/Dropdown.vue'; +import TextareaMarkdown from 'textarea-markdown'; + import { mapState } from 'vuex'; export default { @@ -371,6 +385,11 @@ export default { } }, + mounted() { + let textarea = document.querySelector('textarea'); + new TextareaMarkdown(textarea); + }, + methods: { definePageType() { if (this.$router.history.current.name === 'project_create') { @@ -642,4 +661,15 @@ export default { .close.icon:hover { cursor: pointer; } + +textarea { + height: 10em; +} + +.description.preview { + height: 10em; + overflow: scroll; + border: 1px solid rgba(34, 36, 38, .15); + padding: .78571429em 1em; +} </style> \ No newline at end of file