Compare commits

...

112 Commits

Author SHA1 Message Date
reco_luan
f5fdc3e7fa
Update README.md 2021-04-05 22:17:54 +08:00
reco_luan
99790e29f9
Create FUNDING.yml 2021-03-29 10:54:39 +08:00
reco_luan
1b19bfa135 chore: changelog 2021-03-07 02:22:25 +08:00
reco_luan
b6b195941d v1.6.6 2021-03-07 02:19:37 +08:00
reco_luan
bf2eaaca73 refactor(vuepress-theme-reco): display author only when set it
ISSUES CLOSED: #306
2021-03-07 01:52:46 +08:00
reco_luan
1649cc8511 chore(vuepress-theme-reco): changelog 2021-03-01 00:22:07 +08:00
reco_luan
7aa7b214b4 v1.6.6-alpha.0 2021-02-25 00:26:22 +08:00
reco_luan
f12c76b5cc
Merge pull request #319 from LiDengHui/master
fix(vuepress-theme-reco): vuecomponsition-api接口升级方式修改
2021-02-25 00:12:30 +08:00
李逍遥
898e61031f fix(vuepress-theme-reco): vuecomponsition-api接口升级方式修改
ISSUES CLOSED: #315
2021-02-23 15:52:51 +08:00
reco_luan
8fefc9f9ad fix(vuepress-theme-reco): fix bug of non-ASCII file names cause 404
ISSUES CLOSED: #276, #281
2021-02-18 21:52:22 +08:00
reco_luan
a6e28b073d chore(vuepress-theme-reco): optimize the style of mode picker
ISSUES CLOSED: #316
2021-02-18 21:06:27 +08:00
reco_luan
8a8e70c6c2 fix: restore the display of the sub sidebar 2021-02-18 21:02:36 +08:00
reco_luan
16a44fab19 chore(vuepress-theme-reco): changelog 2021-02-12 22:18:59 +08:00
reco_luan
612aaba960 v1.6.5 2021-02-12 14:40:15 +08:00
reco_luan
1da900081a fix(vuepress-theme-reco): fix content display error 2021-02-12 14:39:33 +08:00
reco_luan
26006febba v1.6.4 2021-02-08 22:09:15 +08:00
reco_luan
05126a4dc0 fix(vuepress-theme-reco): fix some little error 2021-02-08 22:08:29 +08:00
reco_luan
4ee3dbff00 v1.6.3 2021-02-08 21:14:40 +08:00
reco_luan
6a214c77fc fix(vuepress-theme-reco): fix init config of plugin pagation 2021-02-08 21:13:20 +08:00
reco_luan
87c0cc79a5 v1.6.2 2021-02-08 21:07:44 +08:00
reco_luan
07799bf7b9 fix(vuepress-theme-reco): fix posts number
ignore tags and categories of blog posts that have the publish property set to false

ISSUES CLOSED: #288
2021-02-08 12:52:34 +08:00
reco_luan
ff4e3aa7bb style(vuepress-theme-reco): optimize localization
and refactor layout comp using vca

ISSUES CLOSED: #293
2021-02-07 13:02:04 +08:00
reco_luan
a429df42cc fix(vuepress-theme-reco): fix h2 style
ISSUES CLOSED: #300
2021-02-07 00:00:10 +08:00
reco_luan
685e92d5af fix(vuepress-theme-reco): fix anchor point error
ISSUES CLOSED: #310
2021-02-06 22:43:59 +08:00
reco_luan
0a7418503d feat(vuepress-theme-reco): delete lastUpdated when set to false
ISSUES CLOSED: #311
2021-02-06 00:22:21 +08:00
reco_luan
4bae14b796 fix(vuepress-theme-reco): fix date error
ISSUES CLOSED: #312
2021-02-05 23:56:54 +08:00
reco_luan
d938979172 fix(vuepress-theme-reco): fix custom class name in front matter
ISSUES CLOSED: #301
2021-01-25 00:41:21 +08:00
reco_luan
7899d995bc fix(core): fix the display problem of icon
ISSUES CLOSED: #296
2021-01-18 23:41:47 +08:00
reco_luan
b216b31fe3 fix(vuepress-theme-reco): some error 2021-01-10 01:29:52 +08:00
reco_luan
30b7e1c088 refactor(vuepress-theme-reco): use vca 2021-01-09 02:02:43 +08:00
reco_luan
5fd6f88b37
Merge pull request #285 from Zenahr/master
Fix english localization for Categories, Friends Links and Tags labels
2020-12-28 00:02:05 +08:00
Zenahr
8a2e3f7080 fix default config.js localization for tags and categories. related to gh-283 2020-12-27 08:07:08 +01:00
Zenahr
d94e42c59e related to gh-283 2020-12-27 08:04:39 +01:00
reco_luan
612098765c chore: changelog 2020-12-12 04:33:58 +08:00
reco_luan
ec1eb4190d v1.6.1 2020-12-12 04:32:53 +08:00
reco_luan
119ad99306 fix: fix null pointer 2020-12-12 04:32:06 +08:00
reco_luan
51283c41db chore: changelog 2020-12-12 03:57:40 +08:00
reco_luan
65cf3b4ff8 v1.6.0 2020-12-12 03:50:06 +08:00
reco_luan
1108c55c5c chore: edit publishConfig 2020-12-12 03:49:34 +08:00
reco_luan
b1bfafce83 docs: update docs 2020-12-12 02:10:06 +08:00
reco_luan
895eac4983 fix: page title 2020-12-12 01:19:37 +08:00
reco_luan
3c52a9124f style: add submodules 2020-12-12 01:06:14 +08:00
reco_luan
189d5a4449
Merge pull request #279 from ThaePeng/master
fix: fix a bug about go back to home page url
2020-12-08 02:30:57 +08:00
pengtai
540c3365dc fix: fix a bug about go back to home page url 2020-12-06 01:50:26 +08:00
reco_luan
b90238c26a fix: fix a bug about siderbar display 2020-12-05 01:27:56 +08:00
reco_luan
27a9b3b78d refactor(theme): use VCA 2020-12-05 01:26:21 +08:00
reco_luan
ee860177fc refactor(theme): use VCA 2020-12-04 02:09:11 +08:00
reco_luan
1a57da8cd7 fix(theme-reco): fix animation 2020-12-03 01:59:46 +08:00
reco_luan
804fedc4b0 refactor(theme-reco): use compositionAPI 2020-12-03 01:59:14 +08:00
reco_luan
beea671c6a feat(vuepress-theme-reco): support time localization
ISSUES CLOSED: #255
2020-12-02 01:35:48 +08:00
reco_luan
1215e56f77 feat(vuepress-theme-reco): add social links
ISSUES CLOSED: #252
2020-12-02 00:55:02 +08:00
reco_luan
90e9fdc399 refactor(vuepress-theme-reco): module transition 2020-12-01 01:11:38 +08:00
reco_luan
5205fceb9d style(vuepress-theme-reco): remove mode.styl 2020-12-01 00:04:53 +08:00
reco_luan
68b44b7b4f refactor(core): improve the core package
ISSUES CLOSED: #261
2020-11-29 19:57:15 +08:00
reco_luan
e3892044a8 refactor(@vuepress-reco/core): refactor with typescript
ISSUES CLOSED: #261
2020-11-26 01:51:24 +08:00
reco_luan
eb50f364e6 chore(vuepress-theme-reco): optimize style
ISSUES CLOSED: #261
2020-11-12 01:06:20 +08:00
reco_luan
832d67476f fix: optimize style 2020-11-12 00:48:35 +08:00
reco_luan
d524a1b086
Merge pull request #271 from franklinqin0/develop
set defaultTitle always to empty string & make tip, warning, danger vertically centered
2020-11-12 00:22:05 +08:00
reco_luan
558c628821 chore(vuepress-theme-reco): intercept router error
ISSUES CLOSED: #272
2020-11-08 23:07:37 +08:00
reco_luan
1d724bba13
Update LICENSE 2020-10-28 15:49:02 +08:00
reco_luan
217abd30ac fix(vuepress-plugin-pagation): fix invalid bug with perPage
ISSUES CLOSED: #265
2020-10-24 02:50:20 +08:00
reco_luan
ddf1484fc6 Merge branch 'develop' of github.com:recoluan/vuepress-theme-reco 2020-10-23 01:40:51 +08:00
reco_luan
984ed3fc04 refactor(vuepress-theme-reco): refactor the font icon component
1. support Font Awesome
2. create @vuepress-reco/core
2020-10-23 00:42:07 +08:00
Franklin Qin
ad64d75699
Update custom-blocks.styl 2020-10-21 17:38:10 +08:00
Franklin Qin
0e8b6f10f2
Update index.js 2020-10-21 17:37:26 +08:00
reco_luan
16b53230d6 fix(vuepress-theme-reco): solve the problem of className
solve the problem of overlap between className and icon name
2020-10-21 00:11:25 +08:00
reco_luan
6688c86662 fix(vuepress-theme-reco): fix subSidebar invalid
ISSUES CLOSED: #267
2020-10-17 01:07:05 +08:00
reco_luan
7665374308 feat: add google analytics 2020-09-23 00:46:22 +08:00
reco_luan
4228274d5b
Update .gitignore 2020-09-23 00:06:06 +08:00
reco_luan
4ff1b60800
Delete yarn.lock 2020-09-23 00:04:39 +08:00
reco_luan
523fca45e5
Merge pull request #249 from vuepress-reco/dependabot/npm_and_yarn/http-proxy-1.18.1
build(deps): bump http-proxy from 1.18.0 to 1.18.1
2020-09-16 20:20:21 +08:00
reco_luan
4f5e65302e
Merge pull request #250 from vuepress-reco/dependabot/npm_and_yarn/node-fetch-2.6.1
build(deps): bump node-fetch from 2.6.0 to 2.6.1
2020-09-16 20:19:04 +08:00
reco_luan
30d08ec350 chore: changelog 2020-09-16 00:18:54 +08:00
reco_luan
98f64814b5 v1.5.7 2020-09-15 23:57:54 +08:00
reco_luan
00a4e3f5ba chore: add publishConfig 2020-09-15 23:51:10 +08:00
dependabot[bot]
6a4637537b
build(deps): bump node-fetch from 2.6.0 to 2.6.1
Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-12 15:51:51 +00:00
reco_luan
2fce1f82d5 chore: modify notice name as bullet-popover 2020-09-12 23:50:45 +08:00
dependabot[bot]
299cabfc74
build(deps): bump http-proxy from 1.18.0 to 1.18.1
Bumps [http-proxy](https://github.com/http-party/node-http-proxy) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/http-party/node-http-proxy/releases)
- [Changelog](https://github.com/http-party/node-http-proxy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/http-party/node-http-proxy/compare/1.18.0...1.18.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-11 18:38:16 +00:00
reco_luan
ddcf1cba63 chore(vuepress-theme-reco): compatible with sidebar parameters
1. You can control the sidebar by sidebar: 'auto'
2. some minor optimizations
2020-09-01 23:59:51 +08:00
reco_luan
885ffa3481
Update README.md 2020-08-27 19:27:09 +08:00
reco_luan
6496869ace feat(vuepress-plugin-pagation): set page size by plugin option
ISSUES CLOSED: #207
2020-08-25 16:16:42 +08:00
reco_luan
f3476f38d1 Merge branch 'develop' of github.com:vuepress-reco/vuepress-theme-reco into develop 2020-08-24 10:20:15 +08:00
reco_luan
c9f251dae5 feat: create plugin notice 2020-08-23 13:12:02 +08:00
reco_luan
4312914114
Merge pull request #235 from vuepress-reco/dependabot/npm_and_yarn/prismjs-1.21.0
build(deps): bump prismjs from 1.19.0 to 1.21.0
2020-08-17 00:12:18 +08:00
reco_luan
acb37b3d4d fix(vuepress-theme-reco): fix multi-language configuration err
ISSUES CLOSED: #229
2020-08-16 15:02:37 +08:00
reco_luan
84e9516e64 fix(vuepress-theme-reco): fix some style problems
ISSUES CLOSED: #231
2020-08-16 13:24:41 +08:00
reco_luan
5efa924d7b feat(vuepress-theme-reco): use subSidebar to control the sub sidebar 2020-08-08 13:20:54 +08:00
dependabot[bot]
8fb8497bff
build(deps): bump prismjs from 1.19.0 to 1.21.0
Bumps [prismjs](https://github.com/PrismJS/prism) from 1.19.0 to 1.21.0.
- [Release notes](https://github.com/PrismJS/prism/releases)
- [Changelog](https://github.com/PrismJS/prism/blob/master/CHANGELOG.md)
- [Commits](https://github.com/PrismJS/prism/compare/v1.19.0...v1.21.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-08 00:11:51 +00:00
reco_luan
d75005ea6f
Merge pull request #227 from vuepress-reco/dependabot/npm_and_yarn/elliptic-6.5.3
build(deps): bump elliptic from 6.5.2 to 6.5.3
2020-08-04 13:39:46 +08:00
dependabot[bot]
064bf09264
build(deps): bump elliptic from 6.5.2 to 6.5.3
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-01 21:24:23 +00:00
reco_luan
26178068eb chore(vuepress-theme-reco): changelog 2020-08-01 16:08:34 +08:00
reco_luan
1335240067 v1.5.5 2020-08-01 16:05:59 +08:00
reco_luan
6fd83e1ea2 perf(vuepress-theme-reco): optimize the home page and subSidebar 2020-08-01 16:04:28 +08:00
reco_luan
7b4468b379 Merge branch 'develop' of github.com:recoluan/vuepress-theme-reco into develop 2020-07-26 22:12:51 +08:00
reco_luan
1e0c6e5ac6
Merge pull request #225 from z3rog/develop
chore(vuepress-theme-reco): custom style base on theme mode
2020-07-26 20:36:19 +08:00
reco_luan
ab9480652b feat(vuepress-theme-reco): optimize blog homepage
1. change style of blog homepage
2. fix some bugs
2020-07-26 20:30:35 +08:00
z3rog
2831b8385f chore(vuepress-theme-reco): custom style base on theme mode 2020-07-26 17:22:13 +08:00
reco_luan
b56f3dede4
Merge pull request #222 from mkfsn/feature/locale-tag-label
feat(vuepress-theme-reco): add tag locale
2020-07-25 15:00:51 +08:00
reco_luan
ef29a4c25e
Merge pull request #219 from Mr-CHANX/develop
友链信息窗口优化
2020-07-25 14:56:23 +08:00
Pei-Ming Wu
7a7122125b feat: add locale for 'All' tag label 2020-07-22 09:16:57 +08:00
CHANX
b18c552f49
Update FriendLink.vue 2020-07-20 10:29:11 +08:00
reco_luan
cefba8039c
Merge pull request #170 from vuepress-reco/develop
1.4.3&1.4.4
2020-04-19 09:19:44 +08:00
reco_luan
872d21fd45
Merge pull request #160 from vuepress-reco/develop
VERSION 1.4.0
2020-04-03 23:37:43 +08:00
reco_luan
46ac35a4e0
Merge pull request #140 from vuepress-reco/develop
VERSION 1.3.2
2020-03-16 11:09:15 +08:00
reco_luan
7da15d0014
Merge pull request #139 from vuepress-reco/develop
VERSON 1.3.1
2020-03-16 10:46:07 +08:00
reco_luan
92e6afb6e5
Merge pull request #138 from vuepress-reco/develop
VERSON 1.3.0
2020-03-15 20:26:56 +08:00
reco_luan
1b52f8bf8c
Merge pull request #120 from vuepress-reco/develop
VERSION 1.2.2
2020-01-27 15:32:45 +08:00
reco_luan
139094a9c7 Merge branch 'develop' of github.com:recoluan/vuepress-theme-reco 2020-01-07 15:14:39 +08:00
reco_luan
b7a3b361b2
Merge pull request #118 from vuepress-reco/develop
1.2.0
2020-01-01 00:48:43 +08:00
reco_luan
671e3e68f4
Merge pull request #102 from vuepress-reco/develop
VERSION 1.1.2
2019-11-28 11:54:03 +08:00
reco_luan
26727eee29
Merge pull request #86 from vuepress-reco/develop
VERSION 1.1.1
2019-11-03 18:16:47 +08:00
reco_luan
a0ff8b023b
Merge pull request #70 from vuepress-reco/develop
VERSION 1.1.0
2019-10-20 22:37:06 +08:00
108 changed files with 2217 additions and 12651 deletions

View File

@ -51,6 +51,7 @@ module.exports = {
scopes: [
'vuepress-theme-reco',
'core',
'vuepress-plugin-back-to-top',
'vuepress-plugin-comments',
'vuepress-plugin-loading',

View File

@ -2,3 +2,6 @@ styles/
images/
node_modules/
.cz-config.js
lib/
libs/
dist/

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: 'https://vuepress-theme-reco.recoluan.com/views/other/donate.html'

6
.gitignore vendored
View File

@ -1,4 +1,10 @@
node_modules
yarn-error.log
.idea
yarn.lock
.DS_Store
.vscode
package-lock.json
lib
libs
dist

6
.gitmodules vendored Normal file
View File

@ -0,0 +1,6 @@
[submodule "packages/vuepress-reco.github.io"]
path = packages/vuepress-reco.github.io
url = git@github.com:vuepress-reco/vuepress-reco.github.io.git
[submodule "packages/theme-cli"]
path = packages/theme-cli
url = git@github.com:vuepress-reco/theme-cli.git

View File

@ -1,3 +1,80 @@
## [1.6.6](https://github.com/recoluan/vuepress-theme-reco/compare/v1.6.6-alpha.0...v1.6.6) (2021-03-06)
## [1.6.6-alpha.0](https://github.com/recoluan/vuepress-theme-reco/compare/v1.6.5...v1.6.6-alpha.0) (2021-02-24)
### Bug Fixes
* **vuepress-theme-reco:** fix bug of non-ASCII file names cause 404 ([8fefc9f](https://github.com/recoluan/vuepress-theme-reco/commit/8fefc9f9adb82412ef273a8474b7428659f24839)), closes [#276](https://github.com/recoluan/vuepress-theme-reco/issues/276) [#281](https://github.com/recoluan/vuepress-theme-reco/issues/281)
* **vuepress-theme-reco:** vuecomponsition-api接口升级方式修改 ([898e610](https://github.com/recoluan/vuepress-theme-reco/commit/898e61031f0516017ee4e1e04d187ecf06591ffc)), closes [#315](https://github.com/recoluan/vuepress-theme-reco/issues/315)
* restore the display of the sub sidebar ([8a8e70c](https://github.com/recoluan/vuepress-theme-reco/commit/8a8e70c6c2f7c2fe730559e36fd59f739614b089))
## [1.6.5](https://github.com/recoluan/vuepress-theme-reco/compare/v1.6.4...v1.6.5) (2021-02-12)
### Bug Fixes
* **vuepress-theme-reco:** fix content display error ([1da9000](https://github.com/recoluan/vuepress-theme-reco/commit/1da900081a78eedb06acaa82f77af677c665b5f9))
## [1.6.1](https://github.com/recoluan/vuepress-theme-reco/compare/v1.6.0...v1.6.1) (2020-12-11)
### Bug Fixes
* fix a bug about go back to home page url ([540c336](https://github.com/recoluan/vuepress-theme-reco/commit/540c3365dc0cbe4ee73a20f946b6065e3f7b1227))
* fix a bug about siderbar display ([b90238c](https://github.com/recoluan/vuepress-theme-reco/commit/b90238c26a2b39fb8ae824044fab6c7658960f04))
* optimize style ([832d674](https://github.com/recoluan/vuepress-theme-reco/commit/832d67476f79c006f30f1c93017f3a08d018c552))
* page title ([895eac4](https://github.com/recoluan/vuepress-theme-reco/commit/895eac4983be456f454dcd6f288b07ec51010ffa))
* **theme-reco:** fix animation ([1a57da8](https://github.com/recoluan/vuepress-theme-reco/commit/1a57da8cd7a28da19ab372949526245aea8169c3))
* **vuepress-plugin-pagation:** fix invalid bug with perPage ([217abd3](https://github.com/recoluan/vuepress-theme-reco/commit/217abd30acea8c33f6f34a893a275bc7a9a8bbb3)), closes [#265](https://github.com/recoluan/vuepress-theme-reco/issues/265)
* **vuepress-theme-reco:** fix subSidebar invalid ([6688c86](https://github.com/recoluan/vuepress-theme-reco/commit/6688c866627e3abfb25545f3f7d25a8ecc05e904)), closes [#267](https://github.com/recoluan/vuepress-theme-reco/issues/267)
* **vuepress-theme-reco:** solve the problem of className ([16b5323](https://github.com/recoluan/vuepress-theme-reco/commit/16b53230d6c9d3f4ef25b1d9674602aa6ab3f948))
### Features
* **vuepress-theme-reco:** add social links ([1215e56](https://github.com/recoluan/vuepress-theme-reco/commit/1215e56f77867f441919fe0fc3c55975814d1f93)), closes [#252](https://github.com/recoluan/vuepress-theme-reco/issues/252)
* **vuepress-theme-reco:** support time localization ([beea671](https://github.com/recoluan/vuepress-theme-reco/commit/beea671c6a0b9027dbde45dbb4243c0f9d1ca268)), closes [#255](https://github.com/recoluan/vuepress-theme-reco/issues/255)
## [1.5.7](https://github.com/recoluan/vuepress-theme-reco/compare/v1.5.5...v1.5.7) (2020-09-15)
### Bug Fixes
* **vuepress-theme-reco:** fix multi-language configuration err ([acb37b3](https://github.com/recoluan/vuepress-theme-reco/commit/acb37b3d4dcaa169f416c5ac3f4d5782865abdc9)), closes [#229](https://github.com/recoluan/vuepress-theme-reco/issues/229)
* **vuepress-theme-reco:** fix some style problems ([84e9516](https://github.com/recoluan/vuepress-theme-reco/commit/84e9516e64d2d9d4ed2d9df3e2a28bf64dbd6323)), closes [#231](https://github.com/recoluan/vuepress-theme-reco/issues/231)
### Features
* **vuepress-plugin-pagation:** set page size by plugin option ([6496869](https://github.com/recoluan/vuepress-theme-reco/commit/6496869ace0ca4571b7ea19a45b77d2764487d5d)), closes [#207](https://github.com/recoluan/vuepress-theme-reco/issues/207)
* create plugin notice ([c9f251d](https://github.com/recoluan/vuepress-theme-reco/commit/c9f251dae5f757a6cb8a689f382ba3e9ba438f6f))
* **vuepress-theme-reco:** use subSidebar to control the sub sidebar ([5efa924](https://github.com/recoluan/vuepress-theme-reco/commit/5efa924d7bb926223c571ad1393c2ff32aa6ca7b))
## [1.5.5](https://github.com/recoluan/vuepress-theme-reco/compare/v1.5.4...v1.5.5) (2020-08-01)
### Features
* **vuepress-theme-reco:** optimize blog homepage ([ab94806](https://github.com/recoluan/vuepress-theme-reco/commit/ab9480652bfc8374fcf53df7dabee40641779eeb))
* **vuepress-theme-reco:** add locale for 'All' tag label ([7a71221](https://github.com/recoluan/vuepress-theme-reco/commit/7a7122125b897c4316e32d5135f036184e01fa03))
### Performance Improvements
* **vuepress-theme-reco:** optimize the home page and subSidebar ([6fd83e1](https://github.com/recoluan/vuepress-theme-reco/commit/6fd83e1ea295ce398c13523739b0900dedfd06d7))
## [1.5.4](https://github.com/recoluan/vuepress-theme-reco/compare/v1.5.3...v1.5.4) (2020-07-19)

View File

@ -4,7 +4,7 @@
1. This is a Vuepress theme, which is designed to add blog categories, tag walls, pagination, comments and other functions required;
2. The theme is minimalist, modified according to the default theme of Vuepress, and the official theme configuration is still applicable;
3. Demo[午后南杂](https://www.recoluan.com)
3. Demo[午后南杂](https://recoluan.com)
4. Docs[vuepress-theme-reco-doc](https://vuepress-theme-reco.recoluan.com)、[github source](https://vuepress.github.io)、[zeit source](https://vuepress-reco-doc.now.sh)
## Quick start
@ -65,6 +65,8 @@ theme-cli init
**P.S. Thanks to the two beauties for their contributions to the theme logo: Zoey and 冰冰.**
[Join us](https://www.notion.so/vuepress-reco-f8a7a55d18e042929931b612f170dbf4)
## License
[MIT](https://github.com/recoluan/vuepress-theme-reco/blob/master/LICENSE)

View File

@ -9,7 +9,15 @@ module.exports = {
base: '/reco-example-test/',
// theme: 'reco',
theme: require.resolve('../../packages/vuepress-theme-reco'),
locales: {
// 键名是该语言所属的子路径
// 作为特例,默认语言可以使用 '/' 作为其路径。
'/': {
lang: 'zh-CN',
},
},
themeConfig: {
lastUpdated: false,
nav: [
{ text: 'Home', link: '/', icon: 'reco-home' },
{ text: 'TimeLine', link: '/timeline/', icon: 'reco-date' },
@ -45,12 +53,16 @@ module.exports = {
blogConfig: {
category: {
location: 2, // 在导航栏菜单中所占的位置默认2
text: 'Category' // 默认 “分类”
// text: 'Categories' // 默认 “分类”
},
tag: {
location: 3, // 在导航栏菜单中所占的位置默认3
text: 'Tag' // 默认 “标签”
}
// text: 'Tags' // 默认 “标签”
},
socialLinks: [
{ icon: 'reco-github', link: 'https://github.com/recoluan' },
{ icon: 'fa-camera', link: 'https://www.npmjs.com/~reco_luan' }
]
},
logo: '/head.png',
authorAvatar: '/head.png',
@ -58,14 +70,17 @@ module.exports = {
search: true,
searchMaxSuggestions: 10,
// 自动形成侧边导航
// sidebar: 'auto',
subSidebar: 'auto',
sidebarDepth: 4,
// 最后更新时间
lastUpdated: 'Last Updated',
// lastUpdated: 'Last Updated',
// 作者
author: 'reco_luan',
// 备案号
record: 'xxxx',
recordLink: 'http://www.baidu.com',
cyberSecurityRecord: '2222',
cyberSecurityLink: 'http://www.baidu.com',
// 项目开始时间
startYear: '2017',
/**
@ -96,5 +111,32 @@ module.exports = {
* 'tomorrow'
* 'twilight'
*/
}
},
plugins: [
['@vuepress-reco/vuepress-plugin-bulletin-popover', {
body: [
{
type: 'title',
content: '欢迎加入QQ交流群 🎉🎉🎉',
style: 'text-aligin: center;'
},
{
type: 'image',
src: '/rvcode_qq.png'
}
],
footer: [
{
type: 'button',
text: '打赏',
link: '/donate'
},
{
type: 'button',
text: '打赏',
link: '/donate'
}
]
}]
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +1,5 @@
---
title: second page in category1
title: second page in category12
date: 2019-09-21
tags:
- tag2

View File

@ -4,7 +4,7 @@ date: 2018-12-15
tags:
- tag1
categories:
- category1
- 分类
---
first page in category1

View File

@ -1,14 +1,14 @@
---
title: sidebar test
date: 2019-09-21
title: sidebar test1111
date: '2021/01/24'
pageClass: 'customClass customClass2'
sidebarDepth: 5
tags:
- tag2
categories:
- category1
---
## 二级标题1
## 二级标题1 433265344343326534434332653443
### 三级标题1-1

View File

@ -5,6 +5,7 @@ tags:
- webpack
categories:
- frontEnd
publish: false
---
## webpack简介

View File

@ -1,5 +1,6 @@
---
title: bar1
publish: false
---
bar1

View File

@ -1,5 +1,3 @@
---
title: bar1
---
# bar test
bar1

View File

@ -4,10 +4,14 @@ title: bar2
bar2
## sidebar
## 二级标题1
### 三级标题1-1
#### 四级标题1-1-1
#### 四级标题1-1-2
#### 四级标题1-1-3

View File

@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "1.5.4",
"version": "1.6.6",
"npmClient": "yarn",
"useWorkspaces": true
}

View File

@ -9,16 +9,17 @@
],
"scripts": {
"bootstrap": "lerna bootstrap",
"build": "vuepress build example",
"build": "concurrently \"npm run build --prefix packages/@vuepress-reco/core\"",
"build:example": "vuepress build example",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 2",
"commit": "git add . && git-cz",
"deploy:example": "bash scripts/deploy.sh",
"dev": "vuepress dev example",
"eslint-ext": "eslint --ext .js,.vue ./",
"eslint-fix": "eslint --fix --ext .js,.vue ./",
"prepublish": "lerna publish --dist-tag next",
"publish": "lerna publish",
"publish": "yarn build && lerna publish",
"push": "yarn commit && git push",
"test": "bash scripts/test.sh",
"update": "yarn upgrade-interactive --latest"
},
"husky": {
@ -45,17 +46,28 @@
"devDependencies": {
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@types/events": "^3.0.0",
"@types/jest": "^26.0.15",
"@types/unist": "^2.0.3",
"@types/vfile": "^4.0.0",
"@types/vfile-message": "^2.0.0",
"@typescript-eslint/eslint-plugin": "^4.9.1",
"babel-eslint": "^10.1.0",
"commitizen": "^4.1.2",
"concurrently": "^5.3.0",
"conventional-changelog-cli": "^2.0.34",
"cz-customizable": "^6.2.0",
"eslint": "^6.8.0",
"eslint-plugin-typescript": "^0.14.0",
"eslint-plugin-vue": "^6.2.2",
"husky": "^4.2.5",
"jest": "^26.6.3",
"lerna": "^3.22.0",
"lint-staged": "^10.2.7",
"sort-package-json": "^1.44.0",
"vuepress": "^1.5.0"
"ts-jest": "^26.4.4",
"typescript": "4.1.2",
"vuepress": "^1.8.0"
},
"publishConfig": {
"access": "public"

View File

@ -0,0 +1,4 @@
__tests__
__mocks__
node_modules
src

View File

@ -0,0 +1,11 @@
# `core`
> TODO: description
## Usage
```
const core = require('core');
// TODO: DEMONSTRATE API
```

View File

@ -0,0 +1,36 @@
{
"name": "@vuepress-reco/core",
"version": "1.6.2",
"description": "The core library of vuepress-theme-reco.",
"homepage": "https://vuepress-theme-reco.recoluan.com/",
"bugs": {
"url": "https://github.com/recoluan/vuepress-theme-reco/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/recoluan/vuepress-theme-reco.git"
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
"main": "lib/index.js",
"directories": {
"lib": "lib",
"test": "__tests__"
},
"files": [
"lib"
],
"scripts": {
"build": "tsc",
"test": "echo \"Error: run tests from root\" && exit 1"
},
"dependencies": {
"@vue/composition-api": "^1.0.0-beta.20",
"vue": "^2.6.12",
"vue-demi": "^0.5.3",
"vue-property-decorator": "^9.1.2"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,56 @@
import Vue from 'vue';
import Component from 'vue-class-component';
const ModuleTransitionProps = Vue.extend({
props: {
delay: {
type: String,
default: '0'
},
duration: {
type: String,
default: '.25'
},
transform: {
type: Array,
default () {
return ['translateY(-20px)', 'translateY(0)']
}
}
}
})
@Component
class ModuleTransition extends ModuleTransitionProps {
setStyle (items) {
items.style.transition = `transform ${this.duration}s ease-in-out ${this.delay}s, opacity ${this.duration}s ease-in-out ${this.delay}s`
items.style.transform = this.transform[0]
items.style.opacity = 0
}
unsetStyle (items) {
items.style.transform = this.transform[1]
items.style.opacity = 1
}
render () {
return (
<transition
{
...{
attrs: { name: 'module' },
on: {
enter: this.setStyle,
appear: this.setStyle,
'before-leave': this.setStyle,
'after-appear': this.unsetStyle,
'after-enter': this.unsetStyle
}
}
}
>{this.$slots.default}</transition>
)
}
}
export default ModuleTransition

View File

@ -0,0 +1,47 @@
import Vue from 'vue'
import Component from 'vue-class-component'
const ICON_REGEXP = /^(\w+)\-/
const RecoIconProps = Vue.extend({
props: {
icon: {
type: String,
default: ''
},
link: {
type: String,
default: ''
}
}
})
@Component
class RecoIcon extends RecoIconProps {
getClass (icon: string) {
if (ICON_REGEXP.test(icon)) {
return icon.replace(ICON_REGEXP, (...args) => {
return args[1] === 'reco' ? `iconfont ${args[0]}` : `${args[1]} ${args[0]}`
})
}
return icon
}
go (link) {
if (link === '') return
window.open(link)
}
render () {
return (
<i {...{
class: this.getClass(this.icon),
on: { click: this.go.bind(this, this.link) }
}}>
{this.$slots.default}
</i>
)
}
}
export default RecoIcon

View File

@ -0,0 +1,3 @@
import RecoIcon from './RecoIcon'
import ModuleTransition from './ModuleTransition'
export { RecoIcon, ModuleTransition }

View File

@ -0,0 +1,2 @@
export * from './utils'
export * from './components'

View File

@ -0,0 +1,7 @@
export function isArray (target: any): boolean {
return Array.isArray(target)
}
export function isString (target: any): boolean {
return typeof target === 'string'
}

View File

@ -0,0 +1,11 @@
{
"extends": "../../../tsconfig.json",
"include": [
"./src"
],
"compilerOptions": {
"jsx": "react-native",
"outDir": "./lib",
"noImplicitAny": false
}
}

View File

@ -18,10 +18,10 @@ export default {
}
},
mounted () {
window.addEventListener('scroll', this.handleScroll)
window.addEventListener('scroll', this.throttle(this.handleScroll, 500))
},
beforeDestroy () {
window.removeEventListener('scroll', this.handleScroll)
window.removeEventListener('scroll', this.throttle(this.handleScroll, 500))
},
methods: {
handleScroll () {
@ -29,6 +29,25 @@ export default {
},
backToTop () {
window.scrollTo(0, 0)
},
throttle (func, delay) {
let timer = null
let startTime = Date.now()
return function () {
const curTime = Date.now()
const remaining = delay - (curTime - startTime)
const context = this
const args = arguments
clearTimeout(timer)
if (remaining <= 0) {
func.apply(context, args)
startTime = Date.now()
} else {
timer = setTimeout(func, remaining)
}
}
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@vuepress-reco/vuepress-plugin-back-to-top",
"version": "1.5.4",
"version": "1.6.0",
"description": "Back-to-top plugin for vuepress-theme-reco or other vuepress theme",
"keywords": [
"vuepress-theme-reco",
@ -9,7 +9,7 @@
],
"homepage": "https://vuepress-theme-reco.recoluan.com",
"bugs": {
"url": "https://github.com/vuepress-reco/vuepress-plugin-pagation/issues"
"url": "https://github.com/vuepress-reco/vuepress-theme-reco/issues"
},
"repository": {
"type": "git",
@ -17,5 +17,8 @@
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
"main": "index.js"
"main": "index.js",
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
__tests__
__mocks__
node_modules

View File

@ -0,0 +1,87 @@
# @vuepress-reco/vuepress-plugin-bulletin-popover
## Introduce
Bulletin popover plugin for vuepress-theme-reco or other vuepress theme.
## Usage
```js
plugins: [
['@vuepress-reco/vuepress-plugin-bulletin-popover', {
title: '消息提示',
body: [
{
type: 'title',
content: '欢迎加入QQ交流群 🎉🎉🎉',
style: 'text-aligin: center;'
},
{
type: 'image',
src: '/rvcode_qq.png'
}
],
footer: [
{
type: 'button',
text: '打赏',
link: '/donate'
},
{
type: 'button',
text: '打赏',
link: '/donate'
}
]
}]
]
```
弹窗分为三部分,公告标题、公告内容和公告底部操作。其中标题是普通文本,公告内容和公告底部操作内容均为数组,支持 4 种 dom需要通过 schema 配置来控制显示效果,可以根据需要自由组合:
**标题**
```json
{
type: 'title',
content: '这里显示 h5 标题'
}
```
**文本**
```json
{
type: 'text',
content: '这里显示普通文本'
}
```
**图片**
```json
{
type: 'image',
src: '/rvcode_qq.png'
}
```
**按钮**
```json
{
type: 'button',
text: '打赏',
link: '/donate'
}
```
**给 dom 添加样式**
```json
{
type: 'title',
content: '这里显示 h5 标题',
style: 'text-aligin: center;'
}
```

View File

@ -0,0 +1,148 @@
<template>
<transition name="fade">
<div v-if="visible" class="bulletin-wrapper" :style="{ width }">
<h4 class="bulletin-title">
<reco-icon icon="reco-tongzhi" />
<span>{{ title || bulletinLocales.title }}</span>
<i class="btn-close" @click="closeNote">
<svg t="1573745677073" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4448" width="22" height="22"><path d="M512 34.133333a486.4 486.4 0 1 0 486.4 486.4A486.4 486.4 0 0 0 512 34.133333z m209.4848 632.8064l-55.6032 55.466667-151.517867-151.125333-151.517866 151.1168-55.6032-55.466667 151.517866-151.108267L307.242667 364.714667l55.6032-55.466667 151.517866 151.125333 151.517867-151.1168 55.6032 55.466667-151.517867 151.099733z m0 0" p-id="4449"></path></svg>
</i>
</h4>
<div class="bulletin-content" v-html="bodyNodes"></div>
<hr>
<div class="bulletin-footer" v-html="footerNodes"></div>
</div>
</transition>
</template>
<script>
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import bulletinLocales from './locales'
export default {
components: { RecoIcon },
name: 'Bulletin',
data () {
return {
visible: false,
/* eslint-disable no-undef */
title: TITLE,
width: WIDTH,
body: BODY,
footer: FOOTER
}
},
computed: {
bodyNodes () {
return this.handleNode(this.body).join('')
},
footerNodes () {
return this.handleNode(this.footer).join('')
},
bulletinLocales () {
return bulletinLocales(this)
}
},
mounted () {
const closeNote = sessionStorage.getItem('closeNote')
this.visible = closeNote !== 'true'
},
methods: {
closeNote () {
this.visible = false
sessionStorage.setItem('closeNote', 'true')
},
handleNode (nodes) {
if (!Array.isArray(nodes)) {
let type = nodes.type
type = type.slice(0, 1).toUpperCase() + type.slice(1)
return this[`handle${type}`](nodes)
} else {
return nodes.map(node => this.handleNode(node))
}
},
handleImage (node) {
return `<img style=\"${node.style || ''}\" src=\"${node.src}\" />`
},
handleText (node) {
return `<p style=\"${node.style || ''}\">${node.content}</p>`
},
handleTitle (node) {
return `<h5 style=\"${node.style || ''}\">${node.content}</h5>`
},
handleButton (node) {
return `<a style=\"${node.style || ''}\" class=\"btn\" href=\"${node.link}\">${node.text}</a>`
}
}
}
</script>
<style lang="stylus" scoped>
.bulletin-wrapper
position fixed
top 80px
right 20px
z-index 19
box-sizing border-box
background #fff
border 1px solid $accentColor
border-radius .25rem
background var(--background-color)
box-shadow var(--box-shadow)
.bulletin-title
position relative
box-sizing border-box
padding 10px
margin 0
background $accentColor
color #fff
i
color #fff
.btn-close
position absolute
display inline-block
width 22px
height 22px
right 10px
top 0
bottom 0
margin auto
cursor pointer
svg
fill #fff
.bulletin-content
box-sizing border-box
padding 10px 15px 0
::v-deep h5
margin .2rem 0
text-align center
::v-deep img
width 100%
.bulletin-footer
padding 16px
text-align center
::v-deep .btn
display inline-block
width 3.4rem
line-height 3.4rem
text-align center
background-color $accentColor
border-radius 50%
color #fff
font-size 1rem
box-shadow var(--box-shadow)
cursor pointer
&:not(:first-child)
margin-left 10px
::v-deep h5
margin .2rem 0
text-align center
::v-deep img
width 100%
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>

View File

@ -0,0 +1,5 @@
import Bulletin from './Bulletin.vue'
export default ({ Vue }) => {
Vue.component('Bulletin', Bulletin)
}

View File

@ -0,0 +1,39 @@
const zhHans = {
title: '公告'
}
const zhHant = {
title: '公告'
}
const en = {
title: 'Bulletin'
}
const ja = {
bulletin: '公告'
}
const ko = {
title: '공고'
}
export default function bulletinLocales (ctx) {
const { $lang, $recoLocales: { pagation } = {} } = ctx
if (pagation) {
return pagation
}
if (/^zh\-(CN|SG)$/.test($lang)) {
return zhHans
}
if (/^zh\-(HK|MO|TW)$/.test($lang)) {
return zhHant
}
if (/^ja\-JP$/.test($lang)) {
return ja
}
if (/^ko\-KR$/.test($lang)) {
return ko
}
return en
}

View File

@ -0,0 +1,18 @@
const { path } = require('@vuepress/shared-utils')
module.exports = (options, context) => ({
define () {
const { title, width, body, footer } = options || {}
return {
WIDTH: width || '260px',
TITLE: title || '公告',
BODY: body || [],
FOOTER: footer || []
}
},
name: '@vuepress-reco/vuepress-plugin-bulletin-popover',
enhanceAppFiles: [
path.resolve(__dirname, './bin/enhanceAppFile.js')
],
globalUIComponents: 'Bulletin'
})

View File

@ -0,0 +1,24 @@
{
"name": "@vuepress-reco/vuepress-plugin-bulletin-popover",
"version": "1.6.0",
"description": "Bulletin popover plugin for vuepress-theme-reco or other vuepress theme",
"keywords": [
"vuepress-theme-reco",
"bulletin",
"vuepress"
],
"homepage": "https://vuepress-theme-reco.recoluan.com",
"bugs": {
"url": "https://github.com/vuepress-reco/vuepress-theme-reco/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuepress-reco/vuepress-plugin-bulletin-popover.git"
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
"main": "index.js",
"publishConfig": {
"access": "public"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@vuepress-reco/vuepress-plugin-comments",
"version": "1.4.6",
"version": "1.6.0",
"description": "Comments plugin for vuepress-theme-reco or other vuepress theme",
"keywords": [
"vuepress-theme-reco",
@ -13,7 +13,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuepress-reco/vuepress-theme-reco.git"
"url": "git+https://github.com/vuepress-reco/vuepress-plugin-comments.git"
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
@ -26,5 +26,8 @@
"@vssue/api-gitlab-v4": "^1.1.1",
"valine": "^1.4.14",
"vssue": "^1.4.6"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@vuepress-reco/vuepress-plugin-loading-page",
"version": "1.4.0",
"version": "1.6.0",
"description": "Loading page plugin for vuepress-theme-reco or other vuepress theme",
"keywords": [
"vuepress-theme-reco",
@ -13,10 +13,13 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuepress-reco/vuepress-theme-reco.git"
"url": "git+https://github.com/vuepress-reco/vuepress-plugin-loading-page.git"
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
"main": "index.js",
"publishConfig": {
"access": "public"
},
"gitHead": "c3a1db8487bece9341b6269a0f6ebf910cd5462a"
}

View File

@ -76,7 +76,9 @@ export default {
},
data () {
return {
changePage: '' // 跳转页
changePage: '', // 跳转页
/* eslint-disable no-undef */
pageSize: PERPAGE
}
},
props: {
@ -86,7 +88,7 @@ export default {
},
perPage: {
type: Number,
default: 2
default: 10
},
currentPage: {
type: Number,
@ -95,7 +97,8 @@ export default {
},
computed: {
pages () {
return Math.ceil(this.total / this.perPage)
const pageSize = this.pageSize || this.perPage
return Math.ceil(this.total / pageSize)
},
show: function () {
return this.pages && this.pages != 1

View File

@ -47,7 +47,9 @@ import pagationLocales from './locales'
export default {
data () {
return {
changePage: '' //
changePage: '', //
/* eslint-disable no-undef */
pageSize: PERPAGE
}
},
props: {
@ -66,7 +68,8 @@ export default {
},
computed: {
pages () {
return Math.ceil(this.total / this.perPage)
const pageSize = this.pageSize || this.perPage
return Math.ceil(this.total / pageSize)
},
show: function () {
return this.pages && this.pages != 1

View File

@ -1,8 +1,26 @@
const { path } = require('@vuepress/shared-utils')
module.exports = (options, context) => ({
name: '@vuepress-reco/vuepress-plugin-pagation',
enhanceAppFiles: [
path.resolve(__dirname, './bin/enhanceAppFile.js')
]
})
module.exports = (options, context) => {
const { perPage = 10 } = options || {}
return {
define () {
return {
PERPAGE: perPage
}
},
name: '@vuepress-reco/vuepress-plugin-pagation',
enhanceAppFiles: [
path.resolve(__dirname, './bin/enhanceAppFile.js'),
() => ({
name: 'dynamic-pagation',
content: `export default ({ Vue }) => {
Vue.mixin({
computed: {
$perPage () { return ${perPage} }
}
})
}`
})
]
}
}

View File

@ -1,6 +1,6 @@
{
"name": "@vuepress-reco/vuepress-plugin-pagation",
"version": "1.4.7",
"version": "1.6.0",
"description": "Pagation plugin for vuepress-theme-reco or other vuepress theme",
"keywords": [
"vuepress-theme-reco",
@ -13,9 +13,12 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuepress-reco/vuepress-theme-reco.git"
"url": "git+https://github.com/vuepress-reco/vuepress-plugin-pagation.git"
},
"license": "MIT",
"author": "reco_luan <recoluan@outlook.com>",
"main": "index.js"
"main": "index.js",
"publishConfig": {
"access": "public"
}
}

1
packages/theme-cli Submodule

@ -0,0 +1 @@
Subproject commit 03ccebd77846c71c5e5e3432fb7697f0bc06520b

@ -0,0 +1 @@
Subproject commit 0f641fc3704927ec438a41782b29a4152fb1d9bb

View File

@ -4,7 +4,7 @@
class="algolia-search-wrapper search-box"
role="search"
>
<i class="iconfont reco-search"></i>
<reco-icon icon="reco-search" />
<input
id="algolia-search-input"
class="search-query"
@ -14,20 +14,20 @@
</template>
<script>
export default {
props: ['options'],
data () {
return {
placeholder: undefined
}
},
mounted () {
this.initialize(this.options, this.$lang)
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
},
import { defineComponent, ref, onMounted, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
methods: {
initialize (userOptions, lang) {
export default defineComponent({
components: { RecoIcon },
props: ['options'],
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const placeholder = ref(undefined)
const 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')
@ -50,12 +50,19 @@ export default {
}
))
})
},
update (options, lang) {
this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
this.initialize(options, lang)
}
const update = (options, lang) => {
instance.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
instance.initialize(options, lang)
}
onMounted(() => {
initialize(props.options, instance.$lang)
placeholder.value = instance.$site.themeConfig.searchPlaceholder || ''
})
return { placeholder, initialize, update }
},
watch: {
@ -67,11 +74,10 @@ export default {
this.update(newValue, this.$lang)
}
}
}
})
</script>
<style lang="stylus">
@require '../styles/mode.styl'
.algolia-search-wrapper
& > span
vertical-align middle

View File

@ -1,34 +1,22 @@
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd">
<div class="theme-container" :class="pageClasses">
<div v-if="!absoluteEncryption">
<transition name="fade">
<LoadingPage v-show="firstLoad" class="loading-wrapper" />
</transition>
<transition name="fade">
<Password v-show="!isHasKey" class="password-wrapper-out" key="out" />
<Password v-show="!firstLoad && !isHasKey" class="password-wrapper-out" key="out" />
</transition>
<div :class="{ 'hide': firstLoad || !isHasKey }">
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"/>
<Navbar v-if="shouldShowNavbar" @toggle-sidebar="toggleSidebar" />
<div
class="sidebar-mask"
@click="toggleSidebar(false)"></div>
<div class="sidebar-mask" @click="toggleSidebar(false)"></div>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar">
<template slot="top">
<PersonalInfo />
</template>
<slot
name="sidebar-bottom"
slot="bottom"/>
<Sidebar :items="sidebarItems" @toggle-sidebar="toggleSidebar">
<PersonalInfo slot="top" />
<slot name="sidebar-bottom" slot="bottom"/>
</Sidebar>
<Password v-show="!isHasPageKey" :isPage="true" class="password-wrapper-in" key="in"></Password>
@ -42,29 +30,17 @@
<LoadingPage v-if="firstLoad" />
<Password v-else-if="!isHasKey" />
<div v-else>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"/>
<Navbar v-if="shouldShowNavbar" @toggle-sidebar="toggleSidebar"/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"></div>
<div class="sidebar-mask" @click="toggleSidebar(false)"></div>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar">
<template slot="top">
<PersonalInfo />
</template>
<slot
name="sidebar-bottom"
slot="bottom"/>
<Sidebar :items="sidebarItems" @toggle-sidebar="toggleSidebar">
<PersonalInfo slot="top" />
<slot name="sidebar-bottom" slot="bottom"/>
</Sidebar>
<Password v-if="!isHasPageKey" :isPage="true"></Password>
<div v-else>
<slot></slot>
</div>
<slot v-else></slot>
</div>
</transition>
</div>
@ -72,16 +48,14 @@
</template>
<script>
import { defineComponent, computed, ref, onMounted, toRefs, getCurrentInstance } from 'vue-demi'
import Navbar from '@theme/components/Navbar'
import Sidebar from '@theme/components/Sidebar'
import PersonalInfo from '@theme/components/PersonalInfo'
import Password from '@theme/components/Password'
import { setTimeout } from 'timers'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [moduleTransitonMixin],
export default defineComponent({
components: { Sidebar, Navbar, Password, PersonalInfo },
props: {
@ -92,26 +66,28 @@ export default {
sidebarItems: {
type: Array,
default: () => []
}
},
data () {
return {
isSidebarOpen: false,
isHasKey: true,
isHasPageKey: true,
firstLoad: true
}
},
computed: {
absoluteEncryption () {
return this.$themeConfig.keyPage && this.$themeConfig.keyPage.absoluteEncryption === true
},
showModule: {
type: Boolean,
default: false
}
},
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const isSidebarOpen = ref(false)
const isHasKey = ref(true)
const isHasPageKey = ref(true)
const firstLoad = ref(true)
const shouldShowSidebar = computed(() => props.sidebarItems.length > 0)
const absoluteEncryption = computed(() => {
return instance.$themeConfig.keyPage && instance.$themeConfig.keyPage.absoluteEncryption === true
})
const shouldShowNavbar = computed(() => {
const { themeConfig } = instance.$site
const { frontmatter } = instance.$page
if (
frontmatter.navbar === false ||
@ -119,102 +95,83 @@ export default {
) return false
return (
this.$title ||
instance.$title ||
themeConfig.logo ||
themeConfig.repo ||
themeConfig.nav ||
this.$themeLocaleConfig.nav
instance.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
// const { frontmatter } = this.$page
// return (
// this.sidebar !== false &&
// !frontmatter.home &&
// frontmatter.sidebar !== false &&
// this.sidebarItems.length
// )
return this.sidebarItems.length > 0
},
pageClasses () {
const userPageClass = this.$frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
this.hasKey()
this.hasPageKey()
this.handleLoading()
},
const pageClasses = computed(() => {
const classValue = {
'no-navbar': !shouldShowNavbar.value,
'sidebar-open': isSidebarOpen.value,
'no-sidebar': !shouldShowSidebar.value
}
methods: {
hasKey () {
const keyPage = this.$themeConfig.keyPage
const { pageClass: userPageClass } = instance.$frontmatter || {}
if (userPageClass) classValue[userPageClass] = true
return classValue
})
const hasKey = () => {
const { keyPage } = instance.$themeConfig
if (!keyPage || !keyPage.keys || keyPage.keys.length === 0) {
this.isHasKey = true
isHasKey.value = true
return
}
let { keys } = keyPage
keys = keys.map(item => item.toLowerCase())
this.isHasKey = keys && keys.indexOf(sessionStorage.getItem('key')) > -1
},
hasPageKey () {
let pageKeys = this.$frontmatter.keys
isHasKey.value = keys && keys.indexOf(sessionStorage.getItem('key')) > -1
}
const initRouterHandler = () => {
instance.$router.afterEach(() => {
isSidebarOpen.value = false
})
}
const hasPageKey = () => {
let pageKeys = instance.$frontmatter.keys
if (!pageKeys || pageKeys.length === 0) {
this.isHasPageKey = true
isHasPageKey.value = true
return
}
pageKeys = pageKeys.map(item => item.toLowerCase())
this.isHasPageKey = pageKeys.indexOf(sessionStorage.getItem(`pageKey${window.location.pathname}`)) > -1
},
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)
}
}
},
handleLoading () {
const time = this.$frontmatter.home && sessionStorage.getItem('firstLoad') == undefined ? 1000 : 0
isHasPageKey.value = pageKeys.indexOf(sessionStorage.getItem(`pageKey${window.location.pathname}`)) > -1
}
const toggleSidebar = (to) => {
isSidebarOpen.value = typeof to === 'boolean' ? to : !isSidebarOpen.value
}
const handleLoading = () => {
const time = instance.$frontmatter.home && sessionStorage.getItem('firstLoad') == undefined ? 1000 : 0
setTimeout(() => {
this.firstLoad = false
firstLoad.value = false
if (sessionStorage.getItem('firstLoad') == undefined) sessionStorage.setItem('firstLoad', false)
}, time)
}
// recoShowModule true
const { showModule } = toRefs(props)
const recoShowModule = computed(() => {
if (firstLoad.value) {
return true
} else {
return showModule.value
}
})
onMounted(() => {
initRouterHandler()
hasKey()
hasPageKey()
handleLoading()
})
return { isSidebarOpen, absoluteEncryption, shouldShowNavbar, shouldShowSidebar, pageClasses, hasKey, hasPageKey, isHasKey, isHasPageKey, toggleSidebar, firstLoad, recoShowModule }
},
watch: {
@ -223,7 +180,7 @@ export default {
this.hasPageKey()
}
}
}
})
</script>
<style lang="stylus" scoped>
@ -254,9 +211,10 @@ export default {
.hide
height 100vh
overflow hidden
opacity 0
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
transition: opacity .5s ease-in-out .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;

View File

@ -1,27 +1,15 @@
<template>
<div
class="dropdown-wrapper"
:class="{ open }"
>
<a
class="dropdown-title"
@click="toggle"
>
<div class="dropdown-wrapper" :class="{ open }">
<a class="dropdown-title" @click="toggle">
<span class="title">
<i :class="`iconfont ${item.icon}`"></i>
<reco-icon :icon="`${item.icon}`" />
{{ item.text }}
</span>
<span
class="arrow"
:class="open ? 'down' : 'right'"
></span>
<span class="arrow" :class="open ? 'down' : 'right'"></span>
</a>
<DropdownTransition>
<ul
class="nav-dropdown"
v-show="open"
>
<ul class="nav-dropdown" v-show="open">
<li
class="dropdown-item"
:key="subItem.link || index"
@ -37,15 +25,10 @@
class="dropdown-subitem"
:key="childSubItem.link"
v-for="childSubItem in subItem.items"
>
<NavLink :item="childSubItem"/>
</li>
><NavLink :item="childSubItem"/></li>
</ul>
<NavLink
v-else
:item="subItem"
/>
<NavLink v-else :item="subItem" />
</li>
</ul>
</DropdownTransition>
@ -53,17 +36,13 @@
</template>
<script>
import { defineComponent, ref } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import NavLink from '@theme/components/NavLink'
import DropdownTransition from '@theme/components/DropdownTransition'
export default {
components: { NavLink, DropdownTransition },
data () {
return {
open: false
}
},
export default defineComponent({
components: { NavLink, DropdownTransition, RecoIcon },
props: {
item: {
@ -71,17 +50,19 @@ export default {
}
},
methods: {
toggle () {
this.open = !this.open
setup (props, ctx) {
const open = ref(false)
const toggle = () => {
open.value = !open.value
}
return { open, toggle }
}
}
})
</script>
<style lang="stylus">
@require '../styles/mode.styl'
.dropdown-wrapper
cursor pointer
.dropdown-title

View File

@ -10,20 +10,22 @@
</template>
<script>
export default {
import { defineComponent } from 'vue-demi'
export default defineComponent({
name: 'DropdownTransition',
methods: {
setHeight (items) {
// explicitly set height so that it can be transitioned
setup (props, ctx) {
const setHeight = (items) => {
items.style.height = items.scrollHeight + 'px'
},
}
unsetHeight (items) {
const unsetHeight = (items) => {
items.style.height = ''
}
return { setHeight, unsetHeight }
}
}
})
</script>
<style lang="stylus">

View File

@ -1,24 +1,24 @@
<template>
<div class="footer-wrapper">
<span>
<i class="iconfont reco-theme"></i>
<reco-icon icon="reco-theme" />
<a target="blank" href="https://vuepress-theme-reco.recoluan.com">{{`vuepress-theme-reco@${version}`}}</a>
</span>
<span v-if="$themeConfig.record">
<i class="iconfont reco-beian"></i>
<reco-icon icon="reco-beian" />
<a :href="$themeConfig.recordLink || '#'">{{ $themeConfig.record }}</a>
</span>
<span>
<i class="iconfont reco-copyright"></i>
<reco-icon icon="reco-copyright" />
<a>
<span v-if="$themeConfig.author || $site.title">{{ $themeConfig.author || $site.title }}</span>
<span v-if="$themeConfig.author">{{ $themeConfig.author }}</span>
&nbsp;&nbsp;
<span v-if="$themeConfig.startYear && $themeConfig.startYear != (new Date().getFullYear())">{{ $themeConfig.startYear }} - </span>
{{ new Date().getFullYear() }}
</a>
</span>
<span v-show="showAccessNumber">
<i class="iconfont reco-eye"></i>
<reco-icon icon="reco-eye" />
<AccessNumber idVal="/" />
</span>
<p class="cyber-security" v-if="$themeConfig.cyberSecurityRecord">
@ -30,28 +30,26 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import { version } from '../package.json'
export default {
data () {
return {
version
}
},
computed: {
showAccessNumber () {
export default defineComponent({
components: { RecoIcon },
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const showAccessNumber = computed(() => {
const {
$themeConfig: { valineConfig },
$themeLocaleConfig: { valineConfig: valineLocalConfig }
} = this
} = instance
const vc = valineLocalConfig || valineConfig
if (vc && vc.visitor != false) {
return true
}
return false
}
return vc && vc.visitor != false
})
return { version, showAccessNumber }
}
}
})
</script>
<style lang="stylus" scoped>

View File

@ -34,86 +34,112 @@
</div>
</div>
</div>
</transition>
</div>
</div>
</template>
<script>
import { defineComponent, getCurrentInstance, reactive, computed, ref, onMounted } from 'vue-demi'
import md5 from 'md5'
import { getOneColor } from '@theme/helpers/other'
export default {
data () {
return {
popupWindowStyle: {}
}
},
computed: {
dataAddColor () {
let { friendLink } = this.$themeConfig
if (friendLink && friendLink.length > 0) {
friendLink = friendLink.map(item => ({
...item,
color: getOneColor()
}))
return friendLink
}
return []
}
},
methods: {
getMd5 (str) {
return md5(str)
},
showDetail (e) {
const currentDom = e.target
const popupWindowWrapper = currentDom.querySelector('.popup-window-wrapper')
const popupWindow = currentDom.querySelector('.popup-window')
popupWindowWrapper.style.display = 'block'
const { clientWidth } = currentDom
const {
clientWidth: windowWidth,
clientHeight: windowHeight
} = popupWindow
this.popupWindowStyle = {
left: (clientWidth - windowWidth) / 2 + 'px',
top: -windowHeight + 'px'
}
this.$nextTick(() => {
this._adjustPosition(currentDom.querySelector('.popup-window'))
})
},
hideDetail (e) {
const currentDom = e.target
currentDom.querySelector('.popup-window-wrapper').style.display = 'none'
},
getImgUrl (info) {
const { logo, email } = info
if (logo && /^http/.test(logo)) return logo
if (logo && !/^http/.test(logo)) return this.$withBase(logo)
return `//1.gravatar.com/avatar/${this.getMd5(email || '')}?s=50&amp;d=mm&amp;r=x`
},
_adjustPosition (dom) {
const { offsetWidth } = document.body
const { x, width } = dom.getBoundingClientRect()
const distanceToRight = offsetWidth - (x + width)
if (distanceToRight < 0) {
const { offsetLeft } = dom
this.popupWindowStyle = {
...this.popupWindowStyle,
left: offsetLeft + distanceToRight + 'px'
}
}
const useDetail = () => {
const instance = getCurrentInstance().proxy
const isPC = ref(true)
const popupWindowStyle = reactive({
left: 0,
top: 0
})
const adjustPosition = (dom) => {
const { offsetWidth } = document.body
const { x, width } = dom.getBoundingClientRect()
const distanceToRight = offsetWidth - (x + width)
if (distanceToRight < 0) {
const { offsetLeft } = dom
popupWindowStyle.left = offsetLeft + distanceToRight + 'px'
}
}
const showDetail = (e) => {
const currentDom = e.target
const popupWindowWrapper = currentDom.querySelector('.popup-window-wrapper')
popupWindowWrapper.style.display = 'block'
const popupWindow = currentDom.querySelector('.popup-window')
const infoWrapper = document.querySelector('.info-wrapper')
const { clientWidth } = currentDom
const { clientWidth: windowWidth, clientHeight: windowHeight } = popupWindow
if (isPC) {
popupWindowStyle.left = (clientWidth - windowWidth) / 2 + 'px'
popupWindowStyle.top = -windowHeight + 'px'
infoWrapper.style.overflow = 'visible'
instance.$nextTick(() => {
adjustPosition(popupWindow)
})
} else {
const getPosition = function (element) {
const dc = document
const rec = element.getBoundingClientRect()
let _x = rec.left
let _y = rec.top
_x += dc.documentElement.scrollLeft || dc.body.scrollLeft
_y += dc.documentElement.scrollTop || dc.body.scrollTop
return { left: _x, top: _y }
}
infoWrapper.style.overflow = 'hidden'
const left = getPosition(currentDom).left - getPosition(infoWrapper).left
popupWindowStyle.left = (-left + (infoWrapper.clientWidth - popupWindow.clientWidth) / 2) + 'px'
popupWindowStyle.top = -windowHeight + 'px'
}
}
const hideDetail = (e) => {
const currentDom = e.target.querySelector('.popup-window-wrapper')
currentDom.style.display = 'none'
}
onMounted(() => {
isPC.value = !/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)
})
return { popupWindowStyle, showDetail, hideDetail }
}
export default defineComponent({
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const { popupWindowStyle, showDetail, hideDetail } = useDetail()
const dataAddColor = computed(() => {
const { friendLink = [] } = instance && instance.$themeConfig
return friendLink.map(item => {
item.color = getOneColor()
return item
})
})
const getImgUrl = (info) => {
const { logo = '', email = '' } = info
if (logo && /^http/.test(logo)) return logo
if (logo && !/^http/.test(logo)) return instance.$withBase(logo)
return `//1.gravatar.com/avatar/${md5(email || '')}?s=50&amp;d=mm&amp;r=x`
}
return { dataAddColor, popupWindowStyle, showDetail, hideDetail, getImgUrl }
}
})
</script>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.friend-link-wrapper
position relative
margin 30px 0
@ -151,7 +177,7 @@ export default {
border-radius $borderRadius
box-sizing border-box
padding .8rem 1rem
width 300px
width 280px
.logo
margin-right .4rem
width 2rem

View File

@ -9,7 +9,12 @@
alt="hero">
</ModuleTransition>
<ModuleTransition delay="0.04">
<h1 v-if="recoShowModule && $frontmatter.heroText !== null">{{ $frontmatter.heroText || $title || 'vuePress-theme-reco' }}</h1>
<h1
v-if="recoShowModule && $frontmatter.heroText !== null"
:style="{ marginTop: $frontmatter.heroImage ? '0px' : '140px'}"
>
{{ $frontmatter.heroText || $title || 'vuePress-theme-reco' }}
</h1>
</ModuleTransition>
<ModuleTransition delay="0.08">
<p v-if="recoShowModule && $frontmatter.tagline !== null" class="description">
@ -38,35 +43,31 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import NavLink from '@theme/components/NavLink'
import ModuleTransition from '@theme/components/ModuleTransition'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
export default {
mixins: [moduleTransitonMixin],
export default defineComponent({
components: { NavLink, ModuleTransition },
computed: {
actionLink () {
return {
link: this.$frontmatter.actionLink,
text: this.$frontmatter.actionText
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const recoShowModule = computed(() => instance && instance.$parent.recoShowModule)
const actionLink = computed(() => instance && {
link: instance.$frontmatter.actionLink,
text: instance.$frontmatter.actionText
})
const heroImageStyle = computed(() => instance.$frontmatter.heroImageStyle || {
maxHeight: '200px',
margin: '6rem auto 1.5rem'
})
heroImageStyle () {
return this.$frontmatter.heroImageStyle || {
maxHeight: '200px',
margin: '6rem auto 1.5rem'
}
}
return { recoShowModule, actionLink, heroImageStyle }
}
}
})
</script>
<style lang="stylus">
@require '../styles/mode.styl'
.home {
padding: $navbarHeight 2rem 0;
max-width: 960px;
@ -75,6 +76,7 @@ export default {
.hero {
text-align: center;
h1 {
display: block;
font-size: 2.5rem;
color: var(--text-color);
}
@ -94,7 +96,7 @@ export default {
font-size: 1.2rem;
color: #fff;
background-color: $accentColor;
padding: 0.6rem 1.2rem;
padding: 0.2rem 1.2rem;
border-radius: $borderRadius
transition: background-color 0.1s ease;
box-sizing: border-box;
@ -134,59 +136,6 @@ export default {
transform scale(1.05)
}
}
// &.reco-hide {
// .hero {
// img {
// load-start()
// }
// .h1 {
// load-start()
// }
// .description {
// load-start()
// }
// .huawei {
// load-start()
// }
// .action-button {
// load-start()
// }
// }
// .features {
// load-start()
// }
// .home-center {
// load-start()
// padding 0
// }
// }
// &.reco-show {
// .hero {
// img {
// load-end(0.08s)
// }
// .h1 {
// load-end(0.16s)
// }
// .description {
// load-end(0.24s)
// }
// .huawei {
// load-end(0.32s)
// }
// .action-button {
// load-end(0.4s)
// }
// }
// .features {
// load-end(0.40s)
// }
// .home-center {
// load-end(0.48s)
// }
// }
}
@media (max-width: $MQMobile) {

View File

@ -0,0 +1,8 @@
// import { ref, reactive, toRefs, getCurrentInstance } from 'vue-demi'
// const useBlog = () => {
// const currentPage = ref(1)
// return {}
// }
// export { useBlog }

View File

@ -1,54 +1,40 @@
<template>
<div class="home-blog">
<div class="hero" :style="{ ...bgImageStyle }">
<div
class="mask"
:style="{
background: `
url(${$frontmatter.bgImage ?
$withBase($frontmatter.bgImage) :
require('../images/home-bg.jpg')}) center/cover no-repeat
`
}"
></div>
<ModuleTransition>
<img
v-if="recoShowModule && $frontmatter.heroImage"
:style="heroImageStyle || {}"
:src="$withBase($frontmatter.heroImage)"
alt="hero"
/>
</ModuleTransition>
<ModuleTransition delay="0.04">
<h1 v-if="recoShowModule && $frontmatter.heroText !== null">
{{ $frontmatter.heroText || $title || 'vuePress-theme-reco' }}
</h1>
</ModuleTransition>
<div>
<ModuleTransition>
<img
class="hero-img"
v-if="recoShowModule && $frontmatter.heroImage"
:style="heroImageStyle || {}"
:src="$withBase($frontmatter.heroImage)"
alt="hero"
/>
</ModuleTransition>
<ModuleTransition delay="0.08">
<p v-if="recoShowModule && $frontmatter.tagline !== null" class="description">
{{ $frontmatter.tagline || $description || 'Welcome to your vuePress-theme-reco site' }}
</p>
</ModuleTransition>
<ModuleTransition delay="0.04">
<h1 v-if="recoShowModule && $frontmatter.heroText !== null">
{{ $frontmatter.heroText || $title || 'vuePress-theme-reco' }}
</h1>
</ModuleTransition>
<ModuleTransition delay="0.08">
<p v-if="recoShowModule && $frontmatter.tagline !== null" class="description">
{{ $frontmatter.tagline || $description || 'Welcome to your vuePress-theme-reco site' }}
</p>
</ModuleTransition>
</div>
</div>
<ModuleTransition delay="0.16">
<div v-show="recoShowModule" class="home-blog-wrapper">
<div class="blog-list">
<!-- 博客列表 -->
<note-abstract
:data="$recoPosts"
:currentPage="currentPage"></note-abstract>
<!-- 分页 -->
<pagation
class="pagation"
:total="$recoPosts.length"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage" />
<note-abstract :data="$recoPosts" @paginationChange="paginationChange" />
</div>
<div class="info-wrapper">
<PersonalInfo/>
<h4><i class="iconfont reco-category"></i> {{homeBlogCfg.category}}</h4>
<h4><reco-icon icon="reco-category" /> {{$recoLocales.category}}</h4>
<ul class="category-wrapper">
<li class="category-item" v-for="(item, index) in this.$categories.list" :key="index">
<router-link :to="item.path">
@ -58,9 +44,9 @@
</li>
</ul>
<hr>
<h4 v-if="$tags.list.length !== 0"><i class="iconfont reco-tag"></i> {{homeBlogCfg.tag}}</h4>
<h4 v-if="$tags.list.length !== 0"><reco-icon icon="reco-tag" /> {{$recoLocales.tag}}</h4>
<TagList @getCurrentTag="getPagesByTags" />
<h4 v-if="$themeConfig.friendLink && $themeConfig.friendLink.length !== 0"><i class="iconfont reco-friend"></i> {{homeBlogCfg.friendLink}}</h4>
<h4 v-if="$themeConfig.friendLink && $themeConfig.friendLink.length !== 0"><reco-icon icon="reco-friend" /> {{$recoLocales.friendLink}}</h4>
<FriendLink />
</div>
</div>
@ -73,138 +59,88 @@
</template>
<script>
import { defineComponent, toRefs, reactive, computed, getCurrentInstance, onMounted } from 'vue-demi'
import TagList from '@theme/components/TagList'
import FriendLink from '@theme/components/FriendLink'
import NoteAbstract from '@theme/components/NoteAbstract'
import pagination from '@theme/mixins/pagination'
import ModuleTransition from '@theme/components/ModuleTransition'
import { ModuleTransition, RecoIcon } from '@vuepress-reco/core/lib/components'
import PersonalInfo from '@theme/components/PersonalInfo'
import { getOneColor } from '@theme/helpers/other'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [pagination, moduleTransitonMixin],
components: { NoteAbstract, TagList, FriendLink, ModuleTransition, PersonalInfo },
data () {
return {
export default defineComponent({
components: { NoteAbstract, TagList, FriendLink, ModuleTransition, PersonalInfo, RecoIcon },
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const state = reactive({
recoShow: false,
currentPage: 1,
tags: []
}
},
computed: {
homeBlogCfg () {
return this.$recoLocales.homeBlog
},
actionLink () {
const {
actionLink: link,
actionText: text
} = this.$frontmatter
heroHeight: 0
})
const recoShowModule = computed(() => instance && instance.$parent.recoShowModule)
const heroImageStyle = computed(() => instance.$frontmatter.heroImageStyle || {})
const bgImageStyle = computed(() => {
const url = instance.$frontmatter.bgImage
? instance.$withBase(instance.$frontmatter.bgImage)
: require('../../images/bg.svg')
return {
link,
text
}
},
heroImageStyle () {
return this.$frontmatter.heroImageStyle || {
maxHeight: '200px',
margin: '6rem auto 1.5rem'
}
},
bgImageStyle () {
const initBgImageStyle = {
height: '350px',
textAlign: 'center',
overflow: 'hidden'
overflow: 'hidden',
background: `url(${url}) center/cover no-repeat`
}
const {
bgImageStyle
} = this.$frontmatter
const { bgImageStyle } = instance.$frontmatter
return bgImageStyle ? { ...initBgImageStyle, ...bgImageStyle } : initBgImageStyle
},
heroHeight () {
return document.querySelector('.hero').clientHeight
}
},
mounted () {
this.recoShow = true
this._setPage(this._getStoragePage())
})
onMounted(() => {
state.heroHeight = document.querySelector('.hero').clientHeight
state.recoShow = true
})
return { recoShowModule, heroImageStyle, bgImageStyle, ...toRefs(state), getOneColor }
},
methods: {
//
getCurrentPage (page) {
this._setPage(page)
paginationChange (page) {
setTimeout(() => {
window.scrollTo(0, this.heroHeight)
}, 100)
},
//
getPages () {
let pages = this.$site.pages
pages = pages.filter(item => {
const { home, date } = item.frontmatter
return !(home == true || date === undefined)
})
// reverse()
this.pages = pages.length == 0 ? [] : pages
},
getPagesByTags (tagInfo) {
this.$router.push({ path: tagInfo.path })
},
_setPage (page) {
this.currentPage = page
this.$page.currentPage = page
this._setStoragePage(page)
},
getOneColor
}
}
}
})
</script>
<style lang="stylus">
.home-blog {
padding: $navbarHeight 0 0;
padding: 0;
margin: 0px auto;
.hero {
margin $navbarHeight auto 0
position relative
.mask {
position absolute
top 0
bottom 0
left 0
right 0
z-index -1
&:after {
display block
content ' '
background var(--mask-color)
position absolute
top 0
bottom 0
left 0
right 0
z-index 0
opacity .2
}
}
figure {
position absolute
background yellow
box-sizing border-box
padding 0 20px
height 100vh
display flex
align-items center
justify-content center
.hero-img {
max-width: 300px;
margin: 0 auto 1.5rem
}
h1 {
margin:7rem auto 1.8rem;
display: block;
margin:0 auto 1.8rem;
font-size: 2.5rem;
}
h1, .description, .action, .huawei {
color #fff
}
.description {
margin: 1.8rem auto;
font-size: 1.6rem;
@ -215,6 +151,7 @@ export default {
display flex
align-items: flex-start;
margin 20px auto 0
padding 0 20px
max-width $homePageWidth
.blog-list {
flex auto
@ -231,7 +168,6 @@ export default {
top 70px
overflow hidden
transition all .3s
margin-top 15px
margin-left 15px
flex 0 0 300px
height auto
@ -258,10 +194,15 @@ export default {
background-color var(--background-color)
&:hover {
transform scale(1.04)
a {
color $accentColor
}
}
a {
display flex
justify-content: space-between
align-items: center
color var(--text-color)
.post-num {
width 1.6rem;
height 1.6rem
@ -281,10 +222,7 @@ export default {
@media (max-width: $MQMobile) {
.home-blog {
padding-left: 1.5rem;
padding-right: 1.5rem;
.hero {
margin 0 -1.5rem
height 450px
img {
max-height: 210px;
@ -292,14 +230,10 @@ export default {
}
h1 {
margin: 6rem auto 1.8rem ;
margin: 0 auto 1.8rem ;
font-size: 2rem;
}
h1, .description, .action {
// margin: 1.2rem auto;
}
.description {
font-size: 1.2rem;
}
@ -327,19 +261,15 @@ export default {
@media (max-width: $MQMobileNarrow) {
.home-blog {
padding-left: 1.5rem;
padding-right: 1.5rem;
.hero {
margin 0 -1.5rem
height 350px
height 450px
img {
max-height: 210px;
margin: 2rem auto 1.2rem;
}
h1 {
margin: 6rem auto 1.8rem ;
margin: 0 auto 1.8rem ;
font-size: 2rem;
}

View File

@ -17,14 +17,15 @@
</template>
<script>
export default {
mounted () {
import { defineComponent } from 'vue-demi'
export default defineComponent({
setup (props, ctx) {
const script = document.createElement('script')
script.src = 'http://f1.webshare.mob.com/code/mob-share.js?appkey=2d1a37832f835'
script.id = '-mob-share'
document.body.append(script)
}
}
})
</script>

View File

@ -61,8 +61,6 @@ export default {
</script>
<style lang="stylus">
@require '../../styles/mode.styl'
.mode-options
background-color var(--background-color)
min-width: 125px;
@ -79,6 +77,7 @@ export default {
display: flex;
flex-wrap wrap
li
flex: 1;
text-align: center;
font-size 12px
color var(--text-color)

View File

@ -3,10 +3,14 @@ import modeOptions from './modeOptions'
function render (mode) {
const rootElement = document.querySelector(':root')
const options = modeOptions[mode]
const opposite = mode === 'dark' ? 'light' : 'dark'
for (const k in options) {
rootElement.style.setProperty(k, options[k])
}
rootElement.classList.remove(opposite)
rootElement.classList.add(mode)
}
/**

View File

@ -1,17 +1,18 @@
<template>
<div v-click-outside="hideMenu" class="color-picker" v-if="$themeConfig.modePicker !== false" >
<a class="color-button" @click.prevent="showMenu = !showMenu">
<i class="iconfont reco-color"></i>
<reco-icon icon="reco-color" />
</a>
<transition name="menu-transition" mode="out-in">
<ModuleTransition :transform=" ['translate(-50%, 0)', 'translate(-50%, -10px)']">
<div v-show="showMenu" class="color-picker-menu">
<ModePicker />
</div>
</transition>
</ModuleTransition>
</div>
</template>
<script>
import { RecoIcon, ModuleTransition } from '@vuepress-reco/core/lib/components'
import ClickOutside from 'vue-click-outside'
import ModePicker from './ModePicker'
import applyMode from './applyMode'
@ -24,7 +25,9 @@ export default {
},
components: {
ModePicker
ModePicker,
RecoIcon,
ModuleTransition
},
data () {
@ -61,8 +64,6 @@ export default {
</script>
<style lang="stylus">
@require '../../styles/mode.styl'
.color-picker {
position: relative;
margin-right: 1em;
@ -80,17 +81,7 @@ export default {
position: absolute;
top: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 150;
&.menu-transition-enter-active,
&.menu-transition-leave-active {
transition: all 0.25s ease-in-out;
}
&.menu-transition-enter,
&.menu-transition-leave-to {
top: 50px;
opacity: 0;
}
ul {
list-style-type: none;

View File

@ -1,45 +0,0 @@
<template>
<transition
name="module"
@enter="setStyle"
@after-enter="unsetStyle"
@before-leave="setStyle">
<slot />
</transition>
</template>
<script>
export default {
name: 'ModuleTransition',
props: {
delay: {
type: String,
default: '0'
},
duration: {
type: String,
default: '.25'
}
},
methods: {
setStyle (items) {
items.style.transition = `all ${this.duration}s ease-in-out ${this.delay}s`
items.style.transform = 'translateY(-20px)'
items.style.opacity = 0
},
unsetStyle (items) {
items.style.transform = 'translateY(0)'
items.style.opacity = 1
}
}
}
</script>
<style lang="stylus">
.module-enter, .module-leave-to {
opacity: 0;
transform:translateY(-20px);
}
</style>

View File

@ -4,7 +4,7 @@
:to="link"
v-if="!isExternal(link)"
:exact="exact">
<i :class="`iconfont ${item.icon}`"></i>
<reco-icon :icon="`${item.icon}`" />
{{ item.text }}
</router-link>
<a
@ -14,39 +14,41 @@
:target="isMailto(link) || isTel(link) ? null : '_blank'"
:rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
>
<i :class="`iconfont ${item.icon}`"></i>
<reco-icon :icon="`${item.icon}`" />
{{ item.text }}
<OutboundLink/>
</a>
</template>
<script>
import { defineComponent, computed, toRefs, getCurrentInstance } from 'vue-demi'
import { isExternal, isMailto, isTel, ensureExt } from '@theme/helpers/utils'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
export default defineComponent({
components: { RecoIcon },
export default {
props: {
item: {
required: true
}
},
computed: {
link () {
return ensureExt(this.item.link)
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
exact () {
if (this.$site.locales) {
return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
const { item } = toRefs(props)
const link = computed(() => ensureExt(item.value.link))
const exact = computed(() => {
if (instance.$site.locales) {
return Object.keys(instance.$site.locales).some(rootLink => rootLink === link.value)
}
return this.link === '/'
}
},
return link.value === '/'
})
methods: {
isExternal,
isMailto,
isTel
return { link, exact, isExternal, isMailto, isTel }
}
}
})
</script>

View File

@ -1,19 +1,13 @@
<template>
<nav
class="nav-links"
v-if="userLinks.length || repoLink"
>
<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"/>
:key="item.link"
>
<DropdownLink v-if="item.type === 'links'" :item="item" />
<NavLink v-else :item="item" />
</div>
<!-- repo link -->
@ -22,8 +16,9 @@
:href="repoLink"
class="repo-link"
target="_blank"
rel="noopener noreferrer">
<i :class="`iconfont reco-${repoLabel.toLowerCase()}`"></i>
rel="noopener noreferrer"
>
<reco-icon :icon="`reco-${repoLabel.toLowerCase()}`" />
{{ repoLabel }}
<OutboundLink/>
</a>
@ -31,36 +26,41 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import DropdownLink from '@theme/components/DropdownLink'
import { resolveNavLinkItem } from '@theme/helpers/utils'
import NavLink from '@theme/components/NavLink'
export default {
components: { NavLink, DropdownLink },
export default defineComponent({
components: { NavLink, DropdownLink, RecoIcon },
computed: {
userNav () {
return this.$themeLocaleConfig.nav || this.$themeConfig.nav || []
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const userNav = computed(() => {
return instance.$themeLocaleConfig.nav || instance.$themeConfig.nav || []
})
const nav = computed(() => {
const locales = instance.$site.locales || {}
nav () {
const { $site: { locales }, userNav } = this
if (locales && Object.keys(locales).length > 1) {
const currentLink = this.$page.path
const routes = this.$router.options.routes
const themeLocales = this.$themeConfig.locales || {}
const currentLink = instance.$page.path
const routes = instance.$router.options.routes
const themeLocales = instance.$themeConfig.locales || {}
const languageDropdown = {
text: this.$themeLocaleConfig.selectText || 'Languages',
text: instance.$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) {
if (locale.lang === instance.$lang) {
link = currentLink
} else {
// Try to stay on the same page
link = currentLink.replace(this.$localeConfig.path, path)
link = currentLink.replace(instance.$localeConfig.path, path)
// fallback to homepage
if (!routes.some(route => route.path === link)) {
link = path
@ -69,19 +69,20 @@ export default {
return { text, link }
})
}
return [...userNav, languageDropdown]
return [...userNav.value, languageDropdown]
}
// blogConfig
const blogConfig = this.$themeConfig.blogConfig || {}
const isHasCategory = userNav.some(item => {
const blogConfig = instance.$themeConfig.blogConfig || {}
const isHasCategory = userNav.value.some(item => {
if (blogConfig.category) {
return item.text === (blogConfig.category.text || '分类')
} else {
return true
}
})
const isHasTag = userNav.some(item => {
const isHasTag = userNav.value.some(item => {
if (blogConfig.tag) {
return item.text === (blogConfig.tag.text || '标签')
} else {
@ -91,56 +92,59 @@ export default {
if (!isHasCategory && Object.hasOwnProperty.call(blogConfig, 'category')) {
const category = blogConfig.category
const $categories = this.$categories
userNav.splice(parseInt(category.location || 2) - 1, 0, {
const $categories = instance.$categories
userNav.value.splice(parseInt(category.location || 2) - 1, 0, {
items: $categories.list.map(item => {
item.link = item.path
item.text = item.name
return item
}),
text: category.text || '分类',
text: category.text || instance.$recoLocales.category,
type: 'links',
icon: 'reco-category'
})
}
if (!isHasTag && Object.hasOwnProperty.call(blogConfig, 'tag')) {
const tag = blogConfig.tag
userNav.splice(parseInt(tag.location || 3) - 1, 0, {
userNav.value.splice(parseInt(tag.location || 3) - 1, 0, {
link: '/tag/',
text: tag.text || '标签',
text: tag.text || instance.$recoLocales.tag,
type: 'links',
icon: 'reco-tag'
})
}
return userNav
},
return userNav.value
})
userLinks () {
return (this.nav || []).map(link => {
const userLinks = computed(() => {
return (instance.nav || []).map(link => {
return Object.assign(resolveNavLinkItem(link), {
items: (link.items || []).map(resolveNavLinkItem)
})
})
},
})
const repoLink = computed(() => {
const { repo } = instance.$themeConfig
repoLink () {
const { repo } = this.$themeConfig
if (repo) {
return /^https?:/.test(repo)
? repo
: `https://github.com/${repo}`
}
return ''
},
repoLabel () {
if (!this.repoLink) return
if (this.$themeConfig.repoLabel) {
return this.$themeConfig.repoLabel
return ''
})
const repoLabel = computed(() => {
if (!instance.repoLink) return ''
if (instance.$themeConfig.repoLabel) {
return instance.$themeConfig.repoLabel
}
const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
const repoHost = instance.repoLink.match(/^https?:\/\/[^/]+/)[0]
const platforms = ['GitHub', 'GitLab', 'Bitbucket']
for (let i = 0; i < platforms.length; i++) {
const platform = platforms[i]
@ -150,9 +154,11 @@ export default {
}
return 'Source'
}
})
return { userNav, nav, userLinks, repoLink, repoLabel }
}
}
})
</script>
<style lang="stylus">
@ -184,5 +190,4 @@ export default {
.nav-item > a:not(.external)
&:hover, &.router-link-active
margin-bottom -2px
border-bottom 2px solid lighten($accentColor, 8%)
</style>

View File

@ -33,58 +33,62 @@
</template>
<script>
import { defineComponent, ref, onMounted, getCurrentInstance, computed } from 'vue-demi'
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@theme/components/SidebarButton'
import NavLinks from '@theme/components/NavLinks'
import Mode from '@theme/components/Mode'
export default {
export default defineComponent({
components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox, Mode },
data () {
return {
linksWrapMaxWidth: null
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const linksWrapMaxWidth = ref(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)
const algolia = computed(() => {
return instance.$themeLocaleConfig.algolia || instance.$themeConfig.algolia || {}
})
const isAlgoliaSearch = computed(() => {
algolia.value && algolia.value.apiKey && algolia.value.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]
}
onMounted(() => {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING =
parseInt(css(instance.$el, 'paddingLeft')) +
parseInt(css(instance.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
linksWrapMaxWidth.value = null
} else {
linksWrapMaxWidth.value =
instance.$el.offsetWidth -
NAVBAR_VERTICAL_PADDING -
(instance.$refs.siteName && instance.$refs.siteName.offsetWidth || 0)
}
}
}
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$themeConfig.algolia || {}
},
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
})
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
return { linksWrapMaxWidth, algolia, isAlgoliaSearch, css }
}
}
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">
@require '../styles/mode.styl'
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem
@ -106,7 +110,6 @@ $navbar-horizontal-padding = 1.5rem
font-weight 600
color var(--text-color)
position relative
background var(--background-color)
.links
padding-left 1.5rem
box-sizing border-box

View File

@ -5,24 +5,59 @@
:key="item.path"
:item="item"
:currentPage="currentPage"
:currentTag="currentTag" />
:currentTag="currentTag"
/>
<pagation
class="pagation"
:total="data.length"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"
/>
</div>
</template>
<script>
import { defineComponent, ref, toRefs, computed, getCurrentInstance, onMounted } from 'vue-demi'
import pagination from '@theme/mixins/pagination'
import NoteAbstractItem from './NoteAbstractItem'
export default {
export default defineComponent({
mixins: [pagination],
components: { NoteAbstractItem },
props: ['data', 'currentPage', 'currentTag'],
computed: {
currentPageData () {
const start = this.currentPage * 10 - 10
const end = this.currentPage * 10
return this.data.slice(start, end)
props: ['data', 'currentTag'],
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const { data } = toRefs(props)
const currentPage = ref(1)
const currentPageData = computed(() => {
const start = (currentPage.value - 1) * instance.$perPage
const end = currentPage.value * instance.$perPage
return data.value.slice(start, end)
})
const getCurrentPage = (page) => {
currentPage.value = page
instance._setStoragePage(page)
ctx.emit('paginationChange', page)
}
onMounted(() => {
currentPage.value = instance._getStoragePage() || 1
})
return { currentPage, currentPageData, getCurrentPage }
},
watch: {
$route () {
this.currentPage = this._getStoragePage() || 1
}
}
}
})
</script>
<style lang="stylus" scoped>

View File

@ -2,13 +2,12 @@
<div
class="abstract-item"
@click="$router.push(item.path)">
<i v-if="item.frontmatter.sticky" class="iconfont reco-sticky"></i>
<reco-icon v-if="item.frontmatter.sticky" icon="reco-sticky" />
<div class="title">
<i v-if="item.frontmatter.keys" class="iconfont reco-lock"></i>
<reco-icon v-if="item.frontmatter.keys" icon="reco-lock" />
<router-link :to="item.path">{{item.title}}</router-link>
</div>
<div class="abstract" v-html="item.excerpt"></div>
<hr class="hr">
<PageInfo
:pageInfo="item"
:currentTag="currentTag">
@ -17,15 +16,16 @@
</template>
<script>
import { defineComponent } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import PageInfo from './PageInfo'
export default {
components: { PageInfo },
export default defineComponent({
components: { PageInfo, RecoIcon },
props: ['item', 'currentPage', 'currentTag']
}
})
</script>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.abstract-item
position relative
margin: 0 auto 20px;
@ -53,8 +53,10 @@ export default {
.title
position: relative;
font-size: 1.28rem;
line-height: 36px;
line-height: 46px;
display: inline-block;
a
color: var(--text-color);
.reco-lock
font-size 1.28rem
color $accentColor

View File

@ -1,23 +1,19 @@
<template>
<main class="page" :style="pageStyle">
<ModuleTransition>
<div v-show="recoShowModule && $page.title" class="page-title">
<h1>{{$page.title}}</h1>
<hr>
<PageInfo :pageInfo="$page" :showAccessNumber="showAccessNumber"></PageInfo>
</div>
</ModuleTransition>
<ModuleTransition delay="0.08">
<Content v-show="recoShowModule" class="theme-reco-content" />
<section v-show="recoShowModule">
<div class="page-title">
<h1 class="title">{{$page.title}}</h1>
<PageInfo :pageInfo="$page" :showAccessNumber="showAccessNumber"></PageInfo>
</div>
<!-- 这里使用 v-show否则影响 SSR -->
<Content class="theme-reco-content" />
</section>
</ModuleTransition>
<ModuleTransition delay="0.16">
<footer v-show="recoShowModule" class="page-edit">
<div
class="edit-link"
v-if="editLink"
>
<footer v-if="recoShowModule" class="page-edit">
<div class="edit-link" v-if="editLink">
<a
:href="editLink"
target="_blank"
@ -39,31 +35,15 @@
<ModuleTransition delay="0.24">
<div class="page-nav" v-if="recoShowModule && (prev || next)">
<p class="inner">
<span
v-if="prev"
class="prev"
>
<router-link
v-if="prev"
class="prev"
:to="prev.path"
>
<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"
>
<span v-if="next" class="next">
<router-link v-if="next" :to="next.path">
{{ next.title || next.path }}
</router-link>
</span>
</p>
</div>
@ -73,84 +53,88 @@
<Comments v-if="recoShowModule" :isShowComments="shouldShowComments"/>
</ModuleTransition>
<ModuleTransition delay="0.4">
<SubSidebar class="side-bar" />
<ModuleTransition>
<SubSidebar v-if="recoShowModule" class="side-bar" />
</ModuleTransition>
</main>
</template>
<script>
import { defineComponent, computed, getCurrentInstance, toRefs } from 'vue-demi'
import PageInfo from '@theme/components/PageInfo'
import { resolvePage, outboundRE, endingSlashRE } from '@theme/helpers/utils'
import ModuleTransition from '@theme/components/ModuleTransition'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
import SubSidebar from '@theme/components/SubSidebar'
export default {
mixins: [moduleTransitonMixin],
export default defineComponent({
components: { PageInfo, ModuleTransition, SubSidebar },
props: ['sidebarItems'],
data () {
return {
isHasKey: true
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const { sidebarItems } = toRefs(props)
const recoShowModule = computed(() => instance.$parent.recoShowModule)
computed: {
//
shouldShowComments () {
const { isShowComments } = this.$frontmatter
const { showComment } = this.$themeConfig.valineConfig || { showComment: true }
const shouldShowComments = computed(() => {
const { isShowComments } = instance.$frontmatter
const { showComment } = instance.$themeConfig.valineConfig || { showComment: true }
return (showComment !== false && isShowComments !== false) || (showComment === false && isShowComments === true)
},
showAccessNumber () {
})
const showAccessNumber = computed(() => {
const {
$themeConfig: { valineConfig },
$themeLocaleConfig: { valineConfig: valineLocalConfig }
} = this
} = instance || {}
const vc = valineLocalConfig || valineConfig
if (vc && vc.visitor != false) {
return true
return vc && vc.visitor != false
})
const lastUpdated = computed(() => {
if (instance.$themeConfig.lastUpdated === false) return false
return instance.$page.lastUpdated
})
const lastUpdatedText = computed(() => {
if (typeof instance.$themeLocaleConfig.lastUpdated === 'string') {
return instance.$themeLocaleConfig.lastUpdated
}
return false
},
lastUpdated () {
return this.$page.lastUpdated
},
lastUpdatedText () {
if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
return this.$themeLocaleConfig.lastUpdated
}
if (typeof this.$themeConfig.lastUpdated === 'string') {
return this.$themeConfig.lastUpdated
if (typeof instance.$themeConfig.lastUpdated === 'string') {
return instance.$themeConfig.lastUpdated
}
return 'Last Updated'
},
prev () {
const prev = this.$frontmatter.prev
if (prev === false) {
})
const prev = computed(() => {
const frontmatterPrev = instance.$frontmatter.prev
if (frontmatterPrev === false) {
return
} else if (prev) {
return resolvePage(this.$site.pages, prev, this.$route.path)
} else if (frontmatterPrev) {
return resolvePage(instance.$site.pages, frontmatterPrev, instance.$route.path)
} else {
return resolvePrev(this.$page, this.sidebarItems)
return resolvePrev(instance.$page, sidebarItems.value)
}
},
next () {
const next = this.$frontmatter.next
})
const next = computed(() => {
const frontmatterNext = instance.$frontmatter.next
if (next === false) {
return
} else if (next) {
return resolvePage(this.$site.pages, next, this.$route.path)
} else if (frontmatterNext) {
return resolvePage(instance.$site.pages, frontmatterNext, instance.$route.path)
} else {
return resolveNext(this.$page, this.sidebarItems)
return resolveNext(instance.$page, sidebarItems.value)
}
},
editLink () {
if (this.$frontmatter.editLink === false) {
})
const editLink = computed(() => {
if (instance.$frontmatter.editLink === false) {
return false
}
const {
@ -159,53 +143,66 @@ export default {
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = this.$themeConfig
} = instance.$themeConfig
if (docsRepo && editLinks && this.$page.relativePath) {
return this.createEditLink(repo, docsRepo, docsDir, docsBranch, this.$page.relativePath)
if (docsRepo && editLinks && instance.$page.relativePath) {
return createEditLink(repo, docsRepo, docsDir, docsBranch, instance.$page.relativePath)
}
return ''
},
editLinkText () {
return (
this.$themeLocaleConfig.editLinkText || this.$themeConfig.editLinkText || `Edit this page`
)
},
pageStyle () {
const headers = this.$page.headers || []
return headers.length > 0 ? {} : { paddingRight: '0' }
}
},
})
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, '') +
`/src` +
`/${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}`
const editLinkText = computed(() => {
return (
base.replace(endingSlashRE, '') +
`/edit` +
`/${docsBranch}/` +
(docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '') +
path
instance.$themeLocaleConfig.editLinkText || instance.$themeConfig.editLinkText || `Edit this page`
)
})
const pageStyle = computed(() => {
return instance.$showSubSideBar ? {} : { paddingRight: '0' }
})
return {
recoShowModule,
shouldShowComments,
showAccessNumber,
lastUpdated,
lastUpdatedText,
prev,
next,
editLink,
editLinkText,
pageStyle
}
}
})
function 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, '') +
`/src` +
`/${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) {
@ -262,6 +259,17 @@ function flatten (items, res) {
margin: 0 auto;
padding: 1rem 2.5rem;
color var(--text-color)
.theme-reco-content h2
position relative
padding-left 0.8rem
&::before
position absolute
left 0
top 3.5rem
display block
height 1.8rem
content ''
border-left 5px solid $accentColor
.page-edit
@extend $wrapper
padding-top 1rem

View File

@ -1,40 +1,45 @@
<template>
<div>
<i
class="iconfont reco-account"
v-if="pageInfo.frontmatter.author || $themeConfig.author || $site.title">
<span>{{ pageInfo.frontmatter.author || $themeConfig.author || $site.title }}</span>
</i>
<i
<reco-icon
v-if="pageInfo.frontmatter.author || $themeConfig.author"
icon="reco-account"
>
<span>{{ pageInfo.frontmatter.author || $themeConfig.author }}</span>
</reco-icon>
<reco-icon
v-if="pageInfo.frontmatter.date"
class="iconfont reco-date">
<span>{{ pageInfo.frontmatter.date | formatDateValue }}</span>
</i>
<i
icon="reco-date"
>
<span>{{ formatDateValue(pageInfo.frontmatter.date) }}</span>
</reco-icon>
<reco-icon
v-if="showAccessNumber === true"
class="iconfont reco-eye">
<AccessNumber
:idVal="pageInfo.path"
:numStyle="numStyle" />
</i>
<i
icon="reco-eye"
>
<AccessNumber :idVal="pageInfo.path" :numStyle="numStyle" />
</reco-icon>
<reco-icon
v-if="pageInfo.frontmatter.tags"
class="iconfont reco-tag tags">
icon="reco-tag"
class="tags"
>
<span
v-for="(subItem, subIndex) in pageInfo.frontmatter.tags"
:key="subIndex"
class="tag-item"
:class="{ 'active': currentTag == subItem }"
@click.stop="goTags(subItem)">{{subItem}}</span>
</i>
@click.stop="goTags(subItem)"
>{{subItem}}</span>
</reco-icon>
</div>
</template>
<script>
// js
import { formatDate } from '@theme/helpers/utils'
import { defineComponent, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
export default {
export default defineComponent({
components: { RecoIcon },
props: {
pageInfo: {
type: Object,
@ -51,44 +56,29 @@ export default {
default: false
}
},
data () {
return {
numStyle: {
fontSize: '.9rem',
fontWeight: 'normal',
color: '#999'
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const numStyle = {
fontSize: '.9rem',
fontWeight: 'normal',
color: '#999'
}
const goTags = (tag) => {
if (instance.$route.path !== `/tag/${tag}/`) {
instance.$router.push({ path: `/tag/${tag}/` })
}
}
},
filters: {
formatDateValue (value) {
if (!value) return ''
// value2019-09-20T18:22:30.000Z
// value
value = value.replace('T', ' ').slice(0, value.lastIndexOf('.'))
// value 2019-09-20 18:22:30
//
const h = Number(value.substr(11, 2))
const m = Number(value.substr(14, 2))
const s = Number(value.substr(17, 2))
// 00:00:00 (00:00:00)
if (h > 0 || m > 0 || s > 0) {
// > 0 00:00:00
return formatDate(value)
} else {
// 00:00:00
return formatDate(value, 'yyyy-MM-dd')
}
}
},
methods: {
goTags (tag) {
if (this.$route.path !== `/tag/${tag}/`) {
this.$router.push({ path: `/tag/${tag}/` })
}
const formatDateValue = (value) => {
return new Intl.DateTimeFormat(instance.$lang).format(new Date(value))
}
return { numStyle, goTags, formatDateValue }
}
}
})
</script>
<style lang="stylus" scoped>
@ -102,6 +92,7 @@ export default {
.tags
.tag-item
font-family Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif
cursor pointer
&.active
color $accentColor
&:hover

View File

@ -24,13 +24,13 @@
<ModuleTransition delay="0.24">
<div v-show="recoShowModule" class="footer">
<span>
<i class="iconfont reco-theme"></i>
<reco-icon icon="reco-theme" />
<a target="blank" href="https://vuepress-theme-reco.recoluan.com">vuePress-theme-reco</a>
</span>
<span>
<i class="iconfont reco-copyright"></i>
<reco-icon icon="reco-copyright" />
<a>
<span v-if="$themeConfig.author || $site.title">{{ $themeConfig.author || $site.title }}</span>
<span v-if="$themeConfig.author">{{ $themeConfig.author }}</span>
&nbsp;&nbsp;
<span v-if="$themeConfig.startYear && $themeConfig.startYear != year">{{ $themeConfig.startYear }} - </span>
{{ year }}
@ -42,84 +42,78 @@
</template>
<script>
import { defineComponent, ref, toRefs, computed, getCurrentInstance } from 'vue-demi'
import md5 from 'md5'
import ModuleTransition from '@theme/components/ModuleTransition'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
import { ModuleTransition, RecoIcon } from '@vuepress-reco/core/lib/components'
export default {
mixins: [moduleTransitonMixin],
components: { ModuleTransition },
export default defineComponent({
name: 'Password',
components: { ModuleTransition, RecoIcon },
props: {
isPage: {
type: Boolean,
default: false
}
},
name: 'Password',
data () {
return {
warningText: 'Konck! Knock!',
key: ''
}
},
computed: {
year () {
return new Date().getFullYear()
}
},
methods: {
inter () {
const {
key,
isPage,
isHasPageKey,
isHasKey,
$refs: { passwordBtn }
} = this
const keyVal = md5(key.trim())
const pageKey = `pageKey${window.location.pathname}`
const keyName = isPage ? pageKey : 'key'
sessionStorage.setItem(keyName, keyVal)
const isKeyTrue = isPage ? isHasPageKey() : isHasKey()
if (!isKeyTrue) {
this.warningText = 'Key Error'
return
}
setup (props, ctx) {
const instance = getCurrentInstance().proxy
this.warningText = 'Key Success'
const year = new Date().getFullYear()
const width = document.getElementById('box').style.width
const key = ref('')
const warningText = ref('Konck! Knock!')
const recoShowModule = computed(() => instance?.$parent?.recoShowModule)
const { isPage } = toRefs(props)
passwordBtn.style.width = `${width - 2}px`
passwordBtn.style.opacity = 1
setTimeout(() => {
window.location.reload()
}, 800)
},
inputFocus () {
this.warningText = 'Input Your Key'
},
inputBlur () {
this.warningText = 'Konck! Knock!'
},
isHasKey () {
let { keys } = this.$themeConfig.keyPage
const isHasKey = () => {
let { keys } = instance.$themeConfig.keyPage
keys = keys.map(item => item.toLowerCase())
return keys.indexOf(sessionStorage.getItem('key')) > -1
},
isHasPageKey () {
const pageKeys = this.$frontmatter.keys.map(item => item.toLowerCase())
}
const isHasPageKey = () => {
const pageKeys = instance.$frontmatter.keys.map(item => item.toLowerCase())
const pageKey = `pageKey${window.location.pathname}`
return pageKeys && pageKeys.indexOf(sessionStorage.getItem(pageKey)) > -1
}
const inter = () => {
const keyVal = md5(key.value.trim())
const pageKey = `pageKey${window.location.pathname}`
const keyName = isPage.value ? pageKey : 'key'
sessionStorage.setItem(keyName, keyVal)
const isKeyTrue = isPage.value ? isHasPageKey() : isHasKey()
if (!isKeyTrue) {
warningText.value = 'Key Error'
return
}
warningText.value = 'Key Success'
const width = document.getElementById('box').style.width
instance.$refs.passwordBtn.style.width = `${width - 2}px`
instance.$refs.passwordBtn.style.opacity = 1
setTimeout(() => {
window.location.reload()
}, 800)
}
const inputFocus = () => {
warningText.value = 'Input Your Key'
}
const inputBlur = () => {
warningText.value = 'Konck! Knock!'
}
return { warningText, year, key, recoShowModule, inter, inputFocus, inputBlur }
}
}
})
</script>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.password-shadow {
overflow hidden
position relative
@ -161,7 +155,7 @@ export default {
box-sizing border-box
opacity 0.9
input{
width:600px;
width:570px;
height:100%;
border:none;
padding:0;

View File

@ -8,32 +8,50 @@
>
<h3
class="name"
v-if="$themeConfig.author || $site.title"
v-if="$themeConfig.author"
>
{{ $themeConfig.author || $site.title }}
{{ $themeConfig.author }}
</h3>
<div class="num">
<div>
<h3>{{$recoPosts.length}}</h3>
<h6>{{homeBlogCfg.article}}</h6>
<h6>{{$recoLocales.article}}</h6>
</div>
<div>
<h3>{{$tags.list.length}}</h3>
<h6>{{homeBlogCfg.tag}}</h6>
<h6>{{$recoLocales.tag}}</h6>
</div>
</div>
<ul class="social-links">
<li
class="social-item"
v-for="(item, index) in socialLinks"
:key="index"
>
<reco-icon :icon="item.icon" :link="item.link" :style="{ color: item.color }" />
</li>
</ul>
<hr>
</div>
</template>
<script>
export default {
computed: {
homeBlogCfg () {
return this.$recoLocales.homeBlog
}
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
import { getOneColor } from '@theme/helpers/other'
export default defineComponent({
components: { RecoIcon },
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const socialLinks = computed(() => (instance.$themeConfig.blogConfig && instance.$themeConfig.blogConfig.socialLinks || []).map(item => {
if (!item.color) item.color = getOneColor()
return item
}))
return { socialLinks }
}
}
})
</script>
<style lang="stylus" scoped>
@ -72,5 +90,26 @@ export default {
}
}
}
.social-links {
box-sizing border-box
display flex
flex-wrap wrap
padding 10px
.social-item {
width 39px
height 36px
line-height 36px
text-align center
list-style none
transition transform .3s
&:hover {
transform scale(1.08)
}
i {
cursor pointer
font-size 22px
}
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="search-box">
<i class="iconfont reco-search"></i>
<reco-icon icon="reco-search" />
<input
@input="query = $event.target.value"
aria-label="Search"
@ -40,32 +40,44 @@
</template>
<script>
export default {
data () {
return {
import { defineComponent, reactive, toRefs, computed, getCurrentInstance } from 'vue-demi'
import { RecoIcon } from '@vuepress-reco/core/lib/components'
export default defineComponent({
components: { RecoIcon },
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const state = reactive({
query: '',
focused: false,
focusIndex: 0,
placeholder: undefined
}
},
mounted () {
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
},
computed: {
showSuggestions () {
})
const showSuggestions = computed(() => {
return (
this.focused && this.suggestions && this.suggestions.length
state.focused && suggestions.value && suggestions.value.length
)
},
suggestions () {
const query = this.query.trim().toLowerCase()
})
const getPageLocalePath = (page) => {
for (const localePath in instance.$site.locales || {}) {
if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
return localePath
}
}
return '/'
}
const suggestions = computed(() => {
const query = state.query.trim().toLowerCase()
if (!query) {
return
}
const { pages } = this.$site
const max = this.$site.themeConfig.searchMaxSuggestions
const localePath = this.$localePath
const { pages } = instance.$site
const max = instance.$site.themeConfig.searchMaxSuggestions
const localePath = instance.$localePath
const matches = item => (
item && item.title && item.title.toLowerCase().indexOf(query) > -1
)
@ -74,7 +86,7 @@ export default {
if (res.length >= max) break
const p = pages[i]
// filter out results that do not match current locale
if (this.getPageLocalePath(p) !== localePath) {
if (getPageLocalePath(p) !== localePath) {
continue
}
if (matches(p)) {
@ -93,57 +105,57 @@ export default {
}
}
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
})
const alignRight = computed(() => {
const navCount = (instance.$site.themeConfig.nav || []).length
const repo = instance.$site.repo ? 1 : 0
return navCount + repo <= 2
})
const onUp = () => {
if (showSuggestions.value) {
if (state.focusIndex > 0) {
state.focusIndex--
} else {
state.focusIndex = suggestions.value.length - 1
}
}
}
},
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--
const onDown = () => {
if (showSuggestions.value) {
if (state.focusIndex < suggestions.value.length - 1) {
state.focusIndex++
} else {
this.focusIndex = this.suggestions.length - 1
state.focusIndex = 0
}
}
},
onDown () {
if (this.showSuggestions) {
if (this.focusIndex < this.suggestions.length - 1) {
this.focusIndex++
} else {
this.focusIndex = 0
}
}
},
go (i) {
if (!this.showSuggestions) {
}
const go = (i) => {
if (!showSuggestions.value) {
return
}
this.$router.push(this.suggestions[i].path)
this.query = ''
this.focusIndex = 0
},
focus (i) {
this.focusIndex = i
},
unfocus () {
this.focusIndex = -1
instance.$router.push(suggestions.value[i].path)
state.query = ''
state.focusIndex = 0
}
const focus = (i) => {
state.focusIndex = i
}
const unfocus = () => {
state.focusIndex = -1
}
return { showSuggestions, suggestions, alignRight, onUp, onDown, focus, unfocus, go, ...toRefs(state) }
},
mounted () {
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
}
}
})
</script>
<style lang="stylus">

View File

@ -8,16 +8,15 @@
</template>
<script>
import { defineComponent } from 'vue-demi'
import SidebarLinks from '@theme/components/SidebarLinks'
import NavLinks from '@theme/components/NavLinks'
export default {
export default defineComponent({
name: 'Sidebar',
components: { SidebarLinks, NavLinks },
props: ['items']
}
})
</script>
<style lang="stylus">

View File

@ -54,19 +54,23 @@
</template>
<script>
import { defineComponent, getCurrentInstance } from 'vue-demi'
import { isActive } from '@theme/helpers/utils'
import DropdownTransition from '@theme/components/DropdownTransition'
export default {
export default defineComponent({
name: 'SidebarGroup',
props: ['item', 'open', 'collapsable', 'depth'],
components: { DropdownTransition },
// ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
beforeCreate () {
this.$options.components.SidebarLinks = require('./SidebarLinks.vue').default
},
methods: { isActive }
}
setup (props, ctx) {
const instance = getCurrentInstance().proxy
instance.$options.components.SidebarLinks = require('./SidebarLinks.vue').default
return { isActive }
}
})
</script>
<style lang="stylus">

View File

@ -1,7 +1,8 @@
<script>
import { defineComponent } from 'vue-demi'
import { isActive } from '@theme/helpers/utils'
export default {
export default defineComponent({
functional: true,
props: ['item', 'sidebarDepth'],
@ -30,27 +31,8 @@ export default {
: selfActive
const link = renderLink(h, item.path, item.title || item.path, active)
return link
// const configDepth = $page.frontmatter.sidebarDepth ||
// sidebarDepth ||
// $themeLocaleConfig.sidebarDepth ||
// $themeConfig.sidebarDepth
// const maxDepth = configDepth == null ? 1 : configDepth
// const displayAllHeaders = $themeLocaleConfig.displayAllHeaders ||
// $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', {

View File

@ -22,11 +22,12 @@
</template>
<script>
import { defineComponent, ref, getCurrentInstance, toRefs, onUpdated, onMounted } from 'vue-demi'
import SidebarGroup from '@theme/components/SidebarGroup'
import SidebarLink from '@theme/components/SidebarLink'
import { isActive } from '@theme/helpers/utils'
export default {
export default defineComponent({
name: 'SidebarLinks',
components: { SidebarGroup, SidebarLink },
@ -37,57 +38,48 @@ export default {
'sidebarDepth' // depth of headers to be extracted
],
data () {
return {
openGroupIndex: 0
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const { items } = toRefs(props)
const openGroupIndex = ref(0)
const refreshIndex = () => {
const index = resolveOpenGroupIndex(
instance.$route,
items.value
)
if (index > -1) {
openGroupIndex.value = index
}
}
},
created () {
this.refreshIndex()
},
watch: {
'$route' () {
this.refreshIndex()
const activationAnchor = () => {
// eslint-disable-next-line no-undef
const anchors = [].slice.call(document.querySelectorAll(AHL_HEADER_ANCHOR_SELECTOR))
.filter(anchor => decodeURIComponent(instance.$route.fullPath).indexOf(decodeURIComponent(anchor.hash)) != -1)
if (anchors == null || anchors.length < 1 || anchors[0].offsetTop == undefined) return
setTimeout(function () {
window.scrollTo(0, anchors[0].offsetTop + 160)
}, 100)
}
},
mounted () {
this.activationLink()
this.isInViewPortOfOne()
},
updated: function () {
this.isInViewPortOfOne()
},
methods: {
activationLink () {
const subtitleName = decodeURIComponent(this.$route.fullPath)
const activationLink = () => {
const subtitleName = decodeURIComponent(instance.$route.fullPath)
if (!subtitleName || subtitleName == '') return
// eslint-disable-next-line no-undef
const subtitles = [].slice.call(document.querySelectorAll(AHL_SIDEBAR_LINK_SELECTOR))
for (let i = 0; i < subtitles.length; i++) {
if (decodeURIComponent(subtitles[i].getAttribute('href')).indexOf(subtitleName) != -1) {
subtitles[i].click()
this.activationAnchor()
activationAnchor()
return
}
}
},
}
activationAnchor () {
// eslint-disable-next-line no-undef
const anchors = [].slice.call(document.querySelectorAll(AHL_HEADER_ANCHOR_SELECTOR))
.filter(anchor => decodeURIComponent(this.$route.fullPath).indexOf(decodeURIComponent(anchor.hash)) != -1)
if (anchors == null || anchors.length < 1 || anchors[0].offsetTop == undefined) return
setTimeout(function () {
window.scrollTo(0, anchors[0].offsetTop + 160)
}, 100)
},
isInViewPortOfOne () {
const isInViewPortOfOne = () => {
const sidebarScroll = document.getElementsByClassName('sidebar')[0]
let el = document.getElementsByClassName('active sidebar-link')[1]
if (el == null || el == undefined || el.offsetTop == undefined) {
@ -107,27 +99,34 @@ export default {
if (!topVisible) {
sidebarScroll.scrollTop = (offsetTop - 5)
}
},
}
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex = index
}
},
const toggleGroup = (index) => {
instance.openGroupIndex = index === instance.openGroupIndex ? -1 : index
}
toggleGroup (index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index
},
const isActive = (page) => {
return isActive(instance.$route, page.regularPath)
}
isActive (page) {
return isActive(this.$route, page.regularPath)
refreshIndex()
onMounted(() => {
activationLink()
isInViewPortOfOne()
})
onUpdated(() => isInViewPortOfOne())
return { openGroupIndex, refreshIndex, toggleGroup, isActive }
},
watch: {
'$route' () {
this.refreshIndex()
}
}
}
})
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {

View File

@ -1,24 +1,33 @@
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import { isActive } from '@theme/helpers/utils'
export default {
computed: {
headers () {
const headers = (this.$page.headers || []).filter(header => header.level === 2)
return headers
}
},
methods: {
isLinkActive (header) {
return isActive(this.$route, this.$page.path + '#' + header.slug)
export default defineComponent({
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const headers = computed(() => {
return instance.$showSubSideBar ? instance.$page.headers : []
})
const isLinkActive = (header) => {
const active = isActive(instance.$route, instance.$page.path + '#' + header.slug)
if (active) {
setTimeout(() => {
document.querySelector(`.reco-side-${header.slug}`).scrollIntoView()
}, 300)
}
return active
}
return { headers, isLinkActive }
},
render (h) {
return h('ul', {
class: { 'sub-sidebar-wrapper': true },
style: { width: (this.$page.headers || []).length > 0 ? '12rem' : '0' }
style: { width: this.headers.length > 0 ? '12rem' : '0' }
}, [
...(this.$page.headers || []).map(header => {
...this.headers.map(header => {
return h('li', {
class: {
active: this.isLinkActive(header),
@ -27,15 +36,14 @@ export default {
attr: { key: header.title }
}, [
h('router-link', {
class: { 'sidebar-link': true },
class: { 'sidebar-link': true, [`reco-side-${header.slug}`]: true },
props: { to: `${this.$page.path}#${header.slug}` }
}, header.title)
])
})
])
}
}
})
</script>
<style lang="stylus" scoped>

View File

@ -2,6 +2,7 @@
<div class="tags">
<span
v-for="(item, index) in tags"
v-show="!item.pages || (item.pages && item.pages.length > 0)"
:key="index"
:class="{'active': item.name == currentTag}"
:style="{ 'backgroundColor': getOneColor() }"
@ -10,32 +11,32 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import { getOneColor } from '@theme/helpers/other'
export default {
export default defineComponent({
props: {
currentTag: {
type: String,
default: ''
}
},
computed: {
tags () {
return [{ name: '全部', path: '/tag/' }, ...this.$tags.list]
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const tags = computed(() => {
return [{ name: instance.$recoLocales.all, path: '/tag/' }, ...instance.$tagesList]
})
const tagClick = tag => {
ctx.emit('getCurrentTag', tag)
}
},
methods: {
tagClick (tag) {
this.$emit('getCurrentTag', tag)
},
getOneColor
return { tags, tagClick, getOneColor }
}
}
})
</script>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.tags
margin 30px 0
span

View File

@ -1,17 +1,25 @@
/* eslint-disable no-proto */
import postMixin from '@theme/mixins/posts'
import localMixin from '@theme/mixins/locales'
import { addLinkToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss } from '@theme/helpers/other'
import { addLinkToHead, addScriptToHead } from '@theme/helpers/utils'
import { registerCodeThemeCss, interceptRouterError, fixRouterError404 } from '@theme/helpers/other'
import { install } from 'vue-demi'
export default ({
Vue,
siteData,
isServer
isServer,
router
}) => {
install(Vue)
Vue.mixin(postMixin)
Vue.mixin(localMixin)
if (!isServer) {
addLinkToHead('//at.alicdn.com/t/font_1030519_2ciwdtb4x65.css')
addScriptToHead('//kit.fontawesome.com/51b01de608.js')
registerCodeThemeCss(siteData.themeConfig.codeTheme)
}
interceptRouterError(router)
fixRouterError404(router)
}

View File

@ -1,5 +1,7 @@
<script>
export default {
import { defineComponent } from 'vue-demi'
export default defineComponent({
functional: true,
props: {
type: {
@ -20,11 +22,10 @@ export default {
}
}, props.text || slots().default)
}
}
})
</script>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.badge
display inline-block
font-size 14px

View File

@ -1,3 +1,4 @@
/* eslint-disable no-proto */
import { addLinkToHead } from './utils'
export function getOneColor () {
const tagColorArr = [
@ -24,3 +25,27 @@ export function registerCodeThemeCss (theme = 'tomorrow') {
addLinkToHead(href)
}
export function interceptRouterError (router) {
// 获取原型对象上的 push 函数
const originalPush = router.__proto__.push
// 修改原型对象中的p ush 方法
router.__proto__.push = function push (location) {
return originalPush.call(this, location).catch(err => err)
}
}
export function fixRouterError404 (router) {
router.beforeEach((to, from, next) => {
// 解决非ASCII文件名的路由, 防止 404
const decodedPath = decodeURIComponent(to.path)
if (decodedPath !== to.path) {
next(Object.assign({}, to, {
fullPath: decodeURIComponent(to.fullPath),
path: decodedPath
}))
} else {
next()
}
})
}

View File

@ -8,7 +8,7 @@ export function filterPosts (posts, isTimeline) {
if (posts.indexOf(item) !== index) {
return false
} else {
const someConditions = home == true || title == undefined || publish === false
const someConditions = home === true || title == undefined || publish === false
const boo = isTimeline === true
? !(someConditions || date === undefined)
: !someConditions

View File

@ -122,21 +122,6 @@ export function resolveSidebarItems (page, regularPath, site, localePath) {
? 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(regularPath, sidebarConfig)
// return config
// ? config.map(item => resolveItem(item, pages, base))
// : []
// }
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
@ -145,27 +130,6 @@ export function resolveSidebarItems (page, regularPath, site, localePath) {
: []
}
/**
* @param { Page } page
* @returns { SidebarGroup }
*/
// function resolveHeaders (page) {
// const headers = groupHeaders(page.headers || [])
// return [{
// type: 'group',
// collapsable: false,
// title: page.title,
// path: null,
// 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))
@ -235,12 +199,16 @@ export function formatDate (time, fmt = 'yyyy-MM-dd hh:mm:ss') {
// 获取时间的数字类型
export function getTimeNum (date) {
return new Date(date.frontmatter.date).getTime()
const dateNum = !date ? 0 : new Date(date).getTime()
return dateNum
}
// 比对时间
export function compareDate (a, b) {
return getTimeNum(b) - getTimeNum(a)
const aDateNum = getTimeNum(a.frontmatter.date)
const bDateNum = getTimeNum(b.frontmatter.date)
if (aDateNum === 0 || bDateNum === 0) return 0
return bDateNum - aDateNum
}
// 向 head 中添加 style
@ -252,6 +220,14 @@ export function addLinkToHead (href) {
document.head.append(iconLink)
}
// 向 head 中添加 script
export function addScriptToHead (href) {
const iconLink = document.createElement('script')
iconLink.src = href
document.head.append(iconLink)
}
function ensureEndingSlash (path) {
return /(\.html|\/)$/.test(path)
? path

View File

@ -0,0 +1,39 @@
<svg
version="1.1"
baseProfile="full"
width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1400 800"
>
<rect x="1300" y="400" rx="40" ry="40" width="300" height="300" stroke="rgb(129, 201, 149)" fill="rgb(129, 201, 149)">
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 1450 550" to="360 1450 550" repeatCount="indefinite" />
</rect>
<path d="M 100 350 A 150 150 0 1 1 400 350 Q400 370 380 370 L 250 370 L 120 370 Q100 370 100 350" stroke="rgb(253, 214, 99)" fill="rgb(253, 214, 99)">
<animateMotion path="M 800 -200 L 800 -300 L 800 -200" dur="20s" begin="0s" repeatCount="indefinite" />
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 210 530 ; -30 210 530 ; 0 210 530" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite" />
</path>
<circle cx="200" cy="150" r="20" stroke="#1a73e8" fill="#1a73e8">
<animateMotion path="M 0 0 L 40 20 Z" dur="5s" repeatCount="indefinite" />
</circle>
<!-- 三角形 -->
<path d="M 165 580 L 270 580 Q275 578 270 570 L 223 483 Q220 480 217 483 L 165 570 Q160 578 165 580" stroke="rgb(238, 103, 92)" fill="rgb(238, 103, 92)">
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="0 210 530" to="360 210 530" repeatCount="indefinite" />
</path>
<circle cx="1200" cy="600" r="30" stroke="rgb(241, 243, 244)" fill="rgb(241, 243, 244)">
<animateMotion path="M 0 0 L -20 40 Z" dur="9s" repeatCount="indefinite" />
</circle>
<path d="M 100 350 A 40 40 0 1 1 180 350 L 180 430 A 40 40 0 1 1 100 430 Z" stroke="rgb(241, 243, 244)" fill="rgb(241, 243, 244)">
<animateMotion path="M 140 390 L 180 360 L 140 390" dur="20s" begin="0s" repeatCount="indefinite" />
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="30s" type="rotate" values="0 140 390; -60 140 390; 0 140 390" keyTimes="0 ; 0.5 ; 1" repeatCount="indefinite" />
</path>
<rect x="400" y="600" rx="40" ry="40" width="100" height="100" stroke="rgb(129, 201, 149)" fill="rgb(129, 201, 149)">
<animateTransform attributeType="XML" attributeName="transform" begin="0s" dur="35s" type="rotate" from="-30 550 750" to="330 550 750" repeatCount="indefinite" />
</rect>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -57,24 +57,21 @@ module.exports = (options, ctx) => ({
'vuepress-plugin-smooth-scroll',
['container', {
type: 'tip',
defaultTitle: {
'/': '',
'/zh/': '提示'
}
before: info => `<div class="custom-block tip"><p class="title">${info}</p>`,
after: '</div>',
defaultTitle: ''
}],
['container', {
type: 'warning',
defaultTitle: {
'/': '',
'/zh/': '注意'
}
before: info => `<div class="custom-block warning"><p class="title">${info}</p>`,
after: '</div>',
defaultTitle: ''
}],
['container', {
type: 'danger',
defaultTitle: {
'/': '',
'/zh/': '警告'
}
before: info => `<div class="custom-block danger"><p class="title">${info}</p>`,
after: '</div>',
defaultTitle: ''
}],
['container', {
type: 'right',
@ -83,7 +80,8 @@ module.exports = (options, ctx) => ({
['container', {
type: 'theorem',
before: info => `<div class="custom-block theorem"><p class="title">${info}</p>`,
after: '</div>'
after: '</div>',
defaultTitle: ''
}],
['container', {
type: 'details',

View File

@ -9,6 +9,7 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance, onMounted } from 'vue-demi'
const msgs = [
`There's nothing here.`,
`How did we get here?`,
@ -16,28 +17,32 @@ const msgs = [
`Looks like we've got some broken links.`
]
export default {
computed: {
noFoundPageByTencent () {
return this.$themeConfig.noFoundPageByTencent !== false
}
},
mounted () {
if (this.noFoundPageByTencent) {
const dom = document.createElement('script')
dom.setAttribute('homePageName', '回到首页')
dom.setAttribute('homePageUrl', '/')
dom.setAttribute('src', '//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js')
export default defineComponent({
setup (props, ctx) {
const instance = getCurrentInstance().proxy
document.body.append(dom)
}
},
methods: {
getMsg () {
const noFoundPageByTencent = computed(() => {
return instance.$themeConfig.noFoundPageByTencent !== false
})
const getMsg = () => {
return msgs[Math.floor(Math.random() * msgs.length)]
}
onMounted(() => {
if (noFoundPageByTencent.value) {
const dom = document.createElement('script')
dom.setAttribute('homePageName', '回到首页')
dom.setAttribute('homePageUrl', instance.$site.base)
dom.setAttribute('src', '//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js')
document.body.append(dom)
}
})
return { noFoundPageByTencent, getMsg }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>

View File

@ -6,7 +6,8 @@
<li
class="category-item"
:class="title == item.name ? 'active': ''"
v-for="(item, index) in this.$categories.list"
v-for="(item, index) in $categoriesList"
v-show="item.pages.length > 0"
:key="index">
<router-link :to="item.path">
<span class="category-name">{{ item.name }}</span>
@ -22,90 +23,57 @@
v-show="recoShowModule"
class="list"
:data="posts"
:currentPage="currentPage"
@currentTag="getCurrentTag"></note-abstract>
</ModuleTransition>
<!-- 分页 -->
<ModuleTransition delay="0.16">
<pagation
class="pagation"
:total="posts.length"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"></pagation>
@paginationChange="paginationChange"
></note-abstract>
</ModuleTransition>
</Common>
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import Common from '@theme/components/Common'
import NoteAbstract from '@theme/components/NoteAbstract'
import ModuleTransition from '@theme/components/ModuleTransition'
import pagination from '@theme/mixins/pagination'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
import { sortPostsByStickyAndDate, filterPosts } from '@theme/helpers/postData'
import { getOneColor } from '@theme/helpers/other'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [pagination, moduleTransitonMixin],
export default defineComponent({
mixins: [moduleTransitonMixin],
components: { Common, NoteAbstract, ModuleTransition },
data () {
return {
currentPage: 1
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
computed: {
//
posts () {
let posts = this.$currentCategories.pages
const posts = computed(() => {
let posts = instance.$currentCategories.pages
posts = filterPosts(posts)
sortPostsByStickyAndDate(posts)
return posts
},
//
title () {
return this.$currentCategories.key
})
const title = computed(() => {
return instance.$currentCategories.key
})
const getCurrentTag = (tag) => {
ctx.emit('currentTag', tag)
}
},
mounted () {
this._setPage(this._getStoragePage())
},
methods: {
// tag
getCurrentTag (tag) {
this.$emit('currentTag', tag)
},
//
getCurrentPage (page) {
this._setPage(page)
const paginationChange = (page) => {
setTimeout(() => {
window.scrollTo(0, 0)
}, 100)
},
_setPage (page) {
this.currentPage = page
this.$page.currentPage = page
this._setStoragePage(page)
},
getOneColor
},
watch: {
$route () {
this._setPage(this._getStoragePage())
}
return { posts, title, getCurrentTag, paginationChange, getOneColor }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.categories-wrapper
max-width: $contentWidth;
margin: 0 auto;

View File

@ -1,5 +1,5 @@
<template>
<Common :sidebarItems="sidebarItems">
<Common :sidebarItems="sidebarItems" :showModule="recoShowModule">
<component v-if="$frontmatter.home" :is="homeCom"/>
<Page v-else :sidebar-items="sidebarItems"/>
<Footer v-if="$frontmatter.home" class="footer" />
@ -7,33 +7,45 @@
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import Home from '@theme/components/Home'
import HomeBlog from '@theme/components/HomeBlog'
import Page from '@theme/components/Page'
import Footer from '@theme/components/Footer'
import Common from '@theme/components/Common'
import { resolveSidebarItems } from '@theme/helpers/utils'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
export default defineComponent({
mixins: [moduleTransitonMixin],
components: { HomeBlog, Home, Page, Common, Footer },
computed: {
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
homeCom () {
const { type } = this.$themeConfig
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const sidebarItems = computed(() => {
if (instance.$page) {
return resolveSidebarItems(
instance.$page,
instance.$page.regularPath,
instance.$site,
instance.$localePath
)
} else {
return []
}
})
const homeCom = computed(() => {
const { type } = instance.$themeConfig || {}
if (type !== undefined) {
return type == 'blog' ? 'HomeBlog' : type
}
return 'Home'
}
})
return { sidebarItems, homeCom }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>

View File

@ -16,91 +16,61 @@
v-show="recoShowModule"
class="list"
:data="posts"
:currentPage="currentPage"
@currentTag="$currentTags.key"></note-abstract>
</ModuleTransition>
<!-- 分页 -->
<ModuleTransition delay="0.16">
<pagation
class="pagation"
:total="posts.length"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"></pagation>
:currentTag="$currentTags.key"
@paginationChange="paginationChange"></note-abstract>
</ModuleTransition>
</Common>
</template>
<script>
import { defineComponent, computed, getCurrentInstance } from 'vue-demi'
import Common from '@theme/components/Common'
import NoteAbstract from '@theme/components/NoteAbstract'
import TagList from '@theme/components/TagList'
import pagination from '@theme/mixins/pagination'
import ModuleTransition from '@theme/components/ModuleTransition'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
import { sortPostsByStickyAndDate, filterPosts } from '@theme/helpers/postData'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [pagination, moduleTransitonMixin],
export default defineComponent({
mixins: [moduleTransitonMixin],
components: { Common, NoteAbstract, TagList, ModuleTransition },
data () {
return {
currentPage: 1,
currentTag: '全部'
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
computed: {
//
posts () {
let posts = this.$currentTags.pages
const posts = computed(() => {
let posts = instance.$currentTags.pages
posts = filterPosts(posts)
sortPostsByStickyAndDate(posts)
return posts
})
const getCurrentTag = (tag) => {
ctx.emit('currentTag', tag)
}
},
mounted () {
this._setPage(this._getStoragePage())
},
methods: {
// tag
getCurrentTag (tag) {
this.$emit('currentTag', tag)
},
tagClick (tagInfo) {
if (this.$route.path !== tagInfo.path) {
this.$router.push({ path: tagInfo.path })
const tagClick = (tagInfo) => {
if (instance.$route.path !== tagInfo.path) {
instance.$router.push({ path: tagInfo.path })
}
},
//
getCurrentPage (page) {
this._setPage(page)
}
const paginationChange = (page) => {
setTimeout(() => {
window.scrollTo(0, 0)
}, 100)
},
_setPage (page) {
this.currentPage = page
this.$page.currentPage = page
this._setStoragePage(page)
}
},
watch: {
$route () {
this._setPage(this._getStoragePage())
}
return { posts, getCurrentTag, tagClick, paginationChange }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>
<style lang="stylus" scoped>
@require '../styles/mode.styl'
.tag-wrapper
max-width: $contentWidth;
margin: 0 auto;

View File

@ -4,7 +4,7 @@
<ModuleTransition>
<TagList
v-show="recoShowModule"
:currentTag="currentTag"
:currentTag="$recoLocales.all"
@getCurrentTag="tagClick"></TagList>
</ModuleTransition>
@ -14,77 +14,42 @@
v-show="recoShowModule"
class="list"
:data="$recoPosts"
:currentPage="currentPage"
:currentTag="currentTag"
@currentTag="getCurrentTag"></note-abstract>
</ModuleTransition>
<!-- 分页 -->
<ModuleTransition delay="0.16">
<pagation
class="pagation"
:total="$recoPosts.length"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"></pagation>
@paginationChange="paginationChange"
></note-abstract>
</ModuleTransition>
</Common>
</template>
<script>
import { defineComponent, getCurrentInstance } from 'vue-demi'
import Common from '@theme/components/Common'
import TagList from '@theme/components/TagList'
import NoteAbstract from '@theme/components/NoteAbstract'
import pagination from '@theme/mixins/pagination'
import ModuleTransition from '@theme/components/ModuleTransition'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [pagination, moduleTransitonMixin],
export default defineComponent({
mixins: [moduleTransitonMixin],
components: { Common, NoteAbstract, TagList, ModuleTransition },
data () {
return {
tags: [],
currentTag: '全部',
currentPage: 1,
allTagName: '全部'
}
},
created () {
if (this.$tags.list.length > 0) {
this.currentTag = this.$route.query.tag ? this.$route.query.tag : this.currentTag
}
},
setup (props, ctx) {
const instance = getCurrentInstance().proxy
mounted () {
this._setPage(this._getStoragePage())
},
methods: {
tagClick (tagInfo) {
if (this.$route.path !== tagInfo.path) {
this.$router.push({ path: tagInfo.path })
const tagClick = (tagInfo) => {
if (instance.$route.path !== tagInfo.path) {
instance.$router.push({ path: tagInfo.path })
}
},
}
getCurrentTag (tag) {
this.$emit('currentTag', tag)
},
getCurrentPage (page) {
this._setPage(page)
const paginationChange = (page) => {
setTimeout(() => {
window.scrollTo(0, 0)
}, 100)
},
_setPage (page) {
this.currentPage = page
this.$page.currentPage = page
this._setStoragePage(page)
}
return { tagClick, paginationChange }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>

View File

@ -2,7 +2,7 @@
<Common class="timeline-wrapper" :sidebar="false">
<ul class="timeline-content">
<ModuleTransition >
<li v-show="recoShowModule" class="desc">Yesterday Once More!</li>
<li v-show="recoShowModule" class="desc">{{$recoLocales.timeLineMsg}}</li>
</ModuleTransition>
<ModuleTransition
:delay="String(0.08 * (index + 1))"
@ -12,7 +12,7 @@
<h3 class="year">{{item.year}}</h3>
<ul class="year-wrapper">
<li v-for="(subItem, subIndex) in item.data" :key="subIndex">
<span class="date">{{subItem.frontmatter.date | dateFormat}}</span>
<span class="date">{{dateFormat(subItem.frontmatter.date)}}</span>
<span class="title" @click="go(subItem.path)">{{subItem.title}}</span>
</li>
</ul>
@ -23,16 +23,23 @@
</template>
<script>
import { defineComponent, getCurrentInstance } from 'vue-demi'
import Common from '@theme/components/Common'
import ModuleTransition from '@theme/components/ModuleTransition'
import { ModuleTransition } from '@vuepress-reco/core/lib/components'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
export default {
mixins: [moduleTransitonMixin],
export default defineComponent({
name: 'TimeLine',
mixins: [moduleTransitonMixin],
components: { Common, ModuleTransition },
filters: {
dateFormat (date, type) {
setup (props, ctx) {
const instance = getCurrentInstance().proxy
const go = (url) => {
instance.$router.push({ path: url })
}
const dateFormat = (date, type) => {
function renderTime (date) {
const dateee = new Date(date).toJSON()
return new Date(+new Date(dateee) + 8 * 3600 * 1000).toISOString().replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '').replace(/-/g, '/')
@ -43,13 +50,10 @@ export default {
const day = dateObj.getDate()
return `${mon}-${day}`
}
},
methods: {
go (url) {
this.$router.push({ path: url })
}
return { go, dateFormat }
}
}
})
</script>
<style src="../styles/theme.styl" lang="stylus"></style>
@ -128,7 +132,7 @@ export default {
&::before {
content: " ";
position: absolute;
left: -19px;
left: -18px;
top: 41px;
width: 6px;
height: 6px;

View File

@ -1,8 +1,9 @@
export default {
homeBlog: {
article: 'Article',
tag: 'Tag',
category: 'Category',
friendLink: 'Friend Link'
}
all: 'All',
article: 'Articles',
tag: 'Tags',
category: 'Categories',
friendLink: 'Friend Links',
timeLine: 'TimeLine',
timeLineMsg: 'Yesterday Once More!'
}

View File

@ -0,0 +1,9 @@
export default {
all: 'Todas',
article: 'Artículos',
tag: 'Etiquetas',
category: 'Categorías',
friendLink: 'Páginas amigas',
timeLine: 'Cronología',
timeLineMsg: '¡Ayer otra vez!'
}

View File

@ -3,5 +3,6 @@ import zhHant from './zh-hant.js'
import en from './en.js'
import ja from './ja.js'
import ko from './ko.js'
import es from './es.js'
export { zhHans, zhHant, en, ja, ko }
export { zhHans, zhHant, en, ja, ko, es }

View File

@ -1,8 +1,9 @@
export default {
homeBlog: {
article: '文章',
tag: 'ラベル',
category: '分類',
friendLink: '友情リンク'
}
all: '全部',
article: '文章',
tag: 'ラベル',
category: '分類',
friendLink: '友情リンク',
timeLine: 'タイムライン',
timeLineMsg: '昨日また!'
}

View File

@ -1,8 +1,9 @@
export default {
homeBlog: {
article: '글',
tag: '태그',
category: '분류',
friendLink: '링크 참조'
}
all: '전체',
article: '글',
tag: '태그',
category: '분류',
friendLink: '링크 참조',
timeLine: '타임 라인',
timeLineMsg: '어제 또!'
}

View File

@ -1,8 +1,9 @@
export default {
homeBlog: {
article: '文章',
tag: '标签',
category: '分类',
friendLink: '友情链接'
}
all: '全部',
article: '文章',
tag: '标签',
category: '分类',
friendLink: '友情链接',
timeLine: '时间轴',
timeLineMsg: '昨日重现!'
}

View File

@ -1,8 +1,9 @@
export default {
homeBlog: {
article: '文章',
tag: '標簽',
category: '分類',
friendLink: '友情鏈接'
}
all: '全部',
article: '文章',
tag: '標簽',
category: '分類',
friendLink: '友情鏈接',
timeLine: '時間軸',
timeLineMsg: '昨日重現!'
}

View File

@ -1,26 +0,0 @@
export default {
methods: {
_tagColor () {
const tagColorArr = ['#e15b64', '#f47e60', '#f8b26a', '#abbd81', '#849b87', '#e15b64', '#f47e60', '#f8b26a', '#f26d6d', '#67cc86', '#fb9b5f', '#3498db']
const index = Math.floor(Math.random() * tagColorArr.length)
return tagColorArr[index]
},
// 获取当前页码
_getStoragePage () {
const path = window.location.pathname
const currentPage = JSON.parse(sessionStorage.getItem('currentPage'))
if (currentPage === null || path !== currentPage.path) {
sessionStorage.setItem('currentPage', { page: 1, path: '' })
return 1
}
return parseInt(currentPage.page)
},
// 设置当前页码
_setStoragePage (page) {
const path = window.location.pathname
sessionStorage.setItem('currentPage', JSON.stringify({ page, path }))
}
}
}

View File

@ -1,25 +1,26 @@
import { zhHans, zhHant, en, ja, ko } from '../locales/index'
import { zhHans, zhHant, en, ja, ko, es } from '../locales/index'
export default {
computed: {
$recoLocales () {
const recoLocales = this.$themeLocaleConfig.recoLocales
if (recoLocales && recoLocales.homeBlog) {
return { homeBlog: recoLocales.homeBlog }
}
const recoLocales = this.$themeLocaleConfig.recoLocales || {}
if (/^zh\-(CN|SG)$/.test(this.$lang)) {
return zhHans
return { ...zhHans, ...recoLocales }
}
if (/^zh\-(HK|MO|TW)$/.test(this.$lang)) {
return zhHant
return { ...zhHant, ...recoLocales }
}
if (/^ja\-JP$/.test(this.$lang)) {
return ja
return { ...ja, ...recoLocales }
}
if (/^ko\-KR$/.test(this.$lang)) {
return ko
return { ...ko, ...recoLocales }
}
return en
if (/^es(\-[A-Z]+)?$/.test(this.$lang)) {
return { ...es, ...recoLocales }
}
return { ...en, ...recoLocales }
}
}
}

View File

@ -7,7 +7,15 @@ export default {
mounted () {
this.recoShowModule = true
},
destroyed () {
this.recoShowModule = false
watch: {
'$route' (newV, oldV) {
if (newV.path === oldV.path) return
this.recoShowModule = false
setTimeout(() => {
this.recoShowModule = true
}, 200)
}
}
}

View File

@ -6,7 +6,7 @@ export default {
const currentPage = JSON.parse(sessionStorage.getItem('currentPage'))
if (currentPage === null || path !== currentPage.path) {
sessionStorage.setItem('currentPage', { page: 1, path: '' })
sessionStorage.setItem('currentPage', JSON.stringify({ page: 1, path: '' }))
return 1
}

View File

@ -3,13 +3,7 @@ import { filterPosts, sortPostsByStickyAndDate, sortPostsByDate } from '../helpe
export default {
computed: {
$recoPosts () {
const {
$categories: { list: articles }
} = this
let posts = articles.reduce((allData, currentData) => {
return [...allData, ...currentData.pages]
}, [])
let posts = this.$site.pages
posts = filterPosts(posts, false)
sortPostsByStickyAndDate(posts)
@ -41,6 +35,40 @@ export default {
}
return formatPagesArr
},
$categoriesList () {
return this.$categories.list.map(category => {
category.pages = category.pages.filter(page => {
return page.frontmatter.publish !== false
})
return category
})
},
$tagesList () {
return this.$tags.list.map(tag => {
tag.pages = tag.pages.filter(page => {
return page.frontmatter.publish !== false
})
return tag
})
},
$showSubSideBar () {
const {
$themeConfig: { subSidebar: themeSubSidebar, sidebar: themeSidebar },
$frontmatter: { subSidebar: pageSubSidebar, sidebar: pageSidebar }
} = this
const headers = this.$page.headers || []
if ([pageSubSidebar, pageSidebar].indexOf(false) > -1) {
return false
} else if ([pageSubSidebar, pageSidebar].indexOf('auto') > -1 && headers.length > 0) {
return true
} else if ([themeSubSidebar, themeSidebar].indexOf('auto') > -1 && headers.length > 0) {
return true
} else {
return false
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More