@vuepress/core 1.4.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,6 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
6
6
  <title>{{ title }}</title>
7
- <meta name="description" content="{{ description }}">
8
7
  <meta name="generator" content="VuePress {{ version }}">
9
8
  {{{ userHeadTags }}}
10
9
  {{{ pageMeta }}}
@@ -1,15 +1,26 @@
1
+ import unionBy from 'lodash/unionBy'
2
+
1
3
  export default {
4
+ // created will be called on both client and ssr
2
5
  created () {
6
+ this.siteMeta = this.$site.headTags
7
+ .filter(([headerType]) => headerType === 'meta')
8
+ .map(([_, headerValue]) => headerValue)
9
+
3
10
  if (this.$ssrContext) {
11
+ const mergedMetaItems = this.getMergedMetaTags()
12
+
4
13
  this.$ssrContext.title = this.$title
5
14
  this.$ssrContext.lang = this.$lang
6
- this.$ssrContext.description = this.$page.description || this.$description
15
+ this.$ssrContext.pageMeta = renderPageMeta(mergedMetaItems)
7
16
  }
8
17
  },
9
-
18
+ // Other life cycles will only be called at client
10
19
  mounted () {
20
+ // init currentMetaTags from DOM
21
+ this.currentMetaTags = [...document.querySelectorAll('meta')]
22
+
11
23
  // update title / meta tags
12
- this.currentMetaTags = new Set()
13
24
  this.updateMeta()
14
25
  },
15
26
 
@@ -17,22 +28,17 @@ export default {
17
28
  updateMeta () {
18
29
  document.title = this.$title
19
30
  document.documentElement.lang = this.$lang
20
- const userMeta = this.$page.frontmatter.meta || []
21
- const meta = userMeta.slice(0)
22
- const useGlobalDescription = userMeta.filter(m => m.name === 'description').length === 0
23
-
24
- // #665 Avoid duplicate description meta at runtime.
25
- if (useGlobalDescription) {
26
- meta.push({ name: 'description', content: this.$description })
27
- }
28
31
 
29
- // Including description meta coming from SSR.
30
- const descriptionMetas = document.querySelectorAll('meta[name="description"]')
31
- if (descriptionMetas.length) {
32
- descriptionMetas.forEach(m => this.currentMetaTags.add(m))
33
- }
32
+ const newMetaTags = this.getMergedMetaTags()
33
+ this.currentMetaTags = updateMetaTags(newMetaTags, this.currentMetaTags)
34
+ },
34
35
 
35
- this.currentMetaTags = new Set(updateMetaTags(meta, this.currentMetaTags))
36
+ getMergedMetaTags () {
37
+ const pageMeta = this.$page.frontmatter.meta || []
38
+ // pageMetaTags have higher priority than siteMetaTags
39
+ // description needs special attention as it has too many entries
40
+ return unionBy([{ name: 'description', content: this.$description }],
41
+ pageMeta, this.siteMeta, metaIdentifier)
36
42
  }
37
43
  },
38
44
 
@@ -47,14 +53,20 @@ export default {
47
53
  }
48
54
  }
49
55
 
50
- function updateMetaTags (meta, current) {
51
- if (current) {
52
- [...current].forEach(c => {
53
- document.head.removeChild(c)
54
- })
56
+ /**
57
+ * Replace currentMetaTags with newMetaTags
58
+ * @param {Array<Object>} newMetaTags
59
+ * @param {Array<HTMLElement>} currentMetaTags
60
+ * @returns {Array<HTMLElement>}
61
+ */
62
+ function updateMetaTags (newMetaTags, currentMetaTags) {
63
+ if (currentMetaTags) {
64
+ [...currentMetaTags]
65
+ .filter(c => c.parentNode === document.head)
66
+ .forEach(c => document.head.removeChild(c))
55
67
  }
56
- if (meta) {
57
- return meta.map(m => {
68
+ if (newMetaTags) {
69
+ return newMetaTags.map(m => {
58
70
  const tag = document.createElement('meta')
59
71
  Object.keys(m).forEach(key => {
60
72
  tag.setAttribute(key, m[key])
@@ -64,3 +76,35 @@ function updateMetaTags (meta, current) {
64
76
  })
65
77
  }
66
78
  }
79
+
80
+ /**
81
+ * Try to identify a meta tag by name, property or itemprop
82
+ *
83
+ * Return a complete string if none provided
84
+ * @param {Object} tag from frontmatter or siteMetaTags
85
+ * @returns {String}
86
+ */
87
+ function metaIdentifier (tag) {
88
+ for (const item of ['name', 'property', 'itemprop']) {
89
+ if (tag.hasOwnProperty(item)) return tag[item] + item
90
+ }
91
+ return JSON.stringify(tag)
92
+ }
93
+
94
+ /**
95
+ * Render meta tags
96
+ *
97
+ * @param {Array} meta
98
+ * @returns {String}
99
+ */
100
+
101
+ function renderPageMeta (meta) {
102
+ if (!meta) return ''
103
+ return meta.map(m => {
104
+ let res = `<meta`
105
+ Object.keys(m).forEach(key => {
106
+ res += ` ${key}="${m[key]}"`
107
+ })
108
+ return res + `>`
109
+ }).join('\n ')
110
+ }
package/lib/node/App.js CHANGED
@@ -438,6 +438,7 @@ module.exports = class App {
438
438
  title: this.siteConfig.title || '',
439
439
  description: this.siteConfig.description || '',
440
440
  base: this.base,
441
+ headTags: this.siteConfig.head || [],
441
442
  pages: this.pages.map(page => page.toJson()),
442
443
  themeConfig: this.siteConfig.themeConfig || {},
443
444
  locales
@@ -499,4 +500,3 @@ module.exports = class App {
499
500
  return this
500
501
  }
501
502
  }
502
-
@@ -77,13 +77,15 @@ module.exports = class Build extends EventEmitter {
77
77
  })
78
78
 
79
79
  // pre-render head tags from user config
80
+ // filter out meta tags for they will be injected in updateMeta.js
80
81
  this.userHeadTags = (this.context.siteConfig.head || [])
82
+ .filter(([headTagType]) => headTagType !== 'meta')
81
83
  .map(renderHeadTag)
82
- .join('\n ')
84
+ .join('\n ')
83
85
 
84
86
  // if the user does not have a custom 404.md, generate the theme's default
85
87
  if (!this.context.pages.some(p => p.path === '/404.html')) {
86
- this.context.addPage({ path: '/404.html' })
88
+ await this.context.addPage({ path: '/404.html' })
87
89
  }
88
90
 
89
91
  // render pages
@@ -134,14 +136,9 @@ module.exports = class Build extends EventEmitter {
134
136
  async renderPage (page) {
135
137
  const pagePath = decodeURIComponent(page.path)
136
138
 
137
- // #565 Avoid duplicate description meta at SSR.
138
- const meta = (page.frontmatter && page.frontmatter.meta || []).filter(item => item.name !== 'description')
139
- const pageMeta = renderPageMeta(meta)
140
-
141
139
  const context = {
142
140
  url: page.path,
143
141
  userHeadTags: this.userHeadTags,
144
- pageMeta,
145
142
  title: 'VuePress',
146
143
  lang: 'en',
147
144
  description: '',
@@ -221,24 +218,6 @@ function renderAttrs (attrs = {}) {
221
218
  }
222
219
  }
223
220
 
224
- /**
225
- * Render meta tags
226
- *
227
- * @param {Array} meta
228
- * @returns {Array<string>}
229
- */
230
-
231
- function renderPageMeta (meta) {
232
- if (!meta) return ''
233
- return meta.map(m => {
234
- let res = `<meta`
235
- Object.keys(m).forEach(key => {
236
- res += ` ${key}="${escape(m[key])}"`
237
- })
238
- return res + `>`
239
- }).join('')
240
- }
241
-
242
221
  /**
243
222
  * find and remove empty style chunk caused by
244
223
  * https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85
@@ -207,8 +207,12 @@ module.exports = class DevProcess extends EventEmitter {
207
207
  publicPath: this.context.base,
208
208
  watchOptions: {
209
209
  ignored: [
210
- /node_modules/,
211
- `!${this.context.tempPath}/**`
210
+ (x) => {
211
+ if (x.includes(this.context.tempPath)) {
212
+ return false
213
+ }
214
+ return /node_modules/.test(x)
215
+ }
212
216
  ]
213
217
  },
214
218
  historyApiFallback: {
@@ -1,2 +1,2 @@
1
1
  // generated from user config
2
- import('@temp/style.styl')
2
+ import '@temp/style.styl'
@@ -131,7 +131,7 @@ function resolveSFCs (dirs) {
131
131
  /**
132
132
  * normalize component name
133
133
  *
134
- * @param {strin} filename
134
+ * @param {string} filename
135
135
  * @returns {string}
136
136
  */
137
137
 
@@ -137,14 +137,16 @@ module.exports = function createBaseConfig (context, isServer) {
137
137
  .rule('js')
138
138
  .test(/\.jsx?$/)
139
139
  .exclude.add(filePath => {
140
- // Always transpile lib directory
140
+ // transpile lib directory
141
141
  if (filePath.startsWith(libDir)) {
142
142
  return false
143
143
  }
144
- // always transpile js in vue files and md files
144
+
145
+ // transpile js in vue files and md files
145
146
  if (/\.(vue|md)\.js$/.test(filePath)) {
146
147
  return false
147
148
  }
149
+
148
150
  // transpile all core packages and vuepress related packages.
149
151
  // i.e.
150
152
  // @vuepress/*
@@ -152,7 +154,13 @@ module.exports = function createBaseConfig (context, isServer) {
152
154
  if (/(@vuepress[\/\\][^\/\\]*|vuepress-[^\/\\]*)[\/\\](?!node_modules).*\.js$/.test(filePath)) {
153
155
  return false
154
156
  }
155
- // Don't transpile node_modules
157
+
158
+ // transpile @babel/runtime until fix for babel/babel#7597 is released
159
+ if (filePath.includes(path.join('@babel', 'runtime'))) {
160
+ return false
161
+ }
162
+
163
+ // don't transpile node_modules
156
164
  return /node_modules/.test(filePath)
157
165
  }).end()
158
166
  .use('cache-loader')
@@ -171,7 +179,11 @@ module.exports = function createBaseConfig (context, isServer) {
171
179
  // ref: http://babeljs.io/docs/en/config-files
172
180
  configFile: false,
173
181
  presets: [
174
- require.resolve('@vue/babel-preset-app')
182
+ [require.resolve('@vue/babel-preset-app'), {
183
+ entryFiles: [
184
+ path.resolve(__dirname, '../../client', isServer ? 'serverEntry.js' : 'clientEntry.js')
185
+ ]
186
+ }]
175
187
  ]
176
188
  })
177
189
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuepress/core",
3
- "version": "1.4.0",
3
+ "version": "1.5.2",
4
4
  "description": "Minimalistic doc generator with Vue component based layout system",
5
5
  "keywords": [
6
6
  "documentation",
@@ -25,11 +25,11 @@
25
25
  "dependencies": {
26
26
  "@babel/core": "^7.8.4",
27
27
  "@vue/babel-preset-app": "^4.1.2",
28
- "@vuepress/markdown": "^1.4.0",
29
- "@vuepress/markdown-loader": "^1.4.0",
30
- "@vuepress/plugin-last-updated": "^1.4.0",
31
- "@vuepress/plugin-register-components": "^1.4.0",
32
- "@vuepress/shared-utils": "^1.4.0",
28
+ "@vuepress/markdown": "1.5.2",
29
+ "@vuepress/markdown-loader": "1.5.2",
30
+ "@vuepress/plugin-last-updated": "1.5.2",
31
+ "@vuepress/plugin-register-components": "1.5.2",
32
+ "@vuepress/shared-utils": "1.5.2",
33
33
  "autoprefixer": "^9.5.1",
34
34
  "babel-loader": "^8.0.4",
35
35
  "cache-loader": "^3.0.0",
@@ -73,6 +73,5 @@
73
73
  "name": "ULIVZ",
74
74
  "email": "chl814@foxmail.com"
75
75
  }
76
- ],
77
- "gitHead": "58ed07f013b7f7768094e57314f993c39dc6750e"
76
+ ]
78
77
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
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.