Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4fdbf7e

Browse files
Merge pull request #6 from en96321/refactor
refactor(index.js): add babel、eslint、jest、 unit test and refactor vue...
2 parents d650106 + f41fcf9 commit 4fdbf7e

File tree

16 files changed

+4792
-80
lines changed

16 files changed

+4792
-80
lines changed

‎.eslintignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist

‎.eslintrc.cjs‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
es2021: true,
5+
node: true
6+
},
7+
extends: [
8+
'standard' // javascript standard 語法規範。
9+
],
10+
ignorePatterns: ['node_modules/**', 'dist/**'], // 排除檢查
11+
plugins: ['jest'],
12+
overrides: [
13+
{
14+
env: {
15+
node: true,
16+
jest: true
17+
},
18+
files: ['.eslintrc.{js,cjs}', '**/__tests__/*.{j,t}s?(x)', '**/*.spec.{j,t}s?(x)', 'tests/**/*.js'],
19+
plugins: ['jest'],
20+
parserOptions: {
21+
sourceType: 'module'
22+
}
23+
}
24+
],
25+
parserOptions: {
26+
ecmaVersion: 'latest',
27+
sourceType: 'module'
28+
},
29+
rules: {
30+
indent: ['error', 2],
31+
quotes: ['error', 'single'],
32+
semi: ['error', 'never'],
33+
'linebreak-style': ['error', 'unix'],
34+
'comma-dangle': ['error', 'never']
35+
}
36+
}

‎.gitignore‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
vscode/extensions.json
18+
vscode/settings.json
19+
.idea
20+
.DS_Store
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?

‎README.md‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,23 @@ export const ILoading = {
5656
}
5757

5858

59-
//IButton
60-
export const IButton = VueInheritance
61-
.extend(IControl)
62-
.extend(ITheme)
63-
.extend({
64-
methods: {
65-
onClick(e) {
66-
this.$emit('click', e)
67-
}
59+
// IButton
60+
export const IButton = {
61+
extends: VueInheritance.implement(IControl).implement(ITheme)
62+
props: {
63+
size: {
64+
type: String,
65+
default: 'lg'
6866
}
69-
})
67+
},
68+
69+
methods: {
70+
}
71+
}
72+
73+
74+
75+
7076
```
7177

7278
**Implement**

‎babel.config.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
3+
};

‎jest.config.json‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"verbose": true,
3+
"testEnvironment": "node",
4+
"transform": {
5+
"^.+\\.js$": "babel-jest"
6+
}
7+
}
8+
9+

‎package.json‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "vue-inheritance",
3-
"version": "1.0.1-beta.4",
3+
"version": "1.0.1-beta.5",
44
"description": "vue inheritance",
55
"main": "src/index.js",
66
"types": "src/index.d.ts",
77
"scripts": {
8-
"test": "echo \"Error: no test specified\" && exit 1"
8+
"test": "jest"
99
},
1010
"repository": {
1111
"type": "git",
@@ -28,5 +28,18 @@
2828
"homepage": "https://github.com/en96321/vue-Inheritance#readme",
2929
"dependencies": {
3030
"ramda": "0.29.1"
31+
},
32+
"devDependencies": {
33+
"@babel/core": "^7.23.7",
34+
"@babel/preset-env": "^7.23.8",
35+
"babel-jest": "^29.7.0",
36+
"eslint": "^8.56.0",
37+
"eslint-config-standard": "^17.1.0",
38+
"eslint-plugin-import": "^2.25.2",
39+
"eslint-plugin-jest": "^27.6.3",
40+
"eslint-plugin-n": "^16.0.0",
41+
"eslint-plugin-promise": "^6.0.0",
42+
"jest": "^29.7.0",
43+
"vue": "^3.4.15"
3144
}
3245
}

‎src/index.js‎

Lines changed: 129 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,135 @@
1-
import { mergeRight, clone } from 'ramda'
2-
3-
export class VueInheritance {
4-
constructor ({
5-
props,
6-
methods,
7-
computed
8-
}) {
9-
this.props = clone(props)
10-
this.methods = clone(methods)
11-
this.computed = clone(computed)
1+
import { clone, isNil, isNotNil, has, isEmpty } from 'ramda'
2+
3+
/**
4+
* Vue3Component
5+
* @class
6+
* @private
7+
* @author pedro.yang、 ocean.tsai
8+
* @description
9+
*/
10+
class Vue3Component {
11+
/**
12+
* InvalidInterfaceKeys
13+
* @static
14+
* @constant
15+
* @private
16+
* @type
17+
* @description interfaceDefine will be checked, if it conforms to the interface, it return true; otherwise, it returns false.
18+
*/
19+
static InvalidInterfaceKeys = Object.freeze([
20+
'watch',
21+
'beforeCreate', 'created',
22+
'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeUnmount', 'unmounted',
23+
'errorCaptured', 'renderTracked', 'activated', 'deactivated', 'serverPrefetch'
24+
])
25+
26+
/**
27+
* validateInterface
28+
* @static
29+
* @method
30+
* @protected
31+
* @param {VueInterface} interfaceDefine the param will be checked.
32+
* @description interfaceDefine will be checked, if it conforms to the interface, it return true; otherwise, it returns false.
33+
*/
34+
static validateInterface (interfaceDefine) {
35+
// hasIn 是包含 prototype has 不會含 prototype
36+
return Vue3Component.InvalidInterfaceKeys.every((key) => !has(key, interfaceDefine))
37+
}
38+
39+
/**
40+
* typeCheck
41+
* @static
42+
* @method
43+
* @protected
44+
* @param {VueInterface} interfaceDefine the param will be checked.
45+
* @description interfaceDefine will be checked, if it conforms to the interface, it return true; otherwise, it returns false.
46+
*/
47+
static typeCheck (interfaceDefine) {
48+
if (isNil(interfaceDefine)) {
49+
throw new Error('Interface cannot be null or undefined.')
50+
} else if (isEmpty(interfaceDefine)) {
51+
throw new Error('Interface cannot be empty object.')
52+
} else if (!Vue3Component.validateInterface(interfaceDefine)) {
53+
throw new Error('The incoming parameter must be an interface.')
54+
}
55+
}
56+
57+
/**
58+
* extend
59+
* @static
60+
* @method
61+
* @param {VueComponent} componentDefine componentDefine to be inherited.
62+
* @param {VueComponent} override override to be override.
63+
* @description
64+
*/
65+
static extend (componentDefine, override) {
66+
const vue3Component = isNotNil(componentDefine)
67+
? Object.assign(new Vue3Component(), clone(componentDefine))
68+
: new Vue3Component()
69+
70+
return isNotNil(override)
71+
? Object.assign(vue3Component, clone(override))
72+
: vue3Component
73+
}
74+
75+
/**
76+
* implement
77+
* @static
78+
* @method
79+
* @public
80+
* @param {VueComponent} interfaceDefine interfaceDefine to be inherited.
81+
* @description Vue's interface can only define props、methods.
82+
*/
83+
static implement (interfaceDefine) {
84+
Vue3Component.typeCheck(interfaceDefine)
85+
return Vue3Component.extend(interfaceDefine)
1286
}
13-
static extend (extendOptions) {
14-
const sub = new VueInheritance(extendOptions)
15-
sub.extend(extendOptions.extends || {})
16-
return sub
87+
88+
// eslint-disable-next-line no-useless-constructor
89+
constructor (componentOptions) {
1790
}
1891

19-
static implement = VueInheritance.extend
20-
21-
extend (extendOptions) {
22-
const cloneExtendOptions = clone(extendOptions)
23-
try {
24-
this.props = mergeRight(this.props, cloneExtendOptions.props)
25-
this.methods = mergeRight(this.methods, cloneExtendOptions.methods)
26-
this.computed = mergeRight(this.computed, cloneExtendOptions.computed)
27-
return this
28-
} catch (e) {
29-
throw new TypeError('extend error')
92+
/**
93+
* extends
94+
* @type {VueComponent} extends
95+
* @description property of Vue component option api.
96+
*/
97+
extends = null
98+
99+
/**
100+
* implement
101+
* @static
102+
* @method
103+
* @public
104+
* @param {VueInterface} interface interface to be inherited.
105+
* @description Vue's interface can only define props、methods.
106+
*/
107+
implement (interfaceDefine) {
108+
Vue3Component.typeCheck(interfaceDefine)
109+
110+
if (isNil(this.extends) || isEmpty(this.extends)) {
111+
this.extends = clone(interfaceDefine)
112+
} else {
113+
let deepestNode = this.extends
114+
// find deepes node.
115+
while (isNotNil(deepestNode.extends)) {
116+
deepestNode = deepestNode.extends
117+
}
118+
deepestNode.extends = clone(interfaceDefine)
30119
}
120+
return this
31121
}
122+
}
123+
124+
/**
125+
* VueInheritance
126+
* @static
127+
* @public
128+
* @description
129+
*/
130+
const VueInheritance = Object.freeze({
131+
extend: Vue3Component.extend,
132+
implement: Vue3Component.implement
133+
})
32134

33-
implement = this.extend
34-
}
135+
export default VueInheritance

‎tests/controlGroup/IBorder.js‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { IVisibility } from './IVisibility.js'
2+
3+
/**
4+
* IBorder
5+
* @author ocean.tsai
6+
* @public
7+
* @interface
8+
* @description
9+
*/
10+
export const IBorder = {
11+
extends: IVisibility,
12+
props: {
13+
borderSize: {
14+
type: Number,
15+
default: '1px'
16+
}
17+
}
18+
}

‎tests/controlGroup/IButton.js‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { IBorder } from './IBorder.js'
2+
3+
/**
4+
* IButton
5+
* @author ocean.tsai
6+
* @public
7+
* @interface
8+
* @description
9+
*/
10+
export const IButton = {
11+
extends: IBorder,
12+
13+
props: {
14+
buttonSize: {
15+
type: String,
16+
default: 'sm'
17+
}
18+
},
19+
20+
methods: {
21+
onClick () {
22+
this.$emit('click', this.value)
23+
}
24+
}
25+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /