Feat provide eslint prettier modify config (#385)

* fix(monaco-eslint): 修复eslint-worker支持问题

* fix(linter): 解决cdn后eslint worker相对路径问题

* fix: 移除多余的包

* feat(controller): eslint、prettier新增配置文件,worker文件打包从主应用改为随着分应用打包

* fix(controller): 修复eslint worker地址

* feat(controller): eslint-linter-browserify 降版本

* build: 去掉define process.env设置为空对象(旧版tinyVue库需要),当前引起eslint-linter-browserify脚本(已经处理过process的包)构建报错,且主应用有nodePollyfill可以处理process场景重复了

* fix(controller): 去掉多余注释和测试代码注释

* fix: 解决代码检视问题, 去掉注释,补充包引用去掉external,去掉多余的新增依赖

* feat: 单页预览格式化统一引用prettierrc文件配置

* fix: 解决子包的js没有打包为入口的问题

* fix(controller): 修复因目录结构改变需要worker打包为相对地址
This commit is contained in:
rhlin 2024-04-15 23:22:10 -07:00 committed by GitHub
parent 259ef69ba3
commit 681a6fa612
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 129 additions and 115 deletions

View File

@ -23,9 +23,6 @@ export default defineConfig({
'@': path.resolve(__dirname, 'src') '@': path.resolve(__dirname, 'src')
} }
}, },
define: {
'process.env': {}
},
plugins: [ plugins: [
vue({ vue({
template: { template: {

View File

@ -20,9 +20,6 @@ export default defineConfig({
plugins: [vue(), vueJsx()], plugins: [vue(), vueJsx()],
publicDir: false, publicDir: false,
resolve: {}, resolve: {},
define: {
'process.env': {}
},
build: { build: {
cssCodeSplit: false, cssCodeSplit: false,
lib: { lib: {

View File

@ -17,6 +17,7 @@ import prettier from 'prettier'
import parserHtml from 'prettier/parser-html' import parserHtml from 'prettier/parser-html'
import parseCss from 'prettier/parser-postcss' import parseCss from 'prettier/parser-postcss'
import parserBabel from 'prettier/parser-babel' import parserBabel from 'prettier/parser-babel'
import prettierConfig from './config-files/prettierrc'
const METHOD_REGEXP = /function.*?\(/ const METHOD_REGEXP = /function.*?\(/
@ -33,10 +34,7 @@ const formatScript = (string) => {
const options = { const options = {
parser: 'babel', parser: 'babel',
plugins: [parserBabel], plugins: [parserBabel],
printWidth: 120, ...prettierConfig
singleQuote: true,
semi: false,
trailingComma: 'none'
} }
try { try {
// 低码中的编辑器大多只会输入js值并不是一个完整的javascript表达式无法格式化因此需要特殊处理预格式化该种情形 // 低码中的编辑器大多只会输入js值并不是一个完整的javascript表达式无法格式化因此需要特殊处理预格式化该种情形
@ -53,21 +51,21 @@ const formatJson = (string) =>
parser: 'json', parser: 'json',
plugins: [parserBabel], plugins: [parserBabel],
trailingComma: 'es5', trailingComma: 'es5',
tabWidth: 2, ...prettierConfig
semi: false,
singleQuote: true
}) })
const formatHtml = (string) => const formatHtml = (string) =>
prettier.format(string, { prettier.format(string, {
parser: 'html', parser: 'html',
plugins: [parserBabel, parserHtml] plugins: [parserBabel, parserHtml],
...prettierConfig
}) })
const formatCss = (string) => const formatCss = (string) =>
prettier.format(string, { prettier.format(string, {
parser: 'css', parser: 'css',
plugins: [parseCss] plugins: [parseCss],
...prettierConfig
}) })
const formatterMap = { const formatterMap = {

View File

@ -0,0 +1,8 @@
import eslintRecommended from '@eslint/js/src/configs/eslint-recommended.js'
export default {
...eslintRecommended.rules,
'no-console': 'error',
'no-debugger': 'error',
'space-before-function-paren': 'off',
'no-use-before-define': 'error'
}

View File

@ -0,0 +1,8 @@
export default {
semi: false,
singleQuote: true,
printWidth: 120,
trailingComma: 'none',
endOfLine: 'auto',
tabWidth: 2
}

View File

@ -1,27 +1,29 @@
/** /**
* Copyright (c) 2023 - present TinyEngine Authors. * Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd. * Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
* *
* Use of this source code is governed by an MIT-style license. * Use of this source code is governed by an MIT-style license.
* *
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
* *
*/ */
import { PROD, BASE_URL } from './environments' import eslintWorkerUrl from './worker-files/eslint.worker?worker&url'
export const initLinter = (editor, monacoInstance, state) => { export const initLinter = (editor, monacoInstance, state) => {
let workerUrl = `${BASE_URL}monaco-linter/eslint.worker.js` let workerUrl = new URL(eslintWorkerUrl, import.meta.url)
// 线上环境,存在 worker 资源跨域的情况 // 线上环境,存在 worker 资源跨域的情况
if (PROD) { if (workerUrl.origin !== location.origin) {
const workerBlob = new Blob([`importScripts('${workerUrl}');`], { type: 'application/javascript' }) const workerBlob = new Blob([`import('${workerUrl}');`], {
type: 'application/javascript'
})
workerUrl = window.URL.createObjectURL(workerBlob) workerUrl = window.URL.createObjectURL(workerBlob)
} }
const worker = new Worker(workerUrl) const worker = new Worker(workerUrl, { type: 'module' })
// 监听 ESLint web worker 的返回 // 监听 ESLint web worker 的返回
worker.onmessage = function (event) { worker.onmessage = function (event) {

View File

@ -0,0 +1,71 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { Linter } from 'eslint-linter-browserify'
import eslintRule from '../config-files/eslint-rule'
const defaultConfig = {
env: {
browser: true,
es6: true
},
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 'latest',
sourceType: 'module'
}
}
const config = {
...defaultConfig,
rules: {
...eslintRule,
// JS 面板中,仅定义 function但可能不使用该方法
'no-unused-vars': 'off',
'no-alert': 'off',
'no-console': 'off'
},
settings: {}
}
// 错误的等级ESLint 与 monaco 的存在差异,做一层映射
const severityMap = {
2: 'Error',
1: 'Warning'
}
const linter = new Linter()
self.addEventListener('message', (event) => {
const { code, version } = event.data
const ruleDefines = linter.getRules()
const errs = linter.verify(code, config)
const markers = errs.map(({ ruleId = '', line, endLine, column, endColumn, message, severity }) => ({
code: {
value: ruleId || '',
target: ruleDefines.get(ruleId)?.meta?.docs?.url || ''
},
startLineNumber: line,
endLineNumber: endLine,
startColumn: column,
endColumn: endColumn,
message: message,
severity: severityMap[severity],
source: 'ESLint'
}))
// ESLint 静态检查结果,发回主线程
self.postMessage({ markers, version })
})

View File

@ -43,6 +43,7 @@
"@opentiny/vue-renderless": "~3.10.0", "@opentiny/vue-renderless": "~3.10.0",
"@vue/shared": "^3.3.4", "@vue/shared": "^3.3.4",
"css-tree": "^2.3.1", "css-tree": "^2.3.1",
"eslint-linter-browserify": "8.57.0",
"prettier": "2.7.1" "prettier": "2.7.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -17,7 +17,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
import { glob } from 'glob' import { glob } from 'glob'
import { fileURLToPath } from 'node:url' import { fileURLToPath } from 'node:url'
const jsEntries = glob.sync('./js/**.js').map((file) => { const jsEntries = glob.sync('./js/**/*.js').map((file) => {
return [file.slice(0, file.length - path.extname(file).length), fileURLToPath(new URL(file, import.meta.url))] return [file.slice(0, file.length - path.extname(file).length), fileURLToPath(new URL(file, import.meta.url))]
}) })
@ -26,8 +26,8 @@ export default defineConfig({
plugins: [vue(), vueJsx()], plugins: [vue(), vueJsx()],
publicDir: false, publicDir: false,
resolve: {}, resolve: {},
base: './',
define: { define: {
'process.env': {},
'import.meta': 'import.meta', 'import.meta': 'import.meta',
'import.meta.env.MODE': 'import.meta.env.MODE', 'import.meta.env.MODE': 'import.meta.env.MODE',
'import.meta.env.PROD': 'import.meta.env.PROD', 'import.meta.env.PROD': 'import.meta.env.PROD',

View File

@ -85,6 +85,7 @@
"@vue/repl": "^2.9.0", "@vue/repl": "^2.9.0",
"@vueuse/core": "^9.6.0", "@vueuse/core": "^9.6.0",
"element-resize-detector": "^1.2.4", "element-resize-detector": "^1.2.4",
"eslint-linter-browserify": "8.57.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"jszip": "^3.10.1", "jszip": "^3.10.1",

View File

@ -1,57 +0,0 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
// importScripts 不支持 esm, 此处使用 umd, 对外暴露的变量名linter需要填写openTiny的cdn地址
importScripts('')
// 根据公司的编码规范内置了 config/rules, 可以进一步定制
const config = {
...self.linter.config,
rules: {
...self.linter.config.rules,
// JS 面板中,仅定义 function但可能不使用该方法
'no-unused-vars': 'off',
'no-alert': 'off',
'no-console': 'off'
},
settings: {}
}
// 错误的等级ESLint 与 monaco 的存在差异,做一层映射
const severityMap = {
2: 'Error',
1: 'Warning'
}
self.addEventListener('message', (event) => {
const { code, version } = event.data
const ruleDefines = self.linter.esLinter.getRules()
const errs = self.linter.esLinter.verify(code, config)
const markers = errs.map(({ ruleId = '', line, endLine, column, endColumn, message, severity }) => ({
code: {
value: ruleId,
target: ruleDefines.get(ruleId)?.meta?.docs?.url
},
startLineNumber: line,
endLineNumber: endLine,
startColumn: column,
endColumn: endColumn,
message: message,
severity: severityMap[severity],
source: 'ESLint'
}))
// ESLint 静态检查结果,发回主线程
self.postMessage({ markers, version })
})

View File

@ -93,9 +93,6 @@ const config = {
] ]
} }
}, },
define: {
'process.env': {}
},
build: { build: {
commonjsOptions: { commonjsOptions: {
transformMixedEsModules: true, transformMixedEsModules: true,

View File

@ -14,6 +14,7 @@ import prettier from 'prettier'
import parserHtml from 'prettier/parser-html' import parserHtml from 'prettier/parser-html'
import parseCss from 'prettier/parser-postcss' import parseCss from 'prettier/parser-postcss'
import parserBabel from 'prettier/parser-babel' import parserBabel from 'prettier/parser-babel'
import prettierCommon from '@opentiny/tiny-engine-controller/js/config-files/prettierrc'
// LOWCODE_TODO: 从本地配置文件获取 // LOWCODE_TODO: 从本地配置文件获取
const basePaths = { const basePaths = {
@ -36,13 +37,6 @@ const FILE_TYPES = {
Store: 'Store' Store: 'Store'
} }
const prettierCommon = {
printWidth: 120,
semi: false,
singleQuote: true,
trailingComma: 'none'
}
function formatScript(string) { function formatScript(string) {
return prettier.format(string, { return prettier.format(string, {
...prettierCommon, ...prettierCommon,

View File

@ -26,6 +26,7 @@
"license": "MIT", "license": "MIT",
"homepage": "https://opentiny.design/tiny-engine", "homepage": "https://opentiny.design/tiny-engine",
"dependencies": { "dependencies": {
"@opentiny/tiny-engine-controller": "workspace:*",
"@opentiny/tiny-engine-builtin-component": "workspace:*", "@opentiny/tiny-engine-builtin-component": "workspace:*",
"@vue/compiler-sfc": "3.2.45", "@vue/compiler-sfc": "3.2.45",
"@vue/shared": "^3.3.4", "@vue/shared": "^3.3.4",

View File

@ -13,6 +13,7 @@
import { capitalize, hyphenate } from '@vue/shared' import { capitalize, hyphenate } from '@vue/shared'
import { tinyIcon as unifyIconName } from '../pre-processor' import { tinyIcon as unifyIconName } from '../pre-processor'
import { TINY_ICON, JS_FUNCTION } from '../constant' import { TINY_ICON, JS_FUNCTION } from '../constant'
import prettierConfig from '@opentiny/tiny-engine-controller/js/config-files/prettierrc'
const getTypeOfSchema = (schema) => schema.componentName const getTypeOfSchema = (schema) => schema.componentName
@ -69,12 +70,7 @@ const lowerFirst = (str) => str[0].toLowerCase() + str.slice(1)
*/ */
const toPascalCase = (input, delimiter = '-') => input.split(delimiter).map(capitalize).join('') const toPascalCase = (input, delimiter = '-') => input.split(delimiter).map(capitalize).join('')
const commonOpts = { const commonOpts = prettierConfig
printWidth: 120,
semi: false,
singleQuote: true,
trailingComma: 'none'
}
const prettierOpts = { const prettierOpts = {
vue: { ...commonOpts, parser: 'vue', htmlWhitespaceSensitivity: 'ignore' }, vue: { ...commonOpts, parser: 'vue', htmlWhitespaceSensitivity: 'ignore' },
js: { ...commonOpts, parser: 'typescript' } js: { ...commonOpts, parser: 'typescript' }

View File

@ -1,14 +1,14 @@
/** /**
* Copyright (c) 2023 - present TinyEngine Authors. * Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd. * Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
* *
* Use of this source code is governed by an MIT-style license. * Use of this source code is governed by an MIT-style license.
* *
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
* *
*/ */
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import path from 'path' import path from 'path'