From 4f48cfdb7e98dbbd7dd28c78b85de80b3389cb21 Mon Sep 17 00:00:00 2001 From: roguib Date: Tue, 3 Aug 2021 23:22:30 +0200 Subject: [PATCH 01/10] path-resolver.ts --- src/utils/path-resolver.ts | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/utils/path-resolver.ts diff --git a/src/utils/path-resolver.ts b/src/utils/path-resolver.ts new file mode 100644 index 0000000..73d936e --- /dev/null +++ b/src/utils/path-resolver.ts @@ -0,0 +1,74 @@ +const path = require("path"); +const fs = require("fs"); + +/** + * @param {string} filePath Path of the file that extends the base class + * @param {string} importExpr The expression used to import the base class + * @returns {string} An absolute path to the imported file + */ +/** + * TODO: Everytime resolve is being called, it has to open the tsconfig file. We should + * store the definition of that file into the memory, so future access are faster. + */ +export const resolve = ( + filePath: string, + importExpr: string +): string | null => { + /** + * @param {string} importExpr The expression used to import the class in the file + * @returns {string} The the path in the import expression + */ + const extractPathFromImportExpr = (importExpr: string): string => { + let path = importExpr.substr(importExpr.indexOf('"') + 1); + return path.replace(/\"/g, ""); + }; + + let resolvedPath = "", + pathToFile = extractPathFromImportExpr(importExpr); + + if (pathToFile.startsWith("@")) { + const rootProjectDir = process.env.ROOT_PROJECT_PATH; + + const tsconfigFile: any = JSON.parse( + fs.readFileSync(path.resolve(`${rootProjectDir}/tsconfig.json`), { + encoding: "utf8", + flag: "r", + }) + ); + + let compilerOptionsPathsKey = pathToFile.substr(0, pathToFile.indexOf("/")), + compilerOptionsPathsValue = ""; + if (compilerOptionsPathsKey + "/*" in tsconfigFile.compilerOptions.paths) { + compilerOptionsPathsValue = + tsconfigFile.compilerOptions.paths[compilerOptionsPathsKey + "/*"]; + } // TODO: else throw an exception + + const aux = path.join( + path.posix.resolve(), + pathToFile + .replace(compilerOptionsPathsKey, compilerOptionsPathsValue) + .replace(/(\s+)/g, " ") + .replace(/"/g, "") + ".ts" + ); + + resolvedPath = path.join( + path.posix.resolve(), + pathToFile + .replace(compilerOptionsPathsKey, compilerOptionsPathsValue) + .replace(/(\s+)/g, " ") + .replace(/"/g, "") + ".ts" + ); + } else { + resolvedPath = path.join( + path.dirname(filePath), + pathToFile.replace(/(\s+)/g, " ").replace(/"/g, "") + ".ts" + ); + } + + // TODO: Throw an error if the function is unable to resolve the path + return resolvedPath; +}; + +export default { + resolve, +}; From c44da5cabc5319cc00db2abcfe8f5c048ff95299 Mon Sep 17 00:00:00 2001 From: roguib Date: Tue, 3 Aug 2021 23:28:15 +0200 Subject: [PATCH 02/10] use path-resolver.ts to resolve the paths of the extended classes --- src/parser.ts | 89 ++++++++++++-------------------------- src/utils/path-resolver.ts | 3 ++ 2 files changed, 30 insertions(+), 62 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index fd070d8..2cb51b4 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -3,6 +3,7 @@ const path = require("path"); import { File, Input, Output } from "./shared/IFile"; import logger from "./shared/logger"; +import pathResolver from "./utils/path-resolver"; // selectors const componentSelector = /export(\s+)class(\s+)[a-zA-Z0-9-_]+/g; @@ -31,11 +32,11 @@ const regularOutputSelector = /@Output\(\)(\s+)[a-zA-Z0-9-_]+:(\s+)EventEmitter< // other const extendedClassSelector = /export(\s+)class(\s+)[a-zA-Z0-9-_]+(\s+)extends(\s+)[a-zA-Z0-9-_]+/g; -const extendedClassPathSelector = /import(\s+){(\s+)[a-zA-Z0-9-_]+(\s+)}(\s+)from(\s+)[\/A-Za-z0-9."'_-]+/g; +const extendedClassPathSelector = /import(\s+){(\s+)[a-zA-Z0-9-_]+(\s+)}(\s+)from(\s+)[\/\@A-Za-z0-9."'_-]+/g; // TODO: class implementation with inputs/outputs defined -// TODO: Test in in other OS (github actions) -// TODO: Read files synchronously +// TODO: Test in other OS (github actions) +// TODO: Read files asynchronously to improve performance? export const parser = (filePaths: Array): Array => { let result: Array = []; // a temporal variable used for storing @Inputs/@Outputs declared on a parent class @@ -61,8 +62,7 @@ export const parser = (filePaths: Array): Array => { continue; } - let fileNameData: Array = - file?.match(componentSelector) || []; + let fileNameData: Array = file?.match(componentSelector) || []; if (fileNameData.length === 0) { logger.warn("Component tag not defined by any class."); continue; @@ -93,11 +93,9 @@ export const parser = (filePaths: Array): Array => { // Input() foo: 'type1' | 'type2' let inputs: Array = []; let inputsData: Array = - file?.match( - regularInputLiteralTypeSelector - ) || []; + file?.match(regularInputLiteralTypeSelector) || []; for (let input of inputsData) { - logger.log('inputs parsed:', inputsData); + logger.log("inputs parsed:", inputsData); let tmp: Array = input.replace(/(\s)+/g, " ").split(" "); let type = tmp .slice(2, tmp.length) @@ -113,10 +111,7 @@ export const parser = (filePaths: Array): Array => { // @Input() variableName: type; and @Input() variableName: number = 9; inputsData = []; - inputsData = - file?.match( - regularInputWithTypeSelector - ) || []; + inputsData = file?.match(regularInputWithTypeSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); logger.log("input data", inputsData); @@ -129,16 +124,11 @@ export const parser = (filePaths: Array): Array => { inputsData = []; // @Input('inputName') varName: type; and @Input("inputName") varName: type - inputsData = - file?.match( - customNameInputWithTypeSelector - ) || []; + inputsData = file?.match(customNameInputWithTypeSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); - const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) || [])[0].replace( - /'|"/g, - "" - ); + const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) || + [])[0].replace(/'|"/g, ""); inputs.push({ inputName, type: tmp[2].replace(";", ""), @@ -149,10 +139,7 @@ export const parser = (filePaths: Array): Array => { // @Input('inputNameC') varName = 'adv'; // @Input("inputNameD") varName = 2354; inputsData = []; - inputsData = - file?.match( - setterInputCustomNameSelector - ) || []; + inputsData = file?.match(setterInputCustomNameSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); const inputName = (tmp[0].match(/('|")[a-zA-Z0-9-_]+('|")/g) || [ @@ -167,10 +154,7 @@ export const parser = (filePaths: Array): Array => { //@Input() set foo(value) {} inputsData = []; - inputsData = - file?.match( - setterInputSelector - ) || []; + inputsData = file?.match(setterInputSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0]; @@ -183,10 +167,7 @@ export const parser = (filePaths: Array): Array => { //@Input() set foo(value: type) {} inputsData = []; - inputsData = - file?.match( - setterInputWithTypeSelector - ) || []; + inputsData = file?.match(setterInputWithTypeSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0]; @@ -200,18 +181,15 @@ export const parser = (filePaths: Array): Array => { //@Input() set foo(value: 'type1' | 'type2') {} inputsData = []; - inputsData = - file?.match( - setterInputLiteralTypeSelector - ) || []; + inputsData = file?.match(setterInputLiteralTypeSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); const inputName = tmp[2].replace(/(\s+)/g, "").split("(")[0]; const type = tmp - .slice(3, tmp.length) - .join() - .replace(/'|"|\)/g, "") - .replace(/,/g, " "); + .slice(3, tmp.length) + .join() + .replace(/'|"|\)/g, "") + .replace(/,/g, " "); inputs.push({ inputName, type, @@ -239,10 +217,7 @@ export const parser = (filePaths: Array): Array => { let outputs: Array = []; // only @Output() buttonClick: EventEmitter = new EventEmitter(); for now - let outputsData: Array = - file?.match( - regularOutputSelector - ) || []; + let outputsData: Array = file?.match(regularOutputSelector) || []; for (let output of outputsData) { let tmp: Array = output.replace(/(\s+)/g, " ").split(" "); outputs.push({ @@ -257,33 +232,23 @@ export const parser = (filePaths: Array): Array => { logger.log("Outputs detected:", outputs); let extendedClassPath; - if ( - file?.match( - extendedClassSelector - ) - ) { + if (file?.match(extendedClassSelector)) { // we should see if the extended class is in tmp and if not extract the inputs defined inside let matchExtendedClass: Array = - file?.match( - extendedClassSelector - ) || []; + file?.match(extendedClassSelector) || []; // resolve the path of the class let extendedClass: string = matchExtendedClass[0] .replace(/(\s+)/g, " ") .split(" ")[4]; logger.log("extendedClassName:", extendedClass); let matchExtendedClassPath: Array = - file?.match( - extendedClassPathSelector - ) || []; - // TODO: Document this in notes. Notice that by using path.join(path.dirname(fullComponentClassPath), relative path of the base path from ComponentClassPath) resolves into the full path of the base path - extendedClassPath = path.join( - path.dirname(filePath), + file?.match(extendedClassPathSelector) || []; + + extendedClassPath = pathResolver.resolve( + filePath, matchExtendedClassPath[0] - .replace(/(\s+)/g, " ") - .replace(/"/g, "") - .split(" ")[5] + ".ts" ); + logger.log("path:", extendedClassPath); } diff --git a/src/utils/path-resolver.ts b/src/utils/path-resolver.ts index 73d936e..61a79aa 100644 --- a/src/utils/path-resolver.ts +++ b/src/utils/path-resolver.ts @@ -51,6 +51,9 @@ export const resolve = ( .replace(/"/g, "") + ".ts" ); + // Notice that by calling path.join with a relative path of the base + // path from ComponentClassPath and the full path of the file resolves into the + // full path of the base path resolvedPath = path.join( path.posix.resolve(), pathToFile From 313286bb1cf2a716f29b793ef73459f43dd38436 Mon Sep 17 00:00:00 2001 From: roguib Date: Tue, 3 Aug 2021 23:44:34 +0200 Subject: [PATCH 03/10] fixtures and test for importing a class with a path starting with a @ --- tests/fixtures/parser/main.component.ts | 24 ++++------ .../special-base.component.ts | 5 +++ .../special-path.component.ts | 10 +++++ tests/fixtures/parser/tsconfig.json | 24 ++++++++++ tests/parser.test.ts | 45 ++++++++++++++++++- 5 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 tests/fixtures/parser/special-path-tsconfig/special-base.component.ts create mode 100644 tests/fixtures/parser/special-path-tsconfig/special-path.component.ts create mode 100644 tests/fixtures/parser/tsconfig.json diff --git a/tests/fixtures/parser/main.component.ts b/tests/fixtures/parser/main.component.ts index bd225ca..bf3abeb 100644 --- a/tests/fixtures/parser/main.component.ts +++ b/tests/fixtures/parser/main.component.ts @@ -7,31 +7,25 @@ import { BaseComponent } from "./base.component"; }) export class MainComponent extends BaseComponent { foo = false; - @Input() literalType1: 'type1' | 'type2' | 'type3'; - @Input() literalType2: 'type1' | 'type2' | 'type3' = 'type1'; - @Input() literal_Type3: 'type1' | 'type2' | 'type3' = 'type1'; + @Input() literalType1: "type1" | "type2" | "type3"; + @Input() literalType2: "type1" | "type2" | "type3" = "type1"; + @Input() literal_Type3: "type1" | "type2" | "type3" = "type1"; @Input() appName: MediaModel; @Input() foo: TypeError; @Input() numberInput: number = 9; @Input("inputNameA") varName: type; - @Input('inputNameB') varName: type; - @Input('inputNameC') varName = 'adv'; + @Input("inputNameB") varName: type; + @Input("inputNameC") varName = "adv"; @Input("inputNameD") varName = 2354; @Input() withoutType; @Input() withoutTypeNorSemicolon; - @Input() variableAssignedValue = 9 + @Input() variableAssignedValue = 9; @Input() variableAssignedValueAndSemicolon = value; @Output() buttonClick: EventEmitter = new EventEmitter(); @Output() fooVar: EventEmitter = new EventEmitter(); - @Input() set Foo(value) { - - } - @Input() set FooType(value: string) { - - } - @Input() set FooTypeLiteral(value: 'literal1' | 'literal2' | 'literal3') { - - } + @Input() set Foo(value) {} + @Input() set FooType(value: string) {} + @Input() set FooTypeLiteral(value: "literal1" | "literal2" | "literal3") {} someRandomFunction(action) { action = "action"; diff --git a/tests/fixtures/parser/special-path-tsconfig/special-base.component.ts b/tests/fixtures/parser/special-path-tsconfig/special-base.component.ts new file mode 100644 index 0000000..e3405f0 --- /dev/null +++ b/tests/fixtures/parser/special-path-tsconfig/special-base.component.ts @@ -0,0 +1,5 @@ +import { Input } from "@angular/core"; + +export class SpecialBaseComponent { + @Input() baseInputInSpecialBaseClass: "type1" | "type2" | "type3"; +} diff --git a/tests/fixtures/parser/special-path-tsconfig/special-path.component.ts b/tests/fixtures/parser/special-path-tsconfig/special-path.component.ts new file mode 100644 index 0000000..79ac015 --- /dev/null +++ b/tests/fixtures/parser/special-path-tsconfig/special-path.component.ts @@ -0,0 +1,10 @@ +import { Component, Input } from "@angular/core"; +import { SpecialBaseComponent } from "@special-base/special-base.component"; + +@Component({ + selector: "app-main", + templateUrl: "./app.main.component.html", +}) +export class SpecialPathComponent extends SpecialBaseComponent { + @Input() inputInChildClass: "type1" | "type2" | "type3"; +} diff --git a/tests/fixtures/parser/tsconfig.json b/tests/fixtures/parser/tsconfig.json new file mode 100644 index 0000000..2475b1c --- /dev/null +++ b/tests/fixtures/parser/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "sourceRoot": "/", + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "module": "esnext", + "moduleResolution": "node", + "importHelpers": true, + "target": "es2015", + "lib": ["es2018", "dom"], + "paths": { + "@special-base/*": ["tests/fixtures/parser/special-path-tsconfig"] + } + }, + "angularCompilerOptions": { + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true + } +} diff --git a/tests/parser.test.ts b/tests/parser.test.ts index 0101bd5..0821ac1 100644 --- a/tests/parser.test.ts +++ b/tests/parser.test.ts @@ -5,8 +5,7 @@ test("Parses the contents of the candidate files and returns an array of File ty const result = [ { componentName: "MainComponent", - extendedClassFilepath: - path.join( + extendedClassFilepath: path.join( path.posix.resolve(), "/tests/fixtures/parser/base.component.ts" ), @@ -118,3 +117,45 @@ test("Parses the contents of the candidate files and returns an array of File ty ]) ).toStrictEqual(result); }); + +test("Tests the parser when de file is imported using the @ special keyword path defined in tsconfig.json", async () => { + process.env.ROOT_PROJECT_PATH = + "C:/Users/roger/oos/angular-vs-snippets/tests/fixtures/parser"; + const result = [ + { + componentName: "SpecialPathComponent", + extendedClassFilepath: path.join( + path.posix.resolve(), + "/tests/fixtures/parser/special-path-tsconfig/special-base.component.ts" + ), + fileLocation: path.join( + path.posix.resolve(), + "/tests/fixtures/parser/special-path-tsconfig/special-path.component.ts" + ), + inputs: [ + { + inputName: "inputInChildClass", + type: "'type1'|'type2'|'type3'", + }, + { + inputName: "baseInputInSpecialBaseClass", + type: "'type1'|'type2'|'type3'", + }, + ], + outputs: [], + prefix: "app-main", + }, + ]; + expect( + parser.parser([ + path.join( + path.posix.resolve(), + "/tests/fixtures/parser/special-path-tsconfig/special-base.component.ts" + ), + path.join( + path.posix.resolve(), + "/tests/fixtures/parser/special-path-tsconfig/special-path.component.ts" + ), + ]) + ).toStrictEqual(result); +}); From 522b6a200ad96b418868780ba1dd564873b985fa Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 12:14:00 +0200 Subject: [PATCH 04/10] fixed vscode launch config --- .vscode/launch.json | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5183bee..e7d5201 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,17 +19,11 @@ "request": "launch", "name": "End to end execution", "preLaunchTask": "npm: build:cjs", - "program": "./build/ng-vs-snippets", - "args": - [ - "--dir", - "./src", - "--output", - "./.vscode" - ], + "program": "./build/@roguib/ng-vs-snippets.js", + "args": ["--dir", "./src", "--output", "./.vscode"], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", - "disableOptimisticBPs": true, + "disableOptimisticBPs": true } ] } From 4fc582475f30ac73a5265cc594cf2141846260d1 Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 12:15:47 +0200 Subject: [PATCH 05/10] fix README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f0acdc..edd0d85 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Currently, we support snippet generation from the following Angular elements: Install ```ng-vs-snippets``` as a dev-dependency in your Angular project. To do so, run: ``` -npm i ng-vs-snippets --save-dev +npm i @roguib/ng-vs-snippets --save-dev ``` Create a ```package.json``` script to extract snippets from your codebase: From e13cf6c170d6d432fd00c5a19d6963adc676b8d6 Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 12:17:41 +0200 Subject: [PATCH 06/10] fix npm scripts --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 990a819..48ec579 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "scripts": { "build:cjs": "rollup -c", "check": "tsc", - "run": "node ./build/index.js", + "run": "node ./build/@roguib/ng-vs-snippets.js", "test": "npm run build:cjs && jest ./tests/*" }, "dependencies": { From 97b41790da4d1f2c641c1da9b8b63e77dc1a01a2 Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 12:27:01 +0200 Subject: [PATCH 07/10] index.ts clean-up --- src/index.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index bfc5539..eced47b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ -const fs = require("fs"); const path = require("path"); -const readline = require("readline"); const argv = process.argv; import * as walker from "./walker"; import * as parser from "./parser"; @@ -17,6 +15,9 @@ let config: ICLIConfig = { const parseArgs = (args: string[]) => { // TODO: Include multiple options + + logger.log("args:", args); + while (args.length > 0) { const arg = args.shift(); @@ -52,25 +53,24 @@ export const verifyArgs = () => { if (config.outputDir == null) { logger.err("No output directory specified. Aborting."); } -} +}; export const run = async (args: string[]) => { parseArgs(args); verifyArgs(); - // const config = parseArgs(args); if (config.debug) { logger.enableDebugger(); } + + process.env.ROOT_PROJECT_PATH = config.workingDir || path.posix.resolve(); + let candidateFilePaths: Array = walker.walker( - config.workingDir || path.posix.resolve(), + process.env.ROOT_PROJECT_PATH as string, [] ); let fileData: Array = parser.parser(candidateFilePaths); - generator.generator( - fileData, - config.outputDir as string - ); + generator.generator(fileData, config.outputDir as string); }; run(argv.slice(2, argv.length)); From b9ccf5f4d27f797fa823ab7d5a07a648dd7b5a86 Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 12:38:33 +0200 Subject: [PATCH 08/10] path-resolver.ts clean-up --- src/utils/path-resolver.ts | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/utils/path-resolver.ts b/src/utils/path-resolver.ts index 61a79aa..158a0d5 100644 --- a/src/utils/path-resolver.ts +++ b/src/utils/path-resolver.ts @@ -1,15 +1,17 @@ const path = require("path"); const fs = require("fs"); +let tsconfigFile: { + compilerOptions: { + paths: any; + }; +} | null = null; + /** * @param {string} filePath Path of the file that extends the base class * @param {string} importExpr The expression used to import the base class * @returns {string} An absolute path to the imported file */ -/** - * TODO: Everytime resolve is being called, it has to open the tsconfig file. We should - * store the definition of that file into the memory, so future access are faster. - */ export const resolve = ( filePath: string, importExpr: string @@ -29,28 +31,22 @@ export const resolve = ( if (pathToFile.startsWith("@")) { const rootProjectDir = process.env.ROOT_PROJECT_PATH; - const tsconfigFile: any = JSON.parse( - fs.readFileSync(path.resolve(`${rootProjectDir}/tsconfig.json`), { - encoding: "utf8", - flag: "r", - }) - ); + if (tsconfigFile == null) { + tsconfigFile = JSON.parse( + fs.readFileSync(path.resolve(`${rootProjectDir}/tsconfig.json`), { + encoding: "utf8", + flag: "r", + }) + ); + } let compilerOptionsPathsKey = pathToFile.substr(0, pathToFile.indexOf("/")), compilerOptionsPathsValue = ""; - if (compilerOptionsPathsKey + "/*" in tsconfigFile.compilerOptions.paths) { + if (compilerOptionsPathsKey + "/*" in tsconfigFile?.compilerOptions.paths) { compilerOptionsPathsValue = - tsconfigFile.compilerOptions.paths[compilerOptionsPathsKey + "/*"]; + tsconfigFile?.compilerOptions.paths[compilerOptionsPathsKey + "/*"]; } // TODO: else throw an exception - const aux = path.join( - path.posix.resolve(), - pathToFile - .replace(compilerOptionsPathsKey, compilerOptionsPathsValue) - .replace(/(\s+)/g, " ") - .replace(/"/g, "") + ".ts" - ); - // Notice that by calling path.join with a relative path of the base // path from ComponentClassPath and the full path of the file resolves into the // full path of the base path From 6c985116e5d740b302b431f7ace6f19781659d6f Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 13:42:52 +0200 Subject: [PATCH 09/10] pass all the tests --- src/parser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parser.ts b/src/parser.ts index 2cb51b4..9c96934 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -100,6 +100,7 @@ export const parser = (filePaths: Array): Array => { let type = tmp .slice(2, tmp.length) .join() + .replace(/\"/g, "'") .replace(";", "") .replace(/,/g, ""); inputs.push({ From c32e690b0ebc4faf220c1883af6e92ef406881bb Mon Sep 17 00:00:00 2001 From: roguib Date: Wed, 4 Aug 2021 18:43:04 +0200 Subject: [PATCH 10/10] several fixes needed to run the script inside an angular project --- README.md | 29 +++++++++++++++-------------- package-lock.json | 2 +- package.json | 6 +++--- src/parser.ts | 10 ++++++++-- src/utils/path-resolver.ts | 18 ++++++++++++++---- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index edd0d85..af395bd 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # ng-vs-snippets -![ts](https://badgen.net/badge/Built%20With/TypeScript/blue) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![made-for-VSCode](https://img.shields.io/badge/Made%20for-VSCode-1f425f.svg)](https://code.visualstudio.com/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) - +![ts](https://badgen.net/badge/Built%20With/TypeScript/blue) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![made-for-VSCode](https://img.shields.io/badge/Made%20for-VSCode-1f425f.svg)](https://code.visualstudio.com/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) Automatic VS Code snippet file generation for Angular codebases. Seamlessly maintain up-to-date VS Code snippets of all of your code. @@ -9,27 +8,27 @@ Currently, we support snippet generation from the following Angular elements:
-| Element | Status | -|-----------|:-----------------------------------------:| -| Component | :white_check_mark: Supported | -| Directive | :construction_worker: Not yet supported | -| Pipe | :construction_worker: Not yet supported | +| Element | Status | +| --------- | :-------------------------------------: | +| Component | :white_check_mark: Supported | +| Directive | :construction_worker: Not yet supported | +| Pipe | :construction_worker: Not yet supported |
## Installation -Install ```ng-vs-snippets``` as a dev-dependency in your Angular project. To do so, run: +Install `ng-vs-snippets` as a dev-dependency in your Angular project. To do so, run: ``` npm i @roguib/ng-vs-snippets --save-dev ``` -Create a ```package.json``` script to extract snippets from your codebase: +Create a `package.json` script to extract snippets from your codebase: ```json "scripts": { - "ng-vs-snippets": "ng-vs-snippets --dir ./src --output ./.vscode", + "ng-vs-snippets": "ng-vs-snippets --dir . --output ./.vscode", }, ``` @@ -39,16 +38,18 @@ Execute the script by running: npm run ng-vs-snippets ``` -The script will generate a ```out.code-snippets``` file containing all the definitions. **Make sure you don't have any file with the same name** since the data contained in that file **is going to be replaced**. +The script will generate a `out.code-snippets` file containing all the definitions. **Make sure you don't have any file with the same name** since the data contained in that file **is going to be replaced**. ## Troubleshooting -Sometimes, due to VS Code configuration issues, snippets don't appear in the suggestion's dropdown. Make sure to specify, in VS Code ```settings.json``` configuration file the following properties: + +Sometimes, due to VS Code configuration issues, snippets don't appear in the suggestion's dropdown. Make sure to specify, in VS Code `settings.json` configuration file the following properties: ```json "editor.tabCompletion": "on", "editor.snippetSuggestions": "top" ``` -If this doesn't fix the problem, open the command palette and search for ```Preferences: Configure User Snippets``` to ensure the editor is considering the fille where your generated snippets are defined. + +If this doesn't fix the problem, open the command palette and search for `Preferences: Configure User Snippets` to ensure the editor is considering the fille where your generated snippets are defined. ## Documentation @@ -56,4 +57,4 @@ You can find the [full document design at this url](). ## Contributing -Pull requests are welcome :) Make sure to create an issue first so anyone's work is overlaped. \ No newline at end of file +Pull requests are welcome :) Make sure to create an issue first so anyone's work is overlaped. diff --git a/package-lock.json b/package-lock.json index bf4f410..3d60285 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "ng-vs-snippets", + "name": "@roguib/ng-vs-snippets", "version": "0.1.0", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index 48ec579..a526e4a 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,10 @@ "angular", "vs snippets" ], - "main": "build/ng-vs-snippets.js", - "types": "build/ng-vs-snippets.d.ts", + "main": "build/@roguib/ng-vs-snippets.js", + "types": "build/@roguib/ng-vs-snippets.d.ts", "bin": { - "ng-vs-snippets": "build/ng-vs-snippets.js" + "ng-vs-snippets": "build/@roguib/ng-vs-snippets.js" }, "scripts": { "build:cjs": "rollup -c", diff --git a/src/parser.ts b/src/parser.ts index 9c96934..9a375c4 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -115,7 +115,6 @@ export const parser = (filePaths: Array): Array => { inputsData = file?.match(regularInputWithTypeSelector) || []; for (let input of inputsData) { let tmp: Array = input.replace(/(\s+)/g, " ").split(" "); - logger.log("input data", inputsData); inputs.push({ inputName: tmp[1].replace(":", ""), type: tmp[2].replace(";", ""), @@ -263,8 +262,15 @@ export const parser = (filePaths: Array): Array => { extendedClassFilepath: extendedClassPath || undefined, }); } else { + /** + * TODO: Instead of working with relative paths and converting them + * to absolute when needed, we can start the exec by transforming every + * relative path to absolute, and then clean up the resolve calls in the program + * that transforms the code into an spaguetti one. Also it could help by reducing + * the amount of times we call path.join(path.posix.resolve(), path); + */ tmp.push({ - fileLocation: filePath, + fileLocation: path.resolve(filePath), inputs: inputs, outputs: outputs, extendedClassFilepath: undefined, diff --git a/src/utils/path-resolver.ts b/src/utils/path-resolver.ts index 158a0d5..4bc4fa4 100644 --- a/src/utils/path-resolver.ts +++ b/src/utils/path-resolver.ts @@ -21,8 +21,13 @@ export const resolve = ( * @returns {string} The the path in the import expression */ const extractPathFromImportExpr = (importExpr: string): string => { - let path = importExpr.substr(importExpr.indexOf('"') + 1); - return path.replace(/\"/g, ""); + let pathIndex = importExpr.indexOf('"'); + + if (pathIndex === -1) { + pathIndex = importExpr.indexOf("'"); + } + let path = importExpr.substr(pathIndex + 1); + return path.replace(/\"/g, "").replace(/'/g, ""); }; let resolvedPath = "", @@ -41,19 +46,24 @@ export const resolve = ( } let compilerOptionsPathsKey = pathToFile.substr(0, pathToFile.indexOf("/")), - compilerOptionsPathsValue = ""; + compilerOptionsPathsValue: Array = [""]; if (compilerOptionsPathsKey + "/*" in tsconfigFile?.compilerOptions.paths) { compilerOptionsPathsValue = tsconfigFile?.compilerOptions.paths[compilerOptionsPathsKey + "/*"]; } // TODO: else throw an exception + compilerOptionsPathsValue[0] = compilerOptionsPathsValue[0].replace( + "/*", + "" + ); + // Notice that by calling path.join with a relative path of the base // path from ComponentClassPath and the full path of the file resolves into the // full path of the base path resolvedPath = path.join( path.posix.resolve(), pathToFile - .replace(compilerOptionsPathsKey, compilerOptionsPathsValue) + .replace(compilerOptionsPathsKey, compilerOptionsPathsValue[0]) .replace(/(\s+)/g, " ") .replace(/"/g, "") + ".ts" );