Skip to content

Commit

Permalink
DOCSTOOLS-794: support link mode to include tocs
Browse files Browse the repository at this point in the history
  • Loading branch information
yndx-birman committed Oct 19, 2021
1 parent f5a40a6 commit 8ec12a0
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 7 deletions.
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export enum Platforms {
LINUX = 'linux',
}

export enum IncludeModes {
MERGE = 'merge',
LINK = 'link'
}

export const BUILD_FOLDER_PATH = dirname(process.mainModule?.filename || '');

export const YFM_PLUGINS = [
Expand Down
3 changes: 2 additions & 1 deletion src/models.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Logger} from '@doc-tools/transform/lib/log';

import {FileContributors, VCSConnector, VCSConnectorConfig} from './vcs-connector/connector-models';
import {Lang, Stage} from './constants';
import {Lang, Stage, IncludeModes} from './constants';

export type VarsPreset = 'internal'|'external';

Expand Down Expand Up @@ -66,6 +66,7 @@ export interface YfmToc extends Filter {
export interface YfmTocInclude {
repo: string;
path: string;
mode?: IncludeModes;
}

export interface LeadingPage {
Expand Down
51 changes: 46 additions & 5 deletions src/services/tocs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {dirname, extname, join, parse, resolve} from 'path';
import {dirname, extname, join, parse, resolve, relative} from 'path';
import {copyFileSync, readFileSync, writeFileSync, existsSync} from 'fs';
import {load, dump} from 'js-yaml';
import shell from 'shelljs';
Expand All @@ -10,14 +10,15 @@ import {bold} from 'chalk';

import {ArgvService, PresetService} from './index';
import {YfmToc} from '../models';
import {Stage, SINGLE_PAGE_FOLDER} from '../constants';
import {Stage, SINGLE_PAGE_FOLDER, IncludeModes} from '../constants';
import {isExternalHref} from '../utils';
import {filterFiles} from './utils';
import {cloneDeep as _cloneDeep} from 'lodash';

const storage: Map<string, YfmToc> = new Map();
const navigationPaths: string[] = [];
const singlePageNavigationPaths: Set<string> = new Set();
const includedTocPaths: Set<string> = new Set();

function add(path: string) {
const {
Expand Down Expand Up @@ -117,6 +118,10 @@ function getSinglePageNavigationPaths(): Set<string> {
return new Set(singlePageNavigationPaths);
}

function getIncludedTocPaths(): string[] {
return [...includedTocPaths];
}

function prepareNavigationPaths(parsedToc: YfmToc, dirPath: string) {
function processItems(items: YfmToc[], pathToDir: string) {
items.forEach((item) => {
Expand Down Expand Up @@ -211,6 +216,31 @@ function _copyTocDir(tocPath: string, destDir: string) {
});
}

/**
* Make hrefs relative to the main toc in the included toc.
* @param includedToc
* @param includeTocDir
* @param tocDir
* @return
* @private
*/
function _replaceIncludesHrefs(includedToc: YfmToc, includeTocDir: string, tocDir: string) {
if (includedToc.items) {
includedToc.items.forEach((item) => {
if (item.href) {
item.href = relative(tocDir, resolve(includeTocDir, item.href));
}

_replaceIncludesHrefs(item, includeTocDir, tocDir);
});
}

if (includedToc.include) {
const {path} = includedToc.include;
includedToc.include.path = relative(tocDir, resolve(includeTocDir, path));
}
}

/**
* Liquid substitutions in toc file.
* @param input
Expand Down Expand Up @@ -249,8 +279,10 @@ function _replaceIncludes(items: YfmToc[], tocDir: string, sourcesDir: string, v
}

if (item.include) {
const {path} = item.include;
const includeTocPath = resolve(sourcesDir, path);
const {path, mode = IncludeModes.MERGE} = item.include;
const includeTocPath = mode === IncludeModes.MERGE
? resolve(sourcesDir, path)
: resolve(tocDir, path);

try {
const includeToc = load(readFileSync(includeTocPath, 'utf8')) as YfmToc;
Expand All @@ -260,7 +292,15 @@ function _replaceIncludes(items: YfmToc[], tocDir: string, sourcesDir: string, v
return acc;
}

_copyTocDir(includeTocPath, tocDir);
if (mode === IncludeModes.MERGE) {
_copyTocDir(includeTocPath, tocDir);
} else if (mode === IncludeModes.LINK) {
_replaceIncludesHrefs(includeToc, dirname(includeTocPath), tocDir);
}

/* Save the path to exclude toc from the output directory in the next step */
includedTocPaths.add(includeTocPath);

item.items = (item.items || []).concat(includeToc.items);
} catch (err) {
log.error(`Error while including toc: ${bold(includeTocPath)} to ${bold(join(tocDir, 'toc.yaml'))}`);
Expand Down Expand Up @@ -302,4 +342,5 @@ export default {
getNavigationPaths,
getSinglePageNavigationPaths,
getTocDir,
getIncludedTocPaths,
};
13 changes: 12 additions & 1 deletion src/steps/processExcludedFiles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {resolve} from 'path';
import {resolve, relative} from 'path';
import walkSync from 'walk-sync';
import shell from 'shelljs';

Expand All @@ -12,6 +12,7 @@ import {convertBackSlashToSlash} from '../utils';
export function processExcludedFiles() {
const {
input: inputFolderPath,
output: outputFolderPath,
ignore,
} = ArgvService.getConfig();

Expand All @@ -33,4 +34,14 @@ export function processExcludedFiles() {
.filter((filePath) => !tocSpecifiedFiles.has(filePath));

shell.rm('-f', excludedFiles);

const includedTocPaths = TocService.getIncludedTocPaths()
.map((filePath) => {
const relativeTocPath = relative(inputFolderPath, filePath);
const destTocPath = resolve(outputFolderPath, relativeTocPath);

return convertBackSlashToSlash(destTocPath);
});

shell.rm('-f', includedTocPaths);
}
20 changes: 20 additions & 0 deletions tests/include-toc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {compareDirectories, runYfmDocs, getTestPaths} from './utils';

describe('Include toc', () => {
test('Test1', () => {
const testRootPath = './tests/mocks/include-toc/test1';
const {inputPath, outputPath, expectedOutputPath} = getTestPaths(testRootPath);

runYfmDocs(inputPath, outputPath);

const compareResult = compareDirectories(outputPath, expectedOutputPath);

if (typeof compareResult === 'boolean') {
expect(true).toEqual(compareResult);
} else {
const {expectedContent, outputContent} = compareResult;

expect(expectedContent).toEqual(outputContent);
}
});
});
1 change: 1 addition & 0 deletions tests/mocks/include-toc/test1/expected-output/a1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /a1.md file content.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /folder1/a1.md file content.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /folder1/folder1/a1.md file content.
12 changes: 12 additions & 0 deletions tests/mocks/include-toc/test1/expected-output/folder1/toc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
items:
- name: A1
href: a1.md
- name: folder1
items:
- name: A1
href: folder1/a1.md
- name: folder1
items:
- name: A1
href: folder1/folder2/a1.md
base: .
12 changes: 12 additions & 0 deletions tests/mocks/include-toc/test1/expected-output/toc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
items:
- name: A1
href: a1.md
- name: folder1
items:
- name: A1
href: folder1/a1.md
- name: folder1
items:
- name: A1
href: folder1/folder2/a1.md
base: .
1 change: 1 addition & 0 deletions tests/mocks/include-toc/test1/input/a1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /a1.md file content.
1 change: 1 addition & 0 deletions tests/mocks/include-toc/test1/input/folder1/a1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /folder1/a1.md file content.
1 change: 1 addition & 0 deletions tests/mocks/include-toc/test1/input/folder1/folder2/a1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the /folder1/folder1/a1.md file content.
5 changes: 5 additions & 0 deletions tests/mocks/include-toc/test1/input/folder1/folder2/toc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
items:
- name: A1
href: a1.md


7 changes: 7 additions & 0 deletions tests/mocks/include-toc/test1/input/folder1/toc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
items:
- name: A1
href: a1.md
- name: folder1
include:
mode: link
path: folder2/toc.yaml
9 changes: 9 additions & 0 deletions tests/mocks/include-toc/test1/input/toc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
items:
- name: A1
href: a1.md
- name: folder1
include:
mode: link
path: folder1/toc.yaml


0 comments on commit 8ec12a0

Please sign in to comment.