Skip to content

Commit 9f907b5

Browse files
Feature/quickapp2.0 (#65)
* feat: build for lite card Signed-off-by: Yingchun <zhangyingchun@oppo.com> * feat: add fingerprint for widget Signed-off-by: Yingchun <zhangyingchun@oppo.com> * feat: add widgets into subpackages Signed-off-by: Yingchun <zhangyingchun@oppo.com> * fix: update rpk file name for widgets Signed-off-by: Yingchun <zhangyingchun@oppo.com> * fix: create style bundle file for lite card Signed-off-by: Yingchun <zhangyingchun@oppo.com> * fix: show ux file path for invalid <data> in lite card Signed-off-by: Yingchun <zhangyingchun@oppo.com> * fix: code styles by prettier --------- Signed-off-by: Yingchun <zhangyingchun@oppo.com>
1 parent 7b3a574 commit 9f907b5

File tree

23 files changed

+962
-85
lines changed

23 files changed

+962
-85
lines changed

packages/hap-compiler/src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ function parseFragments(source, filePath) {
6868
import: [], // 导入组件
6969
template: [], // 模板
7070
style: [], // 样式
71-
script: [] // 脚本
71+
script: [], // 脚本
72+
data: [] // 数据
7273
}
7374
const fragment = parse5.parseFragment(source, {
7475
treeAdapter: parse5.treeAdapters.default,

packages/hap-compiler/src/template/exp.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ function trimhtml(str) {
3232
* 表达式转换
3333
* @param expContent
3434
* @param toFunc
35+
* @param isLite is lite card
3536
* @returns {*}
3637
*/
37-
function transExpr(expContent, toFunc) {
38+
function transExpr(expContent, toFunc, isLite) {
3839
let ret
3940
const trimExpContent = expContent.trim()
4041
if (!textParser.isExpr(trimExpContent)) {
4142
ret = trimhtml(expContent)
43+
} else if (isLite) {
44+
ret = trimExpContent // lite card template value
4245
} else {
4346
ret = []
4447
const tokens = textParser.parseText(trimExpContent)

packages/hap-compiler/src/template/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ function parse(source, options) {
362362
{ treeAdapter: parse5.treeAdapters.default, locationInfo: true },
363363
options.filePath
364364
)
365-
const output = { result: {}, log: [], depFiles: [] }
365+
const output = { result: {}, log: [], depFiles: [], isLite: !!options.lite }
366366

367367
// 模板为空或解析失败
368368
/* istanbul ignore if */

packages/hap-compiler/src/template/validator.js

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,7 +1419,7 @@ function checkTagName(node, output, options = {}) {
14191419
*/
14201420
function checkId(id, output) {
14211421
if (id) {
1422-
output.result.id = exp.isExpr(id) ? exp(id) : id
1422+
output.result.id = exp.isExpr(id) ? exp(id, true, output.isLite) : id
14231423
}
14241424
}
14251425

@@ -1476,22 +1476,25 @@ function checkClass(className, output) {
14761476
}
14771477
segs.push(className.slice(start)) // trailing static classes
14781478

1479+
const isLite = output.isLite
14791480
classList = segs.reduce((list, seg) => {
14801481
if (exp.isExpr(seg)) {
14811482
hasBinding = true
1482-
list.push(exp(seg, false))
1483+
list.push(exp(seg, false, isLite))
14831484
return list
14841485
}
14851486
return list.concat(
14861487
seg
14871488
.split(/\s+/g)
14881489
.filter((s) => s)
1489-
.map((s) => `'${s}'`)
1490+
.map((s) => (isLite ? s : `'${s}'`))
14901491
)
14911492
}, [])
14921493
classList = classList.filter((klass) => klass.trim())
14931494

1494-
if (hasBinding) {
1495+
if (isLite) {
1496+
output.result.classList = classList
1497+
} else if (hasBinding) {
14951498
const code = '(function () {return [' + classList.join(', ') + ']})'
14961499
try {
14971500
/* eslint-disable no-eval */
@@ -1523,6 +1526,7 @@ function checkStyle(cssText, output, locationInfo, options) {
15231526
let style = {}
15241527
const log = output.log
15251528
if (cssText) {
1529+
const isLite = output.isLite
15261530
if (exp.singleExpr(cssText)) {
15271531
// 检测是否嵌套{{}}
15281532
const incText = exp.removeExprffix(cssText)
@@ -1533,7 +1537,7 @@ function checkStyle(cssText, output, locationInfo, options) {
15331537
reason: 'ERROR: style 属性不能嵌套多层{{}}'
15341538
})
15351539
} else {
1536-
style = exp(cssText)
1540+
style = exp(cssText, true, isLite)
15371541
}
15381542
output.result.style = style
15391543
return
@@ -1551,23 +1555,25 @@ function checkStyle(cssText, output, locationInfo, options) {
15511555
k = pair[0].trim()
15521556
k = hyphenedToCamelCase(k)
15531557
v = pair[1].trim()
1554-
v = exp(v) // 处理值表达式
1555-
vResult = styler.validateDelaration(k, v, options)
1556-
v = vResult.value
1557-
1558-
v.forEach((t) => {
1559-
// 如果校验成功,则保存转换后的属性值
1560-
if (isValidValue(t.v) || typeof t.v === 'function') {
1561-
style[t.n] = t.v
1562-
}
1563-
})
1564-
1565-
if (vResult.log) {
1566-
log.push({
1567-
line: locationInfo.line || 1,
1568-
column: locationInfo.col || 1,
1569-
reason: vResult.log.reason
1558+
v = exp(v, true, isLite) // 处理值表达式
1559+
if (isLite) {
1560+
style[k] = v
1561+
} else {
1562+
vResult = styler.validateDelaration(k, v, options)
1563+
v = vResult.value
1564+
v.forEach((t) => {
1565+
// 如果校验成功,则保存转换后的属性值
1566+
if (isValidValue(t.v) || typeof t.v === 'function') {
1567+
style[t.n] = t.v
1568+
}
15701569
})
1570+
if (vResult.log) {
1571+
log.push({
1572+
line: locationInfo.line || 1,
1573+
column: locationInfo.col || 1,
1574+
reason: vResult.log.reason
1575+
})
1576+
}
15711577
}
15721578
}
15731579
})
@@ -1596,7 +1602,7 @@ function checkIs(value, output, locationInfo) {
15961602
value = exp.addExprffix(value)
15971603

15981604
// 将表达式转换为function
1599-
output.result.is = exp(value)
1605+
output.result.is = exp(value, true, output.isLite)
16001606
} else {
16011607
log.push({
16021608
line: locationInfo.line || 1,
@@ -1617,16 +1623,18 @@ function checkIf(value, output, not, locationInfo, conditionList) {
16171623
if (value) {
16181624
// 如果没有,补充上{{}}
16191625
value = exp.addExprffix(value)
1620-
1626+
const isLite = output.isLite
16211627
if (not) {
1622-
value = '{{' + buildConditionExp(conditionList) + '}}'
1628+
value = isLite
1629+
? buildLiteConditionExp(conditionList)
1630+
: '{{' + buildConditionExp(conditionList) + '}}'
16231631
} else {
16241632
// if动作前需要清除conditionList之前的结构
16251633
conditionList.length > 0 && (conditionList.length = 0)
16261634
conditionList.push(`${value.substr(2, value.length - 4)}`)
16271635
}
16281636
// 将表达式转换为function
1629-
output.result.shown = exp(value)
1637+
output.result.shown = isLite ? value : exp(value, true)
16301638
} else {
16311639
if (!not) {
16321640
log.push({
@@ -1663,12 +1671,17 @@ function checkElif(value, cond, output, locationInfo, conditionList) {
16631671
// 如果没有,补充上{{}}
16641672
value = exp.addExprffix(value)
16651673
cond = exp.addExprffix(cond)
1666-
1667-
newcond =
1668-
'{{(' + value.substr(2, value.length - 4) + ') && ' + buildConditionExp(conditionList) + '}}'
1674+
const isLite = output.isLite
1675+
newcond = isLite
1676+
? '{{' + value.substr(2, value.length - 4) + '}}&&' + buildLiteConditionExp(conditionList)
1677+
: '{{(' +
1678+
value.substr(2, value.length - 4) +
1679+
') && ' +
1680+
buildConditionExp(conditionList) +
1681+
'}}'
16691682

16701683
// 将表达式转换为function
1671-
output.result.shown = exp(newcond)
1684+
output.result.shown = isLite ? newcond : exp(newcond)
16721685
conditionList.push(`${value.substr(2, value.length - 4)}`)
16731686
} else {
16741687
log.push({
@@ -1708,12 +1721,13 @@ function checkFor(value, output, locationInfo) {
17081721
}
17091722
value = '{{' + value + '}}'
17101723

1724+
const isLite = output.isLite
17111725
let repeat
17121726
if (!key && !val) {
1713-
repeat = exp(value)
1727+
repeat = exp(value, true, isLite)
17141728
} else {
17151729
// 如果指定key,value
1716-
repeat = { exp: exp(value) }
1730+
repeat = { exp: exp(value, true, isLite) }
17171731
if (key) {
17181732
repeat.key = key
17191733
}
@@ -1765,9 +1779,9 @@ function checkEvent(name, value, output) {
17651779
try {
17661780
// 将事件转换为函数对象
17671781
/* eslint-disable no-eval */
1768-
value = eval(
1769-
'(function (evt) { return ' + exp(value, false).replace('this.evt', 'evt') + '})'
1770-
)
1782+
value = output.isLite
1783+
? value
1784+
: eval('(function (evt) { return ' + exp(value, false).replace('this.evt', 'evt') + '})')
17711785
/* eslint-enable no-eval */
17721786
} catch (err) {
17731787
err.isExpressionError = true
@@ -1798,7 +1812,7 @@ function checkCustomDirective(name, value, output, node) {
17981812
output.result.directives = output.result.directives || []
17991813
output.result.directives.push({
18001814
name: dirName,
1801-
value: exp.isExpr(value) ? exp(value) : value
1815+
value: exp.isExpr(value) ? exp(value, true, output.isLite) : value
18021816
})
18031817
}
18041818

@@ -1828,7 +1842,7 @@ function checkAttr(name, value, output, tagName, locationInfo, options) {
18281842
output.depFiles.push(value)
18291843
}
18301844
output.result.attr = output.result.attr || {}
1831-
output.result.attr[hyphenedToCamelCase(name)] = exp(value)
1845+
output.result.attr[hyphenedToCamelCase(name)] = exp(value, true, output.isLite)
18321846
if (name === 'value' && tagName === 'text') {
18331847
output.log.push({
18341848
line: locationInfo.line,
@@ -1947,6 +1961,19 @@ function buildConditionExp(list) {
19471961
.join(' && ')
19481962
}
19491963

1964+
/**
1965+
* 输出轻卡条件取反的字符串表示
1966+
* @param list
1967+
* @return {string}
1968+
*/
1969+
function buildLiteConditionExp(list) {
1970+
return list
1971+
.map((exp) => {
1972+
return `!{{${exp}}}`
1973+
})
1974+
.join('&&')
1975+
}
1976+
19501977
/**
19511978
* 检查节点中是否含有指令 if 或者 for
19521979
* @param {Array} nodes
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2024-present, the hapjs-platform Project Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export default function actionLoader(source) {
7+
let jsonObj = {}
8+
try {
9+
const obj = JSON.parse(source)
10+
jsonObj = obj.actions || {}
11+
} catch (e) {
12+
throw new Error(`Invalid <data> in ${this.resourcePath}:: ${e}`)
13+
}
14+
return `module.exports = ${JSON.stringify(jsonObj)}`
15+
}

packages/hap-dsl-xvm/src/loaders/common/utils.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,16 @@ export function convertPath(filePath) {
237237
}
238238
return path.join(pathBase, filePath)
239239
}
240+
241+
/**
242+
* 片段的类型
243+
*/
244+
export const FRAG_TYPE = {
245+
IMPORT: 'import',
246+
TEMPLATE: 'template',
247+
STYLE: 'style',
248+
SCRIPT: 'script',
249+
DATA: 'data',
250+
ACTIONS: 'actions',
251+
PROPS: 'props'
252+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2024-present, the hapjs-platform Project Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export default function dataLoader(source) {
7+
let jsonObj = {}
8+
try {
9+
const obj = JSON.parse(source)
10+
jsonObj = obj.uiData || obj.data || {}
11+
} catch (e) {
12+
throw new Error(`Invalid <data> in ${this.resourcePath}:: ${e}`)
13+
}
14+
return `module.exports = ${JSON.stringify(jsonObj)}`
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright (c) 2024-present, the hapjs-platform Project Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export default function propsLoader(source) {
7+
let jsonObj = {}
8+
try {
9+
const obj = JSON.parse(source)
10+
jsonObj = obj.props || {}
11+
} catch (e) {
12+
throw new Error(`Invalid <data> in ${this.resourcePath}:: ${e}`)
13+
}
14+
return `module.exports = ${JSON.stringify(jsonObj)}`
15+
}

0 commit comments

Comments
 (0)