let cssCache = {}
let cssParentCache = {}
let jsCache = {}
let imgTagName="img"
function genCssContent(block, unitRate, unitName, parentBlock) {
let css = '';
for (let key in block.style) {
let value = new String(block.style[key])
if (value) {
let allCells = value.split(' ')
for (let i = 0; i < allCells.length; i++) {
if (allCells[i].match('[0-9]+px')) {
allCells[i] = (parseInt(allCells[i].replace('px', '')) * unitRate) + unitName
}
}
value = allCells.join(' ')
}
let realCss = key.replace(/([A-Z])/g, "-$1").toLowerCase()
if (realCss == 'font-weight' && value == 'normal') continue
if (realCss == 'font-style' && value == 'normal') continue
if (!(block.blocks && (block.blocks.length > 0 || block.text != null))) {
if (realCss == 'display' && value == 'flex') continue
if (realCss == 'position' && value == 'relative') continue
if (realCss == 'width' && value == '100%' && block.domType == 'div' && parentBlock != null &&
parentBlock.blocks.length > 1) continue
if (realCss == 'flex-direction') continue
if (realCss == 'justify-content') continue
if (realCss == 'align-items') continue
}
if (realCss == 'flex-direction' && value == 'row') continue
if (realCss == 'justify-content' && value == 'flex-start') continue
if (realCss == 'align-items' && value == 'flex-start') continue
if (!(block.style.border ||
block.style.borderBottom ||
block.style.borderLeft ||
block.style.borderRight ||
block.style.borderTop ||
block.style.padding ||
block.style.paddingTop ||
block.style.paddingLeft ||
block.style.paddingRight ||
block.style.paddingBottom)) {
if (realCss == 'box-sizing' && value == 'border-box') continue
}
if (realCss == 'border-top' && value == 'none') continue
if (realCss == 'border-left' && value == 'none') continue
if (realCss == 'border-right' && value == 'none') continue
if (realCss == 'border-bottom' && value == 'none') continue
if (realCss == 'border') {
if (
block.style.borderBottom == 'none' ||
block.style.borderLeft == 'none' ||
block.style.borderRight == 'none' ||
block.style.borderTop == 'none'
) {
continue
}
}
if (value.indexOf('null') != -1) continue
css += `\t\t${realCss}:${value};\n`
}
return css;
}
function genCssMapWithChildren(block, unitRate, unitName, parentBlock, xpath) {
let result = xpath + "\n" + genCssContent(block, unitRate, unitName, parentBlock)
for (let i in block.blocks) {
result += `${xpath}>${i}\n`;
result += genCssContent(block.blocks[i], unitRate, unitName, block, xpath + ">" + i)
}
return result
}
function handleCss(block, unitRate, unitName, parentBlock, css, cssName, parentName, parentCssPath, result) {
css = genCssContent(block, unitRate, unitName, parentBlock);
let cssMap = ''
if (css != '') {
cssMap = genCssMapWithChildren(block, unitRate, unitName, parentBlock, "self")
if (cssCache[cssMap]&&cssParentCache[cssCache[cssMap]]&&cssParentCache[cssCache[cssMap]] == parentCssPath) {
block.id = cssCache[cssMap]
css = ''
}
}
cssName = block.id
let currentCssPath = `.${block.id}`
if (block.id.startsWith(parentName)) {
cssName = block.id.substr(parentName.length + 1)
currentCssPath = `${parentCssPath}>.${cssName}`
}
if (css != '') {
result.css += `\t${currentCssPath}{\n` + css + `\t}`;
if ((block.id.endsWith('-button') || block.id.endsWith('-btn'))) {
result.css += `\n\t${currentCssPath}{\n\t\tuser-select: none;\n\t}`;
result.css += `\n\t${currentCssPath}:hover{\n\t\topacity: 0.8;\n\t}`;
result.css += `\n\t${currentCssPath}:active{\n\t\topacity: 0.5;\n\t}`;
}
}
if (css != '' && cssMap != '') {
cssParentCache[block.id] = parentCssPath
cssCache[cssMap] = block.id
}
return {css, cssName, currentCssPath};
}
* 转换为vue代码
* {
* // BLOCK对象
* block,
* defaultTag: 'view',
* stylesUnit: {
* name: 'rpx',
* rate: 2
* },
* clickEvent: 'tap'
* }
*/
let parse = (config) => {
let {
block,
level,
defaultTag,
parentName,
parentCssPath,
clickEvent,
parentBlock
} = config;
if (!config.stylesUnit) {
config.stylesUnit = {
name: 'px',
rate: 1
}
}
let unitName = config.stylesUnit.name
let unitRate = config.stylesUnit.rate
if (!level) {
level = 1
}
if (level == 1) {
cssCache = {}
cssParentCache = {}
jsCache = {}
block = JSON.parse(JSON.stringify(block))
}
let result = {
html: '',
css: '',
js: ''
}
let html = ''
let js = ''
let {css, cssName, currentCssPath} =
handleCss(block, unitRate, unitName, parentBlock, '', '', parentName, parentCssPath, result);
let camelCaseId = block.id.toLowerCase().replace(/-(\w)/g, (match, p1) => p1.toUpperCase())
if (css != '') {
if ((block.id.endsWith('-button') || block.id.endsWith('-btn'))) {
result.js +=
`\tfunction ${camelCaseId}Click(){\n\t\talert("已触发${camelCaseId}Click事件")\n\t}`
}
}
if (result.js) {
jsCache[block.id] = result.js
}
if (jsCache[block.id]) {
js = jsCache[block.id]
}
let targetDomType = block.domType
if (block.domType) {
if (block.domType == 'div') {
targetDomType = defaultTag
} else if (block.domType == 'img') {
targetDomType = imgTagName
} else {
targetDomType = block.domType
}
} else {
targetDomType = defaultTag
}
for (let i = 0; i < level; i++) html += '\t'
html +=
`<${targetDomType} class="${cssName}"`
if (js) html += ` onclick="${camelCaseId}Click()"`
if (block.domType && block.domType == 'input' && block.text) html += ` value="${block.text}"`
if (block.domType == 'input' || block.domType == 'img' || block.domType == imgTagName) {
html += '/>'
} else {
html += '>'
}
if (block.text && (!block.domType || block.domType != 'input')) {
if (block.blocks && block.blocks.length >= 1) {
html += '\n'
for (let i = 0; i < level + 1; i++) {
html += '\t'
}
}
html += block.text
}
if (block.blocks && block.blocks.length >= 1) {
html += '\n'
for (let i = 0; i < block.blocks.length; i++) {
let child = block.blocks[i]
let childHtml = parse({
...config,
block: child,
level: level + 1,
parentName: block.id,
parentCssPath: currentCssPath,
parentBlock: block,
})
html += childHtml.html
if (childHtml.css != '') {
result.css += '\n' + childHtml.css
}
if (childHtml.js != '') {
if (result.js == '') {
result.js = childHtml.js
} else {
result.js += '\n' + childHtml.js
}
}
if (i != block.blocks.length - 1) {
html += '\n'
}
}
html += '\n'
for (let i = 0; i < level; i++) {
html += '\t'
}
}
if (!(block.domType == 'input' || block.domType == 'img' || block.domType == imgTagName)) {
html += `</${targetDomType}>`
}
if (block.id == 'root') {
let outputFile = ""
outputFile += "<!DOCTYPE html>\n" + "<html lang=\"zhCN\">\n"
+ "<head>\n"
+"\t<meta charset=\"UTF-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n"
+ "\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
+ "\t<title>Document</title>\n"
+ "</head>\n"
+ "<body>\n"
outputFile += `${html}\n`
outputFile += "\t<script>\n"
outputFile += result.js
outputFile += "\n\t</" + "script>\n\n"
outputFile += "\t<style>\n"
outputFile += `\thtml,body,.root{\n`
outputFile += `\t\tpadding:0;\n`
outputFile += `\t\tmargin:0;\n`
outputFile += `\t\twidth:100%;\n`
outputFile += `\t\theight:100%;\n`
outputFile += `\t}\n`
outputFile += `\tinput{\n`
outputFile += `\t\toutline:none;\n`
outputFile += `\t\tborder:none;\n`
outputFile += `\t}\n`
outputFile += result.css + "\n"
outputFile += "\t</style>\n"
outputFile += "</body>\n"
outputFile += "</html>"
html = outputFile
}
result.html = html
return result
}
export default parse