volar-service-css 0.0.30 → 0.0.32
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/index.d.ts +16 -5
- package/index.js +206 -105
- package/package.json +5 -5
package/index.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import type { ServicePlugin } from '@volar/language-service';
|
|
1
|
+
import type { Disposable, DocumentSelector, FormattingOptions, Result, ServiceContext, ServicePlugin } from '@volar/language-service';
|
|
2
2
|
import * as css from 'vscode-css-languageservice';
|
|
3
|
-
import
|
|
3
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
4
4
|
export interface Provide {
|
|
5
|
-
'css/stylesheet': (document: TextDocument) => css.Stylesheet
|
|
6
|
-
'css/languageService': (
|
|
5
|
+
'css/stylesheet': (document: TextDocument, ls: css.LanguageService) => css.Stylesheet;
|
|
6
|
+
'css/languageService': (document: TextDocument) => css.LanguageService | undefined;
|
|
7
7
|
}
|
|
8
|
-
export declare function create(
|
|
8
|
+
export declare function create({ cssDocumentSelector, scssDocumentSelector, lessDocumentSelector, useDefaultDataProvider, getDocumentContext, isFormattingEnabled, getFormattingOptions, getLanguageSettings, getCustomData, onDidChangeCustomData, }?: {
|
|
9
|
+
cssDocumentSelector?: DocumentSelector;
|
|
10
|
+
scssDocumentSelector?: DocumentSelector;
|
|
11
|
+
lessDocumentSelector?: DocumentSelector;
|
|
12
|
+
useDefaultDataProvider?: boolean;
|
|
13
|
+
getDocumentContext?(context: ServiceContext): css.DocumentContext;
|
|
14
|
+
isFormattingEnabled?(document: TextDocument, context: ServiceContext): Result<boolean>;
|
|
15
|
+
getFormattingOptions?(document: TextDocument, options: FormattingOptions, context: ServiceContext): Result<css.CSSFormatConfiguration>;
|
|
16
|
+
getLanguageSettings?(document: TextDocument, context: ServiceContext): Result<css.LanguageSettings | undefined>;
|
|
17
|
+
getCustomData?(context: ServiceContext): Result<css.ICSSDataProvider[]>;
|
|
18
|
+
onDidChangeCustomData?(listener: () => void, context: ServiceContext): Disposable;
|
|
19
|
+
}): ServicePlugin;
|
|
9
20
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -2,70 +2,91 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.create = void 0;
|
|
4
4
|
const css = require("vscode-css-languageservice");
|
|
5
|
+
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
|
|
5
6
|
const vscode_uri_1 = require("vscode-uri");
|
|
6
|
-
function create(
|
|
7
|
+
function create({ cssDocumentSelector = ['css'], scssDocumentSelector = ['scss'], lessDocumentSelector = ['less'], useDefaultDataProvider = true, getDocumentContext = context => {
|
|
8
|
+
return {
|
|
9
|
+
resolveReference(ref, base) {
|
|
10
|
+
if (ref.match(/^\w[\w\d+.-]*:/)) {
|
|
11
|
+
// starts with a schema
|
|
12
|
+
return ref;
|
|
13
|
+
}
|
|
14
|
+
if (ref[0] === '/') { // resolve absolute path against the current workspace folder
|
|
15
|
+
let folderUri = context.env.workspaceFolder;
|
|
16
|
+
if (!folderUri.endsWith('/')) {
|
|
17
|
+
folderUri += '/';
|
|
18
|
+
}
|
|
19
|
+
return folderUri + ref.substring(1);
|
|
20
|
+
}
|
|
21
|
+
const baseUri = vscode_uri_1.URI.parse(base);
|
|
22
|
+
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : vscode_uri_1.Utils.dirname(baseUri);
|
|
23
|
+
return vscode_uri_1.Utils.resolvePath(baseUriDir, ref).toString(true);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}, isFormattingEnabled = async (document, context) => {
|
|
27
|
+
return await context.env.getConfiguration?.(document.languageId + '.format.enable') ?? true;
|
|
28
|
+
}, getFormattingOptions = async (document, options, context) => {
|
|
29
|
+
return {
|
|
30
|
+
...options,
|
|
31
|
+
...await context.env.getConfiguration?.(document.languageId + '.format'),
|
|
32
|
+
};
|
|
33
|
+
}, getLanguageSettings = async (document, context) => {
|
|
34
|
+
return await context.env.getConfiguration?.(document.languageId);
|
|
35
|
+
}, getCustomData = async (context) => {
|
|
36
|
+
const customData = await context.env.getConfiguration?.('css.customData') ?? [];
|
|
37
|
+
const newData = [];
|
|
38
|
+
for (const customDataPath of customData) {
|
|
39
|
+
const uri = vscode_uri_1.Utils.resolvePath(vscode_uri_1.URI.parse(context.env.workspaceFolder), customDataPath);
|
|
40
|
+
const json = await context.env.fs?.readFile?.(uri.toString());
|
|
41
|
+
if (json) {
|
|
42
|
+
try {
|
|
43
|
+
const data = JSON.parse(json);
|
|
44
|
+
newData.push(css.newCSSDataProvider(data));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error(error);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return newData;
|
|
52
|
+
}, onDidChangeCustomData = (listener, context) => {
|
|
53
|
+
const disposable = context.env.onDidChangeConfiguration?.(listener);
|
|
54
|
+
return {
|
|
55
|
+
dispose() {
|
|
56
|
+
disposable?.dispose();
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}, } = {}) {
|
|
7
60
|
return {
|
|
8
61
|
name: 'css',
|
|
9
62
|
// https://github.com/microsoft/vscode/blob/09850876e652688fb142e2e19fd00fd38c0bc4ba/extensions/css-language-features/server/src/cssServer.ts#L97
|
|
10
63
|
triggerCharacters: ['/', '-', ':'],
|
|
11
64
|
create(context) {
|
|
12
|
-
let inited = false;
|
|
13
65
|
const stylesheets = new WeakMap();
|
|
14
66
|
const fileSystemProvider = {
|
|
15
|
-
stat: async (uri) => await context.env.fs?.stat(uri)
|
|
16
|
-
type: css.FileType.Unknown,
|
|
17
|
-
ctime: 0,
|
|
18
|
-
mtime: 0,
|
|
19
|
-
size: 0,
|
|
20
|
-
},
|
|
67
|
+
stat: async (uri) => await context.env.fs?.stat(uri)
|
|
68
|
+
?? { type: css.FileType.Unknown, ctime: 0, mtime: 0, size: 0 },
|
|
21
69
|
readDirectory: async (uri) => await context.env.fs?.readDirectory(uri) ?? [],
|
|
22
70
|
};
|
|
23
|
-
const documentContext =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return base + ref;
|
|
31
|
-
}
|
|
32
|
-
const baseUri = vscode_uri_1.URI.parse(base);
|
|
33
|
-
const baseUriDir = baseUri.path.endsWith('/') ? baseUri : vscode_uri_1.Utils.dirname(baseUri);
|
|
34
|
-
return vscode_uri_1.Utils.resolvePath(baseUriDir, ref).toString(true);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
const cssLs = css.getCSSLanguageService({
|
|
38
|
-
fileSystemProvider,
|
|
39
|
-
clientCapabilities: context.env.clientCapabilities,
|
|
40
|
-
});
|
|
41
|
-
const scssLs = css.getSCSSLanguageService({
|
|
42
|
-
fileSystemProvider,
|
|
43
|
-
clientCapabilities: context.env.clientCapabilities,
|
|
44
|
-
});
|
|
45
|
-
const lessLs = css.getLESSLanguageService({
|
|
46
|
-
fileSystemProvider,
|
|
47
|
-
clientCapabilities: context.env.clientCapabilities,
|
|
48
|
-
});
|
|
49
|
-
const postcssLs = {
|
|
50
|
-
...scssLs,
|
|
51
|
-
doValidation: (document, stylesheet, documentSettings) => {
|
|
52
|
-
let errors = scssLs.doValidation(document, stylesheet, documentSettings);
|
|
53
|
-
errors = errors.filter(error => error.code !== 'css-semicolonexpected');
|
|
54
|
-
errors = errors.filter(error => error.code !== 'css-ruleorselectorexpected');
|
|
55
|
-
errors = errors.filter(error => error.code !== 'unknownAtRules');
|
|
56
|
-
return errors;
|
|
57
|
-
},
|
|
58
|
-
};
|
|
71
|
+
const documentContext = getDocumentContext(context);
|
|
72
|
+
const disposable = onDidChangeCustomData(() => initializing = undefined, context);
|
|
73
|
+
let cssLs;
|
|
74
|
+
let scssLs;
|
|
75
|
+
let lessLs;
|
|
76
|
+
let customData = [];
|
|
77
|
+
let initializing;
|
|
59
78
|
return {
|
|
79
|
+
dispose() {
|
|
80
|
+
disposable.dispose();
|
|
81
|
+
},
|
|
60
82
|
provide: {
|
|
61
83
|
'css/stylesheet': getStylesheet,
|
|
62
84
|
'css/languageService': getCssLs,
|
|
63
85
|
},
|
|
64
86
|
async provideCompletionItems(document, position) {
|
|
65
87
|
return worker(document, async (stylesheet, cssLs) => {
|
|
66
|
-
const settings = await
|
|
67
|
-
|
|
68
|
-
return cssResult;
|
|
88
|
+
const settings = await getLanguageSettings(document, context);
|
|
89
|
+
return await cssLs.doComplete2(document, position, stylesheet, documentContext, settings?.completion);
|
|
69
90
|
});
|
|
70
91
|
},
|
|
71
92
|
provideRenameRange(document, position) {
|
|
@@ -97,13 +118,13 @@ function create() {
|
|
|
97
118
|
},
|
|
98
119
|
async provideDiagnostics(document) {
|
|
99
120
|
return worker(document, async (stylesheet, cssLs) => {
|
|
100
|
-
const settings = await
|
|
121
|
+
const settings = await getLanguageSettings(document, context);
|
|
101
122
|
return cssLs.doValidation(document, stylesheet, settings);
|
|
102
123
|
});
|
|
103
124
|
},
|
|
104
125
|
async provideHover(document, position) {
|
|
105
126
|
return worker(document, async (stylesheet, cssLs) => {
|
|
106
|
-
const settings = await
|
|
127
|
+
const settings = await getLanguageSettings(document, context);
|
|
107
128
|
return cssLs.doHover(document, position, stylesheet, settings?.hover);
|
|
108
129
|
});
|
|
109
130
|
},
|
|
@@ -138,8 +159,8 @@ function create() {
|
|
|
138
159
|
});
|
|
139
160
|
},
|
|
140
161
|
provideFoldingRanges(document) {
|
|
141
|
-
return worker(document, (
|
|
142
|
-
return cssLs.getFoldingRanges(document,
|
|
162
|
+
return worker(document, (_stylesheet, cssLs) => {
|
|
163
|
+
return cssLs.getFoldingRanges(document, context.env.clientCapabilities?.textDocument?.foldingRange);
|
|
143
164
|
});
|
|
144
165
|
},
|
|
145
166
|
provideSelectionRanges(document, positions) {
|
|
@@ -147,59 +168,138 @@ function create() {
|
|
|
147
168
|
return cssLs.getSelectionRanges(document, positions, stylesheet);
|
|
148
169
|
});
|
|
149
170
|
},
|
|
150
|
-
async provideDocumentFormattingEdits(document, formatRange, options) {
|
|
171
|
+
async provideDocumentFormattingEdits(document, formatRange, options, codeOptions) {
|
|
151
172
|
return worker(document, async (_stylesheet, cssLs) => {
|
|
152
|
-
|
|
153
|
-
if (options_2?.enable === false) {
|
|
173
|
+
if (!await isFormattingEnabled(document, context)) {
|
|
154
174
|
return;
|
|
155
175
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
176
|
+
const formatOptions = await getFormattingOptions(document, options, context);
|
|
177
|
+
let formatDocument = document;
|
|
178
|
+
let prefixes = [];
|
|
179
|
+
let suffixes = [];
|
|
180
|
+
if (codeOptions?.initialIndentLevel) {
|
|
181
|
+
for (let i = 0; i < codeOptions.initialIndentLevel; i++) {
|
|
182
|
+
if (i === codeOptions.initialIndentLevel - 1) {
|
|
183
|
+
prefixes.push('_', '{');
|
|
184
|
+
suffixes.unshift('}');
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
prefixes.push('_', '{\n');
|
|
188
|
+
suffixes.unshift('\n}');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
formatDocument = vscode_languageserver_textdocument_1.TextDocument.create(document.uri, document.languageId, document.version, prefixes.join('') + document.getText() + suffixes.join(''));
|
|
192
|
+
formatRange = {
|
|
193
|
+
start: formatDocument.positionAt(0),
|
|
194
|
+
end: formatDocument.positionAt(formatDocument.getText().length),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
let edits = cssLs.format(formatDocument, formatRange, formatOptions);
|
|
198
|
+
if (codeOptions) {
|
|
199
|
+
let newText = vscode_languageserver_textdocument_1.TextDocument.applyEdits(formatDocument, edits);
|
|
200
|
+
for (const prefix of prefixes) {
|
|
201
|
+
newText = newText.trimStart().slice(prefix.trim().length);
|
|
202
|
+
}
|
|
203
|
+
for (const suffix of suffixes.reverse()) {
|
|
204
|
+
newText = newText.trimEnd().slice(0, -suffix.trim().length);
|
|
205
|
+
}
|
|
206
|
+
if (!codeOptions.initialIndentLevel && codeOptions.level > 0) {
|
|
207
|
+
newText = ensureNewLines(newText);
|
|
208
|
+
}
|
|
209
|
+
edits = [{
|
|
210
|
+
range: {
|
|
211
|
+
start: document.positionAt(0),
|
|
212
|
+
end: document.positionAt(document.getText().length),
|
|
213
|
+
},
|
|
214
|
+
newText,
|
|
215
|
+
}];
|
|
216
|
+
}
|
|
217
|
+
return edits;
|
|
218
|
+
function ensureNewLines(newText) {
|
|
219
|
+
const verifyDocument = vscode_languageserver_textdocument_1.TextDocument.create(document.uri, document.languageId, document.version, '_ {' + newText + '}');
|
|
220
|
+
const verifyEdits = cssLs.format(verifyDocument, undefined, formatOptions);
|
|
221
|
+
let verifyText = vscode_languageserver_textdocument_1.TextDocument.applyEdits(verifyDocument, verifyEdits);
|
|
222
|
+
verifyText = verifyText.trimStart().slice('_'.length);
|
|
223
|
+
verifyText = verifyText.trim().slice('{'.length, -'}'.length);
|
|
224
|
+
if (startWithNewLine(verifyText) !== startWithNewLine(newText)) {
|
|
225
|
+
if (startWithNewLine(verifyText)) {
|
|
226
|
+
newText = '\n' + newText;
|
|
227
|
+
}
|
|
228
|
+
else if (newText.startsWith('\n')) {
|
|
229
|
+
newText = newText.slice(1);
|
|
230
|
+
}
|
|
231
|
+
else if (newText.startsWith('\r\n')) {
|
|
232
|
+
newText = newText.slice(2);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (endWithNewLine(verifyText) !== endWithNewLine(newText)) {
|
|
236
|
+
if (endWithNewLine(verifyText)) {
|
|
237
|
+
newText = newText + '\n';
|
|
238
|
+
}
|
|
239
|
+
else if (newText.endsWith('\n')) {
|
|
240
|
+
newText = newText.slice(0, -1);
|
|
241
|
+
}
|
|
242
|
+
else if (newText.endsWith('\r\n')) {
|
|
243
|
+
newText = newText.slice(0, -2);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return newText;
|
|
247
|
+
}
|
|
248
|
+
function startWithNewLine(text) {
|
|
249
|
+
return text.startsWith('\n') || text.startsWith('\r\n');
|
|
250
|
+
}
|
|
251
|
+
function endWithNewLine(text) {
|
|
252
|
+
return text.endsWith('\n') || text.endsWith('\r\n');
|
|
253
|
+
}
|
|
160
254
|
});
|
|
161
255
|
},
|
|
162
256
|
};
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
inited = true;
|
|
257
|
+
function getCssLs(document) {
|
|
258
|
+
if (matchDocument(cssDocumentSelector, document)) {
|
|
259
|
+
if (!cssLs) {
|
|
260
|
+
cssLs = css.getCSSLanguageService({
|
|
261
|
+
fileSystemProvider,
|
|
262
|
+
clientCapabilities: context.env.clientCapabilities,
|
|
263
|
+
useDefaultDataProvider,
|
|
264
|
+
customDataProviders: customData,
|
|
265
|
+
});
|
|
266
|
+
cssLs.setDataProviders(useDefaultDataProvider, customData);
|
|
267
|
+
}
|
|
268
|
+
return cssLs;
|
|
176
269
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
newData.push(css.newCSSDataProvider(require(jsonPath)));
|
|
270
|
+
else if (matchDocument(scssDocumentSelector, document)) {
|
|
271
|
+
if (!scssLs) {
|
|
272
|
+
scssLs = css.getSCSSLanguageService({
|
|
273
|
+
fileSystemProvider,
|
|
274
|
+
clientCapabilities: context.env.clientCapabilities,
|
|
275
|
+
useDefaultDataProvider,
|
|
276
|
+
customDataProviders: customData,
|
|
277
|
+
});
|
|
278
|
+
scssLs.setDataProviders(useDefaultDataProvider, customData);
|
|
187
279
|
}
|
|
188
|
-
|
|
189
|
-
|
|
280
|
+
return scssLs;
|
|
281
|
+
}
|
|
282
|
+
else if (matchDocument(lessDocumentSelector, document)) {
|
|
283
|
+
if (!lessLs) {
|
|
284
|
+
lessLs = css.getLESSLanguageService({
|
|
285
|
+
fileSystemProvider,
|
|
286
|
+
clientCapabilities: context.env.clientCapabilities,
|
|
287
|
+
useDefaultDataProvider,
|
|
288
|
+
customDataProviders: customData,
|
|
289
|
+
});
|
|
290
|
+
lessLs.setDataProviders(useDefaultDataProvider, customData);
|
|
190
291
|
}
|
|
292
|
+
return lessLs;
|
|
191
293
|
}
|
|
192
|
-
return newData;
|
|
193
294
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
295
|
+
async function worker(document, callback) {
|
|
296
|
+
const cssLs = getCssLs(document);
|
|
297
|
+
if (!cssLs)
|
|
298
|
+
return;
|
|
299
|
+
await (initializing ??= initialize());
|
|
300
|
+
return callback(getStylesheet(document, cssLs), cssLs);
|
|
201
301
|
}
|
|
202
|
-
function getStylesheet(document) {
|
|
302
|
+
function getStylesheet(document, ls) {
|
|
203
303
|
const cache = stylesheets.get(document);
|
|
204
304
|
if (cache) {
|
|
205
305
|
const [cacheVersion, cacheStylesheet] = cache;
|
|
@@ -207,25 +307,26 @@ function create() {
|
|
|
207
307
|
return cacheStylesheet;
|
|
208
308
|
}
|
|
209
309
|
}
|
|
210
|
-
const
|
|
211
|
-
if (!cssLs)
|
|
212
|
-
return;
|
|
213
|
-
const stylesheet = cssLs.parseStylesheet(document);
|
|
310
|
+
const stylesheet = ls.parseStylesheet(document);
|
|
214
311
|
stylesheets.set(document, [document.version, stylesheet]);
|
|
215
312
|
return stylesheet;
|
|
216
313
|
}
|
|
217
|
-
async function
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (!cssLs)
|
|
223
|
-
return;
|
|
224
|
-
await initCustomData();
|
|
225
|
-
return callback(stylesheet, cssLs);
|
|
314
|
+
async function initialize() {
|
|
315
|
+
customData = await getCustomData(context);
|
|
316
|
+
cssLs?.setDataProviders(useDefaultDataProvider, customData);
|
|
317
|
+
scssLs?.setDataProviders(useDefaultDataProvider, customData);
|
|
318
|
+
lessLs?.setDataProviders(useDefaultDataProvider, customData);
|
|
226
319
|
}
|
|
227
320
|
},
|
|
228
321
|
};
|
|
229
322
|
}
|
|
230
323
|
exports.create = create;
|
|
324
|
+
function matchDocument(selector, document) {
|
|
325
|
+
for (const sel of selector) {
|
|
326
|
+
if (sel === document.languageId || (typeof sel === 'object' && sel.language === document.languageId)) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
231
332
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "volar-service-css",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Integrate vscode-css-languageservice into Volar",
|
|
5
5
|
"homepage": "https://github.com/volarjs/services/tree/master/packages/css",
|
|
6
6
|
"bugs": "https://github.com/volarjs/services/issues",
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"vscode-css-languageservice": "^6.2.10",
|
|
28
|
+
"vscode-languageserver-textdocument": "^1.0.11",
|
|
28
29
|
"vscode-uri": "^3.0.8"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@types/node": "latest"
|
|
32
|
-
"vscode-languageserver-textdocument": "^1.0.11"
|
|
32
|
+
"@types/node": "latest"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@volar/language-service": "~2.0
|
|
35
|
+
"@volar/language-service": "~2.1.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@volar/language-service": {
|
|
39
39
|
"optional": true
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "717049e7dcd5c30f451f6db8eb71eaba43f74c83"
|
|
43
43
|
}
|