// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+exports[`stringify static html > should bail for <option> elements with number values 1`] = `
+"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+const _hoisted_1 = /*#__PURE__*/_createElementVNode("select", null, [
+ /*#__PURE__*/_createElementVNode("option", { value: 1 }),
+ /*#__PURE__*/_createElementVNode("option", { value: 1 }),
+ /*#__PURE__*/_createElementVNode("option", { value: 1 }),
+ /*#__PURE__*/_createElementVNode("option", { value: 1 }),
+ /*#__PURE__*/_createElementVNode("option", { value: 1 })
+], -1 /* HOISTED */)
+const _hoisted_2 = [
+ _hoisted_1
+]
+
+return function render(_ctx, _cache) {
+ return (_openBlock(), _createElementBlock("div", null, _hoisted_2))
+}"
+`;
+
exports[`stringify static html > should bail on bindings that are hoisted but not stringifiable 1`] = `
"const { createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
}"
`;
+exports[`stringify static html > should work for <option> elements with string values 1`] = `
+"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+const _hoisted_1 = /*#__PURE__*/_createStaticVNode("<select><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option><option value=\\"1\\"></option></select>", 1)
+const _hoisted_2 = [
+ _hoisted_1
+]
+
+return function render(_ctx, _cache) {
+ return (_openBlock(), _createElementBlock("div", null, _hoisted_2))
+}"
+`;
+
exports[`stringify static html > should work with bindings that are non-static but stringifiable 1`] = `
"const { createElementVNode: _createElementVNode, createStaticVNode: _createStaticVNode, openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
expect(code).toMatch(`<code>text1</code>`)
expect(code).toMatchSnapshot()
})
+
+ test('should work for <option> elements with string values', () => {
+ const { ast, code } = compileWithStringify(
+ `<div><select>${repeat(
+ `<option value="1" />`,
+ StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
+ )}</select></div>`,
+ )
+ // should be optimized now
+ expect(ast.hoists).toMatchObject([
+ {
+ type: NodeTypes.JS_CALL_EXPRESSION,
+ callee: CREATE_STATIC,
+ arguments: [
+ JSON.stringify(
+ `<select>${repeat(
+ `<option value="1"></option>`,
+ StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
+ )}</select>`,
+ ),
+ '1',
+ ],
+ },
+ {
+ type: NodeTypes.JS_ARRAY_EXPRESSION,
+ },
+ ])
+ expect(code).toMatchSnapshot()
+ })
+
+ test('should bail for <option> elements with number values', () => {
+ const { ast, code } = compileWithStringify(
+ `<div><select>${repeat(
+ `<option :value="1" />`,
+ StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
+ )}</select></div>`,
+ )
+ expect(ast.hoists).toMatchObject([
+ {
+ type: NodeTypes.VNODE_CALL,
+ },
+ {
+ type: NodeTypes.JS_ARRAY_EXPRESSION,
+ },
+ ])
+ expect(code).toMatchSnapshot()
+ })
})
type TextCallNode,
type TransformContext,
createCallExpression,
+ isStaticArgOf,
} from '@vue/compiler-core'
import {
escapeHtml,
// probably only need to check for most common case
// i.e. non-phrasing-content tags inside `<p>`
function walk(node: ElementNode): boolean {
+ const isOptionTag = node.tag === 'option' && node.ns === Namespaces.HTML
for (let i = 0; i < node.props.length; i++) {
const p = node.props[i]
// bail on non-attr bindings
) {
return bail()
}
+ // <option :value="1"> cannot be safely stringified
+ if (
+ isOptionTag &&
+ isStaticArgOf(p.arg, 'value') &&
+ p.exp &&
+ p.exp.ast &&
+ p.exp.ast.type !== 'StringLiteral'
+ ) {
+ return bail()
+ }
}
}
for (let i = 0; i < node.children.length; i++) {