@diplodoc/cli 4.8.0 → 4.9.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/build/index.js +115 -4
- package/build/index.js.map +3 -3
- package/build/linter.js +9 -1
- package/build/linter.js.map +2 -2
- package/package.json +2 -2
- package/src/models.ts +1 -0
- package/src/services/contributors.ts +46 -2
- package/src/services/metadata.ts +42 -2
- package/src/services/tocs.ts +10 -0
- package/src/vcs-connector/connector-models.ts +2 -0
- package/src/vcs-connector/github.ts +42 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Yandex Data UI Team <data-ui@yandex-team.ru>",
|
|
4
4
|
"description": "Make documentation using yfm-docs in Markdown and HTML formats",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "4.
|
|
6
|
+
"version": "4.9.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git@github.com:diplodoc-platform/cli.git"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@aws-sdk/client-s3": "^3.369.0",
|
|
34
34
|
"@diplodoc/client": "^2.0.0",
|
|
35
|
-
"@diplodoc/latex-extension": "^1.0.
|
|
35
|
+
"@diplodoc/latex-extension": "^1.0.3",
|
|
36
36
|
"@diplodoc/markdown-translation": "^1.0.4",
|
|
37
37
|
"@diplodoc/mermaid-extension": "^1.2.1",
|
|
38
38
|
"@diplodoc/openapi-extension": "^1.4.10",
|
package/src/models.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type NestedContributorsForPathFunction = (
|
|
|
19
19
|
) => void;
|
|
20
20
|
export type UserByLoginFunction = (login: string) => Promise<Contributor | null>;
|
|
21
21
|
export type CollectionOfPluginsFunction = (output: string, options: PluginOptions) => string;
|
|
22
|
+
export type GetModifiedTimeByPathFunction = (filepath: string) => number | undefined;
|
|
22
23
|
|
|
23
24
|
interface YfmConfig {
|
|
24
25
|
varsPreset: VarsPreset;
|
|
@@ -94,7 +94,10 @@ async function getContributorsForNestedFiles(
|
|
|
94
94
|
return Object.assign({}, ...includesContributors);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
function getRelativeIncludeFilePaths(
|
|
97
|
+
function getRelativeIncludeFilePaths(
|
|
98
|
+
fileData: Pick<FileData, 'tmpInputFilePath'>,
|
|
99
|
+
includeContents: string[],
|
|
100
|
+
): Set<string> {
|
|
98
101
|
const {tmpInputFilePath} = fileData;
|
|
99
102
|
const relativeIncludeFilePaths: Set<string> = new Set();
|
|
100
103
|
|
|
@@ -115,4 +118,45 @@ function getRelativeIncludeFilePaths(fileData: FileData, includeContents: string
|
|
|
115
118
|
return relativeIncludeFilePaths;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
|
|
121
|
+
async function getFileIncludes(
|
|
122
|
+
fileData: Pick<FileData, 'fileContent' | 'tmpInputFilePath' | 'inputFolderPathLength'>,
|
|
123
|
+
) {
|
|
124
|
+
const {fileContent, tmpInputFilePath, inputFolderPathLength} = fileData;
|
|
125
|
+
|
|
126
|
+
const results = new Set<string>();
|
|
127
|
+
|
|
128
|
+
const includeContents = fileContent.match(REGEXP_INCLUDE_CONTENTS);
|
|
129
|
+
if (!includeContents || includeContents.length === 0) {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
const relativeIncludeFilePaths: Set<string> = getRelativeIncludeFilePaths(
|
|
133
|
+
{tmpInputFilePath},
|
|
134
|
+
includeContents,
|
|
135
|
+
);
|
|
136
|
+
for (const relativeIncludeFilePath of relativeIncludeFilePaths.values()) {
|
|
137
|
+
const relativeFilePath = relativeIncludeFilePath.substring(inputFolderPathLength + 1);
|
|
138
|
+
if (results.has(relativeFilePath)) continue;
|
|
139
|
+
results.add(relativeFilePath);
|
|
140
|
+
|
|
141
|
+
let contentIncludeFile: string;
|
|
142
|
+
try {
|
|
143
|
+
contentIncludeFile = await readFile(relativeIncludeFilePath, 'utf8');
|
|
144
|
+
} catch (err) {
|
|
145
|
+
if (err.code === 'ENOENT') {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const includedPaths = await getFileIncludes({
|
|
152
|
+
inputFolderPathLength,
|
|
153
|
+
fileContent: contentIncludeFile,
|
|
154
|
+
tmpInputFilePath: relativeIncludeFilePath,
|
|
155
|
+
});
|
|
156
|
+
includedPaths.forEach((path) => results.add(path));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return Array.from(results.values());
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {getFileContributorsMetadata, getFileContributorsString, getFileIncludes};
|
package/src/services/metadata.ts
CHANGED
|
@@ -7,12 +7,16 @@ import {
|
|
|
7
7
|
updateAuthorMetadataStringByAuthorLogin,
|
|
8
8
|
updateAuthorMetadataStringByFilePath,
|
|
9
9
|
} from './authors';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
getFileContributorsMetadata,
|
|
12
|
+
getFileContributorsString,
|
|
13
|
+
getFileIncludes,
|
|
14
|
+
} from './contributors';
|
|
11
15
|
import {isObject} from './utils';
|
|
12
16
|
import {сarriage} from '../utils';
|
|
13
17
|
import {REGEXP_AUTHOR, metadataBorder} from '../constants';
|
|
14
18
|
import {dirname, relative, resolve} from 'path';
|
|
15
|
-
import {ArgvService} from './index';
|
|
19
|
+
import {ArgvService, TocService} from './index';
|
|
16
20
|
|
|
17
21
|
async function getContentWithUpdatedMetadata(
|
|
18
22
|
fileContent: string,
|
|
@@ -105,6 +109,11 @@ async function getContentWithUpdatedDynamicMetadata(
|
|
|
105
109
|
newMetadatas.push(contributorsMetaData);
|
|
106
110
|
}
|
|
107
111
|
|
|
112
|
+
const mtimeMetadata = await getModifiedTimeMetadataString(options, fileContent);
|
|
113
|
+
if (mtimeMetadata) {
|
|
114
|
+
newMetadatas.push(mtimeMetadata);
|
|
115
|
+
}
|
|
116
|
+
|
|
108
117
|
let authorMetadata = '';
|
|
109
118
|
if (fileMetadata) {
|
|
110
119
|
const matchAuthor = fileMetadata.match(REGEXP_AUTHOR);
|
|
@@ -188,6 +197,37 @@ async function getContributorsMetadataString(
|
|
|
188
197
|
return undefined;
|
|
189
198
|
}
|
|
190
199
|
|
|
200
|
+
async function getModifiedTimeMetadataString(options: MetaDataOptions, fileContent: string) {
|
|
201
|
+
const {isContributorsEnabled, vcsConnector, fileData} = options;
|
|
202
|
+
|
|
203
|
+
const {tmpInputFilePath, inputFolderPathLength} = fileData;
|
|
204
|
+
|
|
205
|
+
const relativeFilePath = tmpInputFilePath.substring(inputFolderPathLength + 1);
|
|
206
|
+
|
|
207
|
+
if (!isContributorsEnabled || !vcsConnector) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const includedFiles = await getFileIncludes({...fileData, fileContent});
|
|
212
|
+
includedFiles.push(relativeFilePath);
|
|
213
|
+
|
|
214
|
+
const tocCopyFileMap = TocService.getCopyFileMap();
|
|
215
|
+
|
|
216
|
+
const mtimeList = includedFiles
|
|
217
|
+
.map((path) => {
|
|
218
|
+
const mappedPath = tocCopyFileMap.get(path) || path;
|
|
219
|
+
return vcsConnector.getModifiedTimeByPath(mappedPath);
|
|
220
|
+
})
|
|
221
|
+
.filter((v) => typeof v === 'number') as number[];
|
|
222
|
+
|
|
223
|
+
if (mtimeList.length) {
|
|
224
|
+
const mtime = Math.max(...mtimeList);
|
|
225
|
+
return `updatedAt: ${new Date(mtime * 1000).toISOString()}`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
|
|
191
231
|
function getUpdatedMetadataString(newMetadatas: string[], defaultMetadata = ''): string {
|
|
192
232
|
const newMetadata = newMetadatas.join(сarriage) + (newMetadatas.length ? сarriage : '');
|
|
193
233
|
const preparedDefaultMetadata = defaultMetadata.trimRight();
|
package/src/services/tocs.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface TocServiceData {
|
|
|
24
24
|
const storage: TocServiceData['storage'] = new Map();
|
|
25
25
|
let navigationPaths: TocServiceData['navigationPaths'] = [];
|
|
26
26
|
const includedTocPaths: TocServiceData['includedTocPaths'] = new Set();
|
|
27
|
+
const tocFileCopyMap = new Map<string, string>();
|
|
27
28
|
|
|
28
29
|
async function add(path: string) {
|
|
29
30
|
const {
|
|
@@ -207,6 +208,10 @@ function _copyTocDir(tocPath: string, destDir: string) {
|
|
|
207
208
|
} else {
|
|
208
209
|
shell.cp(from, to);
|
|
209
210
|
}
|
|
211
|
+
|
|
212
|
+
const relFrom = relative(inputFolderPath, from);
|
|
213
|
+
const relTo = relative(inputFolderPath, to);
|
|
214
|
+
tocFileCopyMap.set(relTo, relFrom);
|
|
210
215
|
});
|
|
211
216
|
}
|
|
212
217
|
|
|
@@ -396,6 +401,10 @@ function setNavigationPaths(paths: TocServiceData['navigationPaths']) {
|
|
|
396
401
|
navigationPaths = paths;
|
|
397
402
|
}
|
|
398
403
|
|
|
404
|
+
function getCopyFileMap() {
|
|
405
|
+
return tocFileCopyMap;
|
|
406
|
+
}
|
|
407
|
+
|
|
399
408
|
export default {
|
|
400
409
|
add,
|
|
401
410
|
getForPath,
|
|
@@ -403,4 +412,5 @@ export default {
|
|
|
403
412
|
getTocDir,
|
|
404
413
|
getIncludedTocPaths,
|
|
405
414
|
setNavigationPaths,
|
|
415
|
+
getCopyFileMap,
|
|
406
416
|
};
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
Contributors,
|
|
3
3
|
ContributorsByPathFunction,
|
|
4
4
|
ExternalAuthorByPathFunction,
|
|
5
|
+
GetModifiedTimeByPathFunction,
|
|
5
6
|
NestedContributorsForPathFunction,
|
|
6
7
|
UserByLoginFunction,
|
|
7
8
|
} from '../models';
|
|
@@ -31,6 +32,7 @@ export interface VCSConnector {
|
|
|
31
32
|
addNestedContributorsForPath: NestedContributorsForPathFunction;
|
|
32
33
|
getContributorsByPath: ContributorsByPathFunction;
|
|
33
34
|
getUserByLogin: UserByLoginFunction;
|
|
35
|
+
getModifiedTimeByPath: GetModifiedTimeByPathFunction;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export interface VCSConnectorConfig {
|
|
@@ -33,9 +33,10 @@ const authorByPath: Map<string, Contributor | null> = new Map();
|
|
|
33
33
|
const contributorsByPath: Map<string, FileContributors> = new Map();
|
|
34
34
|
const contributorsData: Map<string, Contributor | null> = new Map();
|
|
35
35
|
const loginUserMap: Map<string, Contributor | null> = new Map();
|
|
36
|
+
const pathMTime = new Map<string, number>();
|
|
36
37
|
|
|
37
38
|
async function getGitHubVCSConnector(): Promise<VCSConnector | undefined> {
|
|
38
|
-
const {contributors} = ArgvService.getConfig();
|
|
39
|
+
const {contributors, rootInput} = ArgvService.getConfig();
|
|
39
40
|
|
|
40
41
|
const httpClientByToken = getHttpClientByToken();
|
|
41
42
|
if (!httpClientByToken) {
|
|
@@ -49,6 +50,7 @@ async function getGitHubVCSConnector(): Promise<VCSConnector | undefined> {
|
|
|
49
50
|
authorByPath.get(path) ?? null;
|
|
50
51
|
|
|
51
52
|
if (contributors) {
|
|
53
|
+
await getFilesMTime(rootInput, pathMTime);
|
|
52
54
|
await getAllContributorsTocFiles(httpClientByToken);
|
|
53
55
|
addNestedContributorsForPath = (path: string, nestedContributors: Contributors) =>
|
|
54
56
|
addNestedContributorsForPathFunction(path, nestedContributors);
|
|
@@ -60,6 +62,7 @@ async function getGitHubVCSConnector(): Promise<VCSConnector | undefined> {
|
|
|
60
62
|
addNestedContributorsForPath,
|
|
61
63
|
getContributorsByPath,
|
|
62
64
|
getUserByLogin: (login: string) => getUserByLogin(httpClientByToken, login),
|
|
65
|
+
getModifiedTimeByPath: (filename: string) => pathMTime.get(filename),
|
|
63
66
|
};
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -364,4 +367,42 @@ function shouldAuthorBeIgnored({email, name}: ShouldAuthorBeIgnoredArgs) {
|
|
|
364
367
|
return false;
|
|
365
368
|
}
|
|
366
369
|
|
|
370
|
+
async function getFilesMTime(repoDir: string, pathMTime: Map<string, number>) {
|
|
371
|
+
const timeFiles = await simpleGit({
|
|
372
|
+
baseDir: repoDir,
|
|
373
|
+
}).raw(
|
|
374
|
+
'log',
|
|
375
|
+
'--reverse',
|
|
376
|
+
'--before=now',
|
|
377
|
+
'--diff-filter=ADMR',
|
|
378
|
+
'--pretty=format:%ct',
|
|
379
|
+
'--name-status',
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const parts = timeFiles.split(/\n\n/);
|
|
383
|
+
parts.forEach((part) => {
|
|
384
|
+
const lines = part.trim().split(/\n/);
|
|
385
|
+
const committerDate = lines.shift();
|
|
386
|
+
const unixtime = Number(committerDate);
|
|
387
|
+
lines.forEach((line) => {
|
|
388
|
+
const [status, from, to] = line.split(/\t/);
|
|
389
|
+
switch (status[0]) {
|
|
390
|
+
case 'R': {
|
|
391
|
+
pathMTime.delete(from);
|
|
392
|
+
pathMTime.set(to, unixtime);
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
case 'D': {
|
|
396
|
+
pathMTime.delete(from);
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
default: {
|
|
400
|
+
pathMTime.set(from, unixtime);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
return pathMTime;
|
|
406
|
+
}
|
|
407
|
+
|
|
367
408
|
export default getGitHubVCSConnector;
|