Skip to content

Commit

Permalink
feat: add 2 more nesting levels for toc
Browse files Browse the repository at this point in the history
  • Loading branch information
regevbr committed Jul 12, 2020
1 parent b2aaf51 commit 5da3c08
Show file tree
Hide file tree
Showing 21 changed files with 207 additions and 32 deletions.
37 changes: 37 additions & 0 deletions client/components/admin/admin-theme.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,41 @@
label='H6'
v-bind:value='6'
)
v-radio-group(
row
outlined
persistent-hint
prepend-icon='mdi-serial-port'
v-model='config.tocCollapseLevel'
label='Collapse Heading Level'
hint='The table of contents will collapse headings starting from the selected level. By default, only heading levels from H2 are collapsed.'
)
v-spacer
v-radio(
label='H1'
v-bind:value='1'
)
v-radio(
label='H2'
v-bind:value='2'
)
v-radio(
label='H3'
v-bind:value='3'
)
v-radio(
label='H4'
v-bind:value='4'
)
v-radio(
label='H5'
v-bind:value='5'
)
v-radio(
label='H6'
v-bind:value='6'
)


v-flex(lg6 xs12)
v-card.animated.fadeInUp.wait-p2s
Expand Down Expand Up @@ -189,6 +224,7 @@ export default {
theme: 'default',
darkMode: false,
tocLevel: 2,
tocCollapseLevel: 2,
iconset: '',
injectCSS: '',
injectHead: '',
Expand Down Expand Up @@ -245,6 +281,7 @@ export default {
iconset: this.config.iconset,
darkMode: this.darkMode,
tocLevel: parseInt(this.config.tocLevel, 10),
tocCollapseLevel: parseInt(this.config.tocCollapseLevel, 10),
injectCSS: this.config.injectCSS,
injectHead: this.config.injectHead,
injectBody: this.config.injectBody
Expand Down
15 changes: 14 additions & 1 deletion client/components/editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export default {
type: Number,
default: 0
},
tocCollapseLevel: {
type: Number,
default: 0
},
checkoutDate: {
type: String,
default: new Date().toISOString()
Expand Down Expand Up @@ -195,6 +199,7 @@ export default {
this.savedState.title !== this.$store.get('page/title'),
this.savedState.description !== this.$store.get('page/description'),
this.savedState.tocLevel !== this.$store.get('page/tocLevel'),
this.savedState.tocCollapseLevel !== this.$store.get('page/tocCollapseLevel'),
this.savedState.tags !== this.$store.get('page/tags'),
this.savedState.isPublished !== this.$store.get('page/isPublished'),
this.savedState.publishStartDate !== this.$store.get('page/publishStartDate'),
Expand Down Expand Up @@ -229,6 +234,7 @@ export default {
this.$store.set('page/scriptCss', this.scriptCss)
this.$store.set('page/scriptJs', this.scriptJs)
this.$store.set('page/tocLevel', this.tocLevel)
this.$store.set('page/tocCollapseLevel', this.tocCollapseLevel)
this.$store.set('page/mode', 'edit')
Expand Down Expand Up @@ -310,6 +316,7 @@ export default {
$scriptCss: String
$scriptJs: String
$tocLevel: Int!
$tocCollapseLevel: Int!
$tags: [String]!
$title: String!
) {
Expand All @@ -327,6 +334,7 @@ export default {
scriptCss: $scriptCss
scriptJs: $scriptJs
tocLevel: $tocLevel
tocCollapseLevel: $tocCollapseLevel
tags: $tags
title: $title
) {
Expand Down Expand Up @@ -357,6 +365,7 @@ export default {
scriptCss: this.$store.get('page/scriptCss'),
scriptJs: this.$store.get('page/scriptJs'),
tocLevel: this.$store.get('page/tocLevel'),
tocCollapseLevel: this.$store.get('page/tocCollapseLevel'),
tags: this.$store.get('page/tags'),
title: this.$store.get('page/title')
}
Expand Down Expand Up @@ -417,6 +426,7 @@ export default {
$scriptCss: String
$scriptJs: String
$tocLevel: Int
$tocCollapseLevel: Int
$tags: [String]
$title: String
) {
Expand All @@ -435,6 +445,7 @@ export default {
scriptCss: $scriptCss
scriptJs: $scriptJs
tocLevel: $tocLevel
tocCollapseLevel: $tocCollapseLevel
tags: $tags
title: $title
) {
Expand Down Expand Up @@ -465,6 +476,7 @@ export default {
scriptCss: this.$store.get('page/scriptCss'),
scriptJs: this.$store.get('page/scriptJs'),
tocLevel: this.$store.get('page/tocLevel'),
tocCollapseLevel: this.$store.get('page/tocCollapseLevel'),
tags: this.$store.get('page/tags'),
title: this.$store.get('page/title')
}
Expand Down Expand Up @@ -548,7 +560,8 @@ export default {
title: this.$store.get('page/title'),
css: this.$store.get('page/scriptCss'),
js: this.$store.get('page/scriptJs'),
tocLevel: this.$store.get('page/tocLevel')
tocLevel: this.$store.get('page/tocLevel'),
tocCollapseLevel: this.$store.get('page/tocCollapseLevel')
}
},
injectCustomCss: _.debounce(css => {
Expand Down
39 changes: 39 additions & 0 deletions client/components/editor/editor-modal-properties.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,44 @@
label='H6'
v-bind:value='6'
)
v-radio-group(
row
outlined
persistent-hint
prepend-icon='mdi-serial-port'
v-model='tocCollapseLevel'
label='Collapse Heading Level'
hint='The table of contents will collapse headings starting from the selected level. By default, only heading levels from H2 are collapsed.'
)
v-spacer
v-radio(
label='Global'
v-bind:value='0'
)
v-radio(
label='H1'
v-bind:value='1'
)
v-radio(
label='H2'
v-bind:value='2'
)
v-radio(
label='H3'
v-bind:value='3'
)
v-radio(
label='H4'
v-bind:value='4'
)
v-radio(
label='H5'
v-bind:value='5'
)
v-radio(
label='H6'
v-bind:value='6'
)
v-divider
v-card-text.grey.pt-5(:class='$vuetify.theme.dark ? `darken-3-d5` : `lighten-4`')
.overline.pb-5 {{$t('editor:props.categorization')}}
Expand Down Expand Up @@ -331,6 +369,7 @@ export default {
publishStartDate: sync('page/publishStartDate'),
publishEndDate: sync('page/publishEndDate'),
tocLevel: sync('page/tocLevel'),
tocCollapseLevel: sync('page/tocCollapseLevel'),
scriptJs: sync('page/scriptJs'),
scriptCss: sync('page/scriptCss'),
hasScriptPermission: get('page/[email protected]'),
Expand Down
4 changes: 2 additions & 2 deletions client/graph/admin/theme/theme-mutation-save.gql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mutation($theme: String!, $iconset: String!, $darkMode: Boolean!, $tocLevel: Int!, $injectCSS: String, $injectHead: String, $injectBody: String) {
mutation($theme: String!, $iconset: String!, $darkMode: Boolean!, $tocLevel: Int!, $tocCollapseLevel: Int!, $injectCSS: String, $injectHead: String, $injectBody: String) {
theming {
setConfig(theme: $theme, iconset: $iconset, darkMode: $darkMode, tocLevel: $tocLevel, injectCSS: $injectCSS, injectHead: $injectHead, injectBody: $injectBody) {
setConfig(theme: $theme, iconset: $iconset, darkMode: $darkMode, tocLevel: $tocLevel, tocCollapseLevel: $tocCollapseLevel, injectCSS: $injectCSS, injectHead: $injectHead, injectBody: $injectBody) {
responseResult {
succeeded
errorCode
Expand Down
1 change: 1 addition & 0 deletions client/graph/admin/theme/theme-query-config.gql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ query {
iconset
darkMode
tocLevel
tocCollapseLevel
injectCSS
injectHead
injectBody
Expand Down
3 changes: 2 additions & 1 deletion client/store/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const state = {
updatedAt: '',
mode: '',
scriptJs: '',
tocLevel: 0,
tocLevel: 2,
tocCollapseLevel: 2,
scriptCss: '',
effectivePermissions: {
comments: {
Expand Down
74 changes: 74 additions & 0 deletions client/themes/default/components/page-toc-item.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template lang="pug">
div
v-list-item(@click='click(item.anchor)', v-if='(item.children.length === 0 || tocLevel === level) || tocCollapseLevel > level',
:key='item.anchor', :class='isNestedLevel ? `pl-9` : `pl-6`')
v-icon.pl-0(small, color='grey lighten-1') {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-4(v-bind:class='titleClasses') {{item.title}}
v-list-group(sub-group, v-else, v-bind:class='{"pl-3": isNestedLevel}')
template(v-slot:activator)
v-list-item.pl-0(@click='click(item.anchor)', :key='item.anchor')
v-list-item-title(v-bind:class='titleClasses') {{item.title}}
template(v-if='tocLevel > level', v-for='subItem in item.children')
page-toc-item(:item='subItem', :level='level + 1', :tocLevel='tocLevel', :tocCollapseLevel='tocCollapseLevel')
template(v-if='tocCollapseLevel > level', v-for='subItem in item.children')
page-toc-item(:item='subItem', :level='level + 1', :tocLevel='tocLevel', :tocCollapseLevel='tocCollapseLevel')
</template>

<script>
export default {
name: "pageTocItem",
props: {
item: {
type: Object,
default: () => {}
},
tocLevel: {
type: Number,
default: 2
},
tocCollapseLevel: {
type: Number,
default: 2
},
level: {
type: Number,
default: 1
}
},
data() {
return {
scrollOpts: {
duration: 1500,
offset: 0,
easing: 'easeInOutCubic'
}
}
},
computed: {
isNestedLevel() {
return this.level > 1
},
titleClasses() {
return {
"caption": this.isNestedLevel,
"grey--text": this.isNestedLevel,
"text--lighten-1": this.$vuetify.theme.dark && this.isNestedLevel,
"text--darken-1": !this.$vuetify.theme.dark && this.isNestedLevel
}
},
},
methods: {
click (anchor) {
this.$vuetify.goTo(anchor, this.scrollOpts)
}
}
}
</script>

<style lang='scss'>
// Hack to fix animations of multi level nesting v-list-group
.v-list-group--sub-group.v-list-group--active .v-list-item:not(.v-list-item--active) .v-list-item__icon.v-list-group__header__prepend-icon .v-icon {
transform: rotate(0deg)!important;
}
</style>
35 changes: 9 additions & 26 deletions client/themes/default/components/page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,9 @@
v-flex.page-col-sd(lg3, xl2, v-if='$vuetify.breakpoint.lgAndUp')
v-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 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}}
template(v-for='tocSubItem in tocItem.children', v-if='tocLevel > 1')
v-list-item(@click='$vuetify.goTo(tocSubItem.anchor, scrollOpts)')
v-icon.pl-3(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-3` : `text--darken-4`') {{tocSubItem.title}}
template(v-for='tocSubItem2nd in tocSubItem.children', v-if='tocLevel > 2')
v-list-item(@click='$vuetify.goTo(tocSubItem2nd.anchor, scrollOpts)')
v-icon.pl-6(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-4` : `text--darken-3`') {{tocSubItem2nd.title}}
template(v-for='tocSubItem3rd in tocSubItem2nd.children', v-if='tocLevel > 3')
v-list-item(@click='$vuetify.goTo(tocSubItem3rd.anchor, scrollOpts)')
v-icon.pl-9(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-5` : `text--darken-2`') {{tocSubItem3rd.title}}
template(v-for='tocSubItem4th in tocSubItem3rd.children', v-if='tocLevel > 4')
v-list-item(@click='$vuetify.goTo(tocSubItem4th.anchor, scrollOpts)')
v-icon.pl-12(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-5` : `text--darken-2`') {{tocSubItem4th.title}}
template(v-for='tocSubItem5th in tocSubItem4th.children', v-if='tocLevel > 5')
v-list-item(@click='$vuetify.goTo(tocSubItem5th.anchor, scrollOpts)')
v-icon.pl-15(color='grey lighten-1', small) {{ $vuetify.rtl ? `mdi-chevron-left` : `mdi-chevron-right` }}
v-list-item-title.pl-3.caption.grey--text(:class='$vuetify.theme.dark ? `text--lighten-5` : `text--darken-2`') {{tocSubItem5th.title}}

v-list.py-0(dense, nav, :class='$vuetify.theme.dark ? `darken-3-d3` : ``')
template(v-for='item in tocDecoded')
page-toc-item(:item='item', :tocLevel='tocLevel', :tocCollapseLevel='tocCollapseLevel')
v-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')}}
Expand Down Expand Up @@ -321,6 +298,7 @@
import { StatusIndicator } from 'vue-status-indicator'
import Tabset from './tabset.vue'
import NavSidebar from './nav-sidebar.vue'
import PageTocItem from './page-toc-item.vue'
import Prism from 'prismjs'
import mermaid from 'mermaid'
import { get, sync } from 'vuex-pathify'
Expand Down Expand Up @@ -368,6 +346,7 @@ Prism.plugins.toolbar.registerButton('copy-to-clipboard', (env) => {
export default {
components: {
NavSidebar,
PageTocItem,
StatusIndicator
},
props: {
Expand Down Expand Up @@ -443,6 +422,10 @@ export default {
type: Number,
default: 2
},
tocCollapseLevel: {
type: Number,
default: 2
}
},
data() {
return {
Expand Down
1 change: 1 addition & 0 deletions server/app/data.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ defaults:
iconset: 'md'
darkMode: false
tocLevel: 2
tocCollapseLevel: 2
auth:
autoLogin: false
enforce2FA: false
Expand Down
3 changes: 3 additions & 0 deletions server/controllers/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ router.get('/*', async (req, res, next) => {
}

const tocLevel = page.tocLevel || WIKI.config.theming.tocLevel
const tocCollapseLevel = page.tocCollapseLevel || WIKI.config.theming.tocCollapseLevel

if (req.query.legacy || req.get('user-agent').indexOf('Trident') >= 0) {
// -> Convert page TOC
Expand All @@ -477,6 +478,7 @@ router.get('/*', async (req, res, next) => {
page,
sidebar,
tocLevel,
tocCollapseLevel,
injectCode,
isAuthenticated: req.user && req.user.id !== 2
})
Expand All @@ -503,6 +505,7 @@ router.get('/*', async (req, res, next) => {
page,
sidebar,
tocLevel,
tocCollapseLevel,
injectCode,
comments: WIKI.data.commentProvider,
effectivePermissions
Expand Down
Loading

0 comments on commit 5da3c08

Please sign in to comment.