@joyzl/eno 1.0.0

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.
Files changed (3) hide show
  1. package/README.md +124 -0
  2. package/index.js +707 -0
  3. package/package.json +28 -0
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # eno
2
+ 提供HTML标签与数据对象之间的互操作支持。
3
+
4
+ ## 安装
5
+ ``` cmd
6
+ npm install @joyzl/eno
7
+ ```
8
+
9
+ ``` javascript
10
+ import eno from `eno`;
11
+ ```
12
+
13
+ ## 使用
14
+
15
+ ### sets
16
+ 将数据对象(例如从服务器获取的JSON对象)设置到HTML元素以显示数据。
17
+
18
+ 首先建立HTML标签元素如下所示:
19
+ ```html
20
+ <div id="user">
21
+ <span name="realname"></span>
22
+ <span name="birthday"></span>
23
+ </div>
24
+ ```
25
+
26
+ 将数据对象设置到HTML标签元素。
27
+ ```javascript
28
+ let user = {
29
+ realname: "小明",
30
+ birthday: "1992-5-27"
31
+ };
32
+ let div = document.getElementById("user");
33
+ eno.sets(div, user);
34
+ ```
35
+
36
+ 数据对象的字段值将根据HTML标签元素指定的name属性插入到标签中。
37
+ ```html
38
+ <div id="user">
39
+ <span name="realname">小明</span>
40
+ <span name="birthday">1992-5-27</span>
41
+ </div>
42
+ ```
43
+
44
+ ### gets
45
+ 从HTML元素获取JSON对象以获得用户数据。
46
+ 与sets方法的功能正好相反。
47
+
48
+ 假设有以下HTML实例:
49
+ ```html
50
+ <div id="user">
51
+ <span name="realname">小明</span>
52
+ <span name="birthday">1992-5-27</span>
53
+ </div>
54
+ ```
55
+
56
+ 执行gets方法获取数据对象:
57
+ ```javascript
58
+ let values = eno.gets(element);
59
+ //{
60
+ // realname: "小明",
61
+ // birthday: "1992-5-27"
62
+ //}
63
+ ```
64
+
65
+ 获取表单输入值,gets将识别传入参数是否表单。
66
+ ```html
67
+ <form>
68
+ <input type="text" name="user" value="小张"/>
69
+ <input type="text" name="birthday" value="1982-10-30"/>
70
+ </form>
71
+ ```
72
+
73
+ 执行gets方法获取form数据对象:
74
+ ```javascript
75
+ let values = eno.gets(element);
76
+ //{
77
+ // realname: "小张",
78
+ // birthday: "1982-10-30"
79
+ //}
80
+ ```
81
+
82
+
83
+ ### query
84
+ 获取指定URL或当前URL中的查询字符串参数。
85
+
86
+ ```javascript
87
+ // 从当前URL获取参数
88
+ let token = eno.query("token");
89
+
90
+ // 从指定URL获取参数
91
+ let url = "http://www.joyzl.net/test?name=value";
92
+ let value = eno.query(url, "name");
93
+ ```
94
+
95
+ ### select
96
+ 获取符合指定选择器字符串的第一个元素。
97
+
98
+ 在整个文档实例范围中查找:
99
+ ```javascript
100
+ let element = eno.select("#user");
101
+ ```
102
+
103
+ 在指定元素实例范围中查找:
104
+ ```javascript
105
+ let form = eno.select("form");
106
+ let user = eno.select(form, "#user");
107
+ ```
108
+
109
+
110
+ ### selects
111
+ 获取符合指定选择器字符串的所有元素。
112
+
113
+
114
+ 在整个文档实例范围中查找:
115
+ ```javascript
116
+ let elements = eno.selects("#user");
117
+ ```
118
+
119
+
120
+ 在指定元素实例范围中查找:
121
+ ```javascript
122
+ let forms = eno.selects("form");
123
+ let users = eno.selects(form, "#user");
124
+ ```
package/index.js ADDED
@@ -0,0 +1,707 @@
1
+ // HTML5 Node Element
2
+ // Easy Node Object
3
+ // 提供HTML标签与数据对象之间的互操作支持。
4
+
5
+ export default {
6
+ create,
7
+ remove,
8
+
9
+ select,
10
+ selects,
11
+ query,
12
+ on,
13
+
14
+ toggle,
15
+ show,
16
+ hide,
17
+
18
+ gets,
19
+ sets,
20
+ entity,
21
+ action
22
+ }
23
+
24
+ /**
25
+ * 显示单个/多个元素
26
+ * @param {Element} element
27
+ */
28
+ function show(element) {
29
+ if (element) {
30
+ if (element.trim) {
31
+ show(selects(element));
32
+ } else
33
+ if (element.length) {
34
+ for (let i = 0; i < element.length; i++) {
35
+ show(element[i]);
36
+ }
37
+ } else
38
+ if (element.nodeType) {
39
+ element.hidden = false;
40
+ }
41
+ }
42
+ }
43
+ /**
44
+ * 隐藏单个/多个元素
45
+ * @param {Element} element
46
+ */
47
+ function hide(element) {
48
+ if (element) {
49
+ if (element.trim) {
50
+ hide(selects(element));
51
+ } else
52
+ if (element.length) {
53
+ for (let i = 0; i < element.length; i++) {
54
+ hide(element[i]);
55
+ }
56
+ } else
57
+ if (element.nodeType) {
58
+ element.hidden = true;
59
+ }
60
+ }
61
+ }
62
+ /**
63
+ * 切换指定元素显示,其余元素隐藏
64
+ * @param {Object} parent 父级
65
+ * @param {Object} element 要显示的元素
66
+ */
67
+ function toggle(parent, element) {
68
+ if (arguments.length == 1) {
69
+ // toggle(element);
70
+
71
+ }
72
+ if (parent && element) {
73
+ if (parent.trim) {
74
+ parent = select(parent);
75
+ }
76
+ if (element.trim) {
77
+ element = select(element);
78
+ }
79
+ if (element.parentElement != parent) {
80
+ parent.appendChild(element);
81
+ }
82
+ for (let i = 0; i < parent.children.length; i++) {
83
+ if (element == parent.children[i]) {
84
+ parent.children[i].hidden = false;
85
+ } else {
86
+ parent.children[i].hidden = true;
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ /**
93
+ * 在指定元素内/整个文档查找标签
94
+ * @param {Element} element 元素内
95
+ * @param {String} selector 选择器
96
+ */
97
+ function select(element, selector) {
98
+ // 仅指定1个参数
99
+ if (arguments.length == 1) {
100
+ // select(selector);
101
+ selector = element;
102
+ return document.querySelector(selector);
103
+ }
104
+ // 指定了2个参数
105
+ if (arguments.length >= 2) {
106
+ // select(element, selector);
107
+ if (element) {
108
+ if (element.trim) {
109
+ element = document.querySelectorAll(element);
110
+ }
111
+ if (element.nodeType) {
112
+ return element.querySelector(selector);
113
+ } else
114
+ if (Array.isArray(element)) {
115
+ let node;
116
+ for (let i = 0; i < elements.length; i++) {
117
+ node = elements[i].querySelector(selector);
118
+ if (node) {
119
+ return node;
120
+ }
121
+ }
122
+ }
123
+ return null;
124
+ } else {
125
+ return document.querySelector(selector);
126
+ }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * 在指定元素内/整个文档查找标签
132
+ * @param {Element} element 元素内
133
+ * @param {String} selector 选择器
134
+ * @returns {NodeList} 元素集合/空集合
135
+ */
136
+ function selects(element, selector) {
137
+ // 仅指定1个参数
138
+ if (arguments.length == 1) {
139
+ // select(selector);
140
+ selector = element;
141
+ return document.querySelectorAll(selector);
142
+ }
143
+ // 指定了2个参数
144
+ if (arguments.length >= 2) {
145
+ // select(element, selector);
146
+ let nodes, items = new Array();
147
+ if (element.trim) {
148
+ element = document.querySelectorAll(element);
149
+ }
150
+ if (Array.isArray(element)) {
151
+ for (let i = 0; i < element.length; i++) {
152
+ nodes = element[i].querySelectorAll(selector);
153
+ if (nodes && nodes.length) {
154
+ for (let i = 0; i < nodes.length; ++i) {
155
+ items.push(nodes[i]);
156
+ }
157
+ }
158
+ }
159
+ } else {
160
+ nodes = element.querySelectorAll(selector);
161
+ if (nodes && nodes.length) {
162
+ for (let i = 0; i < nodes.length; ++i) {
163
+ items.push(nodes[i]);
164
+ }
165
+ }
166
+ }
167
+ return items;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * 绑定事件
173
+ * @param {Element} element
174
+ * @param {String} selector
175
+ * @param {String} evt
176
+ * @param {Function} listener
177
+ */
178
+ function on(element, selector, evt, listener) {
179
+ if (arguments.length == 3) {
180
+ // on(element/selector, evt, listener);
181
+ listener = evt;
182
+ evt = selector;
183
+ if (element.trim) {
184
+ element = selects(element);
185
+ }
186
+ } else
187
+ if (arguments.length == 4) {
188
+ // on(element, selector, evt, listener);
189
+ element = selects(element, selector);
190
+ } else {
191
+ return;
192
+ }
193
+
194
+ if (Array.isArray(element)) {
195
+ for (let i = 0; i < element.length; i++) {
196
+ element[i].addEventListener(evt, listener);
197
+ }
198
+ } else {
199
+ element.addEventListener(evt, listener);
200
+ }
201
+ }
202
+
203
+ // 这个临时标签用于解析HTML字符串
204
+ const TEMP = document.createElement("div");
205
+
206
+ /**
207
+ * 字符串创建HTML元素;
208
+ * A仅创建;
209
+ * B创建并添加到末尾:append;
210
+ * C创建并替换已有元素:replace;
211
+ * @param {String} parent
212
+ * @param {String} html 字符串形式的HTML内容
213
+ * @param {String} place append/replace
214
+ * @return {Element} 单个/多个元素
215
+ */
216
+ function create(parent, html, place) {
217
+ if (arguments.length == 0) {
218
+ // create();
219
+ return null;
220
+ } else
221
+ if (arguments.length == 1) {
222
+ // create(html);
223
+ html = parent;
224
+ parent = null;
225
+ } else
226
+ if (arguments.length == 2) {
227
+ // create(parent,html);
228
+ place = 'append';
229
+ if (parent) {
230
+ if (parent.nodeType) {} else {
231
+ parent = select(parent);
232
+ }
233
+ } else {
234
+ parent = document.body;
235
+ }
236
+ } else
237
+ if (arguments.length == 3) {
238
+ // create(parent,html,place);
239
+ if (parent) {
240
+ if (parent.nodeType) {} else {
241
+ parent = select(parent);
242
+ }
243
+ } else {
244
+ parent = document.body;
245
+ }
246
+ }
247
+
248
+ // 创建元素
249
+ TEMP.innerHTML = html;
250
+ let element;
251
+ if (TEMP.childElementCount == 1) {
252
+ element = TEMP.children[0];
253
+ element.remove();
254
+ } else
255
+ if (TEMP.childElementCount > 1) {
256
+ element = new Array();
257
+ for (let i = 0; i < TEMP.childElementCount; ++i) {
258
+ element.push(TEMP.children[i]);
259
+ TEMP.children[i].remove();
260
+ }
261
+ } else {
262
+ return null;
263
+ }
264
+
265
+ // 添加元素到文档
266
+ if (parent) {
267
+ if ("append" === place) {
268
+ if (element.length) {
269
+ for (let i = 0; i < element.length; i++) {
270
+ parent.appendChild(element[i]);
271
+ }
272
+ } else {
273
+ parent.appendChild(element);
274
+ }
275
+ } else
276
+ if ("replace" === place) {
277
+ if (parent.parentElement) {
278
+ if (element.length) {
279
+ // 待验证
280
+ parent.parentElement.replaceWith(element);
281
+ } else {
282
+ parent.parentElement.replaceChild(parent, element);
283
+ }
284
+ }
285
+ } else {
286
+ console.error("eno.create 不明确的参数" + place);
287
+ }
288
+ }
289
+ return element;
290
+ }
291
+
292
+ /**
293
+ * 从文档移除一个或多个元素
294
+ * @param {Element} element 元素/元素数组
295
+ */
296
+ function remove(element) {
297
+ if (element) {
298
+ if (element.trim) {
299
+ // remove("p");
300
+ element = selects(element);
301
+ }
302
+ if (element.tagName) {
303
+ // remove(document.getElementById("test"));
304
+ element.remove();
305
+ } else
306
+ if (element.length) {
307
+ // remove(["p","span"]);
308
+ // remove(document.getElementByTagName("div"));
309
+ for (let i = 0; i < element.length; i++) {
310
+ remove(element[i]);
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ /**
317
+ * 读取 URL 中的 Query String 参数值
318
+ * @param {String} name 参数名
319
+ */
320
+ function query(url, name) {
321
+ if (arguments.length == 1) {
322
+ // getQueryString(name)
323
+ name = url;
324
+ // window.location.search 返回从问号?开始的URL查询部分
325
+ // ?name1=value1&name2=value2
326
+ url = window.location.search;
327
+ }
328
+ if (arguments.length == 2) {
329
+ // getQueryString(url, name)
330
+ let index = url.indexof("?");
331
+ if (index > 0) {
332
+ url = url.substring(index);
333
+ } else {
334
+ return null;
335
+ }
336
+ }
337
+
338
+ if (url) {
339
+ let start = url.indexOf(name);
340
+ if (start >= 0) {
341
+ start += name.length;
342
+ if (url.charAt(start) == '=') {
343
+ start++;
344
+ let end = url.indexOf('&', start);
345
+ if (end >= 0) {
346
+ return url.substring(start, end);
347
+ }
348
+ return url.substring(start);
349
+ }
350
+ }
351
+ }
352
+ return null;
353
+ }
354
+
355
+ // 默认转换函数
356
+ function defaultConverter(element, parameter, name) {}
357
+
358
+ /**
359
+ * 从指定元素获取值以JSON对象返回{name:value}
360
+ * @param {Element} element 元素
361
+ * @param {Function} converter 转换
362
+ * @returns {Object} {name1:value1,name2:value2,...}
363
+ */
364
+ function gets(element, converter = defaultConverter) {
365
+ if (element) {
366
+ if (element.trim) {
367
+ element = selects(element);
368
+ }
369
+ if (Array.isArray(element)) {
370
+ let parameter = {},
371
+ parameters = new Array();
372
+ for (let i = 0; i < element.length; i++) {
373
+ get(element[i], parameter, converter);
374
+ if (Object.keys(parameter).length) {
375
+ parameters.push(parameter);
376
+ parameter = {};
377
+ }
378
+ }
379
+ return parameters;
380
+ } else {
381
+ let parameter = {};
382
+ get(element, parameter, converter);
383
+ return parameter;
384
+ }
385
+ }
386
+ }
387
+ /**
388
+ * 从指定JSON设置元素值,以name属性作为标识
389
+ * @param {Element} element 元素
390
+ * @param {Object} parameter 对象
391
+ * @param {Function} converter 转换
392
+ * @returns {Element} element
393
+ */
394
+ function sets(element, parameter, converter = defaultConverter) {
395
+ if (element) {
396
+ if (element.trim) {
397
+ // 元素选择字符串
398
+ element = selects(element);
399
+ if (element.length == 0) {
400
+ return null;
401
+ } else
402
+ if (element.length == 1) {
403
+ element = element[0];
404
+ } else {
405
+ // 多个匹配元素
406
+ }
407
+ }
408
+
409
+ if (parameter) {
410
+ if (Array.isArray(parameter)) {
411
+ // if (element.nodeType) {
412
+ // if (element.childElementCount) {
413
+ // element = element.children;
414
+ // } else {
415
+ // // ???
416
+ // return null;
417
+ // }
418
+ // }
419
+
420
+ let i = 0;
421
+ if (element.ENO_SETS) {
422
+ element.ENO_SETS = element.ENO_SETS + 1;
423
+ } else {
424
+ element.ENO_SETS = 1;
425
+ // ...<template>...
426
+ for (; i < element.children.length; i++) {
427
+ if (element.children[i].content) {
428
+ element.template = element.children[i];
429
+ element.a = ++i;
430
+ element.b = element.children.length - i;
431
+ break;
432
+ }
433
+ }
434
+ }
435
+
436
+ if (element.template) {
437
+ // 已定义模板
438
+ if (parameter.length) { // [a,b]
439
+ let node, n;
440
+ // 构造填充元素
441
+ for (i = 0; i < parameter.length; i++) {
442
+ if (element.a + i < element.children.length - element.b) {
443
+ // 重用已有元素
444
+ for (n = 0; n < element.template.content.childElementCount; n++) {
445
+ node = element.children[element.a + i + n];
446
+ node.userData = parameter[i];
447
+ set(node, parameter[i], converter);
448
+ node.hidden = false;
449
+ }
450
+ } else {
451
+ // 克隆新的元素(DocumentFragment)
452
+ node = element.template.content.cloneNode(true);
453
+ n = i * element.template.content.childElementCount;
454
+ node = element.insertBefore(node, element.children[element.a + n]);
455
+ node = node.children;
456
+ for (n = 0; n < node.length; n++) {
457
+ node[n].userData = parameter[i];
458
+ set(node[n], parameter[i], converter);
459
+ node[n].hidden = false;
460
+ }
461
+ }
462
+ }
463
+ // 移除多余元素
464
+ n = i * element.template.content.childElementCount;
465
+ i = element.a + element.b;
466
+ while (element.children.length > i + n) {
467
+ element.children[element.a + n].remove();
468
+ }
469
+ return element;
470
+ } else { // []
471
+ // 移除多余元素
472
+ i = element.a + element.b;
473
+ while (element.length > i) {
474
+ element[element.a + 1].remove();
475
+ }
476
+ return element;
477
+ }
478
+ } else {
479
+ // 未使用模板
480
+ if (parameter.length) { // [a,b]
481
+ let node;
482
+ // 构造填充元素
483
+ for (i = 0; i < parameter.length; i++) {
484
+ if (i < element.children.length) {
485
+ // 重用已有元素
486
+ node = element.children[i];
487
+ } else if (node) {
488
+ // 克隆新的元素
489
+ node = element.appendChild(node.cloneNode(true));
490
+ } else {
491
+ // 干不了
492
+ continue;
493
+ }
494
+ node.userData = parameter[i];
495
+ set(node, parameter[i], converter);
496
+ node.hidden = false;
497
+ }
498
+ // 移除多余元素
499
+ while (element.children.length > i) {
500
+ element.children[i].remove();
501
+ }
502
+ return element;
503
+ } else { // []
504
+ // 保留模板
505
+ element.children[0].hidden = true;
506
+ // 移除多余元素
507
+ while (element.children.length > 1) {
508
+ element.children[1].remove();
509
+ }
510
+ return element;
511
+ }
512
+ }
513
+ } else { // Object
514
+ if (element.nodeType) {
515
+ element.userData = parameter;
516
+ set(element, parameter, converter);
517
+ return element;
518
+ }
519
+ if (element.length) {
520
+ for (let node, i = 0; i < element.length; i++) {
521
+ node = element[i];
522
+ node.userData = parameter;
523
+ set(node, parameter, converter);
524
+ }
525
+ return element;
526
+ }
527
+ }
528
+ } else { // null / undefine
529
+ if (element.nodeType) {
530
+ element.userData = null;
531
+ set(element, null, converter);
532
+ return element;
533
+ }
534
+ if (element.length) {
535
+ // 保留模板
536
+ element[0].hidden = true;
537
+ // 移除多余元素
538
+ while (element.length > 1) {
539
+ element[1].remove();
540
+ }
541
+ return element;
542
+ }
543
+ }
544
+ }
545
+ }
546
+ /**
547
+ * 获取元素值
548
+ * <input name="AAA" value="123"/>
549
+ * <span name="AAA">123</span>
550
+ * <img name="AAA" src="123"/>
551
+ * <i case="AAA"></i>
552
+ */
553
+ function get(element, parameter, converter) {
554
+ let name = element.getAttribute("case");
555
+ if (name && name.length) {
556
+ converter(element, parameter, name);
557
+ }
558
+ name = element.getAttribute("name");
559
+ if (name && name.length) {
560
+ if (element.form) {
561
+ valu(parameter, name, element.value);
562
+ } else
563
+ if (element.src) {
564
+ valu(parameter, name, element.src);
565
+ } else {
566
+ valu(parameter, name, element.innerText);
567
+ }
568
+ }
569
+ if (element.childElementCount) {
570
+ for (let i = 0; i < element.children.length; i++) {
571
+ get(element.children[i], parameter);
572
+ }
573
+ }
574
+ }
575
+ /**
576
+ * 设置元素值
577
+ * <input name="AAA" value="123"/>
578
+ * <span name="AAA">123</span>
579
+ * <img name="AAA" src="123"/>
580
+ * <i case="AAA"></i>
581
+ */
582
+ function set(element, parameter, converter) {
583
+ let name = element.getAttribute("case");
584
+ if (name && name.length) {
585
+ converter(element, parameter, name);
586
+ }
587
+ name = element.getAttribute("name");
588
+ if (name && name.length) {
589
+ if (element.form) {
590
+ element.value = text(vale(parameter, name));
591
+ } else
592
+ if (element.src) {
593
+ element.src = text(vale(parameter, name));
594
+ } else {
595
+ element.innerText = text(vale(parameter, name));
596
+ }
597
+ }
598
+ if (element.childElementCount) {
599
+ for (let i = 0; i < element.children.length; i++) {
600
+ set(element.children[i], parameter, converter);
601
+ }
602
+ }
603
+ }
604
+ /**
605
+ * 根据名称获取对象值
606
+ * @param {Object} o 对象
607
+ * @param {Object} name 名称 "Device.Type.Text"
608
+ * @returns {Object} value 值
609
+ */
610
+ function vale(o, name) {
611
+ name = name.split(".");
612
+ for (let i = 0; i < name.length; i++) {
613
+ if (o) {
614
+ if (Array.isArray(o)) {
615
+ const items = new Array();
616
+ for (let a = 0; a < o.length; a++) {
617
+ if (o[a]) {
618
+ items.push(o[a][name[i]]);
619
+ }
620
+ }
621
+ o = items;
622
+ } else {
623
+ o = o[name[i]];
624
+ }
625
+ } else {
626
+ break;
627
+ }
628
+ }
629
+ return o;
630
+ }
631
+ /**
632
+ * 根据名称设置对象值
633
+ * @param {Object} o
634
+ * @param {Object} name "Device.Type.Text"
635
+ * @param {Object} value
636
+ */
637
+ function valu(o, name, value) {
638
+ name = name.split(".");
639
+ let i = 0;
640
+ for (; i < name.length - 1; i++) {
641
+ if (o) {
642
+ if (o[name[i]]) {
643
+ o = o[name[i]];
644
+ } else {
645
+ o = o[name[i]] = {};
646
+ }
647
+ }
648
+ }
649
+ o[name[i]] = value;
650
+ return o;
651
+ }
652
+ /**
653
+ * 转换为字符串值
654
+ * @param {Object} o
655
+ */
656
+ function text(o) {
657
+ if (Array.isArray(o)) {
658
+ // 数组值合并(逗号分割)
659
+ return o.join(',');
660
+ }
661
+ if (o != undefined) {
662
+ return o.toString();
663
+ }
664
+ return "";
665
+ }
666
+ /**
667
+ * 根据事件或元素获取由sets关联的实体对象
668
+ */
669
+ function entity(e) {
670
+ if (e.target) {
671
+ e = e.target;
672
+ } else
673
+ if (e.srcElement) {
674
+ e = e.srcElement;
675
+ }
676
+
677
+ while (e) {
678
+ if (e.userData) {
679
+ return e.userData;
680
+ } else {
681
+ e = e.parentElement;
682
+ }
683
+ }
684
+ return null;
685
+ }
686
+ /**
687
+ * 根据事件或元素获取属性指定的动作
688
+ * @param {Event} e
689
+ * @param {String} a
690
+ */
691
+ function action(e, a) {
692
+ if (e.target) {
693
+ e = e.target;
694
+ } else
695
+ if (e.srcElement) {
696
+ e = e.srcElement;
697
+ }
698
+
699
+ while (e) {
700
+ if (e.hasAttribute(a)) {
701
+ return true;
702
+ } else {
703
+ e = e.parentElement;
704
+ }
705
+ }
706
+ return false;
707
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@joyzl/eno",
3
+ "version": "1.0.0",
4
+ "description": "Easy Node Object",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/JoyLinks/eno.git"
12
+ },
13
+ "keywords": [
14
+ "eno",
15
+ "webpack",
16
+ "html",
17
+ "json"
18
+ ],
19
+ "author": "ZhangXi",
20
+ "license": "Apache-2.0",
21
+ "bugs": {
22
+ "url": "https://github.com/JoyLinks/eno/issues"
23
+ },
24
+ "homepage": "https://github.com/JoyLinks/eno#readme",
25
+ "devDependencies": {
26
+ "webpack": "^5.91.0"
27
+ }
28
+ }