提交 7edd390a 编写于 作者: fxy060608's avatar fxy060608

wip(app): nvue styler

上级 fd6cbab3
...@@ -13,6 +13,20 @@ export function render(_ctx, _cache) { ...@@ -13,6 +13,20 @@ export function render(_ctx, _cache) {
}" }"
`; `;
exports[`app-nvue: compiler <scroll-view data-id="id" scroll-x="true" :show-scrollbar="true"/> 1`] = `
"import { openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
const _hoisted_1 = {
\\"data-id\\": \\"id\\",
scrollX: \\"true\\",
showScrollbar: true
}
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(\\"scroll-view\\", _hoisted_1))
}"
`;
exports[`app-nvue: compiler <slider/> 1`] = ` exports[`app-nvue: compiler <slider/> 1`] = `
"import { resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\" "import { resolveComponent as _resolveComponent, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
...@@ -62,45 +76,44 @@ export function render(_ctx, _cache) { ...@@ -62,45 +76,44 @@ export function render(_ctx, _cache) {
exports[`app-nvue: compiler <view><text>hello</text></view> 1`] = ` exports[`app-nvue: compiler <view><text>hello</text></view> 1`] = `
"import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\" "import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
const _hoisted_1 = [\\"appendAsTree\\"] const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"u-text\\", null, \\"hello\\", -1 /* HOISTED */)
const _hoisted_2 = [
_hoisted_1
]
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(\\"view\\", null, [ return (_openBlock(), _createElementBlock(\\"view\\", null, _hoisted_2))
_createElementVNode(\\"u-text\\", { appendAsTree: true }, \\"hello\\", 8 /* PROPS */, _hoisted_1)
]))
}" }"
`; `;
exports[`app-nvue: compiler <view>hello</view> 1`] = ` exports[`app-nvue: compiler <view>hello</view> 1`] = `
"import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\" "import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
const _hoisted_1 = [\\"appendAsTree\\"] const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"u-text\\", null, \\"hello\\", -1 /* HOISTED */)
const _hoisted_2 = [
_hoisted_1
]
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(\\"view\\", null, [ return (_openBlock(), _createElementBlock(\\"view\\", null, _hoisted_2))
_createElementVNode(\\"u-text\\", { appendAsTree: true }, \\"hello\\", 8 /* PROPS */, _hoisted_1)
]))
}" }"
`; `;
exports[`app-nvue: compiler <view>hello{{a}}<view>aaa{{a}}</view>{{b}}</view> 1`] = ` exports[`app-nvue: compiler <view>hello{{a}}<view>aaa{{a}}</view>{{b}}</view> 1`] = `
"import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\" "import { createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
const _hoisted_1 = [\\"appendAsTree\\"] const _hoisted_1 = /*#__PURE__*/_createElementVNode(\\"u-text\\", null, \\"hello\\", -1 /* HOISTED */)
const _hoisted_2 = [\\"appendAsTree\\"] const _hoisted_2 = /*#__PURE__*/_createElementVNode(\\"u-text\\", null, \\"aaa\\", -1 /* HOISTED */)
const _hoisted_3 = [\\"appendAsTree\\"]
const _hoisted_4 = [\\"appendAsTree\\"]
const _hoisted_5 = [\\"appendAsTree\\"]
export function render(_ctx, _cache) { export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(\\"view\\", null, [ return (_openBlock(), _createElementBlock(\\"view\\", null, [
_createElementVNode(\\"u-text\\", { appendAsTree: true }, \\"hello\\", 8 /* PROPS */, _hoisted_1), _hoisted_1,
_createElementVNode(\\"u-text\\", { appendAsTree: true }, _toDisplayString(_ctx.a), 9 /* TEXT, PROPS */, _hoisted_2), _createElementVNode(\\"u-text\\", null, _toDisplayString(_ctx.a), 1 /* TEXT */),
_createElementVNode(\\"view\\", null, [ _createElementVNode(\\"view\\", null, [
_createElementVNode(\\"u-text\\", { appendAsTree: true }, \\"aaa\\", 8 /* PROPS */, _hoisted_3), _hoisted_2,
_createElementVNode(\\"u-text\\", { appendAsTree: true }, _toDisplayString(_ctx.a), 9 /* TEXT, PROPS */, _hoisted_4) _createElementVNode(\\"u-text\\", null, _toDisplayString(_ctx.a), 1 /* TEXT */)
]), ]),
_createElementVNode(\\"u-text\\", { appendAsTree: true }, _toDisplayString(_ctx.b), 9 /* TEXT, PROPS */, _hoisted_5) _createElementVNode(\\"u-text\\", null, _toDisplayString(_ctx.b), 1 /* TEXT */)
])) ]))
}" }"
`; `;
import { NVUE_U_BUILT_IN_TAGS } from '@dcloudio/uni-shared' import { NVUE_U_BUILT_IN_TAGS } from '@dcloudio/uni-shared'
import { import {
DirectiveNode,
ElementNode, ElementNode,
ElementTypes, ElementTypes,
findDir, findDir,
findProp,
SimpleExpressionNode, SimpleExpressionNode,
} from '@vue/compiler-core' } from '@vue/compiler-core'
import { compileTemplate } from '@vue/compiler-sfc' import { compileTemplate } from '@vue/compiler-sfc'
...@@ -41,6 +39,7 @@ const codes = [ ...@@ -41,6 +39,7 @@ const codes = [
`<input v-model="text"/>`, `<input v-model="text"/>`,
`<textarea v-model="text"/>`, `<textarea v-model="text"/>`,
`<slider/>`, `<slider/>`,
`<scroll-view data-id="id" scroll-x="true" :show-scrollbar="true"/>`,
] ]
describe('app-nvue: compiler', () => { describe('app-nvue: compiler', () => {
...@@ -58,25 +57,25 @@ describe('app-nvue: compiler', () => { ...@@ -58,25 +57,25 @@ describe('app-nvue: compiler', () => {
test('scroll-view', () => { test('scroll-view', () => {
genAst(`<view></view>`) genAst(`<view></view>`)
}) })
test('render-whole', () => { // test('render-whole', () => {
expect( // expect(
( // (
( // (
findProp( // findProp(
genAst(`<view :render-whole="true">hello</view>`), // genAst(`<view :render-whole="true">hello</view>`),
'appendAsTree', // 'appendAsTree',
true, // true,
false // false
) as DirectiveNode // ) as DirectiveNode
).arg as SimpleExpressionNode // ).arg as SimpleExpressionNode
).content // ).content
).toBe('appendAsTree') // ).toBe('appendAsTree')
}) // })
test('unitary tag', () => { // test('unitary tag', () => {
expect( // expect(
findProp(genAst(`<text>hello</text>`), 'appendAsTree', true, false) // findProp(genAst(`<text>hello</text>`), 'appendAsTree', true, false)
).toBeTruthy() // ).toBeTruthy()
}) // })
test('tap=>click', () => { test('tap=>click', () => {
expect( expect(
( (
......
...@@ -2,6 +2,7 @@ import type { PreRenderedChunk } from 'rollup' ...@@ -2,6 +2,7 @@ import type { PreRenderedChunk } from 'rollup'
import type { Plugin } from 'vite' import type { Plugin } from 'vite'
import path from 'path' import path from 'path'
import colors from 'picocolors' import colors from 'picocolors'
import { defaultNVueRpx2Unit } from '@dcloudio/uni-shared'
import { import {
APP_SERVICE_FILENAME, APP_SERVICE_FILENAME,
commonjsProxyRE, commonjsProxyRE,
...@@ -18,16 +19,16 @@ import { ...@@ -18,16 +19,16 @@ import {
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
import { parse } from '@dcloudio/uni-nvue-styler' import { parse } from '@dcloudio/uni-nvue-styler'
import { nvueOutDir } from '../../utils' import { nvueOutDir } from '../../utils'
import { transformRenderWhole } from './transforms/transformRenderWhole' // import { transformRenderWhole } from './transforms/transformRenderWhole'
import { transformAppendAsTree } from './transforms/transformAppendAsTree' // import { transformAppendAsTree } from './transforms/transformAppendAsTree'
import { transformVideo } from './transforms/transformVideo' import { transformVideo } from './transforms/transformVideo'
import { transformText } from './transforms/transformText' import { transformText } from './transforms/transformText'
import { createConfigResolved } from '../../plugin/configResolved' import { createConfigResolved } from '../../plugin/configResolved'
import { defaultNVueRpx2Unit } from '@dcloudio/uni-shared'
import { external, globals } from '../utils' import { external, globals } from '../utils'
import { transformRootNode } from './transforms/transformRootNode' import { transformRootNode } from './transforms/transformRootNode'
import { transformModel } from './transforms/vModel' import { transformModel } from './transforms/vModel'
import { transformShow } from './transforms/vShow' import { transformShow } from './transforms/vShow'
import { transformAttrs } from './transforms/transformAttrs'
const uTags = { const uTags = {
text: 'u-text', text: 'u-text',
...@@ -44,10 +45,11 @@ export function initNVueNodeTransforms() { ...@@ -44,10 +45,11 @@ export function initNVueNodeTransforms() {
return [ return [
transformRootNode, transformRootNode,
createTransformTag(uTags), createTransformTag(uTags),
transformAttrs,
transformText, transformText,
transformVideo, transformVideo,
transformRenderWhole, // transformRenderWhole,
transformAppendAsTree, // transformAppendAsTree,
] ]
} }
......
import {
isDirectiveNode,
isElementNode,
isSimpleExpressionNode,
} from '@dcloudio/uni-cli-shared'
import { isAppNVueNativeTag } from '@dcloudio/uni-shared'
import { NodeTransform } from '@vue/compiler-core'
import { camelize } from '@vue/shared'
/**
* 将内置组件属性调整为驼峰
* @param node
* @param context
* @returns
*/
export const transformAttrs: NodeTransform = (node, context) => {
if (!isElementNode(node)) {
return
}
if (!isAppNVueNativeTag(node.tag)) {
return
}
node.props.forEach((prop) => {
if (isDirectiveNode(prop)) {
const { arg } = prop
if (arg && isSimpleExpressionNode(arg)) {
arg.content = normalizePropName(arg.content)
}
} else {
prop.name = normalizePropName(prop.name)
}
})
}
function normalizePropName(name: string) {
if (name.startsWith('data-')) {
return name
}
return camelize(name)
}
...@@ -5587,7 +5587,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -5587,7 +5587,8 @@ function baseCreateRenderer(options, createHydrationFns) {
if ('value' in props) { if ('value' in props) {
hostPatchProp(el, 'value', null, props.value); // fixed by xxxxxx
hostPatchProp(el, 'value', null, props.value, false, [], parentComponent);
} }
if (vnodeHook = props.onVnodeBeforeMount) { if (vnodeHook = props.onVnodeBeforeMount) {
...@@ -5733,7 +5734,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -5733,7 +5734,8 @@ function baseCreateRenderer(options, createHydrationFns) {
/* CLASS */ /* CLASS */
) { ) {
if (oldProps.class !== newProps.class) { if (oldProps.class !== newProps.class) {
hostPatchProp(el, 'class', null, newProps.class, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'class', null, newProps.class, isSVG, [], parentComponent);
} }
} // style } // style
// this flag is matched when the element has dynamic style bindings // this flag is matched when the element has dynamic style bindings
...@@ -5742,7 +5744,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -5742,7 +5744,8 @@ function baseCreateRenderer(options, createHydrationFns) {
if (patchFlag & 4 if (patchFlag & 4
/* STYLE */ /* STYLE */
) { ) {
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG, [], parentComponent);
} // props } // props
// This flag is matched when the element has dynamic prop/attr bindings // This flag is matched when the element has dynamic prop/attr bindings
// other than class and style. The keys of dynamic prop/attrs are saved for // other than class and style. The keys of dynamic prop/attrs are saved for
...@@ -5839,7 +5842,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -5839,7 +5842,8 @@ function baseCreateRenderer(options, createHydrationFns) {
} }
if ('value' in newProps) { if ('value' in newProps) {
hostPatchProp(el, 'value', oldProps.value, newProps.value); // fixed by xxxxxx
hostPatchProp(el, 'value', oldProps.value, newProps.value, false, [], parentComponent);
} }
} }
}; };
...@@ -9329,19 +9333,10 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -9329,19 +9333,10 @@ function isMatchParentSelector(parentSelector, el) {
var item = classArray[i]; var item = classArray[i];
var type = item[item.length - 1]; var type = item[item.length - 1];
var className = item.replace(TYPE_RE, ''); var className = item.replace(TYPE_RE, '');
var property = PROPERTY_PARENT_NODE;
var recurse = true;
if (type === '>') { if (type === '~' || type === ' ') {
recurse = false; var property = type === '~' ? PROPERTY_PREVIOUS_SIBLING : PROPERTY_PARENT_NODE;
} else if (type === '+') {
property = PROPERTY_PREVIOUS_SIBLING;
recurse = false;
} else if (type === '~') {
property = PROPERTY_PREVIOUS_SIBLING;
}
if (recurse) {
while (el) { while (el) {
el = el[property]; el = el[property];
...@@ -9354,7 +9349,11 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -9354,7 +9349,11 @@ function isMatchParentSelector(parentSelector, el) {
return false; return false;
} }
} else { } else {
el = el && el[property]; if (type === '>') {
el = el && el[PROPERTY_PARENT_NODE];
} else if (type === '+') {
el = el && el[PROPERTY_PREVIOUS_SIBLING];
}
if (!hasClass(className, el)) { if (!hasClass(className, el)) {
return false; return false;
......
...@@ -4498,7 +4498,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4498,7 +4498,8 @@ function baseCreateRenderer(options, createHydrationFns) {
if ('value' in props) { if ('value' in props) {
hostPatchProp(el, 'value', null, props.value); // fixed by xxxxxx
hostPatchProp(el, 'value', null, props.value, false, [], parentComponent);
} }
if (vnodeHook = props.onVnodeBeforeMount) { if (vnodeHook = props.onVnodeBeforeMount) {
...@@ -4616,7 +4617,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4616,7 +4617,8 @@ function baseCreateRenderer(options, createHydrationFns) {
/* CLASS */ /* CLASS */
) { ) {
if (oldProps.class !== newProps.class) { if (oldProps.class !== newProps.class) {
hostPatchProp(el, 'class', null, newProps.class, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'class', null, newProps.class, isSVG, [], parentComponent);
} }
} // style } // style
// this flag is matched when the element has dynamic style bindings // this flag is matched when the element has dynamic style bindings
...@@ -4625,7 +4627,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4625,7 +4627,8 @@ function baseCreateRenderer(options, createHydrationFns) {
if (patchFlag & 4 if (patchFlag & 4
/* STYLE */ /* STYLE */
) { ) {
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG, [], parentComponent);
} // props } // props
// This flag is matched when the element has dynamic prop/attr bindings // This flag is matched when the element has dynamic prop/attr bindings
// other than class and style. The keys of dynamic prop/attrs are saved for // other than class and style. The keys of dynamic prop/attrs are saved for
...@@ -4722,7 +4725,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4722,7 +4725,8 @@ function baseCreateRenderer(options, createHydrationFns) {
} }
if ('value' in newProps) { if ('value' in newProps) {
hostPatchProp(el, 'value', oldProps.value, newProps.value); // fixed by xxxxxx
hostPatchProp(el, 'value', oldProps.value, newProps.value, false, [], parentComponent);
} }
} }
}; };
...@@ -7596,19 +7600,10 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -7596,19 +7600,10 @@ function isMatchParentSelector(parentSelector, el) {
var item = classArray[i]; var item = classArray[i];
var type = item[item.length - 1]; var type = item[item.length - 1];
var className = item.replace(TYPE_RE, ''); var className = item.replace(TYPE_RE, '');
var property = PROPERTY_PARENT_NODE;
var recurse = true;
if (type === '>') { if (type === '~' || type === ' ') {
recurse = false; var property = type === '~' ? PROPERTY_PREVIOUS_SIBLING : PROPERTY_PARENT_NODE;
} else if (type === '+') {
property = PROPERTY_PREVIOUS_SIBLING;
recurse = false;
} else if (type === '~') {
property = PROPERTY_PREVIOUS_SIBLING;
}
if (recurse) {
while (el) { while (el) {
el = el[property]; el = el[property];
...@@ -7621,7 +7616,11 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -7621,7 +7616,11 @@ function isMatchParentSelector(parentSelector, el) {
return false; return false;
} }
} else { } else {
el = el && el[property]; if (type === '>') {
el = el && el[PROPERTY_PARENT_NODE];
} else if (type === '+') {
el = el && el[PROPERTY_PREVIOUS_SIBLING];
}
if (!hasClass(className, el)) { if (!hasClass(className, el)) {
return false; return false;
......
...@@ -4622,7 +4622,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4622,7 +4622,8 @@ function baseCreateRenderer(options, createHydrationFns) {
* affect non-DOM renderers) * affect non-DOM renderers)
*/ */
if ('value' in props) { if ('value' in props) {
hostPatchProp(el, 'value', null, props.value); // fixed by xxxxxx
hostPatchProp(el, 'value', null, props.value, false, [], parentComponent);
} }
if ((vnodeHook = props.onVnodeBeforeMount)) { if ((vnodeHook = props.onVnodeBeforeMount)) {
invokeVNodeHook(vnodeHook, parentComponent, vnode); invokeVNodeHook(vnodeHook, parentComponent, vnode);
...@@ -4743,13 +4744,15 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4743,13 +4744,15 @@ function baseCreateRenderer(options, createHydrationFns) {
// this flag is matched when the element has dynamic class bindings. // this flag is matched when the element has dynamic class bindings.
if (patchFlag & 2 /* CLASS */) { if (patchFlag & 2 /* CLASS */) {
if (oldProps.class !== newProps.class) { if (oldProps.class !== newProps.class) {
hostPatchProp(el, 'class', null, newProps.class, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'class', null, newProps.class, isSVG, [], parentComponent);
} }
} }
// style // style
// this flag is matched when the element has dynamic style bindings // this flag is matched when the element has dynamic style bindings
if (patchFlag & 4 /* STYLE */) { if (patchFlag & 4 /* STYLE */) {
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG); // fixed by xxxxxx
hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG, [], parentComponent);
} }
// props // props
// This flag is matched when the element has dynamic prop/attr bindings // This flag is matched when the element has dynamic prop/attr bindings
...@@ -4841,7 +4844,8 @@ function baseCreateRenderer(options, createHydrationFns) { ...@@ -4841,7 +4844,8 @@ function baseCreateRenderer(options, createHydrationFns) {
} }
} }
if ('value' in newProps) { if ('value' in newProps) {
hostPatchProp(el, 'value', oldProps.value, newProps.value); // fixed by xxxxxx
hostPatchProp(el, 'value', oldProps.value, newProps.value, false, [], parentComponent);
} }
} }
}; };
...@@ -7813,19 +7817,8 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -7813,19 +7817,8 @@ function isMatchParentSelector(parentSelector, el) {
const item = classArray[i]; const item = classArray[i];
const type = item[item.length - 1]; const type = item[item.length - 1];
const className = item.replace(TYPE_RE, ''); const className = item.replace(TYPE_RE, '');
let property = PROPERTY_PARENT_NODE; if (type === '~' || type === ' ') {
let recurse = true; const property = type === '~' ? PROPERTY_PREVIOUS_SIBLING : PROPERTY_PARENT_NODE;
if (type === '>') {
recurse = false;
}
else if (type === '+') {
property = PROPERTY_PREVIOUS_SIBLING;
recurse = false;
}
else if (type === '~') {
property = PROPERTY_PREVIOUS_SIBLING;
}
if (recurse) {
while (el) { while (el) {
el = el[property]; el = el[property];
if (hasClass(className, el)) { if (hasClass(className, el)) {
...@@ -7837,7 +7830,12 @@ function isMatchParentSelector(parentSelector, el) { ...@@ -7837,7 +7830,12 @@ function isMatchParentSelector(parentSelector, el) {
} }
} }
else { else {
el = el && el[property]; if (type === '>') {
el = el && el[PROPERTY_PARENT_NODE];
}
else if (type === '+') {
el = el && el[PROPERTY_PREVIOUS_SIBLING];
}
if (!hasClass(className, el)) { if (!hasClass(className, el)) {
return false; return false;
} }
......
...@@ -11,24 +11,43 @@ async function objectifierRule(input: string) { ...@@ -11,24 +11,43 @@ async function objectifierRule(input: string) {
} }
describe('nvue-styler: combinators', () => { describe('nvue-styler: combinators', () => {
test('compound', async () => {
const { json, messages } = await objectifierRule(`.a.b{left:0}`)
expect(json).toEqual({ a: { '.b': { left: 0 } } })
expect(messages.length).toBe(0)
const res = await objectifierRule(`.a .b.c.d{left:0}`)
expect(res.json).toEqual({ b: { '.a .c.d': { left: 0 } } })
expect(res.messages.length).toBe(0)
const res1 = await objectifierRule(
`.a .b .c.d.e{left:0} .c{left:1} .a .c{left:2}`
)
expect(res1.json).toEqual({
c: { '.a .b .d.e': { left: 0 }, '': { left: 1 }, '.a ': { left: 2 } },
})
expect(res1.messages.length).toBe(0)
const res2 = await objectifierRule(`.a .b .c.d.e .f{left:0}`)
expect(res2.json).toEqual({ f: { '.a .b .c.d.e ': { left: 0 } } })
expect(res2.messages.length).toBe(0)
})
test('descendant', async () => { test('descendant', async () => {
const { json, messages } = await objectifierRule( const { json, messages } = await objectifierRule(
` .bar {left:5!important;}.foo .bar {left: 0!important;}.foo .bar{left:5;right:5;right:10!important}.bar .bar{left:2}.foo .bar .foobar{left:1}` ` .bar {left:5!important;}.foo .bar {left: 0!important;}.foo .bar{left:5;right:5;right:10!important}.bar .bar{left:2}.foo .bar .foobar{left:1}`
) )
expect(json).toEqual({ expect(json).toEqual({
bar: { bar: {
'': { '': {
'!left': 5, '!left': 5,
}, },
'.foo': { '.foo ': {
'!left': 0, '!left': 0,
'!right': 10, '!right': 10,
}, },
'.bar': { '.bar ': {
left: 2, left: 2,
}, },
}, },
foobar: { '.foo .bar': { left: 1 } }, foobar: { '.foo .bar ': { left: 1 } },
}) })
expect(messages.length).toBe(0) expect(messages.length).toBe(0)
}) })
......
...@@ -8,7 +8,7 @@ async function objectifierRule(input: string) { ...@@ -8,7 +8,7 @@ async function objectifierRule(input: string) {
} }
} }
describe('nvue-styler: parse', () => { describe('nvue-styler: normalize', () => {
test('basic', async () => { test('basic', async () => {
const { json, messages } = await objectifierRule(`.foo{ const { json, messages } = await objectifierRule(`.foo{
color: #FF0000; color: #FF0000;
...@@ -42,11 +42,11 @@ zIndex: 4; ...@@ -42,11 +42,11 @@ zIndex: 4;
expect(json).toEqual({ expect(json).toEqual({
foo: { foo: {
'': { '': {
width: '200px', width: 200,
paddingLeft: 300, paddingLeft: 300,
borderWidth: '1pt', borderWidth: '1pt',
left: 0, left: 0,
right: '0px', right: 0,
height: '10rpx', height: '10rpx',
paddingTop: '11upx', paddingTop: '11upx',
}, },
...@@ -463,7 +463,7 @@ zIndex: 4; ...@@ -463,7 +463,7 @@ zIndex: 4;
'': { '': {
color: '#FF0000', color: '#FF0000',
WebkitTransform: 'rotate(90deg)', WebkitTransform: 'rotate(90deg)',
width: '200px', width: 200,
}, },
}, },
}) })
......
...@@ -8,7 +8,7 @@ async function objectifierRoot(input: string) { ...@@ -8,7 +8,7 @@ async function objectifierRoot(input: string) {
} }
} }
describe('nvue-styler: parse', () => { describe('nvue-styler: objectifier', () => {
test('basic', async () => { test('basic', async () => {
const code = const code =
'html {color: #000000;}\n\n.foo {color: red; background-color: rgba(255,255,255,0.6); -webkit-transform: rotate(90deg); width: 200px; left: 0; right: 0px; border-width: 1pt; font-weight: 100}\n\n.bar {background: red}' 'html {color: #000000;}\n\n.foo {color: red; background-color: rgba(255,255,255,0.6); -webkit-transform: rotate(90deg); width: 200px; left: 0; right: 0px; border-width: 1pt; font-weight: 100}\n\n.bar {background: red}'
...@@ -19,9 +19,9 @@ describe('nvue-styler: parse', () => { ...@@ -19,9 +19,9 @@ describe('nvue-styler: parse', () => {
color: '#FF0000', color: '#FF0000',
backgroundColor: 'rgba(255,255,255,0.6)', backgroundColor: 'rgba(255,255,255,0.6)',
WebkitTransform: 'rotate(90deg)', WebkitTransform: 'rotate(90deg)',
width: '200px', width: 200,
left: 0, left: 0,
right: '0px', right: 0,
borderWidth: '1pt', borderWidth: '1pt',
fontWeight: '100', fontWeight: '100',
}, },
...@@ -56,7 +56,7 @@ describe('nvue-styler: parse', () => { ...@@ -56,7 +56,7 @@ describe('nvue-styler: parse', () => {
test('fix prop value', async () => { test('fix prop value', async () => {
const code = '.foo {font-size: 200px;}' const code = '.foo {font-size: 200px;}'
const { json, messages } = await objectifierRoot(code) const { json, messages } = await objectifierRoot(code)
expect(json).toEqual({ foo: { '': { fontSize: '200px' } } }) expect(json).toEqual({ foo: { '': { fontSize: 200 } } })
expect(messages.length).toBe(0) expect(messages.length).toBe(0)
}) })
test('ensure number type value', async () => { test('ensure number type value', async () => {
...@@ -64,7 +64,7 @@ describe('nvue-styler: parse', () => { ...@@ -64,7 +64,7 @@ describe('nvue-styler: parse', () => {
const { json, messages } = await objectifierRoot(code) const { json, messages } = await objectifierRoot(code)
expect(json).toEqual({ expect(json).toEqual({
foo: { '': { lineHeight: 40 } }, foo: { '': { lineHeight: 40 } },
bar: { '': { lineHeight: '20px' } }, bar: { '': { lineHeight: 20 } },
}) })
expect(messages.length).toBe(0) expect(messages.length).toBe(0)
}) })
...@@ -291,23 +291,23 @@ describe('nvue-styler: parse', () => { ...@@ -291,23 +291,23 @@ describe('nvue-styler: parse', () => {
expect(json).toEqual({ expect(json).toEqual({
foo: { foo: {
'': { '': {
paddingTop: '20px', paddingTop: 20,
paddingRight: '20px', paddingRight: 20,
paddingBottom: '20px', paddingBottom: 20,
paddingLeft: '20px', paddingLeft: 20,
marginTop: '30px', marginTop: 30,
marginRight: 40, marginRight: 40,
marginBottom: '30px', marginBottom: 30,
marginLeft: 40, marginLeft: 40,
}, },
}, },
bar: { bar: {
'': { '': {
paddingTop: 10, paddingTop: 10,
paddingRight: '20px', paddingRight: 20,
paddingBottom: '30px', paddingBottom: 30,
paddingLeft: 40, paddingLeft: 40,
marginTop: '10px', marginTop: 10,
marginRight: 20, marginRight: 20,
marginBottom: 30, marginBottom: 30,
marginLeft: 20, marginLeft: 20,
...@@ -322,17 +322,17 @@ describe('nvue-styler: parse', () => { ...@@ -322,17 +322,17 @@ describe('nvue-styler: parse', () => {
expect(json).toEqual({ expect(json).toEqual({
foo: { foo: {
'': { '': {
paddingTop: '20px', paddingTop: 20,
paddingRight: '20px', paddingRight: 20,
paddingBottom: '20px', paddingBottom: 20,
paddingLeft: '30px', paddingLeft: 30,
}, },
}, },
bar: { bar: {
'': { '': {
marginTop: '10px', marginTop: 10,
marginRight: 20, marginRight: 20,
marginBottom: '30px', marginBottom: 30,
marginLeft: 20, marginLeft: 20,
}, },
}, },
......
...@@ -12,7 +12,7 @@ export const normalizeLength: Normalize = (v: string | number) => { ...@@ -12,7 +12,7 @@ export const normalizeLength: Normalize = (v: string | number) => {
if (match) { if (match) {
var unit = match[1] var unit = match[1]
if (!unit) { if (!unit || unit === 'px') {
return { value: parseFloat(v) } return { value: parseFloat(v) }
} else if (SUPPORT_CSS_UNIT.indexOf(unit) > -1) { } else if (SUPPORT_CSS_UNIT.indexOf(unit) > -1) {
return { value: v } return { value: v }
......
...@@ -68,8 +68,14 @@ function transformSelector( ...@@ -68,8 +68,14 @@ function transformSelector(
if (!res) { if (!res) {
return return
} }
let parentSelector = res[1].trim() let parentSelector = res[1]
let curSelector = res[2].trim().substring(1) let curSelector = res[2].substring(1)
// .a.b => a.b
const dotIndex = curSelector.indexOf('.')
if (dotIndex > -1) {
parentSelector += curSelector.substring(dotIndex)
curSelector = curSelector.substring(0, dotIndex)
}
const pseudoIndex = curSelector.indexOf(':') const pseudoIndex = curSelector.indexOf(':')
if (pseudoIndex > -1) { if (pseudoIndex > -1) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册