|
|
@ -45,6 +45,7 @@ let postTransforms |
|
|
|
let platformIsPreTag |
|
|
|
let platformMustUseProp |
|
|
|
let platformGetTagNamespace |
|
|
|
let maybeComponent |
|
|
|
|
|
|
|
export function createASTElement ( |
|
|
|
tag: string, |
|
|
@ -74,6 +75,8 @@ export function parse ( |
|
|
|
platformIsPreTag = options.isPreTag || no |
|
|
|
platformMustUseProp = options.mustUseProp || no |
|
|
|
platformGetTagNamespace = options.getTagNamespace || no |
|
|
|
const isReservedTag = options.isReservedTag || no |
|
|
|
maybeComponent = (el: ASTElement) => !!el.component || !isReservedTag(el.tag) |
|
|
|
|
|
|
|
transforms = pluckModuleFunction(options.modules, 'transformNode') |
|
|
|
preTransforms = pluckModuleFunction(options.modules, 'preTransformNode') |
|
|
@ -390,7 +393,8 @@ export function processElement ( |
|
|
|
) |
|
|
|
|
|
|
|
processRef(element) |
|
|
|
processSlot(element) |
|
|
|
processSlotContent(element) |
|
|
|
processSlotOutlet(element) |
|
|
|
processComponent(element) |
|
|
|
for (let i = 0; i < transforms.length; i++) { |
|
|
|
element = transforms[i](element, options) || element |
|
|
@ -542,7 +546,79 @@ function processOnce (el) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function processSlot (el) { |
|
|
|
// handle content being passed to a component as slot,
|
|
|
|
// e.g. <template slot="xxx">, <div slot-scope="xxx">
|
|
|
|
function processSlotContent (el) { |
|
|
|
let slotScope |
|
|
|
if (el.tag === 'template') { |
|
|
|
slotScope = getAndRemoveAttr(el, 'scope') |
|
|
|
/* istanbul ignore if */ |
|
|
|
if (process.env.NODE_ENV !== 'production' && slotScope) { |
|
|
|
warn( |
|
|
|
`the "scope" attribute for scoped slots have been deprecated and ` + |
|
|
|
`replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` + |
|
|
|
`can also be used on plain elements in addition to <template> to ` + |
|
|
|
`denote scoped slots.`, |
|
|
|
el.rawAttrsMap['scope'], |
|
|
|
true |
|
|
|
) |
|
|
|
} |
|
|
|
el.slotScope = ( |
|
|
|
slotScope || |
|
|
|
getAndRemoveAttr(el, 'slot-scope') || |
|
|
|
// new in 2.6: slot-props and its shorthand works the same as slot-scope
|
|
|
|
// when used on <template> containers
|
|
|
|
getAndRemoveAttr(el, 'slot-props') || |
|
|
|
getAndRemoveAttr(el, '()') |
|
|
|
) |
|
|
|
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) { |
|
|
|
/* istanbul ignore if */ |
|
|
|
if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) { |
|
|
|
warn( |
|
|
|
`Ambiguous combined usage of slot-scope and v-for on <${el.tag}> ` + |
|
|
|
`(v-for takes higher priority). Use a wrapper <template> for the ` + |
|
|
|
`scoped slot to make it clearer.`, |
|
|
|
el.rawAttrsMap['slot-scope'], |
|
|
|
true |
|
|
|
) |
|
|
|
} |
|
|
|
el.slotScope = slotScope |
|
|
|
} else { |
|
|
|
// 2.6: slot-props on component, denotes default slot
|
|
|
|
slotScope = getAndRemoveAttr(el, 'slot-props') || getAndRemoveAttr(el, '()') |
|
|
|
if (slotScope) { |
|
|
|
if (process.env.NODE_ENV !== 'production' && !maybeComponent(el)) { |
|
|
|
warn( |
|
|
|
`slot-props cannot be used on non-component elements.`, |
|
|
|
el.rawAttrsMap['slot-props'] || el.rawAttrsMap['()'] |
|
|
|
) |
|
|
|
} |
|
|
|
// add the component's children to its default slot
|
|
|
|
const slots = el.scopedSlots || (el.scopedSlots = {}) |
|
|
|
const slotContainer = slots[`"default"`] = createASTElement('template', [], el) |
|
|
|
slotContainer.children = el.children |
|
|
|
slotContainer.slotScope = slotScope |
|
|
|
// remove children as they are returned from scopedSlots now
|
|
|
|
el.children = [] |
|
|
|
// mark el non-plain so data gets generated
|
|
|
|
el.plain = false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// slot="xxx"
|
|
|
|
const slotTarget = getBindingAttr(el, 'slot') |
|
|
|
if (slotTarget) { |
|
|
|
el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget |
|
|
|
// preserve slot as an attribute for native shadow DOM compat
|
|
|
|
// only for non-scoped slots.
|
|
|
|
if (el.tag !== 'template' && !el.slotScope) { |
|
|
|
addAttr(el, 'slot', slotTarget, getRawBindingAttr(el, 'slot')) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// handle <slot/> outlets
|
|
|
|
function processSlotOutlet (el) { |
|
|
|
if (el.tag === 'slot') { |
|
|
|
el.slotName = getBindingAttr(el, 'name') |
|
|
|
if (process.env.NODE_ENV !== 'production' && el.key) { |
|
|
@ -553,44 +629,6 @@ function processSlot (el) { |
|
|
|
getRawBindingAttr(el, 'key') |
|
|
|
) |
|
|
|
} |
|
|
|
} else { |
|
|
|
let slotScope |
|
|
|
if (el.tag === 'template') { |
|
|
|
slotScope = getAndRemoveAttr(el, 'scope') |
|
|
|
/* istanbul ignore if */ |
|
|
|
if (process.env.NODE_ENV !== 'production' && slotScope) { |
|
|
|
warn( |
|
|
|
`the "scope" attribute for scoped slots have been deprecated and ` + |
|
|
|
`replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` + |
|
|
|
`can also be used on plain elements in addition to <template> to ` + |
|
|
|
`denote scoped slots.`, |
|
|
|
el.rawAttrsMap['scope'], |
|
|
|
true |
|
|
|
) |
|
|
|
} |
|
|
|
el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope') |
|
|
|
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) { |
|
|
|
/* istanbul ignore if */ |
|
|
|
if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) { |
|
|
|
warn( |
|
|
|
`Ambiguous combined usage of slot-scope and v-for on <${el.tag}> ` + |
|
|
|
`(v-for takes higher priority). Use a wrapper <template> for the ` + |
|
|
|
`scoped slot to make it clearer.`, |
|
|
|
el.rawAttrsMap['slot-scope'], |
|
|
|
true |
|
|
|
) |
|
|
|
} |
|
|
|
el.slotScope = slotScope |
|
|
|
} |
|
|
|
const slotTarget = getBindingAttr(el, 'slot') |
|
|
|
if (slotTarget) { |
|
|
|
el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget |
|
|
|
// preserve slot as an attribute for native shadow DOM compat
|
|
|
|
// only for non-scoped slots.
|
|
|
|
if (el.tag !== 'template' && !el.slotScope) { |
|
|
|
addAttr(el, 'slot', slotTarget, getRawBindingAttr(el, 'slot')) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|