volar-service-markdown 0.0.16 → 0.0.18
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/out/index.d.ts +2 -3
- package/out/index.js +229 -212
- package/package.json +3 -3
package/out/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ServicePlugin } from '@volar/language-service';
|
|
2
2
|
import type { IMdLanguageService } from 'vscode-markdown-languageservice';
|
|
3
3
|
export interface Provide {
|
|
4
4
|
'markdown/languageService': () => IMdLanguageService;
|
|
5
5
|
}
|
|
6
|
-
export declare function create():
|
|
7
|
-
export default create;
|
|
6
|
+
export declare function create(): ServicePlugin;
|
|
8
7
|
//# sourceMappingURL=index.d.ts.map
|
package/out/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.create = void 0;
|
|
4
|
+
const language_service_1 = require("@volar/language-service");
|
|
4
5
|
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
|
|
5
6
|
const vscode_markdown_languageservice_1 = require("vscode-markdown-languageservice");
|
|
6
7
|
const vscode_uri_1 = require("vscode-uri");
|
|
@@ -15,233 +16,249 @@ function assert(condition, message) {
|
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
function create() {
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
onDidChangeMarkdownDocument.fire(document);
|
|
19
|
+
return {
|
|
20
|
+
create(context) {
|
|
21
|
+
let lastProjectVersion;
|
|
22
|
+
const { fs, onDidChangeWatchedFiles } = context.env;
|
|
23
|
+
assert(fs, 'context.env.fs must be defined');
|
|
24
|
+
assert(onDidChangeWatchedFiles, 'context.env.fs.onDidChangeWatchedFiles must be defined');
|
|
25
|
+
const logger = {
|
|
26
|
+
level: vscode_markdown_languageservice_1.LogLevel.Off,
|
|
27
|
+
log(_logLevel, message) {
|
|
28
|
+
context.env.console?.log(message);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const parser = {
|
|
32
|
+
slugifier: vscode_markdown_languageservice_1.githubSlugifier,
|
|
33
|
+
async tokenize(document) {
|
|
34
|
+
return md.parse(document.getText(), {});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const onDidChangeMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
38
|
+
const onDidCreateMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
39
|
+
const onDidDeleteMarkdownDocument = new vscode_jsonrpc_1.Emitter();
|
|
40
|
+
const fileWatcher = onDidChangeWatchedFiles((event) => {
|
|
41
|
+
for (const change of event.changes) {
|
|
42
|
+
switch (change.type) {
|
|
43
|
+
case 2: {
|
|
44
|
+
const document = getTextDocument(change.uri, false);
|
|
45
|
+
if (document) {
|
|
46
|
+
onDidChangeMarkdownDocument.fire(document);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
case 1: {
|
|
51
|
+
const document = getTextDocument(change.uri, false);
|
|
52
|
+
if (document) {
|
|
53
|
+
onDidCreateMarkdownDocument.fire(document);
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 3: {
|
|
58
|
+
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(change.uri));
|
|
59
|
+
break;
|
|
56
60
|
}
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case 3: {
|
|
60
|
-
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(change.uri));
|
|
61
|
-
break;
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return { isDirectory: stat.type === 2 };
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
workspaceFolders: []
|
|
98
|
-
};
|
|
99
|
-
const ls = (0, vscode_markdown_languageservice_1.createLanguageService)({
|
|
100
|
-
logger,
|
|
101
|
-
parser,
|
|
102
|
-
workspace
|
|
103
|
-
});
|
|
104
|
-
const syncedVersions = new Map();
|
|
105
|
-
const sync = () => {
|
|
106
|
-
const newProjectVersion = context.host.getProjectVersion();
|
|
107
|
-
const shouldUpdate = newProjectVersion !== lastProjectVersion;
|
|
108
|
-
if (!shouldUpdate) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
lastProjectVersion = newProjectVersion;
|
|
112
|
-
const oldVersions = new Set(syncedVersions.keys());
|
|
113
|
-
const newVersions = new Map();
|
|
114
|
-
for (const { root } of context.virtualFiles.allSources()) {
|
|
115
|
-
const embeddeds = [root];
|
|
116
|
-
root.embeddedFiles.forEach(function walk(embedded) {
|
|
117
|
-
embeddeds.push(embedded);
|
|
118
|
-
embedded.embeddedFiles.forEach(walk);
|
|
119
|
-
});
|
|
120
|
-
for (const embedded of embeddeds) {
|
|
121
|
-
const document = context.getTextDocument(embedded.fileName);
|
|
122
|
-
if (document && isMarkdown(document)) {
|
|
123
|
-
newVersions.set(String(document.uri), document);
|
|
63
|
+
});
|
|
64
|
+
const workspace = {
|
|
65
|
+
async getAllMarkdownDocuments() {
|
|
66
|
+
sync();
|
|
67
|
+
return syncedVersions.values();
|
|
68
|
+
},
|
|
69
|
+
getContainingDocument() {
|
|
70
|
+
return undefined;
|
|
71
|
+
},
|
|
72
|
+
hasMarkdownDocument(resource) {
|
|
73
|
+
const document = getTextDocument(resource.toString(), true);
|
|
74
|
+
return Boolean(document && isMarkdown(document));
|
|
75
|
+
},
|
|
76
|
+
onDidChangeMarkdownDocument: onDidChangeMarkdownDocument.event,
|
|
77
|
+
onDidCreateMarkdownDocument: onDidCreateMarkdownDocument.event,
|
|
78
|
+
onDidDeleteMarkdownDocument: onDidDeleteMarkdownDocument.event,
|
|
79
|
+
async openMarkdownDocument(resource) {
|
|
80
|
+
return getTextDocument(resource.toString(), true);
|
|
81
|
+
},
|
|
82
|
+
async readDirectory(resource) {
|
|
83
|
+
const directory = await fs.readDirectory(resource.toString());
|
|
84
|
+
return directory.map(([fileName, fileType]) => [
|
|
85
|
+
fileName,
|
|
86
|
+
{ isDirectory: fileType === 2 }
|
|
87
|
+
]);
|
|
88
|
+
},
|
|
89
|
+
async stat(resource) {
|
|
90
|
+
const stat = await fs.stat(resource.toString());
|
|
91
|
+
if (stat) {
|
|
92
|
+
return { isDirectory: stat.type === 2 };
|
|
124
93
|
}
|
|
94
|
+
},
|
|
95
|
+
workspaceFolders: []
|
|
96
|
+
};
|
|
97
|
+
const ls = (0, vscode_markdown_languageservice_1.createLanguageService)({
|
|
98
|
+
logger,
|
|
99
|
+
parser,
|
|
100
|
+
workspace
|
|
101
|
+
});
|
|
102
|
+
const syncedVersions = new Map();
|
|
103
|
+
const sync = () => {
|
|
104
|
+
const languageServiceHost = context.language.typescript?.languageServiceHost;
|
|
105
|
+
if (!languageServiceHost)
|
|
106
|
+
return;
|
|
107
|
+
const newProjectVersion = languageServiceHost.getProjectVersion?.();
|
|
108
|
+
const shouldUpdate = newProjectVersion === undefined || newProjectVersion !== lastProjectVersion;
|
|
109
|
+
if (!shouldUpdate) {
|
|
110
|
+
return;
|
|
125
111
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (!isMarkdown(document)) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
sync();
|
|
149
|
-
return true;
|
|
150
|
-
};
|
|
151
|
-
return {
|
|
152
|
-
dispose() {
|
|
153
|
-
ls.dispose();
|
|
154
|
-
fileWatcher.dispose();
|
|
155
|
-
onDidDeleteMarkdownDocument.dispose();
|
|
156
|
-
onDidCreateMarkdownDocument.dispose();
|
|
157
|
-
onDidChangeMarkdownDocument.dispose();
|
|
158
|
-
},
|
|
159
|
-
provide: {
|
|
160
|
-
'markdown/languageService': () => ls
|
|
161
|
-
},
|
|
162
|
-
provideCodeActions(document, range, context, token) {
|
|
163
|
-
if (prepare(document)) {
|
|
164
|
-
return ls.getCodeActions(document, range, context, token);
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
async provideCompletionItems(document, position, _context, token) {
|
|
168
|
-
if (prepare(document)) {
|
|
169
|
-
const items = await ls.getCompletionItems(document, position, {}, token);
|
|
170
|
-
return {
|
|
171
|
-
isIncomplete: false,
|
|
172
|
-
items
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
provideDiagnostics(document, token) {
|
|
177
|
-
if (prepare(document)) {
|
|
178
|
-
return ls.computeDiagnostics(document, {
|
|
179
|
-
ignoreLinks: [],
|
|
180
|
-
validateDuplicateLinkDefinitions: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
181
|
-
validateFileLinks: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
182
|
-
validateFragmentLinks: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
183
|
-
validateMarkdownFileLinkFragments: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
184
|
-
validateReferences: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
185
|
-
validateUnusedLinkDefinitions: vscode_markdown_languageservice_1.DiagnosticLevel.warning
|
|
186
|
-
}, token);
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
provideDocumentHighlights(document, position, token) {
|
|
190
|
-
if (prepare(document)) {
|
|
191
|
-
return ls.getDocumentHighlights(document, position, token);
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
provideDocumentLinks(document, token) {
|
|
195
|
-
if (prepare(document)) {
|
|
196
|
-
return ls.getDocumentLinks(document, token);
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
provideDocumentSymbols(document, token) {
|
|
200
|
-
if (prepare(document)) {
|
|
201
|
-
return ls.getDocumentSymbols(document, { includeLinkDefinitions: true }, token);
|
|
112
|
+
lastProjectVersion = newProjectVersion;
|
|
113
|
+
const oldVersions = new Set(syncedVersions.keys());
|
|
114
|
+
const newVersions = new Map();
|
|
115
|
+
for (const fileName of languageServiceHost.getScriptFileNames()) {
|
|
116
|
+
const [_, sourceFile] = context.language.files.getVirtualFile(fileName);
|
|
117
|
+
if (sourceFile?.virtualFile) {
|
|
118
|
+
for (const virtualFile of Array.from((0, language_service_1.forEachEmbeddedFile)(sourceFile.virtualFile[0]))) {
|
|
119
|
+
if (virtualFile.languageId === 'markdown') {
|
|
120
|
+
const document = context.documents.get(virtualFile.id, virtualFile.languageId, virtualFile.snapshot);
|
|
121
|
+
newVersions.set(document.uri, document);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (sourceFile) {
|
|
126
|
+
const document = context.documents.get(fileName, sourceFile.languageId, sourceFile.snapshot);
|
|
127
|
+
if (document && isMarkdown(document)) {
|
|
128
|
+
newVersions.set(document.uri, document);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
202
131
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
132
|
+
for (const [uri, document] of Array.from(newVersions)) {
|
|
133
|
+
const old = syncedVersions.get(uri);
|
|
134
|
+
syncedVersions.set(uri, document);
|
|
135
|
+
if (old) {
|
|
136
|
+
onDidChangeMarkdownDocument.fire(document);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
onDidCreateMarkdownDocument.fire(document);
|
|
140
|
+
}
|
|
207
141
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
142
|
+
for (const uri of Array.from(oldVersions)) {
|
|
143
|
+
if (!newVersions.has(uri)) {
|
|
144
|
+
syncedVersions.delete(uri);
|
|
145
|
+
onDidDeleteMarkdownDocument.fire(vscode_uri_1.URI.parse(uri));
|
|
146
|
+
}
|
|
212
147
|
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (
|
|
216
|
-
return
|
|
148
|
+
};
|
|
149
|
+
const prepare = (document) => {
|
|
150
|
+
if (!isMarkdown(document)) {
|
|
151
|
+
return false;
|
|
217
152
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
153
|
+
sync();
|
|
154
|
+
return true;
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
dispose() {
|
|
158
|
+
ls.dispose();
|
|
159
|
+
fileWatcher.dispose();
|
|
160
|
+
onDidDeleteMarkdownDocument.dispose();
|
|
161
|
+
onDidCreateMarkdownDocument.dispose();
|
|
162
|
+
onDidChangeMarkdownDocument.dispose();
|
|
163
|
+
},
|
|
164
|
+
provide: {
|
|
165
|
+
'markdown/languageService': () => ls
|
|
166
|
+
},
|
|
167
|
+
provideCodeActions(document, range, context, token) {
|
|
168
|
+
if (prepare(document)) {
|
|
169
|
+
return ls.getCodeActions(document, range, context, token);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
async provideCompletionItems(document, position, _context, token) {
|
|
173
|
+
if (prepare(document)) {
|
|
174
|
+
const items = await ls.getCompletionItems(document, position, {}, token);
|
|
175
|
+
return {
|
|
176
|
+
isIncomplete: false,
|
|
177
|
+
items
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
provideDiagnostics(document, token) {
|
|
182
|
+
if (prepare(document)) {
|
|
183
|
+
return ls.computeDiagnostics(document, {
|
|
184
|
+
ignoreLinks: [],
|
|
185
|
+
validateDuplicateLinkDefinitions: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
186
|
+
validateFileLinks: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
187
|
+
validateFragmentLinks: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
188
|
+
validateMarkdownFileLinkFragments: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
189
|
+
validateReferences: vscode_markdown_languageservice_1.DiagnosticLevel.warning,
|
|
190
|
+
validateUnusedLinkDefinitions: vscode_markdown_languageservice_1.DiagnosticLevel.warning
|
|
191
|
+
}, token);
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
provideDocumentHighlights(document, position, token) {
|
|
195
|
+
if (prepare(document)) {
|
|
196
|
+
return ls.getDocumentHighlights(document, position, token);
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
provideDocumentLinks(document, token) {
|
|
200
|
+
if (prepare(document)) {
|
|
201
|
+
return ls.getDocumentLinks(document, token);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
provideDocumentSymbols(document, token) {
|
|
205
|
+
if (prepare(document)) {
|
|
206
|
+
return ls.getDocumentSymbols(document, { includeLinkDefinitions: true }, token);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
provideFileReferences(document, token) {
|
|
210
|
+
if (prepare(document)) {
|
|
211
|
+
return ls.getFileReferences(vscode_uri_1.URI.parse(document.uri), token);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
provideFoldingRanges(document, token) {
|
|
215
|
+
if (prepare(document)) {
|
|
216
|
+
return ls.getFoldingRanges(document, token);
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
provideReferences(document, position, token) {
|
|
220
|
+
if (prepare(document)) {
|
|
221
|
+
return ls.getReferences(document, position, { includeDeclaration: true }, token);
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
provideRenameEdits(document, position, newName, token) {
|
|
225
|
+
if (prepare(document)) {
|
|
226
|
+
return ls.getRenameEdit(document, position, newName, token);
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
provideRenameRange(document, position, token) {
|
|
230
|
+
if (prepare(document)) {
|
|
231
|
+
return ls.prepareRename(document, position, token);
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
provideSelectionRanges(document, positions, token) {
|
|
235
|
+
if (prepare(document)) {
|
|
236
|
+
return ls.getSelectionRanges(document, positions, token);
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
provideWorkspaceSymbols(query, token) {
|
|
240
|
+
sync();
|
|
241
|
+
return ls.getWorkspaceSymbols(query, token);
|
|
242
|
+
},
|
|
243
|
+
async resolveDocumentLink(link, token) {
|
|
244
|
+
const result = await ls.resolveDocumentLink(link, token);
|
|
245
|
+
return result || link;
|
|
222
246
|
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (
|
|
226
|
-
|
|
247
|
+
};
|
|
248
|
+
function getTextDocument(uri, includeVirtualFile) {
|
|
249
|
+
if (includeVirtualFile) {
|
|
250
|
+
const virtualFile = context.language.files.getVirtualFile(uri)[0];
|
|
251
|
+
if (virtualFile) {
|
|
252
|
+
return context.documents.get(uri, virtualFile.languageId, virtualFile.snapshot);
|
|
253
|
+
}
|
|
227
254
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return ls.getSelectionRanges(document, positions, token);
|
|
255
|
+
const sourceFile = context.language.files.getSourceFile(uri);
|
|
256
|
+
if (sourceFile && !sourceFile.virtualFile) {
|
|
257
|
+
return context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
|
|
232
258
|
}
|
|
233
|
-
},
|
|
234
|
-
provideWorkspaceSymbols(query, token) {
|
|
235
|
-
sync();
|
|
236
|
-
return ls.getWorkspaceSymbols(query, token);
|
|
237
|
-
},
|
|
238
|
-
async resolveDocumentLink(link, token) {
|
|
239
|
-
const result = await ls.resolveDocumentLink(link, token);
|
|
240
|
-
return result || link;
|
|
241
259
|
}
|
|
242
|
-
}
|
|
260
|
+
},
|
|
243
261
|
};
|
|
244
262
|
}
|
|
245
263
|
exports.create = create;
|
|
246
|
-
exports.default = create;
|
|
247
264
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "volar-service-markdown",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Integrate vscode-markdown-languageservice into Volar",
|
|
5
5
|
"homepage": "https://github.com/volarjs/services/tree/master/packages/markdown",
|
|
6
6
|
"bugs": "https://github.com/volarjs/services/issues",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"vscode-languageserver-textdocument": "^1.0.11"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@volar/language-service": "
|
|
38
|
+
"@volar/language-service": "2.0.0-alpha.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependenciesMeta": {
|
|
41
41
|
"@volar/language-service": {
|
|
42
42
|
"optional": true
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "8dedd3c6e73740fc7c1fe06df32b727ca504adc0"
|
|
46
46
|
}
|