mirror of
https://github.com/nestjs/docs.nestjs.com.git
synced 2026-02-25 22:15:07 +00:00
feat(): Compile markdown using dgeni
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -125,3 +125,4 @@ src/app/homepage/pages/controllers/controllers.component.html
|
||||
src/app/homepage/pages/pipes/pipes.component.html
|
||||
src/app/homepage/pages/recipes/crud/crud.component.html
|
||||
src/app/homepage/pages/recipes/serve-static/serve-static.component.html
|
||||
src/app/homepage/pages/discover/who-uses/who-uses.component.html
|
||||
@@ -1,172 +0,0 @@
|
||||
import * as chokidar from 'chokidar';
|
||||
import * as fg from 'fast-glob';
|
||||
import * as fs from 'fs';
|
||||
import * as marked from 'marked';
|
||||
import { join } from 'path';
|
||||
import {
|
||||
appendEmptyLine,
|
||||
escapeBrackets,
|
||||
insertText,
|
||||
parseSwitcher,
|
||||
replaceFilename,
|
||||
} from './markdown-utils';
|
||||
|
||||
const renderer: any = new marked.Renderer();
|
||||
|
||||
const originalTableRenderer = renderer.table;
|
||||
renderer.table = (header: string, body: string) =>
|
||||
header.includes('<th></th>')
|
||||
? originalTableRenderer.call(renderer, '', body)
|
||||
: originalTableRenderer.call(renderer, header, body);
|
||||
|
||||
const originalCodeRenderer = renderer.code;
|
||||
renderer.code = function(
|
||||
code: string,
|
||||
language: string,
|
||||
isEscaped: boolean,
|
||||
switcherKey?: string,
|
||||
) {
|
||||
const filenameKey = '@@filename';
|
||||
const filenameIndex = code.indexOf(filenameKey);
|
||||
if (filenameIndex >= 0) {
|
||||
return replaceFilename(
|
||||
(text, directiveRef) =>
|
||||
renderer.code(text, language, isEscaped, directiveRef),
|
||||
code,
|
||||
filenameKey,
|
||||
filenameIndex,
|
||||
);
|
||||
}
|
||||
|
||||
const switchKey = '@@switch';
|
||||
const switchIndex = code.indexOf(switchKey);
|
||||
if (switchIndex >= 0) {
|
||||
const result = parseSwitcher(
|
||||
(text, lang) => renderer.code(text, lang, isEscaped),
|
||||
code,
|
||||
switchKey,
|
||||
switchIndex,
|
||||
switcherKey,
|
||||
);
|
||||
return escapeBrackets(result);
|
||||
}
|
||||
let output: string = originalCodeRenderer.call(
|
||||
renderer,
|
||||
code,
|
||||
language,
|
||||
isEscaped,
|
||||
);
|
||||
output = switcherKey ? output : appendEmptyLine(output);
|
||||
return escapeBrackets(output);
|
||||
};
|
||||
|
||||
const originalLinkRenderer = renderer.link;
|
||||
renderer.link = (href: string, title: string, text: string) => {
|
||||
if (!href.includes('http') && !href.includes('mailto')) {
|
||||
return (originalLinkRenderer.call(
|
||||
renderer,
|
||||
href,
|
||||
title,
|
||||
text,
|
||||
) as string).replace('href', 'routerLink');
|
||||
}
|
||||
|
||||
if (href.includes('http') && !href.includes('mailto')) {
|
||||
let baseLink = (originalLinkRenderer.call(
|
||||
renderer,
|
||||
href,
|
||||
title,
|
||||
text
|
||||
) as string);
|
||||
|
||||
baseLink = `${baseLink.substr(0, 2)} target="_blank"${baseLink.substr(2)}`;
|
||||
return baseLink;
|
||||
}
|
||||
return originalLinkRenderer.call(renderer, href, title, text);
|
||||
};
|
||||
|
||||
const originalHeadingRenderer = renderer.heading.bind(renderer);
|
||||
renderer.heading = (...args: string[]) => {
|
||||
let text = originalHeadingRenderer(...args);
|
||||
if (!text.includes('h4')) {
|
||||
return text;
|
||||
}
|
||||
const startIndex = text.indexOf('<h') + 3;
|
||||
text = insertText(text, startIndex, ` appAnchor`);
|
||||
text = insertText(text, text.indexOf('">') + 2, '<span>');
|
||||
return insertText(text, text.length - 6, '</span>');
|
||||
};
|
||||
|
||||
const originalBlockquoteRenderer = renderer.blockquote.bind(renderer);
|
||||
renderer.blockquote = (quote: string) => {
|
||||
let text: string = originalBlockquoteRenderer(quote);
|
||||
text = text.replace('<p>', '');
|
||||
text = text.replace('</p>', '');
|
||||
|
||||
const blockquoteTag = '<blockquote>';
|
||||
text = text.replace('<blockquote>', '<blockquote');
|
||||
text = insertText(text, blockquoteTag.length - 1, ` class="`);
|
||||
text = insertText(text, text.indexOf('<strong>'), '">');
|
||||
return text;
|
||||
};
|
||||
|
||||
const rootDir = 'content';
|
||||
function readAndCompile(path: string, done: (filename?: string) => void) {
|
||||
fs.readFile(path, 'utf-8', (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return done();
|
||||
}
|
||||
const html = `<div class="content" #contentReference>
|
||||
<div class="github-links">
|
||||
<a href="https://github.com/nestjs/docs.nestjs.com/edit/master/${path}" aria-label="Suggest Edits" title="Suggest Edits">
|
||||
<i class="material-icons" aria-hidden="true" role="img">mode_edit</i>
|
||||
</a>
|
||||
</div>
|
||||
${marked(data.toString(), { renderer })}
|
||||
</div>`;
|
||||
|
||||
const distPath = path.slice(
|
||||
path.indexOf(rootDir) + rootDir.length,
|
||||
path.length - 3, // strip extension
|
||||
);
|
||||
const pathSegments = distPath.split('/');
|
||||
const distFilename =
|
||||
pathSegments[pathSegments.length - 1] + '.component.html';
|
||||
|
||||
fs.writeFileSync(
|
||||
join(process.cwd(), `src/app/homepage/pages${distPath}/${distFilename}`),
|
||||
html + '\n',
|
||||
);
|
||||
return done(distFilename);
|
||||
});
|
||||
}
|
||||
|
||||
const argv = require('yargs').argv;
|
||||
if (argv.watch) {
|
||||
const watcher = chokidar.watch(join(process.cwd(), rootDir), {
|
||||
ignored: /(^|[\/\\])\../,
|
||||
persistent: true,
|
||||
});
|
||||
|
||||
console.log('# Markdown compiler is watching files.. (content dir)');
|
||||
watcher.on('change', path => {
|
||||
readAndCompile(path, (filename?: string) => {
|
||||
filename &&
|
||||
console.log(
|
||||
`[${filename}] has been saved. (${new Date().toLocaleTimeString()})`,
|
||||
);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
fg(['content/**/*.md']).then(entries => {
|
||||
entries.forEach(path =>
|
||||
readAndCompile(path as string, (filename?: string) => {
|
||||
filename &&
|
||||
console.log(
|
||||
`[${filename}] has been saved. (${new Date().toLocaleTimeString()})`,
|
||||
);
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
141
content/discover/who-uses.json
Normal file
141
content/discover/who-uses.json
Normal file
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"Header": [
|
||||
{
|
||||
"logo": "https://nestjs.com/img/valor-software.png",
|
||||
"url": "https://valor-software.com/"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/rewe.svg",
|
||||
"url": "https://rewe-digital.com/",
|
||||
"width": "180px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/roche-logo.png",
|
||||
"url": "https://roche.com",
|
||||
"width": "90px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/adidas.svg",
|
||||
"url": "https://adidas.com",
|
||||
"width": "80px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/capgemini.svg",
|
||||
"url": "https://capgemini.com"
|
||||
},
|
||||
{
|
||||
"logo": "https://nestjs.com/img/gojob-logo.png",
|
||||
"url": "https://gojob.com/",
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"logo": "https://nestjs.com/img/neoteric.png",
|
||||
"url": "https://neoteric.eu/"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/trellis.png",
|
||||
"url": "https://trellis.org/",
|
||||
"width": "70px"
|
||||
},
|
||||
{
|
||||
"logo": "https://nestjs.com/img/scalio-logo.svg",
|
||||
"url": "https://scal.io",
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"logo": "https://nestjs.com/img/swingdev-logo.svg",
|
||||
"url": "https://swingdev.io/"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/cultura-colectiva.png",
|
||||
"url": "https://culturacolectiva.com",
|
||||
"width": "90px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/architectnow.png",
|
||||
"url": "http://architectnow.net",
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/iflix.svg",
|
||||
"url": "https://www.iflix.com",
|
||||
"width": "70px"
|
||||
},
|
||||
{
|
||||
"logo": "https://nestjs.com/img/genuinebee.svg",
|
||||
"url": "https://genuinebee.com/"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/run-players-league.png",
|
||||
"url": "https://runplayersleague.com",
|
||||
"width": "80px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/yanrongyun.svg",
|
||||
"url": "http://www.yanrongyun.com",
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/sclable.svg",
|
||||
"url": "https://sclable.com",
|
||||
"width": "120px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/dozto.png",
|
||||
"url": "https://www.dozto.com",
|
||||
"width": "130px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/qingtui.png",
|
||||
"url": "https://www.qingtui.cn/",
|
||||
"width": "90px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/crowdlinker.svg",
|
||||
"url": "https://crowdlinker.com/",
|
||||
"width": "110px"
|
||||
},
|
||||
{
|
||||
"logo": "/assets/logo/nothing.svg",
|
||||
"url": "https://nothing.ch/",
|
||||
"width": "110px"
|
||||
}
|
||||
],
|
||||
"Body": [
|
||||
"https://gorrion.io/",
|
||||
"http://balticdatascience.com/",
|
||||
"https://prohabits.com/",
|
||||
"https://komed-health.com/",
|
||||
"https://kerberus.com.co/",
|
||||
"http://xtremis.com/",
|
||||
"https://notadd.com/",
|
||||
"http://jsdaddy.io/",
|
||||
"https://yumpingo.com/",
|
||||
"https://analytics-importer.cz/",
|
||||
"https://dayzim.com/",
|
||||
"https://wizkids.co.uk/",
|
||||
"https://pilvia.com/",
|
||||
"https://wi-q.com/",
|
||||
"http://agrofel.com.br",
|
||||
"https://societegenerale.com/",
|
||||
"https://trashpanda.hulan.nl/",
|
||||
"https://bytedance.com/",
|
||||
"https://votercircle.com",
|
||||
"https://erento.com",
|
||||
"https://ideas.manticore-labs.com/",
|
||||
"https://smartexlab.com/",
|
||||
"https://automama.ru/",
|
||||
"https://iflix.com/",
|
||||
"https://framework.watch",
|
||||
"https://mobilejazz.com/",
|
||||
"https://cgiandi.com/",
|
||||
"https://www.titlex.com.au/",
|
||||
"https://codengage.com/",
|
||||
"https://budacode.com/",
|
||||
"https://blueanchor.io/",
|
||||
"https://www.easymetrics.com/",
|
||||
"https://getapollo.io/",
|
||||
"https://big-bench.com/",
|
||||
"https://www.qingtui.cn/"
|
||||
]
|
||||
}
|
||||
8
content/discover/who-uses.md
Normal file
8
content/discover/who-uses.md
Normal file
@@ -0,0 +1,8 @@
|
||||
### Who is using Nest?
|
||||
|
||||
We are proudly helping various companies building their products at scale.
|
||||
If you are using Nest and would you like to be listed here, see this [thread](https://github.com/nestjs/nest/issues/1006).
|
||||
We are willing to put your logo here!
|
||||
|
||||
#### Companies
|
||||
According to our knowledge, all the following companies have built awesome projects on top of our framework:
|
||||
1728
package-lock.json
generated
1728
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@@ -4,17 +4,17 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"prestart": "npm run markdown",
|
||||
"prestart": "npm run docs",
|
||||
"start": "ng serve --source-map=false",
|
||||
"prebuild": "npm run markdown",
|
||||
"prebuild": "npm run docs",
|
||||
"build": "ng build --deleteOutputPath=false",
|
||||
"prebuild:prod": "npm run markdown",
|
||||
"prebuild:prod": "npm run docs",
|
||||
"build:prod": "ng build --prod --aot --deleteOutputPath=false",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"markdown": "ts-node -O \"{\\\"module\\\": \\\"commonjs\\\"}\" compiler/markdown-compiler.ts",
|
||||
"markdown:watch": "ts-node -O \"{\\\"module\\\": \\\"commonjs\\\"}\" compiler/markdown-compiler.ts --watch"
|
||||
"docs": "npm run docs-only",
|
||||
"docs-only": "ts-node -P tools/tsconfig.json tools/dgeni-cli.ts tools/transforms/nestjs-package/index"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
@@ -37,6 +37,8 @@
|
||||
"@ultimate/ngxerrors": "1.4.0",
|
||||
"angular2-highlight-js": "6.0.1-alpha",
|
||||
"core-js": "2.6.9",
|
||||
"dgeni": "0.4.12",
|
||||
"dgeni-packages": "0.28.1",
|
||||
"fast-glob": "3.0.4",
|
||||
"hammerjs": "2.0.8",
|
||||
"lodash": "4.17.15",
|
||||
@@ -58,7 +60,9 @@
|
||||
"@types/jasmine": "3.3.16",
|
||||
"@types/jasminewd2": "2.0.6",
|
||||
"@types/lodash": "4.14.136",
|
||||
"@types/node": "12.6.8",
|
||||
"@types/marked": "^0.6.5",
|
||||
"@types/node": "^12.6.8",
|
||||
"@types/rimraf": "^2.0.2",
|
||||
"chokidar": "3.0.2",
|
||||
"codelyzer": "5.1.0",
|
||||
"concurrently": "4.1.1",
|
||||
@@ -72,6 +76,7 @@
|
||||
"karma-jasmine-html-reporter": "1.4.2",
|
||||
"marked": "0.7.0",
|
||||
"protractor": "6.0.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"ts-node": "8.3.0",
|
||||
"tslint": "5.18.0",
|
||||
"typescript": "3.4.1",
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<div class="content">
|
||||
<h3>Who is using Nest?</h3>
|
||||
<p>
|
||||
We are proudly helping various companies building their products at scale.
|
||||
If you are using Nest and would you like to be listed here, see this <a href="https://github.com/nestjs/nest/issues/1006"
|
||||
target="blank">thread</a>. We are willing to put your logo here!
|
||||
</p>
|
||||
<h4>Companies</h4>
|
||||
<p>
|
||||
According to our knowledge, all the following companies have built awesome projects on top of our framework:
|
||||
</p>
|
||||
<div class="companies-wrapper">
|
||||
<a class="company-logo" *ngFor="let item of companies" [href]="item.url" target="blank"><img [src]="item.logo"
|
||||
[style.width]="item.width" /></a>
|
||||
</div>
|
||||
<table class="companies-list">
|
||||
<tr *ngFor="let item of companiesUrls">
|
||||
<td><a [href]="item" target="blank">{{ item }}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
and a lot more but we don't have enough time to update above list. Feel free to create a <a href="https://github.com/nestjs/docs.nestjs.com/pulls"
|
||||
target="blank">pull
|
||||
request</a> though!
|
||||
</p>
|
||||
</div>
|
||||
19
tools/README.md
Normal file
19
tools/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# docs.nestjs.com project tooling
|
||||
|
||||
This document gives an overview of the tools we use to generate the content for the
|
||||
docs.nestjs.com website.
|
||||
|
||||
# transforms
|
||||
|
||||
All the content that is rendered by the docs.nestjs.com application, and some of its
|
||||
configuration files, are generated from source files by [Dgeni](https://github.com/angular/dgeni).
|
||||
Dgeni is a general purpose documentation generation tool.
|
||||
|
||||
Markdown files in `content` are processed and transformed
|
||||
into files that are consumed by the `docs.nestjs.com` web frontend.
|
||||
|
||||
# dgeni-cli
|
||||
|
||||
The dgeni CLI `tools/dgeni-cli.ts` is wrapper to start a Dgeni package from the command line.
|
||||
We do not take use of the CLI interface provided by the Dgeni package itself, mainly because
|
||||
it does not support TypeScript compilation on the fly.
|
||||
23
tools/dgeni-cli.ts
Normal file
23
tools/dgeni-cli.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Dgeni } from 'dgeni';
|
||||
import { resolve } from 'path';
|
||||
|
||||
const argv = require('yargs').argv;
|
||||
|
||||
const packagePaths = argv._;
|
||||
|
||||
const packages = packagePaths.map(packagePath => {
|
||||
if (packagePath.indexOf('.') === 0) {
|
||||
packagePath = resolve(packagePath);
|
||||
}
|
||||
return require('../' + packagePath).default;
|
||||
});
|
||||
|
||||
new Dgeni(packages)
|
||||
.generate()
|
||||
.then(docs => {
|
||||
console.log(`${docs.length} docs generated.`);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
39
tools/transforms/README.md
Normal file
39
tools/transforms/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Transforms Overview
|
||||
|
||||
All the content that is rendered by the docs.nestjs.com application, and some of its
|
||||
configuration files, are generated from source files by [Dgeni](https://github.com/angular/dgeni).
|
||||
Dgeni is a general purpose documentation generation tool.
|
||||
|
||||
Markdown files in `content` are processed and transformed
|
||||
into files that are consumed by the `docs.nestjs.com` web frontend.
|
||||
|
||||
## Packages
|
||||
|
||||
The documentation tool of NestJS is split into multiple Dgeni packages.
|
||||
|
||||
**nestjs-package**
|
||||
|
||||
The main package. Orchestrates all the following packages and sets
|
||||
final configuration. It is responsible for cleaning up the file system.
|
||||
|
||||
**nestjs-base-package**
|
||||
|
||||
The base package for common configurations, services and processors for
|
||||
each package. It handles the general input / output / template path resolution.
|
||||
|
||||
**nestjs-content-package**
|
||||
|
||||
Orchestrates all hand-written contents for the NestJS documentation.
|
||||
It makes use of the `content`-folders markdown. On top of that
|
||||
it takes care of the `content/**/*.json` files such as `content/discover/who-uses.json`.
|
||||
|
||||
**content-package**
|
||||
|
||||
A package to handle the markdown content files. It creates a new DocType `content`
|
||||
which include a `content` and `title` of each markdown file.
|
||||
The **nestjs-content-package** manages this content further.
|
||||
|
||||
## Templates
|
||||
|
||||
All the templates for the docs.nestjs.com dgeni transformations are stoted in the `tools/transforms/templates`
|
||||
folder. See the [README](./templates/README.md).
|
||||
10
tools/transforms/config.ts
Normal file
10
tools/transforms/config.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { resolve } from 'path';
|
||||
|
||||
|
||||
export const PROJECT_ROOT = resolve(__dirname, '../../');
|
||||
export const CONTENTS_PATH = resolve(PROJECT_ROOT, 'content');
|
||||
|
||||
export const SRC_PATH = resolve(PROJECT_ROOT, 'src');
|
||||
export const OUTPUT_PATH = resolve(SRC_PATH, 'app/homepage/pages');
|
||||
export const DOCS_OUTPUT_PATH = resolve(OUTPUT_PATH, 'docs');
|
||||
export const TEMPLATES_PATH = resolve(__dirname, './templates');
|
||||
57
tools/transforms/content-package/index.ts
Normal file
57
tools/transforms/content-package/index.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { Package } from 'dgeni';
|
||||
import { ContentFileReader, contentFileReader } from './readers';
|
||||
import {
|
||||
extractContentTitleProcessor,
|
||||
computeOutputPathProcessor,
|
||||
computeWhoUsesProcessor
|
||||
} from './processors';
|
||||
import { renderNestJSMarkdown } from './services';
|
||||
import { nestjsMarkedNunjucksTag } from './rendering/tags/nestjsmarked';
|
||||
import { nestjsMarkedNunjucksFilter } from './rendering/filters/nestjsmarked';
|
||||
import { Document } from '../shared';
|
||||
|
||||
export default new Package('content', [])
|
||||
.factory(contentFileReader)
|
||||
.factory(renderNestJSMarkdown)
|
||||
.factory(nestjsMarkedNunjucksTag)
|
||||
.factory(nestjsMarkedNunjucksFilter)
|
||||
|
||||
.processor(extractContentTitleProcessor)
|
||||
.processor(computeOutputPathProcessor)
|
||||
.processor(computeWhoUsesProcessor)
|
||||
|
||||
.config((readFilesProcessor: any, contentFileReader: ContentFileReader) => {
|
||||
readFilesProcessor.fileReaders.push(contentFileReader);
|
||||
})
|
||||
|
||||
.config(
|
||||
(
|
||||
templateEngine: any,
|
||||
nestjsMarkedNunjucksTag: any,
|
||||
nestjsMarkedNunjucksFilter: any
|
||||
) => {
|
||||
templateEngine.tags.push(nestjsMarkedNunjucksTag);
|
||||
templateEngine.filters.push(nestjsMarkedNunjucksFilter);
|
||||
}
|
||||
)
|
||||
|
||||
.config(computeIdsProcessor => {
|
||||
computeIdsProcessor.idTemplates.push({
|
||||
docTypes: ['content', 'who-uses'],
|
||||
getId: (doc: Document) => {
|
||||
return (
|
||||
doc.fileInfo.relativePath
|
||||
// path should be relative to `modules` folder
|
||||
.replace(/.*\/?modules\//, '')
|
||||
// path should not include `/docs/`
|
||||
.replace(/\/docs\//, '/')
|
||||
// path should not have a suffix
|
||||
.replace(/\.\w*$/, '')
|
||||
);
|
||||
},
|
||||
getAliases: (doc: Document) => [doc.id]
|
||||
});
|
||||
});
|
||||
|
||||
export * from './readers';
|
||||
export * from './processors';
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Processor } from 'dgeni';
|
||||
import { join } from 'path';
|
||||
|
||||
import { Document } from '../../shared';
|
||||
import { SRC_PATH } from '../../config';
|
||||
|
||||
export class ComputeOutputPathProcessor implements Processor {
|
||||
$runBefore = ['writeFilesProcessor'];
|
||||
$process(docs: Document[]) {
|
||||
docs.forEach(doc => {
|
||||
if (doc.docType === 'content' || doc.docType === 'who-uses') {
|
||||
const filePath = doc.fileInfo.projectRelativePath;
|
||||
const distPath = filePath.slice(
|
||||
'content'.length + 1,
|
||||
filePath.length - 3 // strip extension
|
||||
);
|
||||
|
||||
const pathSegments = distPath.split('/');
|
||||
const distFilename =
|
||||
pathSegments[pathSegments.length - 1] + '.component.html';
|
||||
|
||||
doc.outputPath = join(
|
||||
SRC_PATH,
|
||||
'/app/homepage/pages',
|
||||
distPath,
|
||||
distFilename
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function computeOutputPathProcessor() {
|
||||
return new ComputeOutputPathProcessor();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Processor } from 'dgeni';
|
||||
import { Document } from '../../shared';
|
||||
|
||||
export class ComputeWhoUsesProcessor implements Processor {
|
||||
$runBefore = ['computePathsProcessor'];
|
||||
$runAfter = ['readFilesProcessor'];
|
||||
$process(docs: Document[]) {
|
||||
let whoUsesJson;
|
||||
docs.forEach((doc, index) => {
|
||||
if (doc.docType === 'who-uses-json') {
|
||||
whoUsesJson = doc.data;
|
||||
docs.splice(index, 1);
|
||||
}
|
||||
});
|
||||
docs.forEach(doc => {
|
||||
if (doc.docType === 'who-uses') {
|
||||
doc.id = 'who-uses';
|
||||
doc.whoUses = whoUsesJson;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function computeWhoUsesProcessor() {
|
||||
return new ComputeWhoUsesProcessor();
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Processor, DocCollection } from 'dgeni';
|
||||
|
||||
/**
|
||||
* Extracts the title of a content file.
|
||||
* This processor assumes that the first line of the
|
||||
* content includes the title.
|
||||
*/
|
||||
export class ExtractContentTitleProcessor implements Processor {
|
||||
$runAfter = ['renderDocsProcessor'];
|
||||
$runBefore = ['convertToJsonProcessor'];
|
||||
$process(docs: DocCollection) {
|
||||
docs.forEach(doc => {
|
||||
if (doc.docType === 'content') {
|
||||
try {
|
||||
const firstLine: string = doc.content.split('\n')[0];
|
||||
const title = firstLine.replace(/#/g, '').trim();
|
||||
doc.title = title;
|
||||
} catch (ex) {
|
||||
// We do not care if the title does not exist here
|
||||
// convertToJson will complain later in case the title
|
||||
// does not exist
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function extractContentTitleProcessor() {
|
||||
return new ExtractContentTitleProcessor();
|
||||
}
|
||||
3
tools/transforms/content-package/processors/index.ts
Normal file
3
tools/transforms/content-package/processors/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './extractContentTitle';
|
||||
export * from './computeOutputPath';
|
||||
export * from './computeWhoUses';
|
||||
23
tools/transforms/content-package/readers/content.ts
Normal file
23
tools/transforms/content-package/readers/content.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { FileReader, FileInfo } from '../../shared';
|
||||
|
||||
/**
|
||||
* Reads markdown content files
|
||||
*/
|
||||
export class ContentFileReader implements FileReader {
|
||||
name = 'contentFileReader';
|
||||
defaultPattern = /\.md$/;
|
||||
getDocs(fileInfo: FileInfo) {
|
||||
return [
|
||||
{
|
||||
docType: fileInfo.baseName === 'who-uses'
|
||||
? 'who-uses'
|
||||
: 'content',
|
||||
content: fileInfo.content
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export function contentFileReader() {
|
||||
return new ContentFileReader();
|
||||
}
|
||||
1
tools/transforms/content-package/readers/index.ts
Normal file
1
tools/transforms/content-package/readers/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './content';
|
||||
@@ -0,0 +1,11 @@
|
||||
import { RenderNestJSMarkdown } from '../../services';
|
||||
|
||||
export function nestjsMarkedNunjucksFilter(renderNestJSMarkdown: RenderNestJSMarkdown) {
|
||||
return {
|
||||
name: 'nestjsmarked',
|
||||
process(str: string) {
|
||||
const output = str && renderNestJSMarkdown(str);
|
||||
return output;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { RenderNestJSMarkdown } from '../../services';
|
||||
|
||||
export function nestjsMarkedNunjucksTag(renderNestJSMarkdown: RenderNestJSMarkdown) {
|
||||
return {
|
||||
tags: ['nestjsmarked'],
|
||||
|
||||
/** Disable autoescape for this tag because the markdown tag renders HTML that shouldn't be escaped. */
|
||||
autoescape: false,
|
||||
|
||||
parse: function(parser: any, nodes: any) {
|
||||
parser.advanceAfterBlockEnd();
|
||||
|
||||
var content = parser.parseUntilBlocks('endmarked');
|
||||
var tag = new nodes.CallExtension(this, 'process', null, [content]);
|
||||
parser.advanceAfterBlockEnd();
|
||||
|
||||
return tag;
|
||||
},
|
||||
|
||||
process(_: any, content: () => string) {
|
||||
const contentString = content();
|
||||
const markedString = renderNestJSMarkdown(contentString);
|
||||
return markedString;
|
||||
}
|
||||
};
|
||||
}
|
||||
1
tools/transforms/content-package/services/index.ts
Normal file
1
tools/transforms/content-package/services/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './renderNestJSMarkdown';
|
||||
@@ -0,0 +1,23 @@
|
||||
import * as marked from 'marked';
|
||||
import {
|
||||
applyTableRenderer,
|
||||
applyCodeRenderer,
|
||||
applyBlockQuoteRenderer,
|
||||
applyHeadingRenderer,
|
||||
applyLinkRenderer
|
||||
} from './renderer';
|
||||
|
||||
export type RenderNestJSMarkdown = (content: string) => string;
|
||||
|
||||
export function renderNestJSMarkdown() {
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
applyTableRenderer(renderer);
|
||||
applyCodeRenderer(renderer);
|
||||
applyLinkRenderer(renderer);
|
||||
applyHeadingRenderer(renderer);
|
||||
applyBlockQuoteRenderer(renderer);
|
||||
|
||||
// @ts-ignore
|
||||
return (content: string) => marked(content, { renderer });
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Renderer } from 'marked';
|
||||
import { insertText } from '../../../shared';
|
||||
|
||||
export function applyBlockQuoteRenderer(renderer: Renderer) {
|
||||
const originalBlockquoteRenderer = renderer.blockquote.bind(renderer);
|
||||
|
||||
const blockquote = (quote: string) => {
|
||||
let text: string = originalBlockquoteRenderer(quote);
|
||||
text = text.replace('<p>', '');
|
||||
text = text.replace('</p>', '');
|
||||
|
||||
const blockquoteTag = '<blockquote>';
|
||||
text = text.replace('<blockquote>', '<blockquote');
|
||||
text = insertText(text, blockquoteTag.length - 1, ` class="`);
|
||||
text = insertText(text, text.indexOf('<strong>'), '">');
|
||||
return text;
|
||||
};
|
||||
|
||||
renderer.blockquote = blockquote;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Renderer } from 'marked';
|
||||
import {
|
||||
replaceFilename,
|
||||
parseSwitcher,
|
||||
escapeBrackets,
|
||||
appendEmptyLine
|
||||
} from '../../../shared';
|
||||
|
||||
export function applyCodeRenderer(renderer: Renderer) {
|
||||
const originalCodeRenderer = renderer.code;
|
||||
renderer.code = function(
|
||||
code: string,
|
||||
language: string,
|
||||
isEscaped: boolean,
|
||||
switcherKey?: string
|
||||
) {
|
||||
const filenameKey = '@@filename';
|
||||
const filenameIndex = code.indexOf(filenameKey);
|
||||
if (filenameIndex >= 0) {
|
||||
return replaceFilename(
|
||||
(text, directiveRef) =>
|
||||
// @ts-ignore
|
||||
renderer.code(text, language, isEscaped, directiveRef),
|
||||
code,
|
||||
filenameKey,
|
||||
filenameIndex
|
||||
);
|
||||
}
|
||||
|
||||
const switchKey = '@@switch';
|
||||
const switchIndex = code.indexOf(switchKey);
|
||||
if (switchIndex >= 0) {
|
||||
const result = parseSwitcher(
|
||||
(text, lang) => renderer.code(text, lang, isEscaped),
|
||||
code,
|
||||
switchKey,
|
||||
switchIndex,
|
||||
switcherKey
|
||||
);
|
||||
return escapeBrackets(result);
|
||||
}
|
||||
let output: string = originalCodeRenderer.call(
|
||||
renderer,
|
||||
code,
|
||||
language,
|
||||
isEscaped
|
||||
);
|
||||
output = switcherKey ? output : appendEmptyLine(output);
|
||||
return escapeBrackets(output);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Renderer } from 'marked';
|
||||
import { insertText } from '../../../shared';
|
||||
|
||||
export function applyHeadingRenderer(renderer: Renderer) {
|
||||
const originalHeadingRenderer = renderer.heading.bind(renderer);
|
||||
|
||||
const heading = (...args: any[]) => {
|
||||
let text = originalHeadingRenderer(...args);
|
||||
if (!text.includes('h4')) {
|
||||
return text;
|
||||
}
|
||||
const startIndex = text.indexOf('<h') + 3;
|
||||
text = insertText(text, startIndex, ` appAnchor`);
|
||||
text = insertText(text, text.indexOf('">') + 2, '<span>');
|
||||
return insertText(text, text.length - 6, '</span>');
|
||||
};
|
||||
|
||||
renderer.heading = heading;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export * from './code.renderer';
|
||||
export * from './blockquote.renderer';
|
||||
export * from './heading.renderer';
|
||||
export * from './link.renderer';
|
||||
export * from './table.renderer';
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Renderer } from 'marked';
|
||||
|
||||
export function applyLinkRenderer(renderer: Renderer) {
|
||||
const originalLinkRenderer = renderer.link;
|
||||
|
||||
const link = (href: string, title: string, text: string) => {
|
||||
if (!href.includes('http') && !href.includes('mailto')) {
|
||||
return (originalLinkRenderer.call(
|
||||
renderer,
|
||||
href,
|
||||
title,
|
||||
text
|
||||
) as string).replace('href', 'routerLink');
|
||||
}
|
||||
|
||||
if (href.includes('http') && !href.includes('mailto')) {
|
||||
let baseLink = originalLinkRenderer.call(
|
||||
renderer,
|
||||
href,
|
||||
title,
|
||||
text
|
||||
) as string;
|
||||
|
||||
baseLink = `${baseLink.substr(0, 2)} target='_blank'${baseLink.substr(
|
||||
2
|
||||
)}`;
|
||||
return baseLink;
|
||||
}
|
||||
return originalLinkRenderer.call(renderer, href, title, text);
|
||||
};
|
||||
|
||||
renderer.link = link;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Renderer } from 'marked';
|
||||
|
||||
export function applyTableRenderer(renderer: Renderer) {
|
||||
const originalTableRenderer = renderer.table;
|
||||
|
||||
const table = (header: string, body: string) =>
|
||||
header.includes('<th></th>')
|
||||
? originalTableRenderer.call(renderer, '', body)
|
||||
: originalTableRenderer.call(renderer, header, body);
|
||||
|
||||
renderer.table = table;
|
||||
}
|
||||
56
tools/transforms/nestjs-base-package/index.ts
Normal file
56
tools/transforms/nestjs-base-package/index.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Package } from 'dgeni';
|
||||
import { relative } from 'path';
|
||||
|
||||
import * as nunjucksPackage from 'dgeni-packages/nunjucks';
|
||||
import * as jsdocPackage from 'dgeni-packages/jsdoc';
|
||||
import * as postProcessPackage from 'dgeni-packages/post-process-html';
|
||||
|
||||
import { PROJECT_ROOT, TEMPLATES_PATH, DOCS_OUTPUT_PATH } from '../config';
|
||||
import { jsonFileReader, JsonFileReader } from './readers';
|
||||
import { convertToJsonProcessor } from './processors';
|
||||
|
||||
export default new Package('nestjs-base', [
|
||||
jsdocPackage,
|
||||
nunjucksPackage,
|
||||
postProcessPackage
|
||||
])
|
||||
.processor(convertToJsonProcessor)
|
||||
.factory(jsonFileReader)
|
||||
.config((readFilesProcessor: any, jsonFileReader: JsonFileReader) => {
|
||||
readFilesProcessor.fileReaders.push(jsonFileReader);
|
||||
readFilesProcessor.basePath = PROJECT_ROOT;
|
||||
readFilesProcessor.sourceFiles = [];
|
||||
})
|
||||
.config(writeFilesProcessor => {
|
||||
writeFilesProcessor.outputFolder = DOCS_OUTPUT_PATH;
|
||||
})
|
||||
.config(
|
||||
(renderDocsProcessor: any, templateFinder: any, templateEngine: any) => {
|
||||
// Where to find the templates for the doc rendering
|
||||
templateFinder.templateFolders = [TEMPLATES_PATH];
|
||||
|
||||
// Standard patterns for matching docs to templates
|
||||
templateFinder.templatePatterns = [
|
||||
'${ doc.template }',
|
||||
'${ doc.id }.${ doc.docType }.template.html',
|
||||
'${ doc.id }.template.html',
|
||||
'${ doc.docType }.template.html',
|
||||
'${ doc.id }.${ doc.docType }.template.js',
|
||||
'${ doc.id }.template.js',
|
||||
'${ doc.docType }.template.js',
|
||||
'${ doc.id }.${ doc.docType }.template.json',
|
||||
'${ doc.id }.template.json',
|
||||
'${ doc.docType }.template.json',
|
||||
'common.template.html'
|
||||
];
|
||||
|
||||
templateEngine.config.tags = { variableStart: '{$', variableEnd: '$}' };
|
||||
|
||||
// helpers are made available to the nunjucks templates
|
||||
renderDocsProcessor.helpers.relativePath = (from, to) =>
|
||||
relative(from, to);
|
||||
}
|
||||
);
|
||||
|
||||
export * from './processors';
|
||||
export * from './readers';
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Processor, DocCollection } from 'dgeni';
|
||||
import { CreateDocMessage, DgeniLogger } from '../../shared';
|
||||
|
||||
/**
|
||||
* Converts doc types set by the `docTypes` property to JSON documents.
|
||||
* A document requires `doc.renderContent` and `doc.title` or `doc.name`
|
||||
* property.
|
||||
*/
|
||||
export class ConvertToJsonProcessor implements Processor {
|
||||
constructor(private log: DgeniLogger, private createDocMessage: CreateDocMessage) {}
|
||||
$runAfter = ['postProcessHtml'];
|
||||
$runBefore = ['writeFilesProcessor'];
|
||||
docTypes = [];
|
||||
$process(docs: DocCollection) {
|
||||
const docTypes = this.docTypes;
|
||||
docs.forEach((doc: any) => {
|
||||
if (docTypes.includes(doc.docType)) {
|
||||
let contents = doc.renderedContent || '';
|
||||
|
||||
let title = doc.title;
|
||||
|
||||
if (title === undefined) {
|
||||
title = doc.name;
|
||||
}
|
||||
|
||||
// If there is still no title then log a warning
|
||||
if (title === undefined) {
|
||||
title = '';
|
||||
this.log.warn(this.createDocMessage('Title property expected', doc));
|
||||
}
|
||||
|
||||
doc.renderedContent = JSON.stringify(
|
||||
{ id: doc.path, title, contents },
|
||||
null,
|
||||
2
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function convertToJsonProcessor(log: any, createDocMessage: any) {
|
||||
return new ConvertToJsonProcessor(log, createDocMessage);
|
||||
}
|
||||
1
tools/transforms/nestjs-base-package/processors/index.ts
Normal file
1
tools/transforms/nestjs-base-package/processors/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './convertToJson';
|
||||
1
tools/transforms/nestjs-base-package/readers/index.ts
Normal file
1
tools/transforms/nestjs-base-package/readers/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './json';
|
||||
20
tools/transforms/nestjs-base-package/readers/json.ts
Normal file
20
tools/transforms/nestjs-base-package/readers/json.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { FileReader, FileInfo } from '../../shared';
|
||||
|
||||
export class JsonFileReader implements FileReader {
|
||||
name = 'jsonFileReader';
|
||||
getDocs(fileInfo: FileInfo) {
|
||||
return [
|
||||
{
|
||||
docType: fileInfo.baseName + '-json',
|
||||
data: JSON.parse(fileInfo.content),
|
||||
template: 'json-doc.template.json',
|
||||
id: fileInfo.baseName,
|
||||
aliases: [fileInfo.baseName, fileInfo.relativePath]
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export function jsonFileReader() {
|
||||
return new JsonFileReader();
|
||||
}
|
||||
53
tools/transforms/nestjs-content-package/index.ts
Normal file
53
tools/transforms/nestjs-content-package/index.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Package } from 'dgeni';
|
||||
|
||||
import { CONTENTS_PATH } from '../config';
|
||||
import nestjsBasePackage, {
|
||||
ConvertToJsonProcessor
|
||||
} from '../nestjs-base-package';
|
||||
import contentPackage, { contentFileReader } from '../content-package';
|
||||
|
||||
export default new Package('nestjs-content', [
|
||||
nestjsBasePackage,
|
||||
contentPackage
|
||||
])
|
||||
.config((readFilesProcessor: any) => {
|
||||
readFilesProcessor.sourceFiles = readFilesProcessor.sourceFiles.concat([
|
||||
{
|
||||
basePath: CONTENTS_PATH,
|
||||
include: CONTENTS_PATH + '/**/*.md',
|
||||
fileReader: contentFileReader.name
|
||||
},
|
||||
{
|
||||
basePath: CONTENTS_PATH,
|
||||
include: CONTENTS_PATH + '/navigation.json',
|
||||
fileReader: 'jsonFileReader'
|
||||
},
|
||||
{
|
||||
basePath: CONTENTS_PATH,
|
||||
include: CONTENTS_PATH + '/discover/who-uses.json',
|
||||
fileReader: 'jsonFileReader'
|
||||
}
|
||||
]);
|
||||
})
|
||||
|
||||
.config((computePathsProcessor: any) => {
|
||||
// Replace any path templates inherited from other packages
|
||||
// (we want full and transparent control)
|
||||
computePathsProcessor.pathTemplates = computePathsProcessor.pathTemplates.concat(
|
||||
[
|
||||
{
|
||||
docTypes: ['content', 'who-uses'],
|
||||
getPath: doc => `${doc.id.replace(/\/index$/, '')}`,
|
||||
outputPathTemplate: '${path}.json'
|
||||
},
|
||||
{
|
||||
docTypes: ['who-uses-json'],
|
||||
pathTemplate: '${id}',
|
||||
outputPathTemplate: '../${id}.json'
|
||||
}
|
||||
]
|
||||
);
|
||||
})
|
||||
// .config((convertToJsonProcessor: ConvertToJsonProcessor) => {
|
||||
// convertToJsonProcessor.docTypes.push('content');
|
||||
// });
|
||||
7
tools/transforms/nestjs-package/index.ts
Normal file
7
tools/transforms/nestjs-package/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Package } from 'dgeni';
|
||||
import nestjsContentPackage from '../nestjs-content-package';
|
||||
import nestjsBasePackage from '../nestjs-base-package';
|
||||
import { cleanGeneratedFiles } from './processors';
|
||||
|
||||
export default new Package('nestjs', [nestjsContentPackage, nestjsBasePackage])
|
||||
.processor(cleanGeneratedFiles)
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as rimraf from 'rimraf';
|
||||
import { Processor } from 'dgeni';
|
||||
import { OUTPUT_PATH } from '../../config';
|
||||
|
||||
/**
|
||||
* Removes the generated assets
|
||||
*/
|
||||
export class CleanGeneratedFiles implements Processor {
|
||||
$runAfter = ['writing-files'];
|
||||
$runBefore = ['writeFilesProcessor'];
|
||||
$process() {
|
||||
rimraf.sync(`${OUTPUT_PATH}/{docs,*.json}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function cleanGeneratedFiles() {
|
||||
return new CleanGeneratedFiles();
|
||||
}
|
||||
1
tools/transforms/nestjs-package/processors/index.ts
Normal file
1
tools/transforms/nestjs-package/processors/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './cleanGeneratedFiles';
|
||||
2
tools/transforms/shared/index.ts
Normal file
2
tools/transforms/shared/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './interfaces';
|
||||
export * from './utils';
|
||||
31
tools/transforms/shared/interfaces/dgeni-helpers.ts
Normal file
31
tools/transforms/shared/interfaces/dgeni-helpers.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export interface Document {
|
||||
docType: string;
|
||||
fileInfo?: FileInfo;
|
||||
outputPath?: string;
|
||||
[any: string]: any;
|
||||
}
|
||||
|
||||
export interface FileInfo {
|
||||
basePath: string;
|
||||
baseName: string;
|
||||
extension: string;
|
||||
filePath: string;
|
||||
fileReader: string;
|
||||
projectRelativePath: string;
|
||||
content: string;
|
||||
relativePath: string;
|
||||
}
|
||||
|
||||
export interface FileReader {
|
||||
name: string;
|
||||
defaultPattern?: any;
|
||||
getDocs: (fileInfo: FileInfo) => Document[];
|
||||
}
|
||||
|
||||
export type CreateDocMessage = (message: string, document: Document) => string;
|
||||
|
||||
export interface DgeniLogger {
|
||||
warn(message: string): void;
|
||||
log(message: string): void;
|
||||
error(message: string): void;
|
||||
}
|
||||
1
tools/transforms/shared/interfaces/index.ts
Normal file
1
tools/transforms/shared/interfaces/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './dgeni-helpers';
|
||||
1
tools/transforms/shared/utils/index.ts
Normal file
1
tools/transforms/shared/utils/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './markdown-utils';
|
||||
6
tools/transforms/templates/README.md
Normal file
6
tools/transforms/templates/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Dgeni Templates
|
||||
|
||||
This folder contains the dgeni templates that are used to generate the API and content docs
|
||||
|
||||
Generally there is a template for each docType. Templates can extend and/or include
|
||||
other templates. Templates can also import macros from other template files.
|
||||
14
tools/transforms/templates/content.template.html
Normal file
14
tools/transforms/templates/content.template.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% block content %}
|
||||
<div class="content" #contentReference>
|
||||
<div class="github-links">
|
||||
<a
|
||||
href="https://github.com/nestjs/docs.nestjs.com/edit/master/{$ doc.fileInfo.projectRelativePath $}"
|
||||
aria-label="Suggest Edits"
|
||||
title="Suggest Edits"
|
||||
>
|
||||
<i class="material-icons" aria-hidden="true" role="img">mode_edit</i>
|
||||
</a>
|
||||
</div>
|
||||
{$ doc.description | nestjsmarked $}
|
||||
</div>
|
||||
{% endblock %}
|
||||
1
tools/transforms/templates/json-doc.template.json
Normal file
1
tools/transforms/templates/json-doc.template.json
Normal file
@@ -0,0 +1 @@
|
||||
{$ doc.data | json $}
|
||||
25
tools/transforms/templates/who-uses.template.html
Normal file
25
tools/transforms/templates/who-uses.template.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{% block content %}
|
||||
<div class="content">
|
||||
{$ doc.description | nestjsmarked $}
|
||||
</div>
|
||||
|
||||
<div class="companies-wrapper">
|
||||
{% for company in doc.whoUses.Header %}
|
||||
<a class="company-logo" href="{$ company.url $}" target="blank"><img src="{$ company.logo $}"
|
||||
{% if company.width %} style="width: {$ company.width $}" {% endif %} /></a>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
<table class="companies-list">
|
||||
{% for company in doc.whoUses.Body %}
|
||||
<tr>
|
||||
<td><a href="{$ company $}" target="blank">{$ company $}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<p>
|
||||
and a lot more but we don't have enough time to update above list. Feel free to create a <a href="https://github.com/nestjs/docs.nestjs.com/pulls"
|
||||
target="blank">pull
|
||||
request</a> though!
|
||||
</p>
|
||||
{% endblock %}
|
||||
16
tools/tsconfig.json
Normal file
16
tools/tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"declaration": false,
|
||||
"allowUnusedLabels": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"target": "es5",
|
||||
"lib": ["esnext"],
|
||||
"baseUrl": "./"
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,11 @@
|
||||
"rulesDirectory": [
|
||||
"node_modules/codelyzer"
|
||||
],
|
||||
"linterOptions": {
|
||||
"exclude": [
|
||||
"tools/transforms/**/*.ts"
|
||||
]
|
||||
},
|
||||
"rules": {
|
||||
"arrow-return-shorthand": true,
|
||||
"callable-types": true,
|
||||
|
||||
Reference in New Issue
Block a user