@likec4/language-server 0.2.2 → 0.4.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/ast.d.ts +0 -1
- package/dist/generated/ast.d.ts +11 -2
- package/dist/generated/ast.js +14 -1
- package/dist/generated/grammar.js +138 -14
- package/dist/lsp/DocumentSymbolProvider.d.ts +0 -1
- package/dist/lsp/DocumentSymbolProvider.js +2 -1
- package/dist/lsp/SemanticTokenProvider.js +4 -0
- package/dist/model/model-builder.js +10 -4
- package/dist/validation/element.d.ts +0 -1
- package/package.json +4 -4
package/dist/ast.d.ts
CHANGED
package/dist/generated/ast.d.ts
CHANGED
|
@@ -21,9 +21,10 @@ export type ThemeColor = 'muted' | 'primary' | 'secondary';
|
|
|
21
21
|
export type View = ElementView;
|
|
22
22
|
export declare const View = "View";
|
|
23
23
|
export declare function isView(item: unknown): item is View;
|
|
24
|
-
export type ViewRule = ViewRuleExpression | ViewRuleStyle;
|
|
24
|
+
export type ViewRule = ViewRuleAutoLayout | ViewRuleExpression | ViewRuleStyle;
|
|
25
25
|
export declare const ViewRule = "ViewRule";
|
|
26
26
|
export declare function isViewRule(item: unknown): item is ViewRule;
|
|
27
|
+
export type ViewRuleLayoutDirection = 'BT' | 'LR' | 'RL' | 'TB';
|
|
27
28
|
export interface ColorProperty extends AstNode {
|
|
28
29
|
readonly $container: ElementStyleProperty | SpecificationElementKindStyle | ViewRuleStyle;
|
|
29
30
|
readonly $type: 'ColorProperty';
|
|
@@ -38,7 +39,7 @@ export interface Element extends AstNode {
|
|
|
38
39
|
body?: ElementBody;
|
|
39
40
|
kind: Reference<ElementKind>;
|
|
40
41
|
name: Name;
|
|
41
|
-
|
|
42
|
+
props: Array<string>;
|
|
42
43
|
}
|
|
43
44
|
export declare const Element = "Element";
|
|
44
45
|
export declare function isElement(item: unknown): item is Element;
|
|
@@ -262,6 +263,13 @@ export interface ViewProperty extends AstNode {
|
|
|
262
263
|
}
|
|
263
264
|
export declare const ViewProperty = "ViewProperty";
|
|
264
265
|
export declare function isViewProperty(item: unknown): item is ViewProperty;
|
|
266
|
+
export interface ViewRuleAutoLayout extends AstNode {
|
|
267
|
+
readonly $container: ElementView;
|
|
268
|
+
readonly $type: 'ViewRuleAutoLayout';
|
|
269
|
+
direction: ViewRuleLayoutDirection;
|
|
270
|
+
}
|
|
271
|
+
export declare const ViewRuleAutoLayout = "ViewRuleAutoLayout";
|
|
272
|
+
export declare function isViewRuleAutoLayout(item: unknown): item is ViewRuleAutoLayout;
|
|
265
273
|
export interface ViewRuleExpression extends AstNode {
|
|
266
274
|
readonly $container: ElementView;
|
|
267
275
|
readonly $type: 'ViewRuleExpression';
|
|
@@ -333,6 +341,7 @@ export interface LikeC4AstType {
|
|
|
333
341
|
View: View;
|
|
334
342
|
ViewProperty: ViewProperty;
|
|
335
343
|
ViewRule: ViewRule;
|
|
344
|
+
ViewRuleAutoLayout: ViewRuleAutoLayout;
|
|
336
345
|
ViewRuleExpression: ViewRuleExpression;
|
|
337
346
|
ViewRuleStyle: ViewRuleStyle;
|
|
338
347
|
WildcardExpression: WildcardExpression;
|
package/dist/generated/ast.js
CHANGED
|
@@ -148,6 +148,10 @@ export const ViewProperty = 'ViewProperty';
|
|
|
148
148
|
export function isViewProperty(item) {
|
|
149
149
|
return reflection.isInstance(item, ViewProperty);
|
|
150
150
|
}
|
|
151
|
+
export const ViewRuleAutoLayout = 'ViewRuleAutoLayout';
|
|
152
|
+
export function isViewRuleAutoLayout(item) {
|
|
153
|
+
return reflection.isInstance(item, ViewRuleAutoLayout);
|
|
154
|
+
}
|
|
151
155
|
export const ViewRuleExpression = 'ViewRuleExpression';
|
|
152
156
|
export function isViewRuleExpression(item) {
|
|
153
157
|
return reflection.isInstance(item, ViewRuleExpression);
|
|
@@ -166,7 +170,7 @@ export function isRelationWithSource(item) {
|
|
|
166
170
|
}
|
|
167
171
|
export class LikeC4AstReflection extends AbstractAstReflection {
|
|
168
172
|
getAllTypes() {
|
|
169
|
-
return ['AStyleProperty', 'ColorProperty', 'Element', 'ElementBody', 'ElementExpression', 'ElementKind', 'ElementProperty', 'ElementRef', 'ElementRefExpression', 'ElementStringProperty', 'ElementStyleProperty', 'ElementView', 'Expression', 'ExtendElement', 'ExtendElementBody', 'InOutExpression', 'IncomingExpression', 'LikeC4Document', 'Model', 'ModelViews', 'OutgoingExpression', 'Relation', 'RelationBody', 'RelationExpression', 'RelationProperty', 'RelationWithSource', 'ShapeProperty', 'SpecificationElementKind', 'SpecificationElementKindStyle', 'SpecificationRule', 'SpecificationTag', 'StrictElementRef', 'Tag', 'Tags', 'View', 'ViewProperty', 'ViewRule', 'ViewRuleExpression', 'ViewRuleStyle', 'WildcardExpression'];
|
|
173
|
+
return ['AStyleProperty', 'ColorProperty', 'Element', 'ElementBody', 'ElementExpression', 'ElementKind', 'ElementProperty', 'ElementRef', 'ElementRefExpression', 'ElementStringProperty', 'ElementStyleProperty', 'ElementView', 'Expression', 'ExtendElement', 'ExtendElementBody', 'InOutExpression', 'IncomingExpression', 'LikeC4Document', 'Model', 'ModelViews', 'OutgoingExpression', 'Relation', 'RelationBody', 'RelationExpression', 'RelationProperty', 'RelationWithSource', 'ShapeProperty', 'SpecificationElementKind', 'SpecificationElementKindStyle', 'SpecificationRule', 'SpecificationTag', 'StrictElementRef', 'Tag', 'Tags', 'View', 'ViewProperty', 'ViewRule', 'ViewRuleAutoLayout', 'ViewRuleExpression', 'ViewRuleStyle', 'WildcardExpression'];
|
|
170
174
|
}
|
|
171
175
|
computeIsSubtype(subtype, supertype) {
|
|
172
176
|
switch (subtype) {
|
|
@@ -195,6 +199,7 @@ export class LikeC4AstReflection extends AbstractAstReflection {
|
|
|
195
199
|
case RelationWithSource: {
|
|
196
200
|
return this.isSubtype(Relation, supertype);
|
|
197
201
|
}
|
|
202
|
+
case ViewRuleAutoLayout:
|
|
198
203
|
case ViewRuleExpression:
|
|
199
204
|
case ViewRuleStyle: {
|
|
200
205
|
return this.isSubtype(ViewRule, supertype);
|
|
@@ -224,6 +229,14 @@ export class LikeC4AstReflection extends AbstractAstReflection {
|
|
|
224
229
|
}
|
|
225
230
|
getTypeMetaData(type) {
|
|
226
231
|
switch (type) {
|
|
232
|
+
case 'Element': {
|
|
233
|
+
return {
|
|
234
|
+
name: 'Element',
|
|
235
|
+
mandatory: [
|
|
236
|
+
{ name: 'props', type: 'array' }
|
|
237
|
+
]
|
|
238
|
+
};
|
|
239
|
+
}
|
|
227
240
|
case 'ElementBody': {
|
|
228
241
|
return {
|
|
229
242
|
name: 'ElementBody',
|
|
@@ -892,23 +892,77 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
892
892
|
},
|
|
893
893
|
"deprecatedSyntax": false
|
|
894
894
|
}
|
|
895
|
+
}
|
|
896
|
+
]
|
|
897
|
+
}
|
|
898
|
+
]
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
"$type": "Group",
|
|
902
|
+
"elements": [
|
|
903
|
+
{
|
|
904
|
+
"$type": "Assignment",
|
|
905
|
+
"feature": "props",
|
|
906
|
+
"operator": "+=",
|
|
907
|
+
"terminal": {
|
|
908
|
+
"$type": "RuleCall",
|
|
909
|
+
"rule": {
|
|
910
|
+
"$ref": "#/rules@22"
|
|
895
911
|
},
|
|
912
|
+
"arguments": []
|
|
913
|
+
}
|
|
914
|
+
},
|
|
915
|
+
{
|
|
916
|
+
"$type": "Group",
|
|
917
|
+
"elements": [
|
|
896
918
|
{
|
|
897
919
|
"$type": "Assignment",
|
|
898
|
-
"feature": "
|
|
899
|
-
"operator": "
|
|
920
|
+
"feature": "props",
|
|
921
|
+
"operator": "+=",
|
|
900
922
|
"terminal": {
|
|
901
923
|
"$type": "RuleCall",
|
|
902
924
|
"rule": {
|
|
903
925
|
"$ref": "#/rules@22"
|
|
904
926
|
},
|
|
905
927
|
"arguments": []
|
|
906
|
-
}
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"$type": "Group",
|
|
932
|
+
"elements": [
|
|
933
|
+
{
|
|
934
|
+
"$type": "Assignment",
|
|
935
|
+
"feature": "props",
|
|
936
|
+
"operator": "+=",
|
|
937
|
+
"terminal": {
|
|
938
|
+
"$type": "RuleCall",
|
|
939
|
+
"rule": {
|
|
940
|
+
"$ref": "#/rules@22"
|
|
941
|
+
},
|
|
942
|
+
"arguments": []
|
|
943
|
+
}
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
"$type": "Assignment",
|
|
947
|
+
"feature": "props",
|
|
948
|
+
"operator": "+=",
|
|
949
|
+
"terminal": {
|
|
950
|
+
"$type": "RuleCall",
|
|
951
|
+
"rule": {
|
|
952
|
+
"$ref": "#/rules@22"
|
|
953
|
+
},
|
|
954
|
+
"arguments": []
|
|
955
|
+
},
|
|
956
|
+
"cardinality": "?"
|
|
957
|
+
}
|
|
958
|
+
],
|
|
907
959
|
"cardinality": "?"
|
|
908
960
|
}
|
|
909
|
-
]
|
|
961
|
+
],
|
|
962
|
+
"cardinality": "?"
|
|
910
963
|
}
|
|
911
|
-
]
|
|
964
|
+
],
|
|
965
|
+
"cardinality": "?"
|
|
912
966
|
},
|
|
913
967
|
{
|
|
914
968
|
"$type": "Assignment",
|
|
@@ -1864,7 +1918,14 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1864
1918
|
{
|
|
1865
1919
|
"$type": "RuleCall",
|
|
1866
1920
|
"rule": {
|
|
1867
|
-
"$ref": "#/rules@
|
|
1921
|
+
"$ref": "#/rules@49"
|
|
1922
|
+
},
|
|
1923
|
+
"arguments": []
|
|
1924
|
+
},
|
|
1925
|
+
{
|
|
1926
|
+
"$type": "RuleCall",
|
|
1927
|
+
"rule": {
|
|
1928
|
+
"$ref": "#/rules@48"
|
|
1868
1929
|
},
|
|
1869
1930
|
"arguments": []
|
|
1870
1931
|
}
|
|
@@ -1908,7 +1969,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1908
1969
|
"terminal": {
|
|
1909
1970
|
"$type": "RuleCall",
|
|
1910
1971
|
"rule": {
|
|
1911
|
-
"$ref": "#/rules@
|
|
1972
|
+
"$ref": "#/rules@50"
|
|
1912
1973
|
},
|
|
1913
1974
|
"arguments": []
|
|
1914
1975
|
}
|
|
@@ -1930,7 +1991,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1930
1991
|
"terminal": {
|
|
1931
1992
|
"$type": "RuleCall",
|
|
1932
1993
|
"rule": {
|
|
1933
|
-
"$ref": "#/rules@
|
|
1994
|
+
"$ref": "#/rules@50"
|
|
1934
1995
|
},
|
|
1935
1996
|
"arguments": []
|
|
1936
1997
|
}
|
|
@@ -1947,6 +2008,69 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1947
2008
|
"parameters": [],
|
|
1948
2009
|
"wildcard": false
|
|
1949
2010
|
},
|
|
2011
|
+
{
|
|
2012
|
+
"$type": "ParserRule",
|
|
2013
|
+
"name": "ViewRuleLayoutDirection",
|
|
2014
|
+
"dataType": "string",
|
|
2015
|
+
"definition": {
|
|
2016
|
+
"$type": "Alternatives",
|
|
2017
|
+
"elements": [
|
|
2018
|
+
{
|
|
2019
|
+
"$type": "Keyword",
|
|
2020
|
+
"value": "TB"
|
|
2021
|
+
},
|
|
2022
|
+
{
|
|
2023
|
+
"$type": "Keyword",
|
|
2024
|
+
"value": "LR"
|
|
2025
|
+
},
|
|
2026
|
+
{
|
|
2027
|
+
"$type": "Keyword",
|
|
2028
|
+
"value": "BT"
|
|
2029
|
+
},
|
|
2030
|
+
{
|
|
2031
|
+
"$type": "Keyword",
|
|
2032
|
+
"value": "RL"
|
|
2033
|
+
}
|
|
2034
|
+
]
|
|
2035
|
+
},
|
|
2036
|
+
"definesHiddenTokens": false,
|
|
2037
|
+
"entry": false,
|
|
2038
|
+
"fragment": false,
|
|
2039
|
+
"hiddenTokens": [],
|
|
2040
|
+
"parameters": [],
|
|
2041
|
+
"wildcard": false
|
|
2042
|
+
},
|
|
2043
|
+
{
|
|
2044
|
+
"$type": "ParserRule",
|
|
2045
|
+
"name": "ViewRuleAutoLayout",
|
|
2046
|
+
"definition": {
|
|
2047
|
+
"$type": "Group",
|
|
2048
|
+
"elements": [
|
|
2049
|
+
{
|
|
2050
|
+
"$type": "Keyword",
|
|
2051
|
+
"value": "autoLayout"
|
|
2052
|
+
},
|
|
2053
|
+
{
|
|
2054
|
+
"$type": "Assignment",
|
|
2055
|
+
"feature": "direction",
|
|
2056
|
+
"operator": "=",
|
|
2057
|
+
"terminal": {
|
|
2058
|
+
"$type": "RuleCall",
|
|
2059
|
+
"rule": {
|
|
2060
|
+
"$ref": "#/rules@47"
|
|
2061
|
+
},
|
|
2062
|
+
"arguments": []
|
|
2063
|
+
}
|
|
2064
|
+
}
|
|
2065
|
+
]
|
|
2066
|
+
},
|
|
2067
|
+
"definesHiddenTokens": false,
|
|
2068
|
+
"entry": false,
|
|
2069
|
+
"fragment": false,
|
|
2070
|
+
"hiddenTokens": [],
|
|
2071
|
+
"parameters": [],
|
|
2072
|
+
"wildcard": false
|
|
2073
|
+
},
|
|
1950
2074
|
{
|
|
1951
2075
|
"$type": "ParserRule",
|
|
1952
2076
|
"name": "ViewRuleStyle",
|
|
@@ -1964,7 +2088,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1964
2088
|
"terminal": {
|
|
1965
2089
|
"$type": "RuleCall",
|
|
1966
2090
|
"rule": {
|
|
1967
|
-
"$ref": "#/rules@
|
|
2091
|
+
"$ref": "#/rules@51"
|
|
1968
2092
|
},
|
|
1969
2093
|
"arguments": []
|
|
1970
2094
|
}
|
|
@@ -1986,7 +2110,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
1986
2110
|
"terminal": {
|
|
1987
2111
|
"$type": "RuleCall",
|
|
1988
2112
|
"rule": {
|
|
1989
|
-
"$ref": "#/rules@
|
|
2113
|
+
"$ref": "#/rules@51"
|
|
1990
2114
|
},
|
|
1991
2115
|
"arguments": []
|
|
1992
2116
|
}
|
|
@@ -2069,7 +2193,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2069
2193
|
"terminal": {
|
|
2070
2194
|
"$type": "RuleCall",
|
|
2071
2195
|
"rule": {
|
|
2072
|
-
"$ref": "#/rules@
|
|
2196
|
+
"$ref": "#/rules@51"
|
|
2073
2197
|
},
|
|
2074
2198
|
"arguments": []
|
|
2075
2199
|
}
|
|
@@ -2101,7 +2225,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2101
2225
|
{
|
|
2102
2226
|
"$type": "RuleCall",
|
|
2103
2227
|
"rule": {
|
|
2104
|
-
"$ref": "#/rules@
|
|
2228
|
+
"$ref": "#/rules@51"
|
|
2105
2229
|
},
|
|
2106
2230
|
"arguments": []
|
|
2107
2231
|
},
|
|
@@ -2131,7 +2255,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2131
2255
|
"terminal": {
|
|
2132
2256
|
"$type": "RuleCall",
|
|
2133
2257
|
"rule": {
|
|
2134
|
-
"$ref": "#/rules@
|
|
2258
|
+
"$ref": "#/rules@51"
|
|
2135
2259
|
},
|
|
2136
2260
|
"arguments": []
|
|
2137
2261
|
}
|
|
@@ -2200,7 +2324,7 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2200
2324
|
{
|
|
2201
2325
|
"$type": "RuleCall",
|
|
2202
2326
|
"rule": {
|
|
2203
|
-
"$ref": "#/rules@
|
|
2327
|
+
"$ref": "#/rules@52"
|
|
2204
2328
|
},
|
|
2205
2329
|
"arguments": []
|
|
2206
2330
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* This program and the accompanying materials are made available under the
|
|
4
4
|
* terms of the MIT License, which is available in the project root.
|
|
5
5
|
******************************************************************************/
|
|
6
|
-
/// <reference types="react" />
|
|
7
6
|
import { type DocumentSymbolProvider, type MaybePromise } from 'langium';
|
|
8
7
|
import { type DocumentSymbol } from 'vscode-languageserver-protocol';
|
|
9
8
|
import { type LikeC4LangiumDocument, ast } from '../ast';
|
|
@@ -110,7 +110,8 @@ export class LikeC4DocumentSymbolProvider {
|
|
|
110
110
|
return [];
|
|
111
111
|
const name = astElement.name;
|
|
112
112
|
const kind = astElement.kind.$refText;
|
|
113
|
-
|
|
113
|
+
// TODO: return the title as well
|
|
114
|
+
const detail = kind; // + (astElement.title ? ': ' + astElement.title : '').replaceAll('\n', ' ').trim()
|
|
114
115
|
return [{
|
|
115
116
|
kind: SymbolKind.Constructor,
|
|
116
117
|
name: name,
|
|
@@ -188,6 +188,10 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
188
188
|
// keyword('steps')
|
|
189
189
|
// return
|
|
190
190
|
// }
|
|
191
|
+
if (ast.isViewRuleAutoLayout(node)) {
|
|
192
|
+
keyword('autoLayout');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
191
195
|
if (ast.isViewRuleStyle(node)) {
|
|
192
196
|
keyword('style');
|
|
193
197
|
return;
|
|
@@ -181,10 +181,11 @@ export class LikeC4ModelBuilder {
|
|
|
181
181
|
const styleProps = astNode.body?.props.find(ast.isElementStyleProperty)?.props;
|
|
182
182
|
const { color, shape } = toElementStyle(styleProps);
|
|
183
183
|
const astPath = this.getAstNodePath(astNode);
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
let [title, description, technology,] = astNode.props;
|
|
185
|
+
const bodyProps = astNode.body?.props.filter((p) => ast.isElementStringProperty(p)) ?? [];
|
|
186
|
+
title = title ?? bodyProps.find(p => p.key === 'title')?.value;
|
|
187
|
+
description = description ?? bodyProps.find(p => p.key === 'description')?.value;
|
|
188
|
+
technology = technology ?? bodyProps.find(p => p.key === 'technology')?.value;
|
|
188
189
|
return {
|
|
189
190
|
id,
|
|
190
191
|
kind,
|
|
@@ -274,6 +275,11 @@ export class LikeC4ModelBuilder {
|
|
|
274
275
|
}
|
|
275
276
|
};
|
|
276
277
|
}
|
|
278
|
+
if (ast.isViewRuleAutoLayout(astNode)) {
|
|
279
|
+
return {
|
|
280
|
+
autoLayout: astNode.direction
|
|
281
|
+
};
|
|
282
|
+
}
|
|
277
283
|
failExpectedNever(astNode);
|
|
278
284
|
}
|
|
279
285
|
parseElementView(astNode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/language-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://like-c4.dev",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"test:watch": "vitest"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@likec4/core": "0.
|
|
63
|
+
"@likec4/core": "0.4.0",
|
|
64
64
|
"@mobily/ts-belt": "^3.13.1",
|
|
65
65
|
"langium": "^1.1.0",
|
|
66
66
|
"nanoid": "^4.0.2",
|
|
@@ -73,12 +73,12 @@
|
|
|
73
73
|
"vscode-uri": "3.0.7"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@types/node": "^18.15.
|
|
76
|
+
"@types/node": "^18.15.11",
|
|
77
77
|
"@types/object-hash": "^3.0.2",
|
|
78
78
|
"langium-cli": "^1.1.0",
|
|
79
79
|
"npm-run-all": "^4.1.5",
|
|
80
80
|
"typescript": "^5.0.3",
|
|
81
81
|
"vite": "^4.2.1",
|
|
82
|
-
"vitest": "^0.
|
|
82
|
+
"vitest": "^0.30.1"
|
|
83
83
|
}
|
|
84
84
|
}
|