Skip to content

Instantly share code, notes, and snippets.

@MarkusGnigler
Last active March 24, 2022 11:11
Show Gist options
  • Save MarkusGnigler/a717b1c9969db0935207bc5af3bb0fab to your computer and use it in GitHub Desktop.
Save MarkusGnigler/a717b1c9969db0935207bc5af3bb0fab to your computer and use it in GitHub Desktop.
generate multiple compodoc site's from nx workspace angular app's or lib's
stages:
- publish
pages:
image: node:16-alpine
stage: publish
before_script:
- npm install fs-extra
script:
- node ./tools/scripts/generate-documentation.ts
- node ./tools/scripts/generate-documentation-root.ts
- mv ./dist/documentation ./public
artifacts:
paths:
- public/
only:
- main

Generate multiple compodoc site's from nx workspace angular app's or lib's

With these two scripts it's possible to generate a compodoc site from an @nrwl/nx monorepo for each library and generate a root index.html that serves as a minimal menu.

Generate all

All scripts must be in ./tools/scripts otherwise you should alter all hardcoded path's to your needs.

  • ROOT_PATH
  • const angularJson = require('../../angular.json');

Generated source code will be copied to dist/documentation

node ./tools/scripts/generate-documentation.ts
node ./tools/scripts/generate-documentation-root.ts

Gitlab pages

With this scripts it's also possible to generate gitlab/github/what-ever pages.

A Gitlab CI pipeline is prepared.

Enhancement

Yes in fact each compodoc site have all off compodoc's js and css. I'm not aware of an alternative solution yet.

const { writeFile, writeFileSync } = require('fs-extra');
const angularJson = require('../../angular.json');
const ROOT_PATH = 'dist/documentation';
const projectKeys = Object.keys(angularJson.projects);
const projectValues = Object.values(angularJson.projects);
const parseAngularJsonToCardItem = () =>
projectKeys
.filter((_, index) => projectValues[index]['projectType'] === 'library')
.map(name => `<a href="${name}/index.html">${name}</a>`)
.map(link => `<div class="card flex-item">${link}</div>`);
const getCssStyles = () => `
html,
body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica, sans-serif;
}
body {
height: 100vh;
color: #fff;
background: #323232;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.flex {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 25px;
}
.flex-item {
flex: 0 0 calc(75% - (150px / 4));
}
.card {
padding: 25px;
background: #232323;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
transition: 0.3s;
text-align: center;
}
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}
a:link,
a:visited {
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
}
a:hover,
a:active {
color: rgb(160, 160, 160);
}`;
const getHtmlDocument = (title, styles, htmlBody) => `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${title}</title>
<style>
${styles}
</style>
</head>
<body>
${htmlBody}
</body>
</html>`;
const getHtmlContent = cardItems => {
const cardsContent = cardItems.reduce((acc, curr) => acc + curr);
return '<section class="flex">' + cardsContent + '</section>';
};
const writeIndexHtmlToDisk = () => {
const filePath = `${ROOT_PATH}/index.html`;
const documentTitle = 'Documentation of masp.frontend';
const cssStyles = getCssStyles();
const htmlContent = getHtmlContent(parseAngularJsonToCardItem());
const htmlDocument = getHtmlDocument(documentTitle, cssStyles, htmlContent);
writeFileSync(filePath, htmlDocument);
};
writeIndexHtmlToDisk();
const fs = require('fs');
const exec = require('child_process').exec;
const angularJson = require('../../angular.json');
const ROOT_PATH = 'dist/documentation';
const projectKeys = Object.keys(angularJson.projects);
const projectValues = Object.values(angularJson.projects);
const runCompodoc = async () => {
parseAngularJson()
.map(project => getCommand(project))
.forEach(async command => await exec(await command));
};
const parseAngularJson = () =>
projectKeys
//.filter((_, index) => projectValues[index]['projectType'] === 'library')
.map(name => ({ name, project: projectValues[0] }))
.map(proj => ({ name: proj.name, tsConfigPath: getTsConfigPath(proj.project) }));
const getTsConfigPath = project =>
project['projectType'] === 'library'
? `${project['root']}/tsconfig.lib.json`
: `${project['root']}/tsconfig.app.json`;
const getCommand = async project => {
const additionalDocumentationPath = `./libs/${project.name}/compodoc`;
return (await fs.existsSync(additionalDocumentationPath))
? `npx compodoc --tsconfig ${project.tsConfigPath} --includes ${additionalDocumentationPath} --output dist/documentation/${project.name}`
: `npx compodoc --tsconfig ${project.tsConfigPath} --output dist/documentation/${project.name}`;
};
runCompodoc();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment