feat: anchor - copy link to clipboard
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueResource from 'vue-resource'
|
import VueResource from 'vue-resource'
|
||||||
|
import VueClipboards from 'vue-clipboards'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import io from 'socket.io-client'
|
import io from 'socket.io-client'
|
||||||
import i18next from 'i18next'
|
import i18next from 'i18next'
|
||||||
@@ -36,6 +37,7 @@ import sourceComponent from './pages/source.component.js'
|
|||||||
// ====================================
|
// ====================================
|
||||||
|
|
||||||
Vue.use(VueResource)
|
Vue.use(VueResource)
|
||||||
|
Vue.use(VueClipboards)
|
||||||
Vue.use(VueI18Next)
|
Vue.use(VueI18Next)
|
||||||
|
|
||||||
i18next
|
i18next
|
||||||
@@ -91,7 +93,7 @@ $(() => {
|
|||||||
i18n,
|
i18n,
|
||||||
el: '#root',
|
el: '#root',
|
||||||
mounted() {
|
mounted() {
|
||||||
$('a').smoothScroll({ speed: 500, offset: -50 })
|
$('a:not(.toc-anchor)').smoothScroll({ speed: 500, offset: -50 })
|
||||||
$('#header').sticky({ topSpacing: 0 })
|
$('#header').sticky({ topSpacing: 0 })
|
||||||
$('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 })
|
$('.sidebar-pagecontents').sticky({ topSpacing: 15, bottomSpacing: 75 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,53 @@
|
|||||||
<template>
|
<template lang="pug">
|
||||||
<div>
|
.modal(v-bind:class='{ "is-active": isShown }')
|
||||||
<p>{{ msg }}</p>
|
.modal-background
|
||||||
<input type="text" v-model="msg" />
|
.modal-container
|
||||||
</div>
|
.modal-content
|
||||||
|
header.is-blue
|
||||||
|
span Copy link to this section
|
||||||
|
section
|
||||||
|
p.control.is-fullwidth
|
||||||
|
input.input(type='text', ref='anchorURLinput', v-model='anchorURL')
|
||||||
|
footer
|
||||||
|
a.button.is-grey.is-outlined(v-on:click='cancel') Discard
|
||||||
|
a.button.is-blue(v-clipboard='anchorURL', @success="clipboardSuccess", @error="clipboardError") Copy to Clipboard
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'anchor',
|
name: 'anchor',
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {}
|
||||||
msg: 'Welcome to Your Vue.js App'
|
},
|
||||||
|
computed: {
|
||||||
|
anchorURL () {
|
||||||
|
return window.location.href.split('#')[0] + '#' + this.$store.state.anchor.hash
|
||||||
|
},
|
||||||
|
isShown () {
|
||||||
|
return this.$store.state.anchor.shown
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
cancel () {
|
||||||
|
this.$store.dispatch('anchorClose')
|
||||||
|
},
|
||||||
|
clipboardSuccess () {
|
||||||
|
this.$store.dispatch('alert', {
|
||||||
|
style: 'blue',
|
||||||
|
icon: 'clipboard',
|
||||||
|
msg: 'The URL has been copied to your clipboard.'
|
||||||
|
})
|
||||||
|
this.$store.dispatch('anchorClose')
|
||||||
|
},
|
||||||
|
clipboardError () {
|
||||||
|
this.$store.dispatch('alert', {
|
||||||
|
style: 'red',
|
||||||
|
icon: 'clipboard',
|
||||||
|
msg: 'Clipboard copy failed. Copy the URL manually.'
|
||||||
|
})
|
||||||
|
this.$refs.anchorURLinput.select()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Vue from 'vue'
|
|||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
import alert from './modules/alert'
|
import alert from './modules/alert'
|
||||||
|
import anchor from './modules/anchor'
|
||||||
import adminUsersCreate from './modules/admin-users-create'
|
import adminUsersCreate from './modules/admin-users-create'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
@@ -20,6 +21,7 @@ export default new Vuex.Store({
|
|||||||
getters: {},
|
getters: {},
|
||||||
modules: {
|
modules: {
|
||||||
alert,
|
alert,
|
||||||
|
anchor,
|
||||||
adminUsersCreate
|
adminUsersCreate
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
23
client/js/store/modules/anchor.js
Normal file
23
client/js/store/modules/anchor.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
state: {
|
||||||
|
shown: false,
|
||||||
|
hash: ''
|
||||||
|
},
|
||||||
|
getters: {},
|
||||||
|
mutations: {
|
||||||
|
anchorChange: (state, opts) => {
|
||||||
|
state.shown = (opts.shown === true)
|
||||||
|
state.hash = opts.hash || ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
anchorOpen({ commit, dispatch }, hash) {
|
||||||
|
commit('anchorChange', { shown: true, hash })
|
||||||
|
},
|
||||||
|
anchorClose({ commit, dispatch }) {
|
||||||
|
commit('anchorChange', { shown: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"uglify-js": "latest",
|
"uglify-js": "latest",
|
||||||
"vee-validate": "^2.0.0-rc.3",
|
"vee-validate": "^2.0.0-rc.3",
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
|
"vue-clipboards": "^1.0.0",
|
||||||
"vue-resource": "^1.3.1",
|
"vue-resource": "^1.3.1",
|
||||||
"vue-template-compiler": "^2.3.3",
|
"vue-template-compiler": "^2.3.3",
|
||||||
"vue-template-es2015-compiler": "^1.5.2",
|
"vue-template-es2015-compiler": "^1.5.2",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ var mkdown = md({
|
|||||||
html: true,
|
html: true,
|
||||||
linkify: true,
|
linkify: true,
|
||||||
typography: true,
|
typography: true,
|
||||||
highlight (str, lang) {
|
highlight(str, lang) {
|
||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'
|
return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'
|
||||||
@@ -206,6 +206,13 @@ const parseContent = (content) => {
|
|||||||
cr(elm).replaceWith(txtLink)
|
cr(elm).replaceWith(txtLink)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// -> Add anchor handler
|
||||||
|
|
||||||
|
cr('a.toc-anchor').each((i, elm) => {
|
||||||
|
let hashText = cr(elm).attr('href').slice(1)
|
||||||
|
cr(elm).attr('v-on:click.stop.prevent', "$store.dispatch('anchorOpen', '" + hashText + "')")
|
||||||
|
})
|
||||||
|
|
||||||
// -> Re-attach blockquote styling classes to their parents
|
// -> Re-attach blockquote styling classes to their parents
|
||||||
|
|
||||||
cr.root().children('blockquote').each((i, elm) => {
|
cr.root().children('blockquote').each((i, elm) => {
|
||||||
@@ -313,7 +320,7 @@ module.exports = {
|
|||||||
* @param {String} content Markdown-formatted content
|
* @param {String} content Markdown-formatted content
|
||||||
* @return {Object} Object containing meta, html and tree data
|
* @return {Object} Object containing meta, html and tree data
|
||||||
*/
|
*/
|
||||||
parse (content) {
|
parse(content) {
|
||||||
return {
|
return {
|
||||||
meta: parseMeta(content),
|
meta: parseMeta(content),
|
||||||
html: parseContent(content),
|
html: parseContent(content),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
extends ./_layout.pug
|
extends ./_layout.pug
|
||||||
|
|
||||||
block rootNavRight
|
block rootNavRight
|
||||||
i.nav-item#notifload
|
loading-spinner
|
||||||
.nav-item
|
.nav-item
|
||||||
a.button(v-on:click='$store.dispatch("adminUsersCreateOpen")')
|
a.button(v-on:click='$store.dispatch("adminUsersCreateOpen")')
|
||||||
i.icon-plus
|
i.icon-plus
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ mixin tocMenu(ti)
|
|||||||
+tocMenu(node.nodes)
|
+tocMenu(node.nodes)
|
||||||
|
|
||||||
block rootNavRight
|
block rootNavRight
|
||||||
i.nav-item#notifload
|
loading-spinner
|
||||||
.nav-item
|
.nav-item
|
||||||
if rights.write
|
if rights.write
|
||||||
a.button.is-outlined.btn-move-prompt.is-hidden
|
a.button.is-outlined.btn-move-prompt.is-hidden
|
||||||
@@ -83,3 +83,4 @@ block content
|
|||||||
|
|
||||||
include ../modals/create.pug
|
include ../modals/create.pug
|
||||||
include ../modals/move.pug
|
include ../modals/move.pug
|
||||||
|
anchor
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ extends ../layout.pug
|
|||||||
|
|
||||||
block rootNavCenter
|
block rootNavCenter
|
||||||
|
|
||||||
block rootNavRight
|
|
||||||
i.nav-item#notifload
|
|
||||||
|
|
||||||
block content
|
block content
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user