export const iterateComponentData = (() => {
const iterator = (fn, childrenData) => {
for (let i = 0; i < childrenData.length; i++) {
const childData = childrenData[i]
if (!childData) { continue }
const flag = fn(childData, childrenData)
if (flag) { return }
if (childData.childrenData && childData.childrenData.length > 0) {
iterator(fn, childData.childrenData)
}
}
}
return (
fn,
childrenData
) => {
iterator(fn, childrenData)
}
})()
export const createTag = ({ type = 'style', key, content }) => {
const dom = document.getElementById(key) || null
const target = dom || document.createElement(type)
type === 'style' && target.setAttribute('type', 'text/css')
target.id = key
target.innerHTML = content
!dom && document.head.appendChild(target)
}
import { kebabCase, cloneDeep } from 'lodash'
const cssKey = 'editing-css'
const jsKey = 'editing-js'
export const OperaType = {
add: 0,
clear: 1,
update: 2
}
const deal = {
style ({ className, style }) {
let itemCss = ''
for (const key in style) {
itemCss += `${kebabCase(key)}: ${style[key]};`
}
itemCss = `${className}{${itemCss}}`
return itemCss
},
interact ({ className, interact }) {
let interactText = ''
for (const key in interact) {
if (key) {
const isPse = /^:/.test(key)
const insterName = isPse ? `${className}${key}` : `${className} ${key}`
interactText += deal.style({ className: insterName, style: interact[key] })
}
}
return interactText
},
media ({ className, media, mediaObj = {} }) {
for (const key in media) {
const mediaInteract = cloneDeep(media[key])
delete mediaInteract.normal
const mediaCss = deal.style({ className, style: media[key].normal }) + deal.interact({ className, interact: mediaInteract })
mediaObj[key] = mediaObj[key] ? `${mediaObj[key]}${mediaCss}` : mediaCss
}
return mediaObj
},
script ({ className, script, isInit }) {
const str = script ? `\n// ${className} start\n ${script.replace(/%blockID%/g, className)}\n// ${className} end` : ''
const oriJsDom = document.querySelector(`[id^='${jsKey}']`)
if (!isInit && oriJsDom) {
let allScriptStr = oriJsDom.innerHTML
console.log(allScriptStr, 'allScriptStrallScriptStrallScriptStr')
const rex = new RegExp(`(?<=\\/\\/\\s+${className}\\s+start)[\\s\\S]*(?=\\/\\/\\s+${className}\\s+end)`, 'g')
if (rex.test(allScriptStr)) {
allScriptStr.replace(rex, str)
} else {
allScriptStr += str
}
oriJsDom && oriJsDom.remove()
setTimeout(() => { createTag({ key: `${jsKey}${new Date().getTime()}`, content: allScriptStr, type: 'script' }) }, 1000)
}
return str
},
delCurrCssFromSheet ({ currClass, styleSheet }) {
const cssRulesList = styleSheet?.cssRules ? Array.from(styleSheet.cssRules) : []
for (let i = cssRulesList.length - 1; i >= 0; i--) {
if (cssRulesList[i].selectorText?.includes(currClass)) {
styleSheet.deleteRule(i)
}
}
}
}
export const updateEditCss = (editData, type = OperaType.update) => {
const currClass = `.${editData.code}-${editData.id}`
const styleSheet = document.getElementById(cssKey)?.sheet || []
const mediaStyleSheet = document.getElementById(`${cssKey}-media`)?.sheet || []
const mediaStyleSheetList = mediaStyleSheet?.cssRules ? Array.from(mediaStyleSheet.cssRules) : []
deal.delCurrCssFromSheet({ styleSheet, currClass })
if (type !== OperaType.add) {
for (const key in editData.media) {
const sheetIndex = mediaStyleSheetList.findIndex(item => item.conditionText === key)
if (sheetIndex !== -1) {
deal.delCurrCssFromSheet({ styleSheet: mediaStyleSheetList[sheetIndex], currClass })
}
}
document.getElementById(currClass) && document.getElementById(currClass).remove()
}
if (type !== OperaType.clear) {
const itemInteract = deal.interact({ className: currClass, interact: editData.interact })
console.log(itemInteract, 'itemInteractitemInteractitemInteract')
const iarr = itemInteract.split('}')
iarr.forEach(rule => {
rule && styleSheet.insertRule(`${rule}}`, 0)
})
const itemStyle = deal.style({ className: currClass, style: editData.style })
styleSheet.insertRule(itemStyle, 0)
const itemMediaObj = deal.media({ className: currClass, media: editData.media })
for (const mediaKey in editData.media) {
const index = mediaStyleSheetList.findIndex(item => item.conditionText === mediaKey)
const mediaText = itemMediaObj[mediaKey]
if (index >= 0) {
const arr = mediaText.split('}')
arr.forEach(rule => {
rule && mediaStyleSheetList[index].insertRule(`${rule}}`, 0)
})
} else {
mediaStyleSheet.insertRule(`@media ${mediaKey}{${mediaText}}`, 0)
}
}
}
deal.script({ className: currClass, script: editData.script || '' })
}
export const editingCss = (data, isPreview) => {
let cssText = ''
let jsText = ''
const mediaObj = {}
iterateComponentData(function(item) {
const currClass = `.${item.code}-${item.id}`
item.style && (cssText += deal.style({ className: currClass, style: item.style }))
item.interact && (cssText += deal.interact({ className: currClass, interact: item.interact }))
item.media && deal.media({ className: currClass, media: item.media, mediaObj })
item.script && (jsText += deal.script({ className: currClass, script: item.script, isInit: true }))
cssText += '\n'
}, data.pages?.[0]?.childrenData || [data] || [])
let mediaText = ''
for (const me in mediaObj) {
mediaText += `@media ${me}{${mediaObj[me]}}`
}
if (isPreview) {
return {
css: [cssText, mediaText],
js: jsText
}
} else {
createTag({ key: cssKey, content: cssText })
createTag({ key: `${cssKey}-media`, content: mediaText })
setTimeout(() => { createTag({ key: jsKey, content: jsText, type: 'script' }) }, 1000)
}
}