@egs33/eslint-config 1.13.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,18 +15,20 @@ $ yarn add -D eslint @egs33/eslint-config
15
15
  ## Usage
16
16
  ### for node.js
17
17
  ```javascript
18
- module.exports = {
19
- root: true,
20
- extends: '@egs33',
21
- };
18
+ import node from '@egs33/eslint-config/nodejs.js';
19
+
20
+ export default [
21
+ ...node,
22
+ ];
22
23
  ```
23
24
 
24
25
  ### for browser
25
26
  ```javascript
26
- module.exports = {
27
- root: true,
28
- extends: '@egs33/eslint-config/browser',
29
- };
27
+ import browser from '@egs33/eslint-config/browser.js';
28
+
29
+ export default [
30
+ ...browser,
31
+ ];
30
32
  ```
31
33
 
32
34
  ### for browser and Vue.js SFC
@@ -35,11 +37,12 @@ $ yarn add -D vue-eslint-parser eslint-plugin-vue
35
37
  ```
36
38
 
37
39
  ```javascript
38
- module.exports = {
39
- root: true,
40
- extends: '@egs33/eslint-config/vue3',
41
- parser: 'vue-eslint-parser',
42
- };
40
+ import vue3 from '@egs33/eslint-config/vue3.js';
41
+ import { applyConfig } from '@egs33/eslint-config/util.js';
42
+
43
+ export default [
44
+ ...applyConfig({ files: ['**/*.vue'] }, vue3),
45
+ ];
43
46
  ```
44
47
  ### for node.js (typescript)
45
48
  ```bash
@@ -47,17 +50,10 @@ $ yarn add -D @typescript-eslint/eslint-plugin
47
50
  ```
48
51
 
49
52
  ```javascript
50
- module.exports = {
51
- root: true,
52
- extends: '@egs33',
53
- overrides: [
54
- {
55
- files: '*.ts',
56
- extends: '@egs33/eslint-config/typescript-node',
57
- parserOptions: {
58
- project: './tsconfig.json',
59
- },
60
- },
61
- ],
62
- };
53
+ import tsNode from '@egs33/eslint-config/typescript-node.js';
54
+ import { applyConfig } from '@egs33/eslint-config/util.js';
55
+
56
+ export default [
57
+ ...applyConfig({ files: ['**/*.ts'] }, tsNode),
58
+ ];
63
59
  ```
package/base.js CHANGED
@@ -1,29 +1,48 @@
1
- const promiseRules = require('./plugin-rules/promise');
1
+ import { FlatCompat } from '@eslint/eslintrc';
2
+ import promise from 'eslint-plugin-promise';
3
+ import { rules as PromiseRules } from './plugin-rules/promise.js';
2
4
 
3
- module.exports = {
4
- extends: [
5
- 'airbnb-base',
6
- 'plugin:array-func/all',
7
- 'plugin:regexp/recommended',
8
- ],
9
- parserOptions: {
10
- ecmaVersion: 2021,
11
- },
12
- env: {
13
- es2020: true,
5
+ const compat = new FlatCompat();
6
+
7
+ export default [
8
+ {
9
+ languageOptions: {
10
+ ecmaVersion: 2023,
11
+ parserOptions: {
12
+ // avoid import plugin error
13
+ ecmaVersion: 2023,
14
+ },
15
+ },
16
+ plugins: { promise },
17
+ linterOptions: {
18
+ reportUnusedDisableDirectives: true,
19
+ },
20
+ settings: {
21
+ 'import/parsers': {
22
+ espree: ['.js', '.cjs', '.mjs', '.jsx'],
23
+ },
24
+ },
14
25
  },
15
- plugins: ['promise', 'array-func', 'regexp'],
16
- rules: {
17
- 'no-plusplus': 'off',
18
- 'no-continue': 'off',
19
- 'func-style': 'error',
20
- 'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
21
- 'import/prefer-default-export': 'off',
22
- 'import/no-default-export': 'error',
23
- 'max-lines': ['error', { max: 500, skipComments: true }],
24
- // https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js#L6
25
- 'array-bracket-newline': 'error',
26
- ...promiseRules,
27
- 'array-func/prefer-array-from': 'off',
26
+ ...compat.extends('eslint-config-airbnb-base'),
27
+ ...compat.extends('plugin:eslint-plugin-array-func/all'),
28
+ ...compat.extends('plugin:eslint-plugin-regexp/recommended'),
29
+ {
30
+ languageOptions: {
31
+ // overwrite plugin-array-func
32
+ ecmaVersion: 2023,
33
+ },
34
+ rules: {
35
+ 'no-plusplus': 'off',
36
+ 'no-continue': 'off',
37
+ 'func-style': 'error',
38
+ 'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
39
+ 'import/prefer-default-export': 'off',
40
+ 'import/no-default-export': 'error',
41
+ 'max-lines': ['error', { max: 500, skipComments: true }],
42
+ // https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js#L6
43
+ 'array-bracket-newline': 'error',
44
+ 'array-func/prefer-array-from': 'off',
45
+ ...PromiseRules,
46
+ },
28
47
  },
29
- };
48
+ ];
package/browser.js CHANGED
@@ -1,6 +1,13 @@
1
- module.exports = {
2
- extends: './base',
3
- env: {
4
- browser: true,
1
+ import globals from 'globals';
2
+ import base from './base.js';
3
+
4
+ export default [
5
+ ...base,
6
+ {
7
+ languageOptions: {
8
+ globals: {
9
+ ...globals.browser,
10
+ },
11
+ },
5
12
  },
6
- };
13
+ ];
package/nodejs.js CHANGED
@@ -1,19 +1,23 @@
1
- module.exports = {
2
- extends: [
3
- './base',
4
- 'plugin:n/recommended',
5
- ],
6
- parserOptions: {
7
- ecmaVersion: 2021,
1
+ import node from 'eslint-plugin-n/configs/recommended-module.js';
2
+ import globals from 'globals';
3
+ import base from './base.js';
4
+
5
+ export default [
6
+ ...base,
7
+ node,
8
+ {
9
+ languageOptions: {
10
+ globals: {
11
+ ...globals.node,
12
+ },
13
+ },
14
+ rules: {
15
+ 'n/no-path-concat': 'error',
16
+ 'n/prefer-global/buffer': 'error',
17
+ 'n/prefer-global/console': 'error',
18
+ 'n/prefer-global/url': 'error',
19
+ 'n/prefer-global/url-search-params': 'error',
20
+ 'import/extensions': ['error', 'always', { ignorePackages: true }],
21
+ },
8
22
  },
9
- env: {
10
- node: true,
11
- },
12
- rules: {
13
- 'n/no-path-concat': 'error',
14
- 'n/prefer-global/buffer': 'error',
15
- 'n/prefer-global/console': 'error',
16
- 'n/prefer-global/url': 'error',
17
- 'n/prefer-global/url-search-params': 'error',
18
- },
19
- };
23
+ ];
package/package.json CHANGED
@@ -1,21 +1,24 @@
1
1
  {
2
2
  "name": "@egs33/eslint-config",
3
3
  "description": "eslint config for me",
4
- "version": "1.13.0",
4
+ "version": "2.0.1",
5
5
  "author": "egs33",
6
+ "type": "module",
6
7
  "dependencies": {
8
+ "@eslint/eslintrc": "^2.0.3",
7
9
  "eslint-config-airbnb-base": "^15.0.0",
8
10
  "eslint-config-airbnb-typescript": "^17.0.0",
9
11
  "eslint-plugin-array-func": "^3.1.7",
10
12
  "eslint-plugin-import": "^2.26.0",
11
- "eslint-plugin-n": "^15.6.1",
13
+ "eslint-plugin-n": "^16.0.1",
12
14
  "eslint-plugin-promise": "^6.0.1",
13
- "eslint-plugin-regexp": "^1.9.0"
15
+ "eslint-plugin-regexp": "^1.9.0",
16
+ "globals": "^13.20.0"
14
17
  },
15
18
  "devDependencies": {
16
19
  "@typescript-eslint/eslint-plugin": "^5.56.0",
17
20
  "@typescript-eslint/parser": "^5.56.0",
18
- "eslint": "^8.23.1",
21
+ "eslint": "^8.44.0",
19
22
  "eslint-plugin-vue": "^9.5.0",
20
23
  "typescript": "^5.0.2",
21
24
  "vue-eslint-parser": "^9.1.0"
@@ -24,10 +27,10 @@
24
27
  "node": ">=16"
25
28
  },
26
29
  "files": [
30
+ "util.js",
27
31
  "base.js",
28
32
  "browser.js",
29
33
  "nodejs.js",
30
- "vue.js",
31
34
  "vue3.js",
32
35
  "typescript-base.js",
33
36
  "typescript-node.js",
@@ -43,7 +46,7 @@
43
46
  "main": "nodejs.js",
44
47
  "peerDependencies": {
45
48
  "@typescript-eslint/eslint-plugin": "^5.37.0",
46
- "eslint": "^8.23.1",
49
+ "eslint": "^8.44.0",
47
50
  "eslint-plugin-vue": "^9.5.0",
48
51
  "typescript": ">=4.4.4",
49
52
  "vue-eslint-parser": "^9.1.0"
@@ -67,7 +70,7 @@
67
70
  "url": "https://github.com/egs33/eslint-config"
68
71
  },
69
72
  "scripts": {
70
- "lint": "eslint . -c base.js",
71
- "lint:fix": "eslint . -c base.js --fix"
73
+ "lint": "eslint .",
74
+ "lint:fix": "eslint . --fix"
72
75
  }
73
76
  }
@@ -1,4 +1,4 @@
1
- module.exports = {
1
+ export const rules = {
2
2
  'promise/always-return': 'off',
3
3
  'promise/no-return-wrap': 'error',
4
4
  'promise/param-names': 'error',
@@ -1,25 +1,35 @@
1
- const base = require('./base');
1
+ import { FlatCompat } from '@eslint/eslintrc';
2
+ import base from './base.js';
2
3
 
3
- module.exports = {
4
- extends: [
5
- 'plugin:@typescript-eslint/recommended',
6
- 'plugin:@typescript-eslint/recommended-requiring-type-checking',
7
- 'airbnb-typescript/base',
8
- ],
9
- rules: {
10
- ...base.rules,
11
- '@typescript-eslint/method-signature-style': ['error', 'property'],
12
- '@typescript-eslint/restrict-template-expressions': 'off',
13
- '@typescript-eslint/consistent-type-imports': 'error',
14
- '@typescript-eslint/array-type': 'error',
15
- '@typescript-eslint/no-invalid-void-type': 'error',
16
- '@typescript-eslint/no-require-imports': 'error',
17
- '@typescript-eslint/non-nullable-type-assertion-style': 'error',
18
- '@typescript-eslint/prefer-for-of': 'error',
19
- '@typescript-eslint/prefer-includes': 'error',
20
- '@typescript-eslint/prefer-optional-chain': 'error',
21
- '@typescript-eslint/prefer-nullish-coalescing': 'error',
22
- '@typescript-eslint/prefer-string-starts-ends-with': 'error',
23
- '@typescript-eslint/type-annotation-spacing': 'error',
4
+ const compat = new FlatCompat();
5
+
6
+ const a = [
7
+ ...base,
8
+ ...compat.extends('plugin:@typescript-eslint/recommended'),
9
+ ...compat.extends('plugin:@typescript-eslint/recommended-requiring-type-checking'),
10
+ ...compat.extends('airbnb-typescript/base'),
11
+ {
12
+ languageOptions: {
13
+ parserOptions: {
14
+ project: './tsconfig.json',
15
+ },
16
+ },
17
+ rules: {
18
+ '@typescript-eslint/method-signature-style': ['error', 'property'],
19
+ '@typescript-eslint/restrict-template-expressions': 'off',
20
+ '@typescript-eslint/consistent-type-imports': 'error',
21
+ '@typescript-eslint/array-type': 'error',
22
+ '@typescript-eslint/no-invalid-void-type': 'error',
23
+ '@typescript-eslint/no-require-imports': 'error',
24
+ '@typescript-eslint/non-nullable-type-assertion-style': 'error',
25
+ '@typescript-eslint/prefer-for-of': 'error',
26
+ '@typescript-eslint/prefer-includes': 'error',
27
+ '@typescript-eslint/prefer-optional-chain': 'error',
28
+ '@typescript-eslint/prefer-nullish-coalescing': 'error',
29
+ '@typescript-eslint/prefer-string-starts-ends-with': 'error',
30
+ '@typescript-eslint/type-annotation-spacing': 'error',
31
+ },
24
32
  },
25
- };
33
+ ];
34
+
35
+ export default a;
@@ -1,6 +1,7 @@
1
- module.exports = {
2
- extends: [
3
- './browser',
4
- './typescript-base',
5
- ],
6
- };
1
+ import browser from './browser.js';
2
+ import typescriptBase from './typescript-base.js';
3
+
4
+ export default [
5
+ ...browser,
6
+ ...typescriptBase,
7
+ ];
@@ -1,9 +1,12 @@
1
- module.exports = {
2
- extends: [
3
- './nodejs',
4
- './typescript-base',
5
- ],
6
- rules: {
7
- 'n/no-missing-import': 'off',
1
+ import nodejs from './nodejs.js';
2
+ import typescriptBase from './typescript-base.js';
3
+
4
+ export default [
5
+ ...nodejs,
6
+ ...typescriptBase,
7
+ {
8
+ rules: {
9
+ 'n/no-missing-import': 'off',
10
+ },
8
11
  },
9
- };
12
+ ];
package/util.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @param {{files?: string[], ignores?: string[]}} filesConfig
3
+ * @param {*[]} sharedConfig
4
+ * @returns {*[]}
5
+ */
6
+ export const applyConfig = (filesConfig, sharedConfig) => sharedConfig
7
+ .map((config) => ({
8
+ ...config,
9
+ ...filesConfig,
10
+ }));
package/vue3.js CHANGED
@@ -1,105 +1,114 @@
1
- module.exports = {
2
- extends: ['./browser', 'plugin:vue/vue3-recommended'],
3
- plugins: ['vue'],
4
- parser: 'vue-eslint-parser',
5
- overrides: [
6
- {
7
- files: '**.vue',
8
- rules: {
9
- 'import/no-default-export': 'off',
10
- },
1
+ import { FlatCompat } from '@eslint/eslintrc';
2
+ import parser from 'vue-eslint-parser';
3
+ import browser from './browser.js';
4
+
5
+ const compat = new FlatCompat();
6
+
7
+ const config = [
8
+ ...browser,
9
+ ...compat.extends('plugin:vue/vue3-recommended'),
10
+ {
11
+ languageOptions: {
12
+ parser,
11
13
  },
12
- ],
13
- rules: {
14
- 'vue/max-attributes-per-line': ['error', {
15
- singleline: 4,
16
- }],
17
- 'vue/html-indent': ['error', 2],
18
- 'vue/html-closing-bracket-newline': ['error', {
19
- singleline: 'never',
20
- multiline: 'never',
21
- }],
22
- // use airbnb rules in vue templates
23
- 'vue/array-bracket-spacing': 'error',
24
- 'vue/arrow-spacing': 'error',
25
- 'vue/block-spacing': 'error',
26
- 'vue/brace-style': [
27
- 'error',
28
- '1tbs',
29
- {
30
- allowSingleLine: true,
31
- },
32
- ],
33
- 'vue/camelcase': [
34
- 'error',
35
- {
36
- properties: 'never',
37
- },
38
- ],
39
- 'vue/comma-dangle': [
40
- 'error',
41
- {
42
- arrays: 'always-multiline',
43
- objects: 'always-multiline',
44
- imports: 'always-multiline',
45
- exports: 'always-multiline',
46
- functions: 'always-multiline',
47
- },
48
- ],
49
- 'vue/comma-spacing': 'error',
50
- 'vue/comma-style': [
51
- 'error',
52
- 'last',
53
- {
54
- exceptions: {
55
- ArrayExpression: false,
56
- ArrayPattern: false,
57
- ArrowFunctionExpression: false,
58
- CallExpression: false,
59
- FunctionDeclaration: false,
60
- FunctionExpression: false,
61
- ImportDeclaration: false,
62
- ObjectExpression: false,
63
- ObjectPattern: false,
64
- VariableDeclaration: false,
65
- NewExpression: false,
14
+ rules: {
15
+ 'import/no-default-export': 'off',
16
+ 'vue/max-attributes-per-line': ['error', {
17
+ singleline: 4,
18
+ }],
19
+ 'vue/html-indent': ['error', 2],
20
+ 'vue/html-closing-bracket-newline': ['error', {
21
+ singleline: 'never',
22
+ multiline: 'never',
23
+ }],
24
+ // use airbnb rules in vue templates
25
+ 'vue/array-bracket-spacing': 'error',
26
+ 'vue/arrow-spacing': 'error',
27
+ 'vue/block-spacing': 'error',
28
+ 'vue/brace-style': [
29
+ 'error',
30
+ '1tbs',
31
+ {
32
+ allowSingleLine: true,
66
33
  },
67
- },
68
- ],
69
- 'vue/dot-location': [
70
- 'error',
71
- 'property',
72
- ],
73
- 'vue/dot-notation': 'error',
74
- 'vue/eqeqeq': 'error',
75
- 'vue/key-spacing': 'error',
76
- 'vue/keyword-spacing': 'error',
77
- 'vue/max-len': ['error', {
78
- code: 100,
79
- template: 100,
80
- comments: 100,
81
- ignoreUrls: true,
82
- ignoreRegExpLiterals: true,
83
- ignoreStrings: true,
84
- ignoreTemplateLiterals: true,
85
- }],
86
- 'vue/no-empty-pattern': 'error',
87
- 'vue/no-irregular-whitespace': 'error',
88
- 'vue/no-restricted-syntax': [
89
- 'error',
90
- 'ForInStatement',
91
- 'LabeledStatement',
92
- 'WithStatement',
93
- ],
94
- 'vue/no-useless-concat': 'error',
95
- 'vue/object-curly-spacing': [
96
- 'error',
97
- 'always',
98
- ],
99
- 'vue/prefer-template': 'error',
100
- 'vue/space-in-parens': 'error',
101
- 'vue/space-infix-ops': 'error',
102
- 'vue/space-unary-ops': 'error',
103
- 'vue/template-curly-spacing': 'error',
34
+ ],
35
+ 'vue/camelcase': [
36
+ 'error',
37
+ {
38
+ properties: 'never',
39
+ },
40
+ ],
41
+ 'vue/comma-dangle': [
42
+ 'error',
43
+ {
44
+ arrays: 'always-multiline',
45
+ objects: 'always-multiline',
46
+ imports: 'always-multiline',
47
+ exports: 'always-multiline',
48
+ functions: 'always-multiline',
49
+ },
50
+ ],
51
+ 'vue/comma-spacing': 'error',
52
+ 'vue/comma-style': [
53
+ 'error',
54
+ 'last',
55
+ {
56
+ exceptions: {
57
+ ArrayExpression: false,
58
+ ArrayPattern: false,
59
+ ArrowFunctionExpression: false,
60
+ CallExpression: false,
61
+ FunctionDeclaration: false,
62
+ FunctionExpression: false,
63
+ ImportDeclaration: false,
64
+ ObjectExpression: false,
65
+ ObjectPattern: false,
66
+ VariableDeclaration: false,
67
+ NewExpression: false,
68
+ },
69
+ },
70
+ ],
71
+ 'vue/dot-location': [
72
+ 'error',
73
+ 'property',
74
+ ],
75
+ 'vue/dot-notation': 'error',
76
+ 'vue/eqeqeq': 'error',
77
+ 'vue/key-spacing': 'error',
78
+ 'vue/keyword-spacing': 'error',
79
+ 'vue/max-len': ['error', {
80
+ code: 100,
81
+ template: 100,
82
+ comments: 100,
83
+ ignoreUrls: true,
84
+ ignoreRegExpLiterals: true,
85
+ ignoreStrings: true,
86
+ ignoreTemplateLiterals: true,
87
+ }],
88
+ 'vue/no-empty-pattern': 'error',
89
+ 'vue/no-irregular-whitespace': 'error',
90
+ 'vue/no-restricted-syntax': [
91
+ 'error',
92
+ 'ForInStatement',
93
+ 'LabeledStatement',
94
+ 'WithStatement',
95
+ ],
96
+ 'vue/no-useless-concat': 'error',
97
+ 'vue/object-curly-spacing': [
98
+ 'error',
99
+ 'always',
100
+ ],
101
+ 'vue/prefer-template': 'error',
102
+ 'vue/space-in-parens': 'error',
103
+ 'vue/space-infix-ops': 'error',
104
+ 'vue/space-unary-ops': 'error',
105
+ 'vue/template-curly-spacing': 'error',
106
+ },
104
107
  },
105
- };
108
+ ];
109
+
110
+ // default name '.vue' is invalid processer name in flat config
111
+ config.plugins.vue.processors.vue = config.plugins.vue.processors['.vue'];
112
+ config.processor = 'vue/vue';
113
+
114
+ export default config;
package/vue.js DELETED
@@ -1,105 +0,0 @@
1
- module.exports = {
2
- extends: ['./browser', 'plugin:vue/recommended'],
3
- plugins: ['vue'],
4
- parser: 'vue-eslint-parser',
5
- overrides: [
6
- {
7
- files: '**.vue',
8
- rules: {
9
- 'import/no-default-export': 'off',
10
- },
11
- },
12
- ],
13
- rules: {
14
- 'vue/max-attributes-per-line': ['error', {
15
- singleline: 4,
16
- }],
17
- 'vue/html-indent': ['error', 2],
18
- 'vue/html-closing-bracket-newline': ['error', {
19
- singleline: 'never',
20
- multiline: 'never',
21
- }],
22
- // use airbnb rules in vue templates
23
- 'vue/array-bracket-spacing': 'error',
24
- 'vue/arrow-spacing': 'error',
25
- 'vue/block-spacing': 'error',
26
- 'vue/brace-style': [
27
- 'error',
28
- '1tbs',
29
- {
30
- allowSingleLine: true,
31
- },
32
- ],
33
- 'vue/camelcase': [
34
- 'error',
35
- {
36
- properties: 'never',
37
- },
38
- ],
39
- 'vue/comma-dangle': [
40
- 'error',
41
- {
42
- arrays: 'always-multiline',
43
- objects: 'always-multiline',
44
- imports: 'always-multiline',
45
- exports: 'always-multiline',
46
- functions: 'always-multiline',
47
- },
48
- ],
49
- 'vue/comma-spacing': 'error',
50
- 'vue/comma-style': [
51
- 'error',
52
- 'last',
53
- {
54
- exceptions: {
55
- ArrayExpression: false,
56
- ArrayPattern: false,
57
- ArrowFunctionExpression: false,
58
- CallExpression: false,
59
- FunctionDeclaration: false,
60
- FunctionExpression: false,
61
- ImportDeclaration: false,
62
- ObjectExpression: false,
63
- ObjectPattern: false,
64
- VariableDeclaration: false,
65
- NewExpression: false,
66
- },
67
- },
68
- ],
69
- 'vue/dot-location': [
70
- 'error',
71
- 'property',
72
- ],
73
- 'vue/dot-notation': 'error',
74
- 'vue/eqeqeq': 'error',
75
- 'vue/key-spacing': 'error',
76
- 'vue/keyword-spacing': 'error',
77
- 'vue/max-len': ['error', {
78
- code: 100,
79
- template: 100,
80
- comments: 100,
81
- ignoreUrls: true,
82
- ignoreRegExpLiterals: true,
83
- ignoreStrings: true,
84
- ignoreTemplateLiterals: true,
85
- }],
86
- 'vue/no-empty-pattern': 'error',
87
- 'vue/no-irregular-whitespace': 'error',
88
- 'vue/no-restricted-syntax': [
89
- 'error',
90
- 'ForInStatement',
91
- 'LabeledStatement',
92
- 'WithStatement',
93
- ],
94
- 'vue/no-useless-concat': 'error',
95
- 'vue/object-curly-spacing': [
96
- 'error',
97
- 'always',
98
- ],
99
- 'vue/prefer-template': 'error',
100
- 'vue/space-in-parens': 'error',
101
- 'vue/space-infix-ops': 'error',
102
- 'vue/space-unary-ops': 'error',
103
- 'vue/template-curly-spacing': 'error',
104
- },
105
- };