-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathenhanceApp.js
142 lines (131 loc) · 3.84 KB
/
enhanceApp.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import getRedirectRouter from '@theme-config/redirectRouter';
import VueRouter from 'vue-router';
import { isServer } from './util';
import OutboundLink from '@theme/components/OutboundLink.vue';
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location, resolve, reject) {
if (resolve || reject) return originalPush.call(this, location, resolve, reject);
return originalPush.call(this, location).catch(err => err);
};
function handleRedirectForCleanUrls(router, to) {
if (isRouteExists(router, to.path)) {
return to.path;
} else {
if (!/(\/|\.html)$/.test(to.path)) {
const endingSlashUrl = to.path + '/';
const endingHtmlUrl = to.path + '.html';
if (isRouteExists(router, endingHtmlUrl)) {
return endingHtmlUrl;
} else if (isRouteExists(router, endingSlashUrl)) {
return endingSlashUrl;
} else {
return to.path.replace(/\.md$/, '');
}
} else if (/\/$/.test(to.path)) {
const endingHtmlUrl = to.path.replace(/\/$/, '') + '.html';
if (isRouteExists(router, endingHtmlUrl)) {
return endingHtmlUrl;
} else {
return to.path;
}
} else {
return to.path;
}
}
}
function isRouteExists(router, path) {
const pathLower = path.toLowerCase();
return router.options.routes.some(route => route.path.toLowerCase() === pathLower);
}
function resolveRouterBase(router, redirectPath) {
if (router.options.base !== '/') redirectPath = (router.options.base + redirectPath).replace(/\/\//g, '/');
return redirectPath;
}
function handlePath(router, to) {
// 重定向路由表
const redirectRouter = getRedirectRouter(to);
if (redirectRouter && !isServer) return location.replace(redirectRouter.path + (redirectRouter.hash || ''));
const id = to.query.id;
delete to.query.id;
let hash = decodeURIComponent(id || to.hash).toLowerCase();
if (hash && hash.indexOf('#') !== 0) hash = '#' + hash;
const redirectPath = handleRedirectForCleanUrls(router, to);
if (id) {
return {
path: resolveRouterBase(router, redirectPath),
replace: true,
hash,
query: to.query,
};
}
if (redirectPath !== to.path) {
return {
path: resolveRouterBase(router, redirectPath),
replace: true,
hash,
query: to.query,
};
}
if (/\bREADME\b/.test(to.path)) {
return {
path: to.path.replace(/\bREADME\b/, ''),
replace: true,
hash,
query: to.query,
};
}
}
export default ({ Vue, options, router, siteData }) => {
let mounted = Vue.$vuepress.store._isMounted;
// debugger
const ScrollBehavior = 'instant';
router.beforeHooks.unshift((to, from, next) => {
const _next = handlePath(router, to);
if (_next && /\.html$/.test(_next.path) && !isServer) return location.replace(_next.path + (_next.hash || ''));
else next(_next);
});
router.options.scrollBehavior = function scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return window.scrollTo({
top: savedPosition.y,
behavior: ScrollBehavior,
});
} else if (to.hash) {
if (Vue.$vuepress.$get('disableScrollBehavior')) {
return false;
}
const selector = decodeURIComponent(to.hash.toLowerCase());
return new Promise((resolve, reject) => {
setTimeout(
() => {
if (!mounted) mounted = true;
const targetElement = document.querySelector(selector);
if (targetElement) {
return window.scrollTo({
top: getElementPosition(targetElement).y,
behavior: ScrollBehavior,
});
}
return resolve(false);
},
mounted ? 0 : 700
);
});
} else {
return window.scrollTo({
top: 0,
behavior: ScrollBehavior,
});
}
};
Vue.component('OutboundLink', OutboundLink);
};
function getElementPosition(el) {
const docEl = document.documentElement;
const docRect = docEl.getBoundingClientRect();
const elRect = el.getBoundingClientRect();
return {
x: elRect.left - docRect.left,
y: elRect.top - docRect.top,
};
}