-
Notifications
You must be signed in to change notification settings - Fork 668
feat: add support for JSX and strings without a slot-scope attribute #871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
36e3032
refactor: remove window dependency from scoped slots
eddyerburgh 94fbb26
feat: support JSX scoped slots
eddyerburgh 998b77b
refactor: rename functions
eddyerburgh 95c061f
refactor: handle template as root element
eddyerburgh 86a1470
test: fix lint errors
eddyerburgh 4c7a3ae
fix: add updated package-lock
eddyerburgh 656b12d
fix: add babel syntax jsx
eddyerburgh 55619f4
refactor: reword comments
eddyerburgh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"presets": ["env", "stage-2", "flow-vue"], | ||
"plugins": ["transform-decorators-legacy"], | ||
"plugins": ["transform-decorators-legacy", "transform-vue-jsx"], | ||
"comments": false | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,54 +32,45 @@ function getVueTemplateCompilerHelpers (): { [name: string]: Function } { | |
names.forEach(name => { | ||
helpers[name] = vue._renderProxy[name] | ||
}) | ||
helpers.$createElement = vue._renderProxy.$createElement | ||
return helpers | ||
} | ||
|
||
function validateEnvironment (): void { | ||
if (window.navigator.userAgent.match(/PhantomJS/i)) { | ||
throwError( | ||
`the scopedSlots option does not support PhantomJS. ` + | ||
`Please use Puppeteer, or pass a component.` | ||
) | ||
} | ||
if (vueVersion < 2.5) { | ||
throwError(`the scopedSlots option is only supported in ` + `[email protected]+.`) | ||
if (vueVersion < 2.1) { | ||
throwError(`the scopedSlots option is only supported in ` + `[email protected]+.`) | ||
} | ||
} | ||
|
||
function validateTempldate (template: string): void { | ||
if (template.trim().substr(0, 9) === '<template') { | ||
throwError( | ||
`the scopedSlots option does not support a template ` + | ||
`tag as the root element.` | ||
) | ||
} | ||
} | ||
const scopedSlotRe = /<[^>]+ slot-scope=\"(.+)\"/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, I think |
||
|
||
export default function createScopedSlots ( | ||
scopedSlotsOption: ?{ [slotName: string]: string } | ||
scopedSlotsOption: ?{ [slotName: string]: string | Function } | ||
): { [slotName: string]: (props: Object) => VNode | Array<VNode>} { | ||
const scopedSlots = {} | ||
if (!scopedSlotsOption) { | ||
return scopedSlots | ||
} | ||
validateEnvironment() | ||
const helpers = getVueTemplateCompilerHelpers() | ||
for (const name in scopedSlotsOption) { | ||
const template = scopedSlotsOption[name] | ||
validateTempldate(template) | ||
const render = compileToFunctions(template).render | ||
const domParser = new window.DOMParser() | ||
const _document = domParser.parseFromString(template, 'text/html') | ||
const slotScope = _document.body.firstChild.getAttribute( | ||
'slot-scope' | ||
) | ||
const isDestructuring = isDestructuringSlotScope(slotScope) | ||
scopedSlots[name] = function (props) { | ||
if (isDestructuring) { | ||
return render.call({ ...helpers, ...props }) | ||
for (const s in scopedSlotsOption) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
const slot = scopedSlotsOption[s] | ||
const isFn = typeof slot === 'function' | ||
const renderFn = isFn | ||
? slot | ||
: compileToFunctions(slot).renderFn | ||
|
||
const hasSlotScopeAttr = !isFn && slot.match(scopedSlotRe) | ||
// // $FlowIgnore | ||
const slotScope = hasSlotScopeAttr && hasSlotScopeAttr[1] | ||
|
||
scopedSlots[s] = function (props) { | ||
if (isFn) { | ||
return renderFn.call({ ...helpers }, props) | ||
} else if (slotScope && !isDestructuringSlotScope(slotScope)) { | ||
return renderFn.call({ ...helpers, [slotScope]: props }) | ||
} else { | ||
return render.call({ ...helpers, [slotScope]: props }) | ||
return renderFn.call({ ...helpers, ...props }) | ||
} | ||
} | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
import { | ||
describeWithShallowAndMount, | ||
vueVersion, | ||
isRunningPhantomJS | ||
vueVersion | ||
} from '~resources/utils' | ||
import ComponentWithScopedSlots from '~resources/components/component-with-scoped-slots.vue' | ||
import { itDoNotRunIf } from 'conditional-specs' | ||
|
@@ -14,7 +13,7 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => { | |
}) | ||
|
||
itDoNotRunIf( | ||
vueVersion < 2.5 || isRunningPhantomJS, | ||
vueVersion < 2.5, | ||
'mounts component scoped slots in render function', | ||
() => { | ||
const destructuringWrapper = mountingMethod( | ||
|
@@ -38,15 +37,15 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => { | |
const notDestructuringWrapper = mountingMethod( | ||
{ | ||
render: function () { | ||
return this.$scopedSlots.default({ | ||
return this.$scopedSlots.named({ | ||
index: 1, | ||
item: 'foo' | ||
}) | ||
} | ||
}, | ||
{ | ||
scopedSlots: { | ||
default: | ||
named: | ||
'<p slot-scope="props">{{props.index}},{{props.item}}</p>' | ||
} | ||
} | ||
|
@@ -56,15 +55,15 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => { | |
) | ||
|
||
itDoNotRunIf( | ||
vueVersion < 2.5 || isRunningPhantomJS, | ||
vueVersion < 2.5, | ||
'mounts component scoped slots', | ||
() => { | ||
const wrapper = mountingMethod(ComponentWithScopedSlots, { | ||
slots: { default: '<span>123</span>' }, | ||
scopedSlots: { | ||
destructuring: | ||
'<p slot-scope="{ index, item }">{{index}},{{item}}</p>', | ||
list: '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>', | ||
list: '<template slot-scope="foo"><p>{{foo.index}},{{foo.text}}</p></template>', | ||
single: '<p slot-scope="bar">{{bar.text}}</p>', | ||
noProps: '<p slot-scope="baz">baz</p>' | ||
} | ||
|
@@ -105,52 +104,40 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => { | |
} | ||
) | ||
|
||
itDoNotRunIf( | ||
vueVersion < 2.5 || isRunningPhantomJS, | ||
'throws exception when it is seted to a template tag at top', | ||
() => { | ||
const fn = () => { | ||
mountingMethod(ComponentWithScopedSlots, { | ||
scopedSlots: { | ||
single: '<template></template>' | ||
} | ||
}) | ||
it('handles JSX', () => { | ||
const wrapper = mountingMethod({ | ||
template: '<div><slot name="single" :text="foo"></slot></div>', | ||
data: () => ({ | ||
foo: 'bar' | ||
}) | ||
}, { | ||
scopedSlots: { | ||
single ({ text }) { | ||
return <p>{{ text }}</p> | ||
} | ||
} | ||
const message = | ||
'[vue-test-utils]: the scopedSlots option does not support a template tag as the root element.' | ||
expect(fn) | ||
.to.throw() | ||
.with.property('message', message) | ||
} | ||
) | ||
}) | ||
expect(wrapper.html()).to.equal('<div><p>bar</p></div>') | ||
}) | ||
|
||
itDoNotRunIf( | ||
vueVersion >= 2.5 || isRunningPhantomJS, | ||
'throws exception when vue version < 2.5', | ||
() => { | ||
const fn = () => { | ||
mountingMethod(ComponentWithScopedSlots, { | ||
scopedSlots: { | ||
list: '<p slot-scope="foo">{{foo.index}},{{foo.text}}</p>' | ||
} | ||
}) | ||
it('handles no slot-scope', () => { | ||
const wrapper = mountingMethod({ | ||
template: '<div><slot name="single" :text="foo" :i="123"></slot></div>', | ||
data: () => ({ | ||
foo: 'bar' | ||
}) | ||
}, { | ||
scopedSlots: { | ||
single: '<p>{{text}},{{i}}</p>' | ||
} | ||
const message = | ||
'[vue-test-utils]: the scopedSlots option is only supported in [email protected]+.' | ||
expect(fn) | ||
.to.throw() | ||
.with.property('message', message) | ||
} | ||
) | ||
}) | ||
expect(wrapper.html()).to.equal('<div><p>bar,123</p></div>') | ||
}) | ||
|
||
itDoNotRunIf( | ||
vueVersion < 2.5, | ||
'throws exception when using PhantomJS', | ||
vueVersion > 2.0, | ||
'throws exception when vue version < 2.1', | ||
() => { | ||
if (window.navigator.userAgent.match(/Chrome|PhantomJS/i)) { | ||
return | ||
} | ||
window = { navigator: { userAgent: 'PhantomJS' }} // eslint-disable-line no-native-reassign | ||
const fn = () => { | ||
mountingMethod(ComponentWithScopedSlots, { | ||
scopedSlots: { | ||
|
@@ -159,7 +146,7 @@ describeWithShallowAndMount('scopedSlots', mountingMethod => { | |
}) | ||
} | ||
const message = | ||
'[vue-test-utils]: the scopedSlots option does not support PhantomJS. Please use Puppeteer, or pass a component.' | ||
'[vue-test-utils]: the scopedSlots option is only supported in [email protected]+.' | ||
expect(fn) | ||
.to.throw() | ||
.with.property('message', message) | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the scopedSlots option is only supported in
+[email protected]+.
↓
the scopedSlots option is only supported in [email protected]+.