mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-19 12:09:25 +08:00
style: 更新eslint版本,更新eslint配置
This commit is contained in:
parent
5e0e776d40
commit
e7e9197ae3
@ -1,14 +0,0 @@
|
||||
dist
|
||||
coverage
|
||||
node_modules
|
||||
dest
|
||||
types
|
||||
public/entry
|
||||
public/runtime
|
||||
|
||||
comp-entry.ts
|
||||
config-entry.ts
|
||||
value-entry.ts
|
||||
|
||||
magic-admin/web/public/runtime
|
||||
magic-admin/server/static
|
@ -1,71 +0,0 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
globals: {
|
||||
describe: true,
|
||||
it: true,
|
||||
expect: true,
|
||||
beforeEach: true,
|
||||
},
|
||||
extends: [
|
||||
'eslint-config-tencent',
|
||||
'eslint-config-tencent/ts',
|
||||
'plugin:vue/vue3-essential',
|
||||
'./prettier.cjs',
|
||||
],
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 12,
|
||||
parser: '@typescript-eslint/parser',
|
||||
extraFileExtensions: ['.vue'],
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: [
|
||||
'vue',
|
||||
'@typescript-eslint',
|
||||
'simple-import-sort'
|
||||
],
|
||||
ignorePatterns: ['.eslintrc.cjs'],
|
||||
rules: {
|
||||
'vue/no-mutating-props': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
"@typescript-eslint/no-misused-promises": [
|
||||
"error",
|
||||
{
|
||||
"checksVoidReturn": false
|
||||
}
|
||||
],
|
||||
'simple-import-sort/imports': [
|
||||
"error", {
|
||||
groups: [
|
||||
['./polyfills'],
|
||||
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
||||
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
||||
[
|
||||
"^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)",
|
||||
],
|
||||
["^(node)(:.*|$)"],
|
||||
// Packages. `react|vue` related packages come first.
|
||||
["^(react|vue|vite)", "^@?\\w"],
|
||||
["^(@tmagic)(/.*|$)"],
|
||||
// Internal packages.
|
||||
["^(@|@editor|@data-source)(/.*|$)"],
|
||||
// Side effect imports.
|
||||
["^\\u0000"],
|
||||
// Parent imports. Put `..` last.
|
||||
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
|
||||
// Other relative imports. Put same-folder imports and `.` last.
|
||||
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
|
||||
// Style imports.
|
||||
["^.+\\.s?css$"],
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -31,3 +31,5 @@ coverage
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
docs/.vitepress/cache
|
||||
|
||||
.eslintcache
|
||||
|
@ -17,11 +17,7 @@
|
||||
<slot name="highlight"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="demo-block-control"
|
||||
ref="control"
|
||||
@click="isExpanded = !isExpanded"
|
||||
>
|
||||
<div class="demo-block-control" ref="control" @click="isExpanded = !isExpanded">
|
||||
<transition name="arrow-slide">
|
||||
<i :class="[iconClass, hovering]"></i>
|
||||
</transition>
|
||||
@ -30,23 +26,14 @@
|
||||
</transition>
|
||||
<el-tooltip effect="dark" :content="'前往 codepen.io 运行此示例'" placement="right">
|
||||
<transition name="text-slide">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
text
|
||||
class="control-button"
|
||||
@click.stop="goCodepen"
|
||||
>
|
||||
{{type === 'form' ? '查看结果' : '在线运行'}}
|
||||
<el-button size="small" type="primary" text class="control-button" @click.stop="goCodepen">
|
||||
{{ type === 'form' ? '查看结果' : '在线运行' }}
|
||||
</el-button>
|
||||
</transition>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="resultVisible"
|
||||
title="result"
|
||||
>
|
||||
<el-dialog v-model="resultVisible" title="result">
|
||||
<pre><code class="language-javascript hljs" v-html="result"></code></pre>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@ -60,7 +47,9 @@
|
||||
transition: 0.2s;
|
||||
|
||||
&.hover {
|
||||
box-shadow: 0 0 8px 0 rgba(232, 237, 250, 0.6), 0 2px 4px 0 rgba(232, 237, 250, 0.5);
|
||||
box-shadow:
|
||||
0 0 8px 0 rgba(232, 237, 250, 0.6),
|
||||
0 2px 4px 0 rgba(232, 237, 250, 0.5);
|
||||
}
|
||||
|
||||
code {
|
||||
@ -219,9 +208,7 @@ export function stripTemplate(content) {
|
||||
}
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'type', 'config'
|
||||
],
|
||||
props: ['type', 'config'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
@ -293,12 +280,15 @@ export default {
|
||||
},
|
||||
|
||||
text() {
|
||||
return this.isStringConfig ?
|
||||
hljs.highlight('js', this.config).value :
|
||||
hljs.highlight('js', serialize(this.config, {
|
||||
space: 2,
|
||||
unsafe: true,
|
||||
}).replace(/"(\w+)":\s/g, '$1: ')).value;
|
||||
return this.isStringConfig
|
||||
? hljs.highlight('js', this.config).value
|
||||
: hljs.highlight(
|
||||
'js',
|
||||
serialize(this.config, {
|
||||
space: 2,
|
||||
unsafe: true,
|
||||
}).replace(/"(\w+)":\s/g, '$1: '),
|
||||
).value;
|
||||
},
|
||||
|
||||
formConfig() {
|
||||
@ -307,7 +297,7 @@ export default {
|
||||
|
||||
isStringConfig() {
|
||||
return typeof this.config === 'string';
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
@ -356,7 +346,7 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
this.removeScrollHandler();
|
||||
},
|
||||
};
|
||||
|
566
eslint-config/flat/base.mjs
Normal file
566
eslint-config/flat/base.mjs
Normal file
@ -0,0 +1,566 @@
|
||||
export default {
|
||||
rules: {
|
||||
/**
|
||||
* 不要在中括号中添加空格
|
||||
*/
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
/**
|
||||
* 数组的方法除了 forEach 之外,回调函数必须有返回值
|
||||
*/
|
||||
'array-callback-return': 'warn',
|
||||
/**
|
||||
* 要求箭头函数体使用大括号
|
||||
*/
|
||||
'arrow-body-style': ['warn', 'as-needed'],
|
||||
/**
|
||||
* 要求箭头函数的参数使用圆括号
|
||||
*/
|
||||
'arrow-parens': [
|
||||
'warn',
|
||||
'as-needed',
|
||||
{
|
||||
requireForBlockBody: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 强制箭头函数的箭头前后使用一致的空格
|
||||
*/
|
||||
'arrow-spacing': 'warn',
|
||||
/**
|
||||
* 要求打开的块标志和同一行上的标志拥有一致的间距。此规则还会在同一行关闭的块标记和前边的标记强制实施一致的间距。
|
||||
*/
|
||||
'block-spacing': 'error',
|
||||
/**
|
||||
* 强制在代码块中使用一致的大括号风格
|
||||
*/
|
||||
'brace-style': 'error',
|
||||
/**
|
||||
* 使用驼峰命名法(camelCase)命名对象、函数和实例。
|
||||
*/
|
||||
camelcase: [
|
||||
'error',
|
||||
{
|
||||
ignoreDestructuring: true,
|
||||
properties: 'never',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 添加尾随逗号
|
||||
*/
|
||||
'comma-dangle': ['warn', 'always-multiline'],
|
||||
/**
|
||||
* 强制在逗号前后使用一致的空格
|
||||
*/
|
||||
'comma-spacing': [
|
||||
'error',
|
||||
{
|
||||
before: false,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 强制使用一致的逗号风格
|
||||
*/
|
||||
'comma-style': ['error', 'last'],
|
||||
/**
|
||||
* 强制在计算的属性的方括号中使用一致的空格
|
||||
*/
|
||||
'computed-property-spacing': ['warn', 'never'],
|
||||
/**
|
||||
* 禁止使用 foo['bar'],必须写成 foo.bar
|
||||
*/
|
||||
'dot-notation': 'warn',
|
||||
/**
|
||||
* 要求或禁止文件末尾存在空行
|
||||
*/
|
||||
'eol-last': ['error', 'always'],
|
||||
/**
|
||||
* 必须使用 === 或 !==,禁止使用 == 或 !=
|
||||
*/
|
||||
eqeqeq: ['warn', 'always'],
|
||||
/**
|
||||
* 要求或禁止在函数标识符和其调用之间有空格
|
||||
*/
|
||||
'func-call-spacing': ['error', 'never'],
|
||||
/**
|
||||
* 必须只使用函数声明或只使用函数表达式
|
||||
*/
|
||||
'func-style': ['off', 'expression'],
|
||||
/**
|
||||
* 强制在函数括号内使用一致的换行
|
||||
*/
|
||||
'function-paren-newline': ['warn', 'multiline'],
|
||||
/**
|
||||
* 强制 generator 函数中 * 号周围使用一致的空格
|
||||
*/
|
||||
'generator-star-spacing': [
|
||||
'warn',
|
||||
{
|
||||
before: false,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 限制变量名长度
|
||||
*/
|
||||
'id-length': 'off',
|
||||
/**
|
||||
* 强制隐式返回的箭头函数体的位置
|
||||
*/
|
||||
'implicit-arrow-linebreak': ['warn', 'beside'],
|
||||
/**
|
||||
* 使用 2 个空格缩进
|
||||
*/
|
||||
indent: [
|
||||
'warn',
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
VariableDeclarator: 1,
|
||||
outerIIFEBody: 1,
|
||||
FunctionDeclaration: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
FunctionExpression: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
CallExpression: {
|
||||
arguments: 1,
|
||||
},
|
||||
ArrayExpression: 1,
|
||||
ObjectExpression: 1,
|
||||
ImportDeclaration: 1,
|
||||
flatTernaryExpressions: false,
|
||||
ignoredNodes: [
|
||||
'JSXElement',
|
||||
'JSXElement > *',
|
||||
'JSXAttribute',
|
||||
'JSXIdentifier',
|
||||
'JSXNamespacedName',
|
||||
'JSXMemberExpression',
|
||||
'JSXSpreadAttribute',
|
||||
'JSXExpressionContainer',
|
||||
'JSXOpeningElement',
|
||||
'JSXClosingElement',
|
||||
'JSXFragment',
|
||||
'JSXOpeningFragment',
|
||||
'JSXClosingFragment',
|
||||
'JSXText',
|
||||
'JSXEmptyExpression',
|
||||
'JSXSpreadChild',
|
||||
],
|
||||
ignoreComments: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 强制在对象字面量的属性中键和值之间使用一致的间距
|
||||
*/
|
||||
'key-spacing': 'error',
|
||||
/**
|
||||
* 强制在关键字前后使用一致的空格
|
||||
*/
|
||||
'keyword-spacing': [
|
||||
'error',
|
||||
{
|
||||
overrides: {
|
||||
if: {
|
||||
after: true,
|
||||
},
|
||||
for: {
|
||||
after: true,
|
||||
},
|
||||
while: {
|
||||
after: true,
|
||||
},
|
||||
else: {
|
||||
after: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 只允许使用 unix 的 LF 作为换行符,Windows 的 CRLF 不可以使用
|
||||
*/
|
||||
'linebreak-style': ['warn', 'unix'],
|
||||
/**
|
||||
* 强制一行的最大长度,限制单行不能超过100个字符,字符串和正则表达式除外。
|
||||
*/
|
||||
'max-len': [
|
||||
'off',
|
||||
{
|
||||
code: 120,
|
||||
ignoreStrings: true,
|
||||
ignoreUrls: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 只有在命名构造器或者类的时候,才用帕斯卡拼命名法(PascalCase),即首字母大写。
|
||||
*/
|
||||
'new-cap': [
|
||||
'error',
|
||||
{
|
||||
newIsCap: true,
|
||||
newIsCapExceptions: [],
|
||||
capIsNew: false,
|
||||
capIsNewExceptions: ['Immutable.Map', 'Immutable.Set', 'Immutable.List'],
|
||||
properties: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 在编写多个方法链式调用(超过两个方法链式调用)时。 使用前导点,强调这行是一个方法调用,而不是一个语句。
|
||||
*/
|
||||
'newline-per-chained-call': [
|
||||
'warn',
|
||||
{
|
||||
ignoreChainWithDepth: 2,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 使用字面量语法创建数组。
|
||||
*/
|
||||
'no-array-constructor': ['error'],
|
||||
/**
|
||||
* 在 case 和 default 的子句中,如果存在声明 (例如. let, const, function, 和 class),使用大括号来创建块级作用域。
|
||||
*/
|
||||
'no-case-declarations': 'error',
|
||||
/**
|
||||
* 避免搞混箭头函数符号 (=>) 和比较运算符 (<=, >=)。
|
||||
*/
|
||||
'no-confusing-arrow': 'warn',
|
||||
/**
|
||||
* 禁止对使用 const 定义的常量重新赋值
|
||||
*/
|
||||
'no-const-assign': 'error',
|
||||
/**
|
||||
* 禁止重复定义类的成员
|
||||
*/
|
||||
'no-dupe-class-members': 'error',
|
||||
/**
|
||||
* 禁止在 else 内使用 return,必须改为提前结束
|
||||
*/
|
||||
'no-else-return': [
|
||||
'warn',
|
||||
{
|
||||
allowElseIf: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止使用 eval
|
||||
*/
|
||||
'no-eval': 'error',
|
||||
/**
|
||||
* 不要使用迭代器。
|
||||
* @reason 推荐使用 JavaScript 的高阶函数代替 for-in。
|
||||
*/
|
||||
'no-iterator': 'warn',
|
||||
/**
|
||||
* 禁止在循环内的函数内部出现循环体条件语句中定义的变量
|
||||
*/
|
||||
'no-loop-func': 'error',
|
||||
/**
|
||||
* 禁止混合使用不同的操作符:
|
||||
* - 禁止 `%`, `**` 之间混用
|
||||
* - 禁止 `%` 与其它运算符之间混用
|
||||
* - 禁止乘除运算符之间混用
|
||||
* - 禁止位运算符之间的任何混用
|
||||
* - 禁止比较运算符之间混用
|
||||
* - 禁止 `&&`, `||` 之间混用
|
||||
*/
|
||||
'no-mixed-operators': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
['%', '**'],
|
||||
['%', '+'],
|
||||
['%', '-'],
|
||||
['%', '*'],
|
||||
['%', '/'],
|
||||
['&', '|', '<<', '>>', '>>>'],
|
||||
['==', '!=', '===', '!=='],
|
||||
['&&', '||'],
|
||||
],
|
||||
allowSamePrecedence: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止连续赋值,比如 foo = bar = 1
|
||||
*/
|
||||
'no-multi-assign': 'error',
|
||||
/**
|
||||
* 不要使用多个空行填充代码。
|
||||
*/
|
||||
'no-multiple-empty-lines': 'error',
|
||||
/**
|
||||
* 禁止使用嵌套的三元表达式,比如 a ? b : c ? d : e
|
||||
*/
|
||||
'no-nested-ternary': 'warn',
|
||||
/**
|
||||
* 禁止使用 new Function
|
||||
* @reason 这和 eval 是等价的
|
||||
*/
|
||||
'no-new-func': 'error',
|
||||
/**
|
||||
* 禁止直接 new Object
|
||||
*/
|
||||
'no-new-object': 'error',
|
||||
/**
|
||||
* 禁止使用 new 来生成 String, Number 或 Boolean
|
||||
*/
|
||||
'no-new-wrappers': 'warn',
|
||||
/**
|
||||
* 禁止对函数的参数重新赋值
|
||||
*/
|
||||
'no-param-reassign': [
|
||||
'warn',
|
||||
{
|
||||
props: true,
|
||||
ignorePropertyModificationsFor: [
|
||||
'acc',
|
||||
'accumulator',
|
||||
'e',
|
||||
'ctx',
|
||||
'req',
|
||||
'request',
|
||||
'res',
|
||||
'response',
|
||||
'$scope',
|
||||
'staticContext',
|
||||
'state',
|
||||
],
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止使用 ++ 或 --
|
||||
*/
|
||||
'no-plusplus': [
|
||||
'error',
|
||||
{
|
||||
allowForLoopAfterthoughts: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止使用 hasOwnProperty, isPrototypeOf 或 propertyIsEnumerable
|
||||
*/
|
||||
'no-prototype-builtins': 'error',
|
||||
/**
|
||||
* 计算指数时,可以使用 ** 运算符。
|
||||
*/
|
||||
'no-restricted-properties': [
|
||||
'warn',
|
||||
{
|
||||
object: 'Math',
|
||||
property: 'pow',
|
||||
message: 'Please use ** instand',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 推荐使用 JavaScript 的高阶函数代替 for-in
|
||||
*/
|
||||
'no-restricted-syntax': [
|
||||
'warn',
|
||||
{
|
||||
selector: 'ForInStatement',
|
||||
message:
|
||||
'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
|
||||
},
|
||||
{
|
||||
selector: 'LabeledStatement',
|
||||
message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
|
||||
},
|
||||
{
|
||||
selector: 'WithStatement',
|
||||
message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 避免在行尾添加空格。
|
||||
*/
|
||||
'no-trailing-spaces': 'error',
|
||||
/**
|
||||
* 变量应先声明再使用,禁止引用任何未声明的变量,除非你明确知道引用的变量存在于当前作用域链上。
|
||||
*/
|
||||
'no-undef': ['error'],
|
||||
/**
|
||||
* 禁止变量名出现下划线
|
||||
*/
|
||||
'no-underscore-dangle': 'warn',
|
||||
/**
|
||||
* 必须使用 !a 替代 a ? false : true
|
||||
*/
|
||||
'no-unneeded-ternary': 'warn',
|
||||
/**
|
||||
* 已定义的变量必须使用
|
||||
* 但不检查最后一个使用的参数之前的参数
|
||||
* 也不检查 rest 属性的兄弟属性
|
||||
*/
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true,
|
||||
argsIgnorePattern: '^_.+',
|
||||
varsIgnorePattern: '^_.+',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止出现没必要的 constructor
|
||||
*/
|
||||
'no-useless-constructor': 'warn',
|
||||
/**
|
||||
* 禁止出现没必要的转义
|
||||
*/
|
||||
'no-useless-escape': 'error',
|
||||
/**
|
||||
* 禁止使用 var
|
||||
*/
|
||||
'no-var': 'error',
|
||||
/**
|
||||
* 禁止属性前有空白
|
||||
*/
|
||||
'no-whitespace-before-property': 'warn',
|
||||
/**
|
||||
* 强制单个语句的位置
|
||||
*/
|
||||
'nonblock-statement-body-position': ['error', 'beside'],
|
||||
/**
|
||||
* 强制在大括号中使用一致的空格
|
||||
*/
|
||||
'object-curly-spacing': ['warn', 'always'],
|
||||
/**
|
||||
* 将对象方法、属性简写,且间歇属性放在前面。
|
||||
*/
|
||||
'object-shorthand': 'warn',
|
||||
/**
|
||||
* 禁止变量申明时用逗号一次申明多个
|
||||
*/
|
||||
'one-var': ['warn', 'never'],
|
||||
/**
|
||||
* 避免在赋值语句 = 前后换行。如果你的代码单行长度超过了 max-len 定义的长度而不得不换行,那么使用括号包裹。
|
||||
*/
|
||||
'operator-linebreak': [
|
||||
'error',
|
||||
'before',
|
||||
{
|
||||
overrides: {
|
||||
'=': 'none',
|
||||
},
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 要求或禁止块内填充
|
||||
*/
|
||||
'padded-blocks': ['error', 'never'],
|
||||
/**
|
||||
* 要求回调函数使用箭头函数
|
||||
*/
|
||||
'prefer-arrow-callback': 'warn',
|
||||
/**
|
||||
* 申明后不再被修改的变量必须使用 const 来申明
|
||||
*/
|
||||
'prefer-const': [
|
||||
'error',
|
||||
{
|
||||
destructuring: 'any',
|
||||
ignoreReadBeforeAssign: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 优先使用解构赋值
|
||||
*/
|
||||
'prefer-destructuring': [
|
||||
'warn',
|
||||
{
|
||||
VariableDeclarator: {
|
||||
array: false,
|
||||
object: true,
|
||||
},
|
||||
AssignmentExpression: {
|
||||
array: true,
|
||||
object: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
enforceForRenamedProperties: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 必须使用 ...args 而不是 arguments
|
||||
*/
|
||||
'prefer-rest-params': 'warn',
|
||||
/**
|
||||
* 必须使用 ... 而不是 apply,比如 foo(...args)
|
||||
*/
|
||||
'prefer-spread': 'warn',
|
||||
/**
|
||||
* 必须使用模版字符串而不是字符串连接
|
||||
*/
|
||||
'prefer-template': 'error',
|
||||
/**
|
||||
* 要求对象字面量属性名称用引号括起来
|
||||
*/
|
||||
'quote-props': [
|
||||
'error',
|
||||
'as-needed',
|
||||
{
|
||||
keywords: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 使用单引号 '' 定义字符串
|
||||
*/
|
||||
quotes: [
|
||||
'warn',
|
||||
'single',
|
||||
{
|
||||
allowTemplateLiterals: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* parseInt 必须传入第二个参数
|
||||
*/
|
||||
radix: 'warn',
|
||||
/**
|
||||
* 要加分号
|
||||
*/
|
||||
semi: ['error', 'always'],
|
||||
/**
|
||||
* 强制在块之前使用一致的空格
|
||||
*/
|
||||
'space-before-blocks': 'error',
|
||||
/**
|
||||
* 强制在 function 的左括号之前使用一致的空格
|
||||
*/
|
||||
'space-before-function-paren': [
|
||||
'error',
|
||||
{
|
||||
anonymous: 'always',
|
||||
named: 'never',
|
||||
asyncArrow: 'always',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 强制在圆括号内使用一致的空格
|
||||
*/
|
||||
'space-in-parens': ['error', 'never'],
|
||||
/**
|
||||
* 要求操作符周围有空格
|
||||
*/
|
||||
'space-infix-ops': 'error',
|
||||
/**
|
||||
* 注释的斜线或 * 后必须有空格
|
||||
*/
|
||||
'spaced-comment': ['error', 'always'],
|
||||
/**
|
||||
* 要求或禁止模板字符串中的嵌入表达式周围空格的使用
|
||||
*/
|
||||
'template-curly-spacing': ['error', 'never'],
|
||||
/**
|
||||
* 要求立即执行的函数使用括号括起来
|
||||
*/
|
||||
'wrap-iife': ['error', 'outside'],
|
||||
},
|
||||
};
|
38
eslint-config/flat/import-sort.mjs
Normal file
38
eslint-config/flat/import-sort.mjs
Normal file
@ -0,0 +1,38 @@
|
||||
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
||||
|
||||
export default {
|
||||
files: ['**/*.{js,mjs,cjs,ts,vue}'],
|
||||
plugins: {
|
||||
'simple-import-sort': simpleImportSort,
|
||||
},
|
||||
rules: {
|
||||
'simple-import-sort/imports': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
['./polyfills'],
|
||||
['^(node)(:.*|$)'],
|
||||
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
||||
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
||||
[
|
||||
'^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)',
|
||||
],
|
||||
// Packages. `react|vue` related packages come first.
|
||||
['^(react|vue|vite|vitest)', '^@?\\w'],
|
||||
['^(@tencent)(/.*|$)'],
|
||||
['^(@tmagic)(/.*|$)'],
|
||||
// Internal packages.
|
||||
['^(@|@editor|@data-source)(/.*|$)'],
|
||||
// Side effect imports.
|
||||
['^\\u0000'],
|
||||
// Parent imports. Put `..` last.
|
||||
['^\\.\\.(?!/?$)', '^\\.\\./?$'],
|
||||
// Other relative imports. Put same-folder imports and `.` last.
|
||||
['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
||||
// Style imports.
|
||||
['^.+\\.s?css$'],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
37
eslint-config/flat/import.mjs
Normal file
37
eslint-config/flat/import.mjs
Normal file
@ -0,0 +1,37 @@
|
||||
import { rules } from 'eslint-plugin-import';
|
||||
|
||||
export default {
|
||||
plugins: {
|
||||
import: {
|
||||
meta: { name: 'eslint-plugin-import' },
|
||||
rules,
|
||||
},
|
||||
},
|
||||
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
},
|
||||
rules: {
|
||||
/**
|
||||
* 导入语句前不允许有任何非导入语句
|
||||
*/
|
||||
'import/first': 'error',
|
||||
/**
|
||||
* 禁止重复导入模块
|
||||
*/
|
||||
'import/no-duplicates': 'error',
|
||||
/**
|
||||
* 禁止使用 let 导出
|
||||
*/
|
||||
'import/no-mutable-exports': 'warn',
|
||||
/**
|
||||
* 禁用导入的模块时使用 webpack 特有的语法(感叹号)
|
||||
*/
|
||||
'import/no-webpack-loader-syntax': 'warn',
|
||||
/**
|
||||
* 当只有一个导出时,必须使用 export default 来导出
|
||||
*/
|
||||
'import/prefer-default-export': 'off',
|
||||
},
|
||||
};
|
@ -1,5 +1,4 @@
|
||||
module.exports = {
|
||||
plugins: ['prettier'],
|
||||
export default {
|
||||
rules: {
|
||||
'wrap-iife': 'off',
|
||||
'template-curly-spacing': 'off',
|
376
eslint-config/flat/ts.mjs
Normal file
376
eslint-config/flat/ts.mjs
Normal file
@ -0,0 +1,376 @@
|
||||
export default {
|
||||
files: ['**/*.ts', '**/*.tsx'],
|
||||
rules: {
|
||||
'brace-style': 'off',
|
||||
'no-empty-function': 'off',
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/491
|
||||
'no-invalid-this': 'off',
|
||||
'no-magic-numbers': 'off',
|
||||
'react/sort-comp': 'off',
|
||||
'func-call-spacing': 'off',
|
||||
'comma-spacing': 'off',
|
||||
'dot-notation': 'off',
|
||||
indent: 'off',
|
||||
'keyword-spacing': 'off',
|
||||
camelcase: 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-array-constructor': 'off',
|
||||
'no-dupe-class-members': 'off',
|
||||
'no-undef': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'no-useless-constructor': 'off',
|
||||
quotes: 'off',
|
||||
semi: 'off',
|
||||
'space-before-function-paren': 'off',
|
||||
// https://github.com/typescript-eslint/typescript-eslint/issues/600
|
||||
'spaced-comment': ['error', 'always', { markers: ['/'] }],
|
||||
/**
|
||||
* 重载的函数必须写在一起
|
||||
* @reason 增加可读性
|
||||
*/
|
||||
'@typescript-eslint/adjacent-overload-signatures': 'error',
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/brace-style': 'error',
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/comma-spacing': [
|
||||
'error',
|
||||
{
|
||||
before: false,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 类型断言必须使用 as Type,禁止使用 <Type>,禁止对对象字面量进行类型断言(断言成 any 是允许的)
|
||||
* @reason <Type> 容易被理解为 jsx
|
||||
*/
|
||||
'@typescript-eslint/consistent-type-assertions': [
|
||||
'error',
|
||||
{
|
||||
assertionStyle: 'as',
|
||||
objectLiteralTypeAssertions: 'never',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 优先使用 interface 而不是 type
|
||||
*/
|
||||
'@typescript-eslint/consistent-type-definitions': 'off',
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@typescript-eslint/dot-notation': 'warn',
|
||||
/**
|
||||
* 必须设置类的成员的可访问性
|
||||
* @reason 将不需要公开的成员设为私有的,可以增强代码的可理解性,对文档输出也很友好
|
||||
*/
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
/**
|
||||
* 要求或禁止在函数标识符和其调用之间有空格
|
||||
*/
|
||||
'@stylistic/ts/func-call-spacing': ['error', 'never'],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/indent': [
|
||||
'warn',
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
VariableDeclarator: 1,
|
||||
outerIIFEBody: 1,
|
||||
FunctionDeclaration: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
FunctionExpression: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
CallExpression: {
|
||||
arguments: 1,
|
||||
},
|
||||
ArrayExpression: 1,
|
||||
ObjectExpression: 1,
|
||||
ImportDeclaration: 1,
|
||||
flatTernaryExpressions: false,
|
||||
ignoredNodes: [
|
||||
'JSXElement',
|
||||
'JSXElement > *',
|
||||
'JSXAttribute',
|
||||
'JSXIdentifier',
|
||||
'JSXNamespacedName',
|
||||
'JSXMemberExpression',
|
||||
'JSXSpreadAttribute',
|
||||
'JSXExpressionContainer',
|
||||
'JSXOpeningElement',
|
||||
'JSXClosingElement',
|
||||
'JSXFragment',
|
||||
'JSXOpeningFragment',
|
||||
'JSXClosingFragment',
|
||||
'JSXText',
|
||||
'JSXEmptyExpression',
|
||||
'JSXSpreadChild',
|
||||
],
|
||||
ignoreComments: false,
|
||||
},
|
||||
],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/keyword-spacing': [
|
||||
'error',
|
||||
{
|
||||
overrides: {
|
||||
if: {
|
||||
after: true,
|
||||
},
|
||||
for: {
|
||||
after: true,
|
||||
},
|
||||
while: {
|
||||
after: true,
|
||||
},
|
||||
else: {
|
||||
after: true,
|
||||
},
|
||||
},
|
||||
before: true,
|
||||
after: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 指定类成员的排序规则
|
||||
* @reason 优先级:
|
||||
* 1. static > instance
|
||||
* 2. field > constructor > method
|
||||
* 3. public > protected > private
|
||||
*/
|
||||
'@typescript-eslint/member-ordering': [
|
||||
'error',
|
||||
{
|
||||
default: [
|
||||
'public-static-field',
|
||||
'protected-static-field',
|
||||
'private-static-field',
|
||||
'static-field',
|
||||
'public-static-method',
|
||||
'protected-static-method',
|
||||
'private-static-method',
|
||||
'static-method',
|
||||
'public-instance-field',
|
||||
'protected-instance-field',
|
||||
'private-instance-field',
|
||||
'public-field',
|
||||
'protected-field',
|
||||
'private-field',
|
||||
'instance-field',
|
||||
'field',
|
||||
'constructor',
|
||||
'public-instance-method',
|
||||
'protected-instance-method',
|
||||
'private-instance-method',
|
||||
'public-method',
|
||||
'protected-method',
|
||||
'private-method',
|
||||
'instance-method',
|
||||
'method',
|
||||
],
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 接口中的方法必须用属性的方式定义
|
||||
*/
|
||||
'@typescript-eslint/method-signature-style': 'off',
|
||||
/** 代替 JS 规则 camelCase 的 TS 规则 */
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'warn',
|
||||
{
|
||||
selector: 'function',
|
||||
format: ['camelCase', 'PascalCase'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
format: ['camelCase', 'UPPER_CASE'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
modifiers: ['global'],
|
||||
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
format: ['camelCase', 'PascalCase'],
|
||||
types: ['function'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
modifiers: ['exported'],
|
||||
format: ['UPPER_CASE'],
|
||||
types: ['boolean', 'string', 'number', 'array'],
|
||||
},
|
||||
{
|
||||
selector: 'variable',
|
||||
modifiers: ['exported'],
|
||||
format: ['camelCase', 'PascalCase'],
|
||||
types: ['function'],
|
||||
},
|
||||
{
|
||||
selector: ['class', 'typeLike'],
|
||||
format: ['PascalCase'],
|
||||
},
|
||||
{
|
||||
selector: ['classMethod', 'classProperty'],
|
||||
leadingUnderscore: 'forbid',
|
||||
trailingUnderscore: 'forbid',
|
||||
format: ['camelCase'],
|
||||
},
|
||||
],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@typescript-eslint/no-array-constructor': 'error',
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@typescript-eslint/no-dupe-class-members': 'error',
|
||||
/**
|
||||
* 禁止定义空的接口
|
||||
*/
|
||||
'@typescript-eslint/no-empty-interface': 'error',
|
||||
/**
|
||||
* 禁止给一个初始化时直接赋值为 number, string 的变量显式的声明类型
|
||||
* @reason 可以简化代码
|
||||
*/
|
||||
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||
/**
|
||||
* 禁止对 promise 的误用,详见示例
|
||||
*/
|
||||
'@typescript-eslint/no-misused-promises': [
|
||||
'error',
|
||||
{
|
||||
checksConditionals: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止使用 namespace 来定义命名空间
|
||||
* @reason 使用 es6 引入模块,才是更标准的方式。
|
||||
* 但是允许使用 declare namespace ... {} 来定义外部命名空间
|
||||
*/
|
||||
'@typescript-eslint/no-namespace': [
|
||||
'error',
|
||||
{
|
||||
allowDeclarations: true,
|
||||
allowDefinitionFiles: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止在 optional chaining 之后使用 non-null 断言(感叹号)
|
||||
* @reason optional chaining 后面的属性一定是非空的
|
||||
*/
|
||||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
|
||||
/**
|
||||
* 禁止给类的构造函数的参数添加修饰符
|
||||
*/
|
||||
'@typescript-eslint/no-parameter-properties': 'off',
|
||||
/**
|
||||
* 禁止使用 require
|
||||
* @reason 统一使用 import 来引入模块,特殊情况使用单行注释允许 require 引入
|
||||
*/
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
/**
|
||||
* 禁止将 this 赋值给其他变量,除非是解构赋值
|
||||
*/
|
||||
'@typescript-eslint/no-this-alias': [
|
||||
'error',
|
||||
{
|
||||
allowDestructuring: true,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止无用的表达式
|
||||
*/
|
||||
'@typescript-eslint/no-unused-expressions': [
|
||||
'error',
|
||||
{
|
||||
allowShortCircuit: true,
|
||||
allowTernary: true,
|
||||
allowTaggedTemplates: true,
|
||||
},
|
||||
],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true,
|
||||
argsIgnorePattern: '^_.+',
|
||||
varsIgnorePattern: '^_.+',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止出现没必要的 constructor
|
||||
*/
|
||||
'@typescript-eslint/no-useless-constructor': 'warn',
|
||||
/**
|
||||
* 使用 for 循环遍历数组时,如果索引仅用于获取成员,则必须使用 for of 循环替代 for 循环
|
||||
* @reason for of 循环更加易读
|
||||
*/
|
||||
'@typescript-eslint/prefer-for-of': 'warn',
|
||||
/**
|
||||
* 使用函数类型别名替代包含函数调用声明的接口
|
||||
*/
|
||||
'@typescript-eslint/prefer-function-type': 'warn',
|
||||
/**
|
||||
* 禁止使用 module 来定义命名空间
|
||||
* @reason module 已成为 js 的关键字
|
||||
*/
|
||||
'@typescript-eslint/prefer-namespace-keyword': 'error',
|
||||
/**
|
||||
* 使用 optional chaining 替代 &&
|
||||
*/
|
||||
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/quotes': [
|
||||
'warn',
|
||||
'single',
|
||||
{
|
||||
allowTemplateLiterals: false,
|
||||
},
|
||||
],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/semi': ['error', 'always'],
|
||||
/** 同 JS 规则的 TS 版本 */
|
||||
'@stylistic/ts/space-before-function-paren': [
|
||||
'error',
|
||||
{
|
||||
anonymous: 'always',
|
||||
named: 'never',
|
||||
asyncArrow: 'always',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 禁止使用三斜杠导入文件
|
||||
* @reason 三斜杠是已废弃的语法,但在类型声明文件中还是可以使用的
|
||||
*/
|
||||
'@typescript-eslint/triple-slash-reference': [
|
||||
'error',
|
||||
{
|
||||
path: 'never',
|
||||
types: 'always',
|
||||
lib: 'always',
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 在类型注释周围需要一致的间距
|
||||
*/
|
||||
'@stylistic/ts/type-annotation-spacing': 'error',
|
||||
/**
|
||||
* interface 和 type 定义时必须声明成员的类型
|
||||
*/
|
||||
'@typescript-eslint/typedef': [
|
||||
'error',
|
||||
{
|
||||
arrayDestructuring: false,
|
||||
arrowParameter: false,
|
||||
memberVariableDeclaration: false,
|
||||
objectDestructuring: false,
|
||||
parameter: false,
|
||||
propertyDeclaration: true,
|
||||
variableDeclaration: false,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* 函数重载时,若能通过联合类型将两个函数的类型声明合为一个,则使用联合类型而不是两个函数声明
|
||||
*/
|
||||
'@typescript-eslint/unified-signatures': 'error',
|
||||
},
|
||||
};
|
39
eslint-config/index.mjs
Normal file
39
eslint-config/index.mjs
Normal file
@ -0,0 +1,39 @@
|
||||
import js from '@eslint/js';
|
||||
import stylistic from '@stylistic/eslint-plugin';
|
||||
import stylisticTs from '@stylistic/eslint-plugin-ts';
|
||||
import parserTs from '@typescript-eslint/parser';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||
import pluginVue from 'eslint-plugin-vue';
|
||||
import globals from 'globals';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
import tencentEslintBaseConfig from './flat/base.mjs';
|
||||
import tencentEslintImportexport from './flat/import.mjs';
|
||||
import ImportSortConfig from './flat/import-sort.mjs';
|
||||
import tencentEslintPrettierConfig from './flat/prettier.mjs';
|
||||
import tencentEslintTsConfig from './flat/ts.mjs';
|
||||
|
||||
export default (tsconfigRootDir) =>
|
||||
defineConfig([
|
||||
{ files: ['**/*.{js,mjs,cjs}'], plugins: { js }, extends: ['js/recommended'] },
|
||||
{ files: ['**/*.{js,mjs,cjs,ts,vue}'], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
...tseslint.config(tencentEslintBaseConfig, tencentEslintImportexport, tseslint.configs.base, {
|
||||
plugins: {
|
||||
'@stylistic': stylistic,
|
||||
'@stylistic/ts': stylisticTs,
|
||||
},
|
||||
languageOptions: {
|
||||
parser: parserTs,
|
||||
parserOptions: {
|
||||
project: tsconfigRootDir,
|
||||
},
|
||||
},
|
||||
...tencentEslintTsConfig,
|
||||
}),
|
||||
pluginVue.configs['flat/essential'],
|
||||
{ files: ['**/*.vue'], languageOptions: { parserOptions: { parser: tseslint.parser } } },
|
||||
eslintPluginPrettierRecommended,
|
||||
tencentEslintPrettierConfig,
|
||||
ImportSortConfig,
|
||||
]);
|
29
eslint-config/package.json
Normal file
29
eslint-config/package.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@tmagic/eslint-config",
|
||||
"version": "0.0.1",
|
||||
"main": "index.mjs",
|
||||
"type": "module",
|
||||
"repository": {
|
||||
"directory": "eslint-config",
|
||||
"type": "git",
|
||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.24.0",
|
||||
"@typescript-eslint/parser": "^8.30.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.30.1",
|
||||
"@stylistic/eslint-plugin": "^4.2.0",
|
||||
"@stylistic/eslint-plugin-ts": "^4.2.0",
|
||||
"eslint-config-prettier": "^10.1.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"eslint-plugin-prettier": "^5.2.6",
|
||||
"globals": "^16.0.0",
|
||||
"typescript-eslint": "^8.30.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=9.24.0",
|
||||
"prettier": ">=3.5.3"
|
||||
}
|
||||
}
|
41
eslint.config.js
Normal file
41
eslint.config.js
Normal file
@ -0,0 +1,41 @@
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||
|
||||
import eslintConfig from '@tmagic/eslint-config';
|
||||
|
||||
export default defineConfig([
|
||||
globalIgnores([
|
||||
'./docs/**/*',
|
||||
'./packages/cli/lib/**/*',
|
||||
'*/**/auto-imports.d.ts',
|
||||
'*/**/components.d.ts',
|
||||
'*/**/dist/**/*',
|
||||
'*/**/.tmagic/**/*',
|
||||
'*/**/public/**/*',
|
||||
'*/**/types/**/*',
|
||||
'*/**/*.config.ts',
|
||||
'vite-env.d.ts',
|
||||
]),
|
||||
...eslintConfig(path.join(path.dirname(fileURLToPath(import.meta.url)), 'tsconfig.json')),
|
||||
{
|
||||
files: ['**/*.vue'],
|
||||
rules: {
|
||||
'vue/no-mutating-props': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.{js,mjs,cjs,ts,vue}'],
|
||||
rules: {
|
||||
'no-param-reassign': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.tsx'],
|
||||
rules: {
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
},
|
||||
},
|
||||
]);
|
18
package.json
18
package.json
@ -9,8 +9,8 @@
|
||||
"clean:top": "rimraf */**/dist */**/types */dist coverage dwt* temp packages/cli/lib",
|
||||
"clean:modules": "rimraf node_modules **/node_modules **/**/node_modules",
|
||||
"clean:all": "pnpm clean:top && pnpm clean:modules",
|
||||
"lint": "eslint . --ext .js,.vue,.ts,.tsx",
|
||||
"lint-fix": "eslint . --fix --ext .vue,.js,.ts,.tsx",
|
||||
"lint": "eslint --cache .",
|
||||
"lint-fix": "eslint --fix --cache .",
|
||||
"playground": "pnpm --filter \"runtime-vue3\" build:libs && pnpm --filter \"runtime-vue3\" --filter \"tmagic-playground\" dev",
|
||||
"pg": "pnpm playground",
|
||||
"playground:vue2": "pnpm --filter \"runtime-vue2\" build:libs && pnpm --filter \"runtime-vue2\" --filter \"tmagic-playground\" dev:vue2",
|
||||
@ -46,9 +46,8 @@
|
||||
"@commitlint/cli": "^18.6.1",
|
||||
"@commitlint/config-conventional": "^18.6.3",
|
||||
"@rollup/plugin-alias": "^5.1.1",
|
||||
"@tmagic/eslint-config": "workspace: ^*",
|
||||
"@types/node": "18.19.61",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vitest/coverage-v8": "^2.1.9",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
@ -59,12 +58,7 @@
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"element-plus": "^2.9.7",
|
||||
"enquirer": "^2.4.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-tencent": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"eslint": "^9.25.0",
|
||||
"execa": "^4.1.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"husky": "^7.0.4",
|
||||
@ -72,7 +66,7 @@
|
||||
"lint-staged": "^11.2.6",
|
||||
"minimist": "^1.2.8",
|
||||
"picocolors": "^1.1.1",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier": "^3.5.3",
|
||||
"recast": "^0.23.11",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^4.38.0",
|
||||
@ -93,7 +87,7 @@
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,vue}": "eslint --fix",
|
||||
"*.{js,ts,vue}": "eslint --fix --cache",
|
||||
"*.scss": "prettier --write"
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import path from 'path';
|
||||
import path from 'node:path';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
|
||||
@ -6,6 +6,7 @@ import { ModuleMainFilePath, UserConfig } from './types';
|
||||
import { prepareEntryFile, resolveAppPackages } from './utils';
|
||||
|
||||
export default class Core {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
public version = require('../package.json').version;
|
||||
|
||||
public options: UserConfig;
|
||||
|
@ -29,6 +29,7 @@ export const cli = (defaultAppConfig: UserConfig): void => {
|
||||
const program = cac('tmagic');
|
||||
|
||||
// display core version and cli version
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const versionCli = require('../package.json').version;
|
||||
program.version(`tmagic/cli@${versionCli}`);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import path from 'path';
|
||||
import path from 'node:path';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const backupFile = (runtimeSource: string, file: string) => {
|
||||
const filePath = path.join(runtimeSource, file);
|
||||
|
@ -10,6 +10,7 @@ export const hasExportDefault = <T = any>(mod: unknown): mod is { default: T } =
|
||||
isPlainObject(mod) && !!mod.__esModule && Object.prototype.hasOwnProperty.call(mod, 'default');
|
||||
|
||||
export const loadUserConfigCjs: UserConfigLoader = async (userConfigPath) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const required = require(userConfigPath);
|
||||
return hasExportDefault(required) ? required.default : required;
|
||||
};
|
||||
|
@ -95,7 +95,7 @@ export const prepareEntryFile = async (app: App) => {
|
||||
app.writeTemp(fileName, content);
|
||||
} else {
|
||||
fileName = `${file}.js`;
|
||||
app.writeTemp(`${file}.d.ts`, `const type: Record<string, any>;\n\nexport default type;`);
|
||||
app.writeTemp(`${file}.d.ts`, 'const type: Record<string, any>;\n\nexport default type;');
|
||||
}
|
||||
app.writeTemp(fileName, content);
|
||||
});
|
||||
@ -136,6 +136,7 @@ export const generateContent = (
|
||||
};
|
||||
|
||||
export const prettyCode = (code: string) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
recast.prettyPrint(recast.parse(code.replace(/\\/g, '/'), { parser: require('recast/parsers/typescript') }), {
|
||||
tabWidth: 2,
|
||||
trailingComma: true,
|
||||
|
@ -127,6 +127,7 @@ const typeAssertion = function ({
|
||||
|
||||
if (isFile(defaultFile)) {
|
||||
const defaultCode = fs.readFileSync(defaultFile, { encoding: 'utf-8', flag: 'r' });
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const ast = recast.parse(defaultCode, { parser: require('recast/parsers/typescript') });
|
||||
if (
|
||||
isDatasource(
|
||||
@ -518,6 +519,7 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
||||
.replace('\n', '');
|
||||
|
||||
const indexCode = fs.readFileSync(indexPath, { encoding: 'utf-8', flag: 'r' });
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const ast: Ast = recast.parse(indexCode, { parser: require('recast/parsers/typescript') });
|
||||
const result = typeAssertion({ ast, indexPath, componentFileAffix, datasoucreSuperClass });
|
||||
|
||||
|
@ -148,7 +148,7 @@ class Node extends EventEmitter {
|
||||
}
|
||||
|
||||
private listenLifeSafe() {
|
||||
this.once('created', async (instance: any) => {
|
||||
this.once('created', (instance: any) => {
|
||||
this.once('destroy', () => {
|
||||
this.instance = null;
|
||||
if (typeof this.data.destroy === 'function') {
|
||||
@ -165,24 +165,27 @@ class Node extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
await this.runHookCode('created');
|
||||
this.runHookCode('created');
|
||||
});
|
||||
|
||||
this.once('mounted', async (instance: any) => {
|
||||
if (instance) {
|
||||
this.registerMethod(instance);
|
||||
if (instance.config) {
|
||||
this.setData(instance.config);
|
||||
this.once('mounted', (instance: any) => {
|
||||
const handler = async () => {
|
||||
if (instance) {
|
||||
this.registerMethod(instance);
|
||||
if (instance.config) {
|
||||
this.setData(instance.config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let eventConfig = this.eventQueue.shift(); eventConfig; eventConfig = this.eventQueue.shift()) {
|
||||
if (typeof instance[eventConfig.method] === 'function') {
|
||||
await instance[eventConfig.method](eventConfig.fromCpt, ...eventConfig.args);
|
||||
for (let eventConfig = this.eventQueue.shift(); eventConfig; eventConfig = this.eventQueue.shift()) {
|
||||
if (typeof instance[eventConfig.method] === 'function') {
|
||||
await instance[eventConfig.method](eventConfig.fromCpt, ...eventConfig.args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this.runHookCode('mounted');
|
||||
this.runHookCode('mounted');
|
||||
};
|
||||
handler();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
|
@ -139,6 +139,7 @@ export const compliedDataSourceField = (value: any, data: DataSourceManagerData)
|
||||
|
||||
try {
|
||||
return getValueByKeyPath(fields.join('.'), dsData);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e) {
|
||||
return value;
|
||||
}
|
||||
@ -151,6 +152,7 @@ export const template = (value: string, data?: DataSourceManagerData) =>
|
||||
value.replaceAll(dataSourceTemplateRegExp, (match, $1) => {
|
||||
try {
|
||||
return getValueByKeyPath($1, data);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (e: any) {
|
||||
return match;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ describe('utils', () => {
|
||||
test('isUseDataSourceField', () => {
|
||||
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID')).toBeTruthy();
|
||||
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID1')).toBeFalsy();
|
||||
expect(utils.isUseDataSourceField([`abcdsID`, 'field'], 'dsID')).toBeFalsy();
|
||||
expect(utils.isUseDataSourceField(['abcdsID', 'field'], 'dsID')).toBeFalsy();
|
||||
expect(utils.isUseDataSourceField([123, 'field'], 123)).toBeFalsy();
|
||||
});
|
||||
|
||||
|
@ -27,9 +27,9 @@ import type { PopoverProps } from './types';
|
||||
|
||||
defineSlots<{
|
||||
/** 触发 Popover 显示的 HTML 元素 */
|
||||
reference(props: {}): any;
|
||||
reference(_props: {}): any;
|
||||
/** Popover 内嵌 HTML 文本 */
|
||||
default(props: {}): any;
|
||||
default(_props: {}): any;
|
||||
}>();
|
||||
|
||||
defineOptions({
|
||||
@ -130,7 +130,7 @@ const mouseenterHandler = () => {
|
||||
popoverVisible.value = true;
|
||||
};
|
||||
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
const mouseleaveHandler = () => {
|
||||
if (props.disabled) return;
|
||||
|
||||
|
@ -9,7 +9,6 @@ import './theme/index.scss';
|
||||
export * from './types';
|
||||
export * from './config';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
export { default as TMagicAutocomplete } from './Autocomplete.vue';
|
||||
export { default as TMagicBadge } from './Badge.vue';
|
||||
export { default as TMagicButton } from './Button.vue';
|
||||
|
@ -142,7 +142,7 @@ import codeBlockService from './services/codeBlock';
|
||||
import componentListService from './services/componentList';
|
||||
import dataSourceService from './services/dataSource';
|
||||
import depService from './services/dep';
|
||||
import editorService, { type EditorService } from './services/editor';
|
||||
import editorService from './services/editor';
|
||||
import eventsService from './services/events';
|
||||
import historyService from './services/history';
|
||||
import keybindingService from './services/keybinding';
|
||||
@ -153,25 +153,9 @@ import uiService from './services/ui';
|
||||
import keybindingConfig from './utils/keybinding-config';
|
||||
import { defaultEditorProps, EditorProps } from './editorProps';
|
||||
import { initServiceEvents, initServiceState } from './initService';
|
||||
import type {
|
||||
EventBus,
|
||||
FrameworkSlots,
|
||||
PropsPanelSlots,
|
||||
Services,
|
||||
SidebarSlots,
|
||||
StageOptions,
|
||||
WorkspaceSlots,
|
||||
} from './type';
|
||||
import type { EditorSlots, EventBus, Services, StageOptions } from './type';
|
||||
|
||||
defineSlots<
|
||||
FrameworkSlots &
|
||||
WorkspaceSlots &
|
||||
SidebarSlots &
|
||||
PropsPanelSlots & {
|
||||
workspace(props: { editorService: EditorService }): any;
|
||||
'workspace-content'(props: { editorService: EditorService }): any;
|
||||
}
|
||||
>();
|
||||
defineSlots<EditorSlots>();
|
||||
|
||||
defineOptions({
|
||||
name: 'MEditor',
|
||||
|
@ -233,7 +233,7 @@ const changeHandler = (values: CodeBlockContent) => {
|
||||
changedValue.value = values;
|
||||
};
|
||||
|
||||
const beforeClose = (done: (cancel?: boolean) => void) => {
|
||||
const beforeClose = (done: (_cancel?: boolean) => void) => {
|
||||
if (!changedValue.value) {
|
||||
done();
|
||||
return;
|
||||
|
@ -39,7 +39,7 @@ const props = withDefaults(
|
||||
defineProps<{
|
||||
position?: Position;
|
||||
title?: string;
|
||||
beforeClose?: (done: (cancel?: boolean) => void) => void;
|
||||
beforeClose?: (_done: (_cancel?: boolean) => void) => void;
|
||||
}>(),
|
||||
{
|
||||
title: '',
|
||||
|
@ -93,7 +93,9 @@ const scrollBy = (delta: number) => {
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
opacity: 0.3;
|
||||
transition: background-color 0.2s linear, opacity 0.2s linear;
|
||||
transition:
|
||||
background-color 0.2s linear,
|
||||
opacity 0.2s linear;
|
||||
|
||||
.m-editor-scroll-bar-thumb {
|
||||
background-color: #aaa;
|
||||
@ -108,7 +110,9 @@ const scrollBy = (delta: number) => {
|
||||
|
||||
.m-editor-scroll-bar-thumb {
|
||||
height: 6px;
|
||||
transition: background-color 0.2s linear, height 0.2s ease-in-out;
|
||||
transition:
|
||||
background-color 0.2s linear,
|
||||
height 0.2s ease-in-out;
|
||||
bottom: 2px;
|
||||
}
|
||||
}
|
||||
@ -120,7 +124,9 @@ const scrollBy = (delta: number) => {
|
||||
|
||||
.m-editor-scroll-bar-thumb {
|
||||
width: 6px;
|
||||
transition: background-color 0.2s linear, width 0.2s ease-in-out;
|
||||
transition:
|
||||
background-color 0.2s linear,
|
||||
width 0.2s ease-in-out;
|
||||
right: 2px;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ const emit = defineEmits(['search']);
|
||||
|
||||
const filterText = ref('');
|
||||
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
const filterTextChangeHandler = () => {
|
||||
timer && clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
|
@ -38,9 +38,9 @@ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
|
||||
import TreeNode from './TreeNode.vue';
|
||||
|
||||
defineSlots<{
|
||||
'tree-node-content'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-label'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-tool'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-content'(_props: { data: TreeNodeData }): any;
|
||||
'tree-node-label'(_props: { data: TreeNodeData }): any;
|
||||
'tree-node-tool'(_props: { data: TreeNodeData }): any;
|
||||
}>();
|
||||
|
||||
defineOptions({
|
||||
|
@ -72,9 +72,9 @@ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
|
||||
import { updateStatus } from '@editor/utils/tree';
|
||||
|
||||
defineSlots<{
|
||||
'tree-node-label'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-tool'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-content'(props: { data: TreeNodeData }): any;
|
||||
'tree-node-label'(_props: { data: TreeNodeData }): any;
|
||||
'tree-node-tool'(_props: { data: TreeNodeData }): any;
|
||||
'tree-node-content'(_props: { data: TreeNodeData }): any;
|
||||
}>();
|
||||
|
||||
defineOptions({
|
||||
|
@ -179,7 +179,11 @@ const curCharIsDot = (dotIndex: number) => dotIndex > -1 && dotIndex === getSele
|
||||
* @param leftCurlyBracketIndex 左大括号字符索引
|
||||
* @param cb 建议的方法
|
||||
*/
|
||||
const dsQuerySearch = (queryString: string, leftCurlyBracketIndex: number, cb: (data: { value: string }[]) => void) => {
|
||||
const dsQuerySearch = (
|
||||
queryString: string,
|
||||
leftCurlyBracketIndex: number,
|
||||
cb: (_data: { value: string }[]) => void,
|
||||
) => {
|
||||
let result: DataSourceSchema[] = [];
|
||||
|
||||
if (curCharIsLeftCurlyBracket(leftCurlyBracketIndex)) {
|
||||
@ -211,7 +215,7 @@ const fieldQuerySearch = (
|
||||
queryString: string,
|
||||
leftAngleIndex: number,
|
||||
dotIndex: number,
|
||||
cb: (data: { value: string }[]) => void,
|
||||
cb: (_data: { value: string }[]) => void,
|
||||
) => {
|
||||
let result: DataSchema[] = [];
|
||||
|
||||
@ -272,7 +276,7 @@ const fieldQuerySearch = (
|
||||
* @param queryString 当前输入框内的字符串
|
||||
* @param cb 建议回调
|
||||
*/
|
||||
const querySearch = (queryString: string, cb: (data: { value: string }[]) => void) => {
|
||||
const querySearch = (queryString: string, cb: (_data: { value: string }[]) => void) => {
|
||||
inputText = queryString;
|
||||
|
||||
const selectionStart = getSelectionStart();
|
||||
|
@ -80,7 +80,7 @@ const methodColumns: ColumnConfig[] = [
|
||||
{
|
||||
text: '编辑',
|
||||
handler: (method: CodeBlockContent, index: number) => {
|
||||
let codeContent = method.content || `({ params, dataSource, app }) => {\n // place your code here\n}`;
|
||||
let codeContent = method.content || '({ params, dataSource, app }) => {\n // place your code here\n}';
|
||||
|
||||
if (typeof codeContent !== 'string') {
|
||||
codeContent = codeContent.toString();
|
||||
@ -114,7 +114,7 @@ const methodColumns: ColumnConfig[] = [
|
||||
const createCodeHandler = () => {
|
||||
codeConfig.value = {
|
||||
name: '',
|
||||
content: `({ params, dataSource, app, flowState }) => {\n // place your code here\n}`,
|
||||
content: '({ params, dataSource, app, flowState }) => {\n // place your code here\n}',
|
||||
params: [],
|
||||
};
|
||||
|
||||
@ -130,7 +130,7 @@ const submitCodeHandler = (value: CodeBlockContent, data: ContainerChangeEventDa
|
||||
// 在保存的时候转换代码内容
|
||||
const parseDSL = getEditorConfig('parseDSL');
|
||||
if (typeof value.content === 'string') {
|
||||
value.content = parseDSL<(...args: any[]) => any>(value.content);
|
||||
value.content = parseDSL<(..._args: any[]) => any>(value.content);
|
||||
}
|
||||
}
|
||||
if (editIndex > -1) {
|
||||
|
@ -70,7 +70,7 @@ const uiSelectMode = ref(false);
|
||||
const cancelHandler = () => {
|
||||
uiService.set('uiSelectMode', false);
|
||||
uiSelectMode.value = false;
|
||||
globalThis.document.removeEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as EventListener);
|
||||
globalThis.document.removeEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as any);
|
||||
};
|
||||
|
||||
const clickHandler = ({ detail }: Event & { detail: HTMLElement | MNode }) => {
|
||||
@ -97,7 +97,7 @@ const toName = computed(() => {
|
||||
const startSelect = () => {
|
||||
uiService.set('uiSelectMode', true);
|
||||
uiSelectMode.value = true;
|
||||
globalThis.document.addEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as EventListener);
|
||||
globalThis.document.addEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as any);
|
||||
};
|
||||
|
||||
const deleteHandler = () => {
|
||||
|
@ -16,7 +16,7 @@ export const useCodeBlockEdit = (codeBlockService: Services['codeBlockService'])
|
||||
const createCodeBlock = async () => {
|
||||
codeConfig.value = {
|
||||
name: '',
|
||||
content: `({app, params, flowState}) => {\n // place your code here\n}`,
|
||||
content: '({app, params, flowState}) => {\n // place your code here\n}',
|
||||
params: [],
|
||||
};
|
||||
|
||||
|
@ -122,7 +122,6 @@ export default {
|
||||
app.use(formPlugin, opt || {});
|
||||
app.use(tablePlugin);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
app.config.globalProperties.$TMAGIC_EDITOR = option;
|
||||
setEditorConfig(option);
|
||||
|
||||
|
@ -269,13 +269,13 @@ export const initServiceEvents = (
|
||||
}
|
||||
};
|
||||
|
||||
const dsDepCollectedHandler = async () => {
|
||||
const dsDepCollectedHandler = () => {
|
||||
const root = editorService.get('root');
|
||||
const app = await getTMagicApp();
|
||||
|
||||
if (root && app?.dsl) {
|
||||
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
||||
}
|
||||
getTMagicApp()?.then((app?: TMagicCore) => {
|
||||
if (root && app?.dsl) {
|
||||
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const collectIdle = (nodes: MComponent[], deep: boolean, type?: DepTargetType) =>
|
||||
@ -317,7 +317,7 @@ export const initServiceEvents = (
|
||||
depService.addTarget(createDataSourceCondTarget(ds, reactive({})));
|
||||
};
|
||||
|
||||
const rootChangeHandler = async (value: MApp | null, preValue?: MApp | null) => {
|
||||
const rootChangeHandler = (value: MApp | null, preValue?: MApp | null) => {
|
||||
if (!value) return;
|
||||
|
||||
value.codeBlocks = value.codeBlocks || {};
|
||||
@ -347,39 +347,40 @@ export const initServiceEvents = (
|
||||
delete value.dataSourceCondDeps;
|
||||
}
|
||||
|
||||
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
||||
let node;
|
||||
if (nodeId) {
|
||||
node = editorService.getNodeById(nodeId);
|
||||
}
|
||||
const handler = async () => {
|
||||
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
||||
let node;
|
||||
if (nodeId) {
|
||||
node = editorService.getNodeById(nodeId);
|
||||
}
|
||||
if (node && node !== value) {
|
||||
await editorService.select(node.id);
|
||||
} else if (value.items?.length) {
|
||||
await editorService.select(value.items[0]);
|
||||
} else if (value.id) {
|
||||
editorService.set('nodes', [value]);
|
||||
editorService.set('parent', null);
|
||||
editorService.set('page', null);
|
||||
}
|
||||
|
||||
if (node && node !== value) {
|
||||
await editorService.select(node.id);
|
||||
} else if (value.items?.length) {
|
||||
await editorService.select(value.items[0]);
|
||||
} else if (value.id) {
|
||||
editorService.set('nodes', [value]);
|
||||
editorService.set('parent', null);
|
||||
editorService.set('page', null);
|
||||
}
|
||||
if (toRaw(value) !== toRaw(preValue)) {
|
||||
emit('update:modelValue', value);
|
||||
}
|
||||
};
|
||||
|
||||
if (toRaw(value) !== toRaw(preValue)) {
|
||||
emit('update:modelValue', value);
|
||||
}
|
||||
handler();
|
||||
};
|
||||
|
||||
// 新增节点,收集依赖
|
||||
const nodeAddHandler = async (nodes: MComponent[]) => {
|
||||
await collectIdle(nodes, true);
|
||||
|
||||
updateStageNodes(nodes);
|
||||
const nodeAddHandler = (nodes: MComponent[]) => {
|
||||
collectIdle(nodes, true).then(() => {
|
||||
updateStageNodes(nodes);
|
||||
});
|
||||
};
|
||||
|
||||
// 节点更新,收集依赖
|
||||
// 仅当修改到数据源相关的才收集
|
||||
const nodeUpdateHandler = async (
|
||||
data: { newNode: MComponent; oldNode: MComponent; changeRecords?: ChangeRecord[] }[],
|
||||
) => {
|
||||
const nodeUpdateHandler = (data: { newNode: MComponent; oldNode: MComponent; changeRecords?: ChangeRecord[] }[]) => {
|
||||
const needRecollectNodes: MComponent[] = [];
|
||||
const normalNodes: MComponent[] = [];
|
||||
for (const { newNode, oldNode, changeRecords } of data) {
|
||||
@ -424,9 +425,12 @@ export const initServiceEvents = (
|
||||
|
||||
if (needRecollectNodes.length) {
|
||||
// 有数据源依赖,需要等依赖重新收集完才更新stage
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE);
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND);
|
||||
updateStageNodes(needRecollectNodes);
|
||||
const handler = async () => {
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE);
|
||||
await collectIdle(needRecollectNodes, true, DepTargetType.DATA_SOURCE_COND);
|
||||
updateStageNodes(needRecollectNodes);
|
||||
};
|
||||
handler();
|
||||
} else {
|
||||
updateStageNodes(normalNodes);
|
||||
// 在上面判断是否需要收集数据源依赖中已经更新stage
|
||||
@ -443,9 +447,10 @@ export const initServiceEvents = (
|
||||
};
|
||||
|
||||
// 由于历史记录变化是更新整个page,所以历史记录变化时,需要重新收集依赖
|
||||
const historyChangeHandler = async (page: MPage | MPageFragment) => {
|
||||
await collectIdle([page], true);
|
||||
updateStageNode(page);
|
||||
const historyChangeHandler = (page: MPage | MPageFragment) => {
|
||||
collectIdle([page], true).then(() => {
|
||||
updateStageNode(page);
|
||||
});
|
||||
};
|
||||
|
||||
editorService.on('history-change', historyChangeHandler);
|
||||
@ -454,27 +459,28 @@ export const initServiceEvents = (
|
||||
editorService.on('remove', nodeRemoveHandler);
|
||||
editorService.on('update', nodeUpdateHandler);
|
||||
|
||||
const dataSourceAddHandler = async (config: DataSourceSchema) => {
|
||||
initDataSourceDepTarget(config);
|
||||
const app = await getTMagicApp();
|
||||
const dataSourceAddHandler = (config: DataSourceSchema) => {
|
||||
const handler = async () => {
|
||||
initDataSourceDepTarget(config);
|
||||
const app = await getTMagicApp();
|
||||
|
||||
if (!app?.dataSourceManager) {
|
||||
return;
|
||||
}
|
||||
if (!app?.dataSourceManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
app.dataSourceManager.addDataSource(config);
|
||||
app.dataSourceManager.addDataSource(config);
|
||||
|
||||
const newDs = app.dataSourceManager.get(config.id);
|
||||
const newDs = app.dataSourceManager.get(config.id);
|
||||
|
||||
if (newDs) {
|
||||
app.dataSourceManager.init(newDs);
|
||||
}
|
||||
if (newDs) {
|
||||
app.dataSourceManager.init(newDs);
|
||||
}
|
||||
};
|
||||
|
||||
handler();
|
||||
};
|
||||
|
||||
const dataSourceUpdateHandler = async (
|
||||
config: DataSourceSchema,
|
||||
{ changeRecords }: { changeRecords: ChangeRecord[] },
|
||||
) => {
|
||||
const dataSourceUpdateHandler = (config: DataSourceSchema, { changeRecords }: { changeRecords: ChangeRecord[] }) => {
|
||||
const updateDsData = async () => {
|
||||
const app = await getTMagicApp();
|
||||
|
||||
@ -565,29 +571,33 @@ export const initServiceEvents = (
|
||||
depService.removeTarget(id, DepTargetType.DATA_SOURCE_METHOD);
|
||||
};
|
||||
|
||||
const dataSourceRemoveHandler = async (id: string) => {
|
||||
const dataSourceRemoveHandler = (id: string) => {
|
||||
const root = editorService.get('root');
|
||||
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodeIds = Object.keys(root.dataSourceDeps?.[id] || {});
|
||||
const nodes = getNodes(nodeIds, root.items);
|
||||
const handler = async () => {
|
||||
const nodeIds = Object.keys(root.dataSourceDeps?.[id] || {});
|
||||
const nodes = getNodes(nodeIds, root.items);
|
||||
|
||||
await Promise.all([
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_COND),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_METHOD),
|
||||
]);
|
||||
await Promise.all([
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_COND),
|
||||
collectIdle(nodes, false, DepTargetType.DATA_SOURCE_METHOD),
|
||||
]);
|
||||
|
||||
updateDataSourceSchema();
|
||||
updateDataSourceSchema();
|
||||
|
||||
const app = await getTMagicApp();
|
||||
app?.dataSourceManager?.removeDataSource(id);
|
||||
const app = await getTMagicApp();
|
||||
app?.dataSourceManager?.removeDataSource(id);
|
||||
|
||||
updateStageNodes(nodes);
|
||||
removeDataSourceTarget(id);
|
||||
updateStageNodes(nodes);
|
||||
removeDataSourceTarget(id);
|
||||
};
|
||||
|
||||
handler();
|
||||
};
|
||||
|
||||
dataSourceService.on('add', dataSourceAddHandler);
|
||||
|
@ -91,7 +91,7 @@ defineOptions({
|
||||
defineProps<{
|
||||
disabledPageFragment: boolean;
|
||||
pageBarSortOptions?: PageBarSortOptions;
|
||||
pageFilterFunction?: (page: MPage | MPageFragment, keyword: string) => boolean;
|
||||
pageFilterFunction?: (_page: MPage | MPageFragment, _keyword: string) => boolean;
|
||||
}>();
|
||||
|
||||
const codeOptions = inject('codeOptions', {});
|
||||
|
@ -69,7 +69,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
|
||||
type: 'button',
|
||||
className: 'delete',
|
||||
icon: markRaw(Delete),
|
||||
tooltip: `刪除(Delete)`,
|
||||
tooltip: '刪除(Delete)',
|
||||
disabled: () => editorService.get('node')?.type === NodeType.PAGE,
|
||||
handler: () => {
|
||||
const node = editorService.get('node');
|
||||
|
@ -91,7 +91,7 @@ const props = withDefaults(
|
||||
defineProps<{
|
||||
disabledPageFragment: boolean;
|
||||
pageBarSortOptions?: PageBarSortOptions;
|
||||
filterFunction?: (page: MPage | MPageFragment, keyword: string) => boolean;
|
||||
filterFunction?: (_page: MPage | MPageFragment, _keyword: string) => boolean;
|
||||
}>(),
|
||||
{
|
||||
filterFunction: (page, keyword) => page.name?.includes(keyword) || `${page.id}`.includes(keyword),
|
||||
|
@ -56,7 +56,7 @@ import { useServices } from '@editor/hooks/use-services';
|
||||
import CodeEditor from '../CodeEditor.vue';
|
||||
|
||||
defineSlots<{
|
||||
'props-form-panel-header'(props: {}): any;
|
||||
'props-form-panel-header'(_props: {}): any;
|
||||
}>();
|
||||
|
||||
defineOptions({
|
||||
@ -70,7 +70,7 @@ const props = defineProps<{
|
||||
labelWidth?: string;
|
||||
codeValueKey?: string;
|
||||
labelPosition?: string;
|
||||
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -82,7 +82,7 @@ defineOptions({
|
||||
|
||||
defineProps<{
|
||||
disabledShowSrc?: boolean;
|
||||
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -80,7 +80,7 @@ const collapseValue = computed(() =>
|
||||
.map((x, i) => `${i}`),
|
||||
);
|
||||
|
||||
let timeout: NodeJS.Timeout | undefined;
|
||||
let timeout: ReturnType<typeof setTimeout> | undefined;
|
||||
let clientX: number;
|
||||
let clientY: number;
|
||||
|
||||
|
@ -55,7 +55,7 @@ defineOptions({
|
||||
const props = defineProps<{
|
||||
indent?: number;
|
||||
nextLevelIndentIncrement?: number;
|
||||
customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
|
||||
customError?: (_id: Id, _errorType: CodeDeleteErrorType) => any;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -79,7 +79,7 @@ defineOptions({
|
||||
const props = defineProps<{
|
||||
indent?: number;
|
||||
nextLevelIndentIncrement?: number;
|
||||
customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
|
||||
customError?: (_id: Id, _errorType: CodeDeleteErrorType) => any;
|
||||
customContentMenu: CustomContentMenuFunction;
|
||||
}>();
|
||||
|
||||
|
@ -149,7 +149,7 @@ watch(zoom, (zoom) => {
|
||||
stage.setZoom(zoom);
|
||||
});
|
||||
|
||||
let timeoutId: NodeJS.Timeout | null = null;
|
||||
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
||||
watch(page, (page) => {
|
||||
if (runtime && page) {
|
||||
editorService.set('stageLoading', true);
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/no-misused-promises */
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
|
@ -1088,10 +1088,11 @@ class Editor extends BaseService {
|
||||
this.isHistoryStateChange = true;
|
||||
await this.update(value.data);
|
||||
this.set('modifiedNodeIds', value.modifiedNodeIds);
|
||||
setTimeout(async () => {
|
||||
setTimeout(() => {
|
||||
if (!value.nodeId) return;
|
||||
await this.select(value.nodeId);
|
||||
this.get('stage')?.select(value.nodeId);
|
||||
this.select(value.nodeId).then(() => {
|
||||
this.get('stage')?.select(value.nodeId);
|
||||
});
|
||||
}, 0);
|
||||
this.emit('history-change', value.data);
|
||||
}
|
||||
|
@ -65,6 +65,15 @@ import type { StageOverlayService } from './services/stageOverlay';
|
||||
import type { StorageService } from './services/storage';
|
||||
import type { UiService } from './services/ui';
|
||||
import type { UndoRedo } from './utils/undo-redo';
|
||||
|
||||
export type EditorSlots = FrameworkSlots &
|
||||
WorkspaceSlots &
|
||||
SidebarSlots &
|
||||
PropsPanelSlots & {
|
||||
workspace(props: { editorService: EditorService }): any;
|
||||
'workspace-content'(props: { editorService: EditorService }): any;
|
||||
};
|
||||
|
||||
export interface FrameworkSlots {
|
||||
header(props: {}): any;
|
||||
nav(props: {}): any;
|
||||
|
@ -179,13 +179,15 @@ export const fillConfig = (config: FormConfig = [], labelWidth = '80px'): FormCo
|
||||
append: {
|
||||
type: 'button',
|
||||
text: '复制',
|
||||
handler: async (vm, { model }) => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(`${model.id}`);
|
||||
tMagicMessage.success('已复制');
|
||||
} catch (err) {
|
||||
tMagicMessage.error('复制失败');
|
||||
}
|
||||
handler: (vm, { model }) => {
|
||||
navigator.clipboard
|
||||
.writeText(`${model.id}`)
|
||||
.then(() => {
|
||||
tMagicMessage.success('已复制');
|
||||
})
|
||||
.catch(() => {
|
||||
tMagicMessage.error('复制失败');
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -63,7 +63,7 @@ const props = withDefaults(
|
||||
keyProp?: string;
|
||||
popperClass?: string;
|
||||
preventSubmitDefault?: boolean;
|
||||
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
||||
}>(),
|
||||
{
|
||||
config: () => [],
|
||||
@ -101,7 +101,7 @@ const formState: FormState = reactive<FormState>({
|
||||
parentValues: props.parentValues,
|
||||
values,
|
||||
lastValuesProcessed,
|
||||
$emit: emit as (event: string, ...args: any[]) => void,
|
||||
$emit: emit as (_event: string, ..._args: any[]) => void,
|
||||
fields,
|
||||
setField: (prop: string, field: any) => fields.set(prop, field),
|
||||
getField: (prop: string) => fields.get(prop),
|
||||
|
@ -82,7 +82,7 @@ withDefaults(
|
||||
labelPosition?: string;
|
||||
preventSubmitDefault?: boolean;
|
||||
/** 关闭前的回调,会暂停 Drawer 的关闭; done 是个 function type 接受一个 boolean 参数, 执行 done 使用 true 参数或不提供参数将会终止关闭 */
|
||||
beforeClose?: (done: (cancel?: boolean) => void) => void;
|
||||
beforeClose?: (_done: (_cancel?: boolean) => void) => void;
|
||||
}>(),
|
||||
{
|
||||
closeOnPressEscape: true,
|
||||
|
@ -449,7 +449,6 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD
|
||||
valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!;
|
||||
|
||||
// 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
delete eventData.modifyKey;
|
||||
} else if (isValidName() && props.model !== value && (v !== value || props.model[name.value] !== value)) {
|
||||
// field内容下包含field-link时,model===value, 这里避免循环引用
|
||||
|
@ -273,22 +273,18 @@ const isFullscreen = ref(false);
|
||||
|
||||
const modelName = computed(() => props.name || props.config.name || '');
|
||||
|
||||
const data = computed(() =>
|
||||
props.config.pagination
|
||||
? (props.model[modelName.value] || []).filter(
|
||||
(item: any, index: number) =>
|
||||
index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
|
||||
)
|
||||
: props.model[modelName.value],
|
||||
);
|
||||
const getDataByPage = (data: any[] = []) =>
|
||||
data.filter(
|
||||
(item: any, index: number) =>
|
||||
index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
|
||||
);
|
||||
|
||||
const pageinationData = computed(() => getDataByPage(props.model[modelName.value]));
|
||||
|
||||
const data = computed(() => (props.config.pagination ? pageinationData.value : props.model[modelName.value]));
|
||||
|
||||
const lastData = computed(() =>
|
||||
props.config.pagination
|
||||
? (props.lastValues[modelName.value] || []).filter(
|
||||
(item: any, index: number) =>
|
||||
index >= pagecontext.value * pagesize.value && index + 1 <= (pagecontext.value + 1) * pagesize.value,
|
||||
)
|
||||
: props.lastValues[modelName.value] || [],
|
||||
props.config.pagination ? getDataByPage(props.lastValues[modelName.value]) : props.lastValues[modelName.value] || [],
|
||||
);
|
||||
|
||||
const sortChange = ({ prop, order }: SortProp) => {
|
||||
|
@ -41,21 +41,21 @@
|
||||
config.dynamic
|
||||
? (name ? model[name] : model)[tabIndex]
|
||||
: tab.name
|
||||
? (name ? model[name] : model)[tab.name]
|
||||
: name
|
||||
? model[name]
|
||||
: model
|
||||
? (name ? model[name] : model)[tab.name]
|
||||
: name
|
||||
? model[name]
|
||||
: model
|
||||
"
|
||||
:last-values="
|
||||
isEmpty(lastValues)
|
||||
? {}
|
||||
: config.dynamic
|
||||
? (name ? lastValues[name] : lastValues)[tabIndex]
|
||||
: tab.name
|
||||
? (name ? lastValues[name] : lastValues)[tab.name]
|
||||
: name
|
||||
? lastValues[name]
|
||||
: lastValues
|
||||
? (name ? lastValues[name] : lastValues)[tabIndex]
|
||||
: tab.name
|
||||
? (name ? lastValues[name] : lastValues)[tab.name]
|
||||
: name
|
||||
? lastValues[name]
|
||||
: lastValues
|
||||
"
|
||||
:is-compare="isCompare"
|
||||
:prop="config.dynamic ? `${prop}${prop ? '.' : ''}${String(tabIndex)}` : prop"
|
||||
|
@ -13,7 +13,6 @@ defineOptions({
|
||||
const props = defineProps<FieldProps<DisplayConfig>>();
|
||||
|
||||
if (props.config.initValue && props.model) {
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
props.model[props.name] = props.config.initValue;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
>
|
||||
<template v-if="config.group">
|
||||
<component
|
||||
v-for="(group, index) in (options as SelectGroupOption[])"
|
||||
v-for="(group, index) in options as SelectGroupOption[]"
|
||||
:key="index"
|
||||
:is="optionGroupComponent?.component || 'el-option-group'"
|
||||
v-bind="
|
||||
@ -55,7 +55,7 @@
|
||||
</template>
|
||||
<template v-else>
|
||||
<component
|
||||
v-for="option in (options as SelectOption[])"
|
||||
v-for="option in options as SelectOption[]"
|
||||
class="tmagic-design-option"
|
||||
:key="config.valueKey ? option.value[config.valueKey] : option.value"
|
||||
:is="optionComponent?.component || 'el-option'"
|
||||
|
@ -31,7 +31,6 @@ const emit = defineEmits(['change']);
|
||||
|
||||
useAddField(props.prop);
|
||||
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
const { names } = props.config;
|
||||
const value = ref<(Date | undefined)[] | null>([]);
|
||||
|
||||
|
@ -101,7 +101,6 @@ export default {
|
||||
install(app: App, opt: FormInstallOptions = {}) {
|
||||
const option = Object.assign(defaultInstallOpt, opt);
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
app.config.globalProperties.$MAGIC_FORM = option;
|
||||
setConfig(option);
|
||||
|
||||
|
@ -196,6 +196,7 @@ export interface OnChangeHandlerData {
|
||||
config: any;
|
||||
prop: string;
|
||||
changeRecords: ChangeRecord[];
|
||||
setModel: (prop: string, value: any) => void;
|
||||
}
|
||||
|
||||
export type OnChangeHandler = (mForm: FormState | undefined, value: any, data: OnChangeHandlerData) => any;
|
||||
|
@ -16,7 +16,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { toRaw } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
|
@ -92,20 +92,24 @@ export default class ActionManager extends EventEmitter {
|
||||
private disabledMultiSelect = false;
|
||||
private config: ActionManagerConfig;
|
||||
|
||||
private mouseMoveHandler = throttle(async (event: MouseEvent): Promise<void> => {
|
||||
if ((event.target as HTMLDivElement)?.classList?.contains('moveable-direction')) {
|
||||
return;
|
||||
}
|
||||
private mouseMoveHandler = throttle((event: MouseEvent): void => {
|
||||
const handler = async () => {
|
||||
if ((event.target as HTMLDivElement)?.classList?.contains('moveable-direction')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = await this.getElementFromPoint(event);
|
||||
const id = getIdFromEl()(el);
|
||||
if (!id) {
|
||||
this.clearHighlight();
|
||||
return;
|
||||
}
|
||||
const el = await this.getElementFromPoint(event);
|
||||
const id = getIdFromEl()(el);
|
||||
if (!id) {
|
||||
this.clearHighlight();
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('mousemove', event);
|
||||
this.highlight(id);
|
||||
this.emit('mousemove', event);
|
||||
this.highlight(id);
|
||||
};
|
||||
|
||||
handler();
|
||||
}, throttleTime);
|
||||
|
||||
constructor(config: ActionManagerConfig) {
|
||||
@ -299,6 +303,7 @@ export default class ActionManager extends EventEmitter {
|
||||
el = this.getTargetElement(id);
|
||||
} catch (error) {
|
||||
this.clearHighlight();
|
||||
console.warn('getTargetElement error:', error);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -606,29 +611,33 @@ export default class ActionManager extends EventEmitter {
|
||||
/**
|
||||
* 在down事件中集中cpu处理画布中选中操作渲染,在up事件中再通知外面的编辑器更新
|
||||
*/
|
||||
private mouseDownHandler = async (event: MouseEvent): Promise<void> => {
|
||||
this.clearHighlight();
|
||||
event.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
private mouseDownHandler = (event: MouseEvent): void => {
|
||||
const handler = async () => {
|
||||
this.clearHighlight();
|
||||
event.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
|
||||
if (this.isStopTriggerSelect(event)) return;
|
||||
if (this.isStopTriggerSelect(event)) return;
|
||||
|
||||
// 点击状态下不触发高亮事件
|
||||
this.container.removeEventListener('mousemove', this.mouseMoveHandler);
|
||||
// 点击状态下不触发高亮事件
|
||||
this.container.removeEventListener('mousemove', this.mouseMoveHandler);
|
||||
|
||||
// 判断触发多选还是单选
|
||||
if (this.isMultiSelectStatus) {
|
||||
await this.beforeMultiSelect(event);
|
||||
if (this.selectedElList.length > 0) {
|
||||
this.emit('before-multi-select', this.selectedElList);
|
||||
// 判断触发多选还是单选
|
||||
if (this.isMultiSelectStatus) {
|
||||
await this.beforeMultiSelect(event);
|
||||
if (this.selectedElList.length > 0) {
|
||||
this.emit('before-multi-select', this.selectedElList);
|
||||
}
|
||||
} else {
|
||||
const el = await this.getElementFromPoint(event);
|
||||
if (!el) return;
|
||||
this.emit('before-select', el, event);
|
||||
}
|
||||
} else {
|
||||
const el = await this.getElementFromPoint(event);
|
||||
if (!el) return;
|
||||
this.emit('before-select', el, event);
|
||||
}
|
||||
|
||||
getDocument().addEventListener('mouseup', this.mouseUpHandler);
|
||||
getDocument().addEventListener('mouseup', this.mouseUpHandler);
|
||||
};
|
||||
|
||||
handler();
|
||||
};
|
||||
|
||||
private isStopTriggerSelect(event: MouseEvent): boolean {
|
||||
|
@ -285,13 +285,18 @@ export default class DragResizeHelper {
|
||||
getIdFromEl()(ev.target)?.startsWith(DRAG_EL_ID_PREFIX) && getIdFromEl()(ev.target)?.endsWith(frameItem.id),
|
||||
);
|
||||
if (!frameSnapShot) return;
|
||||
const targeEl = this.targetList.find(
|
||||
(targetItem) =>
|
||||
getIdFromEl()(ev.target)?.startsWith(DRAG_EL_ID_PREFIX) &&
|
||||
getIdFromEl()(targetItem) &&
|
||||
getIdFromEl()(ev.target)?.endsWith(getIdFromEl()(targetItem)!),
|
||||
);
|
||||
|
||||
const findTargetElFuctin = (targetItem: HTMLElement) => {
|
||||
const getId = getIdFromEl();
|
||||
const targetId = getId(ev.target);
|
||||
const targetItemId = getId(targetItem);
|
||||
return targetId?.startsWith(DRAG_EL_ID_PREFIX) && targetItemId && targetId?.endsWith(targetItemId);
|
||||
};
|
||||
|
||||
const targeEl = this.targetList.find(findTargetElFuctin);
|
||||
|
||||
if (!targeEl) return;
|
||||
|
||||
// 元素与其所属组同时加入多选列表时,只更新父元素
|
||||
const isParentIncluded = this.targetList.find(
|
||||
(targetItem) => getIdFromEl()(targetItem) === getIdFromEl()(targeEl.parentElement),
|
||||
|
@ -16,7 +16,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
import Moveable, { MoveableOptions } from 'moveable';
|
||||
|
||||
import { getIdFromEl } from '@tmagic/core';
|
||||
|
@ -235,22 +235,26 @@ export default class StageRender extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
private iframeLoadHandler = async () => {
|
||||
if (!this.contentWindow?.magic) {
|
||||
this.postTmagicRuntimeReady();
|
||||
}
|
||||
|
||||
if (!this.contentWindow) return;
|
||||
|
||||
if (this.customizedRender) {
|
||||
const el = await this.customizedRender();
|
||||
if (el) {
|
||||
this.contentWindow.document?.body?.appendChild(el);
|
||||
private iframeLoadHandler = () => {
|
||||
const handler = async () => {
|
||||
if (!this.contentWindow?.magic) {
|
||||
this.postTmagicRuntimeReady();
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('onload');
|
||||
if (!this.contentWindow) return;
|
||||
|
||||
injectStyle(this.contentWindow.document, style);
|
||||
if (this.customizedRender) {
|
||||
const el = await this.customizedRender();
|
||||
if (el) {
|
||||
this.contentWindow.document?.body?.appendChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('onload');
|
||||
|
||||
injectStyle(this.contentWindow.document, style);
|
||||
};
|
||||
|
||||
handler();
|
||||
};
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ Object.defineProperties(globalThis.HTMLElement.prototype, {
|
||||
|
||||
const createElement = () => {
|
||||
const el = globalThis.document.createElement('div');
|
||||
el.style.cssText = `width: 100px; height: 100px; position: absolute; left: 100px; top: 100px;`;
|
||||
el.style.cssText = 'width: 100px; height: 100px; position: absolute; left: 100px; top: 100px;';
|
||||
return el;
|
||||
};
|
||||
|
||||
@ -78,7 +78,7 @@ describe('getOffset', () => {
|
||||
});
|
||||
|
||||
test('没有offsetParent, 没有left、top', () => {
|
||||
div.style.cssText = `width: 100px; height: 100px`;
|
||||
div.style.cssText = 'width: 100px; height: 100px';
|
||||
root.appendChild(div);
|
||||
const offset = util.getOffset(div);
|
||||
expect(offset.left).toBe(0);
|
||||
@ -95,7 +95,7 @@ describe('getOffset', () => {
|
||||
|
||||
test('有offsetParent, 没有left、top', () => {
|
||||
const parent = createElement();
|
||||
div.style.cssText = `width: 100px; height: 100px`;
|
||||
div.style.cssText = 'width: 100px; height: 100px';
|
||||
parent.appendChild(div);
|
||||
root.appendChild(parent);
|
||||
|
||||
@ -119,7 +119,7 @@ describe('getAbsolutePosition', () => {
|
||||
|
||||
test('有offsetParent', () => {
|
||||
const parent = createElement();
|
||||
div.style.cssText = `width: 100px; height: 100px`;
|
||||
div.style.cssText = 'width: 100px; height: 100px';
|
||||
parent.appendChild(div);
|
||||
root.appendChild(parent);
|
||||
const offset = util.getAbsolutePosition(div, { left: 100, top: 100 });
|
||||
|
@ -84,7 +84,7 @@ const props = withDefaults(
|
||||
data: any[];
|
||||
columns?: ColumnConfig[];
|
||||
/** 合并行或列的计算方法 */
|
||||
spanMethod?: (data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
||||
spanMethod?: (_data: { row: any; column: any; rowIndex: number; columnIndex: number }) => [number, number];
|
||||
loading?: boolean;
|
||||
/** Table 的最大高度。合法的值为数字或者单位为 px 的高度 */
|
||||
bodyHeight?: string | number;
|
||||
|
@ -25,12 +25,12 @@ export const formatter = (item: ColumnConfig, row: any, data: { index: number })
|
||||
|
||||
if (item.formatter) {
|
||||
if (item.formatter === 'datetime') {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
item.formatter = (value: string) => datetimeFormatter(value);
|
||||
}
|
||||
try {
|
||||
return item.formatter(row[item.prop], row, data);
|
||||
} catch (e) {
|
||||
console.error('Formatter error:', e);
|
||||
return row[item.prop];
|
||||
}
|
||||
} else {
|
||||
|
@ -40,6 +40,7 @@ export * from './dom';
|
||||
// for typeof global checks without @types/node
|
||||
declare let global: {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
let _globalThis: any;
|
||||
export const getGlobalThis = (): any =>
|
||||
_globalThis ||
|
||||
@ -47,12 +48,12 @@ export const getGlobalThis = (): any =>
|
||||
typeof globalThis !== 'undefined'
|
||||
? globalThis
|
||||
: typeof self !== 'undefined'
|
||||
? self
|
||||
: typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof global !== 'undefined'
|
||||
? global
|
||||
: {});
|
||||
? self
|
||||
: typeof window !== 'undefined'
|
||||
? window
|
||||
: typeof global !== 'undefined'
|
||||
? global
|
||||
: {});
|
||||
|
||||
export const sleep = (ms: number): Promise<void> =>
|
||||
new Promise((resolve) => {
|
||||
@ -410,6 +411,7 @@ export const getDefaultValueFromFields = (fields: DataSchema[]) => {
|
||||
data[field.name] = JSON.parse(field.defaultValue);
|
||||
} catch (e) {
|
||||
data[field.name] = defaultValue.object;
|
||||
console.warn('defaultValue 解析失败', field.defaultValue, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -172,8 +172,8 @@ describe('filterXSS', () => {
|
||||
expect(value).toBe('<div></div>');
|
||||
});
|
||||
|
||||
test(`'"`, () => {
|
||||
const value = util.filterXSS(`'div'"span"`);
|
||||
test('\'"', () => {
|
||||
const value = util.filterXSS('\'div\'"span"');
|
||||
expect(value).toBe(''div'"span"');
|
||||
});
|
||||
});
|
||||
|
1104
pnpm-lock.yaml
generated
1104
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -3,4 +3,6 @@ packages:
|
||||
- 'playground'
|
||||
- 'runtime/*'
|
||||
- 'vue-components/*'
|
||||
- 'react-components/*'
|
||||
- 'react-components/*'
|
||||
- 'eslint-config'
|
||||
|
@ -67,7 +67,7 @@ const IteratorContainer: React.FC<IteratorContainerProps> = ({
|
||||
const configs: IteratorItemSchema[] = iteratorData.map((itemData: any, index: number) => {
|
||||
const condResult =
|
||||
app?.platform !== 'editor'
|
||||
? app?.dataSourceManager?.compliedIteratorItemConds(itemData, itemConfig, dsField) ?? true
|
||||
? (app?.dataSourceManager?.compliedIteratorItemConds(itemData, itemConfig, dsField) ?? true)
|
||||
: true;
|
||||
|
||||
const newItems = app?.dataSourceManager?.compliedIteratorItems(itemData, items, dsField) ?? items;
|
||||
|
@ -22,7 +22,7 @@ const runtimes = readdirSync('temp/runtime');
|
||||
const targets = process.env.TARGETS ? process.env.TARGETS.split(',') : null;
|
||||
const targetPackages = targets ? packages.filter((pkg) => targets.includes(pkg)) : packages;
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
function rollupConfig(pkg, base) {
|
||||
return {
|
||||
@ -34,9 +34,9 @@ function rollupConfig(pkg, base) {
|
||||
plugins: [
|
||||
alias({
|
||||
entries: [
|
||||
{ find: /^@form/, replacement: path.join(__dirname, `./temp/packages/form/src`) },
|
||||
{ find: /^@editor/, replacement: path.join(__dirname, `./temp/packages/editor/src`) },
|
||||
{ find: /^@data-source/, replacement: path.join(__dirname, `./temp/packages/data-source/src`) },
|
||||
{ find: /^@form/, replacement: path.join(dirname, './temp/packages/form/src') },
|
||||
{ find: /^@editor/, replacement: path.join(dirname, './temp/packages/editor/src') },
|
||||
{ find: /^@data-source/, replacement: path.join(dirname, './temp/packages/data-source/src') },
|
||||
],
|
||||
}),
|
||||
dts(),
|
||||
@ -57,5 +57,5 @@ export default [
|
||||
];
|
||||
|
||||
function removeScss(path) {
|
||||
writeFileSync(path, readFileSync(path).toString().replace(`import './theme/index.scss';`, ''));
|
||||
writeFileSync(path, readFileSync(path).toString().replace("import './theme/index.scss';", ''));
|
||||
}
|
||||
|
@ -37,13 +37,15 @@ export interface UseAppOptions<T extends MNodeInstance = MNodeInstance> {
|
||||
};
|
||||
}
|
||||
|
||||
export const useNode = (
|
||||
export const useNode = <T extends TMagicNode = TMagicNode>(
|
||||
props: Pick<UseAppOptions, 'config' | 'iteratorContainerId' | 'iteratorIndex'>,
|
||||
app = useContext(AppContent),
|
||||
) =>
|
||||
isDslNode(props.config) && props.config.id
|
||||
? app?.getNode(props.config.id, props.iteratorContainerId, props.iteratorIndex)
|
||||
: undefined;
|
||||
): T | undefined => {
|
||||
if (isDslNode(props.config) && props.config.id) {
|
||||
app?.getNode(props.config.id, props.iteratorContainerId, props.iteratorIndex);
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
export const registerNodeHooks = (node?: TMagicNode, methods: Methods = {}) => {
|
||||
if (!node) {
|
||||
|
@ -48,6 +48,7 @@ const getLocalConfig = (): MApp[] => {
|
||||
// eslint-disable-next-line no-eval
|
||||
return [eval(`(${configStr})`)];
|
||||
} catch (err) {
|
||||
console.error('Error parsing localStorage magicDSL:', err);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
@ -33,13 +33,15 @@ interface UseAppOptions<T extends MNodeInstance = MNodeInstance> {
|
||||
methods?: Methods;
|
||||
}
|
||||
|
||||
export const useNode = (
|
||||
export const useNode = <T extends TMagicNode = TMagicNode>(
|
||||
props: Pick<UseAppOptions, 'config' | 'iteratorContainerId' | 'iteratorIndex'>,
|
||||
app = inject<TMagicApp>('app'),
|
||||
) =>
|
||||
isDslNode(props.config) && props.config.id
|
||||
? app?.getNode(props.config.id, props.iteratorContainerId, props.iteratorIndex)
|
||||
: undefined;
|
||||
): T | undefined => {
|
||||
if (isDslNode(props.config) && props.config.id) {
|
||||
return app?.getNode(props.config.id, props.iteratorContainerId, props.iteratorIndex);
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
export const registerNodeHooks = (node?: TMagicNode, methods: Methods = {}) => {
|
||||
if (!node) {
|
||||
|
@ -8,7 +8,7 @@ export * from './hooks/use-app';
|
||||
export * from './hooks/use-component-status';
|
||||
export { useComponent } from './hooks/use-component';
|
||||
|
||||
export interface userRenderFunctionOptions {
|
||||
export interface UserRenderFunctionOptions {
|
||||
h: typeof h;
|
||||
type: Parameters<typeof h>[0];
|
||||
props?: {
|
||||
@ -26,4 +26,4 @@ export interface userRenderFunctionOptions {
|
||||
directives?: { name: string; value: any; modifiers: any }[];
|
||||
}
|
||||
|
||||
export type UserRenderFunction = (options: userRenderFunctionOptions) => any;
|
||||
export type UserRenderFunction = (options: UserRenderFunctionOptions) => any;
|
||||
|
@ -19,7 +19,7 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
import TMagicApp, { DataSourceManager, DeepObservedData, getUrlParam, registerDataSourceOnDemand } from '@tmagic/core';
|
||||
import type { userRenderFunctionOptions } from '@tmagic/vue-runtime-help';
|
||||
import type { UserRenderFunctionOptions } from '@tmagic/vue-runtime-help';
|
||||
|
||||
import asyncDataSources from '../.tmagic/async-datasource-entry';
|
||||
import components from '../.tmagic/comp-entry';
|
||||
@ -65,7 +65,7 @@ registerDataSourceOnDemand(dsl, asyncDataSources).then((dataSources) => {
|
||||
const vueApp = new Vue({
|
||||
provide: {
|
||||
app,
|
||||
userRender: ({ h, type, props, attrs, style, className }: userRenderFunctionOptions) =>
|
||||
userRender: ({ h, type, props, attrs, style, className }: UserRenderFunctionOptions) =>
|
||||
// class作为保留字符,android 4.4以下不能直接使用, 需要加引号
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
h(type, { props, attrs, style, 'class': className }),
|
||||
|
@ -25,6 +25,7 @@ export const getLocalConfig = (): MApp[] => {
|
||||
// eslint-disable-next-line no-eval
|
||||
return [eval(`(${configStr})`)];
|
||||
} catch (err) {
|
||||
console.error('Error parsing localStorage magicDSL:', err);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
@ -19,7 +19,7 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
import TMagicApp, { DataSourceManager, DeepObservedData } from '@tmagic/core';
|
||||
import type { userRenderFunctionOptions } from '@tmagic/vue-runtime-help';
|
||||
import type { UserRenderFunctionOptions } from '@tmagic/vue-runtime-help';
|
||||
|
||||
import App from './App.vue';
|
||||
|
||||
@ -62,10 +62,8 @@ Promise.all([
|
||||
render: (h) => h(App),
|
||||
provide: {
|
||||
app,
|
||||
userRender: ({ h, type, props, attrs, style, className }: userRenderFunctionOptions) =>
|
||||
// class作为保留字符,android 4.4以下不能直接使用, 需要加引号
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
h(type, { props, attrs, style, 'class': className }),
|
||||
userRender: ({ h, type, props, attrs, style, className }: UserRenderFunctionOptions) =>
|
||||
h(type, { props, attrs, style, class: className }),
|
||||
},
|
||||
el: '#app',
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component :is="pageComponent" :config="(pageConfig as MPage)"></component>
|
||||
<component :is="pageComponent" :config="pageConfig as MPage"></component>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -25,6 +25,7 @@ export const getLocalConfig = (): MApp[] => {
|
||||
// eslint-disable-next-line no-eval
|
||||
return [eval(`(${configStr})`)];
|
||||
} catch (err) {
|
||||
console.error('Error parsing localStorage magicDSL:', err);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
@ -12,9 +12,9 @@ const args = minimist(process.argv.slice(2));
|
||||
|
||||
const toPascalCase = (str) => str.replace(/(^\w|-\w)/g, (text) => text.replace(/-/, '').toUpperCase());
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const packagesDir = path.resolve(__dirname, '../packages');
|
||||
const runtimeDir = path.resolve(__dirname, '../runtime');
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const packagesDir = path.resolve(dirname, '../packages');
|
||||
const runtimeDir = path.resolve(dirname, '../runtime');
|
||||
|
||||
if (args.package) {
|
||||
const pkgRoot = path.resolve(packagesDir, args.package);
|
||||
|
@ -23,7 +23,7 @@ let versionUpdated = false;
|
||||
|
||||
const { prompt } = enquirer;
|
||||
const currentVersion = createRequire(import.meta.url)('../package.json').version;
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const args = minimist(process.argv.slice(2), {
|
||||
alias: {
|
||||
skipBuild: 'skip-build',
|
||||
@ -42,12 +42,13 @@ const { skipBuild } = args;
|
||||
const skipPrompts = args.skipPrompts || args.canary;
|
||||
const skipGit = args.skipGit || args.canary;
|
||||
|
||||
const packages = fs.readdirSync(path.resolve(__dirname, '../packages')).filter((p) => {
|
||||
const pkgRoot = path.resolve(__dirname, '../packages', p);
|
||||
const packages = fs.readdirSync(path.resolve(dirname, '../packages')).filter((p) => {
|
||||
const pkgRoot = path.resolve(dirname, '../packages', p);
|
||||
if (fs.statSync(pkgRoot).isDirectory()) {
|
||||
const pkg = JSON.parse(fs.readFileSync(path.resolve(pkgRoot, 'package.json'), 'utf-8'));
|
||||
return !pkg.private;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const keepThePackageName = (/** @type {string} */ pkgName) => pkgName;
|
||||
@ -77,14 +78,14 @@ const dryRun = async (
|
||||
const runIfNotDry = isDryRun ? dryRun : run;
|
||||
const getPkgRoot = (/** @type {string} */ pkg) => path.resolve(__dirname, `../packages/${pkg}`);
|
||||
const getRunTimeRoot = (pkg) => path.resolve(__dirname, `../runtime/${pkg}`);
|
||||
const getPlayground = () => path.resolve(__dirname, `../playground`);
|
||||
const getPlayground = () => path.resolve(__dirname, '../playground');
|
||||
const step = (/** @type {string} */ msg) => console.log(pico.cyan(msg));
|
||||
|
||||
async function main() {
|
||||
if (!(await isInSyncWithRemote())) {
|
||||
return;
|
||||
}
|
||||
console.log(`${pico.green(`✓`)} commit is up-to-date with remote.\n`);
|
||||
console.log(`${pico.green('✓')} commit is up-to-date with remote.\n`);
|
||||
|
||||
let targetVersion = args._[0];
|
||||
|
||||
@ -141,7 +142,7 @@ async function main() {
|
||||
const { yes: promptSkipTests } = await prompt({
|
||||
type: 'confirm',
|
||||
name: 'yes',
|
||||
message: `CI for this commit passed. Skip local tests?`,
|
||||
message: 'CI for this commit passed. Skip local tests?',
|
||||
});
|
||||
|
||||
skipTests = promptSkipTests;
|
||||
@ -153,7 +154,7 @@ async function main() {
|
||||
if (!isDryRun) {
|
||||
await run('pnpm', ['run', 'test', '--run']);
|
||||
} else {
|
||||
console.log(`Skipped (dry run)`);
|
||||
console.log('Skipped (dry run)');
|
||||
}
|
||||
} else {
|
||||
step('Tests skipped.');
|
||||
@ -169,19 +170,19 @@ async function main() {
|
||||
if (!skipBuild && !isDryRun) {
|
||||
await run('pnpm', ['run', 'build']);
|
||||
} else {
|
||||
console.log(`(skipped)`);
|
||||
console.log('(skipped)');
|
||||
}
|
||||
|
||||
// generate changelog
|
||||
step('\nGenerating changelog...');
|
||||
await run(`pnpm`, ['run', 'changelog']);
|
||||
await run('pnpm', ['run', 'changelog']);
|
||||
|
||||
if (!skipPrompts) {
|
||||
/** @type {{ yes: boolean }} */
|
||||
const { yes: changelogOk } = await prompt({
|
||||
type: 'confirm',
|
||||
name: 'yes',
|
||||
message: `Changelog generated. Does it look good?`,
|
||||
message: 'Changelog generated. Does it look good?',
|
||||
});
|
||||
|
||||
if (!changelogOk) {
|
||||
@ -223,7 +224,7 @@ async function main() {
|
||||
|
||||
// update pnpm-lock.yaml
|
||||
step('\nUpdating lockfile...');
|
||||
await run(`pnpm`, ['install', '--prefer-offline']);
|
||||
await run('pnpm', ['install', '--prefer-offline']);
|
||||
|
||||
if (!skipGit) {
|
||||
const { stdout } = await run('git', ['diff'], { stdio: 'pipe' });
|
||||
@ -245,7 +246,7 @@ async function main() {
|
||||
}
|
||||
|
||||
if (isDryRun) {
|
||||
console.log(`\nDry run finished - run git diff to see package changes.`);
|
||||
console.log('\nDry run finished - run git diff to see package changes.');
|
||||
}
|
||||
|
||||
if (skippedPackages.length) {
|
||||
@ -260,8 +261,7 @@ async function getCIResult() {
|
||||
try {
|
||||
const sha = await getSha();
|
||||
const res = await fetch(
|
||||
`https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${sha}` +
|
||||
`&status=success&exclude_pull_requests=true`,
|
||||
`https://api.github.com/repos/vuejs/core/actions/runs?head_sha=${sha}&status=success&exclude_pull_requests=true`,
|
||||
);
|
||||
const data = await res.json();
|
||||
return data.workflow_runs.length > 0;
|
||||
@ -283,7 +283,7 @@ async function isInSyncWithRemote() {
|
||||
const { yes } = await prompt({
|
||||
type: 'confirm',
|
||||
name: 'yes',
|
||||
message: pico.red(`Local HEAD is not up-to-date with remote. Are you sure you want to continue?`),
|
||||
message: pico.red('Local HEAD is not up-to-date with remote. Are you sure you want to continue?'),
|
||||
});
|
||||
return yes;
|
||||
} catch {
|
||||
|
@ -79,7 +79,7 @@ export default defineComponent({
|
||||
return iteratorData.map((itemData: any) => {
|
||||
const condResult =
|
||||
app?.platform !== 'editor'
|
||||
? app?.dataSourceManager?.compliedIteratorItemConds(itemData, itemConfig, dsField) ?? true
|
||||
? (app?.dataSourceManager?.compliedIteratorItemConds(itemData, itemConfig, dsField) ?? true)
|
||||
: true;
|
||||
|
||||
const newItems = app?.dataSourceManager?.compliedIteratorItems(itemData, items, dsField) ?? items;
|
||||
|
Loading…
x
Reference in New Issue
Block a user