Skip to content

Commit

Permalink
Live editing base.
Browse files Browse the repository at this point in the history
  • Loading branch information
INFRAGISTICS\tiliev committed Mar 2, 2018
1 parent 825a9ca commit 790a952
Show file tree
Hide file tree
Showing 15 changed files with 419 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

Expand Down
12 changes: 12 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ gulp.task("watch-live-editing", ["generate-live-editing"], () => {
["generate-live-editing"]);
});

gulp.task("conf", function () {
var tsNode = require('ts-node').register({
fast: true,
ignore: [/\/node_modules\/(?!igniteui-angular)/],
compilerOptions: {
allowJs: true
}
})

require("./live-editing/LiveEditingManager.ts");
});

function requireFile(path) {
delete require.cache[require.resolve(path)];
return require(path);
Expand Down
15 changes: 15 additions & 0 deletions live-editing/LiveEditingFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const ASSETS_REG_EXP = new RegExp("assets/");

export class LiveEditingFile {
public path: string;
public content: string;
public hasRelativeAssetsUrls: boolean = false;

constructor(path: string, content: string) {
this.path = path;
this.content = content;
if (ASSETS_REG_EXP.test(content)) {
this.hasRelativeAssetsUrls = true;
}
}
}
19 changes: 19 additions & 0 deletions live-editing/LiveEditingManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SampleAssetsGenerator } from "./SampleAssetsGenerator";
import { SharedAssetsGenerator } from "./SharedAssetsGenerator";

class LiveEditingManager {
private sharedAssetsGenerator: SharedAssetsGenerator;
private sampleAssetsGenerator: SampleAssetsGenerator;

constructor() {
this.sharedAssetsGenerator = new SharedAssetsGenerator();
this.sampleAssetsGenerator = new SampleAssetsGenerator();
}

public run() {
//this.sharedAssetsGenerator.generateSharedAssets();
this.sampleAssetsGenerator.generateSamplesAssets();
}
}

new LiveEditingManager().run();
154 changes: 154 additions & 0 deletions live-editing/SampleAssetsGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { GridConfigGenerator } from "./configs/GridConfigGenerator";

import * as fs from "fs";
import * as path from "path";
import * as Collections from "typescript-collections";
import { LiveEditingFile } from "./LiveEditingFile";
import { IConfigGenerator } from "./configs/core/IConfigGenerator";
import { Config } from "./configs/core/Config";
import { TsImportsService } from "./TsImportsService";
import { Type } from "@angular/core/src/type";

const BASE_PATH = path.join(__dirname, "../");
//const BASE_PATH = path.join(__dirname, "../src/app/");
const ASSETS_SAMPLES_DIR = path.join(__dirname, "../src/assets/samples/");
const APP_MODULE_TEMPLATE_PATH = path.join(__dirname, "/templates/app.module.ts.template");
const APP_MODULE_PATH = path.join(__dirname, "../src/app/app.module.ts");

const COMPONENT_FILE_EXTENSIONS = ["ts", "html", "scss"];
const GO_DIR_BACK_REG_EX = new RegExp(/\.\.\//g);

const SAMPLE_ASSETS_BASE_DIR = "app/";
const CONFIG_GENERATORS = [GridConfigGenerator];

export class SampleAssetsGenerator {
private tsImportsService: TsImportsService;

constructor() {
if (!fs.existsSync(ASSETS_SAMPLES_DIR)) {
fs.mkdirSync(ASSETS_SAMPLES_DIR);
}

this.tsImportsService = new TsImportsService();
}

public generateSamplesAssets() {
let currentFileImports = this.tsImportsService.getFileImports(__filename);
for (let i = 0; i < CONFIG_GENERATORS.length; i++) {
let configGeneratorFilePath = path.join(__dirname, currentFileImports.getValue(CONFIG_GENERATORS[i].name) + ".ts");
let configGeneratorImports = this.tsImportsService.getFileImports(configGeneratorFilePath);
let configs = (new CONFIG_GENERATORS[i]).generateConfigs();
for (var j = 0; j < configs.length; j++) {
this.generateSampleAssets(configs[j], configGeneratorImports);
}
}
}

private generateSampleAssets(config: Config, configImports: Collections.Dictionary<string, string>) {
let componentModuleSpecifier = configImports.getValue(config.component.name);
let componentPath = componentModuleSpecifier.replace(GO_DIR_BACK_REG_EX, "");
let componentFilesPaths = new Array<string>();
for (var i = 0; i < COMPONENT_FILE_EXTENSIONS.length; i++) {
componentFilesPaths.push(componentPath + "." + COMPONENT_FILE_EXTENSIONS[i]);
}

let sampleFiles = new Array<LiveEditingFile>();
let componentTsContent: string;
for (let i = 0; i < componentFilesPaths.length; i++) {
let filePath = componentFilesPaths[i].substring(componentFilesPaths[i].indexOf(SAMPLE_ASSETS_BASE_DIR));
let fileContent = fs.readFileSync(path.join(BASE_PATH, componentFilesPaths[i]), "utf8");
let file = new LiveEditingFile(filePath, fileContent);
this.shortenComponentPath(config, file);
sampleFiles.push(file);
//if (componentFilesPaths[i].indexOf(".ts") !== -1) {
// componentTsContent = fileContent;
//}
}

if (config.additionalFiles !== null && config.additionalFiles.length > 0) {
for (let i = 0; i < config.additionalFiles.length; i++) {
var filePath = config.additionalFiles[i].substring(config.additionalFiles[i].indexOf(SAMPLE_ASSETS_BASE_DIR));
var fileContent = fs.readFileSync(path.join(BASE_PATH, config.additionalFiles[i]), "utf8");
var file = new LiveEditingFile(filePath, fileContent);
this.shortenComponentPath(config, file);
sampleFiles.push(file);
}
}

//var appModuleFile = new LiveEditingFile("app/app.module.ts", getAppModuleConfig(sampleConfig));
//sampleFiles.push(shortenComponentPath(sampleConfig, appModuleFile, appModulePath, shortenComponentPathExceptions));
//sampleFiles.push(new LiveEditingFile("app/app.component.html", getAppComponentHtml(componentTsContent)));

//fs.writeFileSync(assetsSamplesDir + sampleConfig.componentRoutePath + ".json", JSON.stringify(sampleFiles));
}

//private getAppComponentHtml(componentTsContent) {
// var componentSelectorRegex = /selector:[\s]*["']([a-zA-Z0-9-]+)["']/g;
// var componentSeletcor = componentSelectorRegex.exec(componentTsContent)[1];
// var appComponentHtml = "<" + componentSeletcor + "></" + componentSeletcor + ">";
// return appComponentHtml;
//}

//private getAppModuleConfig(sampleConfig) {
// var appModuleTemplate = fs.readFileSync(APP_MODULE_TEMPLATE_PATH, "utf8");

// var imports = "";
// for (var i = 0; i < sampleConfig.appModuleConfig.imports.length; i++) {
// var appModuleImport = '\r\nimport { ' +
// this.formatAppModuleTypes(sampleConfig.appModuleConfig.imports[i].import.split(","), false, 1, "\r\n") +
// ' } from "' + sampleConfig.appModuleConfig.imports[i].from + '";';
// imports = imports + appModuleImport;
// }

// var ngDeclarations = "," + this.formatAppModuleTypes(sampleConfig.appModuleConfig.ngDeclarations.split(','), true, 2);
// var ngImports = "," + this.formatAppModuleTypes(sampleConfig.appModuleConfig.ngImports.split(","), true, 2);

// var ngProviders = "";
// if (sampleConfig.appModuleConfig.ngProviders) {
// ngProviders = this.formatAppModuleTypes(sampleConfig.appModuleConfig.ngProviders.split(","), false, 2, "\r\n\t");
// }

// appModuleTemplate = appModuleTemplate
// .replace("{imports}", imports)
// .replace("{ngDeclarations}", ngDeclarations)
// .replace("{ngImports}", ngImports)
// .replace("{ngProviders}", ngProviders);

// return appModuleTemplate;
//}

private formatAppModuleTypes(types, multiline, tabsCount, suffixIfMultiple) {
if (types.length === 1 && !multiline) {
return types.join("");
}

let formattedTypes = "\r\n";
let tabs = "";
for (let i = 0; i < tabsCount; i++) {
tabs = tabs + "\t";
}

for (let i = 0; i < types.length; i++) {
formattedTypes = formattedTypes + tabs + types[i].trim();
if (i < types.length - 1) {
formattedTypes = formattedTypes + ",\r\n";
}
}

if (suffixIfMultiple) {
formattedTypes = formattedTypes + suffixIfMultiple;
}

return formattedTypes;
}

private shortenComponentPath(config: Config, file: LiveEditingFile) {
if (!config.shortenComponentPathBy) {
return;
}

let shorteningRegex = new RegExp(config.shortenComponentPathBy, "g");
file.path = file.path.replace(shorteningRegex, "/");
file.content = file.content.replace(shorteningRegex, "/");
}
}
11 changes: 11 additions & 0 deletions live-editing/SharedAssetsFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { LiveEditingFile } from "./LiveEditingFile";

export class SharedAssetsFile {
public dependencies: string;
public files: Array<LiveEditingFile>;

constructor(dependencies: string, files: Array<LiveEditingFile>) {
this.dependencies = dependencies;
this.files = files;
}
}
77 changes: 77 additions & 0 deletions live-editing/SharedAssetsGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as fs from "fs";
import * as path from "path";
import { LiveEditingFile } from "./LiveEditingFile";
import { SharedAssetsFile } from "./SharedAssetsFile";
import * as Collections from "typescript-collections";

const SAMPLES_PACKAGE_DEPENDENCIES = [
"@angular/animations",
"@angular/common",
"@angular/compiler",
"@angular/core",
"@angular/forms",
"@angular/http",
"@angular/platform-browser",
"@angular/platform-browser-dynamic",
"@angular/router",
"@types/hammerjs",
"classlist.js",
"core-js",
"hammerjs",
"igniteui-angular",
"intl",
"rxjs",
"web-animations-js",
"zone.js"
];

const PACKAGES_CONFIG_PATH = path.join(__dirname, "../package.json");
const INDEX_FILE_PATH = path.join(__dirname, "../src/index.html");
const POLYPFILLS_FILE_PATH = path.join(__dirname, "../src/polyfills.ts");
const STYLES_FILE_PATH = path.join(__dirname, "../src/styles.scss");
const ANGULAR_CLI_TEMPLATE_PATH = path.join(__dirname, "../live-editing/templates/angular-cli.json.template");
const MAIN_TS_FILE_PATH = path.join(__dirname, "../live-editing/templates/main.ts.template");
const APP_COMPONENT_SCSS_PATH = path.join(__dirname, "../src/app/app.component.scss");
const APP_COMPONENT_TS_PATH = path.join(__dirname, "../src/app/app.component.ts");
const ASSETS_SAMPLES_DIR = path.join(__dirname, "../src/assets/samples/");

export class SharedAssetsGenerator {
constructor() {
if (!fs.existsSync(ASSETS_SAMPLES_DIR)) {
fs.mkdirSync(ASSETS_SAMPLES_DIR);
}
}

public generateSharedAssets() {
let files = new Array<LiveEditingFile>();

files.push(new LiveEditingFile("index.html", fs.readFileSync(INDEX_FILE_PATH, "utf8")));
files.push(new LiveEditingFile("polyfills.ts", fs.readFileSync(POLYPFILLS_FILE_PATH, "utf8")));
files.push(new LiveEditingFile("styles.scss", fs.readFileSync(STYLES_FILE_PATH, "utf8")));
files.push(new LiveEditingFile(".angular-cli.json", fs.readFileSync(ANGULAR_CLI_TEMPLATE_PATH, "utf8")));
files.push(new LiveEditingFile("main.ts", fs.readFileSync(MAIN_TS_FILE_PATH, "utf8")));
files.push(new LiveEditingFile("app/app.component.scss", fs.readFileSync(APP_COMPONENT_SCSS_PATH, "utf8")));
files.push(new LiveEditingFile("app/app.component.ts", fs.readFileSync(APP_COMPONENT_TS_PATH, "utf8")));

let sharedFile = new SharedAssetsFile(JSON.stringify(this.getSamplesPackageDependencies()), files);
fs.writeFileSync(ASSETS_SAMPLES_DIR + "/shared.json", JSON.stringify(sharedFile));
}

private getSamplesPackageDependencies() {
let packageFile = JSON.parse(fs.readFileSync(PACKAGES_CONFIG_PATH, "utf8"));
let packageFileDependencies = packageFile.dependencies;
let dependenciesNeeded = new Collections.Set<string>();

for (let i = 0; i < SAMPLES_PACKAGE_DEPENDENCIES.length; i++) {
dependenciesNeeded.add(SAMPLES_PACKAGE_DEPENDENCIES[i]);
}

for (let key in packageFileDependencies) {
if (!dependenciesNeeded.contains(key)) {
delete packageFileDependencies[key];
}
}

return packageFileDependencies;
}
}
46 changes: 46 additions & 0 deletions live-editing/TsImportsService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as Collections from "typescript-collections";
import * as ts from "typescript";
import * as fs from "fs";

export class TsImportsService {
public getFileImports(filePath: string): Collections.Dictionary<string, string> {
let sourceFile = ts.createSourceFile(filePath, fs.readFileSync(filePath).toString(), ts.ScriptTarget.ES2015, true);
let imports = new Collections.Dictionary<string, string>();
let children = sourceFile.getChildren()[0].getChildren();
for (let i = 0; i < children.length; i++) {
this.getImports(children[i], imports);
}

return imports;
}

private getImports(node: ts.Node, imports: Collections.Dictionary<string, string>) {
if (node.kind === ts.SyntaxKind.ImportDeclaration) {
let importDeclaration = (<ts.ImportDeclaration>node);
let moduleSpecifier = importDeclaration.moduleSpecifier.getText();
moduleSpecifier = moduleSpecifier.substring(1, moduleSpecifier.length - 1);
let importSpecifiers = new Array<string>();
let children = node.getChildren();
for (let i = 0; i < children.length; i++) {
this.getImportSpecifiers(node, importSpecifiers);
}

for (let i = 0; i < importSpecifiers.length; i++) {
imports.setValue(importSpecifiers[i], moduleSpecifier);
}
}
}

private getImportSpecifiers(node: ts.Node, importSpecifiers: Array<string>) {
if (node.kind === ts.SyntaxKind.ImportSpecifier) {
let importSpecifier = (<ts.ImportSpecifier>node);
importSpecifiers.push(importSpecifier.getText());
return;
}

let children = node.getChildren();
for (let i = 0; i < children.length; i++) {
this.getImportSpecifiers(children[i], importSpecifiers);
}
}
}
4 changes: 4 additions & 0 deletions live-editing/configs/AvatarConfigs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Config } from "./core/Config";

export class AvatarConfigs implements IConfigGenerator {
}
Loading

0 comments on commit 790a952

Please sign in to comment.