Skip to content

Commit cb2758e

Browse files
committed
feat: support generating tags directly from metaInfo object
1 parent 931c0c4 commit cb2758e

17 files changed

+127
-69
lines changed

scripts/rollup.config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const banner = `/**
2121
const babelConfig = () => ({
2222
presets: [
2323
['@babel/preset-env', {
24+
/*useBuiltIns: 'usage',
25+
corejs: 2,*/
2426
targets: {
2527
node: 8,
2628
ie: 9,

src/client/refresh.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { clientSequences } from '../shared/escaping'
2+
import { getComponentMetaInfo } from '../shared/getComponentOption'
13
import getMetaInfo from '../shared/getMetaInfo'
24
import { isFunction } from '../utils/is-type'
3-
import { clientSequences } from '../shared/escaping'
45
import updateClientMetaInfo from './updateClientMetaInfo'
56

67
export default function _refresh (options = {}) {
@@ -15,10 +16,14 @@ export default function _refresh (options = {}) {
1516
* @return {Object} - new meta info
1617
*/
1718
return function refresh () {
18-
const metaInfo = getMetaInfo(options, this.$root, clientSequences)
19+
// collect & aggregate all metaInfo $options
20+
const rawInfo = getComponentMetaInfo(options, this.$root)
21+
22+
const metaInfo = getMetaInfo(options, rawInfo, clientSequences, this.$root)
1923

2024
const appId = this.$root._vueMeta.appId
2125
const tags = updateClientMetaInfo(appId, options, metaInfo)
26+
2227
// emit "event" with new info
2328
if (tags && isFunction(metaInfo.changed)) {
2429
metaInfo.changed(metaInfo, tags.addedTags, tags.removedTags)

src/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { version } from '../package.json'
22
import createMixin from './shared/mixin'
33
import { setOptions } from './shared/options'
44
import $meta from './server/$meta'
5+
import generate from './server/generate'
56
import { hasMetaInfo } from './shared/meta-helpers'
67

78
/**
@@ -24,5 +25,6 @@ function install (Vue, options = {}) {
2425
export default {
2526
version,
2627
install,
27-
hasMetaInfo
28+
hasMetaInfo,
29+
generate
2830
}

src/server/generate.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import getMetaInfo from '../shared/getMetaInfo'
2+
import { defaultOptions } from '../shared/constants'
3+
import { serverSequences } from '../shared/escaping'
4+
import { setOptions } from '../shared/options'
5+
import generateServerInjector from './generateServerInjector'
6+
7+
export default function generate (options, rawInfo) {
8+
if (arguments.length === 1) {
9+
rawInfo = options
10+
options = defaultOptions
11+
}
12+
13+
const metaInfo = getMetaInfo(setOptions(options), rawInfo, serverSequences)
14+
return generateServerInjector(options, metaInfo)
15+
}

src/server/generateServerInjector.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { metaInfoAttributeKeys } from '../shared/constants'
1+
import { metaInfoOptionKeys, metaInfoAttributeKeys, defaultInfo } from '../shared/constants'
22
import { titleGenerator, attributeGenerator, tagGenerator } from './generators'
33

44
/**
@@ -9,14 +9,24 @@ import { titleGenerator, attributeGenerator, tagGenerator } from './generators'
99
* @return {Object} - the new injector
1010
*/
1111

12-
export default function generateServerInjector (options, type, data) {
13-
if (type === 'title') {
14-
return titleGenerator(options, type, data)
15-
}
12+
export default function generateServerInjector (options, newInfo) {
13+
for (const type in defaultInfo) {
14+
if (metaInfoOptionKeys.includes(type)) {
15+
continue
16+
}
17+
18+
if (type === 'title') {
19+
newInfo[type] = titleGenerator(options, type, newInfo[type])
20+
continue
21+
}
22+
23+
if (metaInfoAttributeKeys.includes(type)) {
24+
newInfo[type] = attributeGenerator(options, type, newInfo[type])
25+
continue
26+
}
1627

17-
if (metaInfoAttributeKeys.includes(type)) {
18-
return attributeGenerator(options, type, data)
28+
newInfo[type] = tagGenerator(options, type, newInfo[type])
1929
}
2030

21-
return tagGenerator(options, type, data)
31+
return newInfo
2232
}

src/server/generators/tag.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export default function tagGenerator ({ ssrAppId, attribute, tagIDKeyName } = {}
1818

1919
return {
2020
text ({ body = false, pbody = false } = {}) {
21+
if (!tags || !tags.length) {
22+
return ''
23+
}
24+
2125
// build a string containing all tags of this type
2226
return tags.reduce((tagsStr, tag) => {
2327
if (tag.skip) {

src/server/inject.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import getMetaInfo from '../shared/getMetaInfo'
2-
import { metaInfoOptionKeys } from '../shared/constants'
31
import { serverSequences } from '../shared/escaping'
2+
import { getComponentMetaInfo } from '../shared/getComponentOption'
3+
import getMetaInfo from '../shared/getMetaInfo'
44
import generateServerInjector from './generateServerInjector'
55

66
export default function _inject (options = {}) {
@@ -12,15 +12,13 @@ export default function _inject (options = {}) {
1212
* @return {Object} - server meta info with `toString` methods
1313
*/
1414
return function inject () {
15-
// get meta info with sensible defaults
16-
const metaInfo = getMetaInfo(options, this.$root, serverSequences)
15+
// collect & aggregate all metaInfo $options
16+
const rawInfo = getComponentMetaInfo(options, this.$root)
17+
18+
const metaInfo = getMetaInfo(options, rawInfo, serverSequences, this.$root)
1719

1820
// generate server injectors
19-
for (const key in metaInfo) {
20-
if (!metaInfoOptionKeys.includes(key) && metaInfo.hasOwnProperty(key)) {
21-
metaInfo[key] = generateServerInjector(options, key, metaInfo[key])
22-
}
23-
}
21+
generateServerInjector(options, metaInfo)
2422

2523
return metaInfo
2624
}

src/shared/escaping.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isString, isArray, isPureObject } from '../utils/is-type'
22
import { includes } from '../utils/array'
3+
import { ensureIsArray } from '../utils/ensure'
34
import { metaInfoOptionKeys, disableOptionKeys } from './constants'
45

56
export const serverSequences = [
@@ -78,3 +79,24 @@ export function escape (info, options, escapeOptions, escapeKeys) {
7879

7980
return escaped
8081
}
82+
83+
export function escapeMetaInfo (options, info, escapeSequences = []) {
84+
const escapeOptions = {
85+
doEscape: value => escapeSequences.reduce((val, [v, r]) => val.replace(v, r), value)
86+
}
87+
88+
disableOptionKeys.forEach((disableKey, index) => {
89+
if (index === 0) {
90+
ensureIsArray(info, disableKey)
91+
} else if (index === 1) {
92+
for (const key in info[disableKey]) {
93+
ensureIsArray(info[disableKey], key)
94+
}
95+
}
96+
97+
escapeOptions[disableKey] = info[disableKey]
98+
})
99+
100+
// begin sanitization
101+
return escape(info, options, escapeOptions)
102+
}

src/shared/getComponentOption.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { isFunction, isObject } from '../utils/is-type'
22
import { findIndex } from '../utils/array'
3+
import { defaultInfo } from './constants'
34
import { merge } from './merge'
45
import { applyTemplate } from './template'
56
import { inMetaInfoBranch } from './meta-helpers'
67

8+
export function getComponentMetaInfo (options = {}, component) {
9+
return getComponentOption(options, component, defaultInfo)
10+
}
11+
712
/**
813
* Returns the `opts.option` $option value of the given `opts.component`.
914
* If methods are encountered, they will be bound to the component context.
@@ -18,7 +23,7 @@ import { inMetaInfoBranch } from './meta-helpers'
1823
* @param {Object} [result={}] - result so far
1924
* @return {Object} result - final aggregated result
2025
*/
21-
export default function getComponentOption (options = {}, component, result = {}) {
26+
export function getComponentOption (options = {}, component, result = {}) {
2227
const { keyName, metaTemplateKeyName, tagIDKeyName } = options
2328
const { $options, $children } = component
2429

src/shared/getMetaInfo.js

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { ensureIsArray } from '../utils/ensure'
1+
import { escapeMetaInfo } from '../shared/escaping'
22
import { applyTemplate } from './template'
3-
import { defaultInfo, disableOptionKeys } from './constants'
4-
import { escape } from './escaping'
5-
import getComponentOption from './getComponentOption'
63

74
/**
85
* Returns the correct meta info for the given component
@@ -11,10 +8,7 @@ import getComponentOption from './getComponentOption'
118
* @param {Object} component - the Vue instance to get meta info from
129
* @return {Object} - returned meta info
1310
*/
14-
export default function getMetaInfo (options = {}, component, escapeSequences = []) {
15-
// collect & aggregate all metaInfo $options
16-
let info = getComponentOption(options, component, defaultInfo)
17-
11+
export default function getMetaInfo (options = {}, info, escapeSequences = [], component) {
1812
// Remove all "template" tags from meta
1913

2014
// backup the title chunk in case user wants access to it
@@ -33,24 +27,5 @@ export default function getMetaInfo (options = {}, component, escapeSequences =
3327
info.base = Object.keys(info.base).length ? [info.base] : []
3428
}
3529

36-
const escapeOptions = {
37-
doEscape: value => escapeSequences.reduce((val, [v, r]) => val.replace(v, r), value)
38-
}
39-
40-
disableOptionKeys.forEach((disableKey, index) => {
41-
if (index === 0) {
42-
ensureIsArray(info, disableKey)
43-
} else if (index === 1) {
44-
for (const key in info[disableKey]) {
45-
ensureIsArray(info[disableKey], key)
46-
}
47-
}
48-
49-
escapeOptions[disableKey] = info[disableKey]
50-
})
51-
52-
// begin sanitization
53-
info = escape(info, options, escapeOptions)
54-
55-
return info
30+
return escapeMetaInfo(options, info, escapeSequences)
5631
}

0 commit comments

Comments
 (0)