From f4f610b154017d9023cc09258a60e25518701340 Mon Sep 17 00:00:00 2001 From: Daniel Castillo Date: Sat, 1 Dec 2018 14:13:23 +0100 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=99=88=20add=20vscode=20config=20to?= =?UTF-8?q?=20.gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9a60952a32..59d753401e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ node_modules *.log .temp +.vscode TODOs.md vuepress From 08e4f7b0335efd86c8cd28323da969b8c505e9a9 Mon Sep 17 00:00:00 2001 From: Daniel Castillo Date: Sat, 1 Dec 2018 17:17:57 +0100 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20remove=20'.html'=20ext=20from?= =?UTF-8?q?=20URLs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/@vuepress/shared-utils/lib/fileToPath.js | 6 +++--- packages/@vuepress/theme-default/util/index.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/@vuepress/shared-utils/lib/fileToPath.js b/packages/@vuepress/shared-utils/lib/fileToPath.js index 57bdf599ec..44b759f9fa 100644 --- a/packages/@vuepress/shared-utils/lib/fileToPath.js +++ b/packages/@vuepress/shared-utils/lib/fileToPath.js @@ -9,8 +9,8 @@ module.exports = function fileToPath (file) { // foo/README.md -> /foo/ return file.replace(indexRE, '/$1') } else { - // foo.md -> /foo.html - // foo/bar.md -> /foo/bar.html - return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html` + // foo.md -> /foo/ + // foo/bar.md -> /foo/bar/ + return `/${file.replace(extRE, '').replace(/\\/g, '/')}/` } } diff --git a/packages/@vuepress/theme-default/util/index.js b/packages/@vuepress/theme-default/util/index.js index 01937e9888..0e73e9c655 100644 --- a/packages/@vuepress/theme-default/util/index.js +++ b/packages/@vuepress/theme-default/util/index.js @@ -7,6 +7,7 @@ export function normalize (path) { return decodeURI(path) .replace(hashRE, '') .replace(extRE, '') + .replace(endingSlashRE, '') } export function getHash (path) { @@ -39,7 +40,7 @@ export function ensureExt (path) { if (endingSlashRE.test(normalized)) { return path } - return normalized + '.html' + hash + return normalized + '/' + hash } export function isActive (route, path) { From 4c568862bec7ae94141abd2bde04fbf6dbb99db1 Mon Sep 17 00:00:00 2001 From: Daniel Castillo Date: Tue, 4 Dec 2018 12:17:48 +0100 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=A8=20add=20config=20for=20htmlSuffix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../@vuepress/core/lib/prepare/AppContext.js | 8 +++- packages/@vuepress/core/lib/prepare/Page.js | 2 +- .../shared-utils/__tests__/fileToPath.spec.js | 2 +- .../@vuepress/shared-utils/lib/fileToPath.js | 6 ++- .../theme-default/components/NavLink.vue | 2 +- .../theme-default/components/Sidebar.vue | 12 ++++-- .../theme-default/components/SidebarLink.vue | 12 +++--- .../@vuepress/theme-default/util/index.js | 40 ++++++++++--------- 8 files changed, 49 insertions(+), 35 deletions(-) diff --git a/packages/@vuepress/core/lib/prepare/AppContext.js b/packages/@vuepress/core/lib/prepare/AppContext.js index 71961ea12d..85d14db747 100644 --- a/packages/@vuepress/core/lib/prepare/AppContext.js +++ b/packages/@vuepress/core/lib/prepare/AppContext.js @@ -54,6 +54,9 @@ module.exports = class AppContext { this.cwd = process.cwd() this.base = this.siteConfig.base || '/' + if (this.siteConfig.htmlSuffix === undefined) { + this.siteConfig.htmlSuffix = true + } this.themeConfig = this.siteConfig.themeConfig || {} const rawOutDir = cliOptions.dest || this.siteConfig.dest @@ -305,7 +308,7 @@ module.exports = class AppContext { */ getSiteData () { - const { locales } = this.siteConfig + const { locales, htmlSuffix } = this.siteConfig if (locales) { Object.keys(locales).forEach(path => { locales[path].path = path @@ -318,7 +321,8 @@ module.exports = class AppContext { base: this.base, pages: this.pages.map(page => page.toJson()), themeConfig: this.siteConfig.themeConfig || {}, - locales + locales, + htmlSuffix } } } diff --git a/packages/@vuepress/core/lib/prepare/Page.js b/packages/@vuepress/core/lib/prepare/Page.js index a3a26a9b55..d5135490e3 100644 --- a/packages/@vuepress/core/lib/prepare/Page.js +++ b/packages/@vuepress/core/lib/prepare/Page.js @@ -56,7 +56,7 @@ module.exports = class Page { this._context = context if (relative) { - this.regularPath = encodeURI(fileToPath(relative)) + this.regularPath = encodeURI(fileToPath(relative, context.siteConfig.htmlSuffix)) } else if (path) { this.regularPath = encodeURI(path) } else if (permalink) { diff --git a/packages/@vuepress/shared-utils/__tests__/fileToPath.spec.js b/packages/@vuepress/shared-utils/__tests__/fileToPath.spec.js index d0b2683283..cdcb060c56 100644 --- a/packages/@vuepress/shared-utils/__tests__/fileToPath.spec.js +++ b/packages/@vuepress/shared-utils/__tests__/fileToPath.spec.js @@ -8,7 +8,7 @@ test('fileToPath', () => { 'foo/bar.md': '/foo/bar.html' } Object.keys(asserts).forEach(file => { - expect(fileToPath(file)).toBe(asserts[file]) + expect(fileToPath(file, true)).toBe(asserts[file]) }) }) diff --git a/packages/@vuepress/shared-utils/lib/fileToPath.js b/packages/@vuepress/shared-utils/lib/fileToPath.js index 44b759f9fa..301453c0a6 100644 --- a/packages/@vuepress/shared-utils/lib/fileToPath.js +++ b/packages/@vuepress/shared-utils/lib/fileToPath.js @@ -3,11 +3,15 @@ const isIndexFile = require('./isIndexFile') const extRE = /\.(vue|md)$/ -module.exports = function fileToPath (file) { +module.exports = function fileToPath (file, htmlSuffix) { if (isIndexFile(file)) { // README.md -> / // foo/README.md -> /foo/ return file.replace(indexRE, '/$1') + } else if (htmlSuffix) { + // foo.md -> /foo.html + // foo/bar.md -> /foo/bar.html + return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html` } else { // foo.md -> /foo/ // foo/bar.md -> /foo/bar/ diff --git a/packages/@vuepress/theme-default/components/NavLink.vue b/packages/@vuepress/theme-default/components/NavLink.vue index 452a1c6dc8..62158ba514 100644 --- a/packages/@vuepress/theme-default/components/NavLink.vue +++ b/packages/@vuepress/theme-default/components/NavLink.vue @@ -29,7 +29,7 @@ export default { computed: { link () { - return ensureExt(this.item.link) + return ensureExt(this.item.link, this.$site.htmlSuffix) }, exact () { diff --git a/packages/@vuepress/theme-default/components/Sidebar.vue b/packages/@vuepress/theme-default/components/Sidebar.vue index 9ed10ed9b8..692803ffea 100644 --- a/packages/@vuepress/theme-default/components/Sidebar.vue +++ b/packages/@vuepress/theme-default/components/Sidebar.vue @@ -50,7 +50,8 @@ export default { refreshIndex () { const index = resolveOpenGroupIndex( this.$route, - this.items + this.items, + this.$site.htmlSuffix ) if (index > -1) { this.openGroupIndex = index @@ -62,15 +63,18 @@ export default { }, isActive (page) { - return isActive(this.$route, page.regularPath) + return isActive(this.$route, page.regularPath, this.$site.htmlSuffix) } } } -function resolveOpenGroupIndex (route, items) { +function resolveOpenGroupIndex (route, items, htmlSuffix) { for (let i = 0; i < items.length; i++) { const item = items[i] - if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) { + if ( + item.type === 'group' && + item.children.some(c => isActive(route, c.path, htmlSuffix)) + ) { return i } } diff --git a/packages/@vuepress/theme-default/components/SidebarLink.vue b/packages/@vuepress/theme-default/components/SidebarLink.vue index 4b08380ed3..93113fe662 100644 --- a/packages/@vuepress/theme-default/components/SidebarLink.vue +++ b/packages/@vuepress/theme-default/components/SidebarLink.vue @@ -9,11 +9,11 @@ export default { render (h, { parent: { $page, $site, $route }, props: { item }}) { // use custom active class matching logic // due to edge case of paths ending with / + hash - const selfActive = isActive($route, item.path) + const selfActive = isActive($route, item.path, $site.htmlSuffix) // for sidebar: auto pages, a hash link should be active if one of its child // matches const active = item.type === 'auto' - ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug)) + ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug, $site.htmlSuffix)) : selfActive const link = renderLink(h, item.path, item.title || item.path, active) const configDepth = $page.frontmatter.sidebarDepth != null @@ -22,10 +22,10 @@ export default { const maxDepth = configDepth == null ? 1 : configDepth const displayAllHeaders = !!$site.themeConfig.displayAllHeaders if (item.type === 'auto') { - return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)] + return [link, renderChildren(h, item.children, item.basePath, $route, $site.htmlSuffix, maxDepth)] } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) { const children = groupHeaders(item.headers) - return [link, renderChildren(h, children, item.path, $route, maxDepth)] + return [link, renderChildren(h, children, item.path, $route, $site.htmlSuffix, maxDepth)] } else { return link } @@ -46,10 +46,10 @@ function renderLink (h, to, text, active) { }, text) } -function renderChildren (h, children, path, route, maxDepth, depth = 1) { +function renderChildren (h, children, path, route, htmlSuffix, maxDepth, depth = 1) { if (!children || depth > maxDepth) return null return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => { - const active = isActive(route, path + '#' + c.slug) + const active = isActive(route, path + '#' + c.slug, htmlSuffix) return h('li', { class: 'sidebar-sub-header' }, [ renderLink(h, path + '#' + c.slug, c.title, active), renderChildren(h, c.children, path, route, maxDepth, depth + 1) diff --git a/packages/@vuepress/theme-default/util/index.js b/packages/@vuepress/theme-default/util/index.js index 0e73e9c655..57c40a9533 100644 --- a/packages/@vuepress/theme-default/util/index.js +++ b/packages/@vuepress/theme-default/util/index.js @@ -3,11 +3,12 @@ export const extRE = /\.(md|html)$/ export const endingSlashRE = /\/$/ export const outboundRE = /^(https?:|mailto:|tel:)/ -export function normalize (path) { - return decodeURI(path) +export function normalize (path, htmlSuffix) { + const normalized = decodeURI(path) .replace(hashRE, '') .replace(extRE, '') - .replace(endingSlashRE, '') + + return htmlSuffix ? normalized : normalized.replace(endingSlashRE, '') } export function getHash (path) { @@ -29,41 +30,42 @@ export function isTel (path) { return /^tel:/.test(path) } -export function ensureExt (path) { +export function ensureExt (path, htmlSuffix) { if (isExternal(path)) { return path } const hashMatch = path.match(hashRE) const hash = hashMatch ? hashMatch[0] : '' - const normalized = normalize(path) + const normalized = normalize(path, htmlSuffix) + const ext = htmlSuffix ? '.html' : '/' if (endingSlashRE.test(normalized)) { return path } - return normalized + '/' + hash + return normalized + ext + hash } -export function isActive (route, path) { +export function isActive (route, path, htmlSuffix) { const routeHash = route.hash const linkHash = getHash(path) if (linkHash && routeHash !== linkHash) { return false } - const routePath = normalize(route.path) - const pagePath = normalize(path) + const routePath = normalize(route.path, htmlSuffix) + const pagePath = normalize(path, htmlSuffix) return routePath === pagePath } -export function resolvePage (pages, rawPath, base) { +export function resolvePage (pages, rawPath, base, htmlSuffix) { if (base) { rawPath = resolvePath(rawPath, base) } - const path = normalize(rawPath) + const path = normalize(rawPath, htmlSuffix) for (let i = 0; i < pages.length; i++) { - if (normalize(pages[i].regularPath) === path) { + if (normalize(pages[i].regularPath, htmlSuffix) === path) { return Object.assign({}, pages[i], { type: 'page', - path: ensureExt(pages[i].path) + path: ensureExt(pages[i].path, htmlSuffix) }) } } @@ -117,7 +119,7 @@ function resolvePath (relative, base, append) { * @returns { SidebarGroup } */ export function resolveSidebarItems (page, regularPath, site, localePath) { - const { pages, themeConfig } = site + const { pages, themeConfig, htmlSuffix } = site const localeConfig = localePath && themeConfig.locales ? themeConfig.locales[localePath] || themeConfig @@ -134,7 +136,7 @@ export function resolveSidebarItems (page, regularPath, site, localePath) { } else { const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig) return config - ? config.map(item => resolveItem(item, pages, base)) + ? config.map(item => resolveItem(item, pages, base, htmlSuffix)) : [] } } @@ -208,11 +210,11 @@ function ensureEndingSlash (path) { : path + '/' } -function resolveItem (item, pages, base, isNested) { +function resolveItem (item, pages, base, htmlSuffix, isNested) { if (typeof item === 'string') { - return resolvePage(pages, item, base) + return resolvePage(pages, item, base, htmlSuffix) } else if (Array.isArray(item)) { - return Object.assign(resolvePage(pages, item[0], base), { + return Object.assign(resolvePage(pages, item[0], base, htmlSuffix), { title: item[1] }) } else { @@ -226,7 +228,7 @@ function resolveItem (item, pages, base, isNested) { return { type: 'group', title: item.title, - children: children.map(child => resolveItem(child, pages, base, true)), + children: children.map(child => resolveItem(child, pages, base, htmlSuffix, true)), collapsable: item.collapsable !== false } } From 519155244bc44d7b029730b121d015da69df64eb Mon Sep 17 00:00:00 2001 From: Daniel Castillo Date: Tue, 4 Dec 2018 12:25:18 +0100 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=80=20Resolve=20conflicts=20with?= =?UTF-8?q?=20master?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/@vuepress/shared-utils/lib/fileToPath.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/@vuepress/shared-utils/lib/fileToPath.js b/packages/@vuepress/shared-utils/lib/fileToPath.js index 301453c0a6..cca2dc21f4 100644 --- a/packages/@vuepress/shared-utils/lib/fileToPath.js +++ b/packages/@vuepress/shared-utils/lib/fileToPath.js @@ -6,15 +6,21 @@ const extRE = /\.(vue|md)$/ module.exports = function fileToPath (file, htmlSuffix) { if (isIndexFile(file)) { // README.md -> / + // README.vue -> / // foo/README.md -> /foo/ + // foo/README.vue -> /foo/ return file.replace(indexRE, '/$1') } else if (htmlSuffix) { // foo.md -> /foo.html + // foo.vue -> /foo.html // foo/bar.md -> /foo/bar.html + // foo/bar.vue -> /foo/bar.html return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html` } else { // foo.md -> /foo/ + // foo.vue -> /foo/ // foo/bar.md -> /foo/bar/ + // foo/bar.vue -> /foo/bar/ return `/${file.replace(extRE, '').replace(/\\/g, '/')}/` } }