tiny-engine/packages/controller/js/ast.js

152 lines
4.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { parse, parseExpression } from '@babel/parser'
import generate from '@babel/generator'
import traverse from '@babel/traverse'
import prettier from 'prettier'
import parserHtml from 'prettier/parser-html'
import parseCss from 'prettier/parser-postcss'
import parserBabel from 'prettier/parser-babel'
import prettierConfig from './config-files/prettierrc'
const METHOD_REGEXP = /function.*?\(/
export const insertName = (name, content) => content.replace(METHOD_REGEXP, `function ${name}(`)
export const removeName = (content) => content.replace(METHOD_REGEXP, 'function (')
export const string2Ast = (string = '') => parse(string, { sourceType: 'module', plugins: ['typescript', 'jsx'] })
export const ast2String = (ast) => generate(ast, { retainLines: true }).code
const formatScript = (string) => {
let newStr = string
const options = {
parser: 'babel',
plugins: [parserBabel],
...prettierConfig
}
try {
// 低码中的编辑器大多只会输入js值并不是一个完整的javascript表达式无法格式化因此需要特殊处理预格式化该种情形
newStr = prettier.format(`!${string}`, options).substring(1).replace(/\n$/, '')
} catch (error) {
newStr = prettier.format(newStr, options)
}
return newStr
}
const formatJson = (string) =>
prettier.format(string, {
parser: 'json',
plugins: [parserBabel],
trailingComma: 'es5',
...prettierConfig
})
const formatHtml = (string) =>
prettier.format(string, {
parser: 'html',
plugins: [parserBabel, parserHtml],
...prettierConfig
})
const formatCss = (string) =>
prettier.format(string, {
parser: 'css',
plugins: [parseCss],
...prettierConfig
})
const formatterMap = {
json: formatJson,
typescript: formatScript,
javascript: formatScript,
html: formatHtml,
css: formatCss
}
export const formatString = (str, language) => {
const formatter = formatterMap[language] || formatJson
let result = str
try {
result = formatter(str)
} catch (error) {
const printer = console
printer.log(error)
}
return result
}
export { parse, parseExpression, traverse, generate }
export const includedExpression = (code, expression) => {
let flag = false
try {
traverse(parse(code), {
ExpressionStatement(path) {
if (path.toString().includes(expression)) {
flag = true
return
}
}
})
} catch (err) {
const printer = console
printer.log(err)
}
return flag
}
export const includedExpressionInSchema = (schemaObj, expression) => {
let hadFlag = false
const checkReferencedFromSchema = (_schemaObj) => {
Object.values(_schemaObj).forEach((schemaObjIner) => {
if (
['[object Array]', '[object Object]'].includes(Object.prototype.toString.call(schemaObjIner)) &&
Object.keys(schemaObjIner).length
) {
if (schemaObjIner.type && ['jsstring', 'JSExpression', 'JSFunction'].includes(schemaObjIner.type)) {
if (includedExpression(schemaObjIner.value, expression)) {
hadFlag = true
return
}
} else {
checkReferencedFromSchema(schemaObjIner)
}
}
})
}
checkReferencedFromSchema(schemaObj)
return hadFlag
}
export const findExpressionInAppSchema = (pageSchemas, expression) => {
const includedPage = []
pageSchemas.forEach((pageSchema) => {
if (includedExpressionInSchema(pageSchema, expression)) {
includedPage.push(pageSchema.fileName)
}
})
return includedPage
}