first commit
This commit is contained in:
1
vant/packages/vant-cli/site/.pydio
Normal file
1
vant/packages/vant-cli/site/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
58a0e612-6925-4750-9303-c27fbbc62ff6
|
||||
1
vant/packages/vant-cli/site/common/.pydio
Normal file
1
vant/packages/vant-cli/site/common/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
2c196b31-1743-44f5-bc79-6d655593b8ad
|
||||
29
vant/packages/vant-cli/site/common/iframe-router.js
Normal file
29
vant/packages/vant-cli/site/common/iframe-router.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 同步父窗口和 iframe 的 vue-router 状态
|
||||
*/
|
||||
|
||||
import { iframeReady, isMobile } from '.';
|
||||
|
||||
window.syncPath = function() {
|
||||
const router = window.vueRouter;
|
||||
const isInIframe = window !== window.top;
|
||||
const currentDir = router.history.current.path;
|
||||
|
||||
if (isInIframe) {
|
||||
window.top.replacePath(currentDir);
|
||||
} else if (!isMobile) {
|
||||
const iframe = document.querySelector('iframe');
|
||||
if (iframe) {
|
||||
iframeReady(iframe, () => {
|
||||
iframe.contentWindow.replacePath(currentDir);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.replacePath = function(path = '') {
|
||||
// should preserve hash for anchor
|
||||
if (window.vueRouter.currentRoute.path !== path) {
|
||||
window.vueRouter.replace(path).catch(() => {});
|
||||
}
|
||||
};
|
||||
30
vant/packages/vant-cli/site/common/index.js
Normal file
30
vant/packages/vant-cli/site/common/index.js
Normal file
@@ -0,0 +1,30 @@
|
||||
function iframeReady(iframe, callback) {
|
||||
const doc = iframe.contentDocument || iframe.contentWindow.document;
|
||||
const interval = () => {
|
||||
if (iframe.contentWindow.replacePath) {
|
||||
callback();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
interval();
|
||||
}, 50);
|
||||
}
|
||||
};
|
||||
|
||||
if (doc.readyState === 'complete') {
|
||||
interval();
|
||||
} else {
|
||||
iframe.onload = interval;
|
||||
}
|
||||
}
|
||||
|
||||
const ua = navigator.userAgent.toLowerCase();
|
||||
const isMobile = /ios|iphone|ipod|ipad|android/.test(ua);
|
||||
|
||||
export function decamelize(str, sep = '-') {
|
||||
return str
|
||||
.replace(/([a-z\d])([A-Z])/g, '$1' + sep + '$2')
|
||||
.replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + sep + '$2')
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
export { isMobile, iframeReady };
|
||||
30
vant/packages/vant-cli/site/common/locales.js
Normal file
30
vant/packages/vant-cli/site/common/locales.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const ZH_CN = 'zh-CN';
|
||||
const EN_US = 'en-US';
|
||||
const CACHE_KEY = 'vant-cli-lang';
|
||||
|
||||
let currentLang = ZH_CN;
|
||||
|
||||
export function getLang() {
|
||||
return currentLang;
|
||||
}
|
||||
|
||||
export function setLang(lang) {
|
||||
currentLang = lang;
|
||||
localStorage.setItem(CACHE_KEY, lang);
|
||||
}
|
||||
|
||||
export function setDefaultLang(langFromConfig) {
|
||||
const cached = localStorage.getItem(CACHE_KEY);
|
||||
|
||||
if (cached) {
|
||||
currentLang = cached;
|
||||
return;
|
||||
}
|
||||
|
||||
if (navigator.language && navigator.language.indexOf('zh-') !== -1) {
|
||||
currentLang = ZH_CN;
|
||||
return;
|
||||
}
|
||||
|
||||
currentLang = langFromConfig || EN_US;
|
||||
}
|
||||
1
vant/packages/vant-cli/site/common/style/.pydio
Normal file
1
vant/packages/vant-cli/site/common/style/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
bec7060d-dbcd-4465-b730-de9b5ccae70a
|
||||
46
vant/packages/vant-cli/site/common/style/base.less
Normal file
46
vant/packages/vant-cli/site/common/style/base.less
Normal file
@@ -0,0 +1,46 @@
|
||||
@import './var';
|
||||
|
||||
body {
|
||||
min-width: 1100px;
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
color: @van-doc-black;
|
||||
font-size: 16px;
|
||||
font-family: PingFang SC, 'Helvetica Neue', Arial, sans-serif;
|
||||
background-color: @van-doc-background-color;
|
||||
-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;
|
||||
}
|
||||
}
|
||||
79
vant/packages/vant-cli/site/common/style/highlight.less
Normal file
79
vant/packages/vant-cli/site/common/style/highlight.less
Normal file
@@ -0,0 +1,79 @@
|
||||
@import './var';
|
||||
|
||||
code {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
overflow-x: auto;
|
||||
color: @van-doc-code-color;
|
||||
font-weight: 400;
|
||||
font-size: 13.4px;
|
||||
font-family: @van-doc-code-font-family;
|
||||
line-height: 26px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
|
||||
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-green;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.hljs-params,
|
||||
.hljs-keyword,
|
||||
.hljs-attribute {
|
||||
color: @van-doc-purple;
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-variable,
|
||||
.hljs-number,
|
||||
.hljs-regexp,
|
||||
.hljs-literal,
|
||||
.hljs-bullet,
|
||||
.hljs-link {
|
||||
color: #eb6f6f;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.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: #4994df;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
29
vant/packages/vant-cli/site/common/style/var.less
Normal file
29
vant/packages/vant-cli/site/common/style/var.less
Normal file
@@ -0,0 +1,29 @@
|
||||
@van-doc-black: #323233;
|
||||
@van-doc-blue: #1989fa;
|
||||
@van-doc-purple: #8080ff;
|
||||
@van-doc-fuchsia: #a7419e;
|
||||
@van-doc-green: #4fc08d;
|
||||
@van-doc-text-color: #34495e;
|
||||
@van-doc-text-light-blue: rgba(69, 90, 100, 0.6);
|
||||
@van-doc-background-color: #f7f8fa;
|
||||
@van-doc-grey: #999;
|
||||
@van-doc-dark-grey: #666;
|
||||
@van-doc-light-grey: #ccc;
|
||||
@van-doc-border-color: #f1f4f8;
|
||||
@van-doc-code-color: #58727e;
|
||||
@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;
|
||||
@van-doc-border-radius: 12px;
|
||||
|
||||
// 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;
|
||||
1
vant/packages/vant-cli/site/desktop/.pydio
Normal file
1
vant/packages/vant-cli/site/desktop/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
a19e2525-f848-4240-a0b0-be63b37c9f6b
|
||||
105
vant/packages/vant-cli/site/desktop/App.vue
Normal file
105
vant/packages/vant-cli/site/desktop/App.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<van-doc
|
||||
:lang="lang"
|
||||
:config="config"
|
||||
:versions="versions"
|
||||
:simulator="simulator"
|
||||
:lang-configs="langConfigs"
|
||||
>
|
||||
<router-view />
|
||||
</van-doc>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VanDoc from './components';
|
||||
import { config, packageVersion } from 'site-desktop-shared';
|
||||
import { setLang } from '../common/locales';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VanDoc,
|
||||
},
|
||||
|
||||
data() {
|
||||
const path = location.pathname.replace('/index', '/');
|
||||
|
||||
return {
|
||||
packageVersion,
|
||||
simulator: `${path}mobile.html${location.hash}`,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
lang() {
|
||||
const { lang } = this.$route.meta;
|
||||
return lang || '';
|
||||
},
|
||||
|
||||
langConfigs() {
|
||||
const { locales = {} } = config.site;
|
||||
return Object.keys(locales).map(key => ({
|
||||
lang: key,
|
||||
label: locales[key].langLabel || '',
|
||||
}));
|
||||
},
|
||||
|
||||
config() {
|
||||
const { locales } = config.site;
|
||||
|
||||
if (locales) {
|
||||
return locales[this.lang];
|
||||
}
|
||||
|
||||
return config.site;
|
||||
},
|
||||
|
||||
versions() {
|
||||
if (config.site.versions) {
|
||||
return [{ label: packageVersion }, ...config.site.versions];
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
lang(val) {
|
||||
setLang(val);
|
||||
this.setTitle();
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.setTitle();
|
||||
},
|
||||
|
||||
methods: {
|
||||
setTitle() {
|
||||
let { title } = this.config;
|
||||
|
||||
if (this.config.description) {
|
||||
title += ` - ${this.config.description}`;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../common/style/base';
|
||||
@import '../common/style/highlight';
|
||||
|
||||
.van-doc-intro {
|
||||
padding-top: 20px;
|
||||
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
1
vant/packages/vant-cli/site/desktop/components/.pydio
Normal file
1
vant/packages/vant-cli/site/desktop/components/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
aee38061-e7df-40fa-b330-e3c710239aa2
|
||||
32
vant/packages/vant-cli/site/desktop/components/Container.vue
Normal file
32
vant/packages/vant-cli/site/desktop/components/Container.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<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/var';
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
238
vant/packages/vant-cli/site/desktop/components/Content.vue
Normal file
238
vant/packages/vant-cli/site/desktop/components/Content.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<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/var';
|
||||
|
||||
.van-doc-content {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
padding: 0 0 75px;
|
||||
|
||||
.card {
|
||||
margin-bottom: 24px;
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
border-radius: @van-doc-border-radius;
|
||||
box-shadow: 0 8px 12px #ebedf0;
|
||||
}
|
||||
|
||||
a {
|
||||
margin: 0 1px;
|
||||
color: @van-doc-green;
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
|
||||
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: 16px;
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
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-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;
|
||||
|
||||
// version tag
|
||||
code {
|
||||
margin: 0;
|
||||
padding: 2px 6px;
|
||||
color: @van-doc-blue;
|
||||
font-weight: 500;
|
||||
font-size: 10px;
|
||||
background-color: fade(@van-doc-blue, 10%);
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
em {
|
||||
color: @van-doc-green;
|
||||
font-size: 12.5px;
|
||||
font-family: @van-doc-code-font-family;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
}
|
||||
|
||||
ul li,
|
||||
ol li {
|
||||
position: relative;
|
||||
margin: 5px 0 5px 10px;
|
||||
padding-left: 15px;
|
||||
color: @van-doc-text-color;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-top: 10px;
|
||||
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;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
word-break: keep-all;
|
||||
background-color: #f0f2f5;
|
||||
border-radius: 4px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
p > code {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 30px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 20px 0 0;
|
||||
padding: 16px;
|
||||
color: rgba(52, 73, 94, 0.8);
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
background-color: #ecf9ff;
|
||||
border-radius: @van-doc-border-radius;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
margin: 16px 0;
|
||||
border-radius: @van-doc-border-radius;
|
||||
}
|
||||
|
||||
&--changelog {
|
||||
strong {
|
||||
display: block;
|
||||
margin: 24px 0 12px;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
+ p code {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
273
vant/packages/vant-cli/site/desktop/components/Header.vue
Normal file
273
vant/packages/vant-cli/site/desktop/components/Header.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="van-doc-header">
|
||||
<div class="van-doc-row">
|
||||
<div class="van-doc-header__top">
|
||||
<a class="van-doc-header__logo">
|
||||
<img :src="config.logo" />
|
||||
<span>{{ config.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.links" class="van-doc-header__top-nav-item">
|
||||
<a
|
||||
class="van-doc-header__logo-link"
|
||||
target="_blank"
|
||||
:href="item.url"
|
||||
>
|
||||
<img :src="item.logo" />
|
||||
</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].label }}
|
||||
<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.label }}
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</span>
|
||||
</li>
|
||||
|
||||
<li v-if="langLabel && langLink" class="van-doc-header__top-nav-item">
|
||||
<a class="van-doc-header__cube" :href="langLink">{{ langLabel }}</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,
|
||||
langConfigs: Array,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
showVersionPop: false,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
langLink() {
|
||||
return `#${this.$route.path.replace(this.lang, this.anotherLang.lang)}`;
|
||||
},
|
||||
|
||||
langLabel() {
|
||||
return this.anotherLang.label;
|
||||
},
|
||||
|
||||
anotherLang() {
|
||||
const items = this.langConfigs.filter(item => item.lang !== this.lang);
|
||||
if (items.length) {
|
||||
return items[0];
|
||||
}
|
||||
|
||||
return {};
|
||||
},
|
||||
|
||||
searchConfig() {
|
||||
return this.config.searchConfig;
|
||||
},
|
||||
},
|
||||
|
||||
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) {
|
||||
if (version.link) {
|
||||
location.href = version.link;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-header {
|
||||
width: 100%;
|
||||
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 12px;
|
||||
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: @van-doc-border-radius;
|
||||
box-shadow: 0 4px 12px #ebedf0;
|
||||
transform-origin: top;
|
||||
transition: 0.2s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
|
||||
&-item {
|
||||
padding-left: 12px;
|
||||
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>
|
||||
158
vant/packages/vant-cli/site/desktop/components/Nav.vue
Normal file
158
vant/packages/vant-cli/site/desktop/components/Nav.vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="van-doc-nav" :style="style">
|
||||
<div
|
||||
v-for="(group, index) in navConfig"
|
||||
class="van-doc-nav__group"
|
||||
:key="index"
|
||||
>
|
||||
<div class="van-doc-nav__title">
|
||||
{{ group.title }}
|
||||
</div>
|
||||
<template v-if="group.items">
|
||||
<div
|
||||
v-for="(item, groupIndex) in group.items"
|
||||
:key="groupIndex"
|
||||
class="van-doc-nav__item"
|
||||
>
|
||||
<van-doc-nav-link :item="item" :base="base" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NavLink from './NavLink';
|
||||
|
||||
export default {
|
||||
name: 'van-doc-nav',
|
||||
|
||||
components: {
|
||||
[NavLink.name]: NavLink,
|
||||
},
|
||||
|
||||
props: {
|
||||
lang: String,
|
||||
navConfig: Array,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
top: 60,
|
||||
bottom: 0,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
style() {
|
||||
return {
|
||||
top: this.top + 'px',
|
||||
bottom: this.bottom + 'px',
|
||||
};
|
||||
},
|
||||
|
||||
base() {
|
||||
return this.lang ? `/${this.lang}/` : '/';
|
||||
},
|
||||
},
|
||||
|
||||
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/var';
|
||||
|
||||
.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: 24px 0 72px;
|
||||
overflow-y: scroll;
|
||||
background-color: #fff;
|
||||
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);
|
||||
}
|
||||
|
||||
&__group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
padding: 8px 0 8px @van-doc-padding;
|
||||
color: #455a64;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
a {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 8px 0 8px @van-doc-padding;
|
||||
color: #455a64;
|
||||
font-size: 14px;
|
||||
line-height: 28px;
|
||||
transition: color 0.2s;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: @van-doc-green;
|
||||
}
|
||||
|
||||
&.active {
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
&__item {
|
||||
a {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&:active {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
vant/packages/vant-cli/site/desktop/components/NavLink.vue
Normal file
62
vant/packages/vant-cli/site/desktop/components/NavLink.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<router-link
|
||||
v-if="item.path"
|
||||
:class="{ active }"
|
||||
:to="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>`;
|
||||
},
|
||||
|
||||
path() {
|
||||
return `${this.base}${this.item.path}`;
|
||||
},
|
||||
|
||||
active() {
|
||||
if (this.$route.path === this.path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.item.path === 'home') {
|
||||
return this.$route.path === this.base;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
active() {
|
||||
this.scrollIntoView();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.scrollIntoView();
|
||||
},
|
||||
|
||||
methods: {
|
||||
scrollIntoView() {
|
||||
if (this.active && this.$el && this.$el.scrollIntoViewIfNeeded) {
|
||||
this.$el.scrollIntoViewIfNeeded();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
101
vant/packages/vant-cli/site/desktop/components/SearchInput.vue
Normal file
101
vant/packages/vant-cli/site/desktop/components/SearchInput.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<input class="van-doc-search" :placeholder="placeholder" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'van-doc-search',
|
||||
|
||||
props: {
|
||||
lang: String,
|
||||
searchConfig: Object,
|
||||
},
|
||||
|
||||
computed: {
|
||||
placeholder() {
|
||||
return this.searchConfig.placeholder || '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/var';
|
||||
|
||||
.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>
|
||||
82
vant/packages/vant-cli/site/desktop/components/Simulator.vue
Normal file
82
vant/packages/vant-cli/site/desktop/components/Simulator.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<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/var';
|
||||
|
||||
.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: @van-doc-border-radius;
|
||||
box-shadow: #ebedf0 0 4px 12px;
|
||||
|
||||
@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>
|
||||
108
vant/packages/vant-cli/site/desktop/components/index.vue
Normal file
108
vant/packages/vant-cli/site/desktop/components/index.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="van-doc">
|
||||
<doc-header
|
||||
:lang="lang"
|
||||
:config="config"
|
||||
:versions="versions"
|
||||
:lang-configs="langConfigs"
|
||||
@switch-version="$emit('switch-version', $event)"
|
||||
/>
|
||||
<doc-nav :lang="lang" :nav-config="config.nav" />
|
||||
<doc-container :has-simulator="!!simulator">
|
||||
<doc-content>
|
||||
<slot />
|
||||
</doc-content>
|
||||
</doc-container>
|
||||
<doc-simulator v-if="simulator" :src="simulator" />
|
||||
</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,
|
||||
simulator: String,
|
||||
langConfigs: Array,
|
||||
config: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
base: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
// eslint-disable-next-line
|
||||
'$route.path'() {
|
||||
this.setNav();
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.setNav();
|
||||
this.keyboardHandler();
|
||||
},
|
||||
|
||||
methods: {
|
||||
setNav() {
|
||||
const { nav } = this.config;
|
||||
const items = nav.reduce((list, item) => list.concat(item.items), []);
|
||||
const currentPath = this.$route.path.split('/').pop();
|
||||
|
||||
let currentIndex;
|
||||
for (let i = 0, len = items.length; i < len; i++) {
|
||||
if (items[i].path === currentPath) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.leftNav = items[currentIndex - 1];
|
||||
this.rightNav = items[currentIndex + 1];
|
||||
},
|
||||
|
||||
keyboardNav(direction) {
|
||||
const nav = direction === 'prev' ? this.leftNav : this.rightNav;
|
||||
if (nav.path) {
|
||||
this.$router.push(this.base + nav.path);
|
||||
}
|
||||
},
|
||||
|
||||
keyboardHandler() {
|
||||
window.addEventListener('keyup', event => {
|
||||
switch (event.keyCode) {
|
||||
case 37: // left
|
||||
this.keyboardNav('prev');
|
||||
break;
|
||||
case 39: // right
|
||||
this.keyboardNav('next');
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
</style>
|
||||
43
vant/packages/vant-cli/site/desktop/index.html
Normal file
43
vant/packages/vant-cli/site/desktop/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta
|
||||
name="description"
|
||||
content="<%= htmlWebpackPlugin.options.description %>"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="<%= htmlWebpackPlugin.options.logo %>"
|
||||
/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<meta http-equiv="Cache-Control" content="no-cache" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<% if (htmlWebpackPlugin.options.baiduAnalytics) { %>
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement('script');
|
||||
hm.src =
|
||||
'https://hm.baidu.com/hm.js?<%= htmlWebpackPlugin.options.baiduAnalytics.seed %>';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body ontouchstart>
|
||||
<div id="app"></div>
|
||||
<script src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
19
vant/packages/vant-cli/site/desktop/main.js
Normal file
19
vant/packages/vant-cli/site/desktop/main.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import Vue from 'vue';
|
||||
import App from './App';
|
||||
import { router } from './router';
|
||||
import { scrollToAnchor } from './utils';
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Vue.config.productionTip = false;
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
mounted() {
|
||||
if (this.$route.hash) {
|
||||
scrollToAnchor(this.$route.hash);
|
||||
}
|
||||
},
|
||||
render: h => h(App),
|
||||
router,
|
||||
});
|
||||
119
vant/packages/vant-cli/site/desktop/router.js
Normal file
119
vant/packages/vant-cli/site/desktop/router.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import { isMobile, decamelize } from '../common';
|
||||
import { config, documents } from 'site-desktop-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import '../common/iframe-router';
|
||||
|
||||
if (isMobile) {
|
||||
location.replace('mobile.html' + location.hash);
|
||||
}
|
||||
|
||||
const { locales, defaultLang } = config.site;
|
||||
|
||||
setDefaultLang(defaultLang);
|
||||
|
||||
function parseName(name) {
|
||||
if (name.indexOf('_') !== -1) {
|
||||
const pairs = name.split('_');
|
||||
const component = pairs.shift();
|
||||
|
||||
return {
|
||||
component: `${decamelize(component)}`,
|
||||
lang: pairs.join('-'),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
component: `${decamelize(name)}`,
|
||||
lang: '',
|
||||
};
|
||||
}
|
||||
|
||||
function getLangFromRoute(route) {
|
||||
const lang = route.path.split('/')[1];
|
||||
const langs = Object.keys(locales);
|
||||
|
||||
if (langs.indexOf(lang) !== -1) {
|
||||
return lang;
|
||||
}
|
||||
|
||||
return getLang();
|
||||
}
|
||||
|
||||
function getRoutes() {
|
||||
const routes = [];
|
||||
const names = Object.keys(documents);
|
||||
|
||||
if (locales) {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: route => `/${getLangFromRoute(route)}/`,
|
||||
});
|
||||
} else {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: '/',
|
||||
});
|
||||
}
|
||||
|
||||
function addHomeRoute(Home, lang) {
|
||||
routes.push({
|
||||
name: lang,
|
||||
path: `/${lang || ''}`,
|
||||
component: Home,
|
||||
meta: { lang },
|
||||
});
|
||||
}
|
||||
|
||||
names.forEach(name => {
|
||||
const { component, lang } = parseName(name);
|
||||
|
||||
if (component === 'home') {
|
||||
addHomeRoute(documents[name], lang);
|
||||
}
|
||||
|
||||
if (lang) {
|
||||
routes.push({
|
||||
name: `${lang}/${component}`,
|
||||
path: `/${lang}/${component}`,
|
||||
component: documents[name],
|
||||
meta: {
|
||||
lang,
|
||||
name: component,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
routes.push({
|
||||
name: `${component}`,
|
||||
path: `/${component}`,
|
||||
component: documents[name],
|
||||
meta: {
|
||||
name: component,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
export const router = new VueRouter({
|
||||
mode: 'hash',
|
||||
routes: getRoutes(),
|
||||
scrollBehavior(to) {
|
||||
if (to.hash) {
|
||||
return { selector: to.hash };
|
||||
}
|
||||
|
||||
return { x: 0, y: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
Vue.nextTick(() => window.syncPath());
|
||||
});
|
||||
|
||||
window.vueRouter = router;
|
||||
19
vant/packages/vant-cli/site/desktop/utils.js
Normal file
19
vant/packages/vant-cli/site/desktop/utils.js
Normal file
@@ -0,0 +1,19 @@
|
||||
export function scrollToAnchor(selector) {
|
||||
let count = 0;
|
||||
|
||||
const timer = setInterval(() => {
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
el.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
});
|
||||
clearInterval(timer);
|
||||
} else {
|
||||
count++;
|
||||
|
||||
if (count > 10) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
1
vant/packages/vant-cli/site/mobile/.pydio
Normal file
1
vant/packages/vant-cli/site/mobile/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
30e8bd7d-e3e2-45e1-92b5-a2f0e3e45b0a
|
||||
30
vant/packages/vant-cli/site/mobile/App.vue
Normal file
30
vant/packages/vant-cli/site/mobile/App.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div>
|
||||
<demo-nav />
|
||||
<keep-alive>
|
||||
<router-view />
|
||||
</keep-alive>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DemoNav from './components/DemoNav';
|
||||
|
||||
export default {
|
||||
components: { DemoNav },
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../common/style/var';
|
||||
@import '../common/style/base';
|
||||
|
||||
body {
|
||||
min-width: 100vw;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
1
vant/packages/vant-cli/site/mobile/components/.pydio
Normal file
1
vant/packages/vant-cli/site/mobile/components/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
2ac1d033-d3a3-4e0c-bfd7-d9f0d1b5a9e5
|
||||
12
vant/packages/vant-cli/site/mobile/components/ArrowRight.vue
Normal file
12
vant/packages/vant-cli/site/mobile/components/ArrowRight.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<svg viewBox="0 0 1024 1024">
|
||||
<path
|
||||
fill="#B6C3D2"
|
||||
d="M601.1 556.5L333.8 289.3c-24.5-24.5-24.5-64.6 0-89.1s64.6-24.5 89.1 0l267.3 267.3c24.5 24.5 24.5 64.6 0 89.1-24.5 24.4-64.6 24.4-89.1-.1z"
|
||||
/>
|
||||
<path
|
||||
fill="#B6C3D2"
|
||||
d="M690.2 556.5L422.9 823.8c-24.5 24.5-64.6 24.5-89.1 0s-24.5-64.6 0-89.1l267.3-267.3c24.5-24.5 64.6-24.5 89.1 0 24.5 24.6 24.5 64.6 0 89.1z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
37
vant/packages/vant-cli/site/mobile/components/DemoBlock.vue
Normal file
37
vant/packages/vant-cli/site/mobile/components/DemoBlock.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div class="van-doc-demo-block">
|
||||
<h2 class="van-doc-demo-block__title">{{ title }}</h2>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'demo-block',
|
||||
|
||||
props: {
|
||||
title: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.van-doc-demo-block {
|
||||
&__title {
|
||||
margin: 0;
|
||||
padding: 32px 16px 16px;
|
||||
color: @van-doc-text-light-blue;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
.van-doc-demo-block__title {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
99
vant/packages/vant-cli/site/mobile/components/DemoHome.vue
Normal file
99
vant/packages/vant-cli/site/mobile/components/DemoHome.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div class="demo-home">
|
||||
<h1
|
||||
class="demo-home__title"
|
||||
:class="{ 'demo-home__title--small': smallTitle }"
|
||||
>
|
||||
<img :src="config.logo" />
|
||||
<span>{{ config.title }}</span>
|
||||
</h1>
|
||||
<h2 v-if="config.description" class="demo-home__desc">
|
||||
{{ config.description }}
|
||||
</h2>
|
||||
<template v-for="(group, index) in config.nav">
|
||||
<demo-home-nav :group="group" :lang="lang" :key="index" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { config } from 'site-mobile-shared';
|
||||
import DemoHomeNav from './DemoHomeNav';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DemoHomeNav,
|
||||
},
|
||||
|
||||
computed: {
|
||||
lang() {
|
||||
const { lang } = this.$route.meta;
|
||||
return lang;
|
||||
},
|
||||
|
||||
config() {
|
||||
const { locales } = config.site;
|
||||
|
||||
if (locales) {
|
||||
return locales[this.lang];
|
||||
}
|
||||
|
||||
return config.site;
|
||||
},
|
||||
|
||||
smallTitle() {
|
||||
return this.config.title.length >= 8;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.demo-home {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
padding: 46px 20px 20px;
|
||||
background: #fff;
|
||||
|
||||
&__title,
|
||||
&__desc {
|
||||
padding-left: 16px;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0 0 16px;
|
||||
font-size: 32px;
|
||||
|
||||
img,
|
||||
span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
span {
|
||||
margin-left: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&--small {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__desc {
|
||||
margin: 0 0 40px;
|
||||
color: rgba(69, 90, 100, 0.6);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="demo-home-nav">
|
||||
<div class="demo-home-nav__title">{{ group.title }}</div>
|
||||
<div class="demo-home-nav__group">
|
||||
<router-link
|
||||
class="demo-home-nav__block"
|
||||
v-for="navItem in group.items"
|
||||
:key="navItem.path"
|
||||
:to="`${base}/${navItem.path}`"
|
||||
>
|
||||
{{ navItem.title }}
|
||||
<arrow-right class="demo-home-nav__icon" />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ArrowRight from './ArrowRight';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ArrowRight,
|
||||
},
|
||||
|
||||
props: {
|
||||
lang: String,
|
||||
group: Object,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
active: [],
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
base() {
|
||||
return this.lang ? `/${this.lang}` : '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@import '../../common/style/var';
|
||||
|
||||
.demo-home-nav {
|
||||
&__title {
|
||||
margin: 24px 0 8px 16px;
|
||||
color: rgba(69, 90, 100, 0.6);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&__block {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin: 0 0 12px;
|
||||
padding-left: 20px;
|
||||
color: #323233;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
background: #f7f8fa;
|
||||
border-radius: 99px;
|
||||
transition: background 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: darken(#f7f8fa, 3%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: darken(#f7f8fa, 6%);
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: -8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
58
vant/packages/vant-cli/site/mobile/components/DemoNav.vue
Normal file
58
vant/packages/vant-cli/site/mobile/components/DemoNav.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div v-show="title" class="demo-nav">
|
||||
<div class="demo-nav__title">{{ title }}</div>
|
||||
<svg class="demo-nav__back" viewBox="0 0 1000 1000" @click="onBack">
|
||||
<path fill="#969799" fill-rule="evenodd" :d="path" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* eslint-disable max-len */
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
path:
|
||||
'M296.114 508.035c-3.22-13.597.473-28.499 11.079-39.105l333.912-333.912c16.271-16.272 42.653-16.272 58.925 0s16.272 42.654 0 58.926L395.504 498.47l304.574 304.574c16.272 16.272 16.272 42.654 0 58.926s-42.654 16.272-58.926 0L307.241 528.058a41.472 41.472 0 0 1-11.127-20.023z',
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
title() {
|
||||
const { name } = this.$route.meta || {};
|
||||
return name ? name.replace(/-/g, '') : '';
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onBack() {
|
||||
history.back();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.demo-nav {
|
||||
position: relative;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
|
||||
&__title {
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
&__back {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<section class="van-doc-demo-section" :class="demoName">
|
||||
<slot />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { decamelize } from '../../common';
|
||||
|
||||
export default {
|
||||
name: 'demo-section',
|
||||
|
||||
computed: {
|
||||
demoName() {
|
||||
const { meta } = this.$route || {};
|
||||
if (meta && meta.name) {
|
||||
return `demo-${decamelize(meta.name)}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.van-doc-demo-section {
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100vh - 56px);
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
41
vant/packages/vant-cli/site/mobile/index.html
Normal file
41
vant/packages/vant-cli/site/mobile/index.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta
|
||||
name="description"
|
||||
content="<%= htmlWebpackPlugin.options.description %>"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="<%= htmlWebpackPlugin.options.logo %>"
|
||||
/>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
|
||||
/>
|
||||
<meta http-equiv="Cache-Control" content="no-cache" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<% if (htmlWebpackPlugin.options.baiduAnalytics) { %>
|
||||
<script>
|
||||
// avoid to load analytics in iframe
|
||||
if (window.top === window) {
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement('script');
|
||||
hm.src =
|
||||
'https://hm.baidu.com/hm.js?<%= htmlWebpackPlugin.options.baiduAnalytics.seed %>';
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
}
|
||||
</script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body ontouchstart>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
21
vant/packages/vant-cli/site/mobile/main.js
Normal file
21
vant/packages/vant-cli/site/mobile/main.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import Vue from 'vue';
|
||||
import DemoBlock from './components/DemoBlock';
|
||||
import DemoSection from './components/DemoSection';
|
||||
import { router } from './router';
|
||||
import App from './App';
|
||||
import '@vant/touch-emulator';
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
Vue.config.productionTip = false;
|
||||
}
|
||||
|
||||
Vue.component(DemoBlock.name, DemoBlock);
|
||||
Vue.component(DemoSection.name, DemoSection);
|
||||
|
||||
setTimeout(() => {
|
||||
new Vue({
|
||||
el: '#app',
|
||||
render: h => h(App),
|
||||
router,
|
||||
});
|
||||
}, 0);
|
||||
98
vant/packages/vant-cli/site/mobile/router.js
Normal file
98
vant/packages/vant-cli/site/mobile/router.js
Normal file
@@ -0,0 +1,98 @@
|
||||
import Vue from 'vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import DemoHome from './components/DemoHome';
|
||||
import { decamelize } from '../common';
|
||||
import { demos, config } from 'site-mobile-shared';
|
||||
import { getLang, setDefaultLang } from '../common/locales';
|
||||
import '../common/iframe-router';
|
||||
|
||||
const { locales, defaultLang } = config.site;
|
||||
|
||||
setDefaultLang(defaultLang);
|
||||
|
||||
function getLangFromRoute(route) {
|
||||
const lang = route.path.split('/')[1];
|
||||
const langs = Object.keys(locales);
|
||||
|
||||
if (langs.indexOf(lang) !== -1) {
|
||||
return lang;
|
||||
}
|
||||
|
||||
return getLang();
|
||||
}
|
||||
|
||||
function getRoutes() {
|
||||
const routes = [];
|
||||
const names = Object.keys(demos);
|
||||
const langs = locales ? Object.keys(locales) : [];
|
||||
|
||||
if (langs.length) {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: route => `/${getLangFromRoute(route)}/`,
|
||||
});
|
||||
|
||||
langs.forEach(lang => {
|
||||
routes.push({
|
||||
path: `/${lang}`,
|
||||
component: DemoHome,
|
||||
meta: { lang },
|
||||
});
|
||||
});
|
||||
} else {
|
||||
routes.push({
|
||||
path: '*',
|
||||
redirect: () => '/',
|
||||
});
|
||||
|
||||
routes.push({
|
||||
path: '/',
|
||||
component: DemoHome,
|
||||
});
|
||||
}
|
||||
|
||||
names.forEach(name => {
|
||||
const component = decamelize(name);
|
||||
|
||||
if (langs.length) {
|
||||
langs.forEach(lang => {
|
||||
routes.push({
|
||||
name: `${lang}/${component}`,
|
||||
path: `/${lang}/${component}`,
|
||||
component: demos[name],
|
||||
meta: {
|
||||
name,
|
||||
lang,
|
||||
},
|
||||
});
|
||||
});
|
||||
} else {
|
||||
routes.push({
|
||||
name,
|
||||
path: `/${component}`,
|
||||
component: demos[name],
|
||||
meta: {
|
||||
name,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
export const router = new VueRouter({
|
||||
mode: 'hash',
|
||||
routes: getRoutes(),
|
||||
scrollBehavior: (to, from, savedPosition) => savedPosition || { x: 0, y: 0 },
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
if (!router.currentRoute.redirectedFrom) {
|
||||
Vue.nextTick(window.syncPath);
|
||||
}
|
||||
});
|
||||
|
||||
window.vueRouter = router;
|
||||
Reference in New Issue
Block a user