chore: merge vant-doc to vant-cli

This commit is contained in:
陈嘉涵
2019-11-18 21:02:36 +08:00
parent 80c09566fe
commit b7d142322b
25 changed files with 40 additions and 218 deletions

View File

@@ -51,7 +51,6 @@
"@babel/preset-env": "^7.7.1",
"@babel/preset-typescript": "^7.7.2",
"@types/jest": "^24.0.22",
"@vant/doc": "^2.6.1",
"@vant/eslint-config": "^1.4.0",
"@vant/markdown-loader": "^2.2.0",
"@vant/markdown-vetur": "^1.0.0",

View File

@@ -0,0 +1,46 @@
@import './variable';
body {
min-width: 1100px;
margin: 0;
overflow-x: auto;
color: #333;
font-size: 16px;
font-family: PingFang SC, 'Helvetica Neue', Arial, sans-serif;
background-color: #f0f3f6;
-webkit-font-smoothing: antialiased;
}
p {
margin: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
font-size: inherit;
}
ul,
ol {
margin: 0;
padding: 0;
list-style: none;
}
a {
text-decoration: none;
}
.van-doc-row {
width: 100%;
@media (min-width: @van-doc-row-max-width) {
width: @van-doc-row-max-width;
margin: 0 auto;
}
}

View File

@@ -0,0 +1,80 @@
@import './variable';
code {
position: relative;
display: block;
margin-top: 20px;
overflow-x: auto;
color: @van-doc-code-color;
font-weight: 400;
font-size: 13px;
font-family: @van-doc-code-font-family;
line-height: 24px;
white-space: pre-wrap;
word-wrap: break-word;
}
pre {
margin: 0;
}
.hljs {
display: block;
padding: 0.5em;
overflow-x: auto;
background: #fff;
}
.hljs-subst {
color: @van-doc-code-color;
}
.hljs-string,
.hljs-meta,
.hljs-symbol,
.hljs-template-tag,
.hljs-template-variable,
.hljs-addition {
color: @van-doc-purple;
}
.hljs-comment,
.hljs-quote {
color: #999;
}
.hljs-number,
.hljs-regexp,
.hljs-literal,
.hljs-bullet,
.hljs-link {
color: #07c160;
}
.hljs-deletion,
.hljs-variable {
color: #88f;
}
.hljs-attr,
.hljs-keyword,
.hljs-selector-tag,
.hljs-title,
.hljs-section,
.hljs-built_in,
.hljs-doctag,
.hljs-type,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-strong {
color: @van-doc-blue;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-attribute {
color: #e6550d;
}

View File

@@ -0,0 +1,3 @@
@import './variable';
@import './base';
@import './highlight';

View File

@@ -0,0 +1,26 @@
@van-doc-black: #323233;
@van-doc-blue: #1989fa;
@van-doc-purple: #5758bb;
@van-doc-fuchsia: #a7419e;
@van-doc-text-color: #34495e;
@van-doc-text-light-blue: rgba(69, 90, 100, .6);
@van-doc-grey: #999;
@van-doc-dark-grey: #666;
@van-doc-light-grey: #ccc;
@van-doc-border-color: #f1f4f8;
@van-doc-code-color: #455a64;
@van-doc-code-background-color: #f1f4f8;
@van-doc-code-font-family: 'Source Code Pro', 'Monaco', 'Inconsolata', monospace;
@van-doc-padding: 30px;
@van-doc-row-max-width: 1680px;
@van-doc-nav-width: 220px;
// header
@van-doc-header-top-height: 60px;
@van-doc-header-bottom-height: 50px;
// simulator
@van-doc-simulator-width: 360px;
@van-doc-simulator-small-width: 320px;
@van-doc-simulator-height: 620px;
@van-doc-simulator-small-height: 560px;

View File

@@ -7,9 +7,14 @@
</template>
<script>
import VanDoc from './components';
import { config } from '../../dist/desktop-config';
export default {
components: {
VanDoc
},
data() {
return {
config,

View File

@@ -0,0 +1,36 @@
<template>
<div
class="van-doc-container van-doc-row"
:class="{ 'van-doc-container--with-simulator': hasSimulator }"
>
<slot />
</div>
</template>
<script>
export default {
name: 'van-doc-container',
props: {
hasSimulator: Boolean
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-container {
box-sizing: border-box;
padding-left: @van-doc-nav-width;
overflow: hidden;
&--with-simulator {
padding-right: @van-doc-simulator-width + @van-doc-padding;
@media (max-width: 1300px) {
padding-right: @van-doc-simulator-small-width + @van-doc-padding;
}
}
}
</style>

View File

@@ -0,0 +1,224 @@
<template>
<div :class="['van-doc-content', `van-doc-content--${currentPage}`]">
<slot />
</div>
</template>
<script>
export default {
name: 'van-doc-content',
computed: {
currentPage() {
const { path } = this.$route;
if (path) {
return path.split('/').slice(-1)[0];
}
return this.$route.name;
}
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-content {
position: relative;
flex: 1;
padding: 0 0 75px;
.card {
margin-bottom: 24px;
padding: 24px;
background-color: #fff;
border-radius: 6px;
box-shadow: 0 8px 12px #ebedf0;
}
a {
color: @van-doc-blue;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: @van-doc-black;
font-weight: normal;
line-height: 1.5;
&[id] {
cursor: pointer;
}
}
h1 {
margin: 0 0 30px;
font-size: 30px;
cursor: default;
}
h2 {
margin: 45px 0 20px;
font-size: 22px;
}
h3 {
margin-bottom: 12px;
font-weight: 500;
font-size: 17px;
}
h4 {
margin: 24px 0 12px;
font-weight: 500;
font-size: 15px;
}
h5 {
margin: 24px 0 12px;
font-weight: 500;
font-size: 14px;
}
p {
color: @van-doc-text-color;
font-size: 14px;
line-height: 26px;
}
table {
width: 100%;
margin-top: 12px;
color: @van-doc-text-color;
font-size: 13px;
line-height: 1.5;
border-radius: 6px;
border-collapse: collapse;
th {
padding: 8px 10px;
font-weight: 500;
text-align: left;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
td {
padding: 8px;
border-top: 1px solid @van-doc-code-background-color;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
code {
padding: 0 8px;
font-size: 13px;
font-family: inherit;
word-break: keep-all;
}
em {
color: @van-doc-fuchsia;
font-size: 12px;
font-family: @van-doc-code-font-family;
font-style: normal;
}
}
ul li,
ol li {
position: relative;
margin: 5px 0 5px 10px;
padding-left: 15px;
color: @van-doc-text-color;
font-size: 14px;
line-height: 22px;
&::before {
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
width: 6px;
height: 6px;
margin-top: 8px;
border: 1px solid @van-doc-dark-grey;
border-radius: 50%;
content: '';
}
}
hr {
margin: 30px 0;
border: 0 none;
border-top: 1px solid #eee;
}
p > code,
li > code,
table code {
display: inline;
margin: 2px 3px;
padding: 2px 5px;
background-color: #f0f2f5;
box-shadow: none;
}
section {
padding: 30px;
overflow: hidden;
}
blockquote {
margin: 20px 0 0;
padding: 16px;
color: rgba(52, 73, 94, 0.8);
font-size: 14px;
background-color: #ecf9ff;
border-left: 5px solid #50bfff;
border-radius: 4px;
}
img {
width: 100%;
margin: 15px 0;
box-shadow: 0 2px 4px #ebedf0;
}
&--changelog {
strong {
display: block;
margin: 12px 0;
font-weight: 500;
font-size: 15px;
}
h3 {
+ p code {
margin: 0;
}
a {
color: inherit;
font-size: 20px;
}
}
}
}
</style>

View File

@@ -0,0 +1,236 @@
<template>
<div class="van-doc-header">
<div class="van-doc-row">
<div class="van-doc-header__top">
<a class="van-doc-header__logo" :href="config.logo.href">
<img :src="config.logo.image">
<span>{{ config.logo.title }}</span>
</a>
<search-input v-if="searchConfig" :lang="lang" :search-config="searchConfig" />
<ul class="van-doc-header__top-nav">
<li v-for="item in config.nav.logoLink" class="van-doc-header__top-nav-item">
<a class="van-doc-header__logo-link" target="_blank" :href="item.url">
<img :src="item.image">
</a>
</li>
<li ref="version" v-if="versions" class="van-doc-header__top-nav-item">
<span class="van-doc-header__cube van-doc-header__version" @click="toggleVersionPop">
{{ versions[0] }}
<transition name="van-doc-dropdown">
<div v-if="showVersionPop" class="van-doc-header__version-pop">
<div
v-for="item in versions"
class="van-doc-header__version-pop-item"
@click="onSwitchVersion(item)"
>{{ item }}</div>
</div>
</transition>
</span>
</li>
<li v-if="config.nav.lang" class="van-doc-header__top-nav-item">
<a class="van-doc-header__cube" :href="langLink">{{ config.nav.lang.text }}</a>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import SearchInput from './SearchInput';
export default {
name: 'van-doc-header',
components: {
SearchInput
},
props: {
lang: String,
config: Object,
versions: Array,
searchConfig: Object
},
data() {
return {
showVersionPop: false
};
},
computed: {
langLink() {
const { lang } = this.config.nav;
return `#${this.$route.path.replace(lang.from, lang.to)}`;
}
},
methods: {
toggleVersionPop() {
const val = !this.showVersionPop;
const action = val ? 'add' : 'remove';
document.body[`${action}EventListener`]('click', this.checkHideVersionPop);
this.showVersionPop = val;
},
checkHideVersionPop(event) {
if (!this.$refs.version.contains(event.target)) {
this.showVersionPop = false;
}
},
onSwitchLang(lang) {
this.$router.push(this.$route.path.replace(lang.from, lang.to));
},
onSwitchVersion(version) {
this.$emit('switch-version', version);
}
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-header {
width: 100%;
box-shadow: 0 4px 12px #ebedf0;
user-select: none;
&__top {
display: flex;
align-items: center;
height: @van-doc-header-top-height;
padding: 0 @van-doc-padding;
line-height: @van-doc-header-top-height;
background-color: #001938;
&-nav {
flex: 1;
font-size: 0;
text-align: right;
> li {
position: relative;
display: inline-block;
vertical-align: middle;
}
&-item {
margin-left: 20px;
}
&-title {
display: block;
font-size: 15px;
}
}
}
&__cube {
position: relative;
display: block;
padding: 0 10px;
color: #fff;
font-size: 14px;
font-family: 'Helvetica Neue', Arial, sans-serif;
line-height: 24px;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.7);
border-radius: 20px;
cursor: pointer;
transition: 0.3s ease-in-out;
}
&__version {
padding-right: 20px;
&::after {
position: absolute;
top: 7px;
right: 7px;
width: 5px;
height: 5px;
color: rgba(255, 255, 255, 0.9);
border: 1px solid;
border-color: transparent transparent currentColor currentColor;
transform: rotate(-45deg);
content: '';
}
&-pop {
position: absolute;
top: 30px;
right: 0;
left: 0;
z-index: 99;
color: #333;
line-height: 36px;
text-align: left;
background-color: #fff;
border-radius: 3px;
box-shadow: 0 4px 12px #ebedf0;
transform-origin: top;
transition: 0.2s cubic-bezier(0.215, 0.61, 0.355, 1);
&-item {
padding-left: 7px;
transition: 0.2s;
&:hover {
color: @van-doc-blue;
}
}
}
}
&__logo {
display: block;
img,
span {
display: inline-block;
vertical-align: middle;
}
img {
width: 24px;
margin-right: 10px;
}
span {
color: #fff;
font-size: 22px;
}
}
&__logo-link {
img {
display: block;
width: 26px;
height: 26px;
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
&:hover {
transform: scale(1.2);
}
}
}
}
.van-doc-dropdown {
&-enter,
&-leave-active {
transform: scaleY(0);
opacity: 0;
}
}
</style>

View File

@@ -0,0 +1,183 @@
<template>
<div class="van-doc-nav" :style="style">
<div v-for="(item, index) in navConfig" class="van-doc-nav__item" :key="index">
<van-doc-nav-link :item="item" :base="base" />
<div v-if="item.children">
<div
class="nav-item van-doc-nav__group-title van-doc-nav__group-title"
v-for="(navItem, navIndex) in item.children"
:key="navIndex"
>
<van-doc-nav-link :item="navItem" :base="base" />
</div>
</div>
<template v-if="item.groups">
<div v-for="(group, groupIndex) in item.groups" :key="groupIndex">
<div class="van-doc-nav__group-title">{{ group.groupName }}</div>
<div>
<template v-for="(navItem, navItemIndex) in group.list">
<div v-if="!navItem.disabled" :key="navItemIndex" class="van-doc-nav__subitem">
<van-doc-nav-link :item="navItem" :base="base" />
</div>
</template>
</div>
</div>
</template>
</div>
</div>
</template>
<script>
import NavLink from './NavLink';
export default {
name: 'van-doc-nav',
components: {
[NavLink.name]: NavLink
},
props: {
navConfig: Array,
base: {
type: String,
default: ''
}
},
data() {
return {
top: 60,
bottom: 0
};
},
computed: {
style() {
return {
top: this.top + 'px',
bottom: this.bottom + 'px'
};
}
},
created() {
window.addEventListener('scroll', this.onScroll);
this.onScroll();
},
methods: {
onScroll() {
const { pageYOffset: offset } = window;
this.top = Math.max(0, 60 - offset);
}
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-nav {
position: fixed;
top: 60px;
bottom: 0;
left: 0;
z-index: 1;
min-width: @van-doc-nav-width;
max-width: @van-doc-nav-width;
padding: 25px 0 75px;
overflow-y: scroll;
background-color: #fff;
border-right: 1px solid @van-doc-border-color;
box-shadow: 0 8px 12px #ebedf0;
@media (min-width: @van-doc-row-max-width) {
left: 50%;
margin-left: -(@van-doc-row-max-width / 2);
}
&::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
&::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 6px;
}
&:hover::-webkit-scrollbar-thumb {
background-color: rgba(69, 90, 100, 0.2);
}
&__item,
&__subitem {
a {
display: block;
margin: 0;
padding: 10px 0 10px @van-doc-padding;
color: #455a64;
font-size: 16px;
line-height: 24px;
transition: all 0.3s;
&.active {
color: #000;
font-weight: 500;
font-size: 15px;
}
}
}
&__item {
> a {
font-weight: 500;
}
}
&__subitem {
a {
font-size: 14px;
&:hover {
color: #000;
}
}
span {
font-size: 13px;
}
}
&__group-title {
padding-left: @van-doc-padding;
color: @van-doc-text-light-blue;
font-size: 12px;
line-height: 40px;
}
@media (max-width: 1300px) {
min-width: 220px;
max-width: 220px;
&__item,
&__subitem {
a {
line-height: 22px;
}
}
&__subitem {
a {
font-size: 13px;
}
&:active {
font-size: 14px;
}
}
}
}
</style>

View File

@@ -0,0 +1,23 @@
<template>
<router-link v-if="item.path" active-class="active" :to="base + item.path" v-html="itemName" />
<a v-else-if="item.link" :href="item.link" v-html="itemName" />
<a v-else v-html="itemName " />
</template>
<script>
export default {
name: 'van-doc-nav-link',
props: {
base: String,
item: Object
},
computed: {
itemName() {
const name = (this.item.title || this.item.name).split(' ');
return `${name[0]} <span>${name.slice(1).join(' ')}</span>`;
}
}
};
</script>

View File

@@ -0,0 +1,101 @@
<template>
<input class="van-doc-search" :placeholder="searchPlaceholder">
</template>
<script>
export default {
name: 'van-doc-search',
props: {
lang: String,
searchConfig: Object
},
computed: {
searchPlaceholder() {
return this.lang === 'zh-CN' ? '搜索文档...' : 'Search...';
}
},
watch: {
lang(lang) {
if (this.docsearchInstance) {
this.docsearchInstance.algoliaOptions.facetFilters = [`lang:${lang}`];
}
}
},
mounted() {
if (this.searchConfig) {
this.docsearchInstance = window.docsearch({
...this.searchConfig,
inputSelector: '.van-doc-search',
algoliaOptions: {
facetFilters: [`lang:${this.lang}`]
}
});
}
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-search {
width: 200px;
height: 60px;
margin-left: 140px;
color: #fff;
font-size: 14px;
background-color: transparent;
border: none;
&:focus {
outline: none;
}
&::placeholder {
color: #fff;
opacity: 0.7;
}
}
.ds-dropdown-menu {
line-height: 1.8;
}
.algolia-autocomplete {
.algolia-docsearch-suggestion--highlight {
color: @van-doc-blue;
background-color: transparent;
}
.algolia-docsearch-suggestion--title {
font-weight: 500;
}
.algolia-docsearch-suggestion--text {
.algolia-docsearch-suggestion--highlight {
box-shadow: inset 0 -1px 0 0 @van-doc-blue;
}
}
.algolia-docsearch-suggestion--category-header {
border-bottom-color: #eee;
}
.ds-dropdown-menu [class^='ds-dataset-'] {
border: none;
}
.ds-dropdown-menu {
top: 80% !important;
box-shadow: 0 4px 12px #ebedf0;
&::before {
display: none;
}
}
}
</style>

View File

@@ -0,0 +1,87 @@
<template>
<div :class="['van-doc-simulator', { 'van-doc-simulator-fixed': isFixed }]">
<iframe ref="iframe" :src="src" :style="simulatorStyle" frameborder="0" />
</div>
</template>
<script>
export default {
name: 'van-doc-simulator',
props: {
src: String
},
data() {
return {
scrollTop: window.scrollY,
windowHeight: window.innerHeight
};
},
computed: {
isFixed() {
return this.scrollTop > 60;
},
simulatorStyle() {
const height = Math.min(640, this.windowHeight - 90);
return {
height: height + 'px'
};
}
},
mounted() {
window.addEventListener('scroll', () => {
this.scrollTop = window.scrollY;
});
window.addEventListener('resize', () => {
this.windowHeight = window.innerHeight;
});
}
};
</script>
<style lang="less">
@import '../../common/style/index';
.van-doc-simulator {
position: absolute;
top: @van-doc-padding + @van-doc-header-top-height;
right: @van-doc-padding;
z-index: 1;
box-sizing: border-box;
width: @van-doc-simulator-width;
min-width: @van-doc-simulator-width;
overflow: hidden;
background: #fafafa;
border-radius: 6px;
box-shadow: #ebedf0 0 4px 12px;
@media (max-width: 1300px) {
width: @van-doc-simulator-small-width;
min-width: @van-doc-simulator-small-width;
}
@media (max-width: 1100px) {
right: auto;
left: 750px;
}
@media (min-width: @van-doc-row-max-width) {
right: 50%;
margin-right: -@van-doc-row-max-width / 2 + 40px;
}
&-fixed {
position: fixed;
top: @van-doc-padding;
}
iframe {
display: block;
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="van-doc">
<doc-header
:lang="lang"
:versions="versions"
:config="config.header"
:search-config="searchConfig"
@switch-version="$emit('switch-version', $event)"
/>
<doc-nav :base="base" :nav-config="config.nav" />
<doc-container :has-simulator="!!(simulator || simulators.length)">
<doc-content>
<slot />
</doc-content>
</doc-container>
<doc-simulator v-if="simulator" :src="simulator" />
<doc-simulator
v-for="(url, index) in simulators"
v-show="index === currentSimulator"
:src="url"
:key="url"
/>
</div>
</template>
<script>
import DocNav from './Nav';
import DocHeader from './Header';
import DocContent from './Content';
import DocContainer from './Container';
import DocSimulator from './Simulator';
export default {
name: 'van-doc',
components: {
DocNav,
DocHeader,
DocContent,
DocContainer,
DocSimulator
},
props: {
lang: String,
versions: Array,
searchConfig: Object,
currentSimulator: Number,
simulator: String,
config: {
type: Object,
required: true
},
simulators: {
type: Array,
default: () => []
},
base: {
type: String,
default: ''
}
},
data() {
return {
nav: [],
currentPath: null,
leftNav: null,
rightNav: null
};
},
watch: {
// eslint-disable-next-line
'$route.path'() {
this.setNav();
this.updateNav();
}
},
created() {
this.setNav();
this.updateNav();
this.keyboardHandler();
},
methods: {
setNav() {
const { nav } = this.config;
for (let i = 0; i < nav.length; i++) {
const navItem = nav[i];
if (!navItem.groups) {
this.nav.push(nav[i]);
} else {
for (let j = 0; j < navItem.groups.length; j++) {
this.nav = this.nav.concat(navItem.groups[j].list);
}
}
}
},
updateNav() {
let currentIndex;
this.currentPath = '/' + this.$route.path.split('/').pop();
for (let i = 0, len = this.nav.length; i < len; i++) {
if (this.nav[i].path === this.currentPath) {
currentIndex = i;
break;
}
}
this.leftNav = this.nav[currentIndex - 1];
this.rightNav = this.nav[currentIndex + 1];
},
handleNavClick(direction) {
const nav = direction === 'prev' ? this.leftNav : this.rightNav;
if (nav.path) {
this.$router.push(this.base + nav.path);
} else if (nav.link) {
window.location.href = nav.link;
}
},
keyboardHandler() {
window.addEventListener('keyup', event => {
switch (event.keyCode) {
case 37: // left
this.handleNavClick('prev');
break;
case 39: // right
this.handleNavClick('next');
break;
}
});
}
}
};
</script>
<style lang="less">
@import '../../common/style/index';
</style>

View File

@@ -1,12 +1,10 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import VantDoc from '@vant/doc';
import App from './App';
import routes from './router';
import { isMobile } from '../common';
import '../common/iframe-router';
Vue.use(VantDoc);
Vue.use(VueRouter);
if (isMobile) {

View File

@@ -1,6 +1,6 @@
<template>
<div>
<nav-bar />
<demo-nav />
<keep-alive>
<router-view />
</keep-alive>

View File

@@ -16,7 +16,7 @@ export default {
</script>
<style lang="less">
@import '../style/variable';
@import '../../common/style/index';
.van-doc-demo-block {
&__title {

View File

@@ -1421,11 +1421,6 @@
semver "^6.3.0"
tsutils "^3.17.1"
"@vant/doc@^2.6.1":
version "2.6.1"
resolved "https://registry.npm.taobao.org/@vant/doc/download/@vant/doc-2.6.1.tgz#667db2ca32cd86f3def452a03c66076c1b97c969"
integrity sha1-Zn2yyjLNhvPe9FKgPGYHbBuXyWk=
"@vant/eslint-config@^1.4.0":
version "1.4.0"
resolved "https://registry.npm.taobao.org/@vant/eslint-config/download/@vant/eslint-config-1.4.0.tgz#c9464beeea842a5ec64e5af714923a0cadf523b3"