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

Add support for Vue #15

Closed
wants to merge 11 commits into from
Closed
103 changes: 100 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,30 @@ var is = require('unist-util-is')

var dashes = /-([a-z])/g

var vueUtils = {
topLevel: [
'class',
'staticClass',
'style',
'key',
'ref',
'refInFor',
'slot',
'scopedSlots'
],
nestableRE: /^(props|domProps|on|nativeOn|hook)([-_A-Z])/,
dirRE: /^v-/,
xlinkRE: /^xlink([A-Z])/
}

module.exports = wrapper

function wrapper(h, node, options) {
var settings = options || {}
var prefix
var r
var v
var vu

if (typeof h !== 'function') {
throw new Error('h is not a function')
Expand All @@ -32,6 +49,7 @@ function wrapper(h, node, options) {

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

if (prefix === null || prefix === undefined) {
prefix = r === true || v === true ? 'h-' : false
Expand Down Expand Up @@ -60,6 +78,7 @@ function wrapper(h, node, options) {
key: 0,
react: r,
vdom: v,
vue: vu,
hyperscript: hyperscript(h)
})
}
Expand Down Expand Up @@ -98,9 +117,9 @@ function toH(h, node, ctx) {

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

Expand Down Expand Up @@ -170,9 +189,11 @@ function addAttribute(props, prop, value, ctx) {
subprop = 'attributes'
} else if (ctx.hyperscript === true) {
subprop = 'attrs'
} else if (ctx.vue === true) {
vueMergeAttributes(props, info, value)
return
}
}

if (subprop) {
if (props[subprop] === undefined) {
props[subprop] = {}
Expand All @@ -184,6 +205,76 @@ function addAttribute(props, prop, value, ctx) {
}
}

function vueMergeAttributes(props, info, value) {
var groupProp = vueGroupAttribute(info, value)
var propName = groupProp.name
var propValue = groupProp.value

props[propName] =
typeof propValue === 'object'
? Object.assign({}, props[propName] || {}, propValue)
: Array.isArray(propValue)
? [].concat(props[propName] || [], propValue)
: propValue
}

function vueGroupAttribute(info, value) {
var name = info.property
var props = {}

var processeddName
var processedValue

if (vueUtils.topLevel.indexOf(name) > -1) {
processeddName = name
processedValue = value
} else {
// Nested modules
var nestMatch = name.match(vueUtils.nestableRE)
if (nestMatch) {
var prefix = nestMatch[1]
var suffix = name.replace(vueUtils.nestableRE, function(_, $1, $2) {
return $2 === '-' ? '' : $2.toLowerCase()
})

var subProp = {}
subProp[suffix] = value
processeddName = prefix
processedValue = subProp
} else if (vueUtils.dirRE.test(info.attribute)) {
// Custom directive
processeddName = 'directives'
processedValue = [
{
name: info.attribute.replace(vueUtils.dirRE, ''),
value: value
}
]
} else {
// Rest are nested under attrs
// guard xlink attributes
var attribute =
info.space && info.space === 'xlink'
? JSON.stringify(
info.attribute.replace(vueUtils.xlinkRE, function(m, p1) {
return 'xlink:' + p1.toLowerCase()
})
)
: info.attribute

var attrs = {}
attrs[attribute] = value
processeddName = 'attrs'
processedValue = attrs
}
}

props.name = processeddName
props.value = processedValue

return props
}

// Check if `h` is `react.createElement`.
function react(h) {
var node = h && h('div')
Expand All @@ -192,6 +283,12 @@ function react(h) {
)
}

// Check if `h` is vue `createElement`.
function vue(h) {
var div = h && h('div')
return div && div.context && div.context._isVue === true
}

// Check if `h` is `hyperscript`.
function hyperscript(h) {
return Boolean(h && h.context && h.cleanup)
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.5.17",
"vue-server-renderer": "^2.5.17",
"xo": "^0.23.0"
},
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ var r = require('react').createElement
var rehype = require('rehype')
var vToString = require('vdom-to-html')
var rToString = require('react-dom/server').renderToStaticMarkup
var vueToString = require('vue-server-renderer').createRenderer({
template: '<!--vue-ssr-outlet-->'
}).renderToString
var toH = require('.')

var processor = rehype().data('settings', {fragment: true, position: false})
Expand Down