chore(merge): resolve merge conflict

This commit is contained in:
giraud florent
2019-09-07 01:02:11 -04:00
246 changed files with 8571 additions and 4662 deletions
+159
View File
@@ -0,0 +1,159 @@
{
"projectName": "VuePress",
"projectOwner": "Ulivz",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"commitConvention": "none",
"contributors": [
{
"login": "yyx990803",
"name": "Evan You",
"avatar_url": "https://avatars1.githubusercontent.com/u/499550?v=4",
"profile": "http://evanyou.me",
"contributions": [
"code"
]
},
{
"login": "ulivz",
"name": "ULIVZ",
"avatar_url": "https://avatars1.githubusercontent.com/u/23133919?v=4",
"profile": "http://ulivz.com",
"contributions": [
"code",
"doc"
]
},
{
"login": "jlooper",
"name": "Jen Looper",
"avatar_url": "https://avatars2.githubusercontent.com/u/1450004?v=4",
"profile": "http://www.jenlooper.com",
"contributions": [
"doc",
"design"
]
},
{
"login": "sarahdayan",
"name": "Sarah Dayan",
"avatar_url": "https://avatars0.githubusercontent.com/u/5370675?v=4",
"profile": "https://frontstuff.io/",
"contributions": [
"code",
"doc"
]
},
{
"login": "kefranabg",
"name": "Franck Abgrall",
"avatar_url": "https://avatars3.githubusercontent.com/u/9840435?v=4",
"profile": "https://www.franck-abgrall.me/",
"contributions": [
"code",
"question"
]
},
{
"login": "sobolevn",
"name": "Nikita Sobolev",
"avatar_url": "https://avatars1.githubusercontent.com/u/4660275?v=4",
"profile": "https://sobolevn.me",
"contributions": [
"code",
"doc"
]
},
{
"login": "f3ltron",
"name": "Giraud Florent",
"avatar_url": "https://avatars1.githubusercontent.com/u/11556276?v=4",
"profile": "https://github.com/f3ltron",
"contributions": [
"code"
]
},
{
"login": "CodesOfRa",
"name": "Ramona",
"avatar_url": "https://avatars0.githubusercontent.com/u/945186?v=4",
"profile": "https://twitter.com/CodesOfRa",
"contributions": [
"code"
]
},
{
"login": "fatihacet",
"name": "Fatih Acet",
"avatar_url": "https://avatars3.githubusercontent.com/u/712419?v=4",
"profile": "https://fatihacet.com",
"contributions": [
"code"
]
},
{
"login": "filrak",
"name": "Filip Rakowski",
"avatar_url": "https://avatars2.githubusercontent.com/u/15185752?v=4",
"profile": "https://rakowski.dev",
"contributions": [
"code"
]
},
{
"login": "farcaller",
"name": "Vladimir Pouzanov",
"avatar_url": "https://avatars2.githubusercontent.com/u/693?v=4",
"profile": "http://farcaller.net/",
"contributions": [
"code"
]
},
{
"login": "vicbergquist",
"name": "Victoria Bergquist",
"avatar_url": "https://avatars0.githubusercontent.com/u/25737281?v=4",
"profile": "https://twitter.com/vicbergquist",
"contributions": [
"code",
"design"
]
},
{
"login": "newsbielt703",
"name": "Billyyyyy3320",
"avatar_url": "https://avatars0.githubusercontent.com/u/38957202?v=4",
"profile": "https://billychin.netlify.com/",
"contributions": [
"code"
]
},
{
"login": "bencodezen",
"name": "Ben Hong",
"avatar_url": "https://avatars0.githubusercontent.com/u/4836334?v=4",
"profile": "http://www.bencodezen.io",
"contributions": [
"code",
"blog"
]
},
{
"login": "vinayakkulkarni",
"name": "Vinayak Kulkarni",
"avatar_url": "https://avatars2.githubusercontent.com/u/19776877?v=4",
"profile": "https://twitter.com/_vinayak_k",
"contributions": [
"plugin",
"code",
"blog"
]
},
],
"contributorsPerLine": 7
}
+1 -1
View File
@@ -34,4 +34,4 @@ jobs:
key: v1-dependencies-{{ checksum "package.json" }}
# run tests!
- run: yarn lint && yarn test
- run: yarn build && yarn lint && yarn test
+82
View File
@@ -0,0 +1,82 @@
## Development Setup
This project uses a monorepo setup that requires using [Yarn](https://yarnpkg.com) because it relies on [Yarn workspaces](https://yarnpkg.com/blog/2017/08/02/introducing-workspaces/).
``` sh
# Install dependencies & compile TypeScript utilities.
yarn bootstrap
# Clean dependencies.
yarn clean
# Useful when creating new submodules.
yarn boot
# Serve the docs.
yarn dev
# Build the docs.
yarn build
# Execute all the test suites.
yarn test
```
## Core packages
- **docs**: Docs of VuePress (do not publish to npm).
- **vuepress**: VuePress CLI.
- **packages**
- `core`: containing the Node.js API, the Plugin API, the Theme API, the Client SPA, etc.
- `markdown`: internal Markdown compiler.
- `markdown-loader`: internal Markdown loader.
- `plugin-active-header-links`: a plugin for active sidebar heading links.
- `plugin-google-analytics`: Google Analytics integration.
- `plugin-last-updated`: implementation of "last updated" feature.
- `plugin-medium-zoom`: `medium-zoom` integration.
- `plugin-nprogress`: `nprogress` integration.
- `plugin-pwa`: PWA plugin.
- `plugin-search`: search plugin, providing the `SearchBox` component.
- `shared-utils`: TypeScript utilities.
- `test-utils`: test utilities.
- `theme-default`: default theme.
- `theme-vue`: a theme tweak from default theme, used for the official Vue project.
## Core packages not in main project
> Previously, for quick iteration, these projects were kept in ULIVZ's workspace. In the future, we may want to build an independent GitHub group.
- [awesome-vuepress](https://github.com/ulivz/awesome-vuepress)
- [@vuepress/plugin-blog](https://github.com/ulivz/vuepress-plugin-blog)
- [@vuepress/theme-blog](https://github.com/ulivz/vuepress-theme-blog)
## Workflow
### Issue
> TODO
### Pull requests
- Create a feature branch from the default branch (`master`) and merge back against that branch.
- It's OK to have multiple small commits as you work on the PR - GitHub automatically squashes them before merging.
- Make sure tests pass.
- If adding a new feature:
- Add accompanying test case(s).
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
- If fixing bug:
- If you are resolving an open issue, add `(fix #xxxx)` (`#xxxx` being the issue ID) in your PR title for a better release log, e.g. `chore(feat): implement SSR (fix #1234)`.
- Provide a detailed description of the bug in the PR. Live demo preferred.
- Add appropriate test coverage if applicable.
### Substantial Changes
> RFC flow, TODO
## Code Specification
> TODO
## Commit specification
Commit messages should follow the [commit message convention](./COMMIT_CONVENTION.md) so that changelogs can be automatically generated.
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: ulivz # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: ulivz # 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: # Replace with a single custom sponsorship URL
+2 -9
View File
@@ -20,13 +20,11 @@ about: Create a report to help us improve
## Bug report
#### Version
#### Steps to reproduce
<!-- If you are reporting a bug that can ONLY be reproduced on your repository, PLEASE provide this repo link. That takes guessing work out of the way and saves us time. -->
<!-- If your repo isn't public, you can use this boilerplate to create a proper reproduction repo quickly: https://github.com/ulivz/template-vuepress -->
<!-- If your repo isn't public, you can use `codesandbox` or `yarn create vuepress` to create a minimal reproduction -->
#### What is expected?
@@ -34,9 +32,4 @@ about: Create a report to help us improve
#### Other relevant information
- Your OS:
- Node.js version:
- Browser version:
- Is this a global or local install?
- Which package manager did you use for the install?
- Does this issue occur when all plugins are disabled?
- Output of `npx vuepress info` in my VuePress project:
+1 -1
View File
@@ -19,4 +19,4 @@ about: Suggest an idea for this project
#### How should this be implemented in your opinion?
#### Are you willing to work on this yourself?**
#### Are you willing to work on this yourself?
+2
View File
@@ -0,0 +1,2 @@
titleAndCommits: true
allowMergeCommits: false
+6
View File
@@ -0,0 +1,6 @@
ports:
- port: 8080
onOpen: open-preview
tasks:
- init: yarn bootstrap
command: yarn dev
+3
View File
@@ -0,0 +1,3 @@
{
"*.{js,vue}": ["eslint --fix", "git add"]
}
+265 -9
View File
@@ -1,3 +1,259 @@
# [](https://github.com/vuejs/vuepress/compare/v1.0.4...v) (2019-09-06)
## [1.0.4](https://github.com/vuejs/vuepress/compare/v1.0.3...v1.0.4) (2019-09-06)
### Bug Fixes
* **$core:** do not transpile core packages' dependencies ([b69b107](https://github.com/vuejs/vuepress/commit/b69b107))
* **avatar:** fix url ([45e31b4](https://github.com/vuejs/vuepress/commit/45e31b4))
* **contributors:** fix for good contributions ([a709a4f](https://github.com/vuejs/vuepress/commit/a709a4f))
* **contributors:** fix url parameters ([db71238](https://github.com/vuejs/vuepress/commit/db71238))
* add missing hash in [#1706](https://github.com/vuejs/vuepress/issues/1706) ([#1780](https://github.com/vuejs/vuepress/issues/1780)) ([25777e4](https://github.com/vuejs/vuepress/commit/25777e4))
* contributors commit link ([#1809](https://github.com/vuejs/vuepress/issues/1809)) ([bb61182](https://github.com/vuejs/vuepress/commit/bb61182))
### Features
* **$core:** use any custom protocol for outboundRE ([#1731](https://github.com/vuejs/vuepress/issues/1731)) ([120d885](https://github.com/vuejs/vuepress/commit/120d885))
* Disable next and prev links from global config ([#1761](https://github.com/vuejs/vuepress/issues/1761)) ([92a1c02](https://github.com/vuejs/vuepress/commit/92a1c02))
# [](https://github.com/vuejs/vuepress/compare/v1.0.3...v) (2019-07-29)
## [1.0.3](https://github.com/vuejs/vuepress/compare/v1.0.2...v1.0.3) (2019-07-29)
### Bug Fixes
* **$core:** `'[Vue warn]: Unknown custom element'` when using `<Content />` in a custom page without markdown ([#1699](https://github.com/vuejs/vuepress/issues/1699)) ([2a59800](https://github.com/vuejs/vuepress/commit/2a59800)), closes [#1173](https://github.com/vuejs/vuepress/issues/1173) [#1426](https://github.com/vuejs/vuepress/issues/1426)
* **$core:** prioritise vuepress dependencies over cwd node_modules (close: [#1708](https://github.com/vuejs/vuepress/issues/1708)) ([#1720](https://github.com/vuejs/vuepress/issues/1720)) ([52f421b](https://github.com/vuejs/vuepress/commit/52f421b))
* **$core:** transpile all scripts under core (close: [#1623](https://github.com/vuejs/vuepress/issues/1623)) ([#1685](https://github.com/vuejs/vuepress/issues/1685)) ([6460b0c](https://github.com/vuejs/vuepress/commit/6460b0c))
* **$plugin-medium-zoom:** disable zoom for links ([#1719](https://github.com/vuejs/vuepress/issues/1719)) ([e3393e3](https://github.com/vuejs/vuepress/commit/e3393e3))
* **$theme-default:** `sidebarDepth: 0` not working in YAML frontmatter (close: [#1701](https://github.com/vuejs/vuepress/issues/1701)) ([#1702](https://github.com/vuejs/vuepress/issues/1702)) ([0624828](https://github.com/vuejs/vuepress/commit/0624828))
### Features
* **$theme-default:** support custom URL scheme for external links ([#1677](https://github.com/vuejs/vuepress/issues/1677)) ([27f005b](https://github.com/vuejs/vuepress/commit/27f005b))
* **$theme-default:** use router for Algolia search to reach no refresh ([#1706](https://github.com/vuejs/vuepress/issues/1706)) ([644142b](https://github.com/vuejs/vuepress/commit/644142b))
## [1.0.2](https://github.com/vuejs/vuepress/compare/v1.0.1...v1.0.2) (2019-06-22)
### Bug Fixes
* **$core:** cannot resolve agreement file from parent theme ([1aaa6e3](https://github.com/vuejs/vuepress/commit/1aaa6e3))
* **$core:** url display in dev log ([#1670](https://github.com/vuejs/vuepress/issues/1670)) ([17ba325](https://github.com/vuejs/vuepress/commit/17ba325))
* **$plugin-medium-zoom:** doesn't work with default plugin options in default theme ([42f19e0](https://github.com/vuejs/vuepress/commit/42f19e0))
### Features
* **$plugin-medium-zoom:** custom options ([#1649](https://github.com/vuejs/vuepress/issues/1649)) ([54bb2f3](https://github.com/vuejs/vuepress/commit/54bb2f3))
## [1.0.1](https://github.com/vuejs/vuepress/compare/v1.0.0...v1.0.1) (2019-06-10)
### Bug Fixes
* **$theme-default:** using '.theme-default-content' to replace '.content' in 404 layout ([#1646](https://github.com/vuejs/vuepress/issues/1646)) ([f0d1344](https://github.com/vuejs/vuepress/commit/f0d1344))
### Features
* **$theme-default:** enhance the styles of `blockquote` ([9d20d5f](https://github.com/vuejs/vuepress/commit/9d20d5f))
# [1.0.0](https://github.com/vuejs/vuepress/compare/v1.0.0-rc.1...v1.0.0) (2019-06-08)
# [1.0.0-rc.1](https://github.com/vuejs/vuepress/compare/v1.0.0-beta.2...v1.0.0-rc.1) (2019-06-08)
It seems no any changes here.
<a name="1.0.0-beta.2"></a>
# [1.0.0-beta.2](https://github.com/vuejs/vuepress/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2019-06-05)
### Bug Fixes
* **$core:** failed to render `<Content />` with dynamic pageKey from current $page. ([83b02ba](https://github.com/vuejs/vuepress/commit/83b02ba))
<a name=""></a>
# [](https://github.com/vuejs/vuepress/compare/v1.0.0-beta.1...v) (2019-06-05)
<a name="1.0.0-beta.1"></a>
# [1.0.0-beta.1](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.50...v1.0.0-beta.1) (2019-06-04)
### Features
* **New Blog Plugin**: [@vuepress/plugin-blog](https://github.com/ulivz/vuepress-plugin-blog)
* A VuePress Blog Theme implemented in around 70 lines**: https://github.com/ulivz/70-lines-of-vuepress-blog-theme
* **Default Blog Theme**: [@vuepress/plugin-blog](https://github.com/ulivz/vuepress-theme-blog)
* Live Example: http://example.vuepress-theme-blog.ulivz.com
### BREAKING CHANGES
* Deprecated `@vuepress/plugin-blog` at alpha stage. ([10dfb66](https://github.com/vuejs/vuepress/commit/10dfb66))
* Deprecated `@vuepress/plugin-pagination` at alpha stage. ([3722192](https://github.com/vuejs/vuepress/commit/3722192))
<a name="1.0.0-alpha.50"></a>
# [1.0.0-alpha.50](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.49...v1.0.0-alpha.50) (2019-06-04)
### Bug Fixes
* **$core:** window is not defined ([d30e078](https://github.com/vuejs/vuepress/commit/d30e078))
<a name="1.0.0-alpha.49"></a>
# [1.0.0-alpha.49](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.48...v1.0.0-alpha.49) (2019-06-03)
### Bug Fixes
* **$core:** cannot load theme with shortcut. ([7eed1f4](https://github.com/vuejs/vuepress/commit/7eed1f4))
* **$core:** cannot retrieve the correct theme name when them path is a local absolute path linked to a javascript file. ([50f64b4](https://github.com/vuejs/vuepress/commit/50f64b4))
### Features
* **$core:** global variable "__VUEPRESS__" to store runtime key infos ([bd0bdf9](https://github.com/vuejs/vuepress/commit/bd0bdf9))
* **$core:** safer class name of content outlet ([7d0542e](https://github.com/vuejs/vuepress/commit/7d0542e))
* **$theme-default:** using '.theme-default-content' to replace '.content' in `<Content />` outlet. ([85ff630](https://github.com/vuejs/vuepress/commit/85ff630))
<a name="1.0.0-alpha.48"></a>
# [1.0.0-alpha.48](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.47...v1.0.0-alpha.48) (2019-05-14)
### Bug Fixes
* **$core:** Failed to load theme when using `layouts/Layout.vue` as entry file (close: [#1563](https://github.com/vuejs/vuepress/issues/1563)) ([#1564](https://github.com/vuejs/vuepress/issues/1564)) ([057d8bf](https://github.com/vuejs/vuepress/commit/057d8bf))
* **$core:** Search result cannot jump to the correct hash anchor (close: [#1594](https://github.com/vuejs/vuepress/issues/1594)) ([#1599](https://github.com/vuejs/vuepress/issues/1599)) ([e6af68f](https://github.com/vuejs/vuepress/commit/e6af68f))
* **$core:** Use directory name to compute slug if filename is readme or index (close: [#1443](https://github.com/vuejs/vuepress/issues/1443)) ([#1535](https://github.com/vuejs/vuepress/issues/1535)) ([9efc678](https://github.com/vuejs/vuepress/commit/9efc678))
* **$core:** webpack externals (ref: [#451](https://github.com/vuejs/vuepress/issues/451)) ([fb324d5](https://github.com/vuejs/vuepress/commit/fb324d5))
### Features
* **$core:** Infer page's date via directory name ([#1553](https://github.com/vuejs/vuepress/issues/1553)) ([2c930c9](https://github.com/vuejs/vuepress/commit/2c930c9))
* **$core:** `info` command ([#1573](https://github.com/vuejs/vuepress/issues/1573)) ([3eeb080](https://github.com/vuejs/vuepress/commit/3eeb080))
* **$core:** Prevent duplicate route ([#1525](https://github.com/vuejs/vuepress/issues/1525)) ([441f023](https://github.com/vuejs/vuepress/commit/441f023))
* **$theme-default:** Support external links in sidebar (close: [#764](https://github.com/vuejs/vuepress/issues/764))([#1534](https://github.com/vuejs/vuepress/issues/1534)) ([141bd11](https://github.com/vuejs/vuepress/commit/141bd11))
<a name="1.0.0-alpha.47"></a>
# [1.0.0-alpha.47](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.46...v1.0.0-alpha.47) (2019-04-06)
### Bug Fixes
* **$core:** `index.styl` is not injected at the end of the style bundle (close: [#1523](https://github.com/vuejs/vuepress/issues/1523)) ([dabf506](https://github.com/vuejs/vuepress/commit/dabf506))
* **$core:** `routerBase` will always get '/' (close: [#1503](https://github.com/vuejs/vuepress/issues/1503)) ([9fba549](https://github.com/vuejs/vuepress/commit/9fba549))
* **$markdown:** Snippets should allow spaces in file path (closes [#1505](https://github.com/vuejs/vuepress/issues/1505)) ([#1517](https://github.com/vuejs/vuepress/issues/1517)) ([5c307c9](https://github.com/vuejs/vuepress/commit/5c307c9))
### Features
* **$core:** assert return type for functional plugin ([#1516](https://github.com/vuejs/vuepress/issues/1516)) ([74887c5](https://github.com/vuejs/vuepress/commit/74887c5))
* **$core:** emit warning if the source directory doesn't exist (close: [#1521](https://github.com/vuejs/vuepress/issues/1521)) ([6da9a5f](https://github.com/vuejs/vuepress/commit/6da9a5f))
* **$plugin-pwa:** allow using local workbox files (close: [#539](https://github.com/vuejs/vuepress/issues/539)) ([4640614](https://github.com/vuejs/vuepress/commit/4640614))
<a name="1.0.0-alpha.46"></a>
# [1.0.0-alpha.46](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.45...v1.0.0-alpha.46) (2019-04-01)
### Bug Fixes
* **$core:** regression of introducing dynamic `routerBase` (close: [#1498](https://github.com/vuejs/vuepress/issues/1498)) ([5e12b49](https://github.com/vuejs/vuepress/commit/5e12b49))
<a name="1.0.0-alpha.45"></a>
# [1.0.0-alpha.45](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.44...v1.0.0-alpha.45) (2019-03-31)
### Bug Fixes
* **$core:** do not register component in render function ([#1449](https://github.com/vuejs/vuepress/issues/1449)) ([ef82c47](https://github.com/vuejs/vuepress/commit/ef82c47))
* **$core:** do not use stylus in outbound link ([d34e038](https://github.com/vuejs/vuepress/commit/d34e038))
* **$core:** should default host be 0.0.0.0 ([699492a](https://github.com/vuejs/vuepress/commit/699492a))
* **$markdown:** treat styl as stylus language ([#1433](https://github.com/vuejs/vuepress/issues/1433)) ([f44e2db](https://github.com/vuejs/vuepress/commit/f44e2db))
* **$markdown-loader:** always use `/` instead of `\` in `relPath` ([#1484](https://github.com/vuejs/vuepress/issues/1484)) ([944ebe4](https://github.com/vuejs/vuepress/commit/944ebe4))
* **$plugin-active-header-links:** side navigation edge case bug ([#1477](https://github.com/vuejs/vuepress/issues/1477)) ([8a11d14](https://github.com/vuejs/vuepress/commit/8a11d14))
* **$plugin-blog:** inconsistent paths of tag and category pages with index page ([#1420](https://github.com/vuejs/vuepress/issues/1420)) ([5c0e62f](https://github.com/vuejs/vuepress/commit/5c0e62f))
* **$plugin-pwa:** fix a typo in `opacity` ([#1444](https://github.com/vuejs/vuepress/issues/1444)) ([c174f0d](https://github.com/vuejs/vuepress/commit/c174f0d))
* **$theme-default:** fix wrong editLink (close: [#1115](https://github.com/vuejs/vuepress/issues/1115), [#1125](https://github.com/vuejs/vuepress/issues/1125)) ([#1419](https://github.com/vuejs/vuepress/issues/1419)) ([3b14375](https://github.com/vuejs/vuepress/commit/3b14375))
* **$theme-default:** nav url change bug (close: [#865](https://github.com/vuejs/vuepress/issues/865)) ([#1475](https://github.com/vuejs/vuepress/issues/1475)) ([521dddd](https://github.com/vuejs/vuepress/commit/521dddd))
### Features
* **$core:** allow dynamic routeBase at runtime ([fc99d59](https://github.com/vuejs/vuepress/commit/fc99d59))
* **$core:** decode page path for better readability ([#1438](https://github.com/vuejs/vuepress/issues/1438)) ([93b2ca1](https://github.com/vuejs/vuepress/commit/93b2ca1))
* **$core:** export version ([#1486](https://github.com/vuejs/vuepress/issues/1486)) ([d7b8daf](https://github.com/vuejs/vuepress/commit/d7b8daf))
* **$core:** functional siteConfig.evergreen ([#1489](https://github.com/vuejs/vuepress/issues/1489)) ([19e0569](https://github.com/vuejs/vuepress/commit/19e0569))
* **$core:** support array as plugin options ([#1493](https://github.com/vuejs/vuepress/issues/1493)) ([9e07b1e](https://github.com/vuejs/vuepress/commit/9e07b1e))
* **$markdown:** markdown plugin (close: [#585](https://github.com/vuejs/vuepress/issues/585)) ([#1422](https://github.com/vuejs/vuepress/issues/1422)) ([9734a58](https://github.com/vuejs/vuepress/commit/9734a58))
* **$plugin-register-components:** custom name registration (close: [#656](https://github.com/vuejs/vuepress/issues/656)) ([#1418](https://github.com/vuejs/vuepress/issues/1418)) ([9c6a00b](https://github.com/vuejs/vuepress/commit/9c6a00b))
### Breaking Changes
* Deprecated [@vuepress/plugin-container](https://www.npmjs.com/package/@vuepress/plugin-container) and moved it to [vuepress-plugin-container](https://www.npmjs.com/package/vuepress-plugin-container).
* Deprecated [@vuepress/plugin-clean-urls](https://www.npmjs.com/package/@vuepress/plugin-clean-urls) and moved it to [vuepress-plugin-clean-urls](https://www.npmjs.com/package/vuepress-plugin-clean-urls).
<a name="1.0.0-alpha.44"></a>
# [1.0.0-alpha.44](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.43...v1.0.0-alpha.44) (2019-03-10)
### Features
* **$core:** optional `callback` when socket connection is ready under dev. ([547e4f9](https://github.com/vuejs/vuepress/commit/547e4f9))
* **$core:** return current app instance in node api ([1c2a6b2](https://github.com/vuejs/vuepress/commit/1c2a6b2))
<a name="1.0.0-alpha.43"></a>
# [1.0.0-alpha.43](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.42...v1.0.0-alpha.43) (2019-03-09)
### Bug Fixes
* **$core:** cannot render another page with pageKey (close: [#1173](https://github.com/vuejs/vuepress/issues/1173)) ([9d01514](https://github.com/vuejs/vuepress/commit/9d01514))
* **$core:** global components cannot be used as layouts (close: [#1321](https://github.com/vuejs/vuepress/issues/1321)) ([0306574](https://github.com/vuejs/vuepress/commit/0306574))
* **$core:** PascalCase layouts cannot be used with camelCase nor hyphen-delimited (close: [#1391](https://github.com/vuejs/vuepress/issues/1391)) ([3e91eba](https://github.com/vuejs/vuepress/commit/3e91eba))
* **$plugin-blog:** read `layoutComponents` from themeAPI ([#1396](https://github.com/vuejs/vuepress/issues/1396)) ([5bf4d24](https://github.com/vuejs/vuepress/commit/5bf4d24))
### Features
* **$core:** refine node api ([#1395](https://github.com/vuejs/vuepress/issues/1395)) ([e5d8ed4](https://github.com/vuejs/vuepress/commit/e5d8ed4))
* **$cli:** `--no-clear-screen` flag (close: [#1421](https://github.com/vuejs/vuepress/issues/1421)) ([e5f51de](https://github.com/vuejs/vuepress/commit/e5f51de))
<a name="1.0.0-alpha.42"></a>
# [1.0.0-alpha.42](https://github.com/vuejs/vuepress/compare/v1.0.0-alpha.41...v1.0.0-alpha.42) (2019-03-03)
@@ -145,7 +401,7 @@
### Features
* **$core:** Support extra watching files ([02cc268](https://github.com/vuejs/vuepress/commit/02cc268)),
* **$core:** Support extra watching files ([02cc268](https://github.com/vuejs/vuepress/commit/02cc268)),
<br>e.g.
```js
// .vuepress/config.js
@@ -167,7 +423,7 @@
* **$core:** Leverage `webpack-dev-server` and sunset `webpack-serve` ([#1195](https://github.com/vuejs/vuepress/issues/1195)) ([81e3ef6](https://github.com/vuejs/vuepress/commit/81e3ef6))
- Add new plugin option api [beforeDevServer](https://v1.vuepress.vuejs.org/plugin/option-api.html#beforedevserver) and [afterDevServer](https://v1.vuepress.vuejs.org/plugin/option-api.html#afterdevserver).
- Remove `enhanceDevServer`.
- Remove `enhanceDevServer`.
- Publish [vuepress-plugin-export](https://github.com/ulivz/vuepress-plugin-export).
* **$core:** Allow a theme package using a sub directory (close [#1204](https://github.com/vuejs/vuepress/issues/1204)) ([#1206](https://github.com/vuejs/vuepress/issues/1206)) ([febe3a7](https://github.com/vuejs/vuepress/commit/febe3a7))
* **$theme-default:** Support shortcut for `sh` and `yml`. (close: [#1221](https://github.com/vuejs/vuepress/issues/1221)) ([fc5dba8](https://github.com/vuejs/vuepress/commit/fc5dba8))
@@ -226,7 +482,7 @@
### Breaking Changes
* **$core:** remove `contentLoading` and refine scroll behavior ([#1117](https://github.com/vuejs/vuepress/issues/1117)) ([0a7d85b](https://github.com/vuejs/vuepress/commit/0a7d85b))
- It also fixes the exisitng issues about anchor links. (Refs: [#1113](https://github.com/vuejs/vuepress/issues/1113), [#1016](https://github.com/vuejs/vuepress/issues/1016), [#1011](https://github.com/vuejs/vuepress/issues/1011), [#895](https://github.com/vuejs/vuepress/issues/895))
- It also fixes the existing issues about anchor links. (Refs: [#1113](https://github.com/vuejs/vuepress/issues/1113), [#1016](https://github.com/vuejs/vuepress/issues/1016), [#1011](https://github.com/vuejs/vuepress/issues/1011), [#895](https://github.com/vuejs/vuepress/issues/895))
### Performance Improvements
@@ -943,8 +1199,8 @@
* $page is missing at 404 page ([#388](https://github.com/vuejs/vuepress/issues/388)) ([cefc8c3](https://github.com/vuejs/vuepress/commit/cefc8c3))
* avoid the searchbox exceeded out of screen in narrow screen ([#254](https://github.com/vuejs/vuepress/issues/254)) ([8f04081](https://github.com/vuejs/vuepress/commit/8f04081))
* code looks not good at small sreen (close: [#350](https://github.com/vuejs/vuepress/issues/350)) ([6514c8f](https://github.com/vuejs/vuepress/commit/6514c8f))
* code looks not good at small sreen (close: [#350](https://github.com/vuejs/vuepress/issues/350)) ([d0ef06f](https://github.com/vuejs/vuepress/commit/d0ef06f))
* code looks not good at small screen (close: [#350](https://github.com/vuejs/vuepress/issues/350)) ([6514c8f](https://github.com/vuejs/vuepress/commit/6514c8f))
* code looks not good at small screen (close: [#350](https://github.com/vuejs/vuepress/issues/350)) ([d0ef06f](https://github.com/vuejs/vuepress/commit/d0ef06f))
* dropdown overlap due to word wrapping (close: [#359](https://github.com/vuejs/vuepress/issues/359)) ([#360](https://github.com/vuejs/vuepress/issues/360)) ([c65a8b7](https://github.com/vuejs/vuepress/commit/c65a8b7))
* duplicate slash when docs dir is not set ([#361](https://github.com/vuejs/vuepress/issues/361)) ([0c59ed5](https://github.com/vuejs/vuepress/commit/0c59ed5))
* emoji doesn't work in toc (close: [#417](https://github.com/vuejs/vuepress/issues/417)) ([#418](https://github.com/vuejs/vuepress/issues/418)) ([1b9012e](https://github.com/vuejs/vuepress/commit/1b9012e))
@@ -1057,7 +1313,7 @@
* fix emoji not showing on sidebars ([#206](https://github.com/vuejs/vuepress/issues/206)) ([bc2c83a](https://github.com/vuejs/vuepress/commit/bc2c83a))
* fix Sidebar link active logic ([#215](https://github.com/vuejs/vuepress/issues/215)) ([9c93d8f](https://github.com/vuejs/vuepress/commit/9c93d8f))
* Fix the style of repo link. ([f55fa00](https://github.com/vuejs/vuepress/commit/f55fa00))
* fix title inferrence regression (close [#208](https://github.com/vuejs/vuepress/issues/208)) ([52c20cf](https://github.com/vuejs/vuepress/commit/52c20cf))
* fix title inference regression (close [#208](https://github.com/vuejs/vuepress/issues/208)) ([52c20cf](https://github.com/vuejs/vuepress/commit/52c20cf))
* renames index.js to enhanceApp.js ([#226](https://github.com/vuejs/vuepress/issues/226)) ([0170449](https://github.com/vuejs/vuepress/commit/0170449))
* siteTitle vs pageTitle ([cd9b788](https://github.com/vuejs/vuepress/commit/cd9b788))
@@ -1073,7 +1329,7 @@
* support excerpt extraction with `<!-- more -->` (close [#174](https://github.com/vuejs/vuepress/issues/174)) ([fa404dc](https://github.com/vuejs/vuepress/commit/fa404dc))
* support for TOML front matter ([#141](https://github.com/vuejs/vuepress/issues/141)) ([#164](https://github.com/vuejs/vuepress/issues/164)) ([70620ba](https://github.com/vuejs/vuepress/commit/70620ba))
* support toml config ([#138](https://github.com/vuejs/vuepress/issues/138)) ([d136e22](https://github.com/vuejs/vuepress/commit/d136e22))
* theme index enhancment support ([#154](https://github.com/vuejs/vuepress/issues/154)) ([d026801](https://github.com/vuejs/vuepress/commit/d026801))
* theme index enhancement support ([#154](https://github.com/vuejs/vuepress/issues/154)) ([d026801](https://github.com/vuejs/vuepress/commit/d026801))
@@ -1119,7 +1375,7 @@
* handle headers that start with numbers (fix [#121](https://github.com/vuejs/vuepress/issues/121)) ([ad83169](https://github.com/vuejs/vuepress/commit/ad83169))
* make search locale-scoped (close [#128](https://github.com/vuejs/vuepress/issues/128)) ([846eb59](https://github.com/vuejs/vuepress/commit/846eb59))
* **nav:** unepxected error when themeConfig.nav isn't given. (close: [#125](https://github.com/vuejs/vuepress/issues/125)) ([#127](https://github.com/vuejs/vuepress/issues/127)) ([f052472](https://github.com/vuejs/vuepress/commit/f052472))
* **nav:** unexpected error when themeConfig.nav isn't given. (close: [#125](https://github.com/vuejs/vuepress/issues/125)) ([#127](https://github.com/vuejs/vuepress/issues/127)) ([f052472](https://github.com/vuejs/vuepress/commit/f052472))
* service worker path ([51c6eb2](https://github.com/vuejs/vuepress/commit/51c6eb2))
* use correct host in tip after the server has started ([#130](https://github.com/vuejs/vuepress/issues/130)) ([fd447ae](https://github.com/vuejs/vuepress/commit/fd447ae))
* use header's slug as it is if possible ([#119](https://github.com/vuejs/vuepress/issues/119)) ([5f7e199](https://github.com/vuejs/vuepress/commit/5f7e199))
@@ -1200,7 +1456,7 @@
### Bug Fixes
* always transpile lib directory ([#73](https://github.com/vuejs/vuepress/issues/73)) ([56e0392](https://github.com/vuejs/vuepress/commit/56e0392))
* avoid html-webpack-plugin requiring incomaptible webpack internals ([4816bef](https://github.com/vuejs/vuepress/commit/4816bef))
* avoid html-webpack-plugin requiring incompatible webpack internals ([4816bef](https://github.com/vuejs/vuepress/commit/4816bef))
* prioritize own deps + avoid serving wrong index.html (fix [#69](https://github.com/vuejs/vuepress/issues/69)) ([781e37a](https://github.com/vuejs/vuepress/commit/781e37a))
* redirect */index.html to */ (close [#83](https://github.com/vuejs/vuepress/issues/83)) ([52e04c4](https://github.com/vuejs/vuepress/commit/52e04c4))
* remove override import when ejecting (close [#56](https://github.com/vuejs/vuepress/issues/56)) ([2d811ed](https://github.com/vuejs/vuepress/commit/2d811ed))
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at vuepresscore@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+85 -13
View File
@@ -5,43 +5,115 @@
</p>
<p align="center">
<a href="https://npmcharts.com/compare/vuepress?minimal=true"><img src="https://img.shields.io/npm/dm/vuepress.svg" alt="Downloads"></a>
<a href="https://npmcharts.com/compare/vuepress?minimal=true"><a href="https://opencollective.com/vuepress" alt="Financial Contributors on Open Collective"><img src="https://opencollective.com/vuepress/all/badge.svg?label=financial+contributors" /></a> <img src="https://img.shields.io/npm/dm/vuepress.svg" alt="Downloads"></a>
<a href="https://www.npmjs.com/package/vuepress"><img src="https://img.shields.io/npm/v/vuepress.svg" alt="Version"></a>
<a href="https://www.npmjs.com/package/vuepress"><img src="https://badgen.net/npm/v/vuepress/next" alt="npm next version"></a>
<a href="https://www.npmjs.com/package/vuepress"><img src="https://img.shields.io/npm/l/vuepress.svg" alt="License"></a>
<a href="https://github.com/vuejs/vuepress/blob/master/LICENSE"><img src="https://img.shields.io/npm/l/vuepress.svg" alt="License"></a>
<a href="https://discordapp.com/invite/HBherRA"><img src="https://img.shields.io/badge/Discord-join%20chat-738bd7.svg" alt="vuepress channel on Discord"></a>
</p>
> This is the branch for `VuePress 1.x` and docs are available at https://v1.vuepress.vuejs.org.
<h2 align="center">Supporting VuePress</h2>
## Status: alpha
Maintaining and developing new features to VuePress takes a considerable amount of time (if you know that Gastby's team is a company), and I am currently exploring the possibility of working on VuePress fulltime.
Certain combinations of plugins may not work properly, and things may change or break until we reach `beta` phase. Do not use in production yet unless you are adventurous.
- [Sponsor ULIVZ on Patreon](https://www.patreon.com/ulivz)
- [Sponsor Vue.js](https://vuejs.org/support-vuejs)
For 0.x, it's moved to [0.x branch](https://github.com/vuejs/vuepress/tree/0.x) and still maintained, the website is: https://vuepress.vuejs.org.
> "VuePress is much more than that." —— ULIVZ
## Install
```bash
yarn add vuepress -D # Install 0.x
yarn add vuepress@next -D # Install 1.x.
yarn add vuepress -D
```
## Showcase
Check out [Awesome Vuepress](https://github.com/ulivz/awesome-vuepress) to find awesome things related to VuePress 1.x .
- [Awesome Vuepress](https://github.com/ulivz/awesome-vuepress)
- [vuepress.gallery](https://vuepress.gallery) (by [@vicbergquist](https://twitter.com/vicbergquist))
## Development
## Documentation
> Please make sure your version of Node.js is greater than 8.
This is the branch for `VuePress 1.x` and docs are available at https://v1.vuepress.vuejs.org.
``` bash
## Contribution
Want to contribute? Check our [issues for beginners](https://github.com/vuejs/vuepress/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)!
```bash
yarn bootstrap # Install and link dependencies for this lerna repo
yarn dev # serves VuePress' own docs with itself
yarn test # make sure your code change pass the test
```
If you don't have a local checkout, you can also open [VuePress in Gitpod](https://gitpod.io/#https://github.com/vuejs/vuepress/blob/master/packages/docs/docs/README.md), a free online IDE for GitHub.
If you intend to make `"substantial"` changes to VuePress or its documentation, please checkout [VuePress RFCs](./rfcs/README.md).
If you have a VuePress-related project/component/tool, add it with a pull request to [this curated list](https://github.com/ulivz/awesome-vuepress)!
## Contributors
### Core Team
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://evanyou.me"><img src="https://avatars1.githubusercontent.com/u/499550?v=4" width="100px;" alt="Evan You"/><br /><sub><b>Evan You</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=yyx990803" title="Code">💻</a></td>
<td align="center"><a href="http://ulivz.com"><img src="https://avatars1.githubusercontent.com/u/23133919?v=4" width="100px;" alt="ULIVZ"/><br /><sub><b>ULIVZ</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=ulivz" title="Code">💻</a> <a href="https://github.com/vuejs/vuepress/commits?author=ulivz" title="Documentation">📖</a></td>
<td align="center"><a href="http://www.jenlooper.com"><img src="https://avatars2.githubusercontent.com/u/1450004?v=4" width="100px;" alt="Jen Looper"/><br /><sub><b>Jen Looper</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=jlooper" title="Documentation">📖</a> <a href="#design-jlooper" title="Design">🎨</a></td>
<td align="center"><a href="https://frontstuff.io/"><img src="https://avatars0.githubusercontent.com/u/5370675?v=4" width="100px;" alt="Sarah Dayan"/><br /><sub><b>Sarah Dayan</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=sarahdayan" title="Code">💻</a> <a href="https://github.com/vuejs/vuepress/commits?author=sarahdayan" title="Documentation">📖</a></td>
<td align="center"><a href="https://www.franck-abgrall.me/"><img src="https://avatars3.githubusercontent.com/u/9840435?v=4" width="100px;" alt="Franck Abgrall"/><br /><sub><b>Franck Abgrall</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=kefranabg" title="Code">💻</a> <a href="#question-kefranabg" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://sobolevn.me"><img src="https://avatars1.githubusercontent.com/u/4660275?v=4" width="100px;" alt="Nikita Sobolev"/><br /><sub><b>Nikita Sobolev</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=sobolevn" title="Code">💻</a> <a href="https://github.com/vuejs/vuepress/commits?author=sobolevn" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/f3ltron"><img src="https://avatars1.githubusercontent.com/u/11556276?v=4" width="100px;" alt="Giraud Florent"/><br /><sub><b>Giraud Florent</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=f3ltron" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://twitter.com/CodesOfRa"><img src="https://avatars0.githubusercontent.com/u/945186?v=4" width="100px;" alt="Ramona"/><br /><sub><b>Ramona</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=CodesOfRa" title="Code">💻</a></td>
<td align="center"><a href="https://fatihacet.com"><img src="https://avatars3.githubusercontent.com/u/712419?v=4" width="100px;" alt="Fatih Acet"/><br /><sub><b>Fatih Acet</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=fatihacet" title="Code">💻</a></td>
<td align="center"><a href="https://rakowski.dev"><img src="https://avatars2.githubusercontent.com/u/15185752?v=4" width="100px;" alt="Filip Rakowski"/><br /><sub><b>Filip Rakowski</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=filrak" title="Code">💻</a></td>
<td align="center"><a href="http://farcaller.net/"><img src="https://avatars2.githubusercontent.com/u/693?v=4" width="100px;" alt="Vladimir Pouzanov"/><br /><sub><b>Vladimir Pouzanov</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=farcaller" title="Code">💻</a></td>
<td align="center"><a href="https://twitter.com/vicbergquist"><img src="https://avatars0.githubusercontent.com/u/25737281?v=4" width="100px;" alt="Victoria Bergquist"/><br /><sub><b>Victoria Bergquist</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=vicbergquist" title="Code">💻</a> <a href="#design-vicbergquist" title="Design">🎨</a></td>
<td align="center"><a href="https://billychin.netlify.com/"><img src="https://avatars0.githubusercontent.com/u/38957202?v=4" width="100px;" alt="Billyyyyy3320"/><br /><sub><b>Billyyyyy3320</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=newsbielt703" title="Code">💻</a></td>
<td align="center"><a href="http://www.bencodezen.io"><img src="https://avatars0.githubusercontent.com/u/4836334?v=4" width="100px;" alt="Ben Hong"/><br /><sub><b>Ben Hong</b></sub></a><br /><a href="https://github.com/vuejs/vuepress/commits?author=bencodezen" title="Code">💻</a> <a href="#blog-bencodezen" title="Blogposts">📝</a></td>
</tr>
<tr>
<td align="center"><a href="http://www.github.com/vinayakkulkarni"><img src="https://avatars2.githubusercontent.com/u/19776877?v=4" width="100px;" alt="Vinayak Kulkarni"/><br /><sub><b>Vinayak Kulkarni</b></sub></a><br /><a href="https://github.com/Ulivz/VuePress/commits?author=vinayakkulkarni" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
### Code Contributors
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/vuejs/vuepress/graphs/contributors"><img src="https://opencollective.com/vuepress/contributors.svg?width=890&button=false" /></a>
### Financial Contributors
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/vuepress/contribute)]
#### Individuals
<a href="https://opencollective.com/vuepress"><img src="https://opencollective.com/vuepress/individuals.svg?width=890"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/vuepress/contribute)]
<a href="https://opencollective.com/vuepress/organization/0/website"><img src="https://opencollective.com/vuepress/organization/0/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/1/website"><img src="https://opencollective.com/vuepress/organization/1/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/2/website"><img src="https://opencollective.com/vuepress/organization/2/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/3/website"><img src="https://opencollective.com/vuepress/organization/3/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/4/website"><img src="https://opencollective.com/vuepress/organization/4/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/5/website"><img src="https://opencollective.com/vuepress/organization/5/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/6/website"><img src="https://opencollective.com/vuepress/organization/6/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/7/website"><img src="https://opencollective.com/vuepress/organization/7/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/8/website"><img src="https://opencollective.com/vuepress/organization/8/avatar.svg"></a>
<a href="https://opencollective.com/vuepress/organization/9/website"><img src="https://opencollective.com/vuepress/organization/9/avatar.svg"></a>
## License
[MIT](https://github.com/vuejs/vuepress/blob/master/LICENSE)
@@ -0,0 +1,2 @@
module.exports = {}
// This file is just for jest.
@@ -0,0 +1,4 @@
{
"name": "vuepress-theme-without-index",
"main": "Layout.vue"
}
+1359
View File
File diff suppressed because one or more lines are too long
+46
View File
@@ -0,0 +1,46 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.73587 7.90886L19.3984 5.43536C19.8439 5.36933 20.3115 5.63888 20.4443 6.03926L27.3378 26.8118C27.5068 27.3216 27.2442 27.8237 26.7485 27.9312L8.08892 31.9766C7.53676 32.0964 6.99003 31.7433 6.87004 31.1904L2.01592 8.81459C1.92304 8.38637 2.24605 7.98155 2.73587 7.90886Z" fill="url(#paint0_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.8401 7.68541L19.5027 5.21191C19.9481 5.14588 20.4158 5.41543 20.5486 5.81581L27.442 26.5884C27.6113 27.0982 27.3484 27.6003 26.8527 27.7077L8.19315 31.7532C7.64099 31.8729 7.09425 31.5199 6.97426 30.967L2.11991 8.59139C2.02702 8.16292 2.35003 7.75834 2.8401 7.68541Z" fill="url(#paint1_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.4202 5.19932L20.9615 2.77387C21.405 2.70882 21.8749 2.98059 22.0124 3.38196L29.0032 23.7904C29.1712 24.2809 28.9172 24.7624 28.434 24.8636L10.3229 28.6681C9.78926 28.7802 9.24967 28.4422 9.11958 27.9152L3.73179 6.09987C3.62633 5.67313 3.93531 5.27053 4.4202 5.19932Z" fill="url(#paint2_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.52418 4.97612L21.0655 2.55066C21.509 2.48562 21.9789 2.75738 22.1163 3.15875L29.1071 23.5672C29.2752 24.0577 29.0212 24.5392 28.538 24.6404L10.4269 28.4449C9.89324 28.557 9.35364 28.219 9.22355 27.692L3.83601 5.87667C3.73056 5.44968 4.03928 5.04708 4.52418 4.97612Z" fill="url(#paint3_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.19741 2.58045L22.5968 0.23236C23.0371 0.169284 23.5062 0.438834 23.6462 0.83552L30.7136 20.8674C30.8824 21.3459 30.6345 21.8138 30.158 21.9111L12.3295 25.5545C11.805 25.6617 11.2693 25.3318 11.1348 24.8193L5.52698 3.46548C5.41611 3.04489 5.71719 2.64919 6.19741 2.58045Z" fill="url(#paint4_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.30139 2.35699L22.7008 0.00915408C23.1411 -0.0539215 23.6102 0.215628 23.7502 0.612315L30.8176 20.6442C30.9864 21.1227 30.7385 21.5906 30.262 21.6879L12.4335 25.3313C11.909 25.4385 11.3733 25.1086 11.2388 24.5961L5.63096 3.24252C5.52033 2.82168 5.82117 2.42574 6.30139 2.35699Z" fill="url(#paint5_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.1566 15.5455L22.3814 14.2066C22.4842 14.1876 22.585 14.2482 22.6163 14.3478L23.829 18.2018C23.8659 18.3193 23.7925 18.443 23.6713 18.4667L16.3429 19.8935C16.2372 19.9139 16.1338 19.8501 16.1044 19.7466L14.9952 15.8044C14.9624 15.6876 15.0371 15.5676 15.1566 15.5455ZM14.5327 15.8884L15.6242 19.8627C15.709 20.1709 16.0167 20.3619 16.3304 20.301L23.7469 18.8592C24.1064 18.7892 24.3242 18.4213 24.2126 18.0727L22.9883 14.2453C22.8949 13.9535 22.6005 13.7759 22.2989 13.8296L15.0149 15.1246C14.6611 15.1877 14.4374 15.5415 14.5327 15.8884ZM15.9739 16.2122L16.7374 18.8927L17.5579 18.7059L17.1193 17.1625L18.2394 18.0397L18.7844 16.805L19.2311 18.3728L20.0272 18.2023L19.2555 15.6113L18.4106 15.7574L17.8989 16.8944L16.7941 16.0577L15.9739 16.2122ZM21.9185 16.5727L21.5095 15.1978L20.6594 15.3432L21.0906 16.7304L20.3268 16.8782L21.8963 17.9253L22.6921 16.4224L21.9185 16.5727Z" fill="#BCC0CF"/>
<path d="M23.8107 18.3664L23.7245 18.5462L23.6974 18.6029C23.6678 18.6473 23.621 18.6793 23.5668 18.6892L16.2392 20.1182C16.1333 20.1379 16.0298 20.0739 16.0002 19.9704L14.8915 16.0282C14.8791 15.9813 14.8816 15.9321 14.9013 15.8902C14.9038 15.8852 14.9062 15.8803 14.9087 15.8754L14.9161 15.8606L14.9999 15.6807C14.9851 15.7177 14.9826 15.7621 14.9949 15.8039L15.0245 15.9099L16.1037 19.7462C16.1333 19.8496 16.2367 19.9137 16.3427 19.894L23.6678 18.4674H23.6703C23.7344 18.4551 23.7836 18.4157 23.8107 18.3664ZM24.1187 18.6226C24.1458 18.5191 24.1434 18.4058 24.1089 18.2949L22.8843 14.4685C22.7907 14.1778 22.4975 14.0004 22.1944 14.0521L14.9112 15.3481C14.751 15.3752 14.6155 15.4639 14.5293 15.5871C14.5785 15.358 14.7633 15.1683 15.0146 15.1239L22.3004 13.8304C22.601 13.7762 22.8966 13.9536 22.9878 14.2443L24.2124 18.0732C24.2764 18.2678 24.2345 18.4723 24.1187 18.6226ZM22.6921 16.4224L22.5714 16.6491L21.815 16.7969L21.406 15.422L20.721 15.5403L20.6594 15.3432L21.5095 15.1978L21.9185 16.5727L22.6921 16.4224ZM20.928 16.7624L21.0906 16.7304L20.9871 16.9546L20.5633 17.0359L20.3268 16.8782L20.928 16.7624ZM17.8949 16.893L17.7939 17.1172L16.6901 16.2819L16.0273 16.4051L15.9731 16.2129L16.7936 16.0577L17.8949 16.893ZM20.0262 18.2013L19.866 18.2358L19.1515 15.8335L18.3089 15.9813L18.4099 15.7571L19.255 15.6118L20.0262 18.2013ZM17.2297 17.5533L17.1188 17.1615L17.0153 17.3858L17.4022 18.7409L17.5574 18.7064L17.2297 17.5533Z" fill="#A2A6B3"/>
<path d="M12.8933 5.37674L10.7645 5.67241L18.3335 12.7093L21.0537 4.07581L19.0431 4.43061L17.4465 9.51608L12.8933 5.37674Z" fill="url(#paint6_linear)"/>
<path d="M12.8932 5.37674L14.8447 5.08107L16.5595 6.61854L17.21 4.72627L19.0431 4.4306L17.4465 9.51607L12.8932 5.37674Z" fill="url(#paint7_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="14.6945" y1="31.9997" x2="14.6945" y2="5.42521" gradientUnits="userSpaceOnUse">
<stop stop-color="#1D2130"/>
<stop offset="1" stop-color="#3E445A"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="14.7986" y1="31.7764" x2="14.7986" y2="5.20194" gradientUnits="userSpaceOnUse">
<stop stop-color="#262B3F"/>
<stop offset="1" stop-color="#656E91"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="16.383" y1="28.6898" x2="16.383" y2="2.76414" gradientUnits="userSpaceOnUse">
<stop stop-color="#267550"/>
<stop offset="1" stop-color="#79B881"/>
</linearGradient>
<linearGradient id="paint3_linear" x1="16.4871" y1="28.4665" x2="16.4871" y2="2.54086" gradientUnits="userSpaceOnUse">
<stop stop-color="#279264"/>
<stop offset="1" stop-color="#A4F3AA"/>
</linearGradient>
<linearGradient id="paint4_linear" x1="18.1351" y1="25.575" x2="18.1351" y2="0.223269" gradientUnits="userSpaceOnUse">
<stop offset="0.59" stop-color="#CECFD0"/>
<stop offset="1" stop-color="#DFDFDF"/>
</linearGradient>
<linearGradient id="paint5_linear" x1="18.2392" y1="25.3517" x2="18.2392" y2="-1.20886e-05" gradientUnits="userSpaceOnUse">
<stop stop-color="#EAEEF0"/>
<stop offset="0.41" stop-color="white"/>
</linearGradient>
<linearGradient id="paint6_linear" x1="13.2661" y1="-3.77058" x2="23.9637" y2="31.2197" gradientUnits="userSpaceOnUse">
<stop offset="0.22" stop-color="#73CB8D"/>
<stop offset="0.4" stop-color="#2F9869"/>
</linearGradient>
<linearGradient id="paint7_linear" x1="11.8979" y1="-6.91736" x2="28.6463" y2="41.7235" gradientUnits="userSpaceOnUse">
<stop offset="0.25" stop-color="#586080"/>
<stop offset="0.35" stop-color="#2C3247"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

+1 -2
View File
@@ -1,6 +1,5 @@
{
"lerna": "2.5.1",
"npmClient": "yarn",
"useWorkspaces": true,
"version": "1.0.0-alpha.42"
"version": "1.0.4"
}
+27 -30
View File
@@ -3,53 +3,50 @@
"workspaces": [
"packages/@vuepress/*",
"packages/vuepress",
"packages/docs",
"packages/blog"
"packages/docs"
],
"description": "Minimalistic doc generator with Vue component based layout system",
"scripts": {
"bootstrap": "yarn && lerna bootstrap && yarn tsc",
"precommit": "lint-staged",
"bootstrap": "yarn && yarn tsc",
"clean": "lerna clean && rm -rf node_modules",
"packages:list": "lerna ls -l",
"packages:diff": "lerna diff",
"packages:changed": "lerna changed",
"boot": "node scripts/bootstrap.js",
"remote-version": "node scripts/remote-version.js",
"dev": "yarn tsc && yarn workspace docs dev",
"build": "yarn tsc && yarn workspace docs build",
"dev": "yarn tsc && yarn dev:docs",
"dev:docs": "yarn workspace docs dev",
"build": "yarn tsc && yarn build:docs",
"build:docs": "yarn workspace docs build",
"view-info": "yarn tsc && yarn workspace docs view-info",
"show-help": "yarn workspace docs show-help",
"dev:blog": "yarn tsc && yarn workspace blog dev",
"build:blog": "yarn tsc && yarn workspace blog build",
"register-vuepress": "lerna exec --scope vuepress -- yarn link",
"unregister-vuepress": "lerna exec --scope vuepress -- yarn unlink",
"lint": "eslint packages --fix --ext .js,.vue",
"release": "yarn --pure-lockfile && yarn tsc && node scripts/release.js",
"release": "yarn --pure-lockfile && yarn tsc && node scripts/release.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 2",
"test": "node scripts/test.js",
"tsc": "lerna run tsc"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,vue}": [
"eslint --fix",
"git add"
]
"tsc": "yarn workspace @vuepress/shared-utils tsc"
},
"devDependencies": {
"conventional-changelog-cli": "^1.3.22",
"@types/escape-html": "^0.0.20",
"@types/fs-extra": "^5.0.4",
"@types/globby": "^9.1.0",
"@types/hash-sum": "^1.0.0",
"@types/lru-cache": "^4.1.1",
"@types/node": "^10.12.12",
"@types/semver": "^6.0.0",
"conventional-changelog-cli": "^2.0.21",
"eslint": "^4.19.1",
"eslint-plugin-jest": "^21.15.1",
"eslint-plugin-vue-libs": "^3.0.0",
"lerna": "^3.6.0",
"lint-staged": "^7.0.4",
"minimist": "^1.2.0",
"yorkie": "^1.0.3",
"husky": "^3.0.2",
"inquirer": "^6.2.0",
"lerna": "3.13.4",
"lint-staged": "^8.1.5",
"minimist": "^1.2.0",
"typescript": "^3.2.2",
"@types/node": "^10.12.12",
"@types/lru-cache": "^4.1.1",
"@types/fs-extra": "^5.0.4",
"@types/semver": "^5.5.0",
"@types/hash-sum": "^1.0.0",
"@types/globby": "^8.0.0",
"@types/escape-html": "^0.0.20"
"all-contributors-cli": "^6.8.1"
}
}
+5 -4
View File
@@ -16,7 +16,6 @@ import Content from './components/Content.js'
import ContentSlotsDistributor from './components/ContentSlotsDistributor'
import OutboundLink from './components/OutboundLink.vue'
import ClientOnly from './components/ClientOnly'
import TOC from './components/TOC.vue'
// suggest dev server restart on base change
if (module.hot) {
@@ -47,8 +46,6 @@ Vue.component('ClientOnly', ClientOnly)
// core components
Vue.component('Layout', getLayoutAsyncComponent('Layout'))
Vue.component('NotFound', getLayoutAsyncComponent('NotFound'))
// markdown components
Vue.component('TOC', TOC)
// global helper for adding base path to absolute urls
Vue.prototype.$withBase = function (path) {
@@ -61,8 +58,12 @@ Vue.prototype.$withBase = function (path) {
}
export function createApp (isServer) {
const routerBase = typeof window !== 'undefined' && window.__VUEPRESS_ROUTER_BASE__
? window.__VUEPRESS_ROUTER_BASE__
: (siteData.routerBase || siteData.base)
const router = new Router({
base: siteData.base,
base: routerBase,
mode: 'history',
fallback: false,
routes,
@@ -4,7 +4,7 @@ import { createApp } from './app'
const { app, router } = createApp(false /* isServer */)
window.__VUEPRESS_VERSION__ = {
window.__VUEPRESS__ = {
version: VUEPRESS_VERSION,
hash: LAST_COMMIT_HASH
}
@@ -1,4 +1,5 @@
import { isPageExists } from '../util'
import Vue from 'vue'
import { setGlobalInfo, getPageAsyncComponent } from '@app/util'
export default {
props: {
@@ -10,7 +11,17 @@ export default {
},
render (h) {
const pageKey = this.pageKey || this.$parent.$page.key
if (isPageExists(pageKey)) {
setGlobalInfo('pageKey', pageKey)
/**
* This is for use cases that render `<Content />`
* with dynamic pageKey from current $page.
*/
if (!Vue.component(pageKey)) {
Vue.component(pageKey, getPageAsyncComponent(pageKey))
}
if (Vue.component(pageKey)) {
return h(pageKey)
}
return h('')
@@ -8,8 +8,7 @@ export default {
return h('div',
{
class: [
'content',
props.slotKey
`content__${props.slotKey}`
]
},
slots()[props.slotKey]
@@ -3,17 +3,30 @@
</template>
<script>
import Vue from 'vue'
import { setGlobalInfo } from '@app/util'
export default {
computed: {
layout () {
methods: {
getLayout () {
if (this.$page.path) {
if (this.$vuepress.isLayoutExists(this.$page.frontmatter.layout)) {
return this.$page.frontmatter.layout
const layout = this.$page.frontmatter.layout
if (layout && (this.$vuepress.getLayoutAsyncComponent(layout)
|| this.$vuepress.getVueComponent(layout))) {
return layout
}
return 'Layout'
}
return 'NotFound'
}
},
computed: {
layout () {
const layout = this.getLayout()
setGlobalInfo('layout', layout)
return Vue.component(layout)
}
}
}
</script>
@@ -1,20 +0,0 @@
<template>
<component :is="listType[0]">
<li v-for="(item, index) in items" :key="index">
<router-link :to="'#' + item.slug" v-text="item.title" />
<HeaderList v-if="item.children" :items="item.children" :list-type="innerListType" />
</li>
</component>
</template>
<script>
export default {
name: 'HeaderList',
props: ['items', 'listType'],
computed: {
innerListType () {
return this.listType.slice(Math.min(this.listType.length - 1, 1))
}
}
}
</script>
@@ -5,11 +5,12 @@
</svg>
</template>
<style lang="stylus">
.icon.outbound
color #aaa
display inline-block
vertical-align middle
position relative
top -1px
<style>
.icon.outbound {
color: #aaa;
display: inline-block;
vertical-align: middle;
position: relative;
top: -1px;
}
</style>
@@ -1,57 +0,0 @@
<template>
<div>
<slot name="header" />
<HeaderList :items="groupedHeaders" :list-type="listTypes" />
<slot name="footer" />
</div>
</template>
<script>
import HeaderList from './HeaderList.vue'
export default {
props: {
listType: {
type: [String, Array],
default: 'ul'
},
includeLevel: {
type: Array,
default: () => [2, 3]
}
},
components: { HeaderList },
computed: {
listTypes () {
return typeof this.listType === 'string' ? [this.listType] : this.listType
},
groupedHeaders () {
return this.groupHeaders(this.$page.headers).list
}
},
methods: {
groupHeaders (headers, startLevel = 1) {
const list = []
let index = 0
while (index < headers.length) {
const header = headers[index]
if (header.level < startLevel) break
if (header.level > startLevel) {
const result = this.groupHeaders(headers.slice(index), header.level)
if (list.length) {
list[list.length - 1].children = result.list
} else {
list.push(...result.list)
}
index += result.index
} else {
if (header.level <= this.includeLevel[1] && header.level >= this.includeLevel[0]) {
list.push({ ...header })
}
index += 1
}
}
return { list, index }
}
}
}
</script>
@@ -1,22 +1,18 @@
import Store from './Store'
import {
isPageExists,
isPageLoaded,
getPageAsyncComponent,
isLayoutExists,
isLayoutLoaded,
getLayoutAsyncComponent
getLayoutAsyncComponent,
getAsyncComponent,
getVueComponent
} from '../util'
class VuePress extends Store {}
Object.assign(VuePress.prototype, {
isPageExists,
isPageLoaded,
getPageAsyncComponent,
isLayoutExists,
isLayoutLoaded,
getLayoutAsyncComponent
getLayoutAsyncComponent,
getAsyncComponent,
getVueComponent
})
export default {
+83 -17
View File
@@ -2,36 +2,89 @@ import Vue from 'vue'
import layoutComponents from '@internal/layout-components'
import pageComponents from '@internal/page-components'
/**
* Create a cached version of a pure function.
*/
function cached (fn) {
const cache = Object.create(null)
// eslint-disable-next-line func-names
return function cachedFn (str) {
const hit = cache[str]
// eslint-disable-next-line no-return-assign
return hit || (cache[str] = fn(str))
}
}
/**
* Camelize a hyphen-delimited string.
*/
const camelizeRE = /-(\w)/g
const camelize = cached(str => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
/**
* Hyphenate a camelCase string.
*/
const hyphenateRE = /\B([A-Z])/g
const hyphenate = cached(str => {
return str.replace(hyphenateRE, '-$1').toLowerCase()
})
/**
* Capitalize a string.
*/
const capitalize = cached(str => {
return str.charAt(0).toUpperCase() + str.slice(1)
})
/**
* This method was for securely getting Vue component when components
* are named in different style.
*
* e.g. a component named `a-b` can be also getted by `AB`, It's the
* same the other way round
*
* @param {function} getter a function of getting component by name
* @param {string} name component's name
* @returns {Component|AsyncComponent}
*/
export function getComponent (getter, name) {
if (!name) return
if (getter(name)) return getter(name)
const isKebabCase = name.includes('-')
if (isKebabCase) return getter(capitalize(camelize(name)))
return getter(capitalize(name)) || getter(hyphenate(name))
}
const asyncComponents = Object.assign({}, layoutComponents, pageComponents)
export function isPageExists (pageKey) {
return Boolean(pageComponents[pageKey])
}
export function isPageLoaded (pageKey) {
return Boolean(Vue.component(pageKey))
}
const asyncComponentsGetter = name => asyncComponents[name]
const pageComponentsGetter = layout => pageComponents[layout]
const layoutComponentsGetter = layout => layoutComponents[layout]
const globalComponentsGetter = name => Vue.component(name)
export function getPageAsyncComponent (pageKey) {
return pageComponents[pageKey]
return getComponent(pageComponentsGetter, pageKey)
}
export function isLayoutExists (layout) {
return Boolean(layoutComponents[layout])
export function getLayoutAsyncComponent (layout) {
return getComponent(layoutComponentsGetter, layout)
}
export function isLayoutLoaded (layout) {
return Boolean(Vue.component(layout))
export function getAsyncComponent (name) {
return getComponent(asyncComponentsGetter, name)
}
export function getLayoutAsyncComponent (pageKey) {
return layoutComponents[pageKey]
export function getVueComponent (name) {
return getComponent(globalComponentsGetter, name)
}
export function ensureAsyncComponentsLoaded (...names) {
return Promise.all(names.filter(v => v).map(async (name) => {
if (!Vue.component(name) && asyncComponents[name]) {
const comp = await asyncComponents[name]()
if (!getVueComponent(name) && getAsyncComponent(name)) {
const comp = await getAsyncComponent(name)()
Vue.component(name, comp.default)
}
}))
@@ -129,3 +182,16 @@ export function normalizeConfig (component, rawConfig) {
}
return rawConfig
}
/**
* Set global info in `window.__VUEPRESS__` for debugging.
*
* @param {string}key
* @param {any} value
*/
export function setGlobalInfo (key, value) {
if (typeof window === 'undefined' || !window.__VUEPRESS__) {
return
}
window.__VUEPRESS__[key] = value
}
+4 -2
View File
@@ -1,6 +1,7 @@
'use strict'
const App = require('./node/App')
const { version } = require('../package')
const { logger } = require('@vuepress/shared-utils')
function createApp (options) {
@@ -11,16 +12,17 @@ function createApp (options) {
async function dev (options) {
const app = createApp(options)
await app.process()
await app.dev()
return app.dev()
}
async function build (options) {
const app = createApp(options)
await app.process()
await app.build()
return app.build()
}
exports.App = App
exports.version = version
exports.createApp = createApp
exports.dev = dev
exports.build = build
+38 -24
View File
@@ -26,13 +26,6 @@ const createTemp = require('./createTemp')
*/
module.exports = class App {
static getInstance (...args) {
if (!App._instance) {
App._instance = new App(...args)
}
return App._instance
}
/**
* Instantiate the app context with a new API
*
@@ -48,6 +41,9 @@ module.exports = class App {
this.options = options
this.sourceDir = this.options.sourceDir || path.join(__dirname, 'docs.fallback')
logger.debug('sourceDir', this.sourceDir)
if (!fs.existsSync(this.sourceDir)) {
logger.warn(`Source directory doesn't exist: ${chalk.yellow(this.sourceDir)}`)
}
const { tempPath, writeTemp } = createTemp(options.temp)
this.tempPath = tempPath
@@ -91,7 +87,8 @@ module.exports = class App {
}
/**
* Load pages, load plugins, apply plugins / plugin options, etc.
* A asynchronous method used to prepare the context of the current app. which
* contains loading pages and plugins, apply plugins, etc.
*
* @returns {Promise<void>}
* @api private
@@ -155,12 +152,12 @@ module.exports = class App {
.use(require('./internal-plugins/transformModule'))
.use(require('./internal-plugins/dataBlock'))
.use(require('./internal-plugins/frontmatterBlock'))
.use('@vuepress/container', {
.use('container', {
type: 'slot',
before: info => `<template slot="${info}">`,
after: '</template>'
})
.use('@vuepress/container', {
.use('container', {
type: 'v-pre',
before: '<div v-pre>',
after: '</div>'
@@ -351,7 +348,14 @@ module.exports = class App {
computed: new this.ClientComputedMixinConstructor(),
enhancers: this.pluginAPI.getOption('extendPageData').items
})
this.pages.push(page)
const index = this.pages.findIndex(({ path }) => path === page.path)
if (index >= 0) {
// Override a page if corresponding path already exists
logger.warn(`Override existing page ${chalk.yellow(page.path)}.`)
this.pages.splice(index, 1, page)
} else {
this.pages.push(page)
}
}
/**
@@ -381,7 +385,7 @@ module.exports = class App {
return current
}
if (this.themeAPI.existsParentTheme) {
const parent = path.resolve(this.themeAPI.theme.path, filepath)
const parent = path.resolve(this.themeAPI.parentTheme.path, filepath)
if (fs.existsSync(parent)) {
return parent
}
@@ -445,9 +449,9 @@ module.exports = class App {
}
/**
* Start a dev process with correct app context
* Launch a dev process with current app context.
*
* @returns {Promise<void>}
* @returns {Promise<App>}
* @api public
*/
@@ -455,20 +459,29 @@ module.exports = class App {
this.isProd = false
this.devProcess = new DevProcess(this)
await this.devProcess.process()
this.devProcess
.on('fileChanged', ({ type, target }) => {
console.log(`Reload due to ${chalk.red(type)} ${chalk.cyan(path.relative(this.sourceDir, target))}`)
this.process()
})
.createServer()
.listen()
const error = await new Promise(resolve => {
try {
this.devProcess
.on('fileChanged', ({ type, target }) => {
console.log(`Reload due to ${chalk.red(type)} ${chalk.cyan(path.relative(this.sourceDir, target))}`)
this.process()
})
.createServer()
.listen(resolve)
} catch (err) {
resolve(err)
}
})
if (error) {
throw error
}
return this
}
/**
* Start a build process with correct app context
* Launch a build process with current app context
*
* @returns {Promise<void>}
* @returns {Promise<App>}
* @api public
*/
@@ -477,6 +490,7 @@ module.exports = class App {
this.buildProcess = new BuildProcess(this)
await this.buildProcess.process()
await this.buildProcess.render()
return this
}
}
+50 -12
View File
@@ -37,7 +37,7 @@ module.exports = class Page {
*/
constructor ({
path,
path: _path,
meta,
title,
content,
@@ -58,12 +58,16 @@ module.exports = class Page {
if (relative) {
this.regularPath = encodeURI(fileToPath(relative))
} else if (path) {
this.regularPath = encodeURI(path)
} else if (_path) {
this.regularPath = encodeURI(_path)
} else if (permalink) {
this.regularPath = encodeURI(permalink)
}
if (filePath) {
this.relativePath = path.relative(context.sourceDir, filePath).replace(/\\/g, '/')
}
this.key = 'v-' + hash(`${this._filePath}${this.regularPath}`)
// Using regularPath first, would be override by permalink later.
this.path = this.regularPath
@@ -85,11 +89,7 @@ module.exports = class Page {
enhancers = [],
preRender = {}
}) {
// relative path
let relPath
if (this._filePath) {
relPath = path.relative(this._context.sourceDir, this._filePath)
logger.developer(`static_route`, chalk.cyan(this.path))
this._content = await fs.readFile(this._filePath, 'utf-8')
} else if (this._content) {
@@ -124,7 +124,7 @@ module.exports = class Page {
if (excerpt) {
const { html } = markdown.render(excerpt, {
frontmatter: this.frontmatter,
relPath
relativePath: this.relativePath
})
this.excerpt = html
}
@@ -146,6 +146,17 @@ module.exports = class Page {
this.buildPermalink()
}
/**
* name of page's parent directory.
*
* @returns {string}
* @api public
*/
get dirname () {
return path.basename(path.dirname(this._filePath || this.regularPath))
}
/**
* file name of page's source markdown file, or the last cut of regularPath.
*
@@ -165,7 +176,19 @@ module.exports = class Page {
*/
get slug () {
return slugify(this.strippedFilename)
const strippedFilename = this.strippedFilename
if (/^(index|readme)$/i.test(strippedFilename)) {
const strippedFilename = this.stripFilename(
path.basename(path.dirname(this._filePath || this.regularPath))
)
if (strippedFilename) {
return slugify(strippedFilename)
}
}
return slugify(strippedFilename)
}
/**
@@ -179,8 +202,7 @@ module.exports = class Page {
*/
get strippedFilename () {
const match = this.filename.match(DATE_RE)
return match ? match[3] : this.filename
return this.stripFilename(this.filename)
}
/**
@@ -191,7 +213,23 @@ module.exports = class Page {
*/
get date () {
return inferDate(this.frontmatter, this.filename)
return inferDate(this.frontmatter, this.filename, this.dirname)
}
/**
* stripped file name.
*
* If filename was yyyy-MM-dd-[title], the date prefix will be stripped.
* If filename was yyyy-MM-[title], the date prefix will be stripped.
*
* @param {string} fileName
* @returns {string}
* @private
*/
stripFilename (fileName) {
const match = fileName.match(DATE_RE)
return match ? match[3] : fileName
}
/**
@@ -18,6 +18,7 @@ describe('App', () => {
theme: '@vuepress/default',
emp: docsTempPath
})
await app.process()
expect(app.sourceDir).toBe(docsPath)
}))
})
@@ -0,0 +1,5 @@
module.exports = {
title: 'Hello VuePress',
description: '# Hello, VuePress!',
theme: 'vuepress-theme-without-index'
}
@@ -50,8 +50,6 @@ module.exports = class Build extends EventEmitter {
*/
async render () {
logger.wait('Extracting site metadata...')
// compile!
const stats = await compile([this.clientConfig, this.serverConfig])
const serverBundle = require(path.resolve(this.outDir, 'manifest/server.json'))
@@ -135,7 +133,7 @@ module.exports = class Build extends EventEmitter {
*/
async renderPage (page) {
const pagePath = page.path
const pagePath = decodeURIComponent(page.path)
readline.clearLine(process.stdout, 0)
readline.cursorTo(process.stdout, 0)
process.stdout.write(`Rendering page: ${pagePath}`)
@@ -145,7 +143,7 @@ module.exports = class Build extends EventEmitter {
const pageMeta = renderPageMeta(meta)
const context = {
url: pagePath,
url: page.path,
userHeadTags: this.userHeadTags,
pageMeta,
title: 'VuePress',
@@ -160,7 +158,7 @@ module.exports = class Build extends EventEmitter {
console.error(logger.error(chalk.red(`Error rendering ${pagePath}:`), false))
throw e
}
const filename = decodeURIComponent(pagePath.replace(/\/$/, '/index.html').replace(/^\//, ''))
const filename = pagePath.replace(/\/$/, '/index.html').replace(/^\//, '')
const filePath = path.resolve(this.outDir, filename)
await fs.ensureDir(path.dirname(filePath))
await fs.writeFile(filePath, html)
+41 -6
View File
@@ -176,7 +176,8 @@ module.exports = class DevProcess extends EventEmitter {
.use(DevLogPlugin, [{
port: this.port,
displayHost: this.displayHost,
publicPath: this.context.base
publicPath: this.context.base,
clearScreen: this.context.options.clearScreen
}])
config = config.toConfig()
@@ -187,6 +188,11 @@ module.exports = class DevProcess extends EventEmitter {
this.webpackConfig = config
}
/**
* Create dev server
* @returns {module.DevProcess}
*/
createServer () {
const contentBase = path.resolve(this.context.sourceDir, '.vuepress/public')
@@ -235,18 +241,32 @@ module.exports = class DevProcess extends EventEmitter {
return this
}
listen () {
this.server.listen(this.port, this.host, err => {
if (err) {
console.log(err)
/**
* delegate listen call.
*
* @param callback handler when connection is ready.
* @returns {module.DevProcess}
*/
listen (callback) {
this.server.listen(this.port, this.host, (err) => {
if (typeof callback === 'function') {
callback(err)
}
})
return this
}
}
/**
* Resolve host.
*
* @param {string} host user's host
* @returns {{displayHost: string, host: string}}
*/
function resolveHost (host) {
const defaultHost = 'localhost'
const defaultHost = '0.0.0.0'
host = host || defaultHost
const displayHost = host === defaultHost
? 'localhost'
@@ -257,6 +277,13 @@ function resolveHost (host) {
}
}
/**
* Resolve port.
*
* @param {number} port user's port
* @returns {Promise<number>}
*/
async function resolvePort (port) {
const portfinder = require('portfinder')
portfinder.basePort = parseInt(port) || 8080
@@ -264,6 +291,14 @@ async function resolvePort (port) {
return port
}
/**
* Normalize file path and always return relative path,
*
* @param {string} filepath user's path
* @param {string} baseDir source directory
* @returns {string}
*/
function normalizeWatchFilePath (filepath, baseDir) {
const { isAbsolute, relative } = require('path')
if (isAbsolute(filepath)) {
@@ -31,15 +31,22 @@ module.exports = (options, ctx) => ({
? `@import(${JSON.stringify(userPalette.replace(/[\\]+/g, '/'))})`
: ''
const nullComment = '// null'
// user's palette can override theme's palette.
let paletteContent = themePaletteContent + userPaletteContent
let paletteContent = '// Theme\'s Palette\n'
+ (themePaletteContent || nullComment)
+ '\n\n// User\'s Palette\n'
+ (userPaletteContent || nullComment)
if (ctx.themeAPI.existsParentTheme) {
const parentThemePalette = path.resolve(ctx.themeAPI.parentTheme.path, 'styles/palette.styl')
const parentThemePaletteContent = fs.existsSync(parentThemePalette)
? `@import(${JSON.stringify(parentThemePalette.replace(/[\\]+/g, '/'))})`
: ''
paletteContent = parentThemePaletteContent + paletteContent
paletteContent = '// Parent Theme\'s Palette\n'
+ (parentThemePaletteContent || nullComment)
+ '\n\n' + paletteContent
}
await writeTemp('palette.styl', paletteContent)
@@ -30,14 +30,23 @@ module.exports = (options, ctx) => ({
? `@import(${JSON.stringify(userStyle.replace(/[\\]+/g, '/'))})`
: ''
let styleContent = themeStyleContent + userStyleContent
const nullComment = '// null'
// user's styles can override theme's styles.
let styleContent = '// Theme\'s Styles\n'
+ (themeStyleContent || nullComment)
+ '\n\n// User\'s Styles\n'
+ (userStyleContent || nullComment)
if (themeAPI.existsParentTheme) {
const parentThemeStyle = path.resolve(themeAPI.parentTheme.path, 'styles/index.styl')
const parentThemeStyleContent = fs.existsSync(parentThemeStyle)
? `@import(${JSON.stringify(parentThemeStyle.replace(/[\\]+/g, '/'))})`
: ''
styleContent = parentThemeStyleContent + styleContent
styleContent = '// Parent Theme\'s Styles\n'
+ (parentThemeStyleContent || nullComment)
+ '\n\n' + styleContent
}
await writeTemp('style.styl', styleContent)
+35 -20
View File
@@ -9,7 +9,8 @@ const {
path: { resolve, parse },
moduleResolver: { getThemeResolver },
datatypes: { isString },
logger, chalk
logger,
chalk
} = require('@vuepress/shared-utils')
const ThemeAPI = require('./theme-api')
@@ -32,11 +33,15 @@ const ThemeAPI = require('./theme-api')
module.exports = function loadTheme (ctx) {
const themeResolver = getThemeResolver()
const theme = resolveTheme(ctx, themeResolver)
if (!theme.path) {
throw new Error(`[vuepress] You must specify a theme, or create a local custom theme. \n For more details, refer to https://vuepress.vuejs.org/guide/custom-themes.html#custom-themes. \n`)
throw new Error(
'[vuepress] You must specify a theme, or create a local custom theme. \n'
+ 'For more details, refer to https://vuepress.vuejs.org/guide/custom-themes.html#custom-themes. \n'
)
}
let applyTip = `Apply theme ${chalk.magenta(theme.name)}`
theme.entry.name = '@vuepress/internal-theme-entry-file'
@@ -46,27 +51,18 @@ module.exports = function loadTheme (ctx) {
parentTheme.entry.name = '@vuepress/internal-parent-theme-entry-file'
applyTip += chalk.gray(` (extends ${chalk.magenta(parentTheme.name)})`)
}
logger.tip(applyTip + ' ...')
logger.debug('theme', theme.name, theme.path)
logger.debug('parentTheme', parentTheme.name, parentTheme.path)
return new ThemeAPI(theme, parentTheme, ctx)
return new ThemeAPI(theme, parentTheme)
}
function normalizeThemePath (resolved) {
const { entry, name, fromDep } = resolved
const { entry, fromDep } = resolved
if (fromDep) {
const packageRoot = require.resolve(`${name}/package.json`)
const { main } = require(packageRoot)
if (main.endsWith('.vue')) {
// For those cases that "main" field is set to an non-index file
// e.g. `layouts/Layout.vue`
return packageRoot
} else {
// For those cases that "index.js" is not at package root
// e.g. `lib/index.js` (#1362)
return parse(require.resolve(name)).dir
}
return parse(require.resolve(entry)).dir
} else if (entry.endsWith('.js') || entry.endsWith('.vue')) {
return parse(entry).dir
} else {
@@ -84,25 +80,44 @@ function resolveTheme (ctx, resolver, ignoreLocal, theme) {
let shortcut
let entry = {}
// 1. From local
if (!ignoreLocal
/**
* 1. From `.vuepress/theme` directory.
*/
if (
!ignoreLocal
&& !fs.existsSync(theme)
&& fs.existsSync(localThemePath)
&& (fs.readdirSync(localThemePath)).length > 0
&& fs.readdirSync(localThemePath).length > 0
) {
path = localThemePath
name = shortcut = 'local'
logger.tip(`Apply local theme at ${chalk.gray(path)}...`)
// 2. From dep
/**
* 2. From deps or custom local path.
* - vuepress-plugin-foo
* - /path/to/a-theme/index.js
*/
} else if (isString(theme)) {
/**
* To let theme resolver get the correct theme name.
*/
if (theme.endsWith('/index.js')) {
theme = theme.replace(/\/index\.js$/, '')
}
const resolved = resolver.resolve(theme, sourceDir)
if (resolved.entry === null) {
throw new Error(`Cannot resolve theme: ${theme}.`)
}
path = normalizeThemePath(resolved)
name = resolved.name
shortcut = resolved.shortcut
/**
* 3. fallback
*/
} else {
return {}
}
@@ -5,12 +5,12 @@
*/
const instantiateOption = require('./override/instantiateOption')
const { flattenPlugin, normalizePluginsConfig } = require('./util')
const { flattenPlugin } = require('./util')
const { PLUGIN_OPTION_MAP } = require('./constants')
const {
moduleResolver: { getPluginResolver },
datatypes: { assertTypes, isPlainObject },
logger, chalk
logger, chalk, normalizeConfig
} = require('@vuepress/shared-utils')
/**
@@ -22,6 +22,7 @@ module.exports = class PluginAPI {
this.options = {}
this._pluginContext = context
this._pluginQueue = []
this._loggedPlugins = []
this._initialized = false
this._pluginResolver = getPluginResolver()
this.initializeOptions(PLUGIN_OPTION_MAP)
@@ -135,7 +136,7 @@ module.exports = class PluginAPI {
*/
useByPluginsConfig (pluginsConfig) {
pluginsConfig = normalizePluginsConfig(pluginsConfig)
pluginsConfig = normalizeConfig(pluginsConfig)
pluginsConfig.forEach(([pluginRaw, pluginOptions]) => {
this.use(pluginRaw, pluginOptions)
})
@@ -214,8 +215,11 @@ module.exports = class PluginAPI {
beforeDevServer,
afterDevServer
}) {
const isInternalPlugin = pluginName.startsWith('@vuepress/internal-')
logger[isInternalPlugin ? 'debug' : 'tip'](pluginLog(pluginName, shortcut))
if (!this._loggedPlugins.includes(pluginName)) {
const isInternalPlugin = pluginName.startsWith('@vuepress/internal-')
logger[isInternalPlugin ? 'debug' : 'tip'](pluginLog(pluginName, shortcut))
this._loggedPlugins.push(pluginName)
}
this
.registerOption(PLUGIN_OPTION_MAP.READY.key, ready, pluginName)
@@ -22,7 +22,7 @@ exports.flattenPlugin = function (
pluginContext,
self
) {
const { valid, warnMsg } = assertTypes(pluginOptions, [Object, Boolean])
const { valid, warnMsg } = assertTypes(pluginOptions, [Object, Array, Boolean])
if (!valid) {
if (pluginOptions !== undefined) {
logger.warn(
@@ -43,6 +43,14 @@ exports.flattenPlugin = function (
// 'Object.create' here is to give each plugin a separate context,
// but also own the inheritance context.
config = config(pluginOptions, Object.create(pluginContext), self)
const { valid, warnMsg } = assertTypes(config, [Object])
if (!valid) {
logger.warn(
`[${chalk.gray(shortcut)}] `
+ `Invalid value for plugin: ${warnMsg}`
)
config = {}
}
}
// respect name in local plugin config
@@ -57,34 +65,3 @@ exports.flattenPlugin = function (
$$options: pluginOptions /* used for test */
})
}
/**
* Normalize plugins config in `.vuepress/config.js`
*
* @param pluginsConfig
*/
exports.normalizePluginsConfig = function (pluginsConfig) {
const { valid, warnMsg } = assertTypes(pluginsConfig, [Object, Array])
if (!valid) {
if (pluginsConfig !== undefined) {
logger.warn(
`[${chalk.gray('config')}] `
+ `Invalid value for "plugin" field : ${warnMsg}`
)
}
pluginsConfig = []
return pluginsConfig
}
if (Array.isArray(pluginsConfig)) {
pluginsConfig = pluginsConfig.map(item => {
return Array.isArray(item) ? item : [item]
})
} else if (typeof pluginsConfig === 'object') {
pluginsConfig = Object.keys(pluginsConfig).map(item => {
return [item, pluginsConfig[item]]
})
}
return pluginsConfig
}
@@ -1,5 +1,9 @@
const { logger, fs, path: { resolve }} = require('@vuepress/shared-utils')
const readdirSync = dir => fs.existsSync(dir) && fs.readdirSync(dir) || []
const {
logger,
fs,
path: { resolve }
} = require('@vuepress/shared-utils')
const readdirSync = dir => (fs.existsSync(dir) && fs.readdirSync(dir)) || []
module.exports = class ThemeAPI {
constructor (theme, parentTheme) {
@@ -30,12 +34,12 @@ module.exports = class ThemeAPI {
this.componentMap = this.getComponents()
this.layoutComponentMap = this.getLayoutComponentMap()
Object.keys(this.componentMap).forEach((name) => {
Object.keys(this.componentMap).forEach(name => {
const { filename, path } = this.componentMap[name]
alias[`@theme/components/${filename}`] = path
})
Object.keys(this.layoutComponentMap).forEach((name) => {
Object.keys(this.layoutComponentMap).forEach(name => {
const { filename, path } = this.layoutComponentMap[name]
alias[`@theme/layouts/${filename}`] = path
})
@@ -44,13 +48,9 @@ module.exports = class ThemeAPI {
}
getComponents () {
const componentDirs = [
resolve(this.theme.path, 'components')
]
const componentDirs = [resolve(this.theme.path, 'components')]
if (this.existsParentTheme) {
componentDirs.unshift(
resolve(this.parentTheme.path, 'components'),
)
componentDirs.unshift(resolve(this.parentTheme.path, 'components'))
}
return resolveSFCs(componentDirs)
}
@@ -63,15 +63,15 @@ module.exports = class ThemeAPI {
if (this.existsParentTheme) {
layoutDirs.unshift(
resolve(this.parentTheme.path, '.'),
resolve(this.parentTheme.path, 'layouts'),
resolve(this.parentTheme.path, 'layouts')
)
}
// built-in named layout or not.
const layoutComponentMap = resolveSFCs(layoutDirs)
const { Layout = {}, NotFound = {}} = layoutComponentMap
const { Layout, NotFound } = layoutComponentMap
// layout component does not exist.
if (!Layout || !fs.existsSync(Layout.path)) {
if (!Layout) {
const fallbackLayoutPath = resolve(__dirname, 'Layout.fallback.vue')
layoutComponentMap.Layout = {
filename: 'Layout.vue',
@@ -80,11 +80,11 @@ module.exports = class ThemeAPI {
isInternal: true
}
logger.warn(
`[vuepress] Cannot resolve Layout.vue file in \n ${Layout.path},`
+ `fallback to default layout: ${fallbackLayoutPath}`
`[vuepress] Cannot resolve Layout.vue file in \n ${Layout.path}, `
+ `fallback to default layout: ${fallbackLayoutPath}`
)
}
if (!NotFound || !fs.existsSync(NotFound.path)) {
if (!NotFound) {
layoutComponentMap.NotFound = {
filename: 'NotFound.vue',
componentName: 'NotFound',
@@ -104,25 +104,28 @@ module.exports = class ThemeAPI {
*/
function resolveSFCs (dirs) {
return dirs.map(
layoutDir => readdirSync(layoutDir)
.filter(filename => filename.endsWith('.vue'))
.map(filename => {
const componentName = getComponentName(filename)
return {
filename,
componentName,
isInternal: isInternal(componentName),
path: resolve(layoutDir, filename)
}
})
).reduce((arr, next) => {
arr.push(...next)
return arr
}, []).reduce((map, component) => {
map[component.componentName] = component
return map
}, {})
return dirs
.map(layoutDir =>
readdirSync(layoutDir)
.filter(filename => filename.endsWith('.vue'))
.map(filename => {
const componentName = getComponentName(filename)
return {
filename,
componentName,
isInternal: isInternal(componentName),
path: resolve(layoutDir, filename)
}
})
)
.reduce((arr, next) => {
arr.push(...next)
return arr
}, [])
.reduce((map, component) => {
map[component.componentName] = component
return map
}, {})
}
/**
@@ -54,13 +54,16 @@ exports.applyUserWebpackConfig = function (userConfig, config, isServer) {
const DATE_RE = /(\d{4}-\d{1,2}(-\d{1,2})?)-(.*)/
exports.DATE_RE = DATE_RE
exports.inferDate = function (frontmatter = {}, filename) {
exports.inferDate = function (frontmatter = {}, filename, dirname) {
let matches
if (frontmatter.date) {
return frontmatter.date
} else if (filename && (matches = filename.match(DATE_RE))) {
return matches[1]
} else if (dirname && (matches = dirname.match(DATE_RE))) {
return matches[1]
} else {
return null
}
const match = filename.match(DATE_RE)
if (match) {
return match[1]
}
return null
}
@@ -17,10 +17,13 @@ module.exports = class DevLogPlugin {
apply (compiler) {
let isFirst = true
const { displayHost, port, publicPath, clearScreen: shouldClearScreen = true } = this.options
compiler.hooks.done.tap('vuepress-log', stats => {
clearScreen()
if (shouldClearScreen) {
clearScreen()
}
const { displayHost, port, publicPath } = this.options
const time = new Date().toTimeString().match(/^[\d:]+/)[0]
const displayUrl = `http://${displayHost}:${port}${publicPath}`
@@ -30,7 +33,7 @@ module.exports = class DevLogPlugin {
+ (
isFirst
? ''
: `${chalk.gray(`(${displayUrl})`)}`
: `${chalk.gray(`( ${displayUrl} )`)}`
)
)
if (isFirst) {
@@ -40,7 +43,9 @@ module.exports = class DevLogPlugin {
logger.developer(`It took a total of ${chalk.cyan(`${duration}ms`)} to run the ${chalk.cyan('vuepress dev')} for the first time.`)
}
})
compiler.hooks.invalid.tap('vuepress-log', clearScreen)
if (shouldClearScreen) {
compiler.hooks.invalid.tap('vuepress-log', clearScreen)
}
}
}
@@ -127,7 +127,10 @@ module.exports = function createBaseConfig (context, isServer) {
.loader('pug-plain-loader')
.end()
if (!siteConfig.evergreen) {
const evergreen = typeof siteConfig.evergreen === 'function'
? siteConfig.evergreen()
: siteConfig.evergreen
if (!evergreen) {
const libDir = path.join(__dirname, '..')
config.module
.rule('js')
@@ -141,6 +144,10 @@ module.exports = function createBaseConfig (context, isServer) {
if (/\.vue\.js$/.test(filePath)) {
return false
}
// transpile all core files
if (/(@vuepress|vuepress-)\/^((?!node_modules).)*\.js$/.test(filePath)) {
return false
}
// Don't transpile node_modules
return /node_modules/.test(filePath)
}).end()
@@ -224,12 +231,13 @@ module.exports = function createBaseConfig (context, isServer) {
}
rule.use('css-loader')
.loader(isServer ? 'css-loader/locals' : 'css-loader')
.loader('css-loader')
.options({
modules,
localIdentName: `[local]_[hash:base64:8]`,
importLoaders: 1,
sourceMap: !isProd
sourceMap: !isProd,
exportOnlyLocals: isServer
})
rule.use('postcss-loader').loader('postcss-loader').options(Object.assign({
@@ -306,5 +314,5 @@ function getLastCommitHash () {
}
function getModulePaths () {
return [path.resolve(process.cwd(), 'node_modules')].concat(module.paths)
return module.paths.concat([path.resolve(process.cwd(), 'node_modules')])
}
@@ -7,6 +7,7 @@
module.exports = function createClientConfig (ctx) {
const { env } = require('@vuepress/shared-utils')
const createBaseConfig = require('./createBaseConfig')
const safeParser = require('postcss-safe-parser')
const config = createBaseConfig(ctx)
@@ -49,7 +50,7 @@ module.exports = function createClientConfig (ctx) {
.use(require('optimize-css-assets-webpack-plugin'), [{
canPrint: false,
cssProcessorOptions: {
safe: true,
parser: safeParser,
autoprefixer: { disable: true },
mergeLonghand: false
}
@@ -16,7 +16,7 @@ module.exports = function createServerConfig (ctx) {
config
.target('node')
.externals([/^vue|vue-router$/])
.externals([/^(vue|vue-router)$/])
.devtool('source-map')
// no need to minimize server build
+19 -18
View File
@@ -1,6 +1,6 @@
{
"name": "@vuepress/core",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "Minimalistic doc generator with Vue component based layout system",
"main": "lib/index.js",
"typings": "lib/types/index.d.ts",
@@ -34,28 +34,28 @@
"@types/webpack-chain": "^5.0.1",
"@types/webpack-dev-server": "^3.1.2",
"@vue/babel-preset-app": "^3.1.1",
"@vuepress/markdown": "^1.0.0-alpha.42",
"@vuepress/markdown-loader": "^1.0.0-alpha.42",
"@vuepress/plugin-container": "^1.0.0-alpha.42",
"@vuepress/plugin-last-updated": "^1.0.0-alpha.42",
"@vuepress/plugin-register-components": "^1.0.0-alpha.42",
"@vuepress/shared-utils": "^1.0.0-alpha.42",
"autoprefixer": "^7.1.2",
"@vuepress/markdown": "^1.0.4",
"@vuepress/markdown-loader": "^1.0.4",
"@vuepress/plugin-last-updated": "^1.0.4",
"@vuepress/plugin-register-components": "^1.0.4",
"@vuepress/shared-utils": "^1.0.4",
"autoprefixer": "^9.5.1",
"babel-loader": "^8.0.4",
"cache-loader": "^1.2.2",
"cache-loader": "^3.0.0",
"chokidar": "^2.0.3",
"connect-history-api-fallback": "^1.5.0",
"copy-webpack-plugin": "^4.5.1",
"copy-webpack-plugin": "^5.0.2",
"cross-spawn": "^6.0.5",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"css-loader": "^2.1.1",
"file-loader": "^3.0.1",
"js-yaml": "^3.11.0",
"lru-cache": "^5.1.1",
"mini-css-extract-plugin": "0.4.4",
"optimize-css-assets-webpack-plugin": "^4.0.0",
"mini-css-extract-plugin": "0.6.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"portfinder": "^1.0.13",
"postcss-loader": "^2.1.5",
"toml": "^2.3.3",
"postcss-loader": "^3.0.0",
"postcss-safe-parser": "^4.0.1",
"toml": "^3.0.0",
"url-loader": "^1.0.1",
"vue": "^2.5.16",
"vue-loader": "^15.2.4",
@@ -63,11 +63,12 @@
"vue-server-renderer": "^2.5.16",
"vue-template-compiler": "^2.5.16",
"vuepress-html-webpack-plugin": "^3.2.0",
"vuepress-plugin-container": "^2.0.0",
"webpack": "^4.8.1",
"webpack-chain": "^4.6.0",
"webpack-dev-server": "^3.1.14",
"webpack-dev-server": "^3.5.1",
"webpack-merge": "^4.1.2",
"webpackbar": "^2.6.1"
"webpackbar": "3.2.0"
},
"engines": {
"node": ">=8.6"
+17 -7
View File
@@ -6,10 +6,11 @@
const { EventEmitter } = require('events')
const { getOptions } = require('loader-utils')
const { fs, path, parseFrontmatter, inferTitle, extractHeaders } = require('@vuepress/shared-utils')
const { fs, path, hash, parseFrontmatter, inferTitle, extractHeaders } = require('@vuepress/shared-utils')
const LRU = require('lru-cache')
const md = require('@vuepress/markdown')
const cache = new LRU({ max: 1000 })
const devCache = new LRU({ max: 1000 })
/**
@@ -31,18 +32,26 @@ module.exports = function (src) {
// vue-loader, and will be applied on the same file multiple times when
// selecting the individual blocks.
const file = this.resourcePath
const { content, data } = parseFrontmatter(src)
const key = hash(file + src)
const cached = cache.get(key)
if (cached && (isProd || /\?vue/.test(this.resourceQuery))) {
return cached
}
const frontmatter = parseFrontmatter(src)
const content = frontmatter.content
if (!isProd && !isServer) {
const inferredTitle = inferTitle(data, content)
const inferredTitle = inferTitle(frontmatter.data, frontmatter.content)
const headers = extractHeaders(content, ['h2', 'h3'], markdown)
delete frontmatter.content
// diff frontmatter and title, since they are not going to be part of the
// returned component, changes in frontmatter do not trigger proper updates
const cachedData = devCache.get(file)
if (cachedData && (
cachedData.inferredTitle !== inferredTitle
|| JSON.stringify(cachedData.frontmatterData) !== JSON.stringify(data)
|| JSON.stringify(cachedData.frontmatterData) !== JSON.stringify(frontmatter.data)
|| headersChanged(cachedData.headers, headers)
)) {
// frontmatter changed... need to do a full reload
@@ -51,7 +60,7 @@ module.exports = function (src) {
devCache.set(file, {
headers,
frontmatterData: data,
frontmatterData: frontmatter.data,
inferredTitle
})
}
@@ -64,8 +73,8 @@ module.exports = function (src) {
dataBlockString
} = markdown.render(content, {
loader,
frontmatter: data,
relPath: path.relative(sourceDir, file)
frontmatter: frontmatter.data,
relativePath: path.relative(sourceDir, file).replace(/\\/g, '/')
})
// check if relative links are valid
@@ -105,6 +114,7 @@ module.exports = function (src) {
+ (hoistedTags || []).join('\n')
+ `\n${dataBlockString}\n`
)
cache.set(key, res)
return res
}
@@ -1,6 +1,6 @@
{
"name": "@vuepress/markdown-loader",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "markdown-loader for vuepress",
"main": "index.js",
"publishConfig": {
@@ -18,7 +18,7 @@
"generator"
],
"dependencies": {
"@vuepress/markdown": "^1.0.0-alpha.42",
"@vuepress/markdown": "^1.0.4",
"loader-utils": "^1.1.0",
"lru-cache": "^5.1.1"
},
@@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`snippet import snippets when the file has a space in the file path 1`] = `
<div class="highlight-lines">
<div class="highlighted">&nbsp;</div>
<div class="highlighted">&nbsp;</div>
<div class="highlighted">&nbsp;</div><br>
</div>export default function () {
// ..
}
`;
exports[`snippet import snippet 1`] = `
<pre><code class="language-js">export default function () {
// ..
@@ -0,0 +1 @@
<<< @/packages/@vuepress/markdown/__tests__/fragments/snippet with spaces.js {1-3}
@@ -0,0 +1,3 @@
export default function () {
// ..
}
@@ -10,7 +10,7 @@ const mdL = Md().use(link, {
dataReturnable(mdL)
const internalLinkAsserts = {
// START abosolute path usage
// START absolute path usage
'/': '/',
'/foo/': '/foo/',
@@ -18,7 +18,7 @@ const internalLinkAsserts = {
'/foo/two.md': '/foo/two.html',
'/foo/two.html': '/foo/two.html',
// END abosolute path usage
// END absolute path usage
// START relative path usage
'README.md': './',
@@ -24,4 +24,10 @@ describe('snippet', () => {
const output = mdH.render(input)
expect(output).toMatchSnapshot()
})
test('import snippets when the file has a space in the file path', () => {
const input = getFragment(__dirname, 'code-snippet-with-space-in-path.md')
const output = mdH.render(input)
expect(output).toMatchSnapshot()
})
})
+24 -18
View File
@@ -5,7 +5,6 @@
*/
const Config = require('markdown-it-chain')
const LRUCache = require('lru-cache')
const highlight = require('./lib/highlight')
const { PLUGINS, REQUIRED_PLUGINS } = require('./lib/constant')
const highlightLinesPlugin = require('./lib/highlightLines')
@@ -15,10 +14,15 @@ const componentPlugin = require('./lib/component')
const hoistScriptStylePlugin = require('./lib/hoist')
const convertRouterLinkPlugin = require('./lib/link')
const snippetPlugin = require('./lib/snippet')
const tocPlugin = require('./lib/tableOfContents')
const emojiPlugin = require('markdown-it-emoji')
const anchorPlugin = require('markdown-it-anchor')
const { slugify: _slugify, logger, chalk, hash } = require('@vuepress/shared-utils')
const tocPlugin = require('markdown-it-table-of-contents')
const {
slugify: _slugify,
parseHeaders,
logger, chalk, normalizeConfig,
moduleResolver: { getMarkdownItResolver }
} = require('@vuepress/shared-utils')
/**
* Create markdown by config.
@@ -29,11 +33,14 @@ module.exports = (markdown = {}) => {
externalLinks,
anchor,
toc,
plugins,
lineNumbers,
beforeInstantiate,
afterInstantiate
} = markdown
const resolver = getMarkdownItResolver()
// allow user config slugify
const slugify = markdown.slugify || _slugify
@@ -87,7 +94,11 @@ module.exports = (markdown = {}) => {
.end()
.plugin(PLUGINS.TOC)
.use(tocPlugin, [toc])
.use(tocPlugin, [Object.assign({
slugify,
includeLevel: [2, 3],
format: parseHeaders
}, toc)])
.end()
if (lineNumbers) {
@@ -100,22 +111,17 @@ module.exports = (markdown = {}) => {
const md = config.toMd(require('markdown-it'), markdown)
afterInstantiate && afterInstantiate(md)
// override parse to allow cache
const parse = md.parse
const cache = new LRUCache({ max: 1000 })
md.parse = (src, env) => {
const key = hash(src + env.relPath)
const cached = cache.get(key)
if (cached) {
return cached
const pluginsConfig = normalizeConfig(plugins || [])
pluginsConfig.forEach(([pluginRaw, pluginOptions]) => {
const plugin = resolver.resolve(pluginRaw)
if (plugin.entry) {
md.use(plugin.entry, pluginOptions)
} else {
const tokens = parse.call(md, src, env)
cache.set(key, tokens)
return tokens
// TODO: error handling
}
}
})
afterInstantiate && afterInstantiate(md)
module.exports.dataReturnable(md)
@@ -39,6 +39,10 @@ module.exports = (str, lang) => {
if (lang === 'yml') {
lang = 'yaml'
}
if (lang === 'styl') {
lang = 'stylus'
}
if (!prism.languages[lang]) {
try {
loadLanguages([lang])
+5 -5
View File
@@ -11,7 +11,7 @@ module.exports = (md, externalAttrs) => {
let hasOpenExternalLink = false
md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
const { relPath } = env
const { relativePath } = env
const token = tokens[idx]
const hrefIndex = token.attrIndex('href')
if (hrefIndex >= 0) {
@@ -28,13 +28,13 @@ module.exports = (md, externalAttrs) => {
}
} else if (isSourceLink) {
hasOpenRouterLink = true
tokens[idx] = toRouterLink(token, link, relPath)
tokens[idx] = toRouterLink(token, link, relativePath)
}
}
return self.renderToken(tokens, idx, options)
}
function toRouterLink (token, link, relPath) {
function toRouterLink (token, link, relativePath) {
link[0] = 'to'
let to = link[1]
@@ -44,8 +44,8 @@ module.exports = (md, externalAttrs) => {
// relative path usage.
if (!to.startsWith('/')) {
to = relPath
? url.resolve('/' + relPath, to)
to = relativePath
? url.resolve('/' + relativePath, to)
: ensureBeginningDotSlash(to)
}
+1 -1
View File
@@ -44,7 +44,7 @@ module.exports = function snippet (md, options = {}) {
const start = pos + 3
const end = state.skipSpacesBack(max, pos)
const rawPath = state.src.slice(start, end).trim().replace(/^@/, root)
const filename = rawPath.split(/[{\s]/).shift()
const filename = rawPath.split(/{/).shift().trim()
const meta = rawPath.replace(filename, '')
state.line = startLine + 1
@@ -1,83 +0,0 @@
// reference: https://github.com/Oktavilla/markdown-it-table-of-contents
const defaults = {
includeLevel: [2, 3],
containerClass: 'table-of-contents',
markerPattern: /^\[\[toc\]\]/im,
listType: 'ul',
containerHeaderHtml: '',
containerFooterHtml: ''
}
module.exports = (md, options) => {
options = Object.assign({}, defaults, options)
const tocRegexp = options.markerPattern
function toc (state, silent) {
var token
var match
// Reject if the token does not start with [
if (state.src.charCodeAt(state.pos) !== 0x5B /* [ */) {
return false
}
// Don't run any pairs in validation mode
if (silent) {
return false
}
// Detect TOC markdown
match = tocRegexp.exec(state.src)
match = !match ? [] : match.filter(function (m) { return m })
if (match.length < 1) {
return false
}
// Build content
token = state.push('toc_open', 'toc', 1)
token.markup = '[[toc]]'
token = state.push('toc_body', '', 0)
token = state.push('toc_close', 'toc', -1)
// Update pos so the parser can continue
var newline = state.src.indexOf('\n')
if (newline !== -1) {
state.pos = state.pos + newline
} else {
state.pos = state.pos + state.posMax + 1
}
return true
}
md.renderer.rules.toc_open = function () {
return vBindEscape`<TOC
:class=${options.containerClass}
:list-type=${options.listType}
:include-level=${options.includeLevel}
>`
}
md.renderer.rules.toc_body = function () {
return `<template slot="header">${options.containerHeaderHtml}</template>`
+ `<template slot="footer">${options.containerFooterHtml}</template>`
}
md.renderer.rules.toc_close = function () {
return `</TOC>`
}
// Insert TOC
md.inline.ruler.after('emphasis', 'toc', toc)
}
/** escape double quotes in v-bind derivatives */
function vBindEscape (strs, ...args) {
return strs.reduce((prev, curr, index) => {
return prev + curr + (index >= args.length
? ''
: `"${JSON.stringify(args[index])
.replace(/"/g, "'")
.replace(/([^\\])(\\\\)*\\'/g, (_, char) => char + '\\u0022')}"`)
}, '')
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@vuepress/markdown",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "markdown for vuepress",
"main": "index.js",
"publishConfig": {
@@ -19,16 +19,16 @@
"markdown"
],
"dependencies": {
"@vuepress/shared-utils": "^1.0.0-alpha.42",
"lru-cache": "^5.1.1",
"@vuepress/shared-utils": "^1.0.4",
"markdown-it": "^8.4.1",
"markdown-it-anchor": "^5.0.2",
"markdown-it-chain": "^1.3.0",
"markdown-it-emoji": "^1.4.0",
"markdown-it-table-of-contents": "^0.4.0",
"prismjs": "^1.13.0"
},
"devDependencies": {
"@vuepress/test-utils": "^1.0.0-alpha.42"
"@vuepress/test-utils": "^1.0.4"
},
"author": "Evan You",
"maintainers": [
@@ -2,4 +2,4 @@
> active-header-links plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-active-header-links.html).
See [documentation](https://v1.vuepress.vuejs.org/plugin/official/plugin-active-header-links.html).
@@ -23,6 +23,13 @@ export default {
document.body.scrollTop
)
const scrollHeight = Math.max(
document.documentElement.scrollHeight,
document.body.scrollHeight
)
const bottomY = window.innerHeight + scrollTop
for (let i = 0; i < anchors.length; i++) {
const anchor = anchors[i]
const nextAnchor = anchors[i + 1]
@@ -31,9 +38,19 @@ export default {
|| (scrollTop >= anchor.parentElement.offsetTop + 10
&& (!nextAnchor || scrollTop < nextAnchor.parentElement.offsetTop - 10))
if (isActive && decodeURIComponent(this.$route.hash) !== decodeURIComponent(anchor.hash)) {
const routeHash = decodeURIComponent(this.$route.hash)
if (isActive && routeHash !== decodeURIComponent(anchor.hash)) {
const activeAnchor = anchor
// check if anchor is at the bottom of the page to keep $route.hash consistent
if (bottomY === scrollHeight) {
for (let j = i + 1; j < anchors.length; j++) {
if (routeHash === decodeURIComponent(anchors[j].hash)) {
return
}
}
}
this.$vuepress.$set('disableScrollBehavior', true)
this.$router.replace(decodeURIComponent(anchor.hash), () => {
this.$router.replace(decodeURIComponent(activeAnchor.hash), () => {
// execute after scrollBehavior handler.
this.$nextTick(() => {
this.$vuepress.$set('disableScrollBehavior', false)
@@ -1,6 +1,6 @@
{
"name": "@vuepress/plugin-active-header-links",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "active-header-links plugin for vuepress",
"main": "index.js",
"publishConfig": {
@@ -2,4 +2,4 @@
> Back-to-top plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-back-to-top.html).
See [documentation](https://v1.vuepress.vuejs.org/plugin/official/plugin-back-to-top.html).
@@ -1,6 +1,6 @@
{
"name": "@vuepress/plugin-back-to-top",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "back-to-top plugin for vuepress",
"main": "index.js",
"publishConfig": {
@@ -1,3 +0,0 @@
__tests__
__mocks__
.temp
-9
View File
@@ -1,9 +0,0 @@
# @vuepress/plugin-blog
> blog plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-blog.html).
@@ -1,63 +0,0 @@
import { findPageByKey } from '@app/util'
import tagMeta from '@dynamic/tag'
import categoryMeta from '@dynamic/category'
class Classifiable {
constructor (metaMap, pages) {
this._metaMap = Object.assign({}, metaMap)
Object.keys(this._metaMap).forEach(name => {
const { pageKeys } = this._metaMap[name]
this._metaMap[name].posts = pageKeys.map(key => findPageByKey(pages, key))
})
}
get length () {
return Object.keys(this._metaMap).length
}
get map () {
return this._metaMap
}
get list () {
return this.toArray()
}
toArray () {
const tags = []
Object.keys(this._metaMap).forEach(name => {
const { posts, path } = this._metaMap[name]
tags.push({ name, posts, path })
})
return tags
}
getItemByName (name) {
return this._metaMap[name]
}
}
export default ({ Vue }) => {
Vue.mixin({
computed: {
$tags () {
const { pages } = this.$site
const tags = new Classifiable(tagMeta, pages)
return tags
},
$tag () {
const tagName = this.$route.meta.tagName
return this.$tags.getItemByName(tagName)
},
$categories () {
const { pages } = this.$site
const categories = new Classifiable(categoryMeta, pages)
return categories
},
$category () {
const categoryName = this.$route.meta.categoryName
return this.$categories.getItemByName(categoryName)
}
}
})
}
-166
View File
@@ -1,166 +0,0 @@
const { path, datatypes: { isString }} = require('@vuepress/shared-utils')
module.exports = (options, ctx) => {
const { themeAPI: { layoutComponentMap }} = ctx
const {
pageEnhancers = [],
postsDir = '_posts',
categoryIndexPageUrl = '/category/',
tagIndexPageUrl = '/tag/',
permalink = '/:year/:month/:day/:slug'
} = options
const isLayoutExists = name => layoutComponentMap[name] !== undefined
const getLayout = (name, fallback) => isLayoutExists(name) ? name : fallback
const isDirectChild = regularPath => path.parse(regularPath).dir === '/'
const enhancers = [
{
when: ({ regularPath }) => regularPath === categoryIndexPageUrl,
frontmatter: { layout: getLayout('Categories', 'Page') }
},
{
when: ({ regularPath }) => regularPath.startsWith('/category/'),
frontmatter: { layout: getLayout('Category', 'Page') }
},
{
when: ({ regularPath }) => regularPath === tagIndexPageUrl,
frontmatter: { layout: getLayout('Tags', 'Page') }
},
{
when: ({ regularPath }) => regularPath.startsWith('/tag/'),
frontmatter: { layout: getLayout('Tag', 'Page') }
},
{
when: ({ regularPath }) => regularPath === '/',
frontmatter: { layout: getLayout('Layout') }
},
{
when: ({ regularPath }) => regularPath.startsWith(`/${postsDir}/`),
frontmatter: {
layout: getLayout('Post', 'Page'),
permalink: permalink
},
data: { type: 'post' }
},
...pageEnhancers,
{
when: ({ regularPath }) => isDirectChild(regularPath),
frontmatter: { layout: getLayout('Page', 'Layout') },
data: { type: 'page' }
}
]
return {
/**
* Modify page's metadata according to the habits of blog users.
*/
extendPageData (pageCtx) {
const { frontmatter: rawFrontmatter } = pageCtx
enhancers.forEach(({
when,
data = {},
frontmatter = {}
}) => {
if (when(pageCtx)) {
Object.keys(frontmatter).forEach(key => {
if (!rawFrontmatter[key]) {
rawFrontmatter[key] = frontmatter[key]
}
})
Object.assign(pageCtx, data)
}
})
},
/**
* Create tag page and category page.
*/
async ready () {
const { pages } = ctx
const tagMap = {}
const categoryMap = {}
const curryHandler = (scope, map) => (key, pageKey) => {
if (key) {
if (!map[key]) {
map[key] = {}
map[key].path = `/${scope}/${key}.html`
map[key].pageKeys = []
}
map[key].pageKeys.push(pageKey)
}
}
const handleTag = curryHandler('tag', tagMap)
const handleCategory = curryHandler('category', categoryMap)
pages.forEach(({
key,
frontmatter: {
tag,
tags,
category,
categories
}
}) => {
if (isString(tag)) {
handleTag(tag, key)
}
if (Array.isArray(tags)) {
tags.forEach(tag => handleTag(tag, key))
}
if (isString(category)) {
handleCategory(category, key)
}
if (Array.isArray(categories)) {
categories.forEach(category => handleCategory(category, key))
}
})
ctx.tagMap = tagMap
ctx.categoryMap = categoryMap
const extraPages = [
{
permalink: tagIndexPageUrl,
frontmatter: { title: `Tags` }
},
{
permalink: categoryIndexPageUrl,
frontmatter: { title: `Categories` }
},
...Object.keys(tagMap).map(tagName => ({
permalink: tagMap[tagName].path,
meta: { tagName },
frontmatter: { title: `${tagName} | Tag` }
})),
...Object.keys(categoryMap).map(categoryName => ({
permalink: categoryMap[categoryName].path,
meta: { categoryName },
frontmatter: { title: `${categoryName} | Category` }
}))
]
await Promise.all(extraPages.map(page => ctx.addPage(page)))
},
/**
* Generate tag and category metadata.
*/
async clientDynamicModules () {
return [
{
name: 'tag.js',
content: `export default ${JSON.stringify(ctx.tagMap, null, 2)}`
},
{
name: 'category.js',
content: `export default ${JSON.stringify(ctx.categoryMap, null, 2)}`
}
]
},
enhanceAppFiles: path.resolve(__dirname, 'enhanceAppFile.js')
}
}
@@ -1,26 +0,0 @@
{
"name": "@vuepress/plugin-blog",
"version": "1.0.0-alpha.42",
"description": "blog plugin for vuepress",
"main": "index.js",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vuepress.git",
"directory": "packages/@vuepress/plugin-blog"
},
"keywords": [
"documentation",
"vue",
"vuepress",
"generator"
],
"author": "ULIVZ <chl814@foxmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vuepress/issues"
},
"homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/plugin-blog#readme"
}
@@ -1,3 +0,0 @@
__tests__
__mocks__
.temp
@@ -1,5 +0,0 @@
# @vuepress/plugin-clean-urls
> clean urls plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-clean-urls.html).
@@ -1,22 +0,0 @@
module.exports = (options = {}, context) => {
const {
normalSuffix = '',
indexSuffix = '/'
} = options
return {
extendPageData (page) {
const { regularPath, frontmatter = {}} = page
if (frontmatter.permalink) return
if (regularPath.endsWith('.html')) {
// normal path
// e.g. foo/bar.md -> foo/bar.html
page.path = regularPath.slice(0, -5) + normalSuffix
} else if (regularPath.endsWith('/')) {
// index path
// e.g. foo/index.md -> foo/
page.path = regularPath.slice(0, -1) + indexSuffix
}
}
}
}
@@ -1,26 +0,0 @@
{
"name": "@vuepress/plugin-clean-urls",
"version": "1.0.0-alpha.42",
"description": "clean urls plugin for vuepress",
"main": "index.js",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vuepress.git",
"directory": "packages/@vuepress/plugin-clean-urls"
},
"keywords": [
"documentation",
"vue",
"vuepress",
"generator"
],
"author": "Shigma <1700011071@pku.edu.cn>",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vuepress/issues"
},
"homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/plugin-clean-urls#readme"
}
@@ -1,3 +0,0 @@
__tests__
__mocks__
.temp
@@ -1,5 +0,0 @@
# @vuepress/plugin-container
> markdown container plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-container.html).
@@ -1,48 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`containers danger.md 1`] = `
<div class="danger custom-block">
<p class="custom-block-title">DANGER</p>
<p>I am a danger</p>
</div>
`;
exports[`containers markdown-slots.md 1`] = `
<template slot="header">
<h1 id="here-might-be-a-page-title"><a class="header-anchor" href="#here-might-be-a-page-title" aria-hidden="true">#</a> Here might be a page title</h1>
</template>
<ul>
<li>A Paragraph</li>
<li>Another Paragraph</li>
</ul>
<template slot="footer">
<p>Here's some contact info</p>
</template>
`;
exports[`containers tip.md 1`] = `
<div class="tip custom-block">
<p class="custom-block-title">TIP</p>
<p>I am a tip</p>
</div>
`;
exports[`containers tip-override.md 1`] = `
<div class="tip custom-block">
<p class="custom-block-title">提示</p>
<p>I am a tip</p>
</div>
`;
exports[`containers v-pre.md 1`] = `
<div v-pre>
<p>I am a v-pre</p>
</div>
`;
exports[`containers warning.md 1`] = `
<div class="warning custom-block">
<p class="custom-block-title">WARNING</p>
<p>I am a warning</p>
</div>
`;
@@ -1,3 +0,0 @@
::: danger
I am a danger
:::
@@ -1,10 +0,0 @@
::: slot header
# Here might be a page title
:::
- A Paragraph
- Another Paragraph
::: slot footer
Here's some contact info
:::
@@ -1,3 +0,0 @@
::: tip 提示
I am a tip
:::
@@ -1,3 +0,0 @@
::: tip
I am a tip
:::
@@ -1,3 +0,0 @@
::: v-pre
I am a v-pre
:::
@@ -1,3 +0,0 @@
::: warning
I am a warning
:::
@@ -1,36 +0,0 @@
const { createApp } = require('@vuepress/core')
const { getFragments } = require('@vuepress/test-utils')
import containerPlugin from '..'
describe('containers', async () => {
let app
beforeAll(async () => {
app = createApp()
app.options.siteConfig = {
plugins: [
[containerPlugin, { type: 'tip' }],
[containerPlugin, { type: 'warning' }],
[containerPlugin, { type: 'danger' }],
[containerPlugin, {
type: 'slot',
before: info => `<template slot="${info}">`,
after: '</template>'
}],
[containerPlugin, {
type: 'v-pre',
before: '<div v-pre>',
after: '</div>'
}]
]
}
return app.process()
})
getFragments(__dirname).forEach(({ name, content: input }) => {
test(name, () => {
const { html } = app.markdown.render(input)
expect(html).toMatchSnapshot()
})
})
})
@@ -1,50 +0,0 @@
const container = require('markdown-it-container')
function call (target, ...args) {
if (typeof target === 'function') {
return target(...args)
} else {
return target
}
}
module.exports = (options, context) => ({
name: require('./package').name,
multiple: true,
extendMarkdown (md) {
const {
validate,
marker,
before,
after,
type = '',
defaultTitle = type.toUpperCase()
} = options
if (!type) return
let { render } = options
if (!render) {
if (before !== undefined && after !== undefined) {
render = (tokens, index) => {
const info = tokens[index].info.trim().slice(type.length).trim()
return tokens[index].nesting === 1 ? call(before, info) : call(after, info)
}
} else {
render = (tokens, index) => {
const token = tokens[index]
let title = token.info.trim().slice(type.length).trim() || defaultTitle
if (title) title = `<p class="custom-block-title">${title}</p>`
if (token.nesting === 1) {
return `<div class="${type} custom-block">${title}\n`
} else {
return `</div>\n`
}
}
}
}
md.use(container, type, { render, validate, marker })
}
})
@@ -1,32 +0,0 @@
{
"name": "@vuepress/plugin-container",
"version": "1.0.0-alpha.42",
"description": "markdown container plugin for vuepress",
"main": "index.js",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vuepress.git",
"directory": "packages/@vuepress/plugin-container"
},
"keywords": [
"documentation",
"vue",
"vuepress",
"generator"
],
"dependencies": {
"markdown-it-container": "^2.0.0"
},
"devDependencies": {
"@vuepress/test-utils": "1.0.0-alpha.42"
},
"author": "Shigma <1700011071@pku.edu.cn>",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vuepress/issues"
},
"homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/plugin-container#readme"
}
@@ -2,4 +2,4 @@
> Google analytics plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-google-analytics.html).
See [documentation](https://v1.vuepress.vuejs.org/plugin/official/plugin-google-analytics.html).
@@ -1,6 +1,6 @@
{
"name": "@vuepress/plugin-google-analytics",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "google-analytics plugin for vuepress",
"main": "index.js",
"publishConfig": {
@@ -1,3 +0,0 @@
__tests__
__mocks__
.temp
@@ -1,5 +0,0 @@
# @vuepress/plugin-i18n-ui
> i18n-ui plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-i18n-ui.html).
@@ -1,5 +0,0 @@
import Layout from './index.vue'
export default ({ Vue }) => {
Vue.component('I18nUILayout', Layout)
}
@@ -1,21 +0,0 @@
const { path } = require('@vuepress/shared-utils')
module.exports = (pluginOptions = {}, context) => ({
name: 'i18n-ui',
// This plugin will be enabled only at development mode.
enabled: !context.isProd,
enhanceAppFiles: [
path.resolve(__dirname, 'client.js')
],
additionalPages: [
{
permalink: pluginOptions.permalink || '/i18n/',
frontmatter: {
'layout': 'I18nUILayout'
}
}
]
})
-154
View File
@@ -1,154 +0,0 @@
<template>
<div class="theme-container" id="vuepress-plugin-i18n-ui">
<div class="tool-box">
<span class="select-lang">Language:&nbsp;</span>
<select>
<option v-for="locale in localeList">
{{ locale.label + '(' + locale.url + ')'}}
</option>
</select>
<span class="select-page">Page:&nbsp;</span>
<select @change="handlePageChange">
<option v-for="page in pages">{{ page.path }}</option>
</select>
</div>
<div class="helper-content">
<div id="left">
<transition name="slide-left">
<Content :page-key="key"/>
</transition>
</div>
<div id="right">
<transition name="slide-left">
<Content :page-key="rightKey"/>
</transition>
</div>
</div>
</div>
</template>
<script>
import { findPageForPath } from '@app/util'
export default {
data () {
return {
currentPagePath: '/'
}
},
mounted () {
syncScroll()
},
computed: {
key () {
return this.currentPage.key
},
currentPage () {
return findPageForPath(this.$site.pages, this.currentPagePath)
},
rightKey () {
return this.rightPage.key
},
rightPage () {
return findPageForPath(this.$site.pages, this.rightLocale + this.currentPagePath.slice(1))
},
rightLocale () {
return this.localeList[0].url
},
localeList () {
const locales = this.$site.themeConfig.locales
const localeList = []
Object.keys(locales).forEach(url => {
if (url !== '/') {
localeList.push(Object.assign({ url }, locales[url]))
}
})
return localeList
},
pages () {
return this.$site.pages
.filter(page => this.localeList.every(locale => page.path.indexOf(locale.url) !== 0))
.filter(page => page.path !== '/translation/')
}
},
methods: {
handlePageChange (e) {
this.currentPagePath = e.target.value
}
}
}
function syncScroll () {
const left = document.querySelector('#left')
const right = document.querySelector('#right')
function getOther (el) {
if (el === left) return right
return left
}
function onScroll (e) {
const el = e.target
const other = getOther(el)
other.removeEventListener('scroll', onScroll)
const percentage = el.scrollTop / (el.scrollHeight - el.offsetHeight)
other.scrollTop = percentage * (other.scrollHeight - other.offsetHeight)
setTimeout(() => other.addEventListener('scroll', onScroll, false), 10)
}
left.addEventListener('scroll', onScroll, false)
right.addEventListener('scroll', onScroll, false)
}
</script>
<style lang="stylus" scoped>
#vuepress-plugin-i18n-ui
.helper-content
position relative
.tool-box
height 4rem
line-height 4rem
text-align center
.select-lang ~ select
margin-right 10px
#left, #right
padding 70px
box-sizing border-box
position absolute
top 0
width 50%
min-height 100px
max-height calc(100vh - 3.6rem - 4rem)
overflow scroll
#left
left 0
#right
left 50%
.slide-left-enter-active
transition all .5s
opacity 1
.slide-left-enter
opacity 0
position absolute !important
transform translate(-5%) !important
.slide-left-leave-to
opacity 0
position absolute !important
transform: translate(5%) !important
</style>
@@ -1,26 +0,0 @@
{
"name": "@vuepress/plugin-i18n-ui",
"version": "1.0.0-alpha.42",
"description": "i18n-ui plugin for vuepress",
"main": "index.js",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vuepress.git",
"directory": "packages/@vuepress/plugin-i18n-ui"
},
"keywords": [
"documentation",
"vue",
"vuepress",
"generator"
],
"author": "ULIVZ <chl814@foxmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vuepress/issues"
},
"homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/plugin-i18n-ui#readme"
}
@@ -2,4 +2,4 @@
> last-updated plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-last-updated.html).
See [documentation](https://v1.vuepress.vuejs.org/plugin/official/plugin-last-updated.html).
@@ -1,6 +1,6 @@
{
"name": "@vuepress/plugin-last-updated",
"version": "1.0.0-alpha.42",
"version": "1.0.4",
"description": "last-updated plugin for vuepress",
"main": "index.js",
"publishConfig": {
@@ -2,4 +2,4 @@
> medium-zoom plugin for vuepress
See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-medium-zoom.html).
See [documentation](https://v1.vuepress.vuejs.org/plugin/official/plugin-medium-zoom.html).
@@ -1,4 +1,4 @@
/* global SELECTOR */
/* global SELECTOR, OPTIONS */
import './style.css'
import zoom from 'medium-zoom'
@@ -20,7 +20,7 @@ export default {
if (this.zoom) {
this.zoom.detach()
}
this.zoom = zoom(SELECTOR)
this.zoom = zoom(SELECTOR, OPTIONS)
}, 1000)
}
}

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