From 4ac024d73d1d94e303e710bdf433d05a4a48458b Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 24 Apr 2020 12:26:49 +0300 Subject: [PATCH] fix(app): build docs script --- package.json | 4 +- scripts/docs/config.ts | 4 +- scripts/gulp/tasks/docs/docs.ts | 7 - scripts/gulp/tasks/docs/example.ts | 186 ----------------------- scripts/gulp/tasks/docs/export-themes.ts | 158 ------------------- 5 files changed, 3 insertions(+), 356 deletions(-) delete mode 100644 scripts/gulp/tasks/docs/example.ts delete mode 100644 scripts/gulp/tasks/docs/export-themes.ts diff --git a/package.json b/package.json index 204ae98a..bb2672b1 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,7 @@ "e2e": "ng e2e", "docs": "compodoc -p src/tsconfig.app.json -d docs", "docs:dirs": "gulp create-docs-dirs", - "docs:parse": "gulp docs", - "docs:prepare": "npm-run-all docs:parse", - "docs:prod": "npm run build -- docs --prod --aot --base-href '/ngx-admin/'", + "docs:prod": "npm run build -- docs --prod --aot --base-href /ngx-admin/", "docs:build": "npm-run-all docs:prod docs:dirs", "docs:serve": "npm start -- docs --port 4100", "docs:gh-pages": "ts-node -P ./scripts/docs/tsconfig.json ./scripts/docs/build-docs.ts", diff --git a/scripts/docs/config.ts b/scripts/docs/config.ts index 92498fc5..807f993c 100644 --- a/scripts/docs/config.ts +++ b/scripts/docs/config.ts @@ -1,4 +1,4 @@ -export const REPO_URL = 'https://github.com/akveo/ngx-admin.git'; -export const REPO_OWNER = 'akveo'; +export const REPO_URL = 'https://github.com/alexeykurbako/ngx-admin.git'; +export const REPO_OWNER = 'alexeykurbako'; export const REPO_NAME = 'ngx-admin'; export const OUT_DIR = 'docs/dist'; // Relative to the directory you run command diff --git a/scripts/gulp/tasks/docs/docs.ts b/scripts/gulp/tasks/docs/docs.ts index 73e8c429..b5f2f17b 100644 --- a/scripts/gulp/tasks/docs/docs.ts +++ b/scripts/gulp/tasks/docs/docs.ts @@ -2,16 +2,9 @@ import { task, series } from 'gulp'; import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; import { isAbsolute, join, resolve, sep } from 'path'; -import './example'; import { structure as DOCS } from '../../../../docs/structure'; import { DOCS_DIST } from '../config'; -task( - 'docs', - series( - 'generate-doc-json-and-parse-themes', - ), -); task('create-docs-dirs', (done) => { const docsStructure = flatten('docs', routesTree(DOCS)); createDirsStructure(docsStructure); diff --git a/scripts/gulp/tasks/docs/example.ts b/scripts/gulp/tasks/docs/example.ts deleted file mode 100644 index 8a0319d8..00000000 --- a/scripts/gulp/tasks/docs/example.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { dest, src, task, series } from 'gulp'; -import { accessSync, readFileSync, writeFileSync } from 'fs'; -import { DOCS_OUTPUT, EXTENSIONS } from '../config'; -import { join } from 'path'; -import { exportThemes } from './export-themes'; - -const del = require('del'); -const replace = require('gulp-replace'); -const typedoc = require('gulp-typedoc'); -const sass = require('gulp-sass'); -const exec = require('child_process').execSync; - -/** - * Copy everything from with-layout and without-layout dirs - * directly into examples dir. This way we can reference examples - * without specifying this dirs. - * For example, @stacked-example(..., button/button-showcase.component) - * instead of @stacked-example(..., layout/button/button-showcase.component) - */ -const EXAMPLES_SRC = [ - './src/playground/*.*', - './src/playground/with-layout/**/*.*', - './src/playground/without-layout/**/*.*', -]; -const EXAMPLES_DEST = './docs/assets/examples'; - -task('copy-examples', () => { - del.sync(EXAMPLES_DEST); - return src(EXAMPLES_SRC) - .pipe(replace(/\/\*\*.*\*\/\n\s*\n/s, '')) - .pipe(dest(EXAMPLES_DEST)); -}); - -task('generate-doc-json', generateDocJson); -function generateDocJson() { - return src(['src/framework/**/*.ts', '!src/**/*.spec.ts', '!src/framework/theme/**/node_modules{,/**}']) - .pipe(typedoc({ - module: 'commonjs', - target: 'ES6', - // TODO: ignoreCompilerErrors, huh? - ignoreCompilerErrors: true, - includeDeclarations: true, - emitDecoratorMetadata: true, - experimentalDecorators: true, - excludeExternals: true, - exclude: 'node_modules/**/*', - json: 'docs/docs.json', - version: true, - noLib: true, - })); -} - -task( - 'parse-themes', - parseThemes, -); -function parseThemes() { - exec('prsr -g typedoc -f angular -i docs/docs.json -o docs/output.json'); - - return src('docs/themes.scss') - .pipe(sass({ - functions: exportThemes('docs/', ''), - })); - -} - -task( - 'generate-doc-json-and-parse-themes', - series( - 'generate-doc-json', - 'parse-themes', - ), -); - -task( - 'validate-examples', - series( - 'copy-examples', - (done) => { - const docs = JSON.parse(readFileSync(DOCS_OUTPUT, 'utf8')); - - docs.classes.forEach(cls => validate(cls)); - - done(); - }, - ), -); - -task( - 'find-full-examples', - series( - 'validate-examples', - (done) => { - const docs = JSON.parse(readFileSync(DOCS_OUTPUT, 'utf8')); - docs.classes.forEach(cls => { - cls.overview = cls.overview.map(unfold); - cls.liveExamples = cls.liveExamples.map(unfold); - }); - writeFileSync(DOCS_OUTPUT, JSON.stringify(docs)); - - done(); - }, - ), -); - -function unfold(tag) { - if (tag.type === 'text') { - return tag; - } - - return unfoldWithFiles(tag); -} - -function unfoldWithFiles(tag) { - if (isFile(tag.content.id)) { - return unfoldFile(tag); - } - - return unfoldComponent(tag); -} - -function unfoldFile(tag) { - const id = withoutExtension(tag.content.id); - const files = [tag.content.id]; - return createNode(tag, files, id); -} - -function unfoldComponent(tag) { - const files = EXTENSIONS - .map(extension => `${tag.content.id}.${extension}`) - .filter(isFileExists); - - return createNode(tag, files); -} - -function createNode(tag, files, id = tag.content.id) { - return { - ...tag, - content: { - ...tag.content, - files, - id, - }, - }; -} - -function validate(cls) { - const examples = cls.overview - .filter(({ type }) => type !== 'text') - .map(({ content }) => content); - - const missing = examples.filter(({ id }) => !isFileExists(id) && !isComponentExists(id)); - - if (missing.length) { - throw new Error(createMissingMsg(missing)); - } -} - -function createMissingMsg(examples): string { - const missing = examples.map(({ id, name }) => `${name}, ${id}`); - return `Can't resolve:\n${missing.join('\n')}`; -} - -function isComponentExists(path): boolean { - return EXTENSIONS - .map(extension => `${path}.${extension}`) - .some(isFileExists); -} - -function isFileExists(file): boolean { - try { - const path = join(EXAMPLES_DEST, file); - accessSync(path); - return true; - } catch (e) { - return false; - } -} - -function isFile(id) { - return EXTENSIONS.some(extension => id.endsWith(extension)); -} - -function withoutExtension(file) { - return file.replace(/\.(ts|html|scss)/, ''); -} diff --git a/scripts/gulp/tasks/docs/export-themes.ts b/scripts/gulp/tasks/docs/export-themes.ts deleted file mode 100644 index d60de2ad..00000000 --- a/scripts/gulp/tasks/docs/export-themes.ts +++ /dev/null @@ -1,158 +0,0 @@ -const _ = require('lodash'); -const fs = require('fs'); -const Colors = require('colors.js'); - -class Prop { - public name: string; - public value: any = null; - public parents: any[] = []; - public childs: any[] = []; - - constructor(name) { - this.name = name; - }; -} - -class PropLink { - public theme: any; - public prop: any; - - constructor(theme, prop) { - this.theme = theme; - this.prop = prop; - } -} - -const exporter = { - get_value(a) { - let value, i; - switch (a.constructor.name) { - case 'SassList': - value = []; - for (i = 0; i < a.getLength(); i++) { - value.push(exporter.get_value(a.getValue(i))); - } - break; - case 'SassMap': - value = {}; - for (i = 0; i < a.getLength(); i++) { - value[a.getKey(i).getValue()] = exporter.get_value(a.getValue(i)); - } - break; - case 'SassColor': - if (1 === a.getA()) { - value = Colors.rgb2hex(a.getR(), a.getG(), a.getB()); - } else { - value = 'rgba(' + a.getR() + ', ' + a.getG() + ', ' + a.getB() + ', ' + a.getA() + ')'; - } - break; - case 'SassNumber': - value = a.getValue(); - if (a.getUnit()) { - value += a.getUnit(); - } - break; - case 'SassNull': - value = null; - break; - default: - value = a.getValue(); - } - return value; - }, - - parseThemes(THEMES) { - let result = {}; - - Object.keys(THEMES).forEach((themeName) => { - result[themeName] = result[themeName] ? result[themeName] : {}; - result[themeName].data = result[themeName].data ? result[themeName].data : {}; - result[themeName].name = themeName; - result[themeName].parent = THEMES[themeName].parent; - const theme = THEMES[themeName].data; - - Object.keys(theme).forEach((prop) => { - result[themeName].data[prop] = result[themeName].data[prop] ? result[themeName].data[prop] : new Prop(prop); - result = exporter.getParent(prop, themeName, themeName, prop, result, THEMES); - }); - }); - - return result; - }, - - getParent(prop, scopedThemeName, resultThemeName, resultProp, resultObj, THEMES) { - const scopedTheme = THEMES[scopedThemeName].data; - const scopedParent = THEMES[scopedThemeName].parent; - const value = scopedTheme[prop]; - if (typeof value === 'string' && scopedTheme[value]) { - if (resultObj[resultThemeName].data[resultProp].parents.length === 0) { - exporter.linkProps(resultObj, scopedThemeName, value, resultThemeName, prop); - } else { - resultObj[resultThemeName].data[resultProp].parents.push(new PropLink(scopedThemeName, value)); - } - exporter.getParent(value, scopedThemeName, resultThemeName, resultProp, resultObj, THEMES); - } else { - resultObj[resultThemeName].data[resultProp].value = value; - if (scopedParent && THEMES[scopedParent].data[prop] === value) { - if (resultObj[resultThemeName].data[resultProp].parents.length === 0) { - exporter.linkProps(resultObj, scopedParent, prop, resultThemeName, prop) - } else { - resultObj[resultThemeName].data[resultProp].parents.push(new PropLink(scopedParent, prop)); - } - } - } - return resultObj; - }, - - - linkProps(resultObj, parentThemeName, parentPropName, childThemeName, childPropName) { - if (!resultObj.hasOwnProperty(parentThemeName)) { - resultObj[parentThemeName].data = {}; - resultObj[parentThemeName].data[parentPropName] = new Prop(parentPropName); - } else if (!resultObj[parentThemeName].data.hasOwnProperty(parentPropName)) { - resultObj[parentThemeName].data[parentPropName] = new Prop(parentPropName); - } - resultObj[childThemeName].data[childPropName].parents.push(new PropLink(parentThemeName, parentPropName)); - resultObj[parentThemeName].data[parentPropName].childs.push(new PropLink(childThemeName, childPropName)); - return resultObj; - }, - - - function(path) { - return function (file, themes, mapping) { - const themesValue = exporter.get_value(themes); - const mappingValue = exporter.get_value(mapping); - - const completeThemes = {}; - Object.keys(themesValue).forEach((themeName) => { - const theme = themesValue[themeName]; - completeThemes[themeName] = { - ...theme, - data: _.defaults(mappingValue, theme.data), - }; - }); - - - let output = { - themes: exporter.parseThemes(themesValue), - // TODO: we need to change internal function interface as it very hard to re-use them - completeThemes: exporter.parseThemes(completeThemes), - }; - - output = _.defaults(JSON.parse(fs.readFileSync(path + '/' + file.getValue())), output); - fs.writeFileSync(path + '/' + file.getValue(), JSON.stringify(output, null, ' ')); - return themes; - } - }, - - interface(name) { - name = name || 'export'; - return name + '($file, $themes, $mapping)'; - }, -}; - -export function exportThemes(path, name) { - const out = {}; - out[exporter.interface(name)] = exporter.function(path); - return out; -}