Skip to content

Commit

Permalink
Merge pull request #86 from mtmacdonald/refactor-ts
Browse files Browse the repository at this point in the history
Continue refactoring code to TypeScript + splitting into modules
  • Loading branch information
mtmacdonald committed Oct 30, 2023
2 parents c01e3c7 + 07070ab commit 9b77c2f
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 167 deletions.
8 changes: 3 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<!doctype html>
<html>
<head>
<!DOCTYPE html><html><head>
<title>DocGen - a documentation tool</title>
<meta http-equiv="REFRESH" content="0;url=docs/index.html">
</head>
<body>
<a href="docs/index.html" style="color:#ccc;font-size:12px">Redirect to homepage</a>
</body>
</html>

</body></html>
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
"dev": "ts-node src/docgen.ts run",
"build": "rimraf dist && tsc -p tsconfig.json && yarn copy:files",
"run:build": "dist/docgen.ts",
"build:docs": "ts-node src/docgen.ts run -i src/docs -o ./docs -p -m -n -d 40000",
"build:docs:nopdf": "ts-node src/docgen.ts run -i src/docs -m -n -o ./docs",
"build:docs": "ts-node src/docgen.ts run -m -n -r -p -d 40000 -i src/docs -o ./docs",
"build:docs:nopdf": "ts-node src/docgen.ts run -m -n -r -i src/docs -o ./docs",
"build:styles": "sass --no-source-map src/styles/main.scss src/include/require/styles/framework.css",
"test": "npm run prettier:check",
"test:run": "rimraf src/__test__/test-run-output && ts-node src/docgen.ts run -i src/__test__/test-run -o src/__test__/test-run-output -p -m -n -d 40000",
"test:scaffold": "rimraf src/__test__/test-run-output && ts-node src/docgen.ts scaffold -o src/__test__/test-run-output",
"test:prod:run": "rimraf src/__test__/test-run-output && ./dist/docgen.js run -i src/__test__/test-run -o ../source/__test__/test-run-output -p -m -n -d 40000",
"prettier:check": "prettier --check 'src/docgen.ts' '*.{js,json,css,less}'",
"prettier:fix": "prettier --write 'src/docgen.ts' '*.{js,json,css,less}'"
"prettier:check": "prettier --check 'src/docgen.ts' '*.{ts,js,json,css,less}'",
"prettier:fix": "prettier --write 'src/docgen.ts' '*.{ts,js,json,css,less}'"
},
"husky": {
"hooks": {
Expand Down
188 changes: 30 additions & 158 deletions src/docgen/docgen.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import {
} from './fs/fs';
import { validateJSON } from './validation/validation';
import { checkPdfVersion, generatePdf } from './pdf/wkhtmltopdf/wkhtmltopdf';
import { scaffold } from './scaffold/scaffold';
import { sortPages } from './meta/sort-pages';
import { generateWebTableOfContents } from './html/web-table-of-contents';
import { processPages } from './html/process-pages';
import { createRedirect } from './html/redirect';
import { version } from '../../package.json';

const markdown = new MarkdownIt('commonmark').enable('table');
Expand Down Expand Up @@ -56,25 +61,29 @@ export function DocGen(process) {
copy the example src files (template) to any directory, when scaffold command is invoked
*/

this.scaffold = async () => {
console.log(chalk.green('Creating scaffold template directory'));
await copyDirectory(
__dirname + '/../include/example',
options.output,
options.verbose === true,
);
};
this.scaffold = async () =>
scaffold({
outputDirectory: options.output,
verbose: options.verbose === true,
});

this.run = async () => {
console.log(chalk.green.bold('DocGen version ' + version));
//delete and recreate the output directory
await cleanDirectory(options.output);
await loadTemplates();
await loadMeta();
sortedPages = sortPages({ tableOfContents: meta.contents });
await loadMarkdown();
await processContent();
await writePages();
await createRedirect();
await createRedirect({
isRedirectEnabled: options.redirect,
outputDirectory: options.output,
redirectTemplate: templates.redirect,
homePage: meta.contents[0].pages[0],
verbose: options.verbose,
});
if (options.pdf === true) {
await checkPdfVersion({ options, mainProcess });
await generatePdf({ options, meta, sortedPages, mainProcess });
Expand Down Expand Up @@ -222,71 +231,6 @@ export function DocGen(process) {
}
};

let sortPages = () => {
//sort the contents by heading
let headings = { 1: [], 2: [], 3: [], 4: [], 5: [] };
meta.contents.forEach((section) => {
if (headings.hasOwnProperty(section.column)) {
headings[section.column].push(section);
}
});
sortedPages = headings;
};

/*
build the HTML for the table of contents
*/

let webToc = () => {
sortPages();
let pdfName = meta.parameters.name.toLowerCase() + '.pdf';
let $ = templates.main;
let html = [],
i = -1;
html[++i] = '<div><table class="unstyled"><tr>';
//build the contents HTML
for (let key in sortedPages) {
if (sortedPages.hasOwnProperty(key)) {
if (key != 5) {
//skip the extra column
html[++i] = '<td class="dg-tocGroup">';
sortedPages[key].forEach((section) => {
html[++i] =
'<ul><li class="dg-tocHeading">' + section.heading + '</li>';
section.pages.forEach((page) => {
let name = page.source.substr(0, page.source.lastIndexOf('.'));
let path = name + '.html';
html[++i] =
'<li><a href="' + path + '">' + page.title + '</a></li>';
});
html[++i] = '</li></ul>';
});
html[++i] = '</td>';
}
}
}

//fixed-width column at end
html[++i] = '<td class="dg-tocGroup" id="dg-tocFixedColumn"><ul>';
html[++i] =
'<li><span class="w-icon dg-tocIcon" data-name="person_group" title="archive"></span><a href="ownership.html">Ownership</a></li>';
html[++i] =
'<li><span class="w-icon dg-tocIcon" data-name="refresh" title="archive"></span><a href="release-notes.html">Release Notes</a></li>';
html[++i] = '</ul><div>';
if (options.pdf) {
html[++i] =
'<button class="whiteInverted" onclick="window.location=\'' +
pdfName +
'\';">';
html[++i] = '<span>PDF</span>';
html[++i] = '</button>';
}
html[++i] = '</div></td>';
html[++i] = '</tr></table></div>';
$('#dg-toc').html(html.join(''));
templates.main = $;
};

/*
insert the parameters into all templates
*/
Expand Down Expand Up @@ -498,68 +442,20 @@ export function DocGen(process) {
*/

let processContent = async () => {
console.log(chalk.green('Generating the static web content'));
webToc();
templates.main = generateWebTableOfContents({
sortedPages,
name: meta.parameters.name,
mainTemplate: templates.main,
pdfEnabled: options.pdf,
});
insertParameters();
meta.contents.forEach((section) => {
section.pages.forEach((page) => {
let $ = cheerio.load(templates.main.html()); //clone
let key = page.source;
let content = pages[key];
//add relevant container
if (page.html === true) {
//raw HTML pages should not be confined to the fixed width
$('#dg-content').html('<div id="dg-innerContent"></div>');
} else {
//Markdown pages should be confined to the fixed width
$('#dg-content').html(
'<div class="w-fixed-width"><div id="dg-innerContent"></div></div>',
);
}
$('#dg-innerContent').html(content);
//------------------------------------------------------------------------------------------------------
//insert permalinks for every page heading
//when pageToc is enabled, also insert a page-level table of contents
let html = [],
i = -1;
let headings = $('h1, h2, h3, h4, h5, h6');
if (headings.length > 0) {
html[++i] = '<ul class="dg-pageToc">';
}
headings.each(function () {
let label = $(this).text();
let anchor = label.toLowerCase().replace(/\s+/g, '-');
$(this).attr('id', anchor);
html[++i] = '<li><a href="#' + anchor + '">' + label + '</a></li>';
});
if (headings.length > 0) {
html[++i] = '</ul>';
}
if (options.pageToc === true && page.html !== true) {
$('#dg-innerContent').prepend(html.join(''));
}
//------------------------------------------------------------------------------------------------------
//prepend the auto heading (which makes the PDF table of contents match the web TOC)
$('#dg-innerContent').prepend(
'<h1 id="dg-autoTitle">' + page.title + '</h1>',
);
if (page.html === true) {
$('#dg-autoTitle').addClass('dg-hiddenTitle');
}
//------------------------------------------------------------------------------------------------------
//apply the w-table class
$('table:not(.unstyled)').addClass('w-table w-fixed w-stripe');
//------------------------------------------------------------------------------------------------------
pages[key] = $;
});
templates.webCover = await processPages({
pages,
pageTableOfContentsEnabled: options.pageToc,
tableOfContents: meta.contents,
mainTemplate: templates.main,
webCover: templates.webCover,
});
//add web ownership page
let $ = cheerio.load(templates.main.html()); //clone
$('#dg-content').html(
'<div class="w-fixed-width"><div id="dg-innerContent"></div></div>',
);
$('#dg-innerContent').html(templates.webCover.html());
templates.webCover = $;
};

/*
Expand Down Expand Up @@ -625,28 +521,4 @@ export function DocGen(process) {
mainProcess.exit(1);
}
};

let createRedirect = async () => {
if (options.redirect) {
let parent = options.output.replace(/\/$/, ''); //trim any trailing slash
parent = parent.split(path.sep).slice(-1).pop(); //get name of final directory in the path
let homepage = meta.contents[0].pages[0];
homepage =
homepage.source.substr(0, homepage.source.lastIndexOf('.')) + '.html';
let redirectLink = parent + '/' + homepage;
let $ = templates.redirect;
$('a').attr('href', redirectLink);
$('meta[http-equiv=REFRESH]').attr('content', '0;url=' + redirectLink);
let file = options.output + '../' + 'index.html';
try {
await writeFile(file, $.html());
} catch (error) {
console.log(chalk.red('Error writing redirect file: ' + file));
if (options.verbose === true) {
console.log(chalk.red(error));
}
//don't exit because redirect error is not a fatal error
}
}
};
}
71 changes: 71 additions & 0 deletions src/docgen/html/process-pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import chalk from 'chalk';
import cheerio from 'cheerio';

export const processPages = async ({
pages,
pageTableOfContentsEnabled,
tableOfContents,
mainTemplate,
webCover
}) => {
console.log(chalk.green('Generating the static web content'));
tableOfContents.forEach((section) => {
section.pages.forEach((page) => {
let $ = cheerio.load(mainTemplate.html()); //clone
let key = page.source;
let content = pages[key];
//add relevant container
if (page.html === true) {
//raw HTML pages should not be confined to the fixed width
$('#dg-content').html('<div id="dg-innerContent"></div>');
} else {
//Markdown pages should be confined to the fixed width
$('#dg-content').html(
'<div class="w-fixed-width"><div id="dg-innerContent"></div></div>',
);
}
$('#dg-innerContent').html(content);
//------------------------------------------------------------------------------------------------------
//insert permalinks for every page heading
//when pageToc is enabled, also insert a page-level table of contents
let html = [],
i = -1;
let headings = $('h1, h2, h3, h4, h5, h6');
if (headings.length > 0) {
html[++i] = '<ul class="dg-pageToc">';
}
headings.each(function () {
let label = $(this).text();
let anchor = label.toLowerCase().replace(/\s+/g, '-');
$(this).attr('id', anchor);
html[++i] = '<li><a href="#' + anchor + '">' + label + '</a></li>';
});
if (headings.length > 0) {
html[++i] = '</ul>';
}
if (pageTableOfContentsEnabled === true && page.html !== true) {
$('#dg-innerContent').prepend(html.join(''));
}
//------------------------------------------------------------------------------------------------------
//prepend the auto heading (which makes the PDF table of contents match the web TOC)
$('#dg-innerContent').prepend(
'<h1 id="dg-autoTitle">' + page.title + '</h1>',
);
if (page.html === true) {
$('#dg-autoTitle').addClass('dg-hiddenTitle');
}
//------------------------------------------------------------------------------------------------------
//apply the w-table class
$('table:not(.unstyled)').addClass('w-table w-fixed w-stripe');
//------------------------------------------------------------------------------------------------------
pages[key] = $;
});
});
//add web ownership page
let $ = cheerio.load(mainTemplate.html()); //clone
$('#dg-content').html(
'<div class="w-fixed-width"><div id="dg-innerContent"></div></div>',
);
$('#dg-innerContent').html(webCover.html());
return $;
};
33 changes: 33 additions & 0 deletions src/docgen/html/redirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import chalk from 'chalk';
import path from 'path';
import { writeFile } from '../fs/fs';

export let createRedirect = async ({
isRedirectEnabled,
outputDirectory,
redirectTemplate,
homePage,
verbose
}) => {
if (isRedirectEnabled) {
let parent = outputDirectory.replace(/\/$/, ''); //trim any trailing slash
parent = parent.split(path.sep).slice(-1).pop(); //get name of final directory in the path
let homepage = homePage;
homepage =
homepage.source.substr(0, homepage.source.lastIndexOf('.')) + '.html';
let redirectLink = parent + '/' + homepage;
let $ = redirectTemplate;
$('a').attr('href', redirectLink);
$('meta[http-equiv=REFRESH]').attr('content', '0;url=' + redirectLink);
let file = outputDirectory + '../' + 'index.html';
try {
await writeFile(file, $.html());
} catch (error) {
console.log(chalk.red('Error writing redirect file: ' + file));
if (verbose === true) {
console.log(chalk.red(error));
}
//don't exit because redirect error is not a fatal error
}
}
};
Loading

0 comments on commit 9b77c2f

Please sign in to comment.