diff options
Diffstat (limited to 'node_modules/vuepress/lib/default-theme')
27 files changed, 2657 insertions, 0 deletions
diff --git a/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue b/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue new file mode 100644 index 00000000..0334ae0b --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue @@ -0,0 +1,156 @@ +<template> + <form + id="search-form" + class="algolia-search-wrapper search-box" + > + <input + id="algolia-search-input" + class="search-query" + > + </form> +</template> + +<script> +export default { + props: ['options'], + + mounted () { + this.initialize(this.options, this.$lang) + }, + + methods: { + initialize (userOptions, lang) { + Promise.all([ + import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'), + import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css') + ]).then(([docsearch]) => { + docsearch = docsearch.default + const { algoliaOptions = {}} = userOptions + docsearch(Object.assign( + {}, + userOptions, + { + inputSelector: '#algolia-search-input', + // #697 Make docsearch work well at i18n mode. + algoliaOptions: Object.assign({ + 'facetFilters': [`lang:${lang}`].concat(algoliaOptions.facetFilters || []) + }, algoliaOptions) + } + )) + }) + }, + + update (options, lang) { + this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">' + this.initialize(options, lang) + } + }, + + watch: { + $lang (newValue) { + this.update(this.options, newValue) + }, + + options (newValue) { + this.update(newValue, this.$lang) + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.algolia-search-wrapper + & > span + vertical-align middle + .algolia-autocomplete + line-height normal + .ds-dropdown-menu + background-color #fff + border 1px solid #999 + border-radius 4px + font-size 16px + margin 6px 0 0 + padding 4px + text-align left + &:before + border-color #999 + [class*=ds-dataset-] + border none + padding 0 + .ds-suggestions + margin-top 0 + .ds-suggestion + border-bottom 1px solid $borderColor + .algolia-docsearch-suggestion--highlight + color #2c815b + .algolia-docsearch-suggestion + border-color $borderColor + padding 0 + .algolia-docsearch-suggestion--category-header + padding 5px 10px + margin-top 0 + background $accentColor + color #fff + font-weight 600 + .algolia-docsearch-suggestion--highlight + background rgba(255, 255, 255, 0.6) + .algolia-docsearch-suggestion--wrapper + padding 0 + .algolia-docsearch-suggestion--title + font-weight 600 + margin-bottom 0 + color $textColor + .algolia-docsearch-suggestion--subcategory-column + vertical-align top + padding 5px 7px 5px 5px + border-color $borderColor + background #f1f3f5 + &:after + display none + .algolia-docsearch-suggestion--subcategory-column-text + color #555 + .algolia-docsearch-footer + border-color $borderColor + .ds-cursor .algolia-docsearch-suggestion--content + background-color #e7edf3 !important + color $textColor + +@media (min-width: $MQMobile) + .algolia-search-wrapper + .algolia-autocomplete + .algolia-docsearch-suggestion + .algolia-docsearch-suggestion--subcategory-column + float none + width 150px + min-width 150px + display table-cell + .algolia-docsearch-suggestion--content + float none + display table-cell + width 100% + vertical-align top + .ds-dropdown-menu + min-width 515px !important + +@media (max-width: $MQMobile) + .algolia-search-wrapper + .ds-dropdown-menu + min-width calc(100vw - 4rem) !important + max-width calc(100vw - 4rem) !important + .algolia-docsearch-suggestion--wrapper + padding 5px 7px 5px 5px !important + .algolia-docsearch-suggestion--subcategory-column + padding 0 !important + background white !important + .algolia-docsearch-suggestion--subcategory-column-text:after + content " > " + font-size 10px + line-height 14.4px + display inline-block + width 5px + margin -3px 3px 0 + vertical-align middle + +</style> diff --git a/node_modules/vuepress/lib/default-theme/DropdownLink.vue b/node_modules/vuepress/lib/default-theme/DropdownLink.vue new file mode 100644 index 00000000..e6000a60 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/DropdownLink.vue @@ -0,0 +1,181 @@ +<template> + <div + class="dropdown-wrapper" + :class="{ open }" + > + <a + class="dropdown-title" + @click="toggle" + > + <span class="title">{{ item.text }}</span> + <span + class="arrow" + :class="open ? 'down' : 'right'" + ></span> + </a> + + <DropdownTransition> + <ul + class="nav-dropdown" + v-show="open" + > + <li + class="dropdown-item" + :key="subItem.link || index" + v-for="(subItem, index) in item.items" + > + <h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4> + + <ul + class="dropdown-subitem-wrapper" + v-if="subItem.type === 'links'" + > + <li + class="dropdown-subitem" + :key="childSubItem.link" + v-for="childSubItem in subItem.items" + > + <NavLink :item="childSubItem"/> + </li> + </ul> + + <NavLink + v-else + :item="subItem" + /> + </li> + </ul> + </DropdownTransition> + </div> +</template> + +<script> +import NavLink from './NavLink.vue' +import DropdownTransition from './DropdownTransition.vue' + +export default { + components: { NavLink, DropdownTransition }, + + data () { + return { + open: false + } + }, + + props: { + item: { + required: true + } + }, + + methods: { + toggle () { + this.open = !this.open + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.dropdown-wrapper + cursor pointer + .dropdown-title + display block + &:hover + border-color transparent + .arrow + vertical-align middle + margin-top -1px + margin-left 0.4rem + .nav-dropdown + .dropdown-item + color inherit + line-height 1.7rem + h4 + margin 0.45rem 0 0 + border-top 1px solid #eee + padding 0.45rem 1.5rem 0 1.25rem + .dropdown-subitem-wrapper + padding 0 + list-style none + .dropdown-subitem + font-size 0.9em + a + display block + line-height 1.7rem + position relative + border-bottom none + font-weight 400 + margin-bottom 0 + padding 0 1.5rem 0 1.25rem + &:hover + color $accentColor + &.router-link-active + color $accentColor + &::after + content "" + width 0 + height 0 + border-left 5px solid $accentColor + border-top 3px solid transparent + border-bottom 3px solid transparent + position absolute + top calc(50% - 2px) + left 9px + &:first-child h4 + margin-top 0 + padding-top 0 + border-top 0 + +@media (max-width: $MQMobile) + .dropdown-wrapper + &.open .dropdown-title + margin-bottom 0.5rem + .nav-dropdown + transition height .1s ease-out + overflow hidden + .dropdown-item + h4 + border-top 0 + margin-top 0 + padding-top 0 + h4, & > a + font-size 15px + line-height 2rem + .dropdown-subitem + font-size 14px + padding-left 1rem + +@media (min-width: $MQMobile) + .dropdown-wrapper + height 1.8rem + &:hover .nav-dropdown + // override the inline style. + display block !important + .dropdown-title .arrow + // make the arrow always down at desktop + border-left 4px solid transparent + border-right 4px solid transparent + border-top 6px solid $arrowBgColor + border-bottom 0 + .nav-dropdown + display none + // Avoid height shaked by clicking + height auto !important + box-sizing border-box; + max-height calc(100vh - 2.7rem) + overflow-y auto + position absolute + top 100% + right 0 + background-color #fff + padding 0.6rem 0 + border 1px solid #ddd + border-bottom-color #ccc + text-align left + border-radius 0.25rem + white-space nowrap + margin 0 +</style> diff --git a/node_modules/vuepress/lib/default-theme/DropdownTransition.vue b/node_modules/vuepress/lib/default-theme/DropdownTransition.vue new file mode 100644 index 00000000..8c711a15 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/DropdownTransition.vue @@ -0,0 +1,33 @@ +<template> + <transition + name="dropdown" + @enter="setHeight" + @after-enter="unsetHeight" + @before-leave="setHeight" + > + <slot/> + </transition> +</template> + +<script> +export default { + name: 'DropdownTransition', + + methods: { + setHeight (items) { + // explicitly set height so that it can be transitioned + items.style.height = items.scrollHeight + 'px' + }, + + unsetHeight (items) { + items.style.height = '' + } + } +} +</script> + +<style lang="stylus"> +.dropdown-enter, .dropdown-leave-to + height 0 !important + +</style> diff --git a/node_modules/vuepress/lib/default-theme/Home.vue b/node_modules/vuepress/lib/default-theme/Home.vue new file mode 100644 index 00000000..a172eb9b --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/Home.vue @@ -0,0 +1,162 @@ +<template> + <div class="home"> + <div class="hero"> + <img + v-if="data.heroImage" + :src="$withBase(data.heroImage)" + alt="hero" + > + + <h1>{{ data.heroText || $title || 'Hello' }}</h1> + + <p class="description"> + {{ data.tagline || $description || 'Welcome to your VuePress site' }} + </p> + + <p + class="action" + v-if="data.actionText && data.actionLink" + > + <NavLink + class="action-button" + :item="actionLink" + /> + </p> + </div> + + <div + class="features" + v-if="data.features && data.features.length" + > + <div + class="feature" + v-for="(feature, index) in data.features" + :key="index" + > + <h2>{{ feature.title }}</h2> + <p>{{ feature.details }}</p> + </div> + </div> + + <Content custom/> + + <div + class="footer" + v-if="data.footer" + > + {{ data.footer }} + </div> + </div> +</template> + +<script> +import NavLink from './NavLink.vue' + +export default { + components: { NavLink }, + + computed: { + data () { + return this.$page.frontmatter + }, + + actionLink () { + return { + link: this.data.actionLink, + text: this.data.actionText + } + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.home + padding $navbarHeight 2rem 0 + max-width 960px + margin 0px auto + .hero + text-align center + img + max-height 280px + display block + margin 3rem auto 1.5rem + h1 + font-size 3rem + h1, .description, .action + margin 1.8rem auto + .description + max-width 35rem + font-size 1.6rem + line-height 1.3 + color lighten($textColor, 40%) + .action-button + display inline-block + font-size 1.2rem + color #fff + background-color $accentColor + padding 0.8rem 1.6rem + border-radius 4px + transition background-color .1s ease + box-sizing border-box + border-bottom 1px solid darken($accentColor, 10%) + &:hover + background-color lighten($accentColor, 10%) + .features + border-top 1px solid $borderColor + padding 1.2rem 0 + margin-top 2.5rem + display flex + flex-wrap wrap + align-items flex-start + align-content stretch + justify-content space-between + .feature + flex-grow 1 + flex-basis 30% + max-width 30% + h2 + font-size 1.4rem + font-weight 500 + border-bottom none + padding-bottom 0 + color lighten($textColor, 10%) + p + color lighten($textColor, 25%) + .footer + padding 2.5rem + border-top 1px solid $borderColor + text-align center + color lighten($textColor, 25%) + +@media (max-width: $MQMobile) + .home + .features + flex-direction column + .feature + max-width 100% + padding 0 2.5rem + +@media (max-width: $MQMobileNarrow) + .home + padding-left 1.5rem + padding-right 1.5rem + .hero + img + max-height 210px + margin 2rem auto 1.2rem + h1 + font-size 2rem + h1, .description, .action + margin 1.2rem auto + .description + font-size 1.2rem + .action-button + font-size 1rem + padding 0.6rem 1.2rem + .feature + h2 + font-size 1.25rem +</style> diff --git a/node_modules/vuepress/lib/default-theme/Layout.vue b/node_modules/vuepress/lib/default-theme/Layout.vue new file mode 100644 index 00000000..ee2e6abe --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/Layout.vue @@ -0,0 +1,183 @@ +<template> + <div + class="theme-container" + :class="pageClasses" + @touchstart="onTouchStart" + @touchend="onTouchEnd" + > + <Navbar + v-if="shouldShowNavbar" + @toggle-sidebar="toggleSidebar" + /> + + <div + class="sidebar-mask" + @click="toggleSidebar(false)" + ></div> + + <Sidebar + :items="sidebarItems" + @toggle-sidebar="toggleSidebar" + > + <slot + name="sidebar-top" + slot="top" + /> + <slot + name="sidebar-bottom" + slot="bottom" + /> + </Sidebar> + + <div + class="custom-layout" + v-if="$page.frontmatter.layout" + > + <component :is="$page.frontmatter.layout"/> + </div> + + <Home v-else-if="$page.frontmatter.home"/> + + <Page + v-else + :sidebar-items="sidebarItems" + > + <slot + name="page-top" + slot="top" + /> + <slot + name="page-bottom" + slot="bottom" + /> + </Page> + + <SWUpdatePopup :updateEvent="swUpdateEvent"/> + </div> +</template> + +<script> +import Vue from 'vue' +import nprogress from 'nprogress' +import Home from './Home.vue' +import Navbar from './Navbar.vue' +import Page from './Page.vue' +import Sidebar from './Sidebar.vue' +import SWUpdatePopup from './SWUpdatePopup.vue' +import { resolveSidebarItems } from './util' + +export default { + components: { Home, Page, Sidebar, Navbar, SWUpdatePopup }, + + data () { + return { + isSidebarOpen: false, + swUpdateEvent: null + } + }, + + computed: { + shouldShowNavbar () { + const { themeConfig } = this.$site + const { frontmatter } = this.$page + if ( + frontmatter.navbar === false || + themeConfig.navbar === false) { + return false + } + return ( + this.$title || + themeConfig.logo || + themeConfig.repo || + themeConfig.nav || + this.$themeLocaleConfig.nav + ) + }, + + shouldShowSidebar () { + const { frontmatter } = this.$page + return ( + !frontmatter.layout && + !frontmatter.home && + frontmatter.sidebar !== false && + this.sidebarItems.length + ) + }, + + sidebarItems () { + return resolveSidebarItems( + this.$page, + this.$route, + this.$site, + this.$localePath + ) + }, + + pageClasses () { + const userPageClass = this.$page.frontmatter.pageClass + return [ + { + 'no-navbar': !this.shouldShowNavbar, + 'sidebar-open': this.isSidebarOpen, + 'no-sidebar': !this.shouldShowSidebar + }, + userPageClass + ] + } + }, + + mounted () { + window.addEventListener('scroll', this.onScroll) + + // configure progress bar + nprogress.configure({ showSpinner: false }) + + this.$router.beforeEach((to, from, next) => { + if (to.path !== from.path && !Vue.component(to.name)) { + nprogress.start() + } + next() + }) + + this.$router.afterEach(() => { + nprogress.done() + this.isSidebarOpen = false + }) + + this.$on('sw-updated', this.onSWUpdated) + }, + + methods: { + toggleSidebar (to) { + this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen + }, + + // side swipe + onTouchStart (e) { + this.touchStart = { + x: e.changedTouches[0].clientX, + y: e.changedTouches[0].clientY + } + }, + + onTouchEnd (e) { + const dx = e.changedTouches[0].clientX - this.touchStart.x + const dy = e.changedTouches[0].clientY - this.touchStart.y + if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) { + if (dx > 0 && this.touchStart.x <= 80) { + this.toggleSidebar(true) + } else { + this.toggleSidebar(false) + } + } + }, + + onSWUpdated (e) { + this.swUpdateEvent = e + } + } +} +</script> + +<style src="prismjs/themes/prism-tomorrow.css"></style> +<style src="./styles/theme.styl" lang="stylus"></style> diff --git a/node_modules/vuepress/lib/default-theme/NavLink.vue b/node_modules/vuepress/lib/default-theme/NavLink.vue new file mode 100644 index 00000000..d9fa4886 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/NavLink.vue @@ -0,0 +1,49 @@ +<template> + <router-link + class="nav-link" + :to="link" + v-if="!isExternal(link)" + :exact="exact" + >{{ item.text }}</router-link> + <a + v-else + :href="link" + class="nav-link external" + :target="isMailto(link) || isTel(link) ? null : '_blank'" + :rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'" + > + {{ item.text }} + <OutboundLink/> + </a> +</template> + +<script> +import { isExternal, isMailto, isTel, ensureExt } from './util' + +export default { + props: { + item: { + required: true + } + }, + + computed: { + link () { + return ensureExt(this.item.link) + }, + + exact () { + if (this.$site.locales) { + return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link) + } + return this.link === '/' + } + }, + + methods: { + isExternal, + isMailto, + isTel + } +} +</script> diff --git a/node_modules/vuepress/lib/default-theme/NavLinks.vue b/node_modules/vuepress/lib/default-theme/NavLinks.vue new file mode 100644 index 00000000..4037f288 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/NavLinks.vue @@ -0,0 +1,151 @@ +<template> + <nav + class="nav-links" + v-if="userLinks.length || repoLink" + > + <!-- user links --> + <div + class="nav-item" + v-for="item in userLinks" + :key="item.link" + > + <DropdownLink + v-if="item.type === 'links'" + :item="item" + /> + <NavLink + v-else + :item="item" + /> + </div> + + <!-- repo link --> + <a + v-if="repoLink" + :href="repoLink" + class="repo-link" + target="_blank" + rel="noopener noreferrer" + > + {{ repoLabel }} + <OutboundLink/> + </a> + </nav> +</template> + +<script> +import DropdownLink from './DropdownLink.vue' +import { resolveNavLinkItem } from './util' +import NavLink from './NavLink.vue' + +export default { + components: { NavLink, DropdownLink }, + + computed: { + userNav () { + return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || [] + }, + + nav () { + const { locales } = this.$site + if (locales && Object.keys(locales).length > 1) { + const currentLink = this.$page.path + const routes = this.$router.options.routes + const themeLocales = this.$site.themeConfig.locales || {} + const languageDropdown = { + text: this.$themeLocaleConfig.selectText || 'Languages', + items: Object.keys(locales).map(path => { + const locale = locales[path] + const text = themeLocales[path] && themeLocales[path].label || locale.lang + let link + // Stay on the current page + if (locale.lang === this.$lang) { + link = currentLink + } else { + // Try to stay on the same page + link = currentLink.replace(this.$localeConfig.path, path) + // fallback to homepage + if (!routes.some(route => route.path === link)) { + link = path + } + } + return { text, link } + }) + } + return [...this.userNav, languageDropdown] + } + return this.userNav + }, + + userLinks () { + return (this.nav || []).map(link => { + return Object.assign(resolveNavLinkItem(link), { + items: (link.items || []).map(resolveNavLinkItem) + }) + }) + }, + + repoLink () { + const { repo } = this.$site.themeConfig + if (repo) { + return /^https?:/.test(repo) + ? repo + : `https://github.com/${repo}` + } + }, + + repoLabel () { + if (!this.repoLink) return + if (this.$site.themeConfig.repoLabel) { + return this.$site.themeConfig.repoLabel + } + + const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0] + const platforms = ['GitHub', 'GitLab', 'Bitbucket'] + for (let i = 0; i < platforms.length; i++) { + const platform = platforms[i] + if (new RegExp(platform, 'i').test(repoHost)) { + return platform + } + } + + return 'Source' + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.nav-links + display inline-block + a + line-height 1.4rem + color inherit + &:hover, &.router-link-active + color $accentColor + .nav-item + position relative + display inline-block + margin-left 1.5rem + line-height 2rem + &:first-child + margin-left 0 + .repo-link + margin-left 1.5rem + +@media (max-width: $MQMobile) + .nav-links + .nav-item, .repo-link + margin-left 0 + +@media (min-width: $MQMobile) + .nav-links a + &:hover, &.router-link-active + color $textColor + .nav-item > a:not(.external) + &:hover, &.router-link-active + margin-bottom -2px + border-bottom 2px solid lighten($accentColor, 8%) +</style> diff --git a/node_modules/vuepress/lib/default-theme/Navbar.vue b/node_modules/vuepress/lib/default-theme/Navbar.vue new file mode 100644 index 00000000..12795665 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/Navbar.vue @@ -0,0 +1,133 @@ +<template> + <header class="navbar"> + <SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/> + + <router-link + :to="$localePath" + class="home-link" + > + <img + class="logo" + v-if="$site.themeConfig.logo" + :src="$withBase($site.themeConfig.logo)" + :alt="$siteTitle" + > + <span + ref="siteName" + class="site-name" + v-if="$siteTitle" + :class="{ 'can-hide': $site.themeConfig.logo }" + >{{ $siteTitle }}</span> + </router-link> + + <div + class="links" + :style="{ + 'max-width': linksWrapMaxWidth + 'px' + }" + > + <AlgoliaSearchBox + v-if="isAlgoliaSearch" + :options="algolia" + /> + <SearchBox v-else-if="$site.themeConfig.search !== false"/> + <NavLinks class="can-hide"/> + </div> + </header> +</template> + +<script> +import SidebarButton from './SidebarButton.vue' +import AlgoliaSearchBox from '@AlgoliaSearchBox' +import SearchBox from './SearchBox.vue' +import NavLinks from './NavLinks.vue' + +export default { + components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox }, + + data () { + return { + linksWrapMaxWidth: null + } + }, + + mounted () { + const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl + const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight')) + const handleLinksWrapWidth = () => { + if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) { + this.linksWrapMaxWidth = null + } else { + this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING - + (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0) + } + } + handleLinksWrapWidth() + window.addEventListener('resize', handleLinksWrapWidth, false) + }, + + computed: { + algolia () { + return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {} + }, + + isAlgoliaSearch () { + return this.algolia && this.algolia.apiKey && this.algolia.indexName + } + } +} + +function css (el, property) { + // NOTE: Known bug, will return 'auto' if style value is 'auto' + const win = el.ownerDocument.defaultView + // null means not to return pseudo styles + return win.getComputedStyle(el, null)[property] +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +$navbar-vertical-padding = 0.7rem +$navbar-horizontal-padding = 1.5rem + +.navbar + padding $navbar-vertical-padding $navbar-horizontal-padding + line-height $navbarHeight - 1.4rem + position relative + a, span, img + display inline-block + .logo + height $navbarHeight - 1.4rem + min-width $navbarHeight - 1.4rem + margin-right 0.8rem + vertical-align top + .site-name + font-size 1.3rem + font-weight 600 + color $textColor + position relative + .links + padding-left 1.5rem + box-sizing border-box + background-color white + white-space nowrap + font-size 0.9rem + position absolute + right $navbar-horizontal-padding + top $navbar-vertical-padding + display flex + .search-box + flex: 0 0 auto + vertical-align top + .nav-links + flex 1 + +@media (max-width: $MQMobile) + .navbar + padding-left 4rem + .can-hide + display none + .links + padding-left 1.5rem +</style> diff --git a/node_modules/vuepress/lib/default-theme/NotFound.vue b/node_modules/vuepress/lib/default-theme/NotFound.vue new file mode 100644 index 00000000..6aefe797 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/NotFound.vue @@ -0,0 +1,26 @@ +<template> + <div class="theme-container"> + <div class="content"> + <h1>404</h1> + <blockquote>{{ getMsg() }}</blockquote> + <router-link to="/">Take me home.</router-link> + </div> + </div> +</template> + +<script> +const msgs = [ + `There's nothing here.`, + `How did we get here?`, + `That's a Four-Oh-Four.`, + `Looks like we've got some broken links.` +] + +export default { + methods: { + getMsg () { + return msgs[Math.floor(Math.random() * msgs.length)] + } + } +} +</script> diff --git a/node_modules/vuepress/lib/default-theme/Page.vue b/node_modules/vuepress/lib/default-theme/Page.vue new file mode 100644 index 00000000..37d65b41 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/Page.vue @@ -0,0 +1,246 @@ +<template> + <div class="page"> + <slot name="top"/> + + <Content :custom="false"/> + + <div class="page-edit"> + <div + class="edit-link" + v-if="editLink" + > + <a + :href="editLink" + target="_blank" + rel="noopener noreferrer" + >{{ editLinkText }}</a> + <OutboundLink/> + </div> + + <div + class="last-updated" + v-if="lastUpdated" + > + <span class="prefix">{{ lastUpdatedText }}: </span> + <span class="time">{{ lastUpdated }}</span> + </div> + </div> + + <div class="page-nav" v-if="prev || next"> + <p class="inner"> + <span + v-if="prev" + class="prev" + > + ← + <router-link + v-if="prev" + class="prev" + :to="prev.path" + > + {{ prev.title || prev.path }} + </router-link> + </span> + + <span + v-if="next" + class="next" + > + <router-link + v-if="next" + :to="next.path" + > + {{ next.title || next.path }} + </router-link> + → + </span> + </p> + </div> + + <slot name="bottom"/> + </div> +</template> + +<script> +import { resolvePage, normalize, outboundRE, endingSlashRE } from './util' + +export default { + props: ['sidebarItems'], + + computed: { + lastUpdated () { + if (this.$page.lastUpdated) { + return new Date(this.$page.lastUpdated).toLocaleString(this.$lang) + } + }, + + lastUpdatedText () { + if (typeof this.$themeLocaleConfig.lastUpdated === 'string') { + return this.$themeLocaleConfig.lastUpdated + } + if (typeof this.$site.themeConfig.lastUpdated === 'string') { + return this.$site.themeConfig.lastUpdated + } + return 'Last Updated' + }, + + prev () { + const prev = this.$page.frontmatter.prev + if (prev === false) { + return + } else if (prev) { + return resolvePage(this.$site.pages, prev, this.$route.path) + } else { + return resolvePrev(this.$page, this.sidebarItems) + } + }, + + next () { + const next = this.$page.frontmatter.next + if (next === false) { + return + } else if (next) { + return resolvePage(this.$site.pages, next, this.$route.path) + } else { + return resolveNext(this.$page, this.sidebarItems) + } + }, + + editLink () { + if (this.$page.frontmatter.editLink === false) { + return + } + const { + repo, + editLinks, + docsDir = '', + docsBranch = 'master', + docsRepo = repo + } = this.$site.themeConfig + + let path = normalize(this.$page.path) + if (endingSlashRE.test(path)) { + path += 'README.md' + } else { + path += '.md' + } + if (docsRepo && editLinks) { + return this.createEditLink(repo, docsRepo, docsDir, docsBranch, path) + } + }, + + editLinkText () { + return ( + this.$themeLocaleConfig.editLinkText || + this.$site.themeConfig.editLinkText || + `Edit this page` + ) + } + }, + + methods: { + createEditLink (repo, docsRepo, docsDir, docsBranch, path) { + const bitbucket = /bitbucket.org/ + if (bitbucket.test(repo)) { + const base = outboundRE.test(docsRepo) + ? docsRepo + : repo + return ( + base.replace(endingSlashRE, '') + + `/${docsBranch}` + + (docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') + + path + + `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default` + ) + } + + const base = outboundRE.test(docsRepo) + ? docsRepo + : `https://github.com/${docsRepo}` + + return ( + base.replace(endingSlashRE, '') + + `/edit/${docsBranch}` + + (docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') + + path + ) + } + } +} + +function resolvePrev (page, items) { + return find(page, items, -1) +} + +function resolveNext (page, items) { + return find(page, items, 1) +} + +function find (page, items, offset) { + const res = [] + items.forEach(item => { + if (item.type === 'group') { + res.push(...item.children || []) + } else { + res.push(item) + } + }) + for (let i = 0; i < res.length; i++) { + const cur = res[i] + if (cur.type === 'page' && cur.path === page.path) { + return res[i + offset] + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' +@require './styles/wrapper.styl' + +.page + padding-bottom 2rem + +.page-edit + @extend $wrapper + padding-top 1rem + padding-bottom 1rem + overflow auto + .edit-link + display inline-block + a + color lighten($textColor, 25%) + margin-right 0.25rem + .last-updated + float right + font-size 0.9em + .prefix + font-weight 500 + color lighten($textColor, 25%) + .time + font-weight 400 + color #aaa + +.page-nav + @extend $wrapper + padding-top 1rem + padding-bottom 0 + .inner + min-height 2rem + margin-top 0 + border-top 1px solid $borderColor + padding-top 1rem + overflow auto // clear float + .next + float right + +@media (max-width: $MQMobile) + .page-edit + .edit-link + margin-bottom .5rem + .last-updated + font-size .8em + float none + text-align left + +</style> diff --git a/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue b/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue new file mode 100644 index 00000000..b224db31 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue @@ -0,0 +1,85 @@ +<template> + <transition name="sw-update-popup"> + <div + v-if="enabled" + class="sw-update-popup" + > + {{message}}<br> + <button @click="reload">{{buttonText}}</button> + </div> + </transition> +</template> + +<script> +export default { + props: { + updateEvent: { + type: Object, + default: null + } + }, + + computed: { + popupConfig () { + for (const config of [this.$themeLocaleConfig, this.$site.themeConfig]) { + const sw = config.serviceWorker + if (sw && sw.updatePopup) { + return typeof sw.updatePopup === 'object' ? sw.updatePopup : {} + } + } + return null + }, + + enabled () { + return Boolean(this.popupConfig && this.updateEvent) + }, + + message () { + const c = this.popupConfig + return (c && c.message) || 'New content is available.' + }, + + buttonText () { + const c = this.popupConfig + return (c && c.buttonText) || 'Refresh' + } + }, + + methods: { + reload () { + if (this.updateEvent) { + this.updateEvent.skipWaiting().then(() => { + location.reload(true) + }) + this.updateEvent = null + } + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.sw-update-popup + position fixed + right 1em + bottom 1em + padding 1em + border 1px solid $accentColor + border-radius 3px + background #fff + box-shadow 0 4px 16px rgba(0, 0, 0, 0.5) + text-align center + + button + margin-top 0.5em + padding 0.25em 2em + +.sw-update-popup-enter-active, .sw-update-popup-leave-active + transition opacity 0.3s, transform 0.3s + +.sw-update-popup-enter, .sw-update-popup-leave-to + opacity 0 + transform translate(0, 50%) scale(0.5) +</style> diff --git a/node_modules/vuepress/lib/default-theme/SearchBox.vue b/node_modules/vuepress/lib/default-theme/SearchBox.vue new file mode 100644 index 00000000..98608552 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/SearchBox.vue @@ -0,0 +1,238 @@ +<template> + <div class="search-box"> + <input + @input="query = $event.target.value" + aria-label="Search" + :value="query" + :class="{ 'focused': focused }" + autocomplete="off" + spellcheck="false" + @focus="focused = true" + @blur="focused = false" + @keyup.enter="go(focusIndex)" + @keyup.up="onUp" + @keyup.down="onDown" + > + <ul + class="suggestions" + v-if="showSuggestions" + :class="{ 'align-right': alignRight }" + @mouseleave="unfocus" + > + <li + class="suggestion" + v-for="(s, i) in suggestions" + :class="{ focused: i === focusIndex }" + @mousedown="go(i)" + @mouseenter="focus(i)" + > + <a :href="s.path" @click.prevent> + <span class="page-title">{{ s.title || s.path }}</span> + <span v-if="s.header" class="header">> {{ s.header.title }}</span> + </a> + </li> + </ul> + </div> +</template> + +<script> +export default { + data () { + return { + query: '', + focused: false, + focusIndex: 0 + } + }, + + computed: { + showSuggestions () { + return ( + this.focused && + this.suggestions && + this.suggestions.length + ) + }, + + suggestions () { + const query = this.query.trim().toLowerCase() + if (!query) { + return + } + + const { pages, themeConfig } = this.$site + const max = themeConfig.searchMaxSuggestions || 5 + const localePath = this.$localePath + const matches = item => ( + item.title && + item.title.toLowerCase().indexOf(query) > -1 + ) + const res = [] + for (let i = 0; i < pages.length; i++) { + if (res.length >= max) break + const p = pages[i] + // filter out results that do not match current locale + if (this.getPageLocalePath(p) !== localePath) { + continue + } + if (matches(p)) { + res.push(p) + } else if (p.headers) { + for (let j = 0; j < p.headers.length; j++) { + if (res.length >= max) break + const h = p.headers[j] + if (matches(h)) { + res.push(Object.assign({}, p, { + path: p.path + '#' + h.slug, + header: h + })) + } + } + } + } + return res + }, + + // make suggestions align right when there are not enough items + alignRight () { + const navCount = (this.$site.themeConfig.nav || []).length + const repo = this.$site.repo ? 1 : 0 + return navCount + repo <= 2 + } + }, + + methods: { + getPageLocalePath (page) { + for (const localePath in this.$site.locales || {}) { + if (localePath !== '/' && page.path.indexOf(localePath) === 0) { + return localePath + } + } + return '/' + }, + + onUp () { + if (this.showSuggestions) { + if (this.focusIndex > 0) { + this.focusIndex-- + } else { + this.focusIndex = this.suggestions.length - 1 + } + } + }, + + onDown () { + if (this.showSuggestions) { + if (this.focusIndex < this.suggestions.length - 1) { + this.focusIndex++ + } else { + this.focusIndex = 0 + } + } + }, + + go (i) { + if (!this.showSuggestions) { + return + } + this.$router.push(this.suggestions[i].path) + this.query = '' + this.focusIndex = 0 + }, + + focus (i) { + this.focusIndex = i + }, + + unfocus () { + this.focusIndex = -1 + } + } +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.search-box + display inline-block + position relative + margin-right 1rem + input + cursor text + width 10rem + color lighten($textColor, 25%) + display inline-block + border 1px solid darken($borderColor, 10%) + border-radius 2rem + font-size 0.9rem + line-height 2rem + padding 0 0.5rem 0 2rem + outline none + transition all .2s ease + background #fff url(./search.svg) 0.6rem 0.5rem no-repeat + background-size 1rem + &:focus + cursor auto + border-color $accentColor + .suggestions + background #fff + width 20rem + position absolute + top 1.5rem + border 1px solid darken($borderColor, 10%) + border-radius 6px + padding 0.4rem + list-style-type none + &.align-right + right 0 + .suggestion + line-height 1.4 + padding 0.4rem 0.6rem + border-radius 4px + cursor pointer + a + white-space normal + color lighten($textColor, 35%) + .page-title + font-weight 600 + .header + font-size 0.9em + margin-left 0.25em + &.focused + background-color #f3f4f5 + a + color $accentColor + +@media (max-width: $MQNarrow) + .search-box + input + cursor pointer + width 0 + border-color transparent + position relative + &:focus + cursor text + left 0 + width 10rem + +@media (max-width: $MQNarrow) and (min-width: $MQMobile) + .search-box + .suggestions + left 0 + +@media (max-width: $MQMobile) + .search-box + margin-right 0 + input + left 1rem + .suggestions + right 0 + +@media (max-width: $MQMobileNarrow) + .search-box + .suggestions + width calc(100vw - 4rem) + input:focus + width 8rem +</style> diff --git a/node_modules/vuepress/lib/default-theme/Sidebar.vue b/node_modules/vuepress/lib/default-theme/Sidebar.vue new file mode 100644 index 00000000..7bcf0059 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/Sidebar.vue @@ -0,0 +1,113 @@ +<template> + <div class="sidebar"> + <NavLinks/> + <slot name="top"/> + <ul class="sidebar-links" v-if="items.length"> + <li v-for="(item, i) in items" :key="i"> + <SidebarGroup + v-if="item.type === 'group'" + :item="item" + :first="i === 0" + :open="i === openGroupIndex" + :collapsable="item.collapsable || item.collapsible" + @toggle="toggleGroup(i)" + /> + <SidebarLink v-else :item="item"/> + </li> + </ul> + <slot name="bottom"/> + </div> +</template> + +<script> +import SidebarGroup from './SidebarGroup.vue' +import SidebarLink from './SidebarLink.vue' +import NavLinks from './NavLinks.vue' +import { isActive } from './util' + +export default { + components: { SidebarGroup, SidebarLink, NavLinks }, + + props: ['items'], + + data () { + return { + openGroupIndex: 0 + } + }, + + created () { + this.refreshIndex() + }, + + watch: { + '$route' () { + this.refreshIndex() + } + }, + + methods: { + refreshIndex () { + const index = resolveOpenGroupIndex( + this.$route, + this.items + ) + if (index > -1) { + this.openGroupIndex = index + } + }, + + toggleGroup (index) { + this.openGroupIndex = index === this.openGroupIndex ? -1 : index + }, + + isActive (page) { + return isActive(this.$route, page.path) + } + } +} + +function resolveOpenGroupIndex (route, items) { + for (let i = 0; i < items.length; i++) { + const item = items[i] + if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) { + return i + } + } + return -1 +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.sidebar + ul + padding 0 + margin 0 + list-style-type none + a + display inline-block + .nav-links + display none + border-bottom 1px solid $borderColor + padding 0.5rem 0 0.75rem 0 + a + font-weight 600 + .nav-item, .repo-link + display block + line-height 1.25rem + font-size 1.1em + padding 0.5rem 0 0.5rem 1.5rem + .sidebar-links + padding 1.5rem 0 + +@media (max-width: $MQMobile) + .sidebar + .nav-links + display block + .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after + top calc(1rem - 2px) + .sidebar-links + padding 1rem 0 +</style> diff --git a/node_modules/vuepress/lib/default-theme/SidebarButton.vue b/node_modules/vuepress/lib/default-theme/SidebarButton.vue new file mode 100644 index 00000000..0a222434 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/SidebarButton.vue @@ -0,0 +1,28 @@ +<template> + <div class="sidebar-button" @click="$emit('toggle-sidebar')"> + <svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"> + <path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path> + </svg> + </div> +</template> + +<style lang="stylus"> +@import './styles/config.styl' + +.sidebar-button + display none + width 1.25rem + height 1.25rem + position absolute + padding 0.6rem + top 0.6rem + left 1rem + .icon + display block + width 1.25rem + height 1.25rem + +@media (max-width: $MQMobile) + .sidebar-button + display block +</style> diff --git a/node_modules/vuepress/lib/default-theme/SidebarGroup.vue b/node_modules/vuepress/lib/default-theme/SidebarGroup.vue new file mode 100644 index 00000000..119dfa14 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/SidebarGroup.vue @@ -0,0 +1,77 @@ +<template> + <div + class="sidebar-group" + :class="{ first, collapsable }" + > + <p + class="sidebar-heading" + :class="{ open }" + @click="$emit('toggle')" + > + <span>{{ item.title }}</span> + <span + class="arrow" + v-if="collapsable" + :class="open ? 'down' : 'right'"> + </span> + </p> + + <DropdownTransition> + <ul + ref="items" + class="sidebar-group-items" + v-if="open || !collapsable" + > + <li v-for="child in item.children"> + <SidebarLink :item="child"/> + </li> + </ul> + </DropdownTransition> + </div> +</template> + +<script> +import SidebarLink from './SidebarLink.vue' +import DropdownTransition from './DropdownTransition.vue' + +export default { + name: 'SidebarGroup', + props: ['item', 'first', 'open', 'collapsable'], + components: { SidebarLink, DropdownTransition } +} +</script> + +<style lang="stylus"> +.sidebar-group + &:not(.first) + margin-top 1em + .sidebar-group + padding-left 0.5em + &:not(.collapsable) + .sidebar-heading + cursor auto + color inherit + +.sidebar-heading + color #999 + transition color .15s ease + cursor pointer + font-size 1.1em + font-weight bold + // text-transform uppercase + padding 0 1.5rem + margin-top 0 + margin-bottom 0.5rem + &.open, &:hover + color inherit + .arrow + position relative + top -0.12em + left 0.5em + &:.open .arrow + top -0.18em + +.sidebar-group-items + transition height .1s ease-out + overflow hidden +</style> diff --git a/node_modules/vuepress/lib/default-theme/SidebarLink.vue b/node_modules/vuepress/lib/default-theme/SidebarLink.vue new file mode 100644 index 00000000..8288bf96 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/SidebarLink.vue @@ -0,0 +1,91 @@ +<script> +import { isActive, hashRE, groupHeaders } from './util' + +export default { + functional: true, + + props: ['item'], + + render (h, { parent: { $page, $site, $route }, props: { item }}) { + // use custom active class matching logic + // due to edge case of paths ending with / + hash + const selfActive = isActive($route, item.path) + // for sidebar: auto pages, a hash link should be active if one of its child + // matches + const active = item.type === 'auto' + ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug)) + : selfActive + const link = renderLink(h, item.path, item.title || item.path, active) + const configDepth = $page.frontmatter.sidebarDepth != null + ? $page.frontmatter.sidebarDepth + : $site.themeConfig.sidebarDepth + const maxDepth = configDepth == null ? 1 : configDepth + const displayAllHeaders = !!$site.themeConfig.displayAllHeaders + if (item.type === 'auto') { + return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)] + } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) { + const children = groupHeaders(item.headers) + return [link, renderChildren(h, children, item.path, $route, maxDepth)] + } else { + return link + } + } +} + +function renderLink (h, to, text, active) { + return h('router-link', { + props: { + to, + activeClass: '', + exactActiveClass: '' + }, + class: { + active, + 'sidebar-link': true + } + }, text) +} + +function renderChildren (h, children, path, route, maxDepth, depth = 1) { + if (!children || depth > maxDepth) return null + return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => { + const active = isActive(route, path + '#' + c.slug) + return h('li', { class: 'sidebar-sub-header' }, [ + renderLink(h, path + '#' + c.slug, c.title, active), + renderChildren(h, c.children, path, route, maxDepth, depth + 1) + ]) + })) +} +</script> + +<style lang="stylus"> +@import './styles/config.styl' + +.sidebar .sidebar-sub-headers + padding-left 1rem + font-size 0.95em + +a.sidebar-link + font-weight 400 + display inline-block + color $textColor + border-left 0.25rem solid transparent + padding 0.35rem 1rem 0.35rem 1.25rem + line-height 1.4 + width: 100% + box-sizing: border-box + &:hover + color $accentColor + &.active + font-weight 600 + color $accentColor + border-left-color $accentColor + .sidebar-group & + padding-left 2rem + .sidebar-sub-headers & + padding-top 0.25rem + padding-bottom 0.25rem + border-left none + &.active + font-weight 500 +</style> diff --git a/node_modules/vuepress/lib/default-theme/search.svg b/node_modules/vuepress/lib/default-theme/search.svg new file mode 100644 index 00000000..03d83913 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/search.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg> diff --git a/node_modules/vuepress/lib/default-theme/styles/arrow.styl b/node_modules/vuepress/lib/default-theme/styles/arrow.styl new file mode 100644 index 00000000..20bffc0d --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/arrow.styl @@ -0,0 +1,22 @@ +@require './config' + +.arrow + display inline-block + width 0 + height 0 + &.up + border-left 4px solid transparent + border-right 4px solid transparent + border-bottom 6px solid $arrowBgColor + &.down + border-left 4px solid transparent + border-right 4px solid transparent + border-top 6px solid $arrowBgColor + &.right + border-top 4px solid transparent + border-bottom 4px solid transparent + border-left 6px solid $arrowBgColor + &.left + border-top 4px solid transparent + border-bottom 4px solid transparent + border-right 6px solid $arrowBgColor diff --git a/node_modules/vuepress/lib/default-theme/styles/code.styl b/node_modules/vuepress/lib/default-theme/styles/code.styl new file mode 100644 index 00000000..8383c6e3 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/code.styl @@ -0,0 +1,129 @@ +@require './config' + +.content + code + color lighten($textColor, 20%) + padding 0.25rem 0.5rem + margin 0 + font-size 0.85em + background-color rgba(27,31,35,0.05) + border-radius 3px + +.content + pre, pre[class*="language-"] + line-height 1.4 + padding 1.25rem 1.5rem + margin 0.85rem 0 + background-color $codeBgColor + border-radius 6px + overflow auto + code + color #fff + padding 0 + background-color transparent + border-radius 0 + +div[class*="language-"] + position relative + background-color $codeBgColor + border-radius 6px + .highlight-lines + user-select none + padding-top 1.3rem + position absolute + top 0 + left 0 + width 100% + line-height 1.4 + .highlighted + background-color rgba(0, 0, 0, 66%) + pre, pre[class*="language-"] + background transparent + position relative + z-index 1 + &::before + position absolute + z-index 3 + top 0.8em + right 1em + font-size 0.75rem + color rgba(255, 255, 255, 0.4) + &:not(.line-numbers-mode) + .line-numbers-wrapper + display none + &.line-numbers-mode + .highlight-lines .highlighted + position relative + &:before + content ' ' + position absolute + z-index 3 + left 0 + top 0 + display block + width $lineNumbersWrapperWidth + height 100% + background-color rgba(0, 0, 0, 66%) + pre + padding-left $lineNumbersWrapperWidth + 1 rem + vertical-align middle + .line-numbers-wrapper + position absolute + top 0 + width $lineNumbersWrapperWidth + text-align center + color rgba(255, 255, 255, 0.3) + padding 1.25rem 0 + line-height 1.4 + br + user-select none + .line-number + position relative + z-index 4 + user-select none + font-size 0.85em + &::after + content '' + position absolute + z-index 2 + top 0 + left 0 + width $lineNumbersWrapperWidth + height 100% + border-radius 6px 0 0 6px + border-right 1px solid rgba(0, 0, 0, 66%) + background-color $codeBgColor + + +for lang in $codeLang + div{'[class~="language-' + lang + '"]'} + &:before + content ('' + lang) + +div[class~="language-javascript"] + &:before + content "js" + +div[class~="language-typescript"] + &:before + content "ts" + +div[class~="language-markup"] + &:before + content "html" + +div[class~="language-markdown"] + &:before + content "md" + +div[class~="language-json"]:before + content "json" + +div[class~="language-ruby"]:before + content "rb" + +div[class~="language-python"]:before + content "py" + +div[class~="language-bash"]:before + content "sh" diff --git a/node_modules/vuepress/lib/default-theme/styles/config.styl b/node_modules/vuepress/lib/default-theme/styles/config.styl new file mode 100644 index 00000000..a57d4484 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/config.styl @@ -0,0 +1,22 @@ +// colors +$accentColor = #3eaf7c +$textColor = #2c3e50 +$borderColor = #eaecef +$codeBgColor = #282c34 +$arrowBgColor = #ccc + +// layout +$navbarHeight = 3.6rem +$sidebarWidth = 20rem +$contentWidth = 740px + +// responsive breakpoints +$MQNarrow = 959px +$MQMobile = 719px +$MQMobileNarrow = 419px + +// code +$lineNumbersWrapperWidth = 3.5rem +$codeLang = js ts html md vue css sass scss less stylus go java c sh yaml py + +@import '~@temp/override.styl' diff --git a/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl b/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl new file mode 100644 index 00000000..3ccc2df2 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl @@ -0,0 +1,28 @@ +.custom-block + .custom-block-title + font-weight 600 + margin-bottom -0.4rem + &.tip, &.warning, &.danger + padding .1rem 1.5rem + border-left-width .5rem + border-left-style solid + margin 1rem 0 + &.tip + background-color #f3f5f7 + border-color #42b983 + &.warning + background-color rgba(255,229,100,.3) + border-color darken(#ffe564, 35%) + color darken(#ffe564, 70%) + .custom-block-title + color darken(#ffe564, 50%) + a + color $textColor + &.danger + background-color #ffe6e6 + border-color darken(red, 20%) + color darken(red, 70%) + .custom-block-title + color darken(red, 40%) + a + color $textColor diff --git a/node_modules/vuepress/lib/default-theme/styles/mobile.styl b/node_modules/vuepress/lib/default-theme/styles/mobile.styl new file mode 100644 index 00000000..b35e59c5 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/mobile.styl @@ -0,0 +1,37 @@ +@require './config' + +$mobileSidebarWidth = $sidebarWidth * 0.82 + +// narrow desktop / iPad +@media (max-width: $MQNarrow) + .sidebar + font-size 15px + width $mobileSidebarWidth + .page + padding-left $mobileSidebarWidth + +// wide mobile +@media (max-width: $MQMobile) + .sidebar + top 0 + padding-top $navbarHeight + transform translateX(-100%) + transition transform .2s ease + .page + padding-left 0 + .theme-container + &.sidebar-open + .sidebar + transform translateX(0) + &.no-navbar + .sidebar + padding-top: 0 + +// narrow mobile +@media (max-width: $MQMobileNarrow) + h1 + font-size 1.9rem + .content + div[class*="language-"] + margin 0.85rem -1.5rem + border-radius 0 diff --git a/node_modules/vuepress/lib/default-theme/styles/nprogress.styl b/node_modules/vuepress/lib/default-theme/styles/nprogress.styl new file mode 100644 index 00000000..f186a67e --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/nprogress.styl @@ -0,0 +1,48 @@ +#nprogress + pointer-events none + .bar + background $accentColor + position fixed + z-index 1031 + top 0 + left 0 + width 100% + height 2px + .peg + display block + position absolute + right 0px + width 100px + height 100% + box-shadow 0 0 10px $accentColor, 0 0 5px $accentColor + opacity 1.0 + transform rotate(3deg) translate(0px, -4px) + .spinner + display block + position fixed + z-index 1031 + top 15px + right 15px + .spinner-icon + width 18px + height 18px + box-sizing border-box + border solid 2px transparent + border-top-color $accentColor + border-left-color $accentColor + border-radius 50% + animation nprogress-spinner 400ms linear infinite + +.nprogress-custom-parent + overflow hidden + position relative + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar + position absolute + +@keyframes nprogress-spinner + 0% + transform rotate(0deg) + 100% + transform rotate(360deg) diff --git a/node_modules/vuepress/lib/default-theme/styles/theme.styl b/node_modules/vuepress/lib/default-theme/styles/theme.styl new file mode 100644 index 00000000..a733861f --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/theme.styl @@ -0,0 +1,190 @@ +@require './config' +@require './nprogress' +@require './code' +@require './custom-blocks' +@require './arrow' +@require './wrapper' +@require './toc' + +html, body + padding 0 + margin 0 + +body + font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif + -webkit-font-smoothing antialiased + -moz-osx-font-smoothing grayscale + font-size 16px + color $textColor + +.page + padding-left $sidebarWidth + +.navbar + position fixed + z-index 20 + top 0 + left 0 + right 0 + height $navbarHeight + background-color #fff + box-sizing border-box + border-bottom 1px solid $borderColor + +.sidebar-mask + position fixed + z-index 9 + top 0 + left 0 + width 100vw + height 100vh + display none + +.sidebar + font-size 15px + background-color #fff + width $sidebarWidth + position fixed + z-index 10 + margin 0 + top $navbarHeight + left 0 + bottom 0 + box-sizing border-box + border-right 1px solid $borderColor + overflow-y auto + +.content:not(.custom) + @extend $wrapper + > *:first-child + margin-top $navbarHeight + a:hover + text-decoration underline + p.demo + padding 1rem 1.5rem + border 1px solid #ddd + border-radius 4px + img + max-width 100% + +.content.custom + padding 0 + margin 0 + img + max-width 100% + +a + font-weight 500 + color $accentColor + text-decoration none + +p a code + font-weight 400 + color $accentColor + +kbd + background #eee + border solid 0.15rem #ddd + border-bottom solid 0.25rem #ddd + border-radius 0.15rem + padding 0 0.15em + +blockquote + font-size 1.2rem + color #999 + border-left .25rem solid #dfe2e5 + margin-left 0 + padding-left 1rem + +ul, ol + padding-left 1.2em + +strong + font-weight 600 + +h1, h2, h3, h4, h5, h6 + font-weight 600 + line-height 1.25 + .content:not(.custom) > & + margin-top (0.5rem - $navbarHeight) + padding-top ($navbarHeight + 1rem) + margin-bottom 0 + &:first-child + margin-top -1.5rem + margin-bottom 1rem + + p, + pre, + .custom-block + margin-top 2rem + &:hover .header-anchor + opacity: 1 + +h1 + font-size 2.2rem + +h2 + font-size 1.65rem + padding-bottom .3rem + border-bottom 1px solid $borderColor + +h3 + font-size 1.35rem + +a.header-anchor + font-size 0.85em + float left + margin-left -0.87em + padding-right 0.23em + margin-top 0.125em + opacity 0 + &:hover + text-decoration none + +code, kbd, .line-number + font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace + +p, ul, ol + line-height 1.7 + +hr + border 0 + border-top 1px solid $borderColor + +table + border-collapse collapse + margin 1rem 0 + display: block + overflow-x: auto + +tr + border-top 1px solid #dfe2e5 + &:nth-child(2n) + background-color #f6f8fa + +th, td + border 1px solid #dfe2e5 + padding .6em 1em + +.custom-layout + padding-top $navbarHeight + +.theme-container + &.sidebar-open + .sidebar-mask + display: block + &.no-navbar + .content:not(.custom) > h1, h2, h3, h4, h5, h6 + margin-top 1.5rem + padding-top 0 + .sidebar + top 0 + .custom-layout + padding-top 0 + + +@media (min-width: ($MQMobile + 1px)) + .theme-container.no-sidebar + .sidebar + display none + .page + padding-left 0 + +@require './mobile.styl' diff --git a/node_modules/vuepress/lib/default-theme/styles/toc.styl b/node_modules/vuepress/lib/default-theme/styles/toc.styl new file mode 100644 index 00000000..d3e71069 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/toc.styl @@ -0,0 +1,3 @@ +.table-of-contents + .badge + vertical-align middle diff --git a/node_modules/vuepress/lib/default-theme/styles/wrapper.styl b/node_modules/vuepress/lib/default-theme/styles/wrapper.styl new file mode 100644 index 00000000..a99262c7 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/styles/wrapper.styl @@ -0,0 +1,9 @@ +$wrapper + max-width $contentWidth + margin 0 auto + padding 2rem 2.5rem + @media (max-width: $MQNarrow) + padding 2rem + @media (max-width: $MQMobileNarrow) + padding 1.5rem + diff --git a/node_modules/vuepress/lib/default-theme/util.js b/node_modules/vuepress/lib/default-theme/util.js new file mode 100644 index 00000000..ef95bea5 --- /dev/null +++ b/node_modules/vuepress/lib/default-theme/util.js @@ -0,0 +1,216 @@ +export const hashRE = /#.*$/ +export const extRE = /\.(md|html)$/ +export const endingSlashRE = /\/$/ +export const outboundRE = /^(https?:|mailto:|tel:)/ + +export function normalize (path) { + return decodeURI(path) + .replace(hashRE, '') + .replace(extRE, '') +} + +export function getHash (path) { + const match = path.match(hashRE) + if (match) { + return match[0] + } +} + +export function isExternal (path) { + return outboundRE.test(path) +} + +export function isMailto (path) { + return /^mailto:/.test(path) +} + +export function isTel (path) { + return /^tel:/.test(path) +} + +export function ensureExt (path) { + if (isExternal(path)) { + return path + } + const hashMatch = path.match(hashRE) + const hash = hashMatch ? hashMatch[0] : '' + const normalized = normalize(path) + + if (endingSlashRE.test(normalized)) { + return path + } + return normalized + '.html' + hash +} + +export function isActive (route, path) { + const routeHash = route.hash + const linkHash = getHash(path) + if (linkHash && routeHash !== linkHash) { + return false + } + const routePath = normalize(route.path) + const pagePath = normalize(path) + return routePath === pagePath +} + +export function resolvePage (pages, rawPath, base) { + if (base) { + rawPath = resolvePath(rawPath, base) + } + const path = normalize(rawPath) + for (let i = 0; i < pages.length; i++) { + if (normalize(pages[i].path) === path) { + return Object.assign({}, pages[i], { + type: 'page', + path: ensureExt(rawPath) + }) + } + } + console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`) + return {} +} + +function resolvePath (relative, base, append) { + const firstChar = relative.charAt(0) + if (firstChar === '/') { + return relative + } + + if (firstChar === '?' || firstChar === '#') { + return base + relative + } + + const stack = base.split('/') + + // remove trailing segment if: + // - not appending + // - appending to trailing slash (last segment is empty) + if (!append || !stack[stack.length - 1]) { + stack.pop() + } + + // resolve relative path + const segments = relative.replace(/^\//, '').split('/') + for (let i = 0; i < segments.length; i++) { + const segment = segments[i] + if (segment === '..') { + stack.pop() + } else if (segment !== '.') { + stack.push(segment) + } + } + + // ensure leading slash + if (stack[0] !== '') { + stack.unshift('') + } + + return stack.join('/') +} + +export function resolveSidebarItems (page, route, site, localePath) { + const { pages, themeConfig } = site + + const localeConfig = localePath && themeConfig.locales + ? themeConfig.locales[localePath] || themeConfig + : themeConfig + + const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar + if (pageSidebarConfig === 'auto') { + return resolveHeaders(page) + } + + const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar + if (!sidebarConfig) { + return [] + } else { + const { base, config } = resolveMatchingConfig(route, sidebarConfig) + return config + ? config.map(item => resolveItem(item, pages, base)) + : [] + } +} + +function resolveHeaders (page) { + const headers = groupHeaders(page.headers || []) + return [{ + type: 'group', + collapsable: false, + title: page.title, + children: headers.map(h => ({ + type: 'auto', + title: h.title, + basePath: page.path, + path: page.path + '#' + h.slug, + children: h.children || [] + })) + }] +} + +export function groupHeaders (headers) { + // group h3s under h2 + headers = headers.map(h => Object.assign({}, h)) + let lastH2 + headers.forEach(h => { + if (h.level === 2) { + lastH2 = h + } else if (lastH2) { + (lastH2.children || (lastH2.children = [])).push(h) + } + }) + return headers.filter(h => h.level === 2) +} + +export function resolveNavLinkItem (linkItem) { + return Object.assign(linkItem, { + type: linkItem.items && linkItem.items.length ? 'links' : 'link' + }) +} + +export function resolveMatchingConfig (route, config) { + if (Array.isArray(config)) { + return { + base: '/', + config: config + } + } + for (const base in config) { + if (ensureEndingSlash(route.path).indexOf(base) === 0) { + return { + base, + config: config[base] + } + } + } + return {} +} + +function ensureEndingSlash (path) { + return /(\.html|\/)$/.test(path) + ? path + : path + '/' +} + +function resolveItem (item, pages, base, isNested) { + if (typeof item === 'string') { + return resolvePage(pages, item, base) + } else if (Array.isArray(item)) { + return Object.assign(resolvePage(pages, item[0], base), { + title: item[1] + }) + } else { + if (isNested) { + console.error( + '[vuepress] Nested sidebar groups are not supported. ' + + 'Consider using navbar + categories instead.' + ) + } + const children = item.children || [] + return { + type: 'group', + title: item.title, + children: children.map(child => resolveItem(child, pages, base, true)), + collapsable: item.collapsable !== false + } + } +} |
