mirror of https://github.com/requarks/wiki
parent
188d36e6bb
commit
ded41321f2
@ -0,0 +1,75 @@
|
||||
<template lang="pug">
|
||||
v-footer.justify-center(:color='bgColor', inset)
|
||||
.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-1`')
|
||||
template(v-if='footerOverride')
|
||||
span(v-html='footerOverrideRender + ` | `')
|
||||
template(v-else-if='company && company.length > 0 && contentLicense !== ``')
|
||||
span(v-if='contentLicense === `alr`') {{ $t('common:footer.copyright', { company: company, year: currentYear, interpolation: { escapeValue: false } }) }} |
|
||||
span(v-else) {{ $t('common:footer.license', { company: company, license: $t('common:license.' + contentLicense), interpolation: { escapeValue: false } }) }} |
|
||||
span {{ $t('common:footer.poweredBy') }} #[a(href='https://wiki.js.org', ref='nofollow') Wiki.js]
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get } from 'vuex-pathify'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
const md = new MarkdownIt({
|
||||
html: false,
|
||||
breaks: false,
|
||||
linkify: true
|
||||
})
|
||||
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: 'grey lighten-3'
|
||||
},
|
||||
darkColor: {
|
||||
type: String,
|
||||
default: 'grey darken-3'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentYear: (new Date()).getFullYear()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
company: get('site/company'),
|
||||
contentLicense: get('site/contentLicense'),
|
||||
footerOverride: get('site/footerOverride'),
|
||||
footerOverrideRender () {
|
||||
if (!this.footerOverride) { return '' }
|
||||
return md.renderInline(this.footerOverride)
|
||||
},
|
||||
bgColor() {
|
||||
if (!this.$vuetify.theme.dark) {
|
||||
return this.color
|
||||
} else {
|
||||
return this.darkColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.v-footer {
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.altbg {
|
||||
background: mc('theme', 'primary');
|
||||
|
||||
span {
|
||||
color: mc('blue', '300');
|
||||
}
|
||||
|
||||
a {
|
||||
color: mc('blue', '200');
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,238 @@
|
||||
<template lang="pug">
|
||||
div
|
||||
.pa-3.d-flex(v-if='navMode === `MIXED`', :class='$vuetify.theme.dark ? `grey darken-5` : `blue darken-3`')
|
||||
v-btn(
|
||||
depressed
|
||||
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
||||
style='min-width:0;'
|
||||
@click='goHome'
|
||||
:aria-label='$t(`common:header.home`)'
|
||||
)
|
||||
v-icon(size='20') mdi-home
|
||||
v-btn.ml-3(
|
||||
v-if='currentMode === `custom`'
|
||||
depressed
|
||||
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
||||
style='flex: 1 1 100%;'
|
||||
@click='switchMode(`browse`)'
|
||||
)
|
||||
v-icon(left) mdi-file-tree
|
||||
.body-2.text-none {{$t('common:sidebar.browse')}}
|
||||
v-btn.ml-3(
|
||||
v-else-if='currentMode === `browse`'
|
||||
depressed
|
||||
:color='$vuetify.theme.dark ? `grey darken-4` : `blue darken-2`'
|
||||
style='flex: 1 1 100%;'
|
||||
@click='switchMode(`custom`)'
|
||||
)
|
||||
v-icon(left) mdi-navigation
|
||||
.body-2.text-none {{$t('common:sidebar.mainMenu')}}
|
||||
v-divider
|
||||
//-> Custom Navigation
|
||||
v-list.py-2(v-if='currentMode === `custom`', dense, :class='color', :dark='dark')
|
||||
template(v-for='item of items')
|
||||
v-list-item(
|
||||
v-if='item.k === `link`'
|
||||
:href='item.t'
|
||||
:target='item.y === `externalblank` ? `_blank` : `_self`'
|
||||
:rel='item.y === `externalblank` ? `noopener` : ``'
|
||||
)
|
||||
v-list-item-avatar(size='24', tile)
|
||||
v-icon(v-if='item.c.match(/fa[a-z] fa-/)', size='19') {{ item.c }}
|
||||
v-icon(v-else) {{ item.c }}
|
||||
v-list-item-title {{ item.l }}
|
||||
v-divider.my-2(v-else-if='item.k === `divider`')
|
||||
v-subheader.pl-4(v-else-if='item.k === `header`') {{ item.l }}
|
||||
//-> Browse
|
||||
v-list.py-2(v-else-if='currentMode === `browse`', dense, :class='color', :dark='dark')
|
||||
template(v-if='currentParent.id > 0')
|
||||
v-list-item(v-for='(item, idx) of parents', :key='`parent-` + item.id', @click='fetchBrowseItems(item)', style='min-height: 30px;')
|
||||
v-list-item-avatar(size='18', :style='`padding-left: ` + (idx * 8) + `px; width: auto; margin: 0 5px 0 0;`')
|
||||
v-icon(small) mdi-folder-open
|
||||
v-list-item-title {{ item.title }}
|
||||
v-divider.mt-2
|
||||
v-list-item.mt-2(v-if='currentParent.pageId > 0', :href='`/` + currentParent.locale + `/` + currentParent.path', :key='`directorypage-` + currentParent.id', :input-value='path === currentParent.path')
|
||||
v-list-item-avatar(size='24')
|
||||
v-icon mdi-text-box
|
||||
v-list-item-title {{ currentParent.title }}
|
||||
v-subheader.pl-4 {{$t('common:sidebar.currentDirectory')}}
|
||||
template(v-for='item of currentItems')
|
||||
v-list-item(v-if='item.isFolder', :key='`childfolder-` + item.id', @click='fetchBrowseItems(item)')
|
||||
v-list-item-avatar(size='24')
|
||||
v-icon mdi-folder
|
||||
v-list-item-title {{ item.title }}
|
||||
v-list-item(v-else, :href='`/` + item.locale + `/` + item.path', :key='`childpage-` + item.id', :input-value='path === item.path')
|
||||
v-list-item-avatar(size='24')
|
||||
v-icon mdi-text-box
|
||||
v-list-item-title {{ item.title }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import _ from 'lodash'
|
||||
import gql from 'graphql-tag'
|
||||
import { get } from 'vuex-pathify'
|
||||
|
||||
/* global siteLangs */
|
||||
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
dark: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
navMode: {
|
||||
type: String,
|
||||
default: 'MIXED'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentMode: 'custom',
|
||||
currentItems: [],
|
||||
currentParent: {
|
||||
id: 0,
|
||||
title: '/ (root)'
|
||||
},
|
||||
parents: [],
|
||||
loadedCache: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
path: get('page/path'),
|
||||
locale: get('page/locale')
|
||||
},
|
||||
methods: {
|
||||
switchMode (mode) {
|
||||
this.currentMode = mode
|
||||
window.localStorage.setItem('navPref', mode)
|
||||
if (mode === `browse` && this.loadedCache.length < 1) {
|
||||
this.loadFromCurrentPath()
|
||||
}
|
||||
},
|
||||
async fetchBrowseItems (item) {
|
||||
this.$store.commit(`loadingStart`, 'browse-load')
|
||||
if (!item) {
|
||||
item = this.currentParent
|
||||
}
|
||||
|
||||
if (this.loadedCache.indexOf(item.id) < 0) {
|
||||
this.currentItems = []
|
||||
}
|
||||
|
||||
if (item.id === 0) {
|
||||
this.parents = []
|
||||
} else {
|
||||
const flushRightIndex = _.findIndex(this.parents, ['id', item.id])
|
||||
if (flushRightIndex >= 0) {
|
||||
this.parents = _.take(this.parents, flushRightIndex)
|
||||
}
|
||||
if (this.parents.length < 1) {
|
||||
this.parents.push(this.currentParent)
|
||||
}
|
||||
this.parents.push(item)
|
||||
}
|
||||
|
||||
this.currentParent = item
|
||||
|
||||
const resp = await this.$apollo.query({
|
||||
query: gql`
|
||||
query ($parent: Int, $locale: String!) {
|
||||
pages {
|
||||
tree(parent: $parent, mode: ALL, locale: $locale) {
|
||||
id
|
||||
path
|
||||
title
|
||||
isFolder
|
||||
pageId
|
||||
parent
|
||||
locale
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
fetchPolicy: 'cache-first',
|
||||
variables: {
|
||||
parent: item.id,
|
||||
locale: this.locale
|
||||
}
|
||||
})
|
||||
this.loadedCache = _.union(this.loadedCache, [item.id])
|
||||
this.currentItems = _.get(resp, 'data.pages.tree', [])
|
||||
this.$store.commit(`loadingStop`, 'browse-load')
|
||||
},
|
||||
async loadFromCurrentPath() {
|
||||
this.$store.commit(`loadingStart`, 'browse-load')
|
||||
const resp = await this.$apollo.query({
|
||||
query: gql`
|
||||
query ($path: String, $locale: String!) {
|
||||
pages {
|
||||
tree(path: $path, mode: ALL, locale: $locale, includeAncestors: true) {
|
||||
id
|
||||
path
|
||||
title
|
||||
isFolder
|
||||
pageId
|
||||
parent
|
||||
locale
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
fetchPolicy: 'cache-first',
|
||||
variables: {
|
||||
path: this.path,
|
||||
locale: this.locale
|
||||
}
|
||||
})
|
||||
const items = _.get(resp, 'data.pages.tree', [])
|
||||
const curPage = _.find(items, ['pageId', this.$store.get('page/id')])
|
||||
if (!curPage) {
|
||||
console.warn('Could not find current page in page tree listing!')
|
||||
return
|
||||
}
|
||||
|
||||
let curParentId = curPage.parent
|
||||
let invertedAncestors = []
|
||||
while (curParentId) {
|
||||
const curParent = _.find(items, ['id', curParentId])
|
||||
if (!curParent) {
|
||||
break
|
||||
}
|
||||
invertedAncestors.push(curParent)
|
||||
curParentId = curParent.parent
|
||||
}
|
||||
|
||||
this.parents = [this.currentParent, ...invertedAncestors.reverse()]
|
||||
this.currentParent = _.last(this.parents)
|
||||
|
||||
this.loadedCache = [curPage.parent]
|
||||
this.currentItems = _.filter(items, ['parent', curPage.parent])
|
||||
this.$store.commit(`loadingStop`, 'browse-load')
|
||||
},
|
||||
goHome () {
|
||||
window.location.assign(siteLangs.length > 0 ? `/${this.locale}/home` : '/')
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.currentParent.title = `/ ${this.$t('common:sidebar.root')}`
|
||||
if (this.navMode === 'TREE') {
|
||||
this.currentMode = 'browse'
|
||||
} else if (this.navMode === 'STATIC') {
|
||||
this.currentMode = 'custom'
|
||||
} else {
|
||||
this.currentMode = window.localStorage.getItem('navPref') || 'custom'
|
||||
}
|
||||
if (this.currentMode === 'browse') {
|
||||
this.loadFromCurrentPath()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,800 @@
|
||||
<template lang="pug">
|
||||
v-app(v-scroll='upBtnScroll', :dark='$vuetify.theme.dark', :class='$vuetify.rtl ? `is-rtl` : `is-ltr`')
|
||||
nav-header(v-if='!printView')
|
||||
v-navigation-drawer(
|
||||
v-if='navMode !== `NONE` && !printView'
|
||||
:class='$vuetify.theme.dark ? `grey darken-4-d4` : `primary`'
|
||||
dark
|
||||
app
|
||||
clipped
|
||||
mobile-breakpoint='600'
|
||||
:temporary='$vuetify.breakpoint.smAndDown'
|
||||
v-model='navShown'
|
||||
:right='$vuetify.rtl'
|
||||
)
|
||||
vue-scroll(:ops='scrollStyle')
|
||||
nav-sidebar(:color='$vuetify.theme.dark ? `grey darken-4-d4` : `primary`', :items='sidebarDecoded', :nav-mode='navMode')
|
||||
|
||||
v-fab-transition(v-if='navMode !== `NONE`')
|
||||
v-btn(
|
||||
fab
|
||||
color='primary'
|
||||
fixed
|
||||
bottom
|
||||
:right='$vuetify.rtl'
|
||||
:left='!$vuetify.rtl'
|
||||
small
|
||||
@click='navShown = !navShown'
|
||||
v-if='$vuetify.breakpoint.mdAndDown'
|
||||
v-show='!navShown'
|
||||
)
|
||||
v-icon mdi-menu
|
||||
|
||||
v-main(ref='content')
|
||||
template(v-if='path !== `home`')
|
||||
v-toolbar(:color='$vuetify.theme.dark ? `grey darken-4-d3` : `grey lighten-3`', flat, dense, v-if='$vuetify.breakpoint.smAndUp')
|
||||
//- v-btn.pl-0(v-if='$vuetify.breakpoint.xsOnly', flat, @click='toggleNavigation')
|
||||
//- v-icon(color='grey darken-2', left) menu
|
||||
//- span Navigation
|
||||
v-breadcrumbs.breadcrumbs-nav.pl-0(
|
||||
:items='breadcrumbs'
|
||||
divider='/'
|
||||
)
|
||||
template(slot='item', slot-scope='props')
|
||||
v-icon(v-if='props.item.path === "/"', small, @click='goHome') mdi-home
|
||||
v-btn.ma-0(v-else, :href='props.item.path', small, text) {{props.item.name}}
|
||||
template(v-if='!isPublished')
|
||||
v-spacer
|
||||
.caption.red--text {{$t('common:page.unpublished')}}
|
||||
status-indicator.ml-3(negative, pulse)
|
||||
v-divider
|
||||
v-container.grey.pa-0(fluid, :class='$vuetify.theme.dark ? `darken-4-l3` : `lighten-4`')
|
||||
v-row.page-header-section(no-gutters, align-content='center', style='height: 90px;')
|
||||
v-col.page-col-content.is-page-header(
|
||||
:offset-xl='tocPosition === `left` ? 2 : 0'
|
||||
:offset-lg='tocPosition === `left` ? 3 : 0'
|
||||
:xl='tocPosition === `right` ? 10 : false'
|
||||
:lg='tocPosition === `right` ? 9 : false'
|
||||
style='margin-top: auto; margin-bottom: auto;'
|
||||
:class='$vuetify.rtl ? `pr-4` : `pl-4`'
|
||||
)
|
||||
.page-header-headings
|
||||
.headline.grey--text(:class='$vuetify.theme.dark ? `text--lighten-2` : `text--darken-3`') {{title}}
|
||||
.caption.grey--text.text--darken-1 {{description}}
|
||||
.page-edit-shortcuts(
|
||||
v-if='editShortcutsObj.editMenuBar'
|
||||
:class='tocPosition === `right` ? `is-right` : ``'
|
||||
)
|
||||
v-btn(
|
||||
v-if='editShortcutsObj.editMenuBtn'
|
||||
@click='pageEdit'
|
||||
depressed
|
||||
small
|
||||
)
|
||||
v-icon.mr-2(small) mdi-pencil
|
||||
span.text-none {{$t(`common:actions.edit`)}}
|
||||
v-btn(
|
||||
v-if='editShortcutsObj.editMenuExternalBtn'
|
||||
:href='editMenuExternalUrl'
|
||||
target='_blank'
|
||||
depressed
|
||||
small
|
||||
)
|
||||
v-icon.mr-2(small) {{ editShortcutsObj.editMenuExternalIcon }}
|
||||
span.text-none {{$t(`common:page.editExternal`, { name: editShortcutsObj.editMenuExternalName })}}
|
||||
v-divider
|
||||
v-container.pl-5.pt-4(fluid, grid-list-xl)
|
||||
v-layout(row)
|
||||
v-flex.page-col-sd(
|
||||
v-if='tocPosition !== `off` && $vuetify.breakpoint.lgAndUp'
|
||||
:order-xs1='tocPosition !== `right`'
|
||||
:order-xs2='tocPosition === `right`'
|
||||
lg3
|
||||
xl2
|
||||
)
|
||||
v-card.page-toc-card.mb-5(v-if='tocDecoded.length')
|
||||
.overline.pa-5.pb-0(:class='$vuetify.theme.dark ? `blue--text text--lighten-2` : `primary--text`') {{$t('common:page.toc')}}
|
||||
v-list.pb-3(dense, nav, :class='$vuetify.theme.dark ? `darken-3-d3` : ``')
|
||||
template(v-for='(tocItem, tocIdx) in tocDecoded')
|
||||
v-list-item(@click='$vuetify.goTo(tocItem.anchor, scrollOpts)')
|
||||
v-icon(color='grey', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
|
||||
v-list-item-title.px-3 {{tocItem.title}}
|
||||
//- v-divider(v-if='tocIdx < toc.length - 1 || tocItem.children.length')
|
||||
template(v-for='tocSubItem in tocItem.children')
|
||||
v-list-item(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)')
|
||||
v-icon.px-3(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
|
||||
v-list-item-title.px-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-1`') {{tocSubItem.title}}
|
||||
//- v-divider(inset, v-if='tocIdx < toc.length - 1')
|
||||
|
||||
v-card.page-tags-card.mb-5(v-if='tags.length > 0')
|
||||
.pa-5
|
||||
.overline.teal--text.pb-2(:class='$vuetify.theme.dark ? `text--lighten-3` : ``') {{$t('common:page.tags')}}
|
||||
v-chip.mr-1.mb-1(
|
||||
label
|
||||
:color='$vuetify.theme.dark ? `teal darken-1` : `teal lighten-5`'
|
||||
v-for='(tag, idx) in tags'
|
||||
:href='`/t/` + tag.tag'
|
||||
:key='`tag-` + tag.tag'
|
||||
)
|
||||
v-icon(:color='$vuetify.theme.dark ? `teal lighten-3` : `teal`', left, small) mdi-tag
|
||||
span(:class='$vuetify.theme.dark ? `teal--text text--lighten-5` : `teal--text text--darken-2`') {{tag.title}}
|
||||
v-chip.mr-1.mb-1(
|
||||
label
|
||||
:color='$vuetify.theme.dark ? `teal darken-1` : `teal lighten-5`'
|
||||
:href='`/t/` + tags.map(t => t.tag).join(`/`)'
|
||||
:aria-label='$t(`common:page.tagsMatching`)'
|
||||
)
|
||||
v-icon(:color='$vuetify.theme.dark ? `teal lighten-3` : `teal`', size='20') mdi-tag-multiple
|
||||
|
||||
v-card.page-comments-card.mb-5(v-if='commentsEnabled && commentsPerms.read')
|
||||
.pa-5
|
||||
.overline.pb-2.blue-grey--text.d-flex.align-center(:class='$vuetify.theme.dark ? `text--lighten-3` : `text--darken-2`')
|
||||
span {{$t('common:comments.sdTitle')}}
|
||||
//- v-spacer
|
||||
//- v-chip.text-center(
|
||||
//- v-if='!commentsExternal'
|
||||
//- label
|
||||
//- x-small
|
||||
//- :color='$vuetify.theme.dark ? `blue-grey darken-3` : `blue-grey darken-2`'
|
||||
//- dark
|
||||
//- style='min-width: 50px; justify-content: center;'
|
||||
//- )
|
||||
//- span {{commentsCount}}
|
||||
.d-flex
|
||||
v-btn.text-none(
|
||||
@click='goToComments()'
|
||||
:color='$vuetify.theme.dark ? `blue-grey` : `blue-grey darken-2`'
|
||||
outlined
|
||||
style='flex: 1 1 100%;'
|
||||
small
|
||||
)
|
||||
span.blue-grey--text(:class='$vuetify.theme.dark ? `text--lighten-1` : `text--darken-2`') {{$t('common:comments.viewDiscussion')}}
|
||||
v-tooltip(right, v-if='commentsPerms.write')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn.ml-2(
|
||||
@click='goToComments(true)'
|
||||
v-on='on'
|
||||
outlined
|
||||
small
|
||||
:color='$vuetify.theme.dark ? `blue-grey` : `blue-grey darken-2`'
|
||||
:aria-label='$t(`common:comments.newComment`)'
|
||||
)
|
||||
v-icon(:color='$vuetify.theme.dark ? `blue-grey lighten-1` : `blue-grey darken-2`', dense) mdi-comment-plus
|
||||
span {{$t('common:comments.newComment')}}
|
||||
|
||||
v-card.page-author-card.mb-5
|
||||
.pa-5
|
||||
.overline.indigo--text.d-flex(:class='$vuetify.theme.dark ? `text--lighten-3` : ``')
|
||||
span {{$t('common:page.lastEditedBy')}}
|
||||
v-spacer
|
||||
v-tooltip(right, v-if='isAuthenticated')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn.btn-animate-edit(
|
||||
icon
|
||||
:href='"/h/" + locale + "/" + path'
|
||||
v-on='on'
|
||||
x-small
|
||||
v-if='hasReadHistoryPermission'
|
||||
:aria-label='$t(`common:header.history`)'
|
||||
)
|
||||
v-icon(color='indigo', dense) mdi-history
|
||||
span {{$t('common:header.history')}}
|
||||
.page-author-card-name.body-2.grey--text(:class='$vuetify.theme.dark ? `` : `text--darken-3`') {{ authorName }}
|
||||
.page-author-card-date.caption.grey--text.text--darken-1 {{ updatedAt | moment('calendar') }}
|
||||
|
||||
//- v-card.mb-5
|
||||
//- .pa-5
|
||||
//- .overline.pb-2.yellow--text(:class='$vuetify.theme.dark ? `text--darken-3` : `text--darken-4`') Rating
|
||||
//- .text-center
|
||||
//- v-rating(
|
||||
//- v-model='rating'
|
||||
//- color='yellow darken-3'
|
||||
//- background-color='grey lighten-1'
|
||||
//- half-increments
|
||||
//- hover
|
||||
//- )
|
||||
//- .caption.grey--text 5 votes
|
||||
|
||||
v-card.page-shortcuts-card(flat)
|
||||
v-toolbar(:color='$vuetify.theme.dark ? `grey darken-4-d3` : `grey lighten-3`', flat, dense)
|
||||
v-spacer
|
||||
//- v-tooltip(bottom)
|
||||
//- template(v-slot:activator='{ on }')
|
||||
//- v-btn(icon, tile, v-on='on', :aria-label='$t(`common:page.bookmark`)'): v-icon(color='grey') mdi-bookmark
|
||||
//- span {{$t('common:page.bookmark')}}
|
||||
v-menu(offset-y, bottom, min-width='300')
|
||||
template(v-slot:activator='{ on: menu }')
|
||||
v-tooltip(bottom)
|
||||
template(v-slot:activator='{ on: tooltip }')
|
||||
v-btn(icon, tile, v-on='{ ...menu, ...tooltip }', :aria-label='$t(`common:page.share`)'): v-icon(color='grey') mdi-share-variant
|
||||
span {{$t('common:page.share')}}
|
||||
social-sharing(
|
||||
:url='pageUrl'
|
||||
:title='title'
|
||||
:description='description'
|
||||
)
|
||||
v-tooltip(bottom)
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(icon, tile, v-on='on', @click='print', :aria-label='$t(`common:page.printFormat`)')
|
||||
v-icon(:color='printView ? `primary` : `grey`') mdi-printer
|
||||
span {{$t('common:page.printFormat')}}
|
||||
v-spacer
|
||||
|
||||
v-flex.page-col-content(
|
||||
xs12
|
||||
:lg9='tocPosition !== `off`'
|
||||
:xl10='tocPosition !== `off`'
|
||||
:order-xs1='tocPosition === `right`'
|
||||
:order-xs2='tocPosition !== `right`'
|
||||
)
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasAnyPagePermissions && editShortcutsObj.editFab')
|
||||
template(v-slot:activator='{ on: onEditActivator }')
|
||||
v-speed-dial(
|
||||
v-model='pageEditFab'
|
||||
direction='top'
|
||||
open-on-hover
|
||||
transition='scale-transition'
|
||||
bottom
|
||||
:right='!$vuetify.rtl'
|
||||
:left='$vuetify.rtl'
|
||||
fixed
|
||||
dark
|
||||
)
|
||||
template(v-slot:activator)
|
||||
v-btn.btn-animate-edit(
|
||||
fab
|
||||
color='primary'
|
||||
v-model='pageEditFab'
|
||||
@click='pageEdit'
|
||||
v-on='onEditActivator'
|
||||
:disabled='!hasWritePagesPermission'
|
||||
:aria-label='$t(`common:page.editPage`)'
|
||||
)
|
||||
v-icon mdi-pencil
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasReadHistoryPermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
small
|
||||
color='white'
|
||||
light
|
||||
v-on='on'
|
||||
@click='pageHistory'
|
||||
)
|
||||
v-icon(size='20') mdi-history
|
||||
span {{$t('common:header.history')}}
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasReadSourcePermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
small
|
||||
color='white'
|
||||
light
|
||||
v-on='on'
|
||||
@click='pageSource'
|
||||
)
|
||||
v-icon(size='20') mdi-code-tags
|
||||
span {{$t('common:header.viewSource')}}
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasWritePagesPermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
small
|
||||
color='white'
|
||||
light
|
||||
v-on='on'
|
||||
@click='pageConvert'
|
||||
)
|
||||
v-icon(size='20') mdi-lightning-bolt
|
||||
span {{$t('common:header.convert')}}
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasWritePagesPermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
small
|
||||
color='white'
|
||||
light
|
||||
v-on='on'
|
||||
@click='pageDuplicate'
|
||||
)
|
||||
v-icon(size='20') mdi-content-duplicate
|
||||
span {{$t('common:header.duplicate')}}
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasManagePagesPermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
small
|
||||
color='white'
|
||||
light
|
||||
v-on='on'
|
||||
@click='pageMove'
|
||||
)
|
||||
v-icon(size='20') mdi-content-save-move-outline
|
||||
span {{$t('common:header.move')}}
|
||||
v-tooltip(:right='$vuetify.rtl', :left='!$vuetify.rtl', v-if='hasDeletePagesPermission')
|
||||
template(v-slot:activator='{ on }')
|
||||
v-btn(
|
||||
fab
|
||||
dark
|
||||
small
|
||||
color='red'
|
||||
v-on='on'
|
||||
@click='pageDelete'
|
||||
)
|
||||
v-icon(size='20') mdi-trash-can-outline
|
||||
span {{$t('common:header.delete')}}
|
||||
span {{$t('common:page.editPage')}}
|
||||
v-alert.mb-5(v-if='!isPublished', color='red', outlined, icon='mdi-minus-circle', dense)
|
||||
.caption {{$t('common:page.unpublishedWarning')}}
|
||||
.contents(ref='container')
|
||||
slot(name='contents')
|
||||
.comments-container#discussion(v-if='commentsEnabled && commentsPerms.read && !printView')
|
||||
.comments-header
|
||||
v-icon.mr-2(dark) mdi-comment-text-outline
|
||||
span {{$t('common:comments.title')}}
|
||||
.comments-main
|
||||
slot(name='comments')
|
||||
nav-footer
|
||||
notify
|
||||
search-results
|
||||
v-fab-transition
|
||||
v-btn(
|
||||
v-if='upBtnShown'
|
||||
fab
|
||||
fixed
|
||||
bottom
|
||||
:right='$vuetify.rtl'
|
||||
:left='!$vuetify.rtl'
|
||||
small
|
||||
:depressed='this.$vuetify.breakpoint.mdAndUp'
|
||||
@click='$vuetify.goTo(0, scrollOpts)'
|
||||
color='primary'
|
||||
dark
|
||||
:style='upBtnPosition'
|
||||
:aria-label='$t(`common:actions.returnToTop`)'
|
||||
)
|
||||
v-icon mdi-arrow-up
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { StatusIndicator } from 'vue-status-indicator'
|
||||
import Tabset from './tabset.vue'
|
||||
import NavSidebar from './nav-sidebar.vue'
|
||||
import Prism from 'prismjs'
|
||||
import mermaid from 'mermaid'
|
||||
import { get, sync } from 'vuex-pathify'
|
||||
import _ from 'lodash'
|
||||
import ClipboardJS from 'clipboard'
|
||||
import Vue from 'vue'
|
||||
|
||||
/* global siteLangs */
|
||||
|
||||
Vue.component('Tabset', Tabset)
|
||||
|
||||
Prism.plugins.autoloader.languages_path = '/_assets/js/prism/'
|
||||
Prism.plugins.NormalizeWhitespace.setDefaults({
|
||||
'remove-trailing': true,
|
||||
'remove-indent': true,
|
||||
'left-trim': true,
|
||||
'right-trim': true,
|
||||
'remove-initial-line-feed': true,
|
||||
'tabs-to-spaces': 2
|
||||
})
|
||||
Prism.plugins.toolbar.registerButton('copy-to-clipboard', (env) => {
|
||||
let linkCopy = document.createElement('button')
|
||||
linkCopy.textContent = 'Copy'
|
||||
|
||||
const clip = new ClipboardJS(linkCopy, {
|
||||
text: () => { return env.code }
|
||||
})
|
||||
|
||||
clip.on('success', () => {
|
||||
linkCopy.textContent = 'Copied!'
|
||||
resetClipboardText()
|
||||
})
|
||||
clip.on('error', () => {
|
||||
linkCopy.textContent = 'Press Ctrl+C to copy'
|
||||
resetClipboardText()
|
||||
})
|
||||
|
||||
return linkCopy
|
||||
|
||||
function resetClipboardText() {
|
||||
setTimeout(() => {
|
||||
linkCopy.textContent = 'Copy'
|
||||
}, 5000)
|
||||
}
|
||||
})
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NavSidebar,
|
||||
StatusIndicator
|
||||
},
|
||||
props: {
|
||||
pageId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
locale: {
|
||||
type: String,
|
||||
default: 'en'
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
default: 'home'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Untitled Page'
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
createdAt: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
updatedAt: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
tags: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
authorName: {
|
||||
type: String,
|
||||
default: 'Unknown'
|
||||
},
|
||||
authorId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
editor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isPublished: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
toc: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
sidebar: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
navMode: {
|
||||
type: String,
|
||||
default: 'MIXED'
|
||||
},
|
||||
commentsEnabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
effectivePermissions: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
commentsExternal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
editShortcuts: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
filename: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
locales: siteLangs,
|
||||
navShown: false,
|
||||
navExpanded: false,
|
||||
upBtnShown: false,
|
||||
pageEditFab: false,
|
||||
scrollOpts: {
|
||||
duration: 1500,
|
||||
offset: 0,
|
||||
easing: 'easeInOutCubic'
|
||||
},
|
||||
scrollStyle: {
|
||||
vuescroll: {},
|
||||
scrollPanel: {
|
||||
initialScrollX: 0.01, // fix scrollbar not disappearing on load
|
||||
scrollingX: false,
|
||||
speed: 50
|
||||
},
|
||||
rail: {
|
||||
gutterOfEnds: '2px'
|
||||
},
|
||||
bar: {
|
||||
onlyShowBarOnScroll: false,
|
||||
background: '#42A5F5',
|
||||
hoverStyle: {
|
||||
background: '#64B5F6'
|
||||
}
|
||||
}
|
||||
},
|
||||
winWidth: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAuthenticated: get('user/authenticated'),
|
||||
commentsCount: get('page/commentsCount'),
|
||||
commentsPerms: get('page/effectivePermissions@comments'),
|
||||
editShortcutsObj: get('page/editShortcuts'),
|
||||
rating: {
|
||||
get () {
|
||||
return 3.5
|
||||
},
|
||||
set (val) {
|
||||
|
||||
}
|
||||
},
|
||||
breadcrumbs() {
|
||||
return [{ path: '/', name: 'Home' }].concat(
|
||||
_.reduce(this.path.split('/'), (result, value) => {
|
||||
result.push({
|
||||
path: _.get(_.last(result), 'path', this.locales.length > 0 ? `/${this.locale}` : '') + `/${value}`,
|
||||
name: value
|
||||
})
|
||||
return result
|
||||
}, []))
|
||||
},
|
||||
pageUrl () { return window.location.href },
|
||||
upBtnPosition () {
|
||||
if (this.$vuetify.breakpoint.mdAndUp) {
|
||||
return this.$vuetify.rtl ? `right: 235px;` : `left: 235px;`
|
||||
} else {
|
||||
return this.$vuetify.rtl ? `right: 65px;` : `left: 65px;`
|
||||
}
|
||||
},
|
||||
sidebarDecoded () {
|
||||
return JSON.parse(Buffer.from(this.sidebar, 'base64').toString())
|
||||
},
|
||||
tocDecoded () {
|
||||
return JSON.parse(Buffer.from(this.toc, 'base64').toString())
|
||||
},
|
||||
tocPosition: get('site/tocPosition'),
|
||||
hasAdminPermission: get('page/effectivePermissions@system.manage'),
|
||||
hasWritePagesPermission: get('page/effectivePermissions@pages.write'),
|
||||
hasManagePagesPermission: get('page/effectivePermissions@pages.manage'),
|
||||
hasDeletePagesPermission: get('page/effectivePermissions@pages.delete'),
|
||||
hasReadSourcePermission: get('page/effectivePermissions@source.read'),
|
||||
hasReadHistoryPermission: get('page/effectivePermissions@history.read'),
|
||||
hasAnyPagePermissions () {
|
||||
return this.hasAdminPermission || this.hasWritePagesPermission || this.hasManagePagesPermission ||
|
||||
this.hasDeletePagesPermission || this.hasReadSourcePermission || this.hasReadHistoryPermission
|
||||
},
|
||||
printView: sync('site/printView'),
|
||||
editMenuExternalUrl () {
|
||||
if (this.editShortcutsObj.editMenuBar && this.editShortcutsObj.editMenuExternalBtn) {
|
||||
return this.editShortcutsObj.editMenuExternalUrl.replace('{filename}', this.filename)
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.set('page/authorId', this.authorId)
|
||||
this.$store.set('page/authorName', this.authorName)
|
||||
this.$store.set('page/createdAt', this.createdAt)
|
||||
this.$store.set('page/description', this.description)
|
||||
this.$store.set('page/isPublished', this.isPublished)
|
||||
this.$store.set('page/id', this.pageId)
|
||||
this.$store.set('page/locale', this.locale)
|
||||
this.$store.set('page/path', this.path)
|
||||
this.$store.set('page/tags', this.tags)
|
||||
this.$store.set('page/title', this.title)
|
||||
this.$store.set('page/editor', this.editor)
|
||||
this.$store.set('page/updatedAt', this.updatedAt)
|
||||
if (this.effectivePermissions) {
|
||||
this.$store.set('page/effectivePermissions', JSON.parse(Buffer.from(this.effectivePermissions, 'base64').toString()))
|
||||
}
|
||||
if (this.editShortcuts) {
|
||||
this.$store.set('page/editShortcuts', JSON.parse(Buffer.from(this.editShortcuts, 'base64').toString()))
|
||||
}
|
||||
|
||||
this.$store.set('page/mode', 'view')
|
||||
},
|
||||
mounted () {
|
||||
if (this.$vuetify.theme.dark) {
|
||||
this.scrollStyle.bar.background = '#424242'
|
||||
}
|
||||
|
||||
// -> Check side navigation visibility
|
||||
this.handleSideNavVisibility()
|
||||
window.addEventListener('resize', _.debounce(() => {
|
||||
this.handleSideNavVisibility()
|
||||
}, 500))
|
||||
|
||||
// -> Highlight Code Blocks
|
||||
Prism.highlightAllUnder(this.$refs.container)
|
||||
|
||||
// -> Render Mermaid diagrams
|
||||
mermaid.mermaidAPI.initialize({
|
||||
startOnLoad: true,
|
||||
theme: this.$vuetify.theme.dark ? `dark` : `default`
|
||||
})
|
||||
|
||||
// -> Handle anchor scrolling
|
||||
if (window.location.hash && window.location.hash.length > 1) {
|
||||
if (document.readyState === 'complete') {
|
||||
this.$nextTick(() => {
|
||||
this.$vuetify.goTo(decodeURIComponent(window.location.hash), this.scrollOpts)
|
||||
})
|
||||
} else {
|
||||
window.addEventListener('load', () => {
|
||||
this.$vuetify.goTo(decodeURIComponent(window.location.hash), this.scrollOpts)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// -> Handle anchor links within the page contents
|
||||
this.$nextTick(() => {
|
||||
this.$refs.container.querySelectorAll(`a[href^="#"], a[href^="${window.location.href.replace(window.location.hash, '')}#"]`).forEach(el => {
|
||||
el.onclick = ev => {
|
||||
ev.preventDefault()
|
||||
ev.stopPropagation()
|
||||
this.$vuetify.goTo(decodeURIComponent(ev.currentTarget.hash), this.scrollOpts)
|
||||
}
|
||||
})
|
||||
|
||||
window.boot.notify('page-ready')
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
goHome () {
|
||||
if (this.locales && this.locales.length > 0) {
|
||||
window.location.assign(`/${this.locale}/home`)
|
||||
} else {
|
||||
window.location.assign('/')
|
||||
}
|
||||
},
|
||||
toggleNavigation () {
|
||||
this.navOpen = !this.navOpen
|
||||
},
|
||||
upBtnScroll () {
|
||||
const scrollOffset = window.pageYOffset || document.documentElement.scrollTop
|
||||
this.upBtnShown = scrollOffset > window.innerHeight * 0.33
|
||||
},
|
||||
print () {
|
||||
if (this.printView) {
|
||||
this.printView = false
|
||||
} else {
|
||||
this.printView = true
|
||||
this.$nextTick(() => {
|
||||
window.print()
|
||||
})
|
||||
}
|
||||
},
|
||||
pageEdit () {
|
||||
this.$root.$emit('pageEdit')
|
||||
},
|
||||
pageHistory () {
|
||||
this.$root.$emit('pageHistory')
|
||||
},
|
||||
pageSource () {
|
||||
this.$root.$emit('pageSource')
|
||||
},
|
||||
pageConvert () {
|
||||
this.$root.$emit('pageConvert')
|
||||
},
|
||||
pageDuplicate () {
|
||||
this.$root.$emit('pageDuplicate')
|
||||
},
|
||||
pageMove () {
|
||||
this.$root.$emit('pageMove')
|
||||
},
|
||||
pageDelete () {
|
||||
this.$root.$emit('pageDelete')
|
||||
},
|
||||
handleSideNavVisibility () {
|
||||
if (window.innerWidth === this.winWidth) { return }
|
||||
this.winWidth = window.innerWidth
|
||||
if (this.$vuetify.breakpoint.mdAndUp) {
|
||||
this.navShown = true
|
||||
} else {
|
||||
this.navShown = false
|
||||
}
|
||||
},
|
||||
goToComments (focusNewComment = false) {
|
||||
this.$vuetify.goTo('#discussion', this.scrollOpts)
|
||||
if (focusNewComment) {
|
||||
document.querySelector('#discussion-new').focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.breadcrumbs-nav {
|
||||
.v-btn {
|
||||
min-width: 0;
|
||||
&__content {
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
.v-breadcrumbs__divider:nth-child(2n) {
|
||||
padding: 0 6px;
|
||||
}
|
||||
.v-breadcrumbs__divider:nth-child(2) {
|
||||
padding: 0 6px 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-col-sd {
|
||||
margin-top: -90px;
|
||||
align-self: flex-start;
|
||||
position: sticky;
|
||||
top: 64px;
|
||||
max-height: calc(100vh - 64px);
|
||||
overflow-y: auto;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
|
||||
.page-col-sd::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-header-section {
|
||||
position: relative;
|
||||
|
||||
> .is-page-header {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-header-headings {
|
||||
min-height: 52px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-edit-shortcuts {
|
||||
position: absolute;
|
||||
bottom: -33px;
|
||||
right: 10px;
|
||||
|
||||
.v-btn {
|
||||
border-right: 1px solid #DDD !important;
|
||||
border-bottom: 1px solid #DDD !important;
|
||||
border-radius: 0;
|
||||
color: #777;
|
||||
background-color: #FFF !important;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background-color: #222 !important;
|
||||
border-right-color: #444 !important;
|
||||
border-bottom-color: #444 !important;
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
.v-icon {
|
||||
color: mc('blue', '700');
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -0,0 +1,209 @@
|
||||
<template lang="pug">
|
||||
.tabset.elevation-2
|
||||
ul.tabset-tabs(ref='tabs', role='tablist')
|
||||
slot(name='tabs')
|
||||
.tabset-content(ref='content')
|
||||
slot(name='content')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { customAlphabet } from 'nanoid/non-secure'
|
||||
|
||||
const nanoid = customAlphabet('1234567890abcdef', 10)
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentTab: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentTab (newValue, oldValue) {
|
||||
this.setActiveTab()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setActiveTab () {
|
||||
this.$refs.tabs.childNodes.forEach((node, idx) => {
|
||||
if (idx === this.currentTab) {
|
||||
node.className = 'is-active'
|
||||
node.setAttribute('aria-selected', 'true')
|
||||
} else {
|
||||
node.className = ''
|
||||
node.setAttribute('aria-selected', 'false')
|
||||
}
|
||||
})
|
||||
this.$refs.content.childNodes.forEach((node, idx) => {
|
||||
if (idx === this.currentTab) {
|
||||
node.className = 'tabset-panel is-active'
|
||||
node.removeAttribute('hidden')
|
||||
} else {
|
||||
node.className = 'tabset-panel'
|
||||
node.setAttribute('hidden', '')
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// Handle scroll to header on load within hidden tab content
|
||||
if (window.location.hash && window.location.hash.length > 1) {
|
||||
const headerId = decodeURIComponent(window.location.hash)
|
||||
let foundIdx = -1
|
||||
this.$refs.content.childNodes.forEach((node, idx) => {
|
||||
if (node.querySelector(headerId)) {
|
||||
foundIdx = idx
|
||||
}
|
||||
})
|
||||
if (foundIdx >= 0) {
|
||||
this.currentTab = foundIdx
|
||||
}
|
||||
}
|
||||
|
||||
this.setActiveTab()
|
||||
|
||||
const tabRefId = nanoid()
|
||||
|
||||
this.$refs.tabs.childNodes.forEach((node, idx) => {
|
||||
node.setAttribute('id', `${tabRefId}-${idx}`)
|
||||
node.setAttribute('role', 'tab')
|
||||
node.setAttribute('aria-controls', `${tabRefId}-${idx}-tab`)
|
||||
node.setAttribute('tabindex', '0')
|
||||
node.addEventListener('click', ev => {
|
||||
this.currentTab = [].indexOf.call(ev.target.parentNode.children, ev.target)
|
||||
})
|
||||
node.addEventListener('keydown', ev => {
|
||||
if (ev.key === 'ArrowLeft' && idx > 0) {
|
||||
this.currentTab = idx - 1
|
||||
this.$refs.tabs.childNodes[idx - 1].focus()
|
||||
} else if (ev.key === 'ArrowRight' && idx < this.$refs.tabs.childNodes.length - 1) {
|
||||
this.currentTab = idx + 1
|
||||
this.$refs.tabs.childNodes[idx + 1].focus()
|
||||
} else if (ev.key === 'Enter' || ev.key === ' ') {
|
||||
this.currentTab = idx
|
||||
node.focus()
|
||||
} else if (ev.key === 'Home') {
|
||||
this.currentTab = 0
|
||||
ev.preventDefault()
|
||||
ev.target.parentNode.children[0].focus()
|
||||
} else if (ev.key === 'End') {
|
||||
this.currentTab = this.$refs.tabs.childNodes.length - 1
|
||||
ev.preventDefault()
|
||||
ev.target.parentNode.children[this.$refs.tabs.childNodes.length - 1].focus()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.$refs.content.childNodes.forEach((node, idx) => {
|
||||
node.setAttribute('id', `${tabRefId}-${idx}-tab`)
|
||||
node.setAttribute('role', 'tabpanel')
|
||||
node.setAttribute('aria-labelledby', `${tabRefId}-${idx}`)
|
||||
node.setAttribute('tabindex', '0')
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.tabset {
|
||||
border-radius: 5px;
|
||||
margin-top: 10px;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background-color: #292929;
|
||||
}
|
||||
|
||||
> .tabset-tabs {
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
background: linear-gradient(to bottom, #FFF, #FAFAFA);
|
||||
box-shadow: inset 0 -1px 0 0 #DDD;
|
||||
border-radius: 5px 5px 0 0;
|
||||
overflow: auto;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background: linear-gradient(to bottom, #424242, #333);
|
||||
box-shadow: inset 0 -1px 0 0 #555;
|
||||
}
|
||||
|
||||
> li {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
margin-top: 0;
|
||||
cursor: pointer;
|
||||
transition: color 1s ease;
|
||||
border-right: 1px solid #FFF;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 1px;
|
||||
user-select: none;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
border-right-color: #555;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: #FFF;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 17px;
|
||||
padding-top: 13px;
|
||||
color: mc('blue', '700');
|
||||
border-top: 3px solid mc('blue', '700');
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background-color: #292929;
|
||||
color: mc('blue', '300');
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
|
||||
&.is-active {
|
||||
border-right: 1px solid #EEE;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
border-right-color: #555;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(#CCC, .1);
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background-color: rgba(#222, .25);
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: #FFF;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
background-color: #292929;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& + li {
|
||||
border-left: 1px solid #EEE;
|
||||
|
||||
@at-root .theme--dark & {
|
||||
border-left-color: #222;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .tabset-content {
|
||||
.tabset-panel {
|
||||
padding: 2px 16px 16px;
|
||||
display: none;
|
||||
|
||||
&.is-active {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1 @@
|
||||
/* THEME SPECIFIC JAVASCRIPT */
|
||||
@ -0,0 +1,718 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600;700&family=Jost:wght@400;500;600;700&display=swap");
|
||||
|
||||
/* ==========================================================================
|
||||
WESTGATE FOR WIKI.JS
|
||||
Best-effort SCSS theme derived from the live NodeBB theme tokens/patterns.
|
||||
This ports the visual language, not the NodeBB DOM structure.
|
||||
========================================================================== */
|
||||
|
||||
/* =========================================================
|
||||
CORE TOKENS
|
||||
========================================================= */
|
||||
|
||||
$wg-bg: #0f0d12;
|
||||
$wg-panel: #141219;
|
||||
$wg-panel-2: #110f15;
|
||||
$wg-panel-3: #1a161d;
|
||||
$wg-border: #2a252d;
|
||||
$wg-border-soft: rgba(194, 163, 90, 0.1);
|
||||
$wg-border-mid: rgba(194, 163, 90, 0.18);
|
||||
$wg-gold: #c2a35a;
|
||||
$wg-gold-soft: #a8893f;
|
||||
$wg-text: #e6e0d6;
|
||||
$wg-text-soft: #b9b2a6;
|
||||
$wg-text-muted: #9a9086;
|
||||
$wg-plum-hover: #2b232d;
|
||||
$wg-chip: #231b17;
|
||||
|
||||
$wg-danger-bg: rgba(71, 18, 24, 0.72);
|
||||
$wg-danger-border: rgba(153, 58, 58, 0.45);
|
||||
$wg-danger-text: #ddb8b8;
|
||||
|
||||
$wg-link: #d8c28a;
|
||||
$wg-link-hover: #e0c878;
|
||||
$wg-selection: rgba(194, 163, 90, 0.32);
|
||||
|
||||
$wg-font-ui: "Jost", Inter, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
||||
$wg-font-display: "Cinzel", Georgia, "Times New Roman", serif;
|
||||
$wg-font-reading: "Jost", Inter, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
||||
|
||||
$wg-velvet-panel: linear-gradient(
|
||||
100deg,
|
||||
rgba(42, 18, 34, 0.42) 0%,
|
||||
rgba(25, 22, 31, 0.94) 22%,
|
||||
rgba(18, 16, 23, 0.98) 58%,
|
||||
rgba(14, 13, 18, 0.96) 100%
|
||||
);
|
||||
|
||||
$wg-velvet-panel-hover: linear-gradient(
|
||||
100deg,
|
||||
rgba(58, 24, 48, 0.52) 0%,
|
||||
rgba(30, 25, 38, 0.98) 24%,
|
||||
rgba(20, 18, 27, 1) 62%,
|
||||
rgba(15, 14, 20, 0.98) 100%
|
||||
);
|
||||
|
||||
$wg-velvet-border: rgba(194, 163, 90, 0.13);
|
||||
$wg-velvet-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.025),
|
||||
inset 0 0 34px rgba(96, 32, 68, 0.1),
|
||||
0 10px 26px rgba(0, 0, 0, 0.22);
|
||||
|
||||
@mixin velvet-panel {
|
||||
background: $wg-velvet-panel !important;
|
||||
border: 1px solid $wg-velvet-border !important;
|
||||
box-shadow: $wg-velvet-shadow !important;
|
||||
}
|
||||
|
||||
@mixin velvet-panel-hover {
|
||||
background: $wg-velvet-panel-hover !important;
|
||||
border-color: rgba(194, 163, 90, 0.2) !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.035),
|
||||
inset 0 0 38px rgba(120, 36, 84, 0.13),
|
||||
0 12px 30px rgba(0, 0, 0, 0.28) !important;
|
||||
}
|
||||
|
||||
@mixin gold-chip {
|
||||
background: $wg-chip !important;
|
||||
color: $wg-link !important;
|
||||
border: 1px solid rgba(194, 163, 90, 0.2) !important;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
@mixin display-heading {
|
||||
font-family: $wg-font-display !important;
|
||||
font-weight: 600 !important;
|
||||
letter-spacing: 0.036em !important;
|
||||
text-shadow:
|
||||
0 1px 0 rgba(0, 0, 0, 0.9),
|
||||
0 0 10px rgba(104, 32, 76, 0.18);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
ROOT / BASE
|
||||
========================================================= */
|
||||
|
||||
:root {
|
||||
--wg-bg: #{$wg-bg};
|
||||
--wg-panel: #{$wg-panel};
|
||||
--wg-panel-2: #{$wg-panel-2};
|
||||
--wg-panel-3: #{$wg-panel-3};
|
||||
--wg-border: #{$wg-border};
|
||||
--wg-border-soft: #{$wg-border-soft};
|
||||
--wg-border-mid: #{$wg-border-mid};
|
||||
--wg-gold: #{$wg-gold};
|
||||
--wg-gold-soft: #{$wg-gold-soft};
|
||||
--wg-text: #{$wg-text};
|
||||
--wg-text-soft: #{$wg-text-soft};
|
||||
--wg-text-muted: #{$wg-text-muted};
|
||||
--wg-chip: #{$wg-chip};
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
background: $wg-bg !important;
|
||||
color: $wg-text-soft !important;
|
||||
font-family: $wg-font-ui !important;
|
||||
}
|
||||
|
||||
body,
|
||||
.v-application {
|
||||
font-family: $wg-font-ui !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: $wg-selection;
|
||||
color: #fff4dd;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
GLOBAL TEXT
|
||||
========================================================= */
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
.page-col-sd h2,
|
||||
.v-toolbar__title,
|
||||
.contents-header,
|
||||
.page-header,
|
||||
.page-title {
|
||||
@include display-heading;
|
||||
color: $wg-text !important;
|
||||
}
|
||||
|
||||
h1 { font-size: clamp(1.9rem, 2.7vw, 2.45rem); }
|
||||
h2 { font-size: clamp(1.45rem, 2.1vw, 1.85rem); }
|
||||
h3 { font-size: clamp(1.18rem, 1.6vw, 1.4rem); }
|
||||
|
||||
p,
|
||||
li,
|
||||
td,
|
||||
th,
|
||||
label,
|
||||
.v-label,
|
||||
.caption,
|
||||
.subtitle-1,
|
||||
.subtitle-2 {
|
||||
color: $wg-text-soft !important;
|
||||
font-family: $wg-font-reading !important;
|
||||
}
|
||||
|
||||
small,
|
||||
.text--secondary,
|
||||
.theme--dark.v-application .text--secondary,
|
||||
.theme--light.v-application .text--secondary,
|
||||
.breadcrumbs,
|
||||
.v-breadcrumbs__item,
|
||||
.v-breadcrumbs__divider {
|
||||
color: $wg-text-muted !important;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $wg-link !important;
|
||||
text-decoration-color: rgba(216, 194, 138, 0.35);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $wg-link-hover !important;
|
||||
text-decoration-color: rgba(224, 200, 120, 0.65);
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
APP CHROME
|
||||
========================================================= */
|
||||
|
||||
.v-application,
|
||||
.application--wrap,
|
||||
.v-main,
|
||||
.v-content,
|
||||
.v-content__wrap {
|
||||
background: $wg-bg !important;
|
||||
}
|
||||
|
||||
.v-app-bar,
|
||||
.v-toolbar,
|
||||
header,
|
||||
nav {
|
||||
background: linear-gradient(to bottom, rgba(20, 18, 25, 0.96), rgba(16, 14, 20, 0.98)) !important;
|
||||
border-bottom: 1px solid $wg-velvet-border !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.02),
|
||||
0 8px 18px rgba(0, 0, 0, 0.18) !important;
|
||||
}
|
||||
|
||||
.v-toolbar__title,
|
||||
nav .title,
|
||||
header .title {
|
||||
color: $wg-text !important;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.v-navigation-drawer,
|
||||
aside,
|
||||
.page-col-sd,
|
||||
.sidebar {
|
||||
background: #121015 !important;
|
||||
border-color: $wg-border !important;
|
||||
box-shadow: inset -1px 0 0 rgba(194, 163, 90, 0.12) !important;
|
||||
}
|
||||
|
||||
.v-navigation-drawer .v-list,
|
||||
.v-navigation-drawer .v-list-item,
|
||||
.v-list,
|
||||
aside .menu,
|
||||
.sidebar .menu {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.v-navigation-drawer .v-list-item,
|
||||
.v-list-item,
|
||||
aside .menu li,
|
||||
.sidebar .menu li,
|
||||
.sidebar a {
|
||||
border-radius: 8px;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
border-color 0.2s ease,
|
||||
color 0.2s ease,
|
||||
box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.v-navigation-drawer .v-list-item,
|
||||
.v-list-item {
|
||||
margin-bottom: 0.35rem;
|
||||
background: $wg-panel-3 !important;
|
||||
border: 1px solid $wg-border !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.v-navigation-drawer .v-list-item:hover,
|
||||
.v-list-item:hover,
|
||||
.v-list-item--active,
|
||||
.v-list-item--link:hover {
|
||||
background: $wg-plum-hover !important;
|
||||
color: #f0e6d8 !important;
|
||||
border-color: $wg-gold !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05),
|
||||
inset 0 -1px 0 rgba(0, 0, 0, 0.35),
|
||||
0 0 8px rgba(194, 163, 90, 0.18);
|
||||
}
|
||||
|
||||
.v-list-item__icon .v-icon,
|
||||
.v-navigation-drawer .v-icon {
|
||||
color: $wg-gold !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
PAGE SURFACES
|
||||
========================================================= */
|
||||
|
||||
.page-col-content,
|
||||
.page-content,
|
||||
.page-editor,
|
||||
.page-history,
|
||||
.page-properties,
|
||||
.v-card,
|
||||
.card,
|
||||
.theme--dark.v-card,
|
||||
.theme--light.v-card,
|
||||
.v-sheet,
|
||||
.editor-markdown-container,
|
||||
.editor-visual-container,
|
||||
.page-block,
|
||||
.page-section {
|
||||
@include velvet-panel;
|
||||
border-radius: 10px !important;
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
.v-card:hover,
|
||||
.card:hover,
|
||||
.page-block:hover,
|
||||
.page-section:hover {
|
||||
@include velvet-panel-hover;
|
||||
}
|
||||
|
||||
.page-col-content,
|
||||
.page-content,
|
||||
.editor-markdown-container,
|
||||
.editor-visual-container {
|
||||
padding: clamp(1rem, 1.6vw, 1.35rem) !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
PAGE HEADER / BREADCRUMBS
|
||||
========================================================= */
|
||||
|
||||
.v-breadcrumbs,
|
||||
.breadcrumbs,
|
||||
.page-header,
|
||||
.page-meta {
|
||||
background: linear-gradient(90deg, rgba(18, 16, 23, 0.42), rgba(23, 20, 29, 0.24), transparent 82%) !important;
|
||||
border: 1px solid rgba(194, 163, 90, 0.08) !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
.page-header,
|
||||
.page-meta {
|
||||
padding: 0.75rem 0.95rem !important;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
margin-top: 0.7rem;
|
||||
height: 1px;
|
||||
background: linear-gradient(to right, transparent, rgba(194, 163, 90, 0.26), transparent);
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
BUTTONS / CHIPS / TABS
|
||||
========================================================= */
|
||||
|
||||
.v-btn,
|
||||
button,
|
||||
.btn {
|
||||
background: transparent !important;
|
||||
border: 1px solid transparent !important;
|
||||
color: $wg-text-soft !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.v-btn:hover,
|
||||
button:hover,
|
||||
.btn:hover {
|
||||
background: #241e26 !important;
|
||||
border-color: $wg-gold !important;
|
||||
color: $wg-text !important;
|
||||
}
|
||||
|
||||
.v-btn.primary,
|
||||
.v-btn.v-btn--has-bg.primary,
|
||||
.v-btn.blue,
|
||||
.v-btn.indigo,
|
||||
button.primary,
|
||||
.btn-primary,
|
||||
.theme--dark .primary {
|
||||
background: linear-gradient(to bottom, #5a4a1a 0%, #473914 100%) !important;
|
||||
border: 1px solid #a8893f !important;
|
||||
color: #f0e6d8 !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.06),
|
||||
0 2px 8px rgba(0, 0, 0, 0.22) !important;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(to bottom, #6a5720 0%, #53431a 100%) !important;
|
||||
border-color: $wg-gold !important;
|
||||
color: #fff4dd !important;
|
||||
}
|
||||
}
|
||||
|
||||
.v-chip,
|
||||
.v-chip--label,
|
||||
.tag,
|
||||
.badge,
|
||||
.page-tag {
|
||||
@include gold-chip;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.v-tabs,
|
||||
.v-tabs-bar,
|
||||
.v-slide-group__content {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.v-tab {
|
||||
color: $wg-text-muted !important;
|
||||
border-bottom: 1px solid transparent !important;
|
||||
|
||||
&.v-tab--active {
|
||||
color: $wg-link-hover !important;
|
||||
border-bottom-color: rgba(194, 163, 90, 0.55) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
TABLES / LISTS
|
||||
========================================================= */
|
||||
|
||||
table,
|
||||
.v-data-table,
|
||||
.theme--dark.v-data-table,
|
||||
.theme--light.v-data-table {
|
||||
background: transparent !important;
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
thead th,
|
||||
.v-data-table-header th {
|
||||
color: $wg-text !important;
|
||||
font-family: $wg-font-ui !important;
|
||||
border-bottom: 1px solid rgba(194, 163, 90, 0.18) !important;
|
||||
}
|
||||
|
||||
tbody tr,
|
||||
.v-data-table tbody tr {
|
||||
transition: background 0.18s ease, box-shadow 0.18s ease;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(even),
|
||||
.v-data-table tbody tr:nth-child(even) {
|
||||
background: rgba(255, 255, 255, 0.012) !important;
|
||||
}
|
||||
|
||||
tbody tr:hover,
|
||||
.v-data-table tbody tr:hover {
|
||||
background: linear-gradient(to right, rgba(194, 163, 90, 0.075), rgba(194, 163, 90, 0.025) 28%, transparent 100%) !important;
|
||||
box-shadow: inset 2px 0 0 rgba(194, 163, 90, 0.42);
|
||||
}
|
||||
|
||||
ul:not(.v-list):not(.contains-task-list),
|
||||
ol {
|
||||
padding-left: 1.4rem;
|
||||
}
|
||||
|
||||
li::marker {
|
||||
color: $wg-gold-soft;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
FORMS / INPUTS
|
||||
========================================================= */
|
||||
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
.v-input__slot,
|
||||
.v-text-field > .v-input__control > .v-input__slot,
|
||||
.v-textarea > .v-input__control > .v-input__slot,
|
||||
.v-select > .v-input__control > .v-input__slot,
|
||||
.v-autocomplete > .v-input__control > .v-input__slot {
|
||||
background: linear-gradient(to bottom, $wg-panel, $wg-panel-2) !important;
|
||||
border: 1px solid $wg-border !important;
|
||||
color: $wg-text !important;
|
||||
border-radius: 8px !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.025),
|
||||
0 4px 12px rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: #8f877d !important;
|
||||
}
|
||||
|
||||
.v-label,
|
||||
.v-input input,
|
||||
.v-input textarea {
|
||||
color: $wg-text !important;
|
||||
}
|
||||
|
||||
.v-input--is-focused .v-input__slot,
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border-color: rgba(194, 163, 90, 0.42) !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
||||
0 0 0 0.18rem rgba(194, 163, 90, 0.12) !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
CONTENT / READING
|
||||
========================================================= */
|
||||
|
||||
.page-content,
|
||||
.contents,
|
||||
.contents-body,
|
||||
.page-view-mode,
|
||||
.markdown-body,
|
||||
.viewer {
|
||||
color: $wg-text !important;
|
||||
font-family: $wg-font-reading !important;
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.68;
|
||||
letter-spacing: 0.005em;
|
||||
}
|
||||
|
||||
.page-content p,
|
||||
.page-content li,
|
||||
.markdown-body p,
|
||||
.markdown-body li {
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
.page-content h1,
|
||||
.page-content h2,
|
||||
.page-content h3,
|
||||
.page-content h4,
|
||||
.markdown-body h1,
|
||||
.markdown-body h2,
|
||||
.markdown-body h3,
|
||||
.markdown-body h4 {
|
||||
font-family: $wg-font-display !important;
|
||||
color: #e8ded0 !important;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
blockquote,
|
||||
.page-content blockquote,
|
||||
.markdown-body blockquote {
|
||||
background: rgba(35, 27, 23, 0.45) !important;
|
||||
border-left: 3px solid rgba(194, 163, 90, 0.35) !important;
|
||||
border-radius: 6px !important;
|
||||
padding: 0.75rem 0.9rem !important;
|
||||
color: #d9cec0 !important;
|
||||
}
|
||||
|
||||
code,
|
||||
.page-content code,
|
||||
.markdown-body code {
|
||||
background: #1b171d !important;
|
||||
color: $wg-link-hover !important;
|
||||
padding: 0.12rem 0.35rem !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
|
||||
pre,
|
||||
.page-content pre,
|
||||
.markdown-body pre,
|
||||
.cm-editor,
|
||||
.cm-scroller {
|
||||
background: #151219 !important;
|
||||
border: 1px solid $wg-border !important;
|
||||
border-radius: 8px !important;
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
TOC / RIGHT RAIL / INDEX BLOCKS
|
||||
========================================================= */
|
||||
|
||||
.toc,
|
||||
.table-of-contents,
|
||||
.page-toc,
|
||||
.nav-toc,
|
||||
.contents-sidebar,
|
||||
.page-col-sd .v-card {
|
||||
@include velvet-panel;
|
||||
border-radius: 8px !important;
|
||||
}
|
||||
|
||||
.toc a,
|
||||
.table-of-contents a,
|
||||
.page-toc a {
|
||||
color: $wg-text-soft !important;
|
||||
text-decoration: none !important;
|
||||
|
||||
&:hover {
|
||||
color: $wg-link-hover !important;
|
||||
}
|
||||
}
|
||||
|
||||
.toc .active,
|
||||
.table-of-contents .active,
|
||||
.page-toc .active {
|
||||
color: $wg-link-hover !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
ALERTS / CALLOUTS
|
||||
========================================================= */
|
||||
|
||||
.v-alert,
|
||||
.alert,
|
||||
.message,
|
||||
.notification {
|
||||
border-radius: 8px !important;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.025),
|
||||
0 4px 12px rgba(0, 0, 0, 0.18) !important;
|
||||
}
|
||||
|
||||
.v-alert.info,
|
||||
.alert-info,
|
||||
.message.info,
|
||||
.notification.info {
|
||||
background: linear-gradient(to bottom, rgba(20, 18, 25, 0.78), rgba(16, 14, 20, 0.9)) !important;
|
||||
border: 1px solid rgba(194, 163, 90, 0.22) !important;
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
.v-alert.error,
|
||||
.v-alert.warning,
|
||||
.alert-error,
|
||||
.alert-warning {
|
||||
background: linear-gradient(to bottom, $wg-danger-bg, rgba(48, 12, 18, 0.78)) !important;
|
||||
border: 1px solid $wg-danger-border !important;
|
||||
color: $wg-danger-text !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
DIALOGS / MENUS
|
||||
========================================================= */
|
||||
|
||||
.v-menu__content,
|
||||
.v-dialog,
|
||||
.v-dialog > .v-card,
|
||||
.v-sheet.v-card,
|
||||
.v-menu__content .v-list {
|
||||
@include velvet-panel;
|
||||
border-radius: 8px !important;
|
||||
color: $wg-text-soft !important;
|
||||
}
|
||||
|
||||
.v-menu__content .v-list-item:hover,
|
||||
.v-dialog .v-list-item:hover {
|
||||
background: rgba(255, 255, 255, 0.018) !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
DIVIDERS / HR
|
||||
========================================================= */
|
||||
|
||||
hr,
|
||||
.v-divider {
|
||||
border-color: rgba(194, 163, 90, 0.12) !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
LOGIN / AUTH / ADMIN SURFACES
|
||||
========================================================= */
|
||||
|
||||
.login-screen,
|
||||
.auth-screen,
|
||||
.admin-screen,
|
||||
.admin-area .v-card,
|
||||
.page-admin .v-card {
|
||||
@include velvet-panel;
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
|
||||
.login-screen .headline,
|
||||
.auth-screen .headline,
|
||||
.admin-screen .headline {
|
||||
@include display-heading;
|
||||
color: $wg-text !important;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
OPTIONAL WESTGATE NOTE BLOCK
|
||||
========================================================= */
|
||||
|
||||
.wg-category-note,
|
||||
.wg-note-banner,
|
||||
.wg-westgate-note {
|
||||
margin: 10px 0 16px 0;
|
||||
padding: 10px 14px;
|
||||
border-left: 3px solid $wg-gold;
|
||||
background: rgba(20, 18, 25, 0.6);
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
color: $wg-text-soft;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
SMALL SCREEN TUNING
|
||||
========================================================= */
|
||||
|
||||
@media (max-width: 959px) {
|
||||
.page-col-content,
|
||||
.page-content,
|
||||
.editor-markdown-container,
|
||||
.editor-visual-container {
|
||||
padding: 0.95rem !important;
|
||||
}
|
||||
|
||||
h1 { font-size: 1.75rem; }
|
||||
h2 { font-size: 1.4rem; }
|
||||
h3 { font-size: 1.15rem; }
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.v-navigation-drawer,
|
||||
aside,
|
||||
.page-col-sd {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.page-header,
|
||||
.page-meta,
|
||||
.v-breadcrumbs {
|
||||
padding: 0.65rem 0.75rem !important;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
name: Westgate
|
||||
author: vickydotbat
|
||||
site: https://wiki.westgate.pw/
|
||||
version: 1.0.0
|
||||
requirements:
|
||||
minimum: '>= 2.0.0'
|
||||
maximum: '< 3.0.0'
|
||||
props:
|
||||
sdPosition:
|
||||
type: String
|
||||
default: 'left'
|
||||
title: Table of Contents Position
|
||||
hint: Should the content sidebar be shown on the left or right.
|
||||
enum:
|
||||
- 'hidden'
|
||||
- 'left'
|
||||
- 'right'
|
||||
order: 1
|
||||
icon: mdi-border-vertical
|
||||
showTOC:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Table of Contents
|
||||
order: 2
|
||||
showTags:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Page Tags
|
||||
order: 3
|
||||
showTags:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Page Author and Date
|
||||
order: 4
|
||||
showTags:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Page Rating
|
||||
order: 5
|
||||
showSocialBar:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Social Links Bar
|
||||
order: 6
|
||||
showEditSpeedDial:
|
||||
type: Boolean
|
||||
default: true
|
||||
title: Display the Edit Speed Dial
|
||||
hint: Shown in the lower right corner of the page.
|
||||
order: 7
|
||||
|
||||
|
After Width: | Height: | Size: 22 KiB |
Loading…
Reference in new issue