Skip to content

Commit

Permalink
DOCSTOOLS-795: fixes for single-page
Browse files Browse the repository at this point in the history
  • Loading branch information
yndx-birman committed Sep 5, 2022
1 parent 59ec006 commit 1fc9692
Show file tree
Hide file tree
Showing 51 changed files with 410 additions and 45 deletions.
2 changes: 2 additions & 0 deletions src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export interface PluginOptions {
log: Logger;
copyFile: (targetPath: string, targetDestPath: string, options?: PluginOptions) => void;
singlePage?: boolean;
singlePageRoot?: string;
root?: string;
destPath?: string;
destRoot?: string;
Expand All @@ -179,6 +180,7 @@ export interface ResolveMd2MdOptions {
inputPath: string;
outputPath: string;
singlePage?: boolean;
singlePageRoot?: string;
metadata?: MetaDataOptions;
}

Expand Down
17 changes: 14 additions & 3 deletions src/resolvers/md2md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {dirname, resolve} from 'path';
import shell from 'shelljs';
import log from '@doc-tools/transform/lib/log';
import liquid from '@doc-tools/transform/lib/liquid';
import yfmlint from '@doc-tools/transform/lib/yfmlint';
import {loadFront} from 'yaml-front-matter';

import {ArgvService, PluginService} from '../services';
import {logger, getVarsPerFile} from '../utils';
Expand All @@ -11,24 +13,31 @@ import {PROCESSING_FINISHED} from '../constants';
import {getContentWithUpdatedMetadata} from '../services/metadata';

export async function resolveMd2Md(options: ResolveMd2MdOptions): Promise<string | void> {
const {inputPath, outputPath, singlePage, metadata} = options;
const {input, output} = ArgvService.getConfig();
const {inputPath, outputPath, singlePage, singlePageRoot, metadata} = options;
const {input, output, vars: configVars} = ArgvService.getConfig();
const resolvedInputPath = resolve(input, inputPath);
const vars = getVarsPerFile(inputPath);

const content = await getContentWithUpdatedMetadata(
let content = await getContentWithUpdatedMetadata(
readFileSync(resolvedInputPath, 'utf8'),
metadata,
vars.__system,
);

// Remove metadata when preparing single page
if (singlePage) {
const {__content} = loadFront(content);
content = __content;
}

const {result} = transformMd2Md(content, {
path: resolvedInputPath,
destPath: outputPath,
root: resolve(input),
destRoot: resolve(output),
collectOfPlugins: PluginService.getCollectOfPlugins(),
singlePage,
singlePageRoot,
vars,
log,
copyFile,
Expand Down Expand Up @@ -85,6 +94,7 @@ function transformMd2Md(input: string, options: PluginOptions) {
log: pluginLog,
copyFile: pluginCopyFile,
singlePage,
singlePageRoot,
} = options;

let output = input;
Expand All @@ -106,6 +116,7 @@ function transformMd2Md(input: string, options: PluginOptions) {
copyFile: pluginCopyFile,
collectOfPlugins,
singlePage,
singlePageRoot,
});
}

Expand Down
43 changes: 32 additions & 11 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, relative} from 'path';
import {dirname, extname, join, parse, resolve, relative, normalize} from 'path';
import {copyFileSync, readFileSync, writeFileSync, existsSync, mkdirSync} from 'fs';
import {load, dump} from 'js-yaml';
import shell from 'shelljs';
Expand Down Expand Up @@ -98,14 +98,20 @@ async function add(path: string) {
/* Store path to toc file to handle relative paths in navigation */
parsedToc.base = pathToDir;

const singlePageFilesInitialCount = singlePageNavigationPaths.size;

prepareNavigationPaths(parsedToc, pathToDir);

const singlePageFilesCount = singlePageNavigationPaths.size - singlePageFilesInitialCount;

if (outputFormat === 'md') {
/* Should copy resolved and filtered toc to output folder */
const outputPath = resolve(outputFolderPath, path);
const outputToc = dump(parsedToc);
shell.mkdir('-p', dirname(outputPath));
writeFileSync(outputPath, outputToc);

if (singlePage) {
if (singlePage && singlePageFilesCount) {
const parsedSinglePageToc = _cloneDeep(parsedToc);
const currentPath = resolve(outputFolderPath, path);
parsedSinglePageToc.items = filterFiles(parsedSinglePageToc.items, 'items', {}, {
Expand All @@ -122,8 +128,6 @@ async function add(path: string) {
writeFileSync(outputSinglePageTocPath, outputSinglePageToc);
}
}

prepareNavigationPaths(parsedToc, pathToDir);
}

function getForPath(path: string): YfmToc|undefined {
Expand Down Expand Up @@ -169,7 +173,9 @@ function prepareNavigationPaths(parsedToc: YfmToc, dirPath: string) {
});
}

processItems([parsedToc], dirPath);
const clonedParsedToc = _cloneDeep(parsedToc);

processItems([clonedParsedToc], dirPath);
}

function prepareTocForSinglePageMode(parsedToc: YfmToc, options: {root: string; currentPath: string}) {
Expand Down Expand Up @@ -201,15 +207,17 @@ function prepareTocForSinglePageMode(parsedToc: YfmToc, options: {root: string;
* @private
*/
function _normalizeHref(href: string): string {
if (href.endsWith('.md') || href.endsWith('.yaml')) {
return href;
const preparedHref = normalize(href);

if (preparedHref.endsWith('.md') || preparedHref.endsWith('.yaml')) {
return preparedHref;
}

if (href.endsWith('/')) {
return `${href}index.yaml`;
if (preparedHref.endsWith('/')) {
return `${preparedHref}index.yaml`;
}

return `${href}.md`;
return `${preparedHref}.md`;
}

/**
Expand Down Expand Up @@ -362,6 +370,18 @@ function _liquidSubstitutions(input: string, vars: Record<string, string>, path:
});
}

function addIncludeTocPath(includeTocPath: string) {
const {singlePage} = ArgvService.getConfig();

includedTocPaths.add(includeTocPath);

if (singlePage) {
const includeSinglePageTocDir = resolve(dirname(includeTocPath), SINGLE_PAGE_FOLDER);

includedTocPaths.add(includeSinglePageTocDir);
}
}

/**
* Replaces include fields in toc file by resolved toc.
* @param items
Expand Down Expand Up @@ -399,8 +419,9 @@ function _replaceIncludes(items: YfmToc[], tocDir: string, sourcesDir: string, v
if (mode === IncludeMode.MERGE || mode === IncludeMode.ROOT_MERGE) {
_copyTocDir(includeTocPath, tocDir);
}

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

let includedTocItems = (item.items || []).concat(includeToc.items);

Expand Down
2 changes: 1 addition & 1 deletion src/steps/processExcludedFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ export function processExcludedFiles() {
return convertBackSlashToSlash(destTocPath);
});

shell.rm('-f', includedTocPaths);
shell.rm('-rf', includedTocPaths);
}
39 changes: 27 additions & 12 deletions src/steps/processPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function processPages(outputBundlePath: string): Promise<void> {
logger.proc(pathToFile);

if (singlePage && outputFormat === 'md' && singlePageNavigationPaths.has(pathToFile)) {
await preparingSinglePages(pathData, singlePage, outputFolderPath);
promises.push(preparingSinglePages(pathData, singlePage, outputFolderPath));
}

const metaDataOptions = getMetaDataOptions(pathData, inputFolderPath.length, vcsConnector);
Expand All @@ -48,6 +48,10 @@ export async function processPages(outputBundlePath: string): Promise<void> {
}

await Promise.all(promises);

if (singlePage) {
saveSinglePages();
}
}

function getPathData(
Expand Down Expand Up @@ -79,22 +83,39 @@ function getPathData(
return pathData;
}

function saveSinglePages() {
try {
for (const singlePageDir of Object.keys(singlePagePaths)) {
if (singlePagePaths[singlePageDir].size) {
const singlePageFn = join(singlePageDir, 'index.md');
const content = joinSinglePageResults(singlePageResults[singlePageDir]);

writeFileSync(singlePageFn, content);
}
}
} catch (error) {
console.log(error);
}
}

async function preparingSinglePages(pathData: PathData, singlePage: boolean, outputFolderPath: string): Promise<void> {
try {
const {pathToFile, outputPath, fileExtension} = pathData;
const pathToDir: string = dirname(pathToFile);
const outputSinglePageDir = resolve(TocService.getTocDir(outputPath), SINGLE_PAGE_FOLDER);
const outputSinglePageFileDir = resolve(outputSinglePageDir, pathToDir);
const outputSinglePageFn = resolve(outputSinglePageDir, pathToFile);

shell.mkdir('-p', outputSinglePageFileDir);
singlePagePaths[outputSinglePageDir] = singlePagePaths[outputSinglePageDir] || new Set();

const isExistFileAsSinglePage =
singlePagePaths[outputSinglePageDir] && singlePagePaths[outputSinglePageDir].has(pathToFile);

if (!(fileExtension === '.yaml') && !isExistFileAsSinglePage) {
const outputSinglePageContent =
await resolveMd2Md({inputPath: pathToFile, outputPath: outputSinglePageFn, singlePage});
await resolveMd2Md({
inputPath: pathToFile,
outputPath,
singlePage,
singlePageRoot: outputSinglePageDir,
});

const absolutePathToFile = resolve(outputFolderPath, pathToFile);
const relativePathToOriginalFile = relative(outputSinglePageDir, absolutePathToFile);
Expand All @@ -105,14 +126,8 @@ async function preparingSinglePages(pathData: PathData, singlePage: boolean, out
content: outputSinglePageContent,
});

singlePagePaths[outputSinglePageDir] = singlePagePaths[outputSinglePageDir] || new Set();
singlePagePaths[outputSinglePageDir].add(pathToFile);
}

const singlePageFn = join(outputSinglePageDir, 'index.md');
const content = joinSinglePageResults(singlePageResults[outputSinglePageDir]);

writeFileSync(singlePageFn, content);
} catch (error) {
console.log(error);
}
Expand Down
17 changes: 17 additions & 0 deletions tests/e2e/single-page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,21 @@ describe('Single page', () => {
expect(expectedContent).toEqual(outputContent);
}
});

test('Test4', () => {
const testRootPath = './tests/mocks/single-page/test4';
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);
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This is the /folder1/folder1/a1.md file content.


<hr class="yfm-page__delimeter">

This is the /folder1/a1.md file content.


<hr class="yfm-page__delimeter">

This is the /folder1/folder1/a1.md file content.


<hr class="yfm-page__delimeter">

This is the /a1.md file content.


<hr class="yfm-page__delimeter">

This is the /folder1/a1.md file content.


<hr class="yfm-page__delimeter">

This is the /folder1/folder1/a1.md file content.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
items:
- name: A1
href: a1.md
href: '#_a1'
- name: folder1
items:
- name: A1
href: folder1/a1.md
href: '#_folder1_a1'
- name: folder1
items:
- name: A1
href: folder1/folder2/a1.md
href: '#_folder1_folder2_a1'
base: .
href: index.md
singlePage: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## File C {data-original-article=/folder/folder/fileC} {#_folder_folder_fileC_file-c} {#_folder_folder_fileC}


<hr class="yfm-page__delimeter">

## File B {data-original-article=/folder/fileB} {#_folder_fileB_file-b} {#_folder_fileB}

Lorem Ipsum is simply dummy text of the printing and typesetting industry.

---

Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.

---


<hr class="yfm-page__delimeter">


## File C {data-original-article=/folder/fileC} {#_folder_fileC_file-c} {#_folder_fileC}


<hr class="yfm-page__delimeter">

## File 1 {data-original-article=/file1} {#_file1_file-1} {#_file1}


<hr class="yfm-page__delimeter">


## File B {data-original-article=/fileB} {#_fileB_file-b} {#_fileB}

Lorem Ipsum is simply dummy text of the printing and typesetting industry.

---

Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.

---


<hr class="yfm-page__delimeter">


## File C {data-original-article=/fileC} {#_fileC_file-c} {#_fileC}


<hr class="yfm-page__delimeter">

## File X {data-original-article=/fileX} {#_fileX_file-x} {#_fileX}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
items:
- name: Name1
href: '#_file1'
- name: NameA
href: '#_fileA'
- name: NameB
href: '#_fileB'
- name: NameC
href: '#_fileC'
- name: NameX
href: '#_fileX'
base: .
href: index.md
singlePage: true
Loading

0 comments on commit 1fc9692

Please sign in to comment.