@lsby/trie-tree 0.0.5

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 ADDED
@@ -0,0 +1,33 @@
1
+ # trie-tree
2
+
3
+ 一个 ts 实现的字典树.
4
+
5
+ ## 使用
6
+
7
+ ```
8
+ npm i @lsby/trie-tree
9
+ ```
10
+
11
+ ```typescript
12
+ import { 创建字典树, 插入字典树, 查询字典树 } from '@lsby/trie-tree'
13
+
14
+ var obj = 创建字典树()
15
+ 插入字典树(obj, 'ni')
16
+ 插入字典树(obj, 'ni1')
17
+ 插入字典树(obj, 'ni2')
18
+ 插入字典树(obj, 'ni3')
19
+ 插入字典树(obj, 'ni45')
20
+ var c = 查询字典树(obj, 'ni') // ['ni1', 'ni2', 'ni3', 'ni45']
21
+ ```
22
+
23
+ ```typescript
24
+ import { 创建字典树, 插入字典树, 查询字典树 } from '@lsby/trie-tree'
25
+
26
+ var obj = 创建字典树()
27
+ 插入字典树(obj, 'n')
28
+ 插入字典树(obj, 'ni')
29
+ 插入字典树(obj, 'nih')
30
+ 插入字典树(obj, 'niha')
31
+ 插入字典树(obj, 'nihao')
32
+ var c = 查询字典树(obj, 'ni') // ['ni', 'nih', 'niha', 'nihao']
33
+ ```
@@ -0,0 +1,29 @@
1
+ declare const 值: unique symbol;
2
+ declare const 类型: unique symbol;
3
+ declare const 当前值: unique symbol;
4
+ declare const 子节点: unique symbol;
5
+ declare const 终结子: unique symbol;
6
+ declare type 终结子 = typeof 终结子;
7
+ declare const 起始子: unique symbol;
8
+ declare type 起始子 = typeof 起始子;
9
+ declare const 节点: unique symbol;
10
+ declare type 节点 = typeof 节点;
11
+ declare type 非空数组<T> = [T, ...T[]];
12
+ export declare type 字典树 = {
13
+ [值]: 起始节点 | 终结节点 | 普通节点;
14
+ };
15
+ declare type 起始节点 = {
16
+ [类型]: 起始子;
17
+ };
18
+ declare type 终结节点 = {
19
+ [类型]: 终结子;
20
+ };
21
+ declare type 普通节点 = {
22
+ [类型]: 节点;
23
+ [当前值]: string;
24
+ [子节点]: 非空数组<普通节点 | 终结节点>;
25
+ };
26
+ export declare function 创建字典树(): 字典树;
27
+ export declare function 插入字典树(a: 字典树, s: string): void;
28
+ export declare function 查询字典树(a: 字典树, s: string): string[];
29
+ export {};
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.查询字典树 = exports.插入字典树 = exports.创建字典树 = void 0;
4
+ const 值 = Symbol();
5
+ const 类型 = Symbol();
6
+ const 当前值 = Symbol();
7
+ const 子节点 = Symbol();
8
+ const 终结子 = Symbol();
9
+ const 起始子 = Symbol();
10
+ const 节点 = Symbol();
11
+ function 创建字典树() {
12
+ return { [值]: { [类型]: 起始子 } };
13
+ }
14
+ exports.创建字典树 = 创建字典树;
15
+ function 创建字典树节点(字符, 子节点对象) {
16
+ return {
17
+ [类型]: 节点,
18
+ [当前值]: 字符,
19
+ [子节点]: 子节点对象,
20
+ };
21
+ }
22
+ function 创建终结子() {
23
+ return {
24
+ [类型]: 终结子,
25
+ };
26
+ }
27
+ function 取值(a) {
28
+ return a[当前值];
29
+ }
30
+ function 查询字符(a, 字符) {
31
+ var c = a[子节点].filter((a) => a[类型] != 终结子 && 取值(a) == 字符);
32
+ if (c.length == 0)
33
+ return null;
34
+ if (c[0][类型] == 终结子)
35
+ throw new Error('意外的终结子');
36
+ return c[0];
37
+ }
38
+ function 构造链(s) {
39
+ if (s.length == 0)
40
+ throw new Error('不能构造空链');
41
+ var arr = s.split('').reverse();
42
+ var r = 创建终结子();
43
+ for (var a of arr) {
44
+ r = 创建字典树节点(a, [r]);
45
+ }
46
+ if (r[类型] == 终结子)
47
+ throw new Error('意外的空链');
48
+ return r;
49
+ }
50
+ function 插入字典树(a, s) {
51
+ if (a[值][类型] == 终结子)
52
+ throw new Error('不能对终结子插入字符');
53
+ if (a[值][类型] == 起始子) {
54
+ if (s.length == 0)
55
+ throw new Error('不能对起始子插入空字符串');
56
+ a[值] = 构造链(s);
57
+ return;
58
+ }
59
+ _插入字典树(a[值], s);
60
+ }
61
+ exports.插入字典树 = 插入字典树;
62
+ function _插入字典树(a, s) {
63
+ if (s.length == 0)
64
+ return;
65
+ var 第一个字符 = s.substring(0, 1);
66
+ var 剩下的字符串 = s.substring(1);
67
+ var 新子节点 = 查询字符(a, 第一个字符);
68
+ if (新子节点 == null) {
69
+ 新子节点 = 构造链(s);
70
+ a[子节点].push(新子节点);
71
+ return;
72
+ }
73
+ _插入字典树(新子节点, 剩下的字符串);
74
+ }
75
+ function 直接含有终止子和普通节点(a) {
76
+ var c = a[子节点].filter((a) => a[类型] == 终结子);
77
+ if (c.length != 0 && a[子节点].length != 1)
78
+ return true;
79
+ return false;
80
+ }
81
+ function 只含有终止子(a) {
82
+ if (a[子节点].length == 1 && a[子节点][0][类型] == 终结子)
83
+ return true;
84
+ return false;
85
+ }
86
+ function 枚举到终结子(a) {
87
+ if (a[类型] == 终结子)
88
+ return [];
89
+ if (只含有终止子(a))
90
+ return [a[当前值]];
91
+ if (直接含有终止子和普通节点(a)) {
92
+ return [
93
+ a[当前值],
94
+ ...a[子节点]
95
+ .map(枚举到终结子)
96
+ .flat()
97
+ .map((x) => a[当前值] + x),
98
+ ];
99
+ }
100
+ return a[子节点]
101
+ .map(枚举到终结子)
102
+ .flat()
103
+ .map((x) => a[当前值] + x);
104
+ }
105
+ function _查询字典树(a, s, 累计字符串 = '') {
106
+ if (s.length == 0)
107
+ return 枚举到终结子(a).map((x) => 累计字符串.substring(0, 累计字符串.length - 1) + x);
108
+ var 第一个字符 = s.substring(0, 1);
109
+ var 剩下的字符串 = s.substring(1);
110
+ var 命中节点 = 查询字符(a, 第一个字符);
111
+ if (命中节点 == null)
112
+ return [];
113
+ return _查询字典树(命中节点, 剩下的字符串, 累计字符串 + 第一个字符);
114
+ }
115
+ function 查询字典树(a, s) {
116
+ if (s == '')
117
+ throw new Error('不能查询空字符串');
118
+ if (a[值][类型] == 终结子)
119
+ throw new Error('不能对终结子查询');
120
+ if (a[值][类型] == 起始子)
121
+ return [];
122
+ return _查询字典树(a[值], s);
123
+ }
124
+ exports.查询字典树 = 查询字典树;
125
+ //# sourceMappingURL=Index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Index.js","sourceRoot":"","sources":["../../src/Index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ import 'mocha';
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("mocha");
4
+ const Index_1 = require("../src/Index");
5
+ function 断言相等(a, b) {
6
+ if (JSON.stringify(a) == JSON.stringify(b))
7
+ return;
8
+ throw new Error(`${JSON.stringify(a)} 不等于 ${JSON.stringify(b)}`);
9
+ }
10
+ it('测试', function () {
11
+ var obj = (0, Index_1.创建字典树)();
12
+ (0, Index_1.插入字典树)(obj, 'ni');
13
+ (0, Index_1.插入字典树)(obj, 'ni1');
14
+ (0, Index_1.插入字典树)(obj, 'ni2');
15
+ (0, Index_1.插入字典树)(obj, 'ni3');
16
+ (0, Index_1.插入字典树)(obj, 'ni45');
17
+ var c = (0, Index_1.查询字典树)(obj, 'ni');
18
+ 断言相等(c, ['ni1', 'ni2', 'ni3', 'ni45']);
19
+ var obj = (0, Index_1.创建字典树)();
20
+ (0, Index_1.插入字典树)(obj, 'n');
21
+ (0, Index_1.插入字典树)(obj, 'ni');
22
+ (0, Index_1.插入字典树)(obj, 'nih');
23
+ (0, Index_1.插入字典树)(obj, 'niha');
24
+ (0, Index_1.插入字典树)(obj, 'nihao');
25
+ var c = (0, Index_1.查询字典树)(obj, 'ni');
26
+ 断言相等(c, ['ni', 'nih', 'niha', 'nihao']);
27
+ });
28
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../test/index.test.ts"],"names":[],"mappings":";;AAAA,iBAAc;AACd,wCAAkD;AAElD,SAAS,IAAI,CAAC,CAAM,EAAE,CAAM;IAC1B,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAAE,OAAM;IAClD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAClE,CAAC;AAED,EAAE,CAAC,IAAI,EAAE;IACP,IAAI,GAAG,GAAG,IAAA,aAAK,GAAE,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAChB,IAAA,aAAK,EAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAClB,IAAI,CAAC,GAAG,IAAA,aAAK,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACxB,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAEtC,IAAI,GAAG,GAAG,IAAA,aAAK,GAAE,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACf,IAAA,aAAK,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAChB,IAAA,aAAK,EAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACjB,IAAA,aAAK,EAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IAClB,IAAA,aAAK,EAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACnB,IAAI,CAAC,GAAG,IAAA,aAAK,EAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IACxB,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AACzC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { Generated } from 'kysely';
2
+ export default interface Database {
3
+ '学生表': {
4
+ 'id': Generated<number>;
5
+ '姓名': string;
6
+ '性别': '男' | '女';
7
+ '所属班级': number;
8
+ 'created_at': Generated<string>;
9
+ };
10
+ '班级表': {
11
+ 'id': Generated<number>;
12
+ '名称': string;
13
+ 'created_at': Generated<string>;
14
+ };
15
+ 'kysely_migration': {
16
+ 'name': string;
17
+ 'timestamp': string;
18
+ };
19
+ 'kysely_migration_lock': {
20
+ 'id': string;
21
+ 'is_locked': Generated<number>;
22
+ };
23
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=Database.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Database.js","sourceRoot":"","sources":["../../../tools/types/Database.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@lsby/trie-tree",
3
+ "version": "0.0.5",
4
+ "description": "一个 ts 实现的字典树.",
5
+ "author": "hbybyyang",
6
+ "main": "dist/src/Index.js",
7
+ "license": "GPL-3.0-or-later",
8
+ "scripts": {
9
+ "=====build=====": "",
10
+ "build:ts": "tsc",
11
+ "=====watch=====": "",
12
+ "watch:ts": "tsc -w",
13
+ "=====test=====": "",
14
+ "test": "cross-env NODE_ENV=dev mocha dist/test/index.test.js --bail --timeout 99999999",
15
+ "coverage": "cross-env NODE_ENV=dev nyc --clean --reporter=html --reporter=text-summary npm run test && open-cli ./coverage/index.html",
16
+ "=====npm=====": "",
17
+ "prepub": "npm i && npm run build:ts",
18
+ "pub": "npm publish --access=public",
19
+ "=====其他=====": "",
20
+ "format:all": "prettier --write .",
21
+ "prepare": "husky install"
22
+ },
23
+ "lint-staged": {
24
+ "**/*": "prettier --write --ignore-unknown"
25
+ },
26
+ "dependencies": {},
27
+ "devDependencies": {
28
+ "@types/mocha": "^9.1.0",
29
+ "mocha": "^9.2.2",
30
+ "husky": "^7.0.4",
31
+ "typescript": "^4.7.4"
32
+ }
33
+ }
package/src/Index.ts ADDED
@@ -0,0 +1,141 @@
1
+ const 值: unique symbol = Symbol()
2
+ const 类型: unique symbol = Symbol()
3
+ const 当前值: unique symbol = Symbol()
4
+ const 子节点: unique symbol = Symbol()
5
+ const 终结子: unique symbol = Symbol()
6
+ type 终结子 = typeof 终结子
7
+ const 起始子: unique symbol = Symbol()
8
+ type 起始子 = typeof 起始子
9
+ const 节点: unique symbol = Symbol()
10
+ type 节点 = typeof 节点
11
+ type 非空数组<T> = [T, ...T[]]
12
+
13
+ export type 字典树 = {
14
+ [值]: 起始节点 | 终结节点 | 普通节点
15
+ }
16
+
17
+ type 起始节点 = {
18
+ [类型]: 起始子
19
+ }
20
+ type 终结节点 = {
21
+ [类型]: 终结子
22
+ }
23
+ type 普通节点 = {
24
+ [类型]: 节点
25
+ [当前值]: string
26
+ [子节点]: 非空数组<普通节点 | 终结节点>
27
+ }
28
+
29
+ export function 创建字典树(): 字典树 {
30
+ return { [值]: { [类型]: 起始子 } }
31
+ }
32
+ function 创建字典树节点(字符: string, 子节点对象: 非空数组<普通节点 | 终结节点>): 普通节点 {
33
+ return {
34
+ [类型]: 节点,
35
+ [当前值]: 字符,
36
+ [子节点]: 子节点对象,
37
+ }
38
+ }
39
+ function 创建终结子(): 终结节点 {
40
+ return {
41
+ [类型]: 终结子,
42
+ }
43
+ }
44
+
45
+ function 取值(a: 普通节点): string {
46
+ return a[当前值]
47
+ }
48
+
49
+ function 查询字符(a: 普通节点, 字符: string): 普通节点 | null {
50
+ var c = a[子节点].filter((a) => a[类型] != 终结子 && 取值(a) == 字符)
51
+ if (c.length == 0) return null
52
+ if (c[0][类型] == 终结子) throw new Error('意外的终结子')
53
+ return c[0]
54
+ }
55
+
56
+ function 构造链(s: string): 普通节点 {
57
+ if (s.length == 0) throw new Error('不能构造空链')
58
+ var arr = s.split('').reverse()
59
+
60
+ var r: 普通节点 | 终结节点 = 创建终结子()
61
+ for (var a of arr) {
62
+ r = 创建字典树节点(a, [r])
63
+ }
64
+
65
+ if (r[类型] == 终结子) throw new Error('意外的空链')
66
+
67
+ return r
68
+ }
69
+
70
+ export function 插入字典树(a: 字典树, s: string): void {
71
+ if (a[值][类型] == 终结子) throw new Error('不能对终结子插入字符')
72
+ if (a[值][类型] == 起始子) {
73
+ if (s.length == 0) throw new Error('不能对起始子插入空字符串')
74
+ a[值] = 构造链(s)
75
+ return
76
+ }
77
+
78
+ _插入字典树(a[值], s)
79
+ }
80
+
81
+ function _插入字典树(a: 普通节点, s: string): void {
82
+ if (s.length == 0) return
83
+
84
+ var 第一个字符 = s.substring(0, 1)
85
+ var 剩下的字符串 = s.substring(1)
86
+
87
+ var 新子节点 = 查询字符(a, 第一个字符)
88
+ if (新子节点 == null) {
89
+ 新子节点 = 构造链(s)
90
+ a[子节点].push(新子节点)
91
+ return
92
+ }
93
+
94
+ _插入字典树(新子节点, 剩下的字符串)
95
+ }
96
+
97
+ function 直接含有终止子和普通节点(a: 普通节点): boolean {
98
+ var c = a[子节点].filter((a) => a[类型] == 终结子)
99
+ if (c.length != 0 && a[子节点].length != 1) return true
100
+ return false
101
+ }
102
+ function 只含有终止子(a: 普通节点): boolean {
103
+ if (a[子节点].length == 1 && a[子节点][0][类型] == 终结子) return true
104
+ return false
105
+ }
106
+
107
+ function 枚举到终结子(a: 普通节点 | 终结节点): string[] {
108
+ if (a[类型] == 终结子) return []
109
+ if (只含有终止子(a)) return [a[当前值]]
110
+ if (直接含有终止子和普通节点(a)) {
111
+ return [
112
+ a[当前值],
113
+ ...a[子节点]
114
+ .map(枚举到终结子)
115
+ .flat()
116
+ .map((x) => a[当前值] + x),
117
+ ]
118
+ }
119
+ return a[子节点]
120
+ .map(枚举到终结子)
121
+ .flat()
122
+ .map((x) => a[当前值] + x)
123
+ }
124
+
125
+ function _查询字典树(a: 普通节点, s: string, 累计字符串: string = ''): string[] {
126
+ if (s.length == 0) return 枚举到终结子(a).map((x) => 累计字符串.substring(0, 累计字符串.length - 1) + x)
127
+
128
+ var 第一个字符 = s.substring(0, 1)
129
+ var 剩下的字符串 = s.substring(1)
130
+
131
+ var 命中节点 = 查询字符(a, 第一个字符)
132
+ if (命中节点 == null) return []
133
+ return _查询字典树(命中节点, 剩下的字符串, 累计字符串 + 第一个字符)
134
+ }
135
+
136
+ export function 查询字典树(a: 字典树, s: string): string[] {
137
+ if (s == '') throw new Error('不能查询空字符串')
138
+ if (a[值][类型] == 终结子) throw new Error('不能对终结子查询')
139
+ if (a[值][类型] == 起始子) return []
140
+ return _查询字典树(a[值], s)
141
+ }
@@ -0,0 +1,27 @@
1
+ import 'mocha'
2
+ import { 创建字典树, 插入字典树, 查询字典树 } from '../src/Index'
3
+
4
+ function 断言相等(a: any, b: any) {
5
+ if (JSON.stringify(a) == JSON.stringify(b)) return
6
+ throw new Error(`${JSON.stringify(a)} 不等于 ${JSON.stringify(b)}`)
7
+ }
8
+
9
+ it('测试', function () {
10
+ var obj = 创建字典树()
11
+ 插入字典树(obj, 'ni')
12
+ 插入字典树(obj, 'ni1')
13
+ 插入字典树(obj, 'ni2')
14
+ 插入字典树(obj, 'ni3')
15
+ 插入字典树(obj, 'ni45')
16
+ var c = 查询字典树(obj, 'ni')
17
+ 断言相等(c, ['ni1', 'ni2', 'ni3', 'ni45'])
18
+
19
+ var obj = 创建字典树()
20
+ 插入字典树(obj, 'n')
21
+ 插入字典树(obj, 'ni')
22
+ 插入字典树(obj, 'nih')
23
+ 插入字典树(obj, 'niha')
24
+ 插入字典树(obj, 'nihao')
25
+ var c = 查询字典树(obj, 'ni')
26
+ 断言相等(c, ['ni', 'nih', 'niha', 'nihao'])
27
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "include": ["src/**/*", "tools/**/*", "test/**/*"],
3
+ "compilerOptions": {
4
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
5
+ /* Basic Options */
6
+ "noEmitOnError": false,
7
+ // "incremental": true, /* Enable incremental compilation */
8
+ "target": "ES2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
9
+ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
10
+ // "lib": [], /* Specify library files to be included in the compilation. */
11
+ // "allowJs": true, /* Allow javascript files to be compiled. */
12
+ // "checkJs": true, /* Report errors in .js files. */
13
+ "jsx": "preserve" /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */,
14
+ "declaration": true /* Generates corresponding '.d.ts' file. */,
15
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
16
+ "sourceMap": true /* Generates corresponding '.map' file. */,
17
+ // "outFile": "./", /* Concatenate and emit output to single file. */
18
+ "outDir": "./dist" /* Redirect output structure to the directory. */,
19
+ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
20
+ // "composite": true, /* Enable project compilation */
21
+ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
22
+ // "removeComments": true, /* Do not emit comments to output. */
23
+ // "noEmit": true, /* Do not emit outputs. */
24
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
25
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
26
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
27
+ /* Strict Type-Checking Options */
28
+ "strict": true /* Enable all strict type-checking options. */,
29
+ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
30
+ "strictNullChecks": true /* Enable strict null checks. */,
31
+ "strictFunctionTypes": true /* Enable strict checking of function types. */,
32
+ "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
33
+ "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
34
+ "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
35
+ "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
36
+ /* Additional Checks */
37
+ // "noUnusedLocals": true, /* Report errors on unused locals. */
38
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
39
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
40
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
41
+ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
42
+ // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
43
+ /* Module Resolution Options */
44
+ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
45
+ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
46
+ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47
+ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
48
+ // "typeRoots": [], /* List of folders to include type definitions from. */
49
+ // "types": [], /* Type declaration files to be included in compilation. */
50
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
51
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
52
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
53
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
54
+ /* Source Map Options */
55
+ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
56
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
57
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
58
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
59
+ /* Experimental Options */
60
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
61
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
62
+ /* Advanced Options */
63
+ "skipLibCheck": true /* Skip type checking of declaration files. */,
64
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
65
+ }
66
+ }
@@ -0,0 +1,68 @@
1
+ var path = require('path')
2
+ var { VueLoaderPlugin } = require('vue-loader')
3
+ var HtmlWebpackPlugin = require('html-webpack-plugin')
4
+ var EventHooksPlugin = require('event-hooks-webpack-plugin')
5
+ var { PromiseTask } = require('event-hooks-webpack-plugin/lib/tasks')
6
+ var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
7
+ var { merge } = require('webpack-merge')
8
+
9
+ var 配置 = {
10
+ entry: path.resolve(__dirname, '../src/Web.ts'),
11
+ output: {
12
+ filename: 'bundle.js',
13
+ path: path.resolve(__dirname, '../dist/web'),
14
+ },
15
+ module: {
16
+ rules: [
17
+ {
18
+ test: /\.ts$/,
19
+ exclude: /node_modules/,
20
+ loader: 'ts-loader',
21
+ options: {
22
+ transpileOnly: true,
23
+ appendTsSuffixTo: [/\.vue$/],
24
+ },
25
+ },
26
+ {
27
+ test: /\.vue$/,
28
+ loader: 'vue-loader',
29
+ options: {
30
+ esModule: true,
31
+ },
32
+ },
33
+ {
34
+ test: /\.css$/,
35
+ use: ['style-loader', 'css-loader'],
36
+ },
37
+ ],
38
+ },
39
+ resolve: {
40
+ extensions: ['.tsx', '.ts', '.js'],
41
+ },
42
+ plugins: [
43
+ new VueLoaderPlugin(),
44
+ new HtmlWebpackPlugin({
45
+ template: path.resolve(__dirname, '../index.html'),
46
+ filename: 'index.html',
47
+ }),
48
+ new EventHooksPlugin({
49
+ run: new PromiseTask(async () => {
50
+ console.log('=====start=====')
51
+ }),
52
+ watchRun: new PromiseTask(async () => {
53
+ console.log('=====start=====')
54
+ }),
55
+ done: new PromiseTask(async () => {
56
+ setTimeout(() => {
57
+ console.log('=====end=====')
58
+ }, 0)
59
+ }),
60
+ }),
61
+ ],
62
+ }
63
+ if (process.env.use_analyzer) {
64
+ 配置 = merge(配置, {
65
+ plugins: [new BundleAnalyzerPlugin()],
66
+ })
67
+ }
68
+ module.exports = 配置
@@ -0,0 +1,15 @@
1
+ var base = require('./webpack.config.base.js')
2
+ var { DefinePlugin } = require('webpack')
3
+ var { merge } = require('webpack-merge')
4
+
5
+ module.exports = merge(base, {
6
+ watch: true,
7
+ devtool: 'source-map',
8
+ mode: 'development',
9
+ plugins: [
10
+ new DefinePlugin({
11
+ __VUE_OPTIONS_API__: true,
12
+ __VUE_PROD_DEVTOOLS__: true,
13
+ }),
14
+ ],
15
+ })
@@ -0,0 +1,15 @@
1
+ var base = require('./webpack.config.base.js')
2
+ var { CleanWebpackPlugin } = require('clean-webpack-plugin')
3
+ var { DefinePlugin } = require('webpack')
4
+ var { merge } = require('webpack-merge')
5
+
6
+ module.exports = merge(base, {
7
+ mode: 'production',
8
+ plugins: [
9
+ new CleanWebpackPlugin(),
10
+ new DefinePlugin({
11
+ __VUE_OPTIONS_API__: false,
12
+ __VUE_PROD_DEVTOOLS__: false,
13
+ }),
14
+ ],
15
+ })