├── .all-contributorsrc ├── .commitlintrc.js ├── .dependabot └── config.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── semantic.yml └── workflows │ └── pull-request-ci.yml ├── .gitignore ├── .gitpod.yml ├── .npmignore ├── .vscode ├── extensions.json └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── __mocks__ ├── @org │ ├── vuepress-plugin-a.js │ ├── vuepress-plugin-b.js │ └── vuepress-theme-a │ │ └── index.js ├── @vuepress │ ├── plugin-a.js │ └── theme-a │ │ └── index.js ├── vuepress-plugin-a.js ├── vuepress-plugin-b.js ├── vuepress-theme-a │ └── index.js ├── vuepress-theme-child │ ├── Layout.vue │ ├── components │ │ └── Home.vue │ └── index.js ├── vuepress-theme-parent │ ├── Layout.vue │ ├── components │ │ ├── Home.vue │ │ └── Sidebar.vue │ └── index.js └── vuepress-theme-without-index │ ├── Layout.vue │ ├── index.js │ └── package.json ├── art ├── VuePress-Icon.ai ├── hero.psd └── vuepress-icon.svg ├── babel.config.js ├── changelog ├── 1.9.2.md └── assets │ └── showcase.png ├── lerna.json ├── package.json ├── packages ├── @vuepress │ ├── core │ │ ├── .npmignore │ │ ├── README.md │ │ ├── lib │ │ │ ├── client │ │ │ │ ├── app.js │ │ │ │ ├── clientEntry.js │ │ │ │ ├── components │ │ │ │ │ ├── ClientOnly.js │ │ │ │ │ ├── Content.js │ │ │ │ │ ├── ContentSlotsDistributor.js │ │ │ │ │ ├── GlobalLayout.vue │ │ │ │ │ ├── NotFound.vue │ │ │ │ │ └── OutboundLink.vue │ │ │ │ ├── dataMixin.js │ │ │ │ ├── index.dev.html │ │ │ │ ├── index.ssr.html │ │ │ │ ├── plugins │ │ │ │ │ ├── Store.d.ts │ │ │ │ │ ├── Store.js │ │ │ │ │ ├── VuePress.d.ts │ │ │ │ │ └── VuePress.js │ │ │ │ ├── redirect.js │ │ │ │ ├── root-mixins │ │ │ │ │ └── updateMeta.js │ │ │ │ ├── serverEntry.js │ │ │ │ ├── style │ │ │ │ │ └── config.styl │ │ │ │ └── util.js │ │ │ ├── eject.js │ │ │ ├── index.js │ │ │ └── node │ │ │ │ ├── App.js │ │ │ │ ├── CacheLoader.js │ │ │ │ ├── ClientComputedMixin.js │ │ │ │ ├── Page.js │ │ │ │ ├── __tests__ │ │ │ │ ├── plugin-api │ │ │ │ │ ├── AsyncOption.spec.js │ │ │ │ │ ├── Option.spec.js │ │ │ │ │ ├── PluginAPI.spec.js │ │ │ │ │ └── PluginUtil.spec.js │ │ │ │ ├── prepare │ │ │ │ │ ├── App.spec.js │ │ │ │ │ ├── Page.spec.js │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ │ └── Page.spec.js.snap │ │ │ │ │ ├── fixtures │ │ │ │ │ │ ├── docs-config │ │ │ │ │ │ │ ├── .vuepress │ │ │ │ │ │ │ │ └── config.js │ │ │ │ │ │ │ └── README.md │ │ │ │ │ │ ├── docs-dep-theme-without-index │ │ │ │ │ │ │ ├── .vuepress │ │ │ │ │ │ │ │ └── config.js │ │ │ │ │ │ │ └── README.md │ │ │ │ │ │ ├── docs-i18n │ │ │ │ │ │ │ ├── .vuepress │ │ │ │ │ │ │ │ └── config.js │ │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ │ └── zh │ │ │ │ │ │ │ │ └── README.md │ │ │ │ │ │ ├── docs-local-theme │ │ │ │ │ │ │ ├── .vuepress │ │ │ │ │ │ │ │ ├── config.js │ │ │ │ │ │ │ │ └── theme │ │ │ │ │ │ │ │ │ └── Layout.vue │ │ │ │ │ │ │ └── README.md │ │ │ │ │ │ ├── docs-patterns │ │ │ │ │ │ │ ├── .vuepress │ │ │ │ │ │ │ │ └── config.js │ │ │ │ │ │ │ └── README.md │ │ │ │ │ │ └── docs │ │ │ │ │ │ │ ├── 2020-01-01-date.md │ │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ │ ├── alpha.md │ │ │ │ │ │ │ └── excerpt.md │ │ │ │ │ └── util.js │ │ │ │ └── theme-api │ │ │ │ │ ├── fixtures │ │ │ │ │ └── theme │ │ │ │ │ │ ├── Layout.vue │ │ │ │ │ │ └── components │ │ │ │ │ │ └── Home.vue │ │ │ │ │ └── index.spec.js │ │ │ │ ├── build │ │ │ │ └── index.js │ │ │ │ ├── createMarkdown.js │ │ │ │ ├── createTemp.js │ │ │ │ ├── dev │ │ │ │ └── index.js │ │ │ │ ├── docs.fallback │ │ │ │ ├── .vuepress │ │ │ │ │ └── theme │ │ │ │ │ │ └── Layout.vue │ │ │ │ └── README.md │ │ │ │ ├── internal-plugins │ │ │ │ ├── dataBlock │ │ │ │ │ ├── index.js │ │ │ │ │ └── loader.js │ │ │ │ ├── enhanceApp.js │ │ │ │ ├── frontmatterBlock │ │ │ │ │ ├── index.js │ │ │ │ │ └── loader.js │ │ │ │ ├── layoutComponents.js │ │ │ │ ├── pageComponents.js │ │ │ │ ├── palette │ │ │ │ │ └── index.js │ │ │ │ ├── rootMixins.js │ │ │ │ ├── routes.js │ │ │ │ ├── siteData.js │ │ │ │ ├── style │ │ │ │ │ ├── client.js │ │ │ │ │ └── index.js │ │ │ │ └── transformModule.js │ │ │ │ ├── loadConfig.js │ │ │ │ ├── loadTheme.js │ │ │ │ ├── plugin-api │ │ │ │ ├── abstract │ │ │ │ │ ├── AsyncOption.js │ │ │ │ │ └── Option.js │ │ │ │ ├── constants.js │ │ │ │ ├── index.js │ │ │ │ ├── override │ │ │ │ │ ├── AliasOption.js │ │ │ │ │ ├── ClientDynamicModulesOption.js │ │ │ │ │ ├── DefineOption.js │ │ │ │ │ ├── EnhanceAppFilesOption.js │ │ │ │ │ ├── GlobalUIComponentsOption.js │ │ │ │ │ └── instantiateOption.js │ │ │ │ └── util.js │ │ │ │ ├── theme-api │ │ │ │ ├── Layout.fallback.vue │ │ │ │ └── index.js │ │ │ │ ├── util │ │ │ │ └── index.js │ │ │ │ └── webpack │ │ │ │ ├── ClientPlugin.js │ │ │ │ ├── DevLogPlugin.js │ │ │ │ ├── HeadPlugin.js │ │ │ │ ├── createBaseConfig.js │ │ │ │ ├── createClientConfig.js │ │ │ │ ├── createServerConfig.js │ │ │ │ └── noopModule.js │ │ └── package.json │ ├── markdown-loader │ │ ├── .npmignore │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── markdown │ │ ├── .npmignore │ │ ├── README.md │ │ ├── __tests__ │ │ │ ├── __snapshots__ │ │ │ │ ├── highlight.spec.js.snap │ │ │ │ ├── highlightLines.spec.js.snap │ │ │ │ ├── hoist.spec.js.snap │ │ │ │ ├── lineNumers.spec.js.snap │ │ │ │ ├── link.spec.js.snap │ │ │ │ ├── preWrapper.spec.js.snap │ │ │ │ └── snippet.spec.js.snap │ │ │ ├── fragments │ │ │ │ ├── Dockerfile │ │ │ │ ├── code-highlightLines-multiple.md │ │ │ │ ├── code-highlightLines-single.md │ │ │ │ ├── code-prewrapper-with-double-quotation-marks.md │ │ │ │ ├── code-prewrapper-with-quotes.md │ │ │ │ ├── code-prewrapper-with-spaces.md │ │ │ │ ├── code-snippet-highlightLines-multiple.md │ │ │ │ ├── code-snippet-highlightLines-single-and-multiple.md │ │ │ │ ├── code-snippet-highlightLines-single.md │ │ │ │ ├── code-snippet-with-indented-region.md │ │ │ │ ├── code-snippet-with-region-and-highlight.md │ │ │ │ ├── code-snippet-with-region-and-single-highlight.md │ │ │ │ ├── code-snippet-with-region.md │ │ │ │ ├── code-snippet-with-space-in-path.md │ │ │ │ ├── code-snippet.md │ │ │ │ ├── code.md │ │ │ │ ├── hoist.md │ │ │ │ ├── snippet with spaces.js │ │ │ │ ├── snippet-with-indented-region.html │ │ │ │ ├── snippet-with-region.js │ │ │ │ └── snippet.js │ │ │ ├── highlight.spec.js │ │ │ ├── highlightLines.spec.js │ │ │ ├── hoist.spec.js │ │ │ ├── lineNumers.spec.js │ │ │ ├── link.spec.js │ │ │ ├── preWrapper.spec.js │ │ │ ├── slugify.spec.js │ │ │ ├── snippet.spec.js │ │ │ └── util.js │ │ ├── index.js │ │ ├── lib │ │ │ ├── component.js │ │ │ ├── constant.js │ │ │ ├── highlight.js │ │ │ ├── highlightLines.js │ │ │ ├── hoist.js │ │ │ ├── lineNumbers.js │ │ │ ├── link.js │ │ │ ├── preWrapper.js │ │ │ └── snippet.js │ │ └── package.json │ ├── plugin-active-header-links │ │ ├── .npmignore │ │ ├── README.md │ │ ├── clientRootMixin.js │ │ ├── index.js │ │ └── package.json │ ├── plugin-back-to-top │ │ ├── .npmignore │ │ ├── BackToTop.vue │ │ ├── README.md │ │ ├── enhanceAppFile.js │ │ ├── index.js │ │ └── package.json │ ├── plugin-google-analytics │ │ ├── .npmignore │ │ ├── README.md │ │ ├── enhanceAppFile.js │ │ ├── index.js │ │ └── package.json │ ├── plugin-last-updated │ │ ├── .npmignore │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── plugin-medium-zoom │ │ ├── .npmignore │ │ ├── README.md │ │ ├── clientRootMixin.js │ │ ├── index.js │ │ ├── package.json │ │ └── style.css │ ├── plugin-nprogress │ │ ├── .npmignore │ │ ├── README.md │ │ ├── clientRootMixin.js │ │ ├── enhanceAppFile.js │ │ ├── index.js │ │ ├── nprogress.styl │ │ └── package.json │ ├── plugin-pwa │ │ ├── .npmignore │ │ ├── README.md │ │ ├── index.js │ │ ├── lib │ │ │ ├── SWUpdateEvent.js │ │ │ ├── SWUpdatePopup.vue │ │ │ ├── enhanceAppFile.js │ │ │ ├── event.js │ │ │ ├── i18n.js │ │ │ └── skip-waiting.js │ │ └── package.json │ ├── plugin-register-components │ │ ├── .npmignore │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── plugin-search │ │ ├── .npmignore │ │ ├── README.md │ │ ├── SearchBox.vue │ │ ├── __tests__ │ │ │ └── matchQuery.spec.js │ │ ├── index.js │ │ ├── match-query.js │ │ ├── package.json │ │ └── search.svg │ ├── shared-utils │ │ ├── .npmignore │ │ ├── README.md │ │ ├── __tests__ │ │ │ ├── deeplyParseHeaders.spec.ts │ │ │ ├── fileToPath.spec.ts │ │ │ ├── fixtures │ │ │ │ ├── plugin-a.js │ │ │ │ └── theme-a │ │ │ │ │ └── index.js │ │ │ ├── isIndexFile.spec.ts │ │ │ ├── moduleResolver.spec.ts │ │ │ ├── parseHeaders.spec.ts │ │ │ ├── removeNonCodeWrappedHTML.spec.ts │ │ │ ├── slugify.spec.ts │ │ │ └── unescapeHtml.spec.ts │ │ ├── package.json │ │ ├── scripts │ │ │ └── update-index.js │ │ ├── src │ │ │ ├── codegen.ts │ │ │ ├── compose.ts │ │ │ ├── datatypes.ts │ │ │ ├── deeplyParseHeaders.ts │ │ │ ├── ensureEndingSlash.ts │ │ │ ├── ensureLeadingSlash.ts │ │ │ ├── env.ts │ │ │ ├── extractHeaders.ts │ │ │ ├── fallback.ts │ │ │ ├── fileToPath.ts │ │ │ ├── getPermalink.ts │ │ │ ├── index.ts │ │ │ ├── inferTitle.ts │ │ │ ├── isIndexFile.ts │ │ │ ├── logger.ts │ │ │ ├── moduleLoader.ts │ │ │ ├── moduleResolver.ts │ │ │ ├── normalizeConfig.ts │ │ │ ├── parseEmojis.ts │ │ │ ├── parseFrontmatter.ts │ │ │ ├── parseHeaders.ts │ │ │ ├── parseVueFrontmatter.ts │ │ │ ├── performance.ts │ │ │ ├── removeNonCodeWrappedHTML.ts │ │ │ ├── slugify.ts │ │ │ ├── sort.ts │ │ │ ├── toAbsolutePath.ts │ │ │ ├── tryChain.ts │ │ │ └── unescapeHtml.ts │ │ └── tsconfig.json │ ├── test-utils │ │ ├── .npmignore │ │ ├── README.md │ │ ├── client │ │ │ ├── createLocalVue.js │ │ │ ├── index.js │ │ │ ├── mockComponent.js │ │ │ └── siteData.js │ │ ├── fixtures │ │ │ └── docs │ │ │ │ ├── .vuepress │ │ │ │ └── theme │ │ │ │ │ └── Layout.vue │ │ │ │ └── README.md │ │ ├── index.js │ │ ├── lib │ │ │ ├── createJestConfig.js │ │ │ ├── createJestRunner.js │ │ │ ├── getFragment.js │ │ │ ├── getFragments.js │ │ │ └── jest.config.js │ │ └── package.json │ ├── theme-default │ │ ├── .npmignore │ │ ├── README.md │ │ ├── __tests__ │ │ │ └── components │ │ │ │ ├── DropdownLink.spec.js │ │ │ │ ├── NavLink.spec.js │ │ │ │ └── __snapshots__ │ │ │ │ ├── DropdownLink.spec.js.snap │ │ │ │ └── NavLink.spec.js.snap │ │ ├── components │ │ │ ├── AlgoliaSearchBox.vue │ │ │ ├── DropdownLink.vue │ │ │ ├── DropdownTransition.vue │ │ │ ├── Home.vue │ │ │ ├── NavLink.vue │ │ │ ├── NavLinks.vue │ │ │ ├── Navbar.vue │ │ │ ├── Page.vue │ │ │ ├── PageEdit.vue │ │ │ ├── PageNav.vue │ │ │ ├── Sidebar.vue │ │ │ ├── SidebarButton.vue │ │ │ ├── SidebarGroup.vue │ │ │ ├── SidebarLink.vue │ │ │ └── SidebarLinks.vue │ │ ├── global-components │ │ │ ├── Badge.vue │ │ │ ├── CodeBlock.vue │ │ │ └── CodeGroup.vue │ │ ├── index.js │ │ ├── layouts │ │ │ ├── 404.vue │ │ │ └── Layout.vue │ │ ├── noopModule.js │ │ ├── package.json │ │ ├── styles │ │ │ ├── arrow.styl │ │ │ ├── code.styl │ │ │ ├── config.styl │ │ │ ├── custom-blocks.styl │ │ │ ├── index.styl │ │ │ ├── mobile.styl │ │ │ ├── toc.styl │ │ │ └── wrapper.styl │ │ └── util │ │ │ └── index.js │ ├── theme-vue │ │ ├── .npmignore │ │ ├── README.md │ │ ├── components │ │ │ ├── BuySellAds.vue │ │ │ └── CarbonAds.vue │ │ ├── index.js │ │ ├── layouts │ │ │ └── Layout.vue │ │ └── package.json │ └── types │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── package.json │ │ ├── src │ │ ├── config.ts │ │ ├── context.ts │ │ ├── index.ts │ │ ├── lang.ts │ │ ├── locale.ts │ │ ├── markdown.ts │ │ ├── official-plugins.ts │ │ ├── plugin-api.ts │ │ ├── plugin.ts │ │ ├── shared.ts │ │ ├── site-data.ts │ │ ├── style.ts │ │ ├── theme-default.ts │ │ ├── theme.ts │ │ └── third-party-plugins.ts │ │ └── tsconfig.json ├── docs │ ├── .remarkrc │ ├── .textlintrc.js │ ├── docs │ │ ├── .vuepress │ │ │ ├── components │ │ │ │ ├── Foo │ │ │ │ │ └── Bar.vue │ │ │ │ ├── OtherComponent.vue │ │ │ │ ├── UpgradePath.vue │ │ │ │ ├── demo-1.vue │ │ │ │ ├── diagram-markdown-slot-relationship.vue │ │ │ │ └── svg-container.vue │ │ │ ├── config.ts │ │ │ ├── config │ │ │ │ ├── index.ts │ │ │ │ ├── nav │ │ │ │ │ ├── en.ts │ │ │ │ │ └── zh.ts │ │ │ │ └── sidebar │ │ │ │ │ ├── en.ts │ │ │ │ │ ├── shared.ts │ │ │ │ │ └── zh.ts │ │ │ ├── enhanceApp.js │ │ │ ├── images │ │ │ │ └── logo.png │ │ │ ├── public │ │ │ │ ├── architecture.png │ │ │ │ ├── assets │ │ │ │ │ ├── 1.9-lang.png │ │ │ │ │ ├── 1.9-official-plugin-options.png │ │ │ │ │ ├── 1.9-official-plugin-tuple-usage.png │ │ │ │ │ └── 1.9-overview.png │ │ │ │ ├── hero.png │ │ │ │ ├── icons │ │ │ │ │ ├── android-chrome-192x192.png │ │ │ │ │ ├── android-chrome-512x512.png │ │ │ │ │ ├── apple-touch-icon-120x120.png │ │ │ │ │ ├── apple-touch-icon-152x152.png │ │ │ │ │ ├── apple-touch-icon-180x180.png │ │ │ │ │ ├── apple-touch-icon-60x60.png │ │ │ │ │ ├── apple-touch-icon-76x76.png │ │ │ │ │ ├── apple-touch-icon.png │ │ │ │ │ ├── favicon-16x16.png │ │ │ │ │ ├── favicon-32x32.png │ │ │ │ │ ├── msapplication-icon-144x144.png │ │ │ │ │ ├── mstile-150x150.png │ │ │ │ │ └── safari-pinned-tab.svg │ │ │ │ ├── line-numbers-desktop.png │ │ │ │ ├── line-numbers-mobile.gif │ │ │ │ ├── logo.png │ │ │ │ ├── manifest.json │ │ │ │ └── plugin.png │ │ │ └── styles │ │ │ │ ├── index.styl │ │ │ │ └── palette.styl │ │ ├── api │ │ │ ├── cli.md │ │ │ └── node.md │ │ ├── config │ │ │ └── README.md │ │ ├── faq │ │ │ └── README.md │ │ ├── guide │ │ │ ├── README.md │ │ │ ├── assets.md │ │ │ ├── basic-config.md │ │ │ ├── deploy.md │ │ │ ├── directory-structure.md │ │ │ ├── frontmatter.md │ │ │ ├── getting-started.md │ │ │ ├── global-computed.md │ │ │ ├── i18n.md │ │ │ ├── markdown-slot.md │ │ │ ├── markdown.md │ │ │ ├── permalinks.md │ │ │ ├── typescript-as-config.md │ │ │ └── using-vue.md │ │ ├── index.md │ │ ├── miscellaneous │ │ │ ├── design-concepts.md │ │ │ ├── glossary.md │ │ │ ├── local-development.md │ │ │ └── migration-guide.md │ │ ├── plugin │ │ │ ├── README.md │ │ │ ├── context-api.md │ │ │ ├── life-cycle.md │ │ │ ├── official │ │ │ │ ├── plugin-active-header-links.md │ │ │ │ ├── plugin-back-to-top.md │ │ │ │ ├── plugin-blog.md │ │ │ │ ├── plugin-google-analytics.md │ │ │ │ ├── plugin-last-updated.md │ │ │ │ ├── plugin-medium-zoom.md │ │ │ │ ├── plugin-nprogress.md │ │ │ │ ├── plugin-pwa.md │ │ │ │ ├── plugin-register-components.md │ │ │ │ └── plugin-search.md │ │ │ ├── option-api.md │ │ │ ├── using-a-plugin.md │ │ │ └── writing-a-plugin.md │ │ ├── theme │ │ │ ├── README.md │ │ │ ├── blog-theme.md │ │ │ ├── default-theme-config.md │ │ │ ├── inheritance.md │ │ │ ├── option-api.md │ │ │ ├── using-a-theme.md │ │ │ └── writing-a-theme.md │ │ └── zh │ │ │ ├── README.md │ │ │ ├── api │ │ │ ├── cli.md │ │ │ └── node.md │ │ │ ├── config │ │ │ └── README.md │ │ │ ├── faq │ │ │ └── README.md │ │ │ ├── guide │ │ │ ├── README.md │ │ │ ├── assets.md │ │ │ ├── basic-config.md │ │ │ ├── deploy.md │ │ │ ├── directory-structure.md │ │ │ ├── frontmatter.md │ │ │ ├── getting-started.md │ │ │ ├── global-computed.md │ │ │ ├── i18n.md │ │ │ ├── markdown-slot.md │ │ │ ├── markdown.md │ │ │ ├── permalinks.md │ │ │ ├── typescript-as-config.md │ │ │ └── using-vue.md │ │ │ ├── miscellaneous │ │ │ ├── design-concepts.md │ │ │ ├── glossary.md │ │ │ ├── local-development.md │ │ │ └── migration-guide.md │ │ │ ├── plugin │ │ │ ├── README.md │ │ │ ├── context-api.md │ │ │ ├── life-cycle.md │ │ │ ├── official │ │ │ │ ├── plugin-active-header-links.md │ │ │ │ ├── plugin-back-to-top.md │ │ │ │ ├── plugin-blog.md │ │ │ │ ├── plugin-google-analytics.md │ │ │ │ ├── plugin-last-updated.md │ │ │ │ ├── plugin-medium-zoom.md │ │ │ │ ├── plugin-nprogress.md │ │ │ │ ├── plugin-pwa.md │ │ │ │ ├── plugin-register-components.md │ │ │ │ └── plugin-search.md │ │ │ ├── option-api.md │ │ │ ├── using-a-plugin.md │ │ │ └── writing-a-plugin.md │ │ │ └── theme │ │ │ ├── README.md │ │ │ ├── blog-theme.md │ │ │ ├── default-theme-config.md │ │ │ ├── inheritance.md │ │ │ ├── option-api.md │ │ │ ├── using-a-theme.md │ │ │ └── writing-a-theme.md │ └── package.json └── vuepress │ ├── README.md │ ├── cli.js │ ├── config.d.ts │ ├── config.js │ ├── index.js │ ├── lib │ ├── checkEnv.js │ ├── handleUnknownCommand.js │ ├── registerCoreCommands.js │ └── util.js │ └── package.json ├── rfcs ├── 002.plugin-git-log.md ├── README.md └── template.md ├── scripts ├── bootstrap.js ├── jest.config.js ├── remote-version.js └── test.js ├── tsconfig.json └── yarn.lock /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | 4 | const vuepressPackages = fs.readdirSync(path.resolve(__dirname, 'packages/@vuepress')) 5 | const availableScopes = [ 6 | 'all', 7 | 'cli', 8 | 'zh', 9 | 'types', 10 | ...vuepressPackages 11 | ] 12 | 13 | module.exports = { 14 | extends: [ 15 | '@commitlint/config-conventional' 16 | ], 17 | rules: { 18 | 'scope-enum': [ 19 | 2, 20 | 'always', 21 | [ 22 | ...availableScopes, 23 | ...availableScopes.map(name => `$${name}`) 24 | ] 25 | ] 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | # Keep package.json (& lockfiles) up to date as soon as 4 | # new versions are published to the npm registry 5 | - package_manager: "javascript" 6 | directory: "/" 7 | update_schedule: "live" 8 | # Apply default reviewer and label to created 9 | # pull requests 10 | default_reviewers: 11 | - "bencodezen" 12 | default_labels: 13 | - "dependencies" 14 | commit_message: 15 | prefix: "fix" 16 | prefix_development: "chore" 17 | include_scope: true 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | !.eslintrc.js 3 | !.commitlintrc.js 4 | !.vuepress 5 | packages/@vuepress/shared-utils/lib 6 | packages/@vuepress/shared-utils/types 7 | packages/@vuepress/types 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | extends: [ 5 | 'plugin:vue-libs/recommended', 6 | 'plugin:vue/recommended' 7 | ], 8 | 9 | rules: { 10 | indent: ['error', 2, { MemberExpression: 'off' }], 11 | 12 | 'no-undef': ['error'], 13 | 14 | 'operator-linebreak': ['error', 'before'], 15 | 16 | 'vue/match-component-file-name': [ 17 | 'error', 18 | { 19 | extensions: ['js', 'vue'], 20 | shouldMatchCase: false 21 | } 22 | ] 23 | }, 24 | 25 | overrides: [ 26 | { 27 | files: ['*.ts'], 28 | extends: [ 29 | 'plugin:@typescript-eslint/recommended' 30 | ], 31 | parser: 'vue-eslint-parser', 32 | parserOptions: { 33 | parser: '@typescript-eslint/parser' 34 | }, 35 | rules: { 36 | 'no-useless-constructor': 'off' 37 | } 38 | }, 39 | { 40 | files: [ 41 | '**/__tests__/**/*.spec.js', 42 | '**/__tests__/**/*.spec.ts' 43 | ], 44 | extends: ['plugin:jest/recommended'] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ulivz # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: ulivz # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with a single custom sponsorship URL 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | - [ ] I confirm that this is an issue rather than a question. 15 | 16 | 17 | 18 | 19 | 20 | 21 | ## Bug report 22 | 23 | #### Steps to reproduce 24 | 25 | 26 | 27 | 28 | 29 | #### What is expected? 30 | 31 | #### What is actually happening? 32 | 33 | #### Other relevant information 34 | 35 | - Output of `npx vuepress info` in my VuePress project: 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | 8 | 9 | 10 | ## Feature request 11 | 12 | 13 | 14 | 15 | 16 | #### What problem does this feature solve? 17 | 18 | #### What does the proposed API look like? 19 | 20 | #### How should this be implemented in your opinion? 21 | 22 | #### Are you willing to work on this yourself? 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | **Summary** 7 | 8 | **What kind of change does this PR introduce?** (check at least one) 9 | 10 | - [ ] Bugfix 11 | - [ ] Feature 12 | - [ ] Code style update 13 | - [ ] Refactor 14 | - [ ] Docs 15 | - [ ] Build-related changes 16 | - [ ] Other, please describe: 17 | 18 | If changing the UI of default theme, please provide the **before/after** screenshot: 19 | 20 | **Does this PR introduce a breaking change?** (check one) 21 | 22 | - [ ] Yes 23 | - [ ] No 24 | 25 | If yes, please describe the impact and migration path for existing applications: 26 | 27 | **The PR fulfills these requirements:** 28 | 29 | - [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number) 30 | 31 | You have tested in the following browsers: (Providing a detailed version will be better.) 32 | 33 | - [ ] Chrome 34 | - [ ] Firefox 35 | - [ ] Safari 36 | - [ ] Edge 37 | - [ ] IE 38 | 39 | If adding a **new feature**, the PR's description includes: 40 | 41 | - [ ] A convincing reason for adding this feature 42 | - [ ] Related documents have been updated 43 | - [ ] Related tests have been updated 44 | 45 | To avoid wasting your time, it's best to open a **feature request issue** first and wait for approval before working on it. 46 | 47 | **Other information:** 48 | -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | titleOnly: true 2 | allowMergeCommits: false 3 | -------------------------------------------------------------------------------- /.github/workflows/pull-request-ci.yml: -------------------------------------------------------------------------------- 1 | name: Pull request workflow 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | pr: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-node@v2 12 | with: 13 | node-version: '14' 14 | check-latest: true 15 | - name: Get yarn cache directory path 16 | id: yarn-cache-dir-path 17 | run: echo "::set-output name=dir::$(yarn cache dir)" 18 | 19 | - uses: actions/cache@v2 20 | with: 21 | path: '**/node_modules' 22 | key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn 27 | 28 | - name: Run tsc 29 | run: yarn tsc 30 | 31 | - name: Run unit tests 32 | run: yarn test 33 | 34 | - name: Check linter 35 | run: yarn lint 36 | 37 | - name: Check markdown linter 38 | run: yarn workspace docs lint-md 39 | 40 | - name: Build vuepress 41 | run: yarn build -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # node modules 2 | node_modules 3 | 4 | # MacOS desktop services store 5 | .DS_Store 6 | 7 | # Log files 8 | *.log 9 | 10 | # Meta files 11 | TODOs.md 12 | 13 | # Editors 14 | .idea 15 | 16 | # VuePress temp directory 17 | .temp 18 | 19 | # Docs dist directory 20 | /vuepress 21 | 22 | # Typescript build dist 23 | packages/@vuepress/shared-utils/lib/ 24 | packages/@vuepress/shared-utils/types/ 25 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | ports: 2 | - port: 8080 3 | onOpen: open-preview 4 | tasks: 5 | - init: yarn 6 | command: yarn dev 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Basic 2 | *.log 3 | .temp 4 | vuepress 5 | art 6 | docs 7 | .eslintrc.js 8 | yarn.lock 9 | TODOs.md 10 | .github 11 | .idea 12 | 13 | # CI related 14 | scripts 15 | 16 | # Test related 17 | test 18 | .babelrc 19 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "amour1688.ts-in-markdown", 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.validate": [ 3 | "javascript", 4 | "javascriptreact", 5 | "typescript", 6 | "typescriptreact", 7 | "html", 8 | "markdown" 9 | ], 10 | "editor.codeActionsOnSave": { 11 | "source.fixAll.eslint": true 12 | }, 13 | "search.exclude": { 14 | "**/.git": true, 15 | "**/.svn": true, 16 | "**/.hg": true, 17 | "**/CVS": true, 18 | "**/.DS_Store": true, 19 | "docs/docs/out/**": true, 20 | "packages/*/lib/**": true 21 | }, 22 | "typescript.tsdk": "node_modules/typescript/lib", 23 | "[typescript]": { 24 | "editor.defaultFormatter": "esbenp.prettier-vscode" 25 | }, 26 | "[typescriptreact]": { 27 | "editor.defaultFormatter": "esbenp.prettier-vscode" 28 | }, 29 | "[javascript]": { 30 | "editor.defaultFormatter": "esbenp.prettier-vscode" 31 | }, 32 | "[javascriptreact]": { 33 | "editor.defaultFormatter": "esbenp.prettier-vscode" 34 | }, 35 | "[markdown]": { 36 | "editor.quickSuggestions": { 37 | "other": true, 38 | "comments": true, 39 | "strings": true 40 | } 41 | }, 42 | "eslint.trace.server": "verbose", 43 | "cSpell.words": [ 44 | "commitlint", 45 | "monoo" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /__mocks__/@org/vuepress-plugin-a.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/@org/vuepress-plugin-b.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/@org/vuepress-theme-a/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/@vuepress/plugin-a.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/@vuepress/theme-a/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/vuepress-plugin-a.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/vuepress-plugin-b.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | multiple: true 3 | } 4 | -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-a/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-child/Layout.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-child/Layout.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-child/components/Home.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-child/components/Home.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-child/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extend: 'vuepress-theme-parent' 3 | } 4 | -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-parent/Layout.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-parent/Layout.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-parent/components/Home.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-parent/components/Home.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-parent/components/Sidebar.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-parent/components/Sidebar.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-parent/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-without-index/Layout.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/__mocks__/vuepress-theme-without-index/Layout.vue -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-without-index/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | // This file is just for jest. 3 | -------------------------------------------------------------------------------- /__mocks__/vuepress-theme-without-index/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuepress-theme-without-index", 3 | "main": "Layout.vue" 4 | } 5 | -------------------------------------------------------------------------------- /art/VuePress-Icon.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/art/VuePress-Icon.ai -------------------------------------------------------------------------------- /art/hero.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/art/hero.psd -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'test': { 4 | 'presets': [ 5 | ['@babel/preset-env', { 'targets': { 'node': 'current' }}] 6 | ], 7 | 'plugins': [ 8 | '@babel/plugin-syntax-dynamic-import', 9 | [ 10 | '@babel/plugin-proposal-class-properties', 11 | { 12 | 'loose': true 13 | } 14 | ] 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /changelog/assets/showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/changelog/assets/showcase.png -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "useWorkspaces": true, 4 | "version": "1.9.10", 5 | "command": { 6 | "version": { 7 | "allowBranch": "master", 8 | "exact": true, 9 | "ignoreChanges": [ 10 | "**/*.md" 11 | ], 12 | "message": "build: release version %v" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/@vuepress/core/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/core/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/core 2 | 3 | ## APIs 4 | 5 | ### dev(sourceDir, options) 6 | 7 | ### build(sourceDir, options) 8 | 9 | ### eject(targetDir) 10 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/clientEntry.js: -------------------------------------------------------------------------------- 1 | /* global VUEPRESS_VERSION, LAST_COMMIT_HASH*/ 2 | 3 | import { createApp } from './app' 4 | 5 | window.__VUEPRESS__ = { 6 | version: VUEPRESS_VERSION, 7 | hash: LAST_COMMIT_HASH 8 | } 9 | 10 | createApp(false /* isServer */).then(({ app, router }) => { 11 | router.onReady(() => { 12 | app.$mount('#app') 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/ClientOnly.js: -------------------------------------------------------------------------------- 1 | export default { 2 | functional: true, 3 | render (h, { parent, children }) { 4 | if (parent._isMounted) { 5 | return children 6 | } else { 7 | parent.$once('hook:mounted', () => { 8 | parent.$forceUpdate() 9 | }) 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/Content.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { setGlobalInfo, getPageAsyncComponent } from '@app/util' 3 | 4 | export default { 5 | props: { 6 | pageKey: String, 7 | slotKey: { 8 | type: String, 9 | default: 'default' 10 | } 11 | }, 12 | render (h) { 13 | const pageKey = this.pageKey || this.$parent.$page.key 14 | setGlobalInfo('pageKey', pageKey) 15 | 16 | /** 17 | * This is for use cases that render `` 18 | * with dynamic pageKey from current $page. 19 | */ 20 | if (!Vue.component(pageKey)) { 21 | Vue.component(pageKey, getPageAsyncComponent(pageKey)) 22 | } 23 | 24 | if (Vue.component(pageKey)) { 25 | return h(pageKey) 26 | } 27 | return h('') 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/ContentSlotsDistributor.js: -------------------------------------------------------------------------------- 1 | export default { 2 | functional: true, 3 | props: { 4 | slotKey: String, 5 | required: true 6 | }, 7 | render (h, { props, slots }) { 8 | return h('div', 9 | { 10 | class: [ 11 | `content__${props.slotKey}` 12 | ] 13 | }, 14 | slots()[props.slotKey] 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/GlobalLayout.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 35 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/NotFound.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/components/OutboundLink.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 36 | 37 | 46 | 47 | 59 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/dataMixin.js: -------------------------------------------------------------------------------- 1 | /* global VUEPRESS_TEMP_PATH */ 2 | 3 | import GLobalVue from 'vue' 4 | 5 | export default function dataMixin (I18n, siteData, Vue = GLobalVue) { 6 | prepare(siteData) 7 | Vue.$vuepress.$set('siteData', siteData) 8 | 9 | if (module.hot) { 10 | module.hot.accept(VUEPRESS_TEMP_PATH + '/internal/siteData.js', () => { 11 | prepare(siteData) 12 | Vue.$vuepress.$set('siteData', siteData) 13 | }) 14 | } 15 | 16 | const I18nConstructor = I18n(Vue.$vuepress.$get('siteData')) 17 | const i18n = new I18nConstructor() 18 | const descriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(i18n)) 19 | const computed = {} 20 | Object.keys(descriptors).reduce((computed, key) => { 21 | if (key.startsWith('$')) { 22 | computed[key] = descriptors[key].get 23 | } 24 | return computed 25 | }, computed) 26 | 27 | return { computed } 28 | } 29 | 30 | function prepare (siteData) { 31 | if (siteData.locales) { 32 | Object.keys(siteData.locales).forEach(path => { 33 | siteData.locales[path].path = path 34 | }) 35 | } 36 | Object.freeze(siteData) 37 | } 38 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/index.dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | 8 | {{{ userHeadTags }}} 9 | {{{ pageMeta }}} 10 | {{{ canonicalLink }}} 11 | {{{ renderResourceHints() }}} 12 | {{{ renderStyles() }}} 13 | 14 | 15 | 16 | {{{ renderScripts() }}} 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/plugins/Store.d.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export declare class Store { 4 | store: Vue; 5 | 6 | $get(key: string): any; 7 | 8 | $set(key: string, value: any): void; 9 | 10 | $emit: typeof Vue.prototype.$emit; 11 | 12 | $on: typeof Vue.prototype.$on; 13 | } 14 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/plugins/Store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export default class Store { 4 | constructor () { 5 | this.store = new Vue({ 6 | data: { 7 | state: {} 8 | } 9 | }) 10 | } 11 | 12 | $get (key) { 13 | return this.store.state[key] 14 | } 15 | 16 | $set (key, value) { 17 | Vue.set(this.store.state, key, value) 18 | } 19 | 20 | $emit (...args) { 21 | this.store.$emit(...args) 22 | } 23 | 24 | $on (...args) { 25 | this.store.$on(...args) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/plugins/VuePress.d.ts: -------------------------------------------------------------------------------- 1 | import { Store } from './Store' 2 | import { AsyncComponent } from 'vue' 3 | 4 | declare class VuePress extends Store { 5 | isPageExists (pageKey: string): boolean; 6 | 7 | isPageLoaded (pageKey: string): boolean; 8 | 9 | getPageAsyncComponent (pageKey: string): () => Promise; 10 | 11 | loadPageAsyncComponent (pageKey: string): Promise; 12 | 13 | registerPageAsyncComponent (pageKey: string): void; 14 | } 15 | 16 | declare module 'vue/types/vue' { 17 | export interface Vue { 18 | $vuepress: VuePress; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/plugins/VuePress.js: -------------------------------------------------------------------------------- 1 | import Store from './Store' 2 | import { 3 | getPageAsyncComponent, 4 | getLayoutAsyncComponent, 5 | getAsyncComponent, 6 | getVueComponent 7 | } from '../util' 8 | 9 | class VuePress extends Store {} 10 | 11 | Object.assign(VuePress.prototype, { 12 | getPageAsyncComponent, 13 | getLayoutAsyncComponent, 14 | getAsyncComponent, 15 | getVueComponent 16 | }) 17 | 18 | export default { 19 | install (Vue) { 20 | const ins = new VuePress() 21 | Vue.$vuepress = ins 22 | Vue.prototype.$vuepress = ins 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/serverEntry.js: -------------------------------------------------------------------------------- 1 | import { createApp } from './app' 2 | 3 | export default context => new Promise((resolve, reject) => { 4 | createApp(true /* isServer */).then(({ app, router }) => { 5 | const { url } = context 6 | const { fullPath } = router.resolve(url).route 7 | 8 | if (fullPath !== url) { 9 | return reject({ url: fullPath }) 10 | } 11 | 12 | // error handled in onReady 13 | router.push(url).catch(() => {}) 14 | router.onReady(() => resolve(app), reject) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/client/style/config.styl: -------------------------------------------------------------------------------- 1 | @require '~@temp/palette.styl' 2 | 3 | // colors 4 | $accentColor ?= #3eaf7c 5 | $textColor ?= #2c3e50 6 | $borderColor ?= #eaecef 7 | $codeBgColor ?= #282c34 8 | $arrowBgColor ?= #ccc 9 | $badgeTipColor ?= #42b983 10 | $badgeWarningColor ?= darken(#ffe564, 35%) 11 | $badgeErrorColor ?= #DA5961 12 | 13 | // layout 14 | $navbarHeight ?= 3.6rem 15 | $sidebarWidth ?= 20rem 16 | $contentWidth ?= 740px 17 | $homePageWidth ?= 960px 18 | 19 | // responsive breakpoints 20 | $MQNarrow ?= 959px 21 | $MQMobile ?= 719px 22 | $MQMobileNarrow ?= 419px 23 | 24 | // code 25 | $lineNumbersWrapperWidth ?= 3.5rem 26 | $codeLang ?= js ts html md vue css sass scss less stylus go java c sh yaml py docker dockerfile makefile 27 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/eject.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { path, chalk, fs, logger } = require('@vuepress/shared-utils') 4 | 5 | const EXCLUDED_FILES = [ 6 | '__tests__', 7 | '.npmignore', 8 | 'package.json', 9 | 'node_modules', 10 | 'README.md' 11 | ] 12 | 13 | module.exports = async (dir) => { 14 | try { 15 | require.resolve('@vuepress/theme-default') 16 | } catch (err) { 17 | console.log(chalk.red(`\n[vuepress] cannot find '@vuepress/theme-default'\n`)) 18 | process.exit(1) 19 | } 20 | const source = require.resolve('@vuepress/theme-default') 21 | logger.debug('entry', chalk.cyan(source)) 22 | 23 | const sourceDir = path.parse(source).dir 24 | const targetDir = path.resolve(dir, '.vuepress/theme') 25 | logger.debug('sourceDir', chalk.cyan(sourceDir)) 26 | logger.debug('targetDir', chalk.cyan(targetDir)) 27 | 28 | await fs.copy(sourceDir, targetDir, { 29 | filter: src => { 30 | const relative = path.relative(sourceDir, src) 31 | if (EXCLUDED_FILES.includes(relative)) { 32 | return false 33 | } 34 | if (relative) { 35 | logger.debug('Copied', chalk.cyan(relative)) 36 | } 37 | return true 38 | } 39 | }) 40 | logger.success(`Copied default theme into ${chalk.cyan(targetDir)}.\n`) 41 | } 42 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const App = require('./node/App') 4 | const { version } = require('../package') 5 | const { logger } = require('@vuepress/shared-utils') 6 | 7 | function createApp (options) { 8 | logger.wait('Extracting site metadata...') 9 | return new App(options) 10 | } 11 | 12 | async function dev (options) { 13 | if (process.env.NODE_ENV === undefined) { 14 | process.env.NODE_ENV = 'development' 15 | } 16 | const app = createApp(options) 17 | await app.process() 18 | return app.dev() 19 | } 20 | 21 | async function build (options) { 22 | if (process.env.NODE_ENV === undefined) { 23 | process.env.NODE_ENV = 'production' 24 | } 25 | const app = createApp(options) 26 | await app.process() 27 | return app.build() 28 | } 29 | 30 | exports.version = version 31 | exports.createApp = createApp 32 | exports.dev = dev 33 | exports.build = build 34 | exports.eject = require('./eject') 35 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/plugin-api/AsyncOption.spec.js: -------------------------------------------------------------------------------- 1 | const AsyncOption = require('../../plugin-api/abstract/AsyncOption') 2 | 3 | describe('AsyncOption', () => { 4 | test('parallelApply', async () => { 5 | const option = new AsyncOption('option') 6 | const handler1 = jest.fn() 7 | const handler2 = jest.fn() 8 | 9 | option.add('plugin-a', handler1) 10 | option.add('plugin-b', handler2) 11 | 12 | // TODO for now, if a class extends from another class. 13 | // the original methods in that class will be lost. 14 | 15 | await option.parallelApply(1, 2) 16 | // expect(handler1.mock.calls).toHaveLength(1) 17 | // expect(handler2.mock.calls).toHaveLength(1) 18 | // expect(handler1.mock.calls[0][0]).toBe(1) 19 | // expect(handler1.mock.calls[0][1]).toBe(2) 20 | // expect(handler2.mock.calls[0][0]).toBe(1) 21 | // expect(handler2.mock.calls[0][1]).toBe(2) 22 | }) 23 | }) 24 | 25 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/App.spec.js: -------------------------------------------------------------------------------- 1 | const { fs, path } = require('@vuepress/shared-utils') 2 | const App = require('../../App') 3 | 4 | const docsBaseDir = path.resolve(__dirname, 'fixtures') 5 | const docsModeNames = fs.readdirSync(docsBaseDir) 6 | const docsModes = docsModeNames.map(name => { 7 | const docsPath = path.resolve(docsBaseDir, name) 8 | const docsTempPath = path.resolve(docsPath, '.vuepress/.temp') 9 | return { name, docsPath, docsTempPath } 10 | }) 11 | 12 | describe('App', () => { 13 | test('should not throw error', async () => { 14 | await Promise.all(docsModes.map(async ({ name, docsPath, docsTempPath }) => { 15 | await fs.ensureDir(docsTempPath) 16 | const app = new App({ 17 | sourceDir: docsPath, 18 | theme: '@vuepress/default', 19 | emp: docsTempPath 20 | }) 21 | await app.process() 22 | expect(app.sourceDir).toBe(docsPath) 23 | })) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/__snapshots__/Page.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`markdown page should extract any content above as excerpt 1`] = ` 4 |

Excerpt

5 |

Blablabla...

6 | `; 7 | 8 | exports[`markdown page should extract headers by config 1`] = ` 9 | Array [ 10 | Object { 11 | "level": 1, 12 | "slug": "alpha", 13 | "title": "Alpha", 14 | }, 15 | Object { 16 | "level": 2, 17 | "slug": "h2", 18 | "title": "h2", 19 | }, 20 | ] 21 | `; 22 | 23 | exports[`markdown page should extract level 2 and 3 headers by default 1`] = ` 24 | Array [ 25 | Object { 26 | "level": 2, 27 | "slug": "h2", 28 | "title": "h2", 29 | }, 30 | Object { 31 | "level": 3, 32 | "slug": "h3", 33 | "title": "h3", 34 | }, 35 | ] 36 | `; 37 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Hello VuePress', 3 | description: '# Hello, VuePress!', 4 | dest: 'vuepress', 5 | base: 'vuepress', 6 | head: [ 7 | ['link', { rel: 'icon', href: '/logo.png' }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-config/README.md: -------------------------------------------------------------------------------- 1 | # Hello, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-dep-theme-without-index/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Hello VuePress', 3 | description: '# Hello, VuePress!', 4 | theme: 'vuepress-theme-without-index' 5 | } 6 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-dep-theme-without-index/README.md: -------------------------------------------------------------------------------- 1 | # Hello, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dest: 'vuepress', 3 | locales: { 4 | '/': { 5 | lang: 'en-US', 6 | title: 'VuePress', 7 | description: 'Vue-powered Static Site Generator' 8 | }, 9 | '/zh/': { 10 | lang: 'zh-CN', 11 | title: 'VuePress', 12 | description: 'Vue 驱动的静态网站生成器' 13 | } 14 | }, 15 | themeConfig: { 16 | repo: 'vuejs/vuepress', 17 | editLinks: true, 18 | docsDir: 'docs', 19 | locales: { 20 | '/': { 21 | label: 'English', 22 | selectText: 'Languages', 23 | editLinkText: 'Edit this page on GitHub', 24 | lastUpdated: 'Last Updated' 25 | }, 26 | '/zh/': { 27 | label: '简体中文', 28 | selectText: '选择语言', 29 | editLinkText: '在 GitHub 上编辑此页', 30 | lastUpdated: '上次更新' 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/README.md: -------------------------------------------------------------------------------- 1 | # Hello, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-i18n/zh/README.md: -------------------------------------------------------------------------------- 1 | # 你好, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Hello VuePress', 3 | description: '# Hello, VuePress!' 4 | } 5 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/.vuepress/theme/Layout.vue -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-local-theme/README.md: -------------------------------------------------------------------------------- 1 | # Hello, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-patterns/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Hello VuePress', 3 | description: '# Hello, VuePress!', 4 | dest: 'vuepress', 5 | base: 'vuepress', 6 | patterns: ['**/*.md', '**/*.vue', '!**/deploy.*'], 7 | head: [ 8 | ['link', { rel: 'icon', href: '/logo.png' }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs-patterns/README.md: -------------------------------------------------------------------------------- 1 | # Hello, VuePress! 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/2020-01-01-date.md: -------------------------------------------------------------------------------- 1 | # Date 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/README.md: -------------------------------------------------------------------------------- 1 | # Home 2 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/alpha.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: VuePress Alpha 3 | --- 4 | 5 | # Alpha 6 | 7 | ## h2 8 | 9 | ### h3 10 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/fixtures/docs/excerpt.md: -------------------------------------------------------------------------------- 1 | # Excerpt 2 | 3 | Blablabla... 4 | 5 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/prepare/util.js: -------------------------------------------------------------------------------- 1 | const { fs, path } = require('@vuepress/shared-utils') 2 | const createMarkdown = require('../../../../../markdown/index') 3 | 4 | const docsBaseDir = path.resolve(__dirname, 'fixtures/docs') 5 | 6 | function getDocument (relative) { 7 | return { 8 | filePath: path.join(docsBaseDir, relative), 9 | relative 10 | } 11 | } 12 | 13 | const getMarkdown = createMarkdown 14 | 15 | const readFile = async filePath => await fs.readFile(filePath, 'utf-8') 16 | 17 | module.exports = { 18 | getMarkdown, 19 | getDocument, 20 | readFile 21 | } 22 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/Layout.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/Layout.vue -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/components/Home.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/@vuepress/core/lib/node/__tests__/theme-api/fixtures/theme/components/Home.vue -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/__tests__/theme-api/index.spec.js: -------------------------------------------------------------------------------- 1 | jest.mock('vuepress-theme-parent') 2 | jest.mock('vuepress-theme-child') 3 | 4 | import ThemeAPI from '../../theme-api' 5 | import { resolve } from 'path' 6 | 7 | const theme = { 8 | path: resolve(process.cwd(), '__mocks__/vuepress-theme-child'), 9 | name: 'vuepress-theme-child', 10 | shortcut: 'child', 11 | entryFile: require('vuepress-theme-child') 12 | } 13 | 14 | const parent = { 15 | path: resolve(process.cwd(), '__mocks__/vuepress-theme-parent'), 16 | name: 'vuepress-theme-parent', 17 | shortcut: 'parent', 18 | entryFile: {} 19 | } 20 | 21 | describe('ThemeAPI', () => { 22 | test('extend', async () => { 23 | const themeAPI = new ThemeAPI(theme, parent) 24 | console.log(themeAPI.theme.entry) 25 | }) 26 | // loadTheme('vuepress-theme-child') 27 | }) 28 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/createMarkdown.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const createMarkdown = require('@vuepress/markdown') 8 | 9 | /** 10 | * Expose createMarkdown. 11 | */ 12 | 13 | module.exports = function (ctx) { 14 | const { markdown: markdownConfig = {}} = ctx.siteConfig 15 | const { chainMarkdown, extendMarkdown } = markdownConfig 16 | 17 | const beforeInstantiate = config => { 18 | chainMarkdown && chainMarkdown(config) 19 | ctx.pluginAPI.applySyncOption('chainMarkdown', config) 20 | } 21 | 22 | const afterInstantiate = md => { 23 | extendMarkdown && extendMarkdown(md) 24 | ctx.pluginAPI.applySyncOption('extendMarkdown', md) 25 | } 26 | 27 | return createMarkdown( 28 | Object.assign(markdownConfig, { 29 | beforeInstantiate, 30 | afterInstantiate 31 | }) 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/docs.fallback/.vuepress/theme/Layout.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/docs.fallback/README.md: -------------------------------------------------------------------------------- 1 | # VuePress 2 | 3 | > `Prompts`: You are running VuePress without setting sourceDir! 4 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/dataBlock/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 3 | */ 4 | module.exports = () => ({ 5 | name: '@vuepress/internal-data-block', 6 | 7 | chainWebpack (config) { 8 | config 9 | .module 10 | .rule('data-block') 11 | .resourceQuery(/blockType=data/) 12 | .use('date-block-loader') 13 | .loader(require.resolve('./loader.js')) 14 | }, 15 | 16 | enhanceAppFiles () { 17 | return [{ 18 | name: 'data-block', 19 | content: ` 20 | export default ({ Vue }) => { Vue.mixin({ 21 | computed: { 22 | $dataBlock() { 23 | return this.$options.__data__block__ 24 | } 25 | } 26 | }) }`.trim() 27 | }] 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/dataBlock/loader.js: -------------------------------------------------------------------------------- 1 | module.exports = function (source, map) { 2 | this.callback( 3 | null, 4 | `export default function (Component) { 5 | Component.options.__data__block__ = ${source.trim()} 6 | }`, 7 | map 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/enhanceApp.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 5 | */ 6 | module.exports = (options, ctx) => ({ 7 | name: '@vuepress/internal-enhance-app', 8 | 9 | enhanceAppFiles () { 10 | const { sourceDir, themeAPI } = ctx 11 | const enhanceAppPath = path.resolve(sourceDir, '.vuepress/enhanceApp.js') 12 | const files = [enhanceAppPath] 13 | if (themeAPI.existsParentTheme) { 14 | files.push(path.resolve(themeAPI.parentTheme.path, 'enhanceApp.js')) 15 | } 16 | const themeEnhanceAppPath = path.resolve(themeAPI.theme.path, 'enhanceApp.js') 17 | files.push(themeEnhanceAppPath) 18 | return files 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/frontmatterBlock/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 3 | */ 4 | module.exports = () => ({ 5 | name: '@vuepress/internal-frontmatter-block', 6 | 7 | chainWebpack (config) { 8 | config 9 | .module 10 | .rule('frontmatter-block') 11 | .resourceQuery(/blockType=frontmatter/) 12 | .use('frontmatter-block-loader') 13 | .loader(require.resolve('./loader.js')) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/frontmatterBlock/loader.js: -------------------------------------------------------------------------------- 1 | const { parseVueFrontmatter: { parseStrippedFrontmatter }} = require('@vuepress/shared-utils') 2 | const { frontmatterEmitter } = require('@vuepress/markdown-loader') 3 | const LRU = require('lru-cache') 4 | const cache = new LRU({ max: 1000 }) 5 | 6 | module.exports = function (source, map) { 7 | const isProd = process.env.NODE_ENV === 'production' 8 | 9 | if (!isProd) { 10 | const file = this.resourcePath 11 | // frontmatter changed... need to do a full reload 12 | const cached = cache.get(file) 13 | const parsed = parseStrippedFrontmatter(source) 14 | 15 | if (cached 16 | && cached.data 17 | && parsed 18 | && parsed.data 19 | && JSON.stringify(cached.data) !== JSON.stringify(parsed.data) 20 | ) { 21 | frontmatterEmitter.emit('update', file) 22 | } 23 | 24 | cache.set(file, parsed) 25 | } 26 | 27 | this.callback(null, '', map) 28 | } 29 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/layoutComponents.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 3 | */ 4 | module.exports = (options, ctx) => { 5 | return { 6 | name: '@vuepress/internal-layout-components', 7 | 8 | async clientDynamicModules () { 9 | const componentNames = Object.keys(ctx.themeAPI.layoutComponentMap) 10 | const code = `export default {\n${componentNames 11 | .map(name => ` ${JSON.stringify(name)}: () => import(${JSON.stringify(ctx.themeAPI.layoutComponentMap[name].path)})`) 12 | .join(',\n')} \n}` 13 | return { name: 'layout-components.js', content: code, dirname: 'internal' } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/pageComponents.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 3 | */ 4 | module.exports = (options, ctx) => { 5 | const { pages } = ctx 6 | // const componentNames = Object.keys(layoutComponentMap) 7 | 8 | return { 9 | name: '@vuepress/internal-page-components', 10 | 11 | async clientDynamicModules () { 12 | const code = `export default {\n${pages 13 | .filter(({ _filePath }) => _filePath) 14 | .map(({ key, _filePath }) => ` ${JSON.stringify(key)}: () => import(${JSON.stringify(_filePath)})`) 15 | .join(',\n')} \n}` 16 | return { name: 'page-components.js', content: code, dirname: 'internal' } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/rootMixins.js: -------------------------------------------------------------------------------- 1 | const { codegen: { pathsToModuleCode }} = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 5 | */ 6 | module.exports = (options, ctx, api) => ({ 7 | name: '@vuepress/internal-root-mixins', 8 | 9 | // @internal/root-mixins 10 | async clientDynamicModules () { 11 | const builtInRootMixins = [ 12 | ctx.getLibFilePath('client/root-mixins/updateMeta.js') 13 | ] 14 | 15 | const rootMixins = [ 16 | ...builtInRootMixins, 17 | ...api.options.clientRootMixin.values 18 | ] 19 | 20 | const rootMixinsCode = pathsToModuleCode(rootMixins) 21 | return { name: 'root-mixins.js', content: rootMixinsCode, dirname: 'internal' } 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/siteData.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 3 | */ 4 | module.exports = (options, ctx) => ({ 5 | name: '@vuepress/internal-site-data', 6 | 7 | // @internal/siteData 8 | async clientDynamicModules () { 9 | const code = `export const siteData = ${JSON.stringify(ctx.getSiteData(), null, 2)}` 10 | return { name: 'siteData.js', content: code, dirname: 'internal' } 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/style/client.js: -------------------------------------------------------------------------------- 1 | // generated from user config 2 | import '@temp/style.styl' 3 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/internal-plugins/transformModule.js: -------------------------------------------------------------------------------- 1 | const { fs, path } = require('@vuepress/shared-utils') 2 | 3 | const DIR = 'transform' 4 | 5 | /** 6 | * @type {import('@vuepress/types').Plugin<{}, import('@vuepress/types').DefaultThemeConfig>} 7 | */ 8 | module.exports = (options, ctx) => ({ 9 | name: '@vuepress/internal-transform-modules', 10 | 11 | alias: { 12 | '@transform': path.resolve(ctx.tempPath, DIR) 13 | }, 14 | 15 | async clientDynamicModules () { 16 | const files = [ 17 | path.resolve(__dirname, '../ClientComputedMixin.js') 18 | ] 19 | 20 | const modules = await Promise.all(files.map(async file => { 21 | const { base } = path.parse(file) 22 | let content = await fs.readFile(file, 'utf-8') 23 | content = content.replace('module.exports =', 'export default') 24 | return { name: base, content, dirname: DIR } 25 | })) 26 | 27 | return modules 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/plugin-api/override/AliasOption.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const Option = require('../abstract/Option') 8 | 9 | /** 10 | * alias option. 11 | */ 12 | 13 | module.exports = class AliasOption extends Option { 14 | apply (config) { 15 | super.syncApply() 16 | const aliases = this.appliedValues 17 | aliases.forEach((alias) => { 18 | Object.keys(alias).forEach(key => { 19 | config.resolve.alias.set(key, alias[key]) 20 | }) 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/plugin-api/override/ClientDynamicModulesOption.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const AsyncOption = require('../abstract/AsyncOption') 8 | 9 | /** 10 | * clientDynamicModules option. 11 | */ 12 | 13 | module.exports = class ClientDynamicModulesOption extends AsyncOption { 14 | async apply (ctx) { 15 | await super.asyncApply() 16 | 17 | for (const { value, name: pluginName } of this.appliedItems) { 18 | const { name, content, dirname = 'dynamic' } = value 19 | await ctx.writeTemp( 20 | `${dirname}/${name}`, 21 | ` 22 | /** 23 | * Generated by "${pluginName}" 24 | */ 25 | ${content}\n\n 26 | `.trim()) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/plugin-api/override/DefineOption.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const Option = require('../abstract/Option') 8 | 9 | /** 10 | * define option. 11 | */ 12 | 13 | module.exports = class DefineOption extends Option { 14 | apply (config) { 15 | super.syncApply() 16 | const defines = this.appliedValues 17 | defines.forEach(define => { 18 | Object.keys(define).forEach(key => { 19 | define[key] = JSON.stringify(define[key]) 20 | }) 21 | config.plugin('injections').tap(([options]) => [ 22 | Object.assign(options, define) 23 | ]) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/plugin-api/override/GlobalUIComponentsOption.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const Option = require('../abstract/Option') 8 | 9 | /** 10 | * globalUIComponents option. 11 | */ 12 | 13 | module.exports = class GlobalUIComponentsOption extends Option { 14 | async apply (ctx) { 15 | await ctx.writeTemp( 16 | `internal/global-ui.js`, 17 | `export default ${JSON.stringify(this.values, null, 2)}` 18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/plugin-api/override/instantiateOption.js: -------------------------------------------------------------------------------- 1 | const EnhanceAppFilesOption = require('./EnhanceAppFilesOption') 2 | const ClientDynamicModulesOption = require('./ClientDynamicModulesOption') 3 | const GlobalUIComponentsOption = require('./GlobalUIComponentsOption') 4 | const DefineOption = require('./DefineOption') 5 | const AliasOption = require('./AliasOption') 6 | const AsyncOption = require('../abstract/AsyncOption') 7 | const Option = require('../abstract/Option') 8 | const { PLUGIN_OPTION_MAP } = require('../constants') 9 | 10 | module.exports = function instantiateOption ({ name, async }) { 11 | switch (name) { 12 | case PLUGIN_OPTION_MAP.ENHANCE_APP_FILES.name: 13 | return new EnhanceAppFilesOption(name) 14 | 15 | case PLUGIN_OPTION_MAP.CLIENT_DYNAMIC_MODULES.name: 16 | return new ClientDynamicModulesOption(name) 17 | 18 | case PLUGIN_OPTION_MAP.GLOBAL_UI_COMPONENTS.name: 19 | return new GlobalUIComponentsOption(name) 20 | 21 | case PLUGIN_OPTION_MAP.DEFINE.name: 22 | return new DefineOption(name) 23 | 24 | case PLUGIN_OPTION_MAP.ALIAS.name: 25 | return new AliasOption(name) 26 | 27 | default: return async ? new AsyncOption(name) : new Option(name) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/theme-api/Layout.fallback.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/webpack/HeadPlugin.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const { normalizeHeadTag } = require('../util/index') 8 | 9 | /** 10 | * Expose HeadPlugin class. 11 | */ 12 | 13 | module.exports = class HeadPlugin { 14 | constructor ({ tags }) { 15 | this.tags = tags 16 | } 17 | 18 | apply (compiler) { 19 | compiler.hooks.compilation.tap('vuepress-site-data', compilation => { 20 | compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('vuepress-site-data', (data, cb) => { 21 | try { 22 | this.tags.forEach(tag => { 23 | data.head.push(normalizeHeadTag(tag)) 24 | }) 25 | } catch (e) { 26 | return cb(e) 27 | } 28 | cb(null, data) 29 | }) 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/@vuepress/core/lib/node/webpack/noopModule.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown-loader/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown-loader/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/markdown-loader 2 | 3 | > markdown-loader for VuePress 4 | 5 | ## Usage 6 | 7 | ```js 8 | const rule = config.module 9 | .rule('markdown') 10 | .test(/\.md$/) 11 | 12 | rule 13 | .use('vue-loader') 14 | .loader('vue-loader') 15 | .options({ /* ... */ }) 16 | 17 | rule 18 | .use('markdown-loader') 19 | .loader(require.resolve('@vuepress/markdown-loader')) 20 | .options({ 21 | markdown: /* instance created by @vuepress/markdown */, 22 | sourceDir: /* root source directory of your docs */, 23 | }) 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/markdown-loader", 3 | "version": "1.9.10", 4 | "description": "markdown-loader for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/markdown-loader#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/markdown-loader" 19 | }, 20 | "license": "MIT", 21 | "author": "Evan You", 22 | "maintainers": [ 23 | { 24 | "name": "ULIVZ", 25 | "email": "chl814@foxmail.com" 26 | } 27 | ], 28 | "main": "index.js", 29 | "dependencies": { 30 | "@vuepress/markdown": "1.9.10", 31 | "loader-utils": "^1.1.0", 32 | "lru-cache": "^5.1.1" 33 | }, 34 | "publishConfig": { 35 | "access": "public" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/highlight.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`highlight should highlight code 1`] = ` 4 |
new Vue()
5 | 
6 | `; 7 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/highlightLines.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`highlightLines highlight multiple lines 1`] = ` 4 |
5 |
 
6 |
 

7 |
 
8 |
 


9 |
const app = new Vue({ 10 | render, 11 | router 12 | }) 13 | 14 | app.$mount('#app') 15 | `; 16 | 17 | exports[`highlightLines highlight single line 1`] = ` 18 |
19 |
 

20 |
new Vue() 21 | `; 22 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/hoist.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`hoist Should keep script and style when not using hoist 1`] = ` 4 |

H1

5 | 6 | 11 |

H2

12 | `; 13 | 14 | exports[`hoist Should miss script and style when using hoist 1`] = ` 15 |

H1

16 |

H2

17 | `; 18 | 19 | exports[`hoist Should miss script and style when using hoist 2`] = ` 20 | Object { 21 | "__data_block": Object {}, 22 | "hoistedTags": Array [ 23 | , 24 | , 29 | ], 30 | } 31 | `; 32 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/lineNumers.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`lineNumbers should lineNumbers work with highlightLines 1`] = ` 4 | 5 |
6 | 7 |
8 |
 

9 |
new Vue() 10 |
11 | 12 |
13 | 14 | `; 15 | 16 | exports[`lineNumbers should render lineNumbers 1`] = ` 17 | 18 |
19 |
new Vue()
20 | 
21 |
22 | 23 |
24 | 25 | `; 26 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/link.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`link should render external links correctly 1`] = ` 4 |

vue 5 |

6 | `; 7 | 8 | exports[`link should render external links correctly 2`] = ` 9 |

vue 10 |

11 | `; 12 | 13 | exports[`link should render external links correctly 3`] = ` 14 |

some link with code 15 |

16 | `; 17 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/__snapshots__/preWrapper.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`preWrapper should wrap code with double quotation marks 1`] = ` 4 | 5 |
6 |
new Vue()
 7 | 
8 | 9 |
10 | 11 | `; 12 | 13 | exports[`preWrapper should wrap code with quadruple space 1`] = ` 14 | 15 |
16 |
new Vue()
17 | 
18 | 19 |
20 | 21 | `; 22 | 23 | exports[`preWrapper should wrap code with triple back quote 1`] = ` 24 | 25 |
26 |
new Vue()
27 | 
28 | 29 |
30 | 31 | `; 32 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/Dockerfile: -------------------------------------------------------------------------------- 1 | # Sample snippet file with no filename extension. 2 | FROM ubuntu:latest 3 | CMD echo hello! 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-highlightLines-multiple.md: -------------------------------------------------------------------------------- 1 | ``` js {1-2,4-5} 2 | const app = new Vue({ 3 | render, 4 | router 5 | }) 6 | 7 | app.$mount('#app') 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-highlightLines-single.md: -------------------------------------------------------------------------------- 1 | ``` js {1} 2 | new Vue() 3 | ``` 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-prewrapper-with-double-quotation-marks.md: -------------------------------------------------------------------------------- 1 | ``` js name="marks" 2 | new Vue() 3 | ``` 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-prewrapper-with-quotes.md: -------------------------------------------------------------------------------- 1 | ``` js 2 | new Vue() 3 | ``` 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-prewrapper-with-spaces.md: -------------------------------------------------------------------------------- 1 | new Vue() 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-highlightLines-multiple.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet.js{1-3} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-highlightLines-single-and-multiple.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet.js{1-2,3} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-highlightLines-single.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet.js{1,3} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-with-indented-region.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet-with-indented-region.html#body 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-with-region-and-highlight.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet-with-region.js#snippet{1,3} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-with-region-and-single-highlight.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet-with-region.js#snippet{11} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-with-region.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet-with-region.js#snippet 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet-with-space-in-path.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet with spaces.js {1-3} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code-snippet.md: -------------------------------------------------------------------------------- 1 | <<< @/packages/@vuepress/markdown/__tests__/fragments/snippet.js 2 | 3 | <<< @/packages/@vuepress/markdown/__tests__/fragments/Dockerfile 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/code.md: -------------------------------------------------------------------------------- 1 | ``` js 2 | new Vue() 3 | ``` 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/hoist.md: -------------------------------------------------------------------------------- 1 | # H1 2 | 3 | 4 | 9 | 10 | ## H2 11 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/snippet with spaces.js: -------------------------------------------------------------------------------- 1 | export default function () { 2 | // .. 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/snippet-with-indented-region.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 |
11 |

Hello World

12 |
13 |
Lorem Ipsum
14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/snippet-with-region.js: -------------------------------------------------------------------------------- 1 | // #region snippet 2 | function foo () { 3 | return ({ 4 | dest: '../../vuepress', 5 | locales: { 6 | '/': { 7 | lang: 'en-US', 8 | title: 'VuePress', 9 | description: 'Vue-powered Static Site Generator' 10 | }, 11 | '/zh/': { 12 | lang: 'zh-CN', 13 | title: 'VuePress', 14 | description: 'Vue 驱动的静态网站生成器' 15 | } 16 | }, 17 | head: [ 18 | ['link', { rel: 'icon', href: `/logo.png` }], 19 | ['link', { rel: 'manifest', href: '/manifest.json' }], 20 | ['meta', { name: 'theme-color', content: '#3eaf7c' }], 21 | ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], 22 | ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }], 23 | ['link', { rel: 'apple-touch-icon', href: `/icons/apple-touch-icon-152x152.png` }], 24 | ['link', { rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#3eaf7c' }], 25 | ['meta', { name: 'msapplication-TileImage', content: '/icons/msapplication-icon-144x144.png' }], 26 | ['meta', { name: 'msapplication-TileColor', content: '#000000' }] 27 | ] 28 | }) 29 | } 30 | // #endregion snippet 31 | 32 | export default foo 33 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/fragments/snippet.js: -------------------------------------------------------------------------------- 1 | export default function () { 2 | // .. 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/highlight.spec.js: -------------------------------------------------------------------------------- 1 | import { getFragment } from '@vuepress/test-utils' 2 | import { Md } from './util' 3 | import highlight from '../lib/highlight.js' 4 | 5 | const md = Md() 6 | const mdH = Md().set({ highlight }) 7 | 8 | describe('highlight', () => { 9 | test('should highlight code', () => { 10 | const input = getFragment(__dirname, 'code.md') 11 | const output1 = md.render(input) 12 | const output2 = mdH.render(input) 13 | expect(output1 === output2).toBe(false) 14 | expect(output2).toMatchSnapshot() 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/highlightLines.spec.js: -------------------------------------------------------------------------------- 1 | import { getFragment } from '@vuepress/test-utils' 2 | import { Md } from './util' 3 | import highlightLines from '../lib/highlightLines.js' 4 | 5 | const md = Md() 6 | const mdH = Md().use(highlightLines) 7 | 8 | describe('highlightLines', () => { 9 | test('should the output not change when highlightLines is not detected', () => { 10 | const input = getFragment(__dirname, 'code.md') 11 | const output1 = md.render(input) 12 | const output2 = mdH.render(input) 13 | expect(output1).toBe(output2) 14 | }) 15 | 16 | test('highlight single line', () => { 17 | const input = getFragment(__dirname, 'code-highlightLines-single.md') 18 | const output = mdH.render(input) 19 | expect(output).toMatchSnapshot() 20 | }) 21 | 22 | test('highlight multiple lines', () => { 23 | const input = getFragment(__dirname, 'code-highlightLines-multiple.md') 24 | const output = mdH.render(input) 25 | expect(output).toMatchSnapshot() 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/hoist.spec.js: -------------------------------------------------------------------------------- 1 | import { getFragment } from '@vuepress/test-utils' 2 | import { Md } from './util' 3 | import hoist from '../lib/hoist.js' 4 | import { dataReturnable } from '../index.js' 5 | 6 | const md = Md().set({ html: true }) 7 | const mdH = Md().set({ html: true }).use(hoist) 8 | 9 | dataReturnable(mdH) 10 | 11 | describe('hoist', () => { 12 | test('Should keep script and style when not using hoist', () => { 13 | const input = getFragment(__dirname, 'hoist.md') 14 | const output = md.render(input) 15 | expect(output).toMatchSnapshot() 16 | }) 17 | 18 | test('Should miss script and style when using hoist', () => { 19 | const input = getFragment(__dirname, 'hoist.md') 20 | const { html, data } = mdH.render(input) 21 | expect(html).toMatchSnapshot() 22 | expect(data).toMatchSnapshot() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/lineNumers.spec.js: -------------------------------------------------------------------------------- 1 | import { getFragment } from '@vuepress/test-utils' 2 | import { Md } from './util' 3 | import preWrapper from '../lib/preWrapper.js' 4 | import lineNumbers from '../lib/lineNumbers.js' 5 | import highlightLines from '../lib/highlightLines.js' 6 | 7 | // lineNumbers must be chained after preWrapper. 8 | // since lineNumbers needs to add extra stateful class to its block wrapper. 9 | const mdL = Md().use(preWrapper).use(lineNumbers) 10 | const mdLH = Md().use(highlightLines).use(preWrapper).use(lineNumbers) 11 | 12 | describe('lineNumbers', () => { 13 | test('should render lineNumbers', () => { 14 | const input = getFragment(__dirname, 'code.md') 15 | const output = mdL.render(input) 16 | expect(output).toMatchSnapshot() 17 | }) 18 | 19 | test('should lineNumbers work with highlightLines', () => { 20 | const input = getFragment(__dirname, 'code-highlightLines-single.md') 21 | const output = mdLH.render(input) 22 | expect(output).toMatchSnapshot() 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/preWrapper.spec.js: -------------------------------------------------------------------------------- 1 | import { getFragment } from '@vuepress/test-utils' 2 | import { Md } from './util' 3 | import preWrapper from '../lib/preWrapper.js' 4 | 5 | const md = Md() 6 | const mdP = Md().use(preWrapper) 7 | 8 | describe('preWrapper', () => { 9 | test('should wrap code with triple back quote', () => { 10 | const input = getFragment(__dirname, 'code-prewrapper-with-quotes.md') 11 | const output1 = md.render(input) 12 | const output2 = mdP.render(input) 13 | expect(output1 === output2).toBe(false) 14 | expect(output2).toMatchSnapshot() 15 | }) 16 | 17 | test('should wrap code with quadruple space', () => { 18 | const input = getFragment(__dirname, 'code-prewrapper-with-spaces.md') 19 | const output1 = md.render(input) 20 | const output2 = mdP.render(input) 21 | expect(output1 === output2).toBe(false) 22 | expect(output2).toMatchSnapshot() 23 | }) 24 | 25 | test('should wrap code with double quotation marks', () => { 26 | const input = getFragment(__dirname, 'code-prewrapper-with-double-quotation-marks.md') 27 | const output2 = mdP.render(input) 28 | expect(output2).toMatchSnapshot() 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/slugify.spec.js: -------------------------------------------------------------------------------- 1 | import { Md } from './util' 2 | import anchor from 'markdown-it-anchor' 3 | import slugify from '../../shared-utils/lib/slugify.js' 4 | 5 | const mdS = Md().use(anchor, { 6 | slugify, 7 | permalink: true, 8 | permalinkBefore: true, 9 | permalinkSymbol: '#' 10 | }) 11 | 12 | const asserts = { 13 | /* header: slug */ 14 | '# a b': 'a-b', 15 | '# a-b': 'a-b', 16 | '# ``': 'a', 17 | '# ``b': 'a-b', 18 | '# `` b': 'a-b' 19 | } 20 | 21 | describe('slugify', () => { 22 | test('should convert headers to slug correctly', () => { 23 | for (const input in asserts) { 24 | const output = mdS.render(input) 25 | expect(getSlug(output)).toBe(asserts[input]) 26 | } 27 | }) 28 | }) 29 | 30 | function getSlug (output) { 31 | return output.match(/id=\\?"([^"]*)\\?"/)[1] 32 | } 33 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/__tests__/util.js: -------------------------------------------------------------------------------- 1 | export function Md () { 2 | return require('markdown-it')() 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/lib/constant.js: -------------------------------------------------------------------------------- 1 | exports.PLUGINS = { 2 | COMPONENT: 'component', 3 | HIGHLIGHT_LINES: 'highlight-lines', 4 | PRE_WRAPPER: 'pre-wrapper', 5 | SNIPPET: 'snippet', 6 | CONVERT_ROUTER_LINK: 'convert-router-link', 7 | HOIST_SCRIPT_STYLE: 'hoist-script-style', 8 | ANCHOR: 'anchor', 9 | EMOJI: 'emoji', 10 | TOC: 'toc', 11 | LINE_NUMBERS: 'line-numbers' 12 | } 13 | 14 | exports.REQUIRED_PLUGINS = [ 15 | exports.PLUGINS.COMPONENT, 16 | exports.PLUGINS.ANCHOR 17 | ] 18 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/lib/hoist.js: -------------------------------------------------------------------------------- 1 | module.exports = md => { 2 | const RE = /^<(script|style)(?=(\s|>|$))/i 3 | 4 | md.renderer.rules.html_block = (tokens, idx) => { 5 | const content = tokens[idx].content 6 | const hoistedTags = md.$data.hoistedTags || (md.$data.hoistedTags = []) 7 | if (RE.test(content.trim())) { 8 | hoistedTags.push(content) 9 | return '' 10 | } else { 11 | return content 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/lib/lineNumbers.js: -------------------------------------------------------------------------------- 1 | // markdown-it plugin for generating line numbers. 2 | // It depends on preWrapper plugin. 3 | 4 | module.exports = md => { 5 | const fence = md.renderer.rules.fence 6 | md.renderer.rules.fence = (...args) => { 7 | const rawCode = fence(...args) 8 | const code = rawCode.slice( 9 | rawCode.indexOf(''), 10 | rawCode.indexOf('') 11 | ) 12 | 13 | const lines = code.split('\n') 14 | const lineNumbersCode = [...Array(lines.length - 1)] 15 | .map((line, index) => `${index + 1}
`).join('') 16 | 17 | const lineNumbersWrapperCode 18 | = `
${lineNumbersCode}
` 19 | 20 | const finalCode = rawCode 21 | .replace('', `${lineNumbersWrapperCode}`) 22 | .replace('extra-class', 'line-numbers-mode') 23 | 24 | return finalCode 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/lib/preWrapper.js: -------------------------------------------------------------------------------- 1 | // markdown-it plugin for wrapping
 ... 
. 2 | // 3 | // If your plugin was chained before preWrapper, you can add additional element directly. 4 | // If your plugin was chained after preWrapper, you can use these slots: 5 | // 1. 6 | // 2. 7 | // 3. 8 | // 4. 9 | 10 | module.exports = md => { 11 | const wrap = (wrapped) => (...args) => { 12 | const [tokens, idx] = args 13 | const token = tokens[idx] 14 | const rawCode = wrapped(...args) 15 | const tokenInfo = token.info.trim().replace(/\"/g, '\'') 16 | return `
` 17 | + `${rawCode}
` 18 | } 19 | const { fence, code_block: codeBlock } = md.renderer.rules 20 | md.renderer.rules.fence = wrap(fence) 21 | md.renderer.rules.code_block = wrap(codeBlock) 22 | } 23 | -------------------------------------------------------------------------------- /packages/@vuepress/markdown/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/markdown", 3 | "version": "1.9.10", 4 | "description": "markdown for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "markdown", 9 | "vue", 10 | "vuepress" 11 | ], 12 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/markdown#readme", 13 | "bugs": { 14 | "url": "https://github.com/vuejs/vuepress/issues" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vuejs/vuepress.git", 19 | "directory": "packages/@vuepress/markdown" 20 | }, 21 | "license": "MIT", 22 | "author": "Evan You", 23 | "maintainers": [ 24 | { 25 | "name": "ULIVZ", 26 | "email": "chl814@foxmail.com" 27 | } 28 | ], 29 | "main": "index.js", 30 | "dependencies": { 31 | "@vuepress/shared-utils": "1.9.10", 32 | "markdown-it": "^8.4.1", 33 | "markdown-it-anchor": "^5.0.2", 34 | "markdown-it-chain": "^1.3.0", 35 | "markdown-it-emoji": "^1.4.0", 36 | "markdown-it-table-of-contents": "^0.4.0", 37 | "prismjs": "^1.13.0" 38 | }, 39 | "publishConfig": { 40 | "access": "public" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-active-header-links/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-active-header-links/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-active-header-links 2 | 3 | > active-header-links plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-active-header-links.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-active-header-links/index.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = options => ({ 7 | clientRootMixin: path.resolve(__dirname, 'clientRootMixin.js'), 8 | define: { 9 | AHL_SIDEBAR_LINK_SELECTOR: options.sidebarLinkSelector || '.sidebar-link', 10 | AHL_HEADER_ANCHOR_SELECTOR: options.headerAnchorSelector || '.header-anchor' 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-active-header-links/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-active-header-links", 3 | "version": "1.9.10", 4 | "description": "active-header-links plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-active-header-links#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-active-header-links" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10", 25 | "lodash.debounce": "^4.0.8" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-back-to-top/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-back-to-top/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-back-to-top 2 | 3 | > Back-to-top plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-back-to-top.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-back-to-top/enhanceAppFile.js: -------------------------------------------------------------------------------- 1 | import BackToTop from './BackToTop.vue' 2 | 3 | export default ({ Vue }) => { 4 | // eslint-disable-next-line vue/match-component-file-name 5 | Vue.component('BackToTop', BackToTop) 6 | } 7 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-back-to-top/index.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = { 7 | enhanceAppFiles: [ 8 | path.resolve(__dirname, 'enhanceAppFile.js') 9 | ], 10 | 11 | globalUIComponents: 'BackToTop' 12 | } 13 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-back-to-top/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-back-to-top", 3 | "version": "1.9.10", 4 | "description": "back-to-top plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-back-to-top#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-back-to-top" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10", 25 | "lodash.debounce": "^4.0.8" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-google-analytics/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-google-analytics/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-google-analytics 2 | 3 | > Google analytics plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-google-analytics.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-google-analytics/enhanceAppFile.js: -------------------------------------------------------------------------------- 1 | /* global GA_ID, ga */ 2 | 3 | export default ({ router }) => { 4 | // Google analytics integration 5 | if (process.env.NODE_ENV === 'production' && GA_ID && typeof window !== 'undefined') { 6 | (function (i, s, o, g, r, a, m) { 7 | i['GoogleAnalyticsObject'] = r 8 | i[r] = i[r] || function () { 9 | (i[r].q = i[r].q || []).push(arguments) 10 | } 11 | i[r].l = 1 * new Date() 12 | a = s.createElement(o) 13 | m = s.getElementsByTagName(o)[0] 14 | a.async = 1 15 | a.src = g 16 | m.parentNode.insertBefore(a, m) 17 | })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga') 18 | 19 | ga('create', GA_ID, 'auto') 20 | ga('set', 'anonymizeIp', true) 21 | 22 | router.afterEach(function (to) { 23 | ga('set', 'page', router.app.$withBase(to.fullPath)) 24 | ga('send', 'pageview') 25 | }) 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-google-analytics/index.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = (options = {}, context) => ({ 7 | define () { 8 | const { siteConfig = {}} = context 9 | const ga = options.ga || siteConfig.ga 10 | const GA_ID = ga || false 11 | return { GA_ID } 12 | }, 13 | 14 | enhanceAppFiles: path.resolve(__dirname, 'enhanceAppFile.js') 15 | }) 16 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-google-analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-google-analytics", 3 | "version": "1.9.10", 4 | "description": "google-analytics plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-google-analytics#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-google-analytics" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10" 25 | }, 26 | "publishConfig": { 27 | "access": "public" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-last-updated/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-last-updated/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-last-updated 2 | 3 | > last-updated plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-last-updated.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-last-updated/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const spawn = require('cross-spawn') 3 | 4 | /** 5 | * @type {import('@vuepress/types').Plugin} 6 | */ 7 | module.exports = (options = {}, context) => ({ 8 | extendPageData ($page) { 9 | const { transformer, dateOptions } = options 10 | const timestamp = getGitLastUpdatedTimeStamp($page._filePath) 11 | const $lang = $page._computed.$lang 12 | if (timestamp) { 13 | const lastUpdated = typeof transformer === 'function' 14 | ? transformer(timestamp, $lang) 15 | : defaultTransformer(timestamp, $lang, dateOptions) 16 | $page.lastUpdated = lastUpdated 17 | $page.lastUpdatedTimestamp = timestamp 18 | } 19 | } 20 | }) 21 | 22 | function defaultTransformer (timestamp, lang, dateOptions) { 23 | return new Date(timestamp).toLocaleString(lang, dateOptions) 24 | } 25 | 26 | function getGitLastUpdatedTimeStamp (filePath) { 27 | let lastUpdated 28 | try { 29 | lastUpdated = parseInt(spawn.sync( 30 | 'git', 31 | ['log', '-1', '--format=%at', path.basename(filePath)], 32 | { cwd: path.dirname(filePath) } 33 | ).stdout.toString('utf-8')) * 1000 34 | } catch (e) { /* do not handle for now */ } 35 | return lastUpdated 36 | } 37 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-last-updated/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-last-updated", 3 | "version": "1.9.10", 4 | "description": "last-updated plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-last-updated#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-last-updated" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10", 25 | "cross-spawn": "^6.0.5" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-medium-zoom 2 | 3 | > medium-zoom plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-medium-zoom.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/clientRootMixin.js: -------------------------------------------------------------------------------- 1 | /* global SELECTOR, OPTIONS */ 2 | 3 | import './style.css' 4 | import zoom from 'medium-zoom' 5 | 6 | export default { 7 | data: () => ({ zoom: null }), 8 | 9 | mounted () { 10 | this.updateZoom() 11 | }, 12 | 13 | updated () { 14 | this.updateZoom() 15 | }, 16 | 17 | methods: { 18 | updateZoom () { 19 | setTimeout(() => { 20 | if (this.zoom) { 21 | this.zoom.detach() 22 | } 23 | this.zoom = zoom(SELECTOR, OPTIONS) 24 | }, 1000) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/index.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = (options, context) => ({ 7 | define: { 8 | SELECTOR: options.selector || '.theme-default-content :not(a) > img', 9 | OPTIONS: options.options 10 | }, 11 | clientRootMixin: path.resolve(__dirname, 'clientRootMixin.js') 12 | }) 13 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-medium-zoom", 3 | "version": "1.9.10", 4 | "description": "medium-zoom plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-medium-zoom#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-medium-zoom" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10", 25 | "medium-zoom": "^1.0.4" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-medium-zoom/style.css: -------------------------------------------------------------------------------- 1 | .medium-zoom-overlay { 2 | z-index: 100; 3 | } 4 | 5 | .medium-zoom-overlay ~ img { 6 | z-index: 101; 7 | } 8 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-nprogress 2 | 3 | > nprogress plugin for VuePress 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/clientRootMixin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import nprogress from 'nprogress' 3 | 4 | export default { 5 | mounted () { 6 | // configure progress bar 7 | nprogress.configure({ showSpinner: false }) 8 | 9 | this.$router.beforeEach((to, from, next) => { 10 | if (to.path !== from.path && !Vue.component(to.name)) { 11 | nprogress.start() 12 | } 13 | next() 14 | }) 15 | 16 | this.$router.afterEach(() => { 17 | nprogress.done() 18 | this.isSidebarOpen = false 19 | }) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/enhanceAppFile.js: -------------------------------------------------------------------------------- 1 | import './nprogress.styl' 2 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/index.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = { 7 | clientRootMixin: resolve(__dirname, 'clientRootMixin.js'), 8 | enhanceAppFiles: resolve(__dirname, 'enhanceAppFile.js') 9 | } 10 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/nprogress.styl: -------------------------------------------------------------------------------- 1 | $nprogressColor ?= $accentColor 2 | 3 | #nprogress 4 | pointer-events none 5 | .bar 6 | background $nprogressColor 7 | position fixed 8 | z-index 1031 9 | top 0 10 | left 0 11 | width 100% 12 | height 2px 13 | .peg 14 | display block 15 | position absolute 16 | right 0px 17 | width 100px 18 | height 100% 19 | box-shadow 0 0 10px $nprogressColor, 0 0 5px $nprogressColor 20 | opacity 1.0 21 | transform rotate(3deg) translate(0px, -4px) 22 | .spinner 23 | display block 24 | position fixed 25 | z-index 1031 26 | top 15px 27 | right 15px 28 | .spinner-icon 29 | width 18px 30 | height 18px 31 | box-sizing border-box 32 | border solid 2px transparent 33 | border-top-color $nprogressColor 34 | border-left-color $nprogressColor 35 | border-radius 50% 36 | animation nprogress-spinner 400ms linear infinite 37 | 38 | .nprogress-custom-parent 39 | overflow hidden 40 | position relative 41 | 42 | .nprogress-custom-parent #nprogress .spinner, 43 | .nprogress-custom-parent #nprogress .bar 44 | position absolute 45 | 46 | @keyframes nprogress-spinner 47 | 0% 48 | transform rotate(0deg) 49 | 100% 50 | transform rotate(360deg) 51 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-nprogress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-nprogress", 3 | "version": "1.9.10", 4 | "description": "nprogress plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-nprogress#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-nprogress" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10", 25 | "nprogress": "^0.2.0" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-pwa 2 | 3 | > PWA plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-pwa.html). 6 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/lib/SWUpdateEvent.js: -------------------------------------------------------------------------------- 1 | export default class SWUpdateEvent { 2 | constructor (registration) { 3 | Object.defineProperty(this, 'registration', { 4 | value: registration, 5 | configurable: true, 6 | writable: true 7 | }) 8 | } 9 | 10 | /** 11 | * Check if the new service worker exists or not. 12 | */ 13 | update () { 14 | return this.registration.update() 15 | } 16 | 17 | /** 18 | * Activate new service worker to work 'location.reload()' with new data. 19 | */ 20 | skipWaiting () { 21 | const worker = this.registration.waiting 22 | if (!worker) { 23 | return Promise.resolve() 24 | } 25 | 26 | console.log('[vuepress:sw] Doing worker.skipWaiting().') 27 | return new Promise((resolve, reject) => { 28 | const channel = new MessageChannel() 29 | 30 | channel.port1.onmessage = (event) => { 31 | console.log('[vuepress:sw] Done worker.skipWaiting().') 32 | if (event.data.error) { 33 | reject(event.data.error) 34 | } else { 35 | resolve(event.data) 36 | } 37 | } 38 | 39 | worker.postMessage({ type: 'skip-waiting' }, [channel.port2]) 40 | }) 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/lib/event.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | export default new Vue() 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/lib/i18n.js: -------------------------------------------------------------------------------- 1 | export const popupConfig = { 2 | '/': { 3 | message: 'New content is available.', 4 | buttonText: 'Refresh' 5 | }, 6 | '/zh/': { 7 | message: '发现新内容可用', 8 | buttonText: '刷新' 9 | }, 10 | '/ru/': { 11 | message: 'Доступен новый контент.', 12 | buttonText: 'Обновить' 13 | }, 14 | '/uk/': { 15 | message: 'Доступний новий контент.', 16 | buttonText: 'Оновити' 17 | }, 18 | '/ja/': { 19 | message: '新しいコンテンツがあります。', 20 | buttonText: '更新する' 21 | }, 22 | '/es/': { 23 | message: 'Hay nuevo contenido disponible.', 24 | buttonText: 'Actualizar' 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/lib/skip-waiting.js: -------------------------------------------------------------------------------- 1 | addEventListener('message', event => { 2 | const replyPort = event.ports[0] 3 | const message = event.data 4 | if (replyPort && message && message.type === 'skip-waiting') { 5 | event.waitUntil( 6 | self.skipWaiting().then( 7 | () => replyPort.postMessage({ error: null }), 8 | error => replyPort.postMessage({ error }) 9 | ) 10 | ) 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-pwa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-pwa", 3 | "version": "1.9.10", 4 | "description": "pwa plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-pwa#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-pwa" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/shared-utils": "1.9.10", 25 | "@vuepress/types": "1.9.10", 26 | "register-service-worker": "^1.7.0", 27 | "workbox-build": "^4.3.1" 28 | }, 29 | "publishConfig": { 30 | "access": "public" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-register-components/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-register-components/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-register-components 2 | 3 | > register-components plugin for VuePress 4 | 5 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-register-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-register-components", 3 | "version": "1.9.10", 4 | "description": "register-global-components plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-register-components#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-register-components" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/shared-utils": "1.9.10", 25 | "@vuepress/types": "1.9.10" 26 | }, 27 | "publishConfig": { 28 | "access": "public" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/plugin-search 2 | 3 | > header-based search plugin for VuePress 4 | 5 | See [documentation](https://vuepress.vuejs.org/plugin/official/plugin-search.html). 6 | 7 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/__tests__/matchQuery.spec.js: -------------------------------------------------------------------------------- 1 | import matchQuery from '../match-query' 2 | 3 | describe('matchQuery', () => { 4 | const page = { 5 | title: 'HoMe PaGe', 6 | frontmatter: { 7 | tags: ['vuepress', 'is', 'jUst AwEsOme'] 8 | } 9 | } 10 | 11 | test('should match when query includes part of the page title', () => { 12 | const query = 'hom' 13 | 14 | const match = matchQuery(query, page) 15 | 16 | expect(match).toBe(true) 17 | }) 18 | 19 | test('should match when query includes the full page title', () => { 20 | const query = 'home page' 21 | 22 | const match = matchQuery(query, page) 23 | 24 | expect(match).toBe(true) 25 | }) 26 | 27 | test('should match when query includes a tag', () => { 28 | const query = 'vuepress' 29 | 30 | const match = matchQuery(query, page) 31 | 32 | expect(match).toBe(true) 33 | }) 34 | 35 | test('should match when query includes part of tag', () => { 36 | const query = 'just aw' 37 | 38 | const match = matchQuery(query, page) 39 | 40 | expect(match).toBe(true) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/index.js: -------------------------------------------------------------------------------- 1 | const { path } = require('@vuepress/shared-utils') 2 | 3 | /** 4 | * @type {import('@vuepress/types').Plugin} 5 | */ 6 | module.exports = (options) => ({ 7 | alias: { 8 | '@SearchBox': 9 | path.resolve(__dirname, 'SearchBox.vue') 10 | }, 11 | 12 | define: { 13 | SEARCH_MAX_SUGGESTIONS: options.searchMaxSuggestions || 5, 14 | SEARCH_PATHS: options.test || null, 15 | SEARCH_HOTKEYS: options.searchHotkeys || ['s', '/'] 16 | } 17 | }) 18 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/plugin-search", 3 | "version": "1.9.10", 4 | "description": "search plugin for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/plugin-search#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/plugin-search" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@vuepress/types": "1.9.10" 25 | }, 26 | "publishConfig": { 27 | "access": "public" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/plugin-search/search.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/shared-utils 2 | 3 | > shared-utils for VuePress 4 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/deeplyParseHeaders.spec.ts: -------------------------------------------------------------------------------- 1 | import deeplyParseHeaders from '../src/deeplyParseHeaders' 2 | 3 | test('deeplyParseHeaders', () => { 4 | const asserts: Record = { 5 | // Remove tail html 6 | '# `H1` ': '# H1', 7 | '# *H1* ': '# H1', 8 | 9 | // Reserve code-wrapped tail html 10 | '# `H1` ``': '# H1 ', 11 | '# *H1* ``': '# H1 ', 12 | 13 | // Remove leading html 14 | '# `H1`': '# H1', 15 | '# *H1*': '# H1', 16 | 17 | // Reserve code-wrapped leading html 18 | '# `` `H1`': '# H1', 19 | '# `` *H1*': '# H1', 20 | 21 | // Remove middle html 22 | '# `H1` `H2`': '# H1 H2', 23 | '# `H1` `H2`': '# H1 H2', 24 | 25 | // Reserve middle html 26 | '# `H1` `` `H2`': '# H1 H2', 27 | '# `H1` `` `H2`': '# H1 H2' 28 | } 29 | 30 | Object.keys(asserts).forEach(input => { 31 | expect(deeplyParseHeaders(input)).toBe(asserts[input]) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/fileToPath.spec.ts: -------------------------------------------------------------------------------- 1 | import fileToPath from '../src/fileToPath' 2 | 3 | test('should return dirname of the path when it is index file ', () => { 4 | const asserts: Record = { 5 | 'README.md': '/', 6 | 'README.vue': '/', 7 | 'foo/README.md': '/foo/', 8 | 'foo/README.vue': '/foo/' 9 | } 10 | Object.keys(asserts).forEach(file => { 11 | expect(fileToPath(file)).toBe(asserts[file]) 12 | }) 13 | }) 14 | 15 | test('should return a path with .html suffix', () => { 16 | const asserts: Record = { 17 | 'foo.md': '/foo.html', 18 | 'foo.vue': '/foo.html', 19 | 'foo/bar.md': '/foo/bar.html', 20 | 'foo/bar.vue': '/foo/bar.html' 21 | } 22 | Object.keys(asserts).forEach(file => { 23 | expect(fileToPath(file)).toBe(asserts[file]) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/fixtures/plugin-a.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'a' 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/fixtures/theme-a/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/isIndexFile.spec.ts: -------------------------------------------------------------------------------- 1 | import { isIndexFile } from '../src/isIndexFile' 2 | 3 | test('isIndexFile', () => { 4 | [ 5 | 'README.md', 6 | 'readme.md', 7 | 'INDEX.md', 8 | 'index.md', 9 | 'foo/README.md', 10 | 'foo/index.md', 11 | 'README.vue', 12 | 'readme.vue', 13 | 'INDEX.vue', 14 | 'index.vue', 15 | 'foo/README.vue', 16 | 'foo/index.vue' 17 | ].forEach(file => { 18 | expect(isIndexFile(file)).toBe(true) 19 | }); 20 | [ 21 | 'foo/one.md', 22 | 'one.md', 23 | 'one-index.md', 24 | 'foo/one-index.md', 25 | 'foo/one.vue', 26 | 'one.vue', 27 | 'one-index.vue', 28 | 'foo/one-index.vue' 29 | ].forEach(file => { 30 | expect(isIndexFile(file)).toBe(false) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/parseHeaders.spec.ts: -------------------------------------------------------------------------------- 1 | import parseHeaders from '../src/parseHeaders' 2 | 3 | describe('parseHeaders', () => { 4 | test('should unescape html', () => { 5 | const input = `<div :id="'app'">` 6 | expect(parseHeaders(input)).toBe(`
`) 7 | }) 8 | 9 | test('should remove markdown tokens correctly', () => { 10 | const asserts: Record = { 11 | // #238 12 | '[vue](vuejs.org)': 'vue', 13 | '`vue`': 'vue', 14 | '*vue*': 'vue', 15 | '**vue**': 'vue', 16 | '***vue***': 'vue', 17 | '_vue_': 'vue', 18 | '\\_vue\\_': '_vue_', 19 | '\\*vue\\*': '*vue*', 20 | '\\!vue\\!': '!vue!', 21 | 22 | // #2688 23 | '[vue](vuejs.org) / [vue](vuejs.org)': 'vue / vue', 24 | '[\\](vuejs.org)': '', 25 | 26 | // #564 For multiple markdown tokens 27 | '`a` and `b`': 'a and b', 28 | '***bold and italic***': 'bold and italic', 29 | '**bold** and *italic*': 'bold and italic' 30 | } 31 | Object.keys(asserts).forEach(input => { 32 | expect(parseHeaders(input)).toBe(asserts[input]) 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/slugify.spec.ts: -------------------------------------------------------------------------------- 1 | import slugify from '../src/slugify' 2 | 3 | describe('slugify', () => { 4 | test('should slugify', () => { 5 | const asserts: Record = { 6 | 'Привет': 'привет', 7 | 'Лед üäöß': 'лед-uaoß', 8 | 'hangul 가': 'hangul-가', 9 | 'ع': 'ع', 10 | 'džℍΩ': 'dzhω', 11 | 'カi⁹': 'カi9', 12 | // ㌀ -> アパート' 13 | '㌀': decodeURIComponent('%E3%82%A2%E3%83%8F%E3%82%9A%E3%83%BC%E3%83%88'), 14 | '¼': '_1⁄4', 15 | 'džℍΩカi⁹¼': 'dzhωカi91⁄4', 16 | 'Iлtèrnåtïonɑlíƶatï߀ԉ': 'iлternationɑliƶati߀ԉ', 17 | 'Båcòл ípѕùm ðoɭ߀r ѕït aϻèt âùþê aԉᏧ߀üïlɭê ƃëéf culρá fïlèt ϻiǥnòn cuρiᏧatat ut êлim tòлɢùê.': 18 | 'bacoл-ipѕum-ðoɭ߀r-ѕit-aϻet-auþe-aԉꮷ߀uilɭe-ƃeef-culρa-filet-ϻiǥnon-cuρiꮷatat-ut-eлim-toлɢue', 19 | 'ᴎᴑᴅᴇȷʂ': 'ᴎᴑᴅᴇȷʂ', 20 | 'hambúrguer': 'hamburguer', 21 | 'hŒllœ': 'hœllœ', 22 | 'Fußball': 'fußball', 23 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZé': 'abcdefghijklmnopqrstuvwxyze' 24 | } 25 | 26 | Object.keys(asserts).forEach(input => { 27 | expect(slugify(input)).toBe(asserts[input]) 28 | }) 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/__tests__/unescapeHtml.spec.ts: -------------------------------------------------------------------------------- 1 | import unescapeHtml from '../src/unescapeHtml' 2 | 3 | test('should unescape html', () => { 4 | const input = `<div :id="'app'">` 5 | expect(unescapeHtml(input)).toBe(`
`) 6 | }) 7 | 8 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/shared-utils", 3 | "version": "1.9.10", 4 | "description": "shared-utils for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/shared-utils#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/shared-utils" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "lib/index.js", 23 | "types": "lib/index.d.ts", 24 | "files": [ 25 | "lib", 26 | "types" 27 | ], 28 | "scripts": { 29 | "tsc": "tsc", 30 | "update-index": "node scripts/update-index.js" 31 | }, 32 | "dependencies": { 33 | "chalk": "^2.3.2", 34 | "escape-html": "^1.0.3", 35 | "fs-extra": "^7.0.1", 36 | "globby": "^9.2.0", 37 | "gray-matter": "^4.0.1", 38 | "hash-sum": "^1.0.2", 39 | "semver": "^6.0.0", 40 | "toml": "^3.0.0", 41 | "upath": "^1.1.0" 42 | }, 43 | "devDependencies": { 44 | "@types/diacritics": "^1.3.1" 45 | }, 46 | "publishConfig": { 47 | "access": "public" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/scripts/update-index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs-extra') 3 | 4 | const source = path.resolve(__dirname, '../src') 5 | const target = path.resolve(source, 'index.ts') 6 | 7 | const modules = fs.readdirSync(source) 8 | .filter(v => v !== 'index.ts') 9 | .map(v => v.slice(0, v.indexOf('.'))) 10 | 11 | const getImport = (n, p) => `import * as ${n} from '${p}'` 12 | 13 | const EXPORTED_MODULES = [ 14 | 'chalk', 15 | 'fs', 16 | 'path', 17 | 'globby', 18 | ['hash-sum', 'hash'] 19 | ] 20 | 21 | const code 22 | = [ 23 | ...modules.map(v => getImport(v, `./${v}`)), 24 | ...EXPORTED_MODULES.map(v => Array.isArray(v) ? getImport(v[1], v[0]) : getImport(v, v)) 25 | ].join('\n') 26 | + `\n\nexport {\n` 27 | + [ 28 | ...modules, 29 | ...EXPORTED_MODULES.map(v => Array.isArray(v) ? v[1] : v) 30 | ].map(v => ` ${v},`).join('\n') 31 | + '\n}' 32 | 33 | fs.writeFileSync(target, code, 'utf-8') 34 | 35 | console.log('[Success] Update entry file!') 36 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/codegen.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert paths string to real-world import code. 3 | */ 4 | 5 | export function pathsToModuleCode (files: string[]) { 6 | let index = 0 7 | let code = '' 8 | 9 | code += files 10 | .map(filePath => `import m${index++} from ${JSON.stringify(filePath)}`) 11 | .join('\n') 12 | 13 | code += '\n\nexport default [\n' 14 | 15 | for (let i = 0; i < index; i++) { 16 | code += ` m${i}` 17 | code += i === index - 1 ? '\n' : ',\n' 18 | } 19 | 20 | code += ']\n' 21 | 22 | return code 23 | } 24 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/compose.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Build functional pipeline. 3 | */ 4 | 5 | type Pipe = (...args: T[]) => U 6 | 7 | export = function compose (...processors: Array>): Pipe { 8 | if (processors.length === 0) return (input: T) => input 9 | if (processors.length === 1) return processors[0] 10 | return processors.reduce((prev, next) => { 11 | return (...args: any[]) => next(prev(...args)) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/deeplyParseHeaders.ts: -------------------------------------------------------------------------------- 1 | import compose from './compose' 2 | import parseHeaders from './parseHeaders' 3 | import removeNonCodeWrappedHTML from './removeNonCodeWrappedHTML' 4 | 5 | // Also clean the html that isn't wrapped by code. 6 | // Because we want to support using VUE components in headers. 7 | // e.g. https://vuepress.vuejs.org/guide/using-vue.html#badge 8 | export = compose( 9 | removeNonCodeWrappedHTML, 10 | parseHeaders 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/ensureEndingSlash.ts: -------------------------------------------------------------------------------- 1 | export = function ensureEndingSlash (path: string): string { 2 | return /(\.html|\/)$/.test(path) 3 | ? path 4 | : path + '/' 5 | } 6 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/ensureLeadingSlash.ts: -------------------------------------------------------------------------------- 1 | export = function ensureLeadingSlash (path: string): string { 2 | return path.replace(/^\/?/, '/') 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/env.ts: -------------------------------------------------------------------------------- 1 | class ENV { 2 | isDebug: boolean; 3 | isTest: boolean; 4 | isProduction: boolean; 5 | 6 | constructor () { 7 | this.isDebug = false 8 | this.isTest = process.env.NODE_ENV === 'test' || false 9 | this.isProduction = false 10 | } 11 | 12 | setOptions (options: Record) { 13 | Object.assign(this, options) 14 | } 15 | } 16 | 17 | export = new ENV() 18 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/extractHeaders.ts: -------------------------------------------------------------------------------- 1 | import LRU from 'lru-cache' 2 | import deeplyParseHeaders from './deeplyParseHeaders' 3 | 4 | /** 5 | * Extract headers from markdown source content. 6 | * 7 | * @param {string} content 8 | * @param {array} include 9 | * @param {object} md 10 | * @returns {array} 11 | */ 12 | 13 | const cache = new LRU({ max: 1000 }) 14 | 15 | export = function (content: string, include: any[] = [], md: any) { 16 | const key = content + include.join(',') 17 | const hit = cache.get(key) 18 | if (hit) { 19 | return hit 20 | } 21 | 22 | const tokens = md.parse(content, {}) 23 | 24 | const res: any[] = [] 25 | tokens.forEach((t: any, i: any) => { 26 | if (t.type === 'heading_open' && include.includes(t.tag)) { 27 | const title = tokens[i + 1].content 28 | const slug = t.attrs.find(([name]: any[]) => name === 'id')[1] 29 | res.push({ 30 | level: parseInt(t.tag.slice(1), 10), 31 | title: deeplyParseHeaders(title), 32 | slug: slug || md.slugify(title) 33 | }) 34 | } 35 | }) 36 | 37 | cache.set(key, res) 38 | return res 39 | } 40 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/fallback.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | 3 | export function fsExistsFallback (files: string[]): string | void { 4 | for (const file of files) { 5 | if (fs.existsSync(file)) { 6 | return file 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/fileToPath.ts: -------------------------------------------------------------------------------- 1 | import { indexRE, isIndexFile } from './isIndexFile' 2 | 3 | const extRE = /\.(vue|md)$/ 4 | 5 | export = function fileToPath (file: string): string { 6 | if (isIndexFile(file)) { 7 | // README.md -> / 8 | // README.vue -> / 9 | // foo/README.md -> /foo/ 10 | // foo/README.vue -> /foo/ 11 | return file.replace(indexRE, '/$1') 12 | } else { 13 | // foo.md -> /foo.html 14 | // foo.vue -> /foo.html 15 | // foo/bar.md -> /foo/bar.html 16 | // foo/bar.vue -> /foo/bar.html 17 | return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html` 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/inferTitle.ts: -------------------------------------------------------------------------------- 1 | import deeplyParseHeaders from './deeplyParseHeaders' 2 | 3 | /** 4 | * Infer a page's title via frontmatter and content. 5 | * 6 | * @param {object} frontmatter 7 | * @param {string} strippedContent 8 | * @returns {*} 9 | */ 10 | 11 | export = function (frontmatter: Record, strippedContent: string): string | void { 12 | if (frontmatter.title) { 13 | return deeplyParseHeaders(frontmatter.title) 14 | } 15 | if (frontmatter.home) { 16 | return 'Home' 17 | } 18 | const match = strippedContent.trim().match(/^#+\s+(.*)/) 19 | if (match) { 20 | return deeplyParseHeaders(match[1]) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/isIndexFile.ts: -------------------------------------------------------------------------------- 1 | export const indexRE = /(^|.*\/)(index|readme)\.(md|vue)$/i 2 | 3 | export function isIndexFile (file: string): boolean { 4 | return indexRE.test(file) 5 | } 6 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/normalizeConfig.ts: -------------------------------------------------------------------------------- 1 | import { assertTypes } from './datatypes' 2 | import logger from './logger' 3 | import chalk from 'chalk' 4 | 5 | export default function normalizeConfig (pluginsConfig: any) { 6 | const { valid, warnMsg } = assertTypes(pluginsConfig, [Object, Array]) 7 | if (!valid) { 8 | if (pluginsConfig !== undefined) { 9 | logger.warn( 10 | `[${chalk.gray('config')}] ` 11 | + `Invalid value for "plugin" field : ${warnMsg}` 12 | ) 13 | } 14 | pluginsConfig = [] 15 | return pluginsConfig 16 | } 17 | 18 | if (Array.isArray(pluginsConfig)) { 19 | pluginsConfig = pluginsConfig.map(item => { 20 | return Array.isArray(item) ? item : [item] 21 | }) 22 | } else if (typeof pluginsConfig === 'object') { 23 | pluginsConfig = Object.keys(pluginsConfig).map(item => { 24 | return [item, pluginsConfig[item]] 25 | }) 26 | } 27 | return pluginsConfig 28 | } 29 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/parseEmojis.ts: -------------------------------------------------------------------------------- 1 | import emojiData from 'markdown-it-emoji/lib/data/full.json' 2 | 3 | export default (str: string) => { 4 | return String(str).replace(/:(.+?):/g, (placeholder, key) => emojiData[key] || placeholder) 5 | } 6 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/parseFrontmatter.ts: -------------------------------------------------------------------------------- 1 | import matter from 'gray-matter' 2 | import toml from 'toml' 3 | 4 | export = function parseFrontmatter (content: string) { 5 | return matter(content, { 6 | // eslint-disable-next-line @typescript-eslint/camelcase 7 | excerpt_separator: '', 8 | engines: { 9 | toml: toml.parse.bind(toml) 10 | } 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/parseHeaders.ts: -------------------------------------------------------------------------------- 1 | import compose from './compose' 2 | import unescapeHtml from './unescapeHtml' 3 | import parseEmojis from './parseEmojis' 4 | 5 | // Since VuePress needs to extract the header from the markdown source 6 | // file and display it in the sidebar or title (#238), this file simply 7 | // removes some unnecessary elements to make header displays well at 8 | // sidebar or title. 9 | // 10 | // But header's parsing in the markdown content is done by the markdown 11 | // loader based on markdown-it. markdown-it parser will always keep 12 | // HTML in headers, so in VuePress, after being parsed by the markdown 13 | // loader, the raw HTML in headers will finally be parsed by Vue-loader. 14 | // so that we can write HTML/Vue in the header. One exception is the HTML 15 | // wrapped by (markdown token: '`') tag. 16 | 17 | const removeMarkdownTokens = (str: string): string => String(str) 18 | .replace(/(\[(.[^\]]+)\]\((.[^)]+)\))/g, '$2') // []() 19 | .replace(/(`|\*{1,3}|_)(.*?[^\\])\1/g, '$2') // `{t}` | *{t}* | **{t}** | ***{t}*** | _{t}_ 20 | .replace(/(\\)(\*|_|`|\!|<)/g, '$2') // remove escape char '\' 21 | 22 | const trim = (str: string): string => str.trim() 23 | 24 | // Unescape html, parse emojis and remove some md tokens. 25 | const parseHeaders: (v: string) => string = compose( 26 | unescapeHtml, 27 | parseEmojis, 28 | removeMarkdownTokens, 29 | trim 30 | ) 31 | 32 | export = parseHeaders 33 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/parseVueFrontmatter.ts: -------------------------------------------------------------------------------- 1 | import { parse as _parse } from '@vue/component-compiler-utils' 2 | import parseFrontmatter from './parseFrontmatter' 3 | 4 | export function parseStrippedFrontmatter (src: string) { 5 | src = `---\n${src}\n---` 6 | return parseFrontmatter(src) 7 | } 8 | 9 | export function parse (src: string) { 10 | const output = _parse({ 11 | source: src, 12 | compiler: require('vue-template-compiler'), 13 | needMap: false 14 | }) 15 | const find = output.customBlocks.find(block => block.type === 'frontmatter') 16 | const frontmatterRaw = find && find.content 17 | if (frontmatterRaw) { 18 | return parseStrippedFrontmatter(frontmatterRaw) 19 | } 20 | return {} 21 | } 22 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/performance.ts: -------------------------------------------------------------------------------- 1 | import os from 'os' 2 | 3 | class Performance { 4 | private _totalMemory: number 5 | private _startFreeMemory: number 6 | private _endFreeMemory: number 7 | private _startTime: number 8 | private _endTime: number 9 | 10 | constructor () { 11 | this._totalMemory = os.totalmem() 12 | } 13 | 14 | start () { 15 | this._startTime = Date.now() 16 | this._startFreeMemory = os.freemem() 17 | } 18 | 19 | stop () { 20 | this._endTime = Date.now() 21 | this._endFreeMemory = os.freemem() 22 | return { 23 | duration: this._endTime - this._startTime, 24 | memoryDiff: this._endFreeMemory - this._startFreeMemory 25 | } 26 | } 27 | } 28 | 29 | export = new Performance() 30 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/removeNonCodeWrappedHTML.ts: -------------------------------------------------------------------------------- 1 | // This method remove the raw HTML but reserve the HTML wrapped by ``. 2 | // e.g. 3 | // Input: " b", Output: "b" 4 | // Input: "`` b", Output: "`` b" 5 | export = function removeNonCodeWrappedHTML (str: string): string { 6 | return String(str).replace(/(^|[^><`\\])<.*>([^><`]|$)/g, '$1$2') 7 | } 8 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/slugify.ts: -------------------------------------------------------------------------------- 1 | // string.js slugify drops non ascii chars so we have to 2 | // use a custom implementation here 3 | 4 | // eslint-disable-next-line no-control-regex 5 | const rControl = /[\u0000-\u001f]/g 6 | const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’–—<>,.?/]+/g 7 | const rCombining = /[\u0300-\u036F]/g 8 | 9 | export = function slugify (str: string): string { 10 | // Split accented characters into components 11 | return str.normalize('NFKD') 12 | // Remove accents 13 | .replace(rCombining, '') 14 | // Remove control characters 15 | .replace(rControl, '') 16 | // Replace special characters 17 | .replace(rSpecial, '-') 18 | // Remove continuous separators 19 | .replace(/\-{2,}/g, '-') 20 | // Remove prefixing and trailing separators 21 | .replace(/^\-+|\-+$/g, '') 22 | // ensure it doesn't start with a number (#121) 23 | .replace(/^(\d)/, '_$1') 24 | // lowercase 25 | .toLowerCase() 26 | } 27 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/sort.ts: -------------------------------------------------------------------------------- 1 | export = function sort (arr: number[]) { 2 | return arr.sort((a, b) => { 3 | if (a < b) return -1 4 | if (a > b) return 1 5 | return 0 6 | }) 7 | } 8 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/toAbsolutePath.ts: -------------------------------------------------------------------------------- 1 | import path from 'upath' 2 | 3 | /** 4 | * Normalize path request to absolute path. 5 | */ 6 | 7 | export = function toAbsolutePath (raw: string, cwd: string = process.cwd()) { 8 | if (path.isAbsolute(raw)) { 9 | return raw 10 | } 11 | return path.resolve(cwd, raw) 12 | } 13 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/tryChain.ts: -------------------------------------------------------------------------------- 1 | type Provider = (arg: T) => U 2 | type Resolver = (Provider | boolean)[] | Provider 3 | 4 | export = function tryChain (resolvers: Array>, arg: T): U | void { 5 | let response: U 6 | 7 | for (let resolver of resolvers) { 8 | if (!Array.isArray(resolver)) { 9 | resolver = [resolver, true] 10 | } 11 | const [provider, condition] = resolver 12 | if (!condition) { 13 | continue 14 | } 15 | try { 16 | response = (provider as Provider)(arg) 17 | return response 18 | } catch (e) { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/src/unescapeHtml.ts: -------------------------------------------------------------------------------- 1 | export = (html: string): string => String(html) 2 | .replace(/"/g, '"') 3 | .replace(/'/g, '\'') 4 | .replace(/:/g, ':') 5 | .replace(/</g, '<') 6 | .replace(/>/g, '>') 7 | 8 | -------------------------------------------------------------------------------- /packages/@vuepress/shared-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "declarationDir": "types" 6 | }, 7 | "include": [ 8 | "./src" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/test-utils 2 | 3 | > test-utils for VuePress 4 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/client/createLocalVue.js: -------------------------------------------------------------------------------- 1 | import Router from 'vue-router' 2 | import VuePress from '@vuepress/core/lib/client/plugins/VuePress' 3 | import dataMixin from '@vuepress/core/lib/client/dataMixin' 4 | import { createLocalVue } from '@vue/test-utils' 5 | 6 | import mockComponent from './mockComponent' 7 | import siteData from './siteData' 8 | import ClientComputedMixin from '@vuepress/core/lib/node/ClientComputedMixin' 9 | 10 | module.exports = function () { 11 | const localVue = createLocalVue() 12 | localVue.use(Router) 13 | localVue.use(VuePress) 14 | 15 | // register global component 16 | localVue.component('OutboundLink', mockComponent('outbound-link')) 17 | localVue.component(siteData.pages[0].key, mockComponent('page-component')) 18 | localVue.mixin(dataMixin(ClientComputedMixin, siteData, localVue)) 19 | return localVue 20 | } 21 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/client/index.js: -------------------------------------------------------------------------------- 1 | import createLocalVue from './createLocalVue' 2 | import mockComponent from './mockComponent' 3 | 4 | export { 5 | createLocalVue, 6 | mockComponent 7 | } 8 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/client/mockComponent.js: -------------------------------------------------------------------------------- 1 | const Component = { 2 | props: ['name'], 3 | render (h) { 4 | return h('p', { 5 | class: ['component', this.name] 6 | }, this.name) 7 | } 8 | } 9 | 10 | // When the child component is a pure presentation component, 11 | // we want to be able to display a sub-component with minimal info, 12 | // rather than stubbing it directly. 13 | export default function mockComponent (name) { 14 | return { 15 | render (h) { 16 | return h(Component, { props: { name }}) 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/client/siteData.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | export default { 4 | "title": "VuePress", 5 | "description": "", 6 | "base": "/", 7 | "pages": [ 8 | { 9 | "title": "Hello, VuePress!", 10 | "frontmatter": {}, 11 | "key": "v-37b29011bd265", 12 | "path": "/", 13 | "regularPath": "/" 14 | }, 15 | { 16 | "title": "你好, VuePress!", 17 | "frontmatter": {}, 18 | "key": "v-6a0244c805bde", 19 | "path": "/zh/", 20 | "regularPath": "/zh/" 21 | } 22 | ], 23 | "themeConfig": { 24 | "repo": "vuejs/vuepress", 25 | "editLinks": true, 26 | "docsDir": "docs", 27 | "locales": { 28 | "/": { 29 | "label": "English", 30 | "selectText": "Languages", 31 | "editLinkText": "Edit this page on GitHub", 32 | "lastUpdated": "Last Updated" 33 | }, 34 | "/zh/": { 35 | "label": "简体中文", 36 | "selectText": "选择语言", 37 | "editLinkText": "在 GitHub 上编辑此页", 38 | "lastUpdated": "上次更新" 39 | } 40 | } 41 | }, 42 | "locales": { 43 | "/": { 44 | "lang": "en-US", 45 | "title": "VuePress", 46 | "description": "Vue-powered Static Site Generator", 47 | "path": "/" 48 | }, 49 | "/zh/": { 50 | "lang": "zh-CN", 51 | "title": "VuePress", 52 | "description": "Vue 驱动的静态网站生成器", 53 | "path": "/zh/" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/fixtures/docs/.vuepress/theme/Layout.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/fixtures/docs/README.md: -------------------------------------------------------------------------------- 1 | # App 2 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/index.js: -------------------------------------------------------------------------------- 1 | const getFragment = require('./lib/getFragment') 2 | const getFragments = require('./lib/getFragments') 3 | const createJestRunner = require('./lib/createJestRunner') 4 | const createJestConfig = require('./lib/createJestConfig') 5 | 6 | module.exports = { 7 | getFragment, 8 | getFragments, 9 | createJestRunner, 10 | createJestConfig 11 | } 12 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/lib/createJestConfig.js: -------------------------------------------------------------------------------- 1 | const defaultJestConfig = require('./jest.config') 2 | 3 | module.exports = function createJestConfig (override) { 4 | return Object.assign({}, defaultJestConfig, override) 5 | } 6 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/lib/getFragment.js: -------------------------------------------------------------------------------- 1 | const LRU = require('lru-cache') 2 | const { fs, path } = require('@vuepress/shared-utils') 3 | 4 | const cache = new LRU({ max: 1000 }) 5 | 6 | module.exports = function getFragment (dirname, name, fragmentsDir = 'fragments') { 7 | const target = path.resolve(dirname, `${fragmentsDir}/${name}`) 8 | let content = cache.get(target) 9 | if (content) { 10 | return content 11 | } 12 | content = fs.readFileSync(target, 'utf-8') 13 | cache.set(target, content) 14 | return content 15 | } 16 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/lib/getFragments.js: -------------------------------------------------------------------------------- 1 | const { fs, path } = require('@vuepress/shared-utils') 2 | const getFragment = require('./getFragment') 3 | 4 | module.exports = function getFragments (dirname, fragmentsDir = 'fragments') { 5 | const names = fs.readdirSync(path.join(dirname, fragmentsDir)) 6 | return names.map(name => { 7 | const content = getFragment(dirname, name, fragmentsDir) 8 | return { 9 | name, 10 | content 11 | } 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/lib/jest.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '..'), 5 | verbose: true, 6 | testURL: 'http://localhost/', 7 | moduleFileExtensions: [ 8 | 'js', 9 | 'vue', 10 | 'ts', 11 | 'json' 12 | ], 13 | testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.(ts|js)?$', 14 | testPathIgnorePatterns: [ 15 | 'test.js', 16 | path.resolve(__dirname, '../test') 17 | ], 18 | moduleNameMapper: { 19 | '^@/(.*)$': '/$1' 20 | }, 21 | transform: { 22 | '^.+\\.js$': '/node_modules/babel-jest', 23 | '.*\\.(vue)$': '/node_modules/vue-jest', 24 | '^.+\\.ts?$': '/node_modules/ts-jest' 25 | }, 26 | snapshotSerializers: [ 27 | '/node_modules/jest-serializer-vue' 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/@vuepress/test-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/test-utils", 3 | "version": "1.9.10", 4 | "description": "test-utils for vuepress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/test-utils#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/test-utils" 19 | }, 20 | "license": "MIT", 21 | "author": "ULIVZ ", 22 | "main": "index.js", 23 | "dependencies": { 24 | "@babel/core": "^7.0.0", 25 | "@babel/preset-env": "^7.0.0", 26 | "@types/jest": "^24.0.9", 27 | "@vue/test-utils": "^1.0.0-beta.29", 28 | "@vuepress/core": "1.9.10", 29 | "@vuepress/shared-utils": "1.9.10", 30 | "babel-jest": "^24.7.1", 31 | "execa": "^1.0.0", 32 | "jest": "^24.7.1", 33 | "jest-serializer-vue": "^2.0.2", 34 | "ts-jest": "^24.0.2", 35 | "vue": "^2.6.10", 36 | "vue-jest": "^4.0.0-beta.1", 37 | "vue-template-compiler": "^2.6.10" 38 | }, 39 | "publishConfig": { 40 | "access": "public" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ 3 | .temp 4 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/theme-default 2 | 3 | > theme-default for VuePress 4 | 5 | ## Plugins 6 | 7 | The default theme has the following plugin built in: 8 | 9 | - [@vuepress/plugin-active-header-links](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-active-header-links) 10 | - [@vuepress/plugin-google-analytics](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-google-analytics) 11 | - [@vuepress/plugin-search](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-search) 12 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/__tests__/components/DropdownLink.spec.js: -------------------------------------------------------------------------------- 1 | import { mount, RouterLinkStub } from '@vue/test-utils' 2 | import DropdownLink from '../../components/DropdownLink.vue' 3 | import { createLocalVue } from '@vuepress/test-utils/client' 4 | 5 | describe('DropdownLink', () => { 6 | test('renders dropdown link.', () => { 7 | const item = { 8 | text: 'Learn More', 9 | ariaLabel: 'Learn More Select', 10 | items: [ 11 | { 12 | text: 'Guide', 13 | link: '/guide/' 14 | }, 15 | { 16 | text: 'Config Reference', 17 | link: '/config/' 18 | } 19 | ] 20 | } 21 | const wrapper = mount(DropdownLink, { 22 | localVue: createLocalVue(), 23 | stubs: { 24 | 'RouterLink': RouterLinkStub 25 | }, 26 | propsData: { item } 27 | }) 28 | expect(wrapper.html()).toMatchSnapshot() 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/__tests__/components/NavLink.spec.js: -------------------------------------------------------------------------------- 1 | import { mount, RouterLinkStub } from '@vue/test-utils' 2 | import { createLocalVue } from '@vuepress/test-utils/client' 3 | import NavLink from '../../components/NavLink.vue' 4 | 5 | describe('NavLink', () => { 6 | test('renders nav link with internal link', () => { 7 | const item = { 8 | link: '/', 9 | text: 'VuePress' 10 | } 11 | const wrapper = mount(NavLink, { 12 | localVue: createLocalVue(), 13 | stubs: { 14 | 'RouterLink': RouterLinkStub 15 | }, 16 | propsData: { item } 17 | }) 18 | expect(wrapper.html()).toMatchSnapshot() 19 | }) 20 | 21 | test('renders nav link with external link', () => { 22 | const item = { 23 | link: 'http://vuejs.org/', 24 | text: 'Vue' 25 | } 26 | const wrapper = mount(NavLink, { 27 | localVue: createLocalVue(), 28 | propsData: { item } 29 | }) 30 | expect(wrapper.html()).toMatchSnapshot() 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/__tests__/components/__snapshots__/DropdownLink.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`DropdownLink renders dropdown link. 1`] = ` 4 | 16 | `; 17 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/__tests__/components/__snapshots__/NavLink.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`NavLink renders nav link with external link 1`] = ` 4 | 5 | Vue 6 | 7 | `; 8 | 9 | exports[`NavLink renders nav link with internal link 1`] = ` 10 | 11 | VuePress 12 | 13 | `; 14 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/components/DropdownTransition.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/components/Page.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 32 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/components/SidebarButton.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 41 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/global-components/Badge.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/global-components/CodeBlock.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 30 | 31 | 42 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/layouts/404.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 31 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/noopModule.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/theme-default", 3 | "version": "1.9.10", 4 | "description": "Default theme for VuePress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/theme-default#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/theme-default" 19 | }, 20 | "license": "MIT", 21 | "author": "Evan You", 22 | "maintainers": [ 23 | { 24 | "name": "ULIVZ", 25 | "email": "chl814@foxmail.com" 26 | } 27 | ], 28 | "main": "index.js", 29 | "dependencies": { 30 | "@vuepress/plugin-active-header-links": "1.9.10", 31 | "@vuepress/plugin-nprogress": "1.9.10", 32 | "@vuepress/plugin-search": "1.9.10", 33 | "@vuepress/types": "1.9.10", 34 | "docsearch.js": "^2.5.2", 35 | "lodash": "^4.17.15", 36 | "stylus": "^0.54.8", 37 | "stylus-loader": "^3.0.2", 38 | "vuepress-plugin-container": "^2.0.2", 39 | "vuepress-plugin-smooth-scroll": "^0.0.3" 40 | }, 41 | "publishConfig": { 42 | "access": "public" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/arrow.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | .arrow 4 | display inline-block 5 | width 0 6 | height 0 7 | &.up 8 | border-left 4px solid transparent 9 | border-right 4px solid transparent 10 | border-bottom 6px solid $arrowBgColor 11 | &.down 12 | border-left 4px solid transparent 13 | border-right 4px solid transparent 14 | border-top 6px solid $arrowBgColor 15 | &.right 16 | border-top 4px solid transparent 17 | border-bottom 4px solid transparent 18 | border-left 6px solid $arrowBgColor 19 | &.left 20 | border-top 4px solid transparent 21 | border-bottom 4px solid transparent 22 | border-right 6px solid $arrowBgColor 23 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/config.styl: -------------------------------------------------------------------------------- 1 | $contentClass = '.theme-default-content' 2 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/custom-blocks.styl: -------------------------------------------------------------------------------- 1 | .custom-block 2 | .custom-block-title 3 | font-weight 600 4 | margin-bottom -0.4rem 5 | &.tip, &.warning, &.danger 6 | padding .1rem 1.5rem 7 | border-left-width .5rem 8 | border-left-style solid 9 | margin 1rem 0 10 | &.tip 11 | background-color #f3f5f7 12 | border-color #42b983 13 | &.warning 14 | background-color rgba(255,229,100,.3) 15 | border-color darken(#ffe564, 35%) 16 | color darken(#ffe564, 70%) 17 | .custom-block-title 18 | color darken(#ffe564, 50%) 19 | a 20 | color $textColor 21 | &.danger 22 | background-color #ffe6e6 23 | border-color darken(red, 20%) 24 | color darken(red, 70%) 25 | .custom-block-title 26 | color darken(red, 40%) 27 | a 28 | color $textColor 29 | &.details 30 | display block 31 | position relative 32 | border-radius 2px 33 | margin 1.6em 0 34 | padding 1.6em 35 | background-color #eee 36 | h4 37 | margin-top 0 38 | figure, p 39 | &:last-child 40 | margin-bottom 0 41 | padding-bottom 0 42 | summary 43 | outline none 44 | cursor pointer 45 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/mobile.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | $mobileSidebarWidth = $sidebarWidth * 0.82 4 | 5 | // narrow desktop / iPad 6 | @media (max-width: $MQNarrow) 7 | .sidebar 8 | font-size 15px 9 | width $mobileSidebarWidth 10 | .page 11 | padding-left $mobileSidebarWidth 12 | 13 | // wide mobile 14 | @media (max-width: $MQMobile) 15 | .sidebar 16 | top 0 17 | padding-top $navbarHeight 18 | transform translateX(-100%) 19 | transition transform .2s ease 20 | .page 21 | padding-left 0 22 | .theme-container 23 | &.sidebar-open 24 | .sidebar 25 | transform translateX(0) 26 | &.no-navbar 27 | .sidebar 28 | padding-top: 0 29 | 30 | // narrow mobile 31 | @media (max-width: $MQMobileNarrow) 32 | h1 33 | font-size 1.9rem 34 | {$contentClass} 35 | div[class*="language-"] 36 | margin 0.85rem -1.5rem 37 | border-radius 0 38 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/toc.styl: -------------------------------------------------------------------------------- 1 | .table-of-contents 2 | .badge 3 | vertical-align middle 4 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-default/styles/wrapper.styl: -------------------------------------------------------------------------------- 1 | $wrapper 2 | max-width $contentWidth 3 | margin 0 auto 4 | padding 2rem 2.5rem 5 | @media (max-width: $MQNarrow) 6 | padding 2rem 7 | @media (max-width: $MQMobileNarrow) 8 | padding 1.5rem 9 | 10 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-vue/.npmignore: -------------------------------------------------------------------------------- 1 | __tests__ 2 | __mocks__ -------------------------------------------------------------------------------- /packages/@vuepress/theme-vue/README.md: -------------------------------------------------------------------------------- 1 | # @vuepress/theme-vue 2 | 3 | > theme-vue for VuePress 4 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-vue/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extend: '@vuepress/theme-default' 3 | } 4 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-vue/layouts/Layout.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | -------------------------------------------------------------------------------- /packages/@vuepress/theme-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/theme-vue", 3 | "version": "1.9.10", 4 | "description": "VuePress theme for official Vue projects", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "vue", 9 | "vuepress" 10 | ], 11 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/theme-vue#readme", 12 | "bugs": { 13 | "url": "https://github.com/vuejs/vuepress/issues" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/vuejs/vuepress.git", 18 | "directory": "packages/@vuepress/theme-vue" 19 | }, 20 | "license": "MIT", 21 | "author": "Evan You", 22 | "maintainers": [ 23 | { 24 | "name": "ULIVZ", 25 | "email": "chl814@foxmail.com" 26 | } 27 | ], 28 | "main": "index.js", 29 | "dependencies": { 30 | "@vuepress/theme-default": "1.9.10" 31 | }, 32 | "publishConfig": { 33 | "access": "public" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/@vuepress/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | UserConfig, 3 | ThemeConfig, 4 | PluginOptions, 5 | DefaultThemeConfig, 6 | Theme, 7 | Plugin 8 | } from "./src"; 9 | 10 | export * from "./src"; 11 | 12 | /** 13 | * A helper function to define VuePress config file. 14 | * 15 | * @see https://vuepress.vuejs.org/config/ 16 | */ 17 | export function defineConfig(config: UserConfig): void; 18 | 19 | /** 20 | * A helper function to define VuePress config file, for custom theme. 21 | * 22 | * @see https://vuepress.vuejs.org/config/ 23 | */ 24 | export function defineConfig4CustomTheme( 25 | config: UserConfig 26 | ): void; 27 | 28 | /** 29 | * A helper function to define VuePress theme entry file. 30 | * 31 | * @see https://vuepress.vuejs.org/theme/option-api.html 32 | */ 33 | export function defineTheme( 34 | config: Theme 35 | ): void; 36 | 37 | /** 38 | * A helper function to define VuePress theme entry file. 39 | * 40 | * @see https://vuepress.vuejs.org/plugin/writing-a-plugin.html 41 | */ 42 | export function definePlugin< 43 | T extends PluginOptions = PluginOptions, 44 | U extends ThemeConfig = ThemeConfig 45 | >(config: Plugin): void; 46 | -------------------------------------------------------------------------------- /packages/@vuepress/types/index.js: -------------------------------------------------------------------------------- 1 | function define(config) { 2 | return config; 3 | } 4 | exports.defineConfig = define; 5 | exports.defineConfig4CustomTheme = define; 6 | exports.defineTheme = define; 7 | exports.definePlugin = define; 8 | -------------------------------------------------------------------------------- /packages/@vuepress/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vuepress/types", 3 | "version": "1.9.10", 4 | "description": "Types for VuePress", 5 | "keywords": [ 6 | "documentation", 7 | "generator", 8 | "types", 9 | "vue", 10 | "vuepress" 11 | ], 12 | "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/types#readme", 13 | "bugs": { 14 | "url": "https://github.com/vuejs/vuepress/issues" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/vuejs/vuepress.git", 19 | "directory": "packages/@vuepress/types" 20 | }, 21 | "license": "MIT", 22 | "author": "ULIVZ", 23 | "main": "index.js", 24 | "types": "index.d.ts", 25 | "scripts": { 26 | "tsc": "tsc" 27 | }, 28 | "dependencies": { 29 | "@types/markdown-it": "^10.0.0", 30 | "@types/webpack-dev-server": "^3", 31 | "webpack-chain": "^6.0.0" 32 | }, 33 | "publishConfig": { 34 | "access": "public" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/@vuepress/types/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config' 2 | export * from './locale' 3 | export * from './markdown' 4 | export * from './style' 5 | export * from './context' 6 | export * from './theme-default' 7 | export * from './theme' 8 | export * from './plugin' 9 | export * from './plugin-api' 10 | export * from "./third-party-plugins" 11 | export * from "./official-plugins" 12 | -------------------------------------------------------------------------------- /packages/@vuepress/types/src/locale.ts: -------------------------------------------------------------------------------- 1 | import { Lang } from "./lang"; 2 | /** 3 | * Local config. 4 | */ 5 | export interface LocaleConfig { 6 | /** 7 | * Locale's lang 8 | */ 9 | lang: Lang; 10 | /** 11 | * Locale's title 12 | */ 13 | title: string; 14 | /** 15 | * Locale's description 16 | */ 17 | description: string; 18 | } 19 | 20 | export type Locales = { [path: string]: LocaleConfig }; 21 | -------------------------------------------------------------------------------- /packages/@vuepress/types/src/shared.ts: -------------------------------------------------------------------------------- 1 | import ChainWebpackConfig from "webpack-chain"; 2 | 3 | export type ChainWebpack = (config: ChainWebpackConfig, isServer: boolean) => void; 4 | 5 | export type Hook = (...arg: U) => R; 6 | 7 | export type AsyncHook = Hook< 8 | U, 9 | Promise 10 | >; 11 | 12 | export type PluginObject = Record; -------------------------------------------------------------------------------- /packages/@vuepress/types/src/site-data.ts: -------------------------------------------------------------------------------- 1 | import { Page } from "./context"; 2 | import { ThemeConfig } from "./theme"; 3 | import { Locales } from "./locale"; 4 | import { HeadTags } from "./config"; 5 | 6 | export interface SiteData { 7 | title: string; 8 | description: string; 9 | base: string; 10 | pages: Page[]; 11 | headTags: HeadTags; 12 | themeConfig: T; 13 | locales: Locales; 14 | } 15 | -------------------------------------------------------------------------------- /packages/@vuepress/types/src/style.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * postcss-loader does not provide official typings, so we extract types from: 3 | * 4 | * @see https://github.com/webpack-contrib/postcss-loader/tree/v3.0.0 5 | */ 6 | export interface PostCssLoaderOptions { 7 | /** 8 | * Postcss plugins 9 | */ 10 | plugins?: unknown[]; 11 | /** 12 | * Enables/Disables generation of source maps 13 | */ 14 | sourceMap?: boolean; 15 | /** 16 | * Omit other options 17 | */ 18 | [key: string]: any; 19 | } 20 | -------------------------------------------------------------------------------- /packages/@vuepress/types/src/third-party-plugins.ts: -------------------------------------------------------------------------------- 1 | export type KnownThirdPartyPlugins = 2 | /** 3 | * Plugins from VuePress Community 4 | * 5 | * @see https://vuepress-community.netlify.app/en/plugins/clean-urls/ 6 | */ 7 | | "vuepress-plugin-container" 8 | | "vuepress-plugin-copyright" 9 | | "vuepress-plugin-dehydrate" 10 | | "vuepress-plugin-git-log" 11 | | "vuepress-plugin-mathjax" 12 | | "vuepress-plugin-medium-zoom" 13 | | "vuepress-plugin-migrate" 14 | | "vuepress-plugin-named-chunks" 15 | | "vuepress-plugin-nprogress" 16 | | "vuepress-plugin-redirect" 17 | | "vuepress-plugin-serve" 18 | | "vuepress-plugin-smooth-scroll" 19 | | "vuepress-plugin-table-of-contents" 20 | | "vuepress-plugin-typescript" 21 | | "vuepress-plugin-zooming" 22 | /** 23 | * Other third-party plugins. 24 | */ 25 | | "vuepress-plugin-flowchart"; 26 | -------------------------------------------------------------------------------- /packages/@vuepress/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "noEmit": true, 6 | "outDir": "./lib", 7 | "noImplicitAny": true 8 | }, 9 | "include": ["./src"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/docs/.remarkrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "preset-lint-recommended", 4 | "preset-lint-consistent", 5 | 6 | ["lint-list-item-indent", "space"], 7 | ["lint-heading-style", false] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/docs/.textlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rules: { 3 | "@textlint-rule/no-unmatched-pair": true, 4 | apostrophe: true, 5 | "common-misspellings": true, 6 | diacritics: true, 7 | "en-capitalization": false, 8 | "stop-words": { 9 | severity: "warning" 10 | }, 11 | terminology: { 12 | terms: [ 13 | "VuePress", 14 | "sass", 15 | [ 16 | "front[- ]matter", 17 | "frontmatter" 18 | ] 19 | ] 20 | }, 21 | "write-good": { 22 | severity: "warning" 23 | } 24 | }, 25 | filters: { 26 | comments: true 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/components/Foo/Bar.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/components/OtherComponent.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/components/UpgradePath.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 36 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/components/demo-1.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/components/svg-container.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/config/index.ts: -------------------------------------------------------------------------------- 1 | export * from './nav/en' 2 | export * from './nav/zh' 3 | export * from './sidebar/en' 4 | export * from './sidebar/zh' 5 | 6 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/config/sidebar/en.ts: -------------------------------------------------------------------------------- 1 | import { SidebarConfig4Multiple } from 'vuepress/config' 2 | import { 3 | getApiSidebar, 4 | getGuideSidebar, 5 | getPluginSidebar, 6 | getThemeSidebar 7 | } from './shared' 8 | 9 | export const Sidebar4EN: SidebarConfig4Multiple = { 10 | '/api/': getApiSidebar(), 11 | '/guide/': getGuideSidebar('Guide', 'Advanced'), 12 | '/plugin/': getPluginSidebar('Plugin', 'Introduction', 'Official Plugins'), 13 | '/theme/': getThemeSidebar('Theme', 'Introduction') 14 | } 15 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/config/sidebar/zh.ts: -------------------------------------------------------------------------------- 1 | import { SidebarConfig4Multiple } from 'vuepress/config' 2 | import { 3 | getApiSidebar, 4 | getGuideSidebar, 5 | getPluginSidebar, 6 | getThemeSidebar 7 | } from './shared' 8 | 9 | export const Sidebar4ZH: SidebarConfig4Multiple = { 10 | '/zh/api/': getApiSidebar(), 11 | '/zh/guide/': getGuideSidebar('指南', '深入'), 12 | '/zh/plugin/': getPluginSidebar('插件', '介绍', '官方插件'), 13 | '/zh/theme/': getThemeSidebar('主题', '介绍') 14 | } 15 | 16 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | export default ({ Vue, isServer }) => { 2 | if (!isServer) { 3 | import('vue-toasted' /* webpackChunkName: "notification" */).then((module) => { 4 | Vue.use(module.default) 5 | }) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/images/logo.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/architecture.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/assets/1.9-lang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/assets/1.9-lang.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/assets/1.9-official-plugin-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/assets/1.9-official-plugin-options.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/assets/1.9-official-plugin-tuple-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/assets/1.9-official-plugin-tuple-usage.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/assets/1.9-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/assets/1.9-overview.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/hero.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/icons/mstile-150x150.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/line-numbers-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/line-numbers-desktop.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/line-numbers-mobile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/line-numbers-mobile.gif -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/logo.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "VuePress", 3 | "short_name": "VuePress", 4 | "icons": [ 5 | { 6 | "src": "/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "/index.html", 17 | "display": "standalone", 18 | "background_color": "#fff", 19 | "theme_color": "#3eaf7c" 20 | } 21 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/public/plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs/vuepress/9fb4bb00925d9409e6732118e996411c6a82c85d/packages/docs/docs/.vuepress/public/plugin.png -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | // placeholder for test, dont't remove it. 2 | 3 | //.content { 4 | // font-size 30px; 5 | //} 6 | 7 | pre.vue-container 8 | border-left-width: .5rem; 9 | border-left-style: solid; 10 | border-color: #42b983; 11 | border-radius: 0px; 12 | & > code 13 | font-size: 14px !important; 14 | & > p 15 | margin: -5px 0 -20px 0; 16 | code 17 | background-color: #42b983 !important; 18 | padding: 3px 5px; 19 | border-radius: 3px; 20 | color #000 21 | em 22 | color #808080 23 | font-weight light 24 | 25 | -------------------------------------------------------------------------------- /packages/docs/docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | // placeholder for test, dont't remove it. 2 | 3 | //$accentColor = #f00 4 | -------------------------------------------------------------------------------- /packages/docs/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /hero.png 4 | actionText: Get Started → 5 | actionLink: /guide/getting-started.html 6 | --- 7 | 8 |
9 |
10 |

Simplicity First

11 |

Minimal setup with markdown-centered project structure helps you focus on writing.

12 |
13 |
14 |

Vue-Powered

15 |

Enjoy the dev experience of Vue + webpack, use Vue components in markdown, and develop custom themes with Vue.

16 |
17 |
18 |

Performant

19 |

VuePress generates pre-rendered static HTML for each page, and runs as an SPA once a page is loaded.

20 |
21 |
22 | 23 | ::: slot footer 24 | MIT Licensed | Copyright © 2018-present [Evan You](https://github.com/yyx990803) 25 | ::: -------------------------------------------------------------------------------- /packages/docs/docs/plugin/context-api.md: -------------------------------------------------------------------------------- 1 | # Context API 2 | 3 | Starting with VuePress 1.x.x, VuePress provides an `AppContext` object that stores all the state of the current app and can be accessed through the plugin API. 4 | 5 | ::: warning Note 6 | Context of each plugin is a isolated context inherited from the same app context. 7 | ::: 8 | 9 | ```js 10 | module.exports = (options, ctx) => { 11 | // ... 12 | } 13 | ``` 14 | 15 | ## ctx.isProd 16 | 17 | - Type: `boolean` 18 | 19 | Whether VuePress run in production environment mode. 20 | 21 | ## ctx.pages 22 | 23 | - Type: `array` 24 | 25 | Contains a list of Page objects 26 | 27 | ## ctx.sourceDir 28 | 29 | - Type: `string` 30 | 31 | Root directory where the documents are located. 32 | 33 | ## ctx.tempPath 34 | 35 | - Type: `string` 36 | 37 | Root directory where the temporary files are located. 38 | 39 | ## ctx.outDir 40 | 41 | - Type: `string` 42 | 43 | Output path. 44 | 45 | ## ctx.base 46 | 47 | - Type: `string` 48 | 49 | See: [base](../config/README.md#base). 50 | 51 | ## ctx.writeTemp 52 | 53 | - Type: `Function` 54 | 55 | A utility for writing temporary files to tempPath. 56 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/life-cycle.md: -------------------------------------------------------------------------------- 1 | # Lifecycle 2 | 3 | ## ready 4 | 5 | - Type: `AsyncFunction` 6 | - Scope:`dev|build` 7 | 8 | ```js 9 | module.exports = { 10 | async ready() { 11 | // ... 12 | } 13 | } 14 | ``` 15 | 16 | ::: tip 17 | The `ready` hook is executed after the application is initialized and before some specific functional APIs are executed. These functional APIs include: 18 | 19 | - [clientDynamicModules](./option-api.md#clientdynamicmodules) 20 | - [enhanceAppFiles](./option-api.md#enhanceappfiles) 21 | 22 | ::: 23 | 24 | ## updated 25 | 26 | - Type: `Function` 27 | - Scope:`dev` 28 | 29 | ```js 30 | module.exports = { 31 | updated() { 32 | // ... 33 | } 34 | } 35 | ``` 36 | 37 | ## generated 38 | 39 | - Type: `AsyncFunction` 40 | - Scope:`build` 41 | 42 | Called when a (production) build finishes, with an array of generated page HTML paths. 43 | 44 | ``` js 45 | module.exports = { 46 | async generated (pagePaths) { 47 | // ... 48 | } 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/official/plugin-active-header-links.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: active-header-links 3 | metaTitle: A plugin of automatically activating sidebar links when page scrolls | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-active-header-links](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-active-header-links) 7 | 8 | > A plugin of automatically activating sidebar links when page scrolls 9 | 10 | ## Install 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-active-header-links 14 | # OR npm install -D @vuepress/plugin-active-header-links 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/active-header-links'] 22 | } 23 | ``` 24 | 25 | ### Passing Options 26 | 27 | ```javascript 28 | module.exports = { 29 | plugins: ['@vuepress/active-header-links', { 30 | sidebarLinkSelector: '.sidebar-link', 31 | headerAnchorSelector: '.header-anchor' 32 | }] 33 | } 34 | ``` 35 | 36 | ## Options 37 | 38 | ### sidebarLinkSelector 39 | 40 | - Type: `string` 41 | - Default: `.sidebar-link` 42 | 43 | ### headerAnchorSelector 44 | 45 | - Type: `string` 46 | - Default: `.header-anchor` 47 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/official/plugin-back-to-top.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: back-to-top 3 | metaTitle: Back-To-Top Plugin | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-back-to-top](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-back-to-top) 7 | 8 | > Back-to-top plugin 9 | 10 | ## Install 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-back-to-top 14 | # OR npm install -D @vuepress/plugin-back-to-top 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/back-to-top'] 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/official/plugin-blog.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: blog 3 | metaTitle: Blog plugin | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-blog](https://github.com/vuepressjs/vuepress-plugin-blog) 7 | 8 | ## Features 9 | 10 | - [**Classification**](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html#document-classifier): 11 | Powerful classification system lets you quickly classify your posts. 12 | - [**Pagination**](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html#pagination): 13 | Pagination runs through the entire plugin, and it has never been so simple. 14 | - [**Client APIs**](https://vuepress-plugin-blog.billyyyyy3320.com/client-api/): Simple client APIs make it easier for you to write a blog theme. 15 | 16 | ## Install 17 | 18 | We strongly recommend that you read the [Getting Started](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html) section before using this plugin. 19 | 20 | ```bash 21 | yarn add -D @vuepress/plugin-blog 22 | # OR npm install -D @vuepress/plugin-blog 23 | ``` 24 | 25 | ## Usage 26 | 27 | ```javascript 28 | module.exports = { 29 | plugins: ['@vuepress/blog'] 30 | } 31 | ``` 32 | 33 | Please head [documentation](https://vuepress-theme-blog.billyyyyy3320.com/) to see all available options. 34 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/official/plugin-google-analytics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: google-analytics 3 | metaTitle: Google Analytics Plugin | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-google-analytics](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-google-analytics) 7 | 8 | 9 | > Google analytics plugin 10 | 11 | ## Install 12 | 13 | ```bash 14 | yarn add -D @vuepress/plugin-google-analytics 15 | # OR npm install -D @vuepress/plugin-google-analytics 16 | ``` 17 | 18 | ::: warning 19 | We currently recommend using [Yarn](https://yarnpkg.com/en/) instead of npm to install all dependencies if you are using Google Analytics Plugin, because npm fails to generate the correct dependency tree in this case. 20 | ::: 21 | 22 | ## Usage 23 | 24 | ```javascript 25 | module.exports = { 26 | plugins: [ 27 | [ 28 | '@vuepress/google-analytics', 29 | { 30 | 'ga': '' // UA-00000000-0 31 | } 32 | ] 33 | ] 34 | } 35 | ``` 36 | 37 | ::: tip 38 | Please be aware of [GDPR (2018 reform of EU data protection rules)](https://ec.europa.eu/commission/priorities/justice-and-fundamental-rights/data-protection/2018-reform-eu-data-protection-rules_en) as IPs are anonymized automatically. 39 | ::: 40 | 41 | ## Options 42 | 43 | ### ga 44 | 45 | - Type: `string` 46 | - Default: `undefined` 47 | 48 | Provide the Google Analytics ID to enable integration. 49 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/official/plugin-nprogress.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: nprogress 3 | metaTitle: Nprogress Plugin | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-nprogress](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-nprogress) 7 | 8 | > A progress bar plugin based on [nprogress](https://github.com/rstacruz/nprogress). 9 | 10 | ## Install 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-nprogress 14 | # OR npm install -D @vuepress/plugin-nprogress 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/nprogress'] 22 | } 23 | ``` 24 | 25 | ## Custom color 26 | 27 | Set `$nprogressColor` in your __site__ or __theme__ `palette.styl` file to change the color of the progress bar (default is `$accentColor`). 28 | 29 | ```stylus 30 | // .vuepress/styles/palette.styl 31 | // or 32 | // .vuepress/theme/styles/palette.styl 33 | 34 | $nprogressColor = red 35 | ``` 36 | 37 | __Also see:__ 38 | 39 | - [Config Reference > Styling](../../config/README.md#styling) 40 | -------------------------------------------------------------------------------- /packages/docs/docs/plugin/writing-a-plugin.md: -------------------------------------------------------------------------------- 1 | # Writing a Plugin 2 | 3 | A plugin should export a `plain JavaScript object`(`#1`). If the plugin needs to take options, it can be a function that returns a plain object(`#2`). The function will be called with the plugin’s options as the first argument, along with [ctx](./context-api.md) which provides some compile-time metadata. 4 | 5 | ``` js 6 | // #1 7 | module.exports = { 8 | // ... 9 | } 10 | ``` 11 | 12 | ``` js 13 | // #2 14 | module.exports = (options, ctx) => { 15 | return { 16 | // ... 17 | } 18 | } 19 | ``` 20 | 21 | ::: tip 22 | A VuePress plugin module should be a `CommonJS Module` because VuePress plugins runs on the Node.js side. 23 | ::: 24 | -------------------------------------------------------------------------------- /packages/docs/docs/theme/README.md: -------------------------------------------------------------------------------- 1 | # Theme 2 | 3 | ::: tip 4 | Theme components are under the same [browser API access restrictions](../guide/using-vue.md#browser-api-access-restrictions). 5 | ::: 6 | -------------------------------------------------------------------------------- /packages/docs/docs/theme/blog-theme.md: -------------------------------------------------------------------------------- 1 | # Blog theme 2 | 3 | ## Sites 4 | 5 | - [Documentation](https://vuepress-theme-blog.billyyyyy3320.com) 6 | - [Live Example](https://example.vuepress-theme-blog.billyyyyy3320.com/) 7 | - [Live Example - ULIVZ’s space](https://billyyyyy3320.com/) 8 | - [Live Example - Billyyyyy3320’s space](https://billyyyyy3320.com/) 9 | 10 | ## Install 11 | 12 | ```bash 13 | yarn add @vuepress/theme-blog -D 14 | # OR npm install @vuepress/theme-blog -D 15 | ``` 16 | ## Usage 17 | 18 | ```js 19 | // .vuepress/config.js 20 | module.exports = { 21 | theme: '@vuepress/blog', 22 | themeConfig: { 23 | // Please read documentation to see the available options. 24 | } 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /packages/docs/docs/theme/using-a-theme.md: -------------------------------------------------------------------------------- 1 | # Using a theme 2 | 3 | Using a theme is almost the same as using a plugin. 4 | 5 | ## Using a theme from a dependency 6 | 7 | Themes can be published on npm in raw Vue SFC format as `vuepress-theme-xxx`. 8 | 9 | ``` js 10 | // .vuepress/config.js 11 | module.exports = { 12 | theme: 'vuepress-theme-xx' 13 | } 14 | ``` 15 | 16 | ## Theme Shorthand 17 | 18 | If you prefix the theme with `vuepress-theme-`, you can use a shorthand to leave out that prefix: 19 | 20 | ``` js 21 | // .vuepress/config.js 22 | module.exports = { 23 | theme: 'xxx' 24 | } 25 | ``` 26 | 27 | Same with: 28 | 29 | ``` js 30 | // .vuepress/config.js 31 | module.exports = { 32 | theme: 'vuepress-theme-xxx' 33 | } 34 | ``` 35 | 36 | This also works with [Scoped Packages](https://docs.npmjs.com/misc/scope): 37 | 38 | ``` js 39 | // .vuepress/config.js 40 | module.exports = { 41 | theme: '@org/vuepress-theme-xxx', // or an official theme: '@vuepress/theme-xxx' 42 | } 43 | ``` 44 | 45 | Shorthand: 46 | 47 | ``` js 48 | // .vuepress/config.js 49 | module.exports = { 50 | theme: '@org/xxx', // or an official theme: '@vuepress/xxx' 51 | } 52 | ``` 53 | 54 | ::: warning Note 55 | The theme whose name starts with `@vuepress/theme-` is an officially maintained theme. 56 | ::: 57 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /hero.png 4 | actionText: 快速上手 → 5 | actionLink: /zh/guide/ 6 | features: 7 | - title: 简洁至上 8 | details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。 9 | - title: Vue 驱动 10 | details: 享受 Vue + webpack 的开发体验,可以在 Markdown 中使用 Vue 组件,又可以使用 Vue 来开发自定义主题。 11 | - title: 高性能 12 | details: VuePress 会为每个页面预渲染生成静态的 HTML,同时,每个页面被加载的时候,将作为 SPA 运行。 13 | footer: MIT Licensed | Copyright © 2018-present Evan You 14 | --- 15 | 16 | ### 像数 1, 2, 3 一样容易 17 | 18 | ``` bash 19 | # 安装 20 | yarn global add vuepress # 或者:npm install -g vuepress 21 | 22 | # 新建一个 markdown 文件 23 | echo '# Hello VuePress!' > README.md 24 | 25 | # 开始写作 26 | vuepress dev . 27 | 28 | # 构建静态文件 29 | vuepress build . 30 | ``` 31 | 32 | ::: warning 注意 33 | 请确保你的 Node.js 版本 >= 8.6。 34 | ::: 35 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/api/cli.md: -------------------------------------------------------------------------------- 1 | # 命令行接口 2 | 3 | ## 基本用法 4 | 5 | ```bash 6 | vuepress targetDir [options] 7 | ``` 8 | 9 | ## build 10 | 11 | 在指定的目录生成一个静态站点。 12 | 13 | ### -p, --port `` 14 | 查看 [port](../config/README.md#port)。 15 | 16 | ### -t, --temp `` 17 | 查看 [temp](../config/README.md#temp)。 18 | 19 | ### -c, --cache `[cache]` 20 | ### --no-cache 21 | 查看 [cache](../config/README.md#cache)。 22 | 23 | ### --dest `` 24 | 查看 [dest](../config/README.md#dest)。 25 | 26 | ### --debug 27 | 以调试模式启动开发服务器。 28 | 29 | ### --silent 30 | 以安静模式启动开发服务器。 31 | 32 | ### --max-concurrency 33 | 设置渲染文档的最大并发量,当渲染大量文档,可能造成内存溢出时使用 34 | 35 | ## dev 36 | 37 | 启动一个开发服务器。来自 `vuepress build` 的所有选项都可用。除此以外,还有几个专门针对 dev 的选项: 38 | 39 | ### --host `` 40 | 查看 [host](../config/README.md#host)。 41 | 42 | ### --open 43 | 当服务端准备就绪时自动打开浏览器。 44 | 45 | ### --no-clear-screen 46 | 当 dev server 就绪时不清除屏幕。请注意 dev server 不会在调试模式下清除屏幕。 47 | 48 | ## eject 49 | 50 | 将默认主题复制到 `.vuepress/theme` 目录,以供自定义。 51 | 52 | ## 更多指令 53 | 54 | 你可以使用 [extendCli](../plugin/option-api.md#extendcli) 来创建自定义命令。 55 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/context-api.md: -------------------------------------------------------------------------------- 1 | # Context API 2 | 3 | VuePress 提供了一个存储了当前页面所有状态的 Context API。 4 | 5 | ::: tip 提示 6 | 每个函数式插件的上下文对象是一个继承于根上下文的隔离上下文对象。 7 | ::: 8 | 9 | ```js 10 | module.exports = (options, ctx) => { 11 | // ... 12 | } 13 | ``` 14 | 15 | ## ctx.isProd 16 | 17 | - 类型: `boolean` 18 | 19 | VuePress 是否运行在生产环境模式下。 20 | 21 | ## ctx.pages 22 | 23 | - 类型: `array` 24 | 25 | 一个包含了页面对象的列表。 26 | 27 | ## ctx.sourceDir 28 | 29 | - 类型: `string` 30 | 31 | 文档的根目录路径。 32 | 33 | ## ctx.tempPath 34 | 35 | - 类型: `string` 36 | 37 | 临时文件所在的根目录路径。 38 | 39 | ## ctx.outDir 40 | 41 | - 类型: `string` 42 | 43 | 输出目录。 44 | 45 | ## ctx.base 46 | 47 | - 类型: `string` 48 | 49 | 参考: [base](../config/README.md#base). 50 | 51 | ## ctx.writeTemp 52 | 53 | - 类型: `Function` 54 | 55 | 一个用于向 tempPath 写入临时文件的方法。 56 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/life-cycle.md: -------------------------------------------------------------------------------- 1 | # 生命周期 2 | 3 | ## ready 4 | 5 | - 类型: `AsyncFunction` 6 | - 作用域:`dev|build` 7 | 8 | ```js 9 | module.exports = { 10 | async ready() { 11 | // ... 12 | } 13 | } 14 | ``` 15 | 16 | ::: tip 提示 17 | 18 | `ready` 钩子在应用初始化之后,并在某些特定的函数式 API 执行之前执行。这些函数式 API 包括: 19 | 20 | - [clientDynamicModules](./option-api.md#clientdynamicmodules) 21 | - [enhanceAppFiles](./option-api.md#enhanceappfiles) 22 | 23 | ::: 24 | 25 | ## updated 26 | 27 | - 类型: `Function` 28 | - 作用域:`dev` 29 | 30 | ```js 31 | module.exports = { 32 | updated() { 33 | // ... 34 | } 35 | } 36 | ``` 37 | 38 | ## generated 39 | 40 | - 类型: `AsyncFunction` 41 | - 作用域:`build` 42 | 43 | 在生产环境的构建结束后被调用,生成的页面的路径数组将作为该函数的第一个参数。 44 | 45 | ``` js 46 | module.exports = { 47 | async generated (pagePaths) { 48 | // ... 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-active-header-links.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: active-header-links 3 | metaTitle: 页面滚动时自动激活侧边栏链接的插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-active-header-links](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-active-header-links) 7 | 8 | > 页面滚动时自动激活侧边栏链接的插件 9 | 10 | ## 安装 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-active-header-links 14 | # OR npm install -D @vuepress/plugin-active-header-links 15 | ``` 16 | 17 | ## 使用 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/active-header-links'] 22 | } 23 | ``` 24 | 25 | ### 配置选项 26 | 27 | ```javascript 28 | module.exports = { 29 | plugins: ['@vuepress/active-header-links', { 30 | sidebarLinkSelector: '.sidebar-link', 31 | headerAnchorSelector: '.header-anchor' 32 | }] 33 | } 34 | ``` 35 | 36 | ## 选项 37 | 38 | ### sidebarLinkSelector 39 | 40 | - 类型: `string` 41 | - 默认值: `.sidebar-link` 42 | 43 | ### headerAnchorSelector 44 | 45 | - 类型: `string` 46 | - 默认值: `.header-anchor` 47 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-back-to-top.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: back-to-top 3 | metaTitle: Back-To-Top 插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-back-to-top](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-back-to-top) 7 | 8 | > back-to-top 插件. 9 | 10 | ## 安装 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-back-to-top 14 | # OR npm install -D @vuepress/plugin-back-to-top 15 | ``` 16 | 17 | ## 使用 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/back-to-top'] 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-blog.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: blog 3 | metaTitle: 博客插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-blog](https://github.com/vuepressjs/vuepress-plugin-blog) 7 | 8 | ## 功能 9 | 10 | - [**分类**](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html#document-classifier):强大的分类系统让你快速将贴文分类。 11 | - [**分页**](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html#pagination): 极其简单的开箱即用的分页功能。 12 | - [**客户端 API**](https://vuepress-plugin-blog.billyyyyy3320.com/client-api/): 透过客户端 API 轻松地写一个博客主题。 13 | 14 | ## 安装 15 | 16 | 在使用这个插件之前,我们强烈建议你先阅读 [Getting Started](https://vuepress-plugin-blog.billyyyyy3320.com/guide/getting-started.html)。 17 | 18 | ```bash 19 | yarn add -D @vuepress/plugin-blog 20 | # OR npm install -D @vuepress/plugin-blog 21 | ``` 22 | 23 | ## 使用 24 | 25 | ```javascript 26 | module.exports = { 27 | plugins: ['@vuepress/blog'] 28 | } 29 | ``` 30 | 31 | 参考 [文档](https://vuepress-theme-blog.billyyyyy3320.com/) 来查看所有可用的选项。 32 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-google-analytics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: google-analytics 3 | metaTitle: Google Analytics 插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-google-analytics](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-google-analytics) 7 | 8 | > Google analytics 插件 9 | 10 | ## 安装 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-google-analytics 14 | # OR npm install -D @vuepress/plugin-google-analytics 15 | ``` 16 | 17 | ::: warning 18 | 如果你的项目正在使用 Google analytics 插件,推荐使用 [Yarn](https://yarnpkg.com/en/) 而不是 npm 来安装所有依赖。因为在这种情形下,npm 会生成错误的依赖树。 19 | ::: 20 | 21 | ## 使用 22 | 23 | ```javascript 24 | module.exports = { 25 | plugins: [ 26 | [ 27 | '@vuepress/google-analytics', 28 | { 29 | 'ga': '' // UA-00000000-0 30 | } 31 | ] 32 | ] 33 | } 34 | ``` 35 | 36 | ::: tip 提示 37 | 请留意 [GDPR (2018年欧盟数据保护规则改革)](https://ec.europa.eu/commission/priorities/justice-and-fundamental-rights/data-protection/2018-reform-eu-data-protection-rules_en), 在合适或者需要的情况下,考虑将 Google Analytics 设置为[匿名化的 IP](https://support.google.com/analytics/answer/2763052?hl=zh-Hans)。 38 | ::: 39 | 40 | ## 选项 41 | 42 | ### ga 43 | 44 | - 类型: `string` 45 | - 默认值: `undefined` 46 | 47 | 提供 Google Analytics ID 以启用集成。 48 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-medium-zoom.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: medium-zoom 3 | metaTitle: Medium-Zoom 插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-medium-zoom](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-medium-zoom) 7 | 8 | > [medium-zoom](https://github.com/francoischalifour/medium-zoom) 插件 9 | 10 | ## 安装 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-medium-zoom 14 | # OR npm install -D @vuepress/plugin-medium-zoom 15 | ``` 16 | 17 | ## 使用 18 | 19 | **简单使用**: 20 | 21 | ```javascript 22 | module.exports = { 23 | plugins: ['@vuepress/medium-zoom'] 24 | } 25 | ``` 26 | 27 | **自定义选项**: 28 | 29 | ```javascript 30 | module.exports = { 31 | plugins: { 32 | '@vuepress/medium-zoom': { 33 | selector: 'img.zoom-custom-imgs', 34 | // medium-zoom options here 35 | // See: https://github.com/francoischalifour/medium-zoom#options 36 | options: { 37 | margin: 16 38 | } 39 | } 40 | } 41 | } 42 | ``` 43 | 44 | ## 选项 45 | 46 | ### selector 47 | 48 | - 类型: `string` 49 | - 默认值: `.theme-default-content :not(a) > img` 50 | 51 | 值得注意的是, `.theme-default-content` 是默认主题添加给 [``](../../guide/using-vue.md#content) 组件的 class name。 52 | 53 | ### options 54 | 55 | - 类型: `object` 56 | - 默认值: `undefined` 57 | 58 | [medium-zoom](https://github.com/francoischalifour/medium-zoom) 的 [选项](https://github.com/francoischalifour/medium-zoom#options)。 59 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/official/plugin-nprogress.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: nprogress 3 | metaTitle: Nprogress 插件 | VuePress 4 | --- 5 | 6 | # [@vuepress/plugin-nprogress](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-nprogress) 7 | 8 | > 一个基于 [nprogress](https://github.com/rstacruz/nprogress) 的进度条插件。 9 | 10 | ## 安装 11 | 12 | ```bash 13 | yarn add -D @vuepress/plugin-nprogress 14 | # 或者 npm install -D @vuepress/plugin-nprogress 15 | ``` 16 | 17 | ## 使用 18 | 19 | ```javascript 20 | module.exports = { 21 | plugins: ['@vuepress/nprogress'] 22 | } 23 | ``` 24 | 25 | ## 自定义颜色 26 | 27 | 在你的 __site__ 或 __theme__ 的 `palette.styl` 文件中设置 `$nprogressColor` 来改变进度条的颜色(默认使用 `$accentColor`)。 28 | 29 | ```stylus 30 | // .vuepress/styles/palette.styl 31 | // 或者 32 | // .vuepress/theme/styles/palette.styl 33 | 34 | $nprogressColor = red 35 | ``` 36 | 37 | __参考:__ 38 | 39 | - [配置 > Styling](../../config/README.md#styling) 40 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/plugin/writing-a-plugin.md: -------------------------------------------------------------------------------- 1 | # 开发插件 2 | 3 | 一个插件应该导出一个普通的 JavaScript 对象(`#1`),如果插件需要接受配置选项,那么它可以是一个返回对象的函数(`#2`),这个函数接受插件的配置选项为第一个参数、包含编译期上下文的 [ctx](./context-api.md) 对象作为第二个参数。 4 | 5 | ``` js 6 | // #1 7 | module.exports = { 8 | // ... 9 | } 10 | ``` 11 | 12 | ``` js 13 | // #2 14 | module.exports = (options, ctx) => { 15 | return { 16 | // ... 17 | } 18 | } 19 | ``` 20 | 21 | ::: tip 22 | 一个 VuePress 插件应该是一个 `CommonJS 模块`,因为 VuePress 插件运行在 Node 端。 23 | ::: 24 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/theme/README.md: -------------------------------------------------------------------------------- 1 | # 主题 2 | 3 | ::: tip 4 | 主题组件受到相同的 [浏览器的 API 访问限制](../guide/using-vue.md#浏览器的API访问限制). 5 | ::: 6 | 7 | 本栏的主要内容如下: 8 | 9 | - [使用主题](./using-a-theme.md) 10 | - [开发主题](./writing-a-theme.md) 11 | - [主题的配置](./option-api.md) 12 | - [主题的继承](./inheritance.md) 13 | - [默认主题配置](./default-theme-config.md) 14 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/theme/blog-theme.md: -------------------------------------------------------------------------------- 1 | # 博客主题 2 | 3 | ## 网站 4 | 5 | - [文档](https://vuepress-theme-blog.billyyyyy3320.com) 6 | - [线上范例](https://example.vuepress-theme-blog.billyyyyy3320.com/) 7 | - [线上范例 - Billyyyyy3320's space](https://billyyyyy3320.com/) 8 | 9 | ## 安装 10 | 11 | ```bash 12 | yarn add @vuepress/theme-blog -D 13 | # OR npm install @vuepress/theme-blog -D 14 | ``` 15 | ## 使用 16 | 17 | ```js 18 | // .vuepress/config.js 19 | module.exports = { 20 | theme: '@vuepress/blog', 21 | themeConfig: { 22 | // 请参考文档来查看所有可用的选项。 23 | } 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/docs/docs/zh/theme/using-a-theme.md: -------------------------------------------------------------------------------- 1 | # 使用主题 2 | 3 | 使用一个主题和使用一个插件的方式几乎一致。 4 | 5 | ## 使用来自依赖的主题 6 | 7 | 一个主题可以在以 `vuepress-theme-xxx` 的形式发布到 npm,你可以这样使用它: 8 | 9 | ``` js 10 | // .vuepress/config.js 11 | module.exports = { 12 | theme: 'vuepress-theme-xx' 13 | } 14 | ``` 15 | 16 | ## 主题的缩写 17 | 18 | 如果你的主题名以 `vuepress-theme-` 开头,你可以使用缩写来省略这个前缀: 19 | 20 | ``` js 21 | // .vuepress/config.js 22 | module.exports = { 23 | theme: 'xxx' 24 | } 25 | ``` 26 | 27 | 和下面等价: 28 | 29 | ``` js 30 | // .vuepress/config.js 31 | module.exports = { 32 | theme: 'vuepress-theme-xxx' 33 | } 34 | ``` 35 | 36 | 这也适用于 [Scoped Packages](https://docs.npmjs.com/misc/scope): 37 | 38 | ``` js 39 | // .vuepress/config.js 40 | module.exports = { 41 | theme: '@org/vuepress-theme-xxx', // 或者一个官方主题: '@vuepress/theme-xxx' 42 | } 43 | ``` 44 | 45 | 缩写: 46 | 47 | ``` js 48 | // .vuepress/config.js 49 | module.exports = { 50 | theme: '@org/xxx', // 或者一个官方主题: '@vuepress/xxx' 51 | } 52 | ``` 53 | 54 | ::: warning 55 | 以 `@vuepress/theme-` 开头的主题是官方维护的主题。 56 | ::: 57 | -------------------------------------------------------------------------------- /packages/vuepress/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const updateNotifier = require('update-notifier') 4 | 5 | const checkEnv = require('./lib/checkEnv') 6 | const { CLI } = require('./lib/util') 7 | const registerCoreCommands = require('./lib/registerCoreCommands') 8 | const handleUnknownCommand = require('./lib/handleUnknownCommand') 9 | 10 | const OPTIONS = { 11 | theme: '@vuepress/default' 12 | } 13 | 14 | CLI({ 15 | async beforeParse (cli) { 16 | const pkg = require('@vuepress/core/package.json') 17 | checkEnv(pkg) 18 | updateNotifier({ pkg }).notify() 19 | registerCoreCommands(cli, OPTIONS) 20 | await handleUnknownCommand(cli, OPTIONS) 21 | cli.version(pkg.version).help() 22 | }, 23 | 24 | async afterParse (cli) { 25 | if (!process.argv.slice(2).length) { 26 | cli.outputHelp() 27 | } 28 | } 29 | }) 30 | 31 | -------------------------------------------------------------------------------- /packages/vuepress/config.d.ts: -------------------------------------------------------------------------------- 1 | export * from '@vuepress/types' 2 | -------------------------------------------------------------------------------- /packages/vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@vuepress/types') 2 | -------------------------------------------------------------------------------- /packages/vuepress/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@vuepress/core') 2 | -------------------------------------------------------------------------------- /packages/vuepress/lib/checkEnv.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const { chalk, semver } = require('@vuepress/shared-utils') 8 | 9 | /** 10 | * Check if Node version meets VuePress requirement. 11 | */ 12 | 13 | module.exports = function checkEnv (pkg) { 14 | const requiredVersion = pkg.engines.node 15 | 16 | if (!semver.satisfies(process.version, requiredVersion)) { 17 | console.log(chalk.red( 18 | `\n[vuepress] minimum Node version not met:` 19 | + `\nYou are using Node ${process.version}, but VuePress ` 20 | + `requires Node ${requiredVersion}.\nPlease upgrade your Node version.\n` 21 | )) 22 | process.exit(1) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/vuepress/lib/util.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | const { chalk } = require('@vuepress/shared-utils') 8 | const CAC = require('cac') 9 | 10 | /** 11 | * Bootstrap a CAC cli 12 | * @param {function} beforeParse 13 | * @param {function} afterParse 14 | * @returns {Promise} 15 | */ 16 | 17 | async function CLI ({ 18 | beforeParse, 19 | afterParse 20 | }) { 21 | const cli = CAC() 22 | beforeParse && await beforeParse(cli) 23 | cli.parse(process.argv) 24 | afterParse && await afterParse(cli) 25 | } 26 | 27 | /** 28 | * Wrap a function to catch error. 29 | * @param {function} fn 30 | * @returns {function(...[*]): (*|Promise|Promise)} 31 | */ 32 | 33 | function wrapCommand (fn) { 34 | return (...args) => { 35 | return fn(...args).catch(err => { 36 | console.error(chalk.red(err.stack)) 37 | process.exitCode = 1 38 | }) 39 | } 40 | } 41 | 42 | /** 43 | * Check if a command is built-in 44 | * @param {array} argv 45 | * @returns {boolean} 46 | */ 47 | 48 | function isKnownCommand (argv) { 49 | return ['dev', 'build', 'eject', 'info'].includes(argv[0]) 50 | } 51 | 52 | module.exports = { 53 | CLI, 54 | isKnownCommand, 55 | wrapCommand 56 | } 57 | -------------------------------------------------------------------------------- /scripts/jest.config.js: -------------------------------------------------------------------------------- 1 | const path = require('upath') 2 | const { createJestConfig } = require('@vuepress/test-utils') 3 | 4 | module.exports = createJestConfig({ 5 | rootDir: path.resolve(__dirname, '..'), 6 | moduleNameMapper: { 7 | '^@/(.*)$': '/$1', 8 | '^@core/(.*)$': '/packages/@vuepress/core/$1', 9 | '^@theme/(.*)$': '/packages/@vuepress/theme-default/$1', 10 | '^@temp/(.*)$': '/.temp/$1', 11 | '^@internal/(.*)$': '/.temp/internal/$1', 12 | '^@transform/(.*)$': '/.temp/transform/$1' 13 | }, 14 | modulePathIgnorePatterns: [ 15 | '/packages/@vuepress/core/__test__/plugin-api/AsyncOption.spec.js' 16 | ] 17 | }) 18 | -------------------------------------------------------------------------------- /scripts/remote-version.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path') 2 | const { readdirSync } = require('fs') 3 | const chalk = require('chalk') 4 | const execa = require('execa') 5 | 6 | const PRIVATE_PACKAGES = ['theme-vue', '.DS_Store'] 7 | 8 | const scopePackages = readdirSync( 9 | join(__dirname, '../packages/@vuepress') 10 | ) 11 | .filter(n => !PRIVATE_PACKAGES.includes(n)) 12 | .map(n => `@vuepress/${n}`) 13 | 14 | async function log () { 15 | await Promise.all(['vuepress', ...scopePackages].map(async pkg => { 16 | const version = (await execa('npm', ['view', `${pkg}@next`, 'version'])).stdout.toString() 17 | console.log(`${pkg}: ${chalk.cyan(version)}`) 18 | })) 19 | } 20 | 21 | log() 22 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | const minimist = require('minimist') 2 | const { createJestRunner } = require('@vuepress/test-utils') 3 | const { createApp } = require('@vuepress/core') 4 | 5 | const rawArgs = process.argv.slice(2) 6 | const args = minimist(rawArgs) 7 | 8 | let regex 9 | const debug = !!args['inspect-brk'] 10 | 11 | if (args.p || args.package) { 12 | const packages = (args.p || args.package).split(',').join('|') 13 | regex = `.*@vuepress/(${packages}|plugin-(${packages}))/.*\\.spec\\.(js|ts)$` 14 | const i = rawArgs.indexOf('-p') 15 | rawArgs.splice(i, 2) 16 | } 17 | 18 | const jestRunner = createJestRunner([ 19 | '--config', 'scripts/jest.config.js', 20 | '--runInBand', 21 | ...(regex ? [regex] : []) 22 | ], debug) 23 | 24 | // ensure the basic temp files were generated 25 | createApp({ 26 | temp: '.temp' 27 | }) 28 | .process() 29 | .then(() => jestRunner()) 30 | .catch(err => { 31 | console.error(err) 32 | process.exit(1) 33 | }) 34 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "pretty": true, 7 | "moduleResolution": "node", 8 | "lib": ["es2015", "es2016.array.include","DOM"], 9 | "allowSyntheticDefaultImports": true, 10 | "stripInternal": true, 11 | "noImplicitAny": false, 12 | "noImplicitReturns": true, 13 | "noImplicitThis": true, 14 | "noUnusedParameters": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "resolveJsonModule": true, 17 | "strictNullChecks": true, 18 | "strictFunctionTypes": true, 19 | "alwaysStrict": true, 20 | "module": "commonjs", 21 | "outDir": "lib", 22 | "typeRoots": [ 23 | "node_modules/@types" 24 | ] 25 | }, 26 | "exclude": [ 27 | "node_modules", 28 | "**/*.spec.ts" 29 | ] 30 | } 31 | --------------------------------------------------------------------------------