@niceties/draftlog-appender 1.1.0 → 1.2.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.
- package/dist/core.cjs +40 -39
- package/dist/core.mjs +40 -39
- package/dist/details/model.d.ts +5 -6
- package/dist/index.cjs +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +18 -25
package/dist/core.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var draftlog = require('draftlog');
|
|
6
|
+
var list = require('@slimlib/list');
|
|
6
7
|
|
|
7
8
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
9
|
|
|
@@ -18,13 +19,9 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
18
19
|
updaters.splice(0, model.skipLines_);
|
|
19
20
|
model.skipLines_ = 0;
|
|
20
21
|
}
|
|
21
|
-
if (!model.items_.length) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
22
|
let key = 0, dirty = false;
|
|
25
|
-
const stack = [
|
|
26
|
-
|
|
27
|
-
const item = stack[stack.length - 1].shift();
|
|
23
|
+
const stack = [];
|
|
24
|
+
for (const item of model) {
|
|
28
25
|
let updater = updaters[Number(key)];
|
|
29
26
|
if (!updater) {
|
|
30
27
|
updater = console.draft(' ');
|
|
@@ -39,7 +36,7 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
39
36
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
40
37
|
action: (item.status_ === undefined ? 3 /* log */ : undefined),
|
|
41
38
|
tag: item.tag_
|
|
42
|
-
}, prefix, ident *
|
|
39
|
+
}, prefix, ident * stack.length));
|
|
43
40
|
if (item.dirty_) {
|
|
44
41
|
item.dirty_ = false;
|
|
45
42
|
dirty = true;
|
|
@@ -47,10 +44,13 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
47
44
|
}
|
|
48
45
|
// iterate
|
|
49
46
|
++key;
|
|
50
|
-
if (
|
|
51
|
-
stack
|
|
47
|
+
if (stack[stack.length - 1] === item) {
|
|
48
|
+
stack[stack.length - 1] = null;
|
|
49
|
+
}
|
|
50
|
+
if (item.lastLeaf_) {
|
|
51
|
+
stack.push(item.lastLeaf_);
|
|
52
52
|
}
|
|
53
|
-
while (stack.length && stack[stack.length - 1]
|
|
53
|
+
while (stack.length && stack[stack.length - 1] == null) {
|
|
54
54
|
stack.pop();
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -65,16 +65,12 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function createModel(logAboveSpinners) {
|
|
68
|
-
const model =
|
|
69
|
-
|
|
70
|
-
tick_: 0,
|
|
71
|
-
spinning_: 0,
|
|
72
|
-
items_: []
|
|
73
|
-
};
|
|
68
|
+
const model = new list.List();
|
|
69
|
+
model.tick_ = model.skipLines_ = model.spinning_ = 0;
|
|
74
70
|
const itemById = Object.create(null);
|
|
75
71
|
return [({ message: text, inputId, action, loglevel, ref, parentId, context, tag }) => {
|
|
76
72
|
// item has status undefined, so it is static by default
|
|
77
|
-
const item = { text_: text, loglevel_: loglevel, ref_: ref, parentId_: parentId,
|
|
73
|
+
const item = { text_: text, loglevel_: loglevel, ref_: ref, parentId_: parentId, dirty_: true, context_: context, tag_: tag };
|
|
78
74
|
if (action === 0 /* start */) {
|
|
79
75
|
item.status_ = 1 /* inprogress */;
|
|
80
76
|
}
|
|
@@ -87,15 +83,20 @@ function createModel(logAboveSpinners) {
|
|
|
87
83
|
}
|
|
88
84
|
cleanupModel();
|
|
89
85
|
if (action === 3 /* log */) {
|
|
90
|
-
|
|
86
|
+
appendToModel(item, logAboveSpinners);
|
|
91
87
|
}
|
|
92
88
|
return model;
|
|
93
89
|
}, () => {
|
|
94
90
|
cleanupModel();
|
|
95
91
|
return model;
|
|
96
92
|
}];
|
|
97
|
-
function
|
|
98
|
-
|
|
93
|
+
function appendToModel(item, head) {
|
|
94
|
+
if (head) {
|
|
95
|
+
list.prepend(model, item);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
list.append(model, item);
|
|
99
|
+
}
|
|
99
100
|
model.spinning_ += (item.status_ || 0);
|
|
100
101
|
}
|
|
101
102
|
function updateModel(inputId, options) {
|
|
@@ -105,47 +106,47 @@ function createModel(logAboveSpinners) {
|
|
|
105
106
|
itemById[inputId] = item;
|
|
106
107
|
const itemParentId = item.parentId_;
|
|
107
108
|
if (itemParentId != null) {
|
|
108
|
-
putIntoChildren(itemParentId, item);
|
|
109
|
+
putIntoChildren(itemParentId, item, item);
|
|
109
110
|
}
|
|
110
111
|
else {
|
|
111
|
-
|
|
112
|
+
appendToModel(item, false);
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
else {
|
|
115
116
|
const statusDiff = (options.status_ || 0) - (modelItem.status_ || 0);
|
|
116
|
-
delete options.children_;
|
|
117
117
|
const moveIntoParent = options.parentId_ != null && modelItem.parentId_ == null;
|
|
118
118
|
Object.assign(modelItem, options);
|
|
119
119
|
model.spinning_ += statusDiff;
|
|
120
120
|
if (moveIntoParent) {
|
|
121
|
-
|
|
121
|
+
let lastLeaf = modelItem;
|
|
122
|
+
while (lastLeaf.lastLeaf_) {
|
|
123
|
+
lastLeaf = lastLeaf.lastLeaf_;
|
|
124
|
+
}
|
|
122
125
|
model.spinning_ -= (modelItem.status_ || 0);
|
|
123
126
|
modelItem.dirty_ = true;
|
|
124
|
-
|
|
127
|
+
list.removeRange(modelItem, lastLeaf);
|
|
128
|
+
putIntoChildren(modelItem.parentId_, modelItem, lastLeaf);
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
|
-
function putIntoChildren(itemParentId,
|
|
132
|
+
function putIntoChildren(itemParentId, begin, end) {
|
|
129
133
|
let parent = itemById[itemParentId];
|
|
130
134
|
if (!parent) {
|
|
131
|
-
parent = { inputId_: itemParentId, text_: '',
|
|
132
|
-
|
|
135
|
+
parent = { inputId_: itemParentId, text_: '', loglevel_: 0, ref_: new WeakRef(model) };
|
|
136
|
+
appendToModel(parent, false);
|
|
133
137
|
itemById[itemParentId] = parent;
|
|
134
138
|
}
|
|
135
|
-
parent.
|
|
136
|
-
|
|
139
|
+
list.appendRange((parent.lastLeaf_ || parent), begin, end);
|
|
140
|
+
parent.lastLeaf_ = begin;
|
|
141
|
+
model.spinning_ += (begin.status_ || 0);
|
|
137
142
|
}
|
|
138
143
|
function cleanupModel() {
|
|
139
144
|
var _a;
|
|
140
|
-
for (const item of model
|
|
141
|
-
if (!((_a = item.ref_) === null || _a === void 0 ? void 0 : _a.deref())
|
|
142
|
-
model.skipLines_ += 1
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
do {
|
|
146
|
-
currentItem.inputId_ != null && delete itemById[currentItem.inputId_];
|
|
147
|
-
model.spinning_ -= (currentItem.status_ || 0);
|
|
148
|
-
} while ((currentItem = item.children_.pop()));
|
|
145
|
+
for (const item of model) {
|
|
146
|
+
if (!((_a = item.ref_) === null || _a === void 0 ? void 0 : _a.deref())) {
|
|
147
|
+
model.skipLines_ += 1;
|
|
148
|
+
item.inputId_ != null && delete itemById[item.inputId_];
|
|
149
|
+
list.remove(item);
|
|
149
150
|
}
|
|
150
151
|
else {
|
|
151
152
|
break;
|
package/dist/core.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import draftlog from 'draftlog';
|
|
2
|
+
import { List, prepend, append, removeRange, appendRange, remove } from '@slimlib/list';
|
|
2
3
|
|
|
3
4
|
function createCanvas(spinner, formatter, ident) {
|
|
4
5
|
draftlog(console);
|
|
@@ -10,13 +11,9 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
10
11
|
updaters.splice(0, model.skipLines_);
|
|
11
12
|
model.skipLines_ = 0;
|
|
12
13
|
}
|
|
13
|
-
if (!model.items_.length) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
14
|
let key = 0, dirty = false;
|
|
17
|
-
const stack = [
|
|
18
|
-
|
|
19
|
-
const item = stack[stack.length - 1].shift();
|
|
15
|
+
const stack = [];
|
|
16
|
+
for (const item of model) {
|
|
20
17
|
let updater = updaters[Number(key)];
|
|
21
18
|
if (!updater) {
|
|
22
19
|
updater = console.draft(' ');
|
|
@@ -31,7 +28,7 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
31
28
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
29
|
action: (item.status_ === undefined ? 3 /* log */ : undefined),
|
|
33
30
|
tag: item.tag_
|
|
34
|
-
}, prefix, ident *
|
|
31
|
+
}, prefix, ident * stack.length));
|
|
35
32
|
if (item.dirty_) {
|
|
36
33
|
item.dirty_ = false;
|
|
37
34
|
dirty = true;
|
|
@@ -39,10 +36,13 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
39
36
|
}
|
|
40
37
|
// iterate
|
|
41
38
|
++key;
|
|
42
|
-
if (
|
|
43
|
-
stack
|
|
39
|
+
if (stack[stack.length - 1] === item) {
|
|
40
|
+
stack[stack.length - 1] = null;
|
|
41
|
+
}
|
|
42
|
+
if (item.lastLeaf_) {
|
|
43
|
+
stack.push(item.lastLeaf_);
|
|
44
44
|
}
|
|
45
|
-
while (stack.length && stack[stack.length - 1]
|
|
45
|
+
while (stack.length && stack[stack.length - 1] == null) {
|
|
46
46
|
stack.pop();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -57,16 +57,12 @@ function createCanvas(spinner, formatter, ident) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function createModel(logAboveSpinners) {
|
|
60
|
-
const model =
|
|
61
|
-
|
|
62
|
-
tick_: 0,
|
|
63
|
-
spinning_: 0,
|
|
64
|
-
items_: []
|
|
65
|
-
};
|
|
60
|
+
const model = new List();
|
|
61
|
+
model.tick_ = model.skipLines_ = model.spinning_ = 0;
|
|
66
62
|
const itemById = Object.create(null);
|
|
67
63
|
return [({ message: text, inputId, action, loglevel, ref, parentId, context, tag }) => {
|
|
68
64
|
// item has status undefined, so it is static by default
|
|
69
|
-
const item = { text_: text, loglevel_: loglevel, ref_: ref, parentId_: parentId,
|
|
65
|
+
const item = { text_: text, loglevel_: loglevel, ref_: ref, parentId_: parentId, dirty_: true, context_: context, tag_: tag };
|
|
70
66
|
if (action === 0 /* start */) {
|
|
71
67
|
item.status_ = 1 /* inprogress */;
|
|
72
68
|
}
|
|
@@ -79,15 +75,20 @@ function createModel(logAboveSpinners) {
|
|
|
79
75
|
}
|
|
80
76
|
cleanupModel();
|
|
81
77
|
if (action === 3 /* log */) {
|
|
82
|
-
|
|
78
|
+
appendToModel(item, logAboveSpinners);
|
|
83
79
|
}
|
|
84
80
|
return model;
|
|
85
81
|
}, () => {
|
|
86
82
|
cleanupModel();
|
|
87
83
|
return model;
|
|
88
84
|
}];
|
|
89
|
-
function
|
|
90
|
-
|
|
85
|
+
function appendToModel(item, head) {
|
|
86
|
+
if (head) {
|
|
87
|
+
prepend(model, item);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
append(model, item);
|
|
91
|
+
}
|
|
91
92
|
model.spinning_ += (item.status_ || 0);
|
|
92
93
|
}
|
|
93
94
|
function updateModel(inputId, options) {
|
|
@@ -97,47 +98,47 @@ function createModel(logAboveSpinners) {
|
|
|
97
98
|
itemById[inputId] = item;
|
|
98
99
|
const itemParentId = item.parentId_;
|
|
99
100
|
if (itemParentId != null) {
|
|
100
|
-
putIntoChildren(itemParentId, item);
|
|
101
|
+
putIntoChildren(itemParentId, item, item);
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
|
-
|
|
104
|
+
appendToModel(item, false);
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
else {
|
|
107
108
|
const statusDiff = (options.status_ || 0) - (modelItem.status_ || 0);
|
|
108
|
-
delete options.children_;
|
|
109
109
|
const moveIntoParent = options.parentId_ != null && modelItem.parentId_ == null;
|
|
110
110
|
Object.assign(modelItem, options);
|
|
111
111
|
model.spinning_ += statusDiff;
|
|
112
112
|
if (moveIntoParent) {
|
|
113
|
-
|
|
113
|
+
let lastLeaf = modelItem;
|
|
114
|
+
while (lastLeaf.lastLeaf_) {
|
|
115
|
+
lastLeaf = lastLeaf.lastLeaf_;
|
|
116
|
+
}
|
|
114
117
|
model.spinning_ -= (modelItem.status_ || 0);
|
|
115
118
|
modelItem.dirty_ = true;
|
|
116
|
-
|
|
119
|
+
removeRange(modelItem, lastLeaf);
|
|
120
|
+
putIntoChildren(modelItem.parentId_, modelItem, lastLeaf);
|
|
117
121
|
}
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
|
-
function putIntoChildren(itemParentId,
|
|
124
|
+
function putIntoChildren(itemParentId, begin, end) {
|
|
121
125
|
let parent = itemById[itemParentId];
|
|
122
126
|
if (!parent) {
|
|
123
|
-
parent = { inputId_: itemParentId, text_: '',
|
|
124
|
-
|
|
127
|
+
parent = { inputId_: itemParentId, text_: '', loglevel_: 0, ref_: new WeakRef(model) };
|
|
128
|
+
appendToModel(parent, false);
|
|
125
129
|
itemById[itemParentId] = parent;
|
|
126
130
|
}
|
|
127
|
-
parent.
|
|
128
|
-
|
|
131
|
+
appendRange((parent.lastLeaf_ || parent), begin, end);
|
|
132
|
+
parent.lastLeaf_ = begin;
|
|
133
|
+
model.spinning_ += (begin.status_ || 0);
|
|
129
134
|
}
|
|
130
135
|
function cleanupModel() {
|
|
131
136
|
var _a;
|
|
132
|
-
for (const item of model
|
|
133
|
-
if (!((_a = item.ref_) === null || _a === void 0 ? void 0 : _a.deref())
|
|
134
|
-
model.skipLines_ += 1
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
do {
|
|
138
|
-
currentItem.inputId_ != null && delete itemById[currentItem.inputId_];
|
|
139
|
-
model.spinning_ -= (currentItem.status_ || 0);
|
|
140
|
-
} while ((currentItem = item.children_.pop()));
|
|
137
|
+
for (const item of model) {
|
|
138
|
+
if (!((_a = item.ref_) === null || _a === void 0 ? void 0 : _a.deref())) {
|
|
139
|
+
model.skipLines_ += 1;
|
|
140
|
+
item.inputId_ != null && delete itemById[item.inputId_];
|
|
141
|
+
remove(item);
|
|
141
142
|
}
|
|
142
143
|
else {
|
|
143
144
|
break;
|
package/dist/details/model.d.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { LogLevel, LogMessage } from '@niceties/logger/types';
|
|
2
|
+
import { List, ListNode } from '@slimlib/list';
|
|
2
3
|
export declare const enum ItemStatus {
|
|
3
4
|
finished = 0,
|
|
4
5
|
inprogress = 1
|
|
5
6
|
}
|
|
6
|
-
export interface ModelItem {
|
|
7
|
+
export interface ModelItem extends Partial<ListNode> {
|
|
7
8
|
inputId_?: number;
|
|
8
9
|
text_: string;
|
|
9
10
|
status_?: ItemStatus;
|
|
10
11
|
loglevel_: LogLevel;
|
|
11
12
|
ref_?: WeakRef<never>;
|
|
12
13
|
parentId_?: number;
|
|
13
|
-
tag_?: string;
|
|
14
|
-
next_?: ModelItem;
|
|
15
|
-
children_: ModelItem[];
|
|
16
14
|
dirty_?: boolean;
|
|
15
|
+
lastLeaf_?: ModelItem;
|
|
16
|
+
tag_?: string;
|
|
17
17
|
context_?: any;
|
|
18
18
|
}
|
|
19
|
-
export declare type Model = {
|
|
20
|
-
items_: ModelItem[];
|
|
19
|
+
export declare type Model = List<ModelItem> & {
|
|
21
20
|
skipLines_: number;
|
|
22
21
|
tick_: number;
|
|
23
22
|
spinning_: number;
|
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var defaultFormatting = require('@niceties/logger/default-formatting');
|
|
|
7
7
|
var core = require('./core.cjs');
|
|
8
8
|
var spinners = require('./spinners.cjs');
|
|
9
9
|
require('draftlog');
|
|
10
|
+
require('@slimlib/list');
|
|
10
11
|
|
|
11
12
|
const supportsUnicode = formatUtils.terminalSupportsUnicode();
|
|
12
13
|
const spinner = supportsUnicode ? spinners.dots : spinners.line;
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { colors, unicodePrefixes, asciiPrefixes, tagFactory } from '@niceties/lo
|
|
|
5
5
|
import { createDraftlogAppender } from './core.mjs';
|
|
6
6
|
import { dots, line } from './spinners.mjs';
|
|
7
7
|
import 'draftlog';
|
|
8
|
+
import '@slimlib/list';
|
|
8
9
|
|
|
9
10
|
const supportsUnicode = terminalSupportsUnicode();
|
|
10
11
|
const spinner = supportsUnicode ? dots : line;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.2.0",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@niceties/draftlog-appender",
|
|
5
5
|
"author": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"default": "./dist/core.mjs"
|
|
18
18
|
},
|
|
19
19
|
"./spinners": {
|
|
20
|
-
"require": "./
|
|
21
|
-
"default": "./
|
|
20
|
+
"require": "./dist/spinners.cjs",
|
|
21
|
+
"default": "./dist/spinners.mjs"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"main": "./dist/index.cjs",
|
|
@@ -41,44 +41,37 @@
|
|
|
41
41
|
},
|
|
42
42
|
"homepage": "https://github.com/kshutkin/niceties/blob/main/draftlog-appender/README.md",
|
|
43
43
|
"readme": "README.md",
|
|
44
|
+
"description": "Appender for '@niceites/logger' implemented using draftlog package.",
|
|
44
45
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"dev": "rimraf ./dist && rollup -c -w",
|
|
46
|
+
"build": "pkgbld",
|
|
47
47
|
"test": "node --expose-gc ../node_modules/jest-cli/bin/jest.js --collectCoverage",
|
|
48
48
|
"lint": "eslint ./src",
|
|
49
49
|
"semantic-release": "npx semantic-release"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@rollup/plugin-commonjs": "21.0.1",
|
|
53
|
-
"@rollup/plugin-node-resolve": "13.0.6",
|
|
54
52
|
"@semantic-release/changelog": "6.0.1",
|
|
55
53
|
"@semantic-release/commit-analyzer": "9.0.1",
|
|
56
54
|
"@semantic-release/git": "10.0.1",
|
|
57
55
|
"@semantic-release/npm": "8.0.2",
|
|
58
56
|
"@semantic-release/release-notes-generator": "10.0.2",
|
|
59
|
-
"@types/jest": "27.0
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
61
|
-
"@typescript-eslint/parser": "5.
|
|
57
|
+
"@types/jest": "27.4.0",
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "5.11.0",
|
|
59
|
+
"@typescript-eslint/parser": "5.11.0",
|
|
62
60
|
"conventional-changelog-angular": "5.0.13",
|
|
63
|
-
"eslint": "8.
|
|
64
|
-
"jest": "27.
|
|
65
|
-
"lodash": "4.17.21",
|
|
66
|
-
"rimraf": "3.0.2",
|
|
67
|
-
"rollup": "2.60.1",
|
|
68
|
-
"rollup-plugin-terser": "7.0.2",
|
|
69
|
-
"rollup-plugin-typescript2": "0.31.1",
|
|
70
|
-
"rollup-plugin-preprocess": "0.0.4",
|
|
61
|
+
"eslint": "8.8.0",
|
|
62
|
+
"jest": "27.5.1",
|
|
71
63
|
"semantic-release": "18.0.0",
|
|
72
64
|
"semantic-release-monorepo": "7.0.5",
|
|
73
|
-
"ts-jest": "27.
|
|
74
|
-
"typescript": "4.
|
|
75
|
-
"update-monorepo-package-json": "0.2.0"
|
|
65
|
+
"ts-jest": "27.1.3",
|
|
66
|
+
"typescript": "4.5.x",
|
|
67
|
+
"update-monorepo-package-json": "0.2.0",
|
|
68
|
+
"pkgbld": "1.1.10"
|
|
76
69
|
},
|
|
77
70
|
"peerDependencies": {
|
|
78
|
-
"@niceties/logger": "^1.1.
|
|
71
|
+
"@niceties/logger": "^1.1.1"
|
|
79
72
|
},
|
|
80
73
|
"dependencies": {
|
|
81
|
-
"draftlog": "^1.0.13"
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
"draftlog": "^1.0.13",
|
|
75
|
+
"@slimlib/list": "^1.0.0"
|
|
76
|
+
}
|
|
84
77
|
}
|