@diplodoc/cli-tests 0.0.0-rc-toc-translation-202506261401 → 0.0.0-rc-liquid-conditions-saving-202509050811

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.
Files changed (106) hide show
  1. package/e2e/__snapshots__/generate-map.spec.ts.snap +345 -0
  2. package/e2e/__snapshots__/include-toc.test.ts.snap +8 -0
  3. package/e2e/__snapshots__/load-custom-resources.spec.ts.snap +68 -56
  4. package/e2e/__snapshots__/metadata.spec.ts.snap +31 -23
  5. package/e2e/__snapshots__/preprocess.test.ts.snap +549 -0
  6. package/e2e/__snapshots__/regression.test.ts.snap +197 -142
  7. package/e2e/__snapshots__/rtl.spec.ts.snap +51 -41
  8. package/e2e/__snapshots__/search.test.ts.snap +86 -0
  9. package/e2e/__snapshots__/skip-html-extension.spec.ts.snap +211 -0
  10. package/e2e/__snapshots__/translation.spec.ts.snap +2138 -1026
  11. package/e2e/errors.spec.ts +33 -2
  12. package/e2e/generate-map.spec.ts +9 -3
  13. package/e2e/preprocess.test.ts +33 -0
  14. package/e2e/redirects-validation.spec.ts +61 -0
  15. package/e2e/search.test.ts +15 -0
  16. package/e2e/skip-html-extension.spec.ts +15 -0
  17. package/e2e/translation.spec.ts +73 -3
  18. package/fixtures/cliAdapter.ts +23 -0
  19. package/fixtures/globals.d.ts +4 -0
  20. package/fixtures/runners/binary.ts +4 -3
  21. package/fixtures/runners/types.ts +1 -2
  22. package/fixtures/utils/file.ts +5 -5
  23. package/fixtures/utils/test.ts +18 -8
  24. package/mocks/docs-viewer-interface/input/.yfm +6 -0
  25. package/mocks/docs-viewer-interface/input/index.md +3 -0
  26. package/mocks/docs-viewer-interface/input/toc.yaml +5 -0
  27. package/mocks/errors/extract-filtered-link/input/filtered.md +1 -0
  28. package/mocks/errors/extract-filtered-link/input/filtered2.md +0 -0
  29. package/mocks/errors/extract-filtered-link/input/index.md +7 -0
  30. package/mocks/errors/extract-filtered-link/input/toc.yaml +1 -0
  31. package/mocks/load-custom-resources/md2html-with-resources/input/page.md +9 -2
  32. package/mocks/load-custom-resources/md2md-with-resources/input/page.md +9 -2
  33. package/mocks/load-custom-resources/single-page-with-resources/input/page.md +9 -2
  34. package/mocks/metadata/md2html-with-metadata/input/page.md +8 -1
  35. package/mocks/metadata/md2md-with-metadata/input/page.md +7 -0
  36. package/mocks/preprocess/input/.yfm +1 -0
  37. package/mocks/preprocess/input/1.md +29 -0
  38. package/mocks/preprocess/input/_assets/1.png +0 -0
  39. package/mocks/preprocess/input/_assets/1.svg +0 -0
  40. package/mocks/preprocess/input/autotitle.md +23 -0
  41. package/mocks/preprocess/input/commented-include.md +3 -0
  42. package/mocks/preprocess/input/images.md +5 -0
  43. package/mocks/preprocess/input/included-item.md +12 -0
  44. package/mocks/preprocess/input/includes/deep.md +1 -0
  45. package/mocks/preprocess/input/includes/deepWithIndent.md +6 -0
  46. package/mocks/preprocess/input/includes/presets.yaml +2 -0
  47. package/mocks/preprocess/input/includes/sub/user.md +1 -0
  48. package/mocks/preprocess/input/includes/sub/userWithIndent.md +5 -0
  49. package/mocks/preprocess/input/includes/test.md +1 -0
  50. package/mocks/preprocess/input/includes/user.md +1 -0
  51. package/mocks/preprocess/input/includes.md +18 -0
  52. package/mocks/preprocess/input/latex.md +3 -0
  53. package/mocks/preprocess/input/mermaid.md +13 -0
  54. package/mocks/preprocess/input/presets.yaml +8 -0
  55. package/mocks/preprocess/input/sub/folder/item-1.md +7 -0
  56. package/mocks/preprocess/input/sub/toc.yaml +5 -0
  57. package/mocks/preprocess/input/toc-i.yaml +3 -0
  58. package/mocks/preprocess/input/toc.yaml +16 -0
  59. package/mocks/redirects-validation/extensions-deprecation/input/blah.md +0 -0
  60. package/mocks/redirects-validation/extensions-deprecation/input/redirects.yaml +5 -0
  61. package/mocks/redirects-validation/extensions-deprecation/input/toc.yaml +4 -0
  62. package/mocks/redirects-validation/invalid-regex/input/blah.md +0 -0
  63. package/mocks/redirects-validation/invalid-regex/input/redirects.yaml +3 -0
  64. package/mocks/redirects-validation/invalid-regex/input/toc.yaml +4 -0
  65. package/mocks/redirects-validation/malformed-redirect/input/blah.md +0 -0
  66. package/mocks/redirects-validation/malformed-redirect/input/redirects.yaml +6 -0
  67. package/mocks/redirects-validation/malformed-redirect/input/toc.yaml +4 -0
  68. package/mocks/redirects-validation/same-path/input/blah.md +0 -0
  69. package/mocks/redirects-validation/same-path/input/redirects.yaml +3 -0
  70. package/mocks/redirects-validation/same-path/input/toc.yaml +4 -0
  71. package/mocks/redirects-validation/unparseable/input/blah.md +0 -0
  72. package/mocks/redirects-validation/unparseable/input/redirects.yaml +11 -0
  73. package/mocks/redirects-validation/unparseable/input/toc.yaml +4 -0
  74. package/mocks/regression/input/.yfm +2 -0
  75. package/mocks/regression/input/images.md +2 -0
  76. package/mocks/regression/input/includes/deep.md +2 -0
  77. package/mocks/regression/input/includes/presets.yaml +1 -0
  78. package/mocks/regression/input/includes/tools.md +1 -0
  79. package/mocks/regression/input/includes.md +5 -0
  80. package/mocks/regression/input/merge/merge.md +2 -0
  81. package/mocks/regression/input/merge/presets.yaml +1 -0
  82. package/mocks/regression/input/merge/toc.yaml +2 -0
  83. package/mocks/regression/input/presets.yaml +1 -0
  84. package/mocks/regression/input/toc.yaml +2 -0
  85. package/mocks/search/input/.yfm +12 -0
  86. package/mocks/search/input/index.md +3 -0
  87. package/mocks/search/input/toc.yaml +1 -0
  88. package/mocks/skip-html-extension/input/.yfm +1 -0
  89. package/mocks/skip-html-extension/input/folder/index.md +1 -0
  90. package/mocks/skip-html-extension/input/index-test-html/index.md +4 -0
  91. package/mocks/skip-html-extension/input/index.md +6 -0
  92. package/mocks/skip-html-extension/input/page1.md +3 -0
  93. package/mocks/skip-html-extension/input/page2.md +6 -0
  94. package/mocks/skip-html-extension/input/toc.yaml +13 -0
  95. package/mocks/translation/conditions/input/index.md +37 -0
  96. package/mocks/translation/dir-files/input/ru/nested/syntax/base.md +2 -0
  97. package/mocks/translation/no-translate/input/index.md +7 -0
  98. package/mocks/translation/no-translate/input/no-translate.md +57 -0
  99. package/mocks/translation/no-translate/input/openapi-spec.yaml +37 -0
  100. package/mocks/translation/no-translate/input/toc.yaml +11 -0
  101. package/mocks/translation/openapi/input/openapi-spec.yaml +42 -0
  102. package/mocks/translation/openapi/input/toc.yaml +8 -0
  103. package/mocks/warning/unreachable-autotitle/input/index.md +1 -0
  104. package/mocks/warning/unreachable-autotitle/input/link.md +0 -0
  105. package/mocks/warning/unreachable-autotitle/input/toc.yaml +4 -0
  106. package/package.json +5 -5
@@ -13,12 +13,12 @@ function test(path: string, expect: Function) {
13
13
  const {inputPath, outputPath} = getTestPaths(path);
14
14
 
15
15
  const md = await TestAdapter.build.run(inputPath, outputPath, ['-j2', '-f', 'md']);
16
- const html = await TestAdapter.build.run(outputPath, outputPath + '-html', ['-j2', '-f', 'html']);
17
-
16
+ const html = await TestAdapter.build.run(inputPath, outputPath + '-html', ['-j2', '-f', 'html']);
18
17
  return expect({md, html});
19
18
  });
20
19
  }
21
20
 
21
+
22
22
  describe('Errors', () => {
23
23
  test('mocks/errors/unreachable-link', ({html}: TestResult) => {
24
24
  expectErrors(html, [
@@ -26,6 +26,29 @@ describe('Errors', () => {
26
26
  'ERR index.md: 2: YFM003 / unreachable-link Link is unreachable [Context: "[Unreachable link: "missed.html"][missed file](./missed.md)"]'
27
27
  ]);
28
28
  });
29
+
30
+ it('translate extract with filtered links', async () => {
31
+ const {inputPath, outputPath} = getTestPaths('mocks/errors/extract-filtered-link');
32
+
33
+ const result = await TestAdapter.extract.run(inputPath, outputPath, ['--source', 'ru-RU', '--target', 'es-ES', '--filter']);
34
+
35
+ expect(result.code).toEqual(1);
36
+
37
+ expect(result.errors).toEqual([
38
+ "ERR File index.md contains link to filtered.md, which was filtered from toc.yaml or it's not been included initially",
39
+ "ERR File index.md contains link to filtered2.md, which was filtered from toc.yaml or it's not been included initially",
40
+ "ERR File index.md contains link to filtered2.md, which was filtered from toc.yaml or it's not been included initially",
41
+ "ERR File index.md contains link to filtered3.md, which was filtered from toc.yaml or it's not been included initially",
42
+ ])
43
+ });
44
+ });
45
+
46
+ describe('Warnings', () => {
47
+ test('mocks/warning/unreachable-autotitle', ({html}: TestResult) => {
48
+ expectWarnings(html, [
49
+ 'WARN index.md: 1: YFM010 / unreachable-autotitle-anchor Auto title anchor is unreachable [Context: "[Unreachable autotitle anchor: "link.html#unknown_yfm010"][{#T}](./link.md#unknown_yfm010)"]',
50
+ ]);
51
+ });
29
52
  });
30
53
 
31
54
  function expectErrors(report: Report, errors: string[]) {
@@ -35,3 +58,11 @@ function expectErrors(report: Report, errors: string[]) {
35
58
  expect(report.errors).toContain(error);
36
59
  }
37
60
  }
61
+
62
+ function expectWarnings(report: Report, warnings: string[]) {
63
+ expect(report.warns.length).toEqual(warnings.length);
64
+
65
+ for (const warn of warnings) {
66
+ expect(report.warns).toContain(warn);
67
+ }
68
+ }
@@ -1,6 +1,7 @@
1
1
  import {describe, expect, test} from 'vitest';
2
2
  import {TestAdapter, bundleless, getFileContent, getTestPaths} from '../fixtures';
3
- import {join} from 'path';
3
+ import {join} from 'node:path';
4
+ import {readFile} from 'node:fs/promises';
4
5
 
5
6
  const generateMapTestTemplate = (
6
7
  testTitle: string,
@@ -11,11 +12,17 @@ const generateMapTestTemplate = (
11
12
  test(testTitle, async () => {
12
13
  const {inputPath, outputPath} = getTestPaths(testRootPath);
13
14
 
14
- await TestAdapter.testBuildPass(inputPath, outputPath, {md2md, md2html, args: '--add-map-file'});
15
+ await TestAdapter.testBuildPass(inputPath, outputPath, {
16
+ md2md,
17
+ md2html,
18
+ args: '--add-map-file --build-manifest',
19
+ });
15
20
 
16
21
  const content = getFileContent(join(outputPath, 'files.json'));
22
+ const manifestContent = await readFile(join(outputPath, 'yfm-build-manifest.json'), 'utf-8');
17
23
 
18
24
  expect(bundleless(content)).toMatchSnapshot();
25
+ expect(JSON.parse(manifestContent)).toMatchSnapshot();
19
26
  });
20
27
  };
21
28
 
@@ -28,7 +35,6 @@ describe('Generate map for', () => {
28
35
  generateMapTestTemplate(
29
36
  'project with single language and toc include - only md2html',
30
37
  'mocks/generate-map/test1',
31
- false,
32
38
  );
33
39
 
34
40
  generateMapTestTemplate('project with multiple language', 'mocks/generate-map/test2');
@@ -0,0 +1,33 @@
1
+ import {describe, test} from 'vitest';
2
+ import {TestAdapter, compareDirectories, getTestPaths} from '../fixtures';
3
+
4
+ const generateFilesYamlTestTemplate = (
5
+ testTitle: string,
6
+ testRootPath: string,
7
+ args: string[] = [],
8
+ ) => {
9
+ test(testTitle, async () => {
10
+ const {inputPath, outputPath} = getTestPaths(testRootPath);
11
+ await TestAdapter.testBuildPass(inputPath, outputPath, {
12
+ md2md:true,
13
+ md2html: false,
14
+ args: args.join(' '),
15
+ });
16
+ await TestAdapter.testBuildPass(outputPath, outputPath + '-html', {
17
+ md2md: false,
18
+ md2html: true,
19
+ args: args.join(' '),
20
+ });
21
+ await compareDirectories(outputPath);
22
+ });
23
+ };
24
+
25
+ describe('Preprocess', () => {
26
+ generateFilesYamlTestTemplate('HashIncludes=true,Autotitles=false', 'mocks/preprocess', [
27
+ '--no-merge-autotitles'
28
+ ]);
29
+
30
+ generateFilesYamlTestTemplate('HashIncludes=true,Autotitles=true', 'mocks/preprocess');
31
+
32
+ // generateFilesYamlTestTemplate('Nested toc restricted access', 'mocks/preprocess/test3');
33
+ });
@@ -0,0 +1,61 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import {TestAdapter, getTestPaths} from '../fixtures';
3
+
4
+ describe('Redirects validation', () => {
5
+ it('should emit an error on an unparseable redirects.yaml', async () => {
6
+ const {inputPath, outputPath} = getTestPaths('mocks/redirects-validation/unparseable');
7
+
8
+ const report = await TestAdapter.build.run(inputPath, outputPath, ['-f', 'md']);
9
+
10
+ expect(report.code).toBe(1);
11
+ expect(report.errors).toContainEqual(expect.stringMatching(/redirects.yaml parsing error/));
12
+ });
13
+
14
+ it.skip('should emit a warning when supplied with a `redirects.yaml` that mentions file extensions', async () => {
15
+ const {inputPath, outputPath} = getTestPaths(
16
+ 'mocks/redirects-validation/extensions-deprecation',
17
+ );
18
+
19
+ const report = await TestAdapter.build.run(inputPath, outputPath, ['-f', 'md']);
20
+
21
+ expect(report.code).toBe(0);
22
+ expect(report.warns).toContainEqual(
23
+ expect.stringMatching(/Redirects with explicit extensions are deprecated./),
24
+ );
25
+ });
26
+
27
+ it('should emit an error when an invalid regular expression pattern is encountered', async () => {
28
+ const {inputPath, outputPath} = getTestPaths('mocks/redirects-validation/invalid-regex');
29
+
30
+ const report = await TestAdapter.build.run(inputPath, outputPath, ['-f', 'md']);
31
+
32
+ expect(report.code).toBe(1);
33
+ expect(report.errors).toContainEqual(
34
+ expect.stringMatching(
35
+ /Redirects configuration results in a non-valid regular expression/,
36
+ ),
37
+ );
38
+ });
39
+
40
+ it('should emit an error when a redirect is malformed', async () => {
41
+ const {inputPath, outputPath} = getTestPaths('mocks/redirects-validation/malformed-redirect');
42
+
43
+ const report = await TestAdapter.build.run(inputPath, outputPath, ['-f', 'md']);
44
+
45
+ expect(report.code).toBe(1);
46
+ expect(report.errors).toContainEqual(
47
+ expect.stringMatching(/One of the two parameters is missing/),
48
+ );
49
+ });
50
+
51
+ it('should emit an error when a redirect leads to the same path', async () => {
52
+ const {inputPath, outputPath} = getTestPaths('mocks/redirects-validation/same-path');
53
+
54
+ const report = await TestAdapter.build.run(inputPath, outputPath, ['-f', 'md']);
55
+
56
+ expect(report.code).toBe(1);
57
+ expect(report.errors).toContainEqual(
58
+ expect.stringMatching(/Parameters must be different/),
59
+ );
60
+ });
61
+ });
@@ -0,0 +1,15 @@
1
+ import {describe, it} from 'vitest';
2
+ import {TestAdapter, compareDirectories, getTestPaths} from '../fixtures';
3
+
4
+ describe('Local search', () => {
5
+ it('internal', async () => {
6
+ const {inputPath, outputPath} = getTestPaths('mocks/search');
7
+
8
+ await TestAdapter.testBuildPass(inputPath, outputPath, {
9
+ md2md: false,
10
+ md2html: true,
11
+ args: '-j2 --search --interface-toc',
12
+ });
13
+ await compareDirectories(outputPath);
14
+ });
15
+ });
@@ -0,0 +1,15 @@
1
+ import {describe, it} from 'vitest';
2
+ import {TestAdapter, compareDirectories, getTestPaths} from '../fixtures';
3
+
4
+ describe('Skip html extension', () => {
5
+ it('transforms links correctly', async () => {
6
+ const {inputPath, outputPath} = getTestPaths('mocks/skip-html-extension');
7
+
8
+ await TestAdapter.testBuildPass(inputPath, outputPath, {
9
+ md2md: false,
10
+ md2html: true,
11
+ args: '-j2 --skip-html-extension',
12
+ });
13
+ await compareDirectories(outputPath);
14
+ });
15
+ });
@@ -5,13 +5,14 @@ const generateMapTestTemplate = (
5
5
  testTitle: string,
6
6
  testRootPath: string,
7
7
  args: TranslateRunArgs,
8
+ ignoreFileContent = true,
8
9
  ) => {
9
10
  test(testTitle, async () => {
10
11
  const {inputPath, outputPath} = getTestPaths(testRootPath);
11
12
 
12
13
  await TestAdapter.testTranslatePass(inputPath, outputPath, args);
13
14
 
14
- await compareDirectories(outputPath);
15
+ await compareDirectories(outputPath, ignoreFileContent);
15
16
  });
16
17
  };
17
18
 
@@ -29,11 +30,43 @@ const generateFilesYamlTestTemplate = (
29
30
  });
30
31
  };
31
32
 
33
+ const buildFilesYamlTestTemplate = (
34
+ testTitle: string,
35
+ testRootPath: string,
36
+ buildProps: {md2md?: boolean; md2html?: boolean},
37
+ ) => {
38
+ test(testTitle, async () => {
39
+ const {inputPath, outputPath} = getTestPaths(testRootPath);
40
+ const {md2md, md2html} =buildProps;
41
+
42
+ await TestAdapter.testBuildPass(inputPath, outputPath, {md2html, md2md});
43
+
44
+ await compareDirectories(outputPath);
45
+ });
46
+ };
47
+
32
48
  describe('Translate command', () => {
49
+ buildFilesYamlTestTemplate('build translated md files and remove no-translate directives', 'mocks/translation/no-translate', {md2md: true});
50
+
51
+ buildFilesYamlTestTemplate('build translated static files and remove no-translate directives', 'mocks/translation/no-translate', {md2html: true});
52
+
53
+ generateFilesYamlTestTemplate('extract openapi spec files', 'mocks/translation/openapi', {
54
+ subcommand: 'extract',
55
+ source: 'ru-RU',
56
+ target: 'es-ES',
57
+ });
58
+
59
+ generateMapTestTemplate('do not filter files on extract', 'mocks/translation/dir-files', {
60
+ subcommand: 'extract',
61
+ source: 'ru-RU',
62
+ target: 'es-ES',
63
+ });
64
+
33
65
  generateMapTestTemplate('filter files on extract', 'mocks/translation/dir-files', {
34
66
  subcommand: 'extract',
35
67
  source: 'ru-RU',
36
68
  target: 'es-ES',
69
+ additionalArgs: '--filter'
37
70
  });
38
71
 
39
72
  generateMapTestTemplate(
@@ -43,7 +76,7 @@ describe('Translate command', () => {
43
76
  subcommand: 'extract',
44
77
  source: 'ru-RU',
45
78
  target: 'es-ES',
46
- additionalArgs: '--exclude ru/to-be-excluded.md',
79
+ additionalArgs: '--exclude ru/to-be-excluded.md --filter',
47
80
  },
48
81
  );
49
82
 
@@ -55,13 +88,50 @@ describe('Translate command', () => {
55
88
  subcommand: 'extract',
56
89
  source: 'ru-RU',
57
90
  target: 'es-ES',
58
- additionalArgs: `--vars ${JSON.stringify(vars)}`,
91
+ additionalArgs: `--vars ${JSON.stringify(vars)} --filter`,
59
92
  },
60
93
  );
61
94
 
95
+ generateMapTestTemplate(
96
+ 'test no-translate directive',
97
+ 'mocks/translation/no-translate',
98
+ {
99
+ subcommand: 'extract',
100
+ source: 'ru-RU',
101
+ target: 'es-ES',
102
+ },
103
+ false,
104
+ );
105
+
62
106
  generateFilesYamlTestTemplate('extract yaml scheme files', 'mocks/translation/yaml-scheme', {
63
107
  subcommand: 'extract',
64
108
  source: 'ru-RU',
65
109
  target: 'en-US',
66
110
  });
111
+
112
+ let conditionVars = {prod: true, inner: true, list: ['item']};
113
+ generateMapTestTemplate(
114
+ 'save truthy liquid conditions structures',
115
+ 'mocks/translation/conditions',
116
+ {
117
+ subcommand: 'extract',
118
+ source: 'ru-RU',
119
+ target: 'es-ES',
120
+ additionalArgs: `--vars ${JSON.stringify(conditionVars)}`,
121
+ },
122
+ false,
123
+ );
124
+
125
+ conditionVars = {prod: false, inner: false, list: ['item']};
126
+ generateMapTestTemplate(
127
+ 'remove falsy liquid conditions structures',
128
+ 'mocks/translation/conditions',
129
+ {
130
+ subcommand: 'extract',
131
+ source: 'ru-RU',
132
+ target: 'es-ES',
133
+ additionalArgs: `--vars ${JSON.stringify(conditionVars)}`,
134
+ },
135
+ false,
136
+ );
67
137
  });
@@ -34,11 +34,34 @@ class Build {
34
34
  }
35
35
  }
36
36
 
37
+ class Extract {
38
+ private readonly runner: Runner;
39
+
40
+ constructor(runner: Runner) {
41
+ this.runner = runner;
42
+ }
43
+
44
+ run(input: string, output: string, args: string[]) {
45
+ return this.runner.runYfmDocs([
46
+ 'translate',
47
+ 'extract',
48
+ '--input',
49
+ input,
50
+ '--output',
51
+ output,
52
+ '--quiet',
53
+ ...args,
54
+ ]);
55
+ }
56
+ }
57
+
37
58
  export class CliTestAdapter {
38
59
  readonly runner: Runner = createRunner();
39
60
 
40
61
  readonly build = new Build(this.runner);
41
62
 
63
+ readonly extract = new Extract(this.runner);
64
+
42
65
  async testBuildPass(
43
66
  inputPath: string,
44
67
  outputPath: string,
@@ -0,0 +1,4 @@
1
+ declare module "@diplodoc/cli/manifest" {
2
+ const manifest: Record<string, Record<string, string[]>>;
3
+ export = manifest;
4
+ }
@@ -1,5 +1,6 @@
1
1
  import {Runner} from './types';
2
2
  import {execa} from 'execa';
3
+ import strip from 'strip-ansi';
3
4
 
4
5
  export class BinaryRunner implements Runner {
5
6
  private readonly binaryPath: string;
@@ -29,7 +30,7 @@ export class BinaryRunner implements Runner {
29
30
 
30
31
  function fillLog(filter: RegExp, source: string) {
31
32
  return source.split('\n')
32
- .filter((line) => line.match(filter))
33
- .map((line) => line.trim())
34
- .filter(Boolean);
33
+ .map((line) => strip(line).trim())
34
+ .filter(Boolean)
35
+ .filter((line) => line.match(filter));
35
36
  }
@@ -2,9 +2,8 @@ export type Report = {
2
2
  code: number;
3
3
  warns: string[];
4
4
  errors: string[];
5
- }
5
+ };
6
6
 
7
7
  export interface Runner {
8
8
  runYfmDocs(argv: string[]): Promise<Report>;
9
9
  }
10
-
@@ -1,12 +1,12 @@
1
1
  import {readFileSync} from 'node:fs';
2
+ import {rm} from 'node:fs/promises';
2
3
  import {join, resolve} from 'node:path';
3
4
  import {glob} from 'glob';
4
5
  import {bundleless, hashless, platformless} from './test';
5
6
  import {expect} from 'vitest';
6
- import {$} from 'execa';
7
7
 
8
8
  export function getFileContent(filePath: string) {
9
- return bundleless(platformless(readFileSync(filePath, 'utf8')));
9
+ return platformless(bundleless(readFileSync(filePath, 'utf8')));
10
10
  }
11
11
 
12
12
  const uselessFile = (file: string) =>
@@ -21,9 +21,9 @@ export async function compareDirectories(outputPath: string, ignoreFileContent =
21
21
  nodir: true,
22
22
  posix: true,
23
23
  })
24
- ).sort();
24
+ ).map(bundleless).sort();
25
25
 
26
- expect(hashless(bundleless(JSON.stringify(filesFromOutput, null, 2)))).toMatchSnapshot('filelist');
26
+ expect(hashless(JSON.stringify(filesFromOutput, null, 2))).toMatchSnapshot('filelist');
27
27
 
28
28
  if (!ignoreFileContent) {
29
29
  filesFromOutput.filter(uselessFile).forEach((filePath) => {
@@ -46,5 +46,5 @@ export function getTestPaths(testRootPath: string): TestPaths {
46
46
  }
47
47
 
48
48
  export function cleanupDirectory(path: string) {
49
- return $`rm -rf ${path}`;
49
+ return rm(path, {recursive: true, force: true});
50
50
  }
@@ -1,21 +1,34 @@
1
- import {readFileSync} from 'node:fs';
1
+ import assets from '@diplodoc/cli/manifest';
2
2
 
3
3
  export function platformless(text: string): string {
4
+ let index = 1;
5
+
4
6
  return hashless(text)
5
7
  .replace(/\r\n/g, '\n')
8
+ // Fix for XML equiv-text attributes in Windows - handle various patterns
9
+ .replace(/equiv-text="[\r\n]+&#10;"/g, 'equiv-text="&#10;"')
10
+ .replace(/equiv-text="[\r\n]+&amp;#10;"/g, 'equiv-text="&amp;#10;"')
11
+ // Also normalize any other attributes that might have line ending issues
12
+ .replace(/(ctype|id)="[\r\n]+(.*?)"/g, '$1="$2"')
6
13
  .replace(/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/g, 'UUID')
7
- .replace(/(content"?[:=]{1}[" ]{1}Diplodoc.*? )v\d+\.\d+\.\d+(?:-[\w-]+)?/g, `$1vDIPLODOC-VERSION`)
8
- .replace(/(\\(?![/"'])){1,2}/g, '/');
14
+ .replace(
15
+ /(content"?[:=]{1}[" ]{1}Diplodoc.*? )v\d+\.\d+\.\d+(?:-[\w-]+)?/g,
16
+ `$1vDIPLODOC-VERSION`,
17
+ )
18
+ .replace(/(\\(?![/"'])){1,2}/g, '/')
19
+ .replace(
20
+ /id=\\"inline-code-id-[a-zA-Z0-9]{8}\\"/g,
21
+ () => `id="inline-code-id-${index++}"`
22
+ )
9
23
  }
10
24
 
11
25
  export function hashless(text: string): string {
12
26
  return text
13
27
  .replace(/-[a-z0-9]{12}\./g, '-hash.')
28
+ .replace(/(\/|\\)[a-z0-9]{12,13}-(index|registry|resources)\./g, '/hash-$2.');
14
29
  }
15
30
 
16
31
  export function bundleless(text: string): string {
17
- const assets = require('@diplodoc/client/manifest') as Record<string, Record<string, string[]>>;
18
-
19
32
  for (const [entryKey, entry] of Object.entries(assets)) {
20
33
  for (const [typeKey, type] of Object.entries(entry)) {
21
34
  for (let index = 0; index < type.length; index++) {
@@ -31,6 +44,3 @@ export function bundleless(text: string): string {
31
44
  return text;
32
45
  }
33
46
 
34
- export function getNormalizedContent(filePath: string): string {
35
- return bundleless(platformless(readFileSync(filePath, 'utf8')));
36
- }
@@ -0,0 +1,6 @@
1
+ langs: ['en','ru']
2
+
3
+ interface:
4
+ toc: false
5
+ feedback: false
6
+ search: false
@@ -0,0 +1,3 @@
1
+ # Hello World!
2
+
3
+ some text inside
@@ -0,0 +1,5 @@
1
+ title: Test123
2
+ href: index.md
3
+ items:
4
+ - name: Главная
5
+ href: index.md
@@ -0,0 +1 @@
1
+ File exists but not attached to toc
@@ -0,0 +1,7 @@
1
+ [filtered file](./filtered.md)
2
+
3
+ {% if test == "dev" %}[will be deleted on translate-extract](./index.md){% endif %}
4
+
5
+ [second missed link](./filtered2.md)
6
+ [second missed link](./filtered2.md)
7
+ [second missed link](./filtered3.md)
@@ -0,0 +1 @@
1
+ href: index.md
@@ -1,7 +1,14 @@
1
1
  ---
2
+ title: Page Title
3
+ description: Some test description
4
+
5
+ interface:
6
+ toc: false
7
+ favicon-src: /favicon.ico
8
+
2
9
  metadata:
3
10
  - name: yfm
4
- content: builder
11
+ content: builder in page
5
12
  ---
6
13
 
7
- Lorem
14
+ Lorem
@@ -1,7 +1,14 @@
1
1
  ---
2
+ title: Page Title
3
+ description: Some test description
4
+
5
+ interface:
6
+ toc: false
7
+ favicon-src: /favicon.ico
8
+
2
9
  metadata:
3
10
  - name: yfm
4
- content: builder
11
+ content: builder in page
5
12
  ---
6
13
 
7
- Lorem
14
+ Lorem
@@ -1,7 +1,14 @@
1
1
  ---
2
+ title: Page Title
3
+ description: Some test description
4
+
5
+ interface:
6
+ toc: false
7
+ favicon-src: /favicon.ico
8
+
2
9
  metadata:
3
10
  - name: yfm
4
- content: builder
11
+ content: builder in page
5
12
  ---
6
13
 
7
- Lorem
14
+ Lorem
@@ -1,7 +1,14 @@
1
1
  ---
2
+ title: Page Title
3
+ description: Some test description
4
+
5
+ interface:
6
+ toc: false
7
+ favicon-src: /favicon.ico
8
+
2
9
  metadata:
3
10
  - name: yfm
4
- value: builder in page
11
+ content: builder in page
5
12
  ---
6
13
 
7
14
  Lorem
@@ -1,4 +1,11 @@
1
1
  ---
2
+ title: Page Title
3
+ description: Some test description
4
+
5
+ interface:
6
+ toc: false
7
+ favicon-src: /favicon.ico
8
+
2
9
  metadata:
3
10
  - name: yfm
4
11
  content: builder in page
@@ -0,0 +1 @@
1
+ allowHtml: true
@@ -0,0 +1,29 @@
1
+ # Title
2
+
3
+ Text not_var{{not-var}} not_var{{skip()}} {{default-var}}
4
+
5
+ Text `not_var{{not-var}}` `not_var{{skip()}}` `{{default-var}}`
6
+
7
+ Text
8
+ ```
9
+ not_var{{not-var}}
10
+
11
+ not_var{{skip()}}
12
+
13
+ {{default-var}}
14
+ ```
15
+
16
+
17
+ `[not a link](./path/to/relative/file.md)`
18
+
19
+ ## Subtitle {#subtitle}
20
+
21
+ [{#T}](mermaid.md)
22
+
23
+ [{#T}](mermaid.md#info)
24
+
25
+ [](latex.md)
26
+
27
+ [noext-link](includes)
28
+
29
+ {% include [user](includes/user.md) %}
File without changes
File without changes