Skip to content
This repository was archived by the owner on Aug 9, 2023. It is now read-only.

Add support for Vue #17

Merged
merged 2 commits into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function wrapper(h, node, options) {
var prefix
var r
var v
var vd

if (typeof h !== 'function') {
throw new Error('h is not a function')
Expand All @@ -31,10 +32,11 @@ function wrapper(h, node, options) {
}

r = react(h)
v = vdom(h)
v = vue(h)
vd = vdom(h)

if (prefix === null || prefix === undefined) {
prefix = r === true || v === true ? 'h-' : false
prefix = r === true || v === true || vd === true ? 'h-' : false
}

if (is('root', node)) {
Expand All @@ -59,7 +61,8 @@ function wrapper(h, node, options) {
prefix: prefix,
key: 0,
react: r,
vdom: v,
vue: v,
vdom: vd,
hyperscript: hyperscript(h)
})
}
Expand Down Expand Up @@ -98,9 +101,9 @@ function toH(h, node, ctx) {

if (
typeof attributes.style === 'string' &&
(ctx.vdom === true || ctx.react === true)
(ctx.vdom === true || ctx.vue === true || ctx.react === true)
) {
// VDOM and React accept `style` as object.
// VDOM, Vue, and React accept `style` as object.
attributes.style = parseStyle(attributes.style, name)
}

Expand Down Expand Up @@ -140,7 +143,7 @@ function toH(h, node, ctx) {
}

function addAttribute(props, prop, value, ctx) {
var hyperlike = ctx.hyperscript || ctx.vdom
var hyperlike = ctx.hyperscript || ctx.vdom || ctx.vue
var schema = ctx.schema
var info = find(schema, prop)
var subprop
Expand All @@ -167,7 +170,11 @@ function addAttribute(props, prop, value, ctx) {
value = ''
}

if (!info.mustUseProperty) {
if (ctx.vue) {
if (prop !== 'style') {
subprop = 'attrs'
}
} else if (!info.mustUseProperty) {
if (ctx.vdom === true) {
subprop = 'attributes'
} else if (ctx.hyperscript === true) {
Expand Down Expand Up @@ -204,6 +211,11 @@ function vdom(h) {
return h && h('div').type === 'VirtualNode'
}

function vue(h) {
var node = h && h('div')
return Boolean(node && node.context && node.context._isVue)
}

function parseStyle(value, tagName) {
var result = {}

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
"unist-builder": "^1.0.1",
"vdom-to-html": "^2.3.1",
"virtual-dom": "^2.1.1",
"vue": "^2.6.10",
"vue-server-renderer": "^2.6.10",
"xo": "^0.24.0"
},
"scripts": {
Expand Down
119 changes: 116 additions & 3 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ var r = require('react').createElement
var rehype = require('rehype')
var vToString = require('vdom-to-html')
var rToString = require('react-dom/server').renderToStaticMarkup
var Vue = require('vue')
var VueSSR = require('vue-server-renderer')
var toH = require('.')

var processor = rehype().data('settings', {fragment: true, position: false})
Expand Down Expand Up @@ -386,6 +388,119 @@ test('hast-to-hyperscript', function(t) {
st.end()
})

t.test('should support `Vue`', function(st) {
var baseline = doc.replace(/<div>/, '<div data-server-rendered="true">')
var actual
var expected

st.plan(3)

Promise.all([vueToString(actualRender), vueToString(expectedRender)])
.then(function(all) {
var actualString = all[0]
var expectedString = all[0]

st.deepEqual(clean(actual), clean(expected), 'equal syntax trees')
st.deepEqual(html(actualString), html(baseline), 'equal output')

st.deepEqual(
html(expectedString),
html(baseline),
'equal output baseline'
)
})
.catch(function(error) {
st.ifErr(error, 'did not expect an error')
})

function actualRender(h) {
actual = toH(h, hast)
return actual
}

function expectedRender(h) {
expected = h(
'div',
{key: 'h-1', attrs: {'data-server-rendered': 'true'}},
[
h(
'h1',
{
key: 'h-2',
attrs: {
class: 'b c',
id: 'a',
hidden: true,
height: 2
}
},
[
'bravo ',
h(
'strong',
{
key: 'h-3',
style: {color: 'red'},
attrs: {
foo: 'bar',
camelCase: 'on off',
'data-123': '456',
'data-some': 'yes',
'aria-valuenow': '1'
}
},
['charlie']
),
' delta',
h('input', {
key: 'h-4',
attrs: {
checked: true,
type: 'file',
accept: '.jpg, .jpeg'
}
})
]
),
h(
'svg',
{
key: 'h-5',
attrs: {
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 500 500'
}
},
[h('circle', {key: 'h-6', attrs: {cx: 120, cy: 120, r: 100}})]
)
]
)
return expected
}

function identity(value) {
return value
}

function vueToString(render) {
return VueSSR.createRenderer({template: identity}).renderToString(
new Vue({render: render}).$mount()
)
}

function clean(node) {
remove(node)
return json(node)
}

function remove(node) {
delete node.context
if (node.children) {
node.children.forEach(remove)
}
}
})

t.test('should support keys', function(st) {
st.equal(
toH(h, u('element', {tagName: 'div'})).key,
Expand Down Expand Up @@ -508,9 +623,7 @@ test('hast-to-hyperscript', function(t) {
st.end()
})

t.test('flattens a `root` with one element child to that child', function(
st
) {
t.test('flattens a `root` with one element to that child', function(st) {
var actual = toH(
h,
u('root', [u('element', {tagName: 'h1', properties: {id: 'a'}}, [])])
Expand Down