From 04882b673b37ac529b088834417b827876f844b7 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Fri, 22 Dec 2017 23:31:47 +0100 Subject: [PATCH 01/12] Add support for multiple soyToImport configs --- src/config.ts | 29 ++++++++++++++++++++--------- src/validate-call-imports.ts | 15 +++++++++++---- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/config.ts b/src/config.ts index b11c3c3..8492a10 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,29 +7,40 @@ const CONFIG_FILE_NAMES = [ '.soycriticrc.json', ]; +type CallToImportConfig = { + regex: string; + replace: string; +} + export interface ImplicitParamsMap { [nameOrRegex: string]: string | Array } export interface Config { - callToImportRegex: string - callToImportReplace: string + callToImport: Array implicitParams: ImplicitParamsMap } export const DEFAULT_CONFIG: Config = { - callToImportRegex: '(.*)', - callToImportReplace: '{$1}', + callToImport: [{regex: '(.*)',replace: '{$1}'}], implicitParams: {} }; export function validateConfig(config: Config): Config { - if (!isRegex(config.callToImportRegex)) { - throw new Error('callToImportRegex is not a valid RegExp.'); + if (!Array.isArray(config.callToImport)) { + throw new Error('callToImport is not a valid config array.'); } - if (!isRegex(config.callToImportReplace)) { - throw new Error('callToImportReplace is not a valid replace string.'); + for (let i=0; i < config.callToImport.length; i++) { + let callToImportItem = config.callToImport[i]; + + if (!isRegex(callToImportItem.regex)) { + throw new Error(`callToImport.regex "${callToImportItem.regex}" is not a valid RegExp.`); + } + + if (!isRegex(callToImportItem.replace)) { + throw new Error(`callToImport.replace "${callToImportItem.replace}" is not a valid replace string.`); + } } for (const key in config.implicitParams) { @@ -78,4 +89,4 @@ export function isRegex(regex: string): boolean { return false; } return true; -} +} \ No newline at end of file diff --git a/src/validate-call-imports.ts b/src/validate-call-imports.ts index 04abe23..8b47f68 100644 --- a/src/validate-call-imports.ts +++ b/src/validate-call-imports.ts @@ -33,11 +33,18 @@ function getImportPaths(ast: T.Node): Array { export default function valdiateCallImports(soyContext: SoyContext, jsContext: JSContext, config: Config): Result { const importNames = getImportPaths(jsContext.ast) .map(importPath => path.parse(importPath).name); - - const missingImports = getExternalSoyCalls(soyContext) + + const missingImports = getExternalSoyCalls(soyContext) .filter(name => { - name = transform(name, config.callToImportRegex, config.callToImportReplace); - return !importNames.find(importName => importName.includes(name)); + for (let i=0; i < config.callToImport.length; i++) { + let transformedName = transform(name, config.callToImport[i].regex, config.callToImport[i].replace); + + if (importNames.find(importName => importName.includes(transformedName))) { + return false; + } + } + + return true; }); if (missingImports.length) { From bff5560fe855f3fa9046e1e8c9ddee1d91d76209 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Fri, 22 Dec 2017 23:32:04 +0100 Subject: [PATCH 02/12] Add tests for the support of multiple callToImport config --- src/__tests__/__snapshots__/index.ts.snap | 2 +- src/__tests__/config.ts | 14 +++++++++----- test/fixtures/config-json/.soycriticrc.json | 8 ++++++-- test/fixtures/config/.soycriticrc | 8 ++++++-- test/fixtures/invalid-config/.soycriticrc | 8 ++++++-- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/__tests__/__snapshots__/index.ts.snap b/src/__tests__/__snapshots__/index.ts.snap index f7b1e9e..02ef876 100644 --- a/src/__tests__/__snapshots__/index.ts.snap +++ b/src/__tests__/__snapshots__/index.ts.snap @@ -7,7 +7,7 @@ exports[`cli should accept an ignore glob 1`] = ` `; exports[`cli should fail with invalid config file 1`] = ` -"Failed to read config: callToImportRegex is not a valid RegExp. +"Failed to read config: callToImport.regex \\"(\\\\S+\\" is not a valid RegExp. " `; diff --git a/src/__tests__/config.ts b/src/__tests__/config.ts index 3863d72..5696048 100644 --- a/src/__tests__/config.ts +++ b/src/__tests__/config.ts @@ -35,7 +35,7 @@ describe('config', () => { const config = Config.readConfig(); expect(config).toBeInstanceOf(Object); - expect(config.callToImportRegex).toBe('(.*)'); + expect(config.callToImport).toEqual([{regex: '(.*)', replace: '{$1}'}]); }); it('should return a configuration specified in a file', () => { @@ -43,7 +43,7 @@ describe('config', () => { const config = Config.readConfig(); - expect(config.callToImportRegex).toBe('(\\S+)'); + expect(config.callToImport).toEqual([{regex: '(\\S+)', replace: '{$1|param}'}]); }); it('should read config files with a json extension', () => { @@ -51,7 +51,7 @@ describe('config', () => { const config = Config.readConfig(); - expect(config.callToImportRegex).toBe('json'); + expect(config.callToImport).toEqual([{regex: 'json', replace: '{$1|param}'}]); }); }); @@ -70,8 +70,12 @@ describe('config', () => { it('should throw an Error if the config is invalid', () => { const invalidConfig = { - callToImportRegex: '(asd', - callToImportReplace: 'bar', + callToImport: [ + { + regex: '(asd', + replace: 'bar', + } + ], implicitParams: {}, }; diff --git a/test/fixtures/config-json/.soycriticrc.json b/test/fixtures/config-json/.soycriticrc.json index bd7e31b..3e729f2 100644 --- a/test/fixtures/config-json/.soycriticrc.json +++ b/test/fixtures/config-json/.soycriticrc.json @@ -1,4 +1,8 @@ { - "callToImportRegex": "json", - "callToImportReplace": "{$1|param}" + "callToImport": [ + { + "regex": "json", + "replace": "{$1|param}" + } + ] } diff --git a/test/fixtures/config/.soycriticrc b/test/fixtures/config/.soycriticrc index 399fd9d..d0d5e2f 100644 --- a/test/fixtures/config/.soycriticrc +++ b/test/fixtures/config/.soycriticrc @@ -1,4 +1,8 @@ { - "callToImportRegex": "(\\S+)", - "callToImportReplace": "{$1|param}" + "callToImport": [ + { + "regex": "(\\S+)", + "replace": "{$1|param}" + } + ] } diff --git a/test/fixtures/invalid-config/.soycriticrc b/test/fixtures/invalid-config/.soycriticrc index bac036a..86ed256 100644 --- a/test/fixtures/invalid-config/.soycriticrc +++ b/test/fixtures/invalid-config/.soycriticrc @@ -1,4 +1,8 @@ { - "callToImportRegex": "(\\S+", - "callToImportReplace": "{$1|param}" + "callToImport": [ + { + "regex": "(\\S+", + "replace": "{$1|param}" + } + ] } From 6f972b909a24cf55eb020c9d5c174a4d88a6cf5b Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Fri, 22 Dec 2017 23:49:39 +0100 Subject: [PATCH 03/12] Add conversion from deprecated callToImport config API to new one --- src/config.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 8492a10..c6a1dc7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,3 +1,4 @@ +import * as chalk from 'chalk'; import * as fs from 'fs'; import * as path from 'path'; import * as process from 'process'; @@ -52,6 +53,22 @@ export function validateConfig(config: Config): Config { return config; } +export function convertConfig(config: any): Config { + if (config.callToImportRegex && config.callToImportReplace) { + config.callToImport = [ + { + regex: config.callToImportRegex, + replace: config.callToImportReplace + } + ]; + + console.log(chalk.yellow('CONFIG API HAS CHANGED, PLEASE UPDATE\n')); + console.log('\tYour callToImport configuration is outdated, update it to new API.\n'); + } + + return config; +} + export function readConfig(): Config { const filePath = getConfigFilePath(); let config = {}; @@ -61,7 +78,9 @@ export function readConfig(): Config { config = JSON.parse(buffer.toString('utf8')); } - + + config = convertConfig(config); + return validateConfig({...DEFAULT_CONFIG, ...config}); } From 52517c899c77fd55f299aacf33fda8aa3f836dc2 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Fri, 22 Dec 2017 23:55:32 +0100 Subject: [PATCH 04/12] Add tests for conversion from deprecated callToImport API to new one --- src/__tests__/config.ts | 9 +++++++++ test/fixtures/deprecated-config/.soycriticrc | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 test/fixtures/deprecated-config/.soycriticrc diff --git a/src/__tests__/config.ts b/src/__tests__/config.ts index 5696048..61fbfbc 100644 --- a/src/__tests__/config.ts +++ b/src/__tests__/config.ts @@ -53,6 +53,15 @@ describe('config', () => { expect(config.callToImport).toEqual([{regex: 'json', replace: '{$1|param}'}]); }); + + it('should return a converted configuration specified in a file if is found in the old way', () => { + process.chdir('./test/fixtures/deprecated-config'); + + const config = Config.readConfig(); + + expect(config.callToImport).toEqual([{regex: '(\\S+)', replace: '{$1|param}'}]); + }); + }); describe('isRegex', () => { diff --git a/test/fixtures/deprecated-config/.soycriticrc b/test/fixtures/deprecated-config/.soycriticrc new file mode 100644 index 0000000..ac42791 --- /dev/null +++ b/test/fixtures/deprecated-config/.soycriticrc @@ -0,0 +1,4 @@ +{ + "callToImportRegex": "(\\S+)", + "callToImportReplace": "{$1|param}" +} \ No newline at end of file From fb43df7576fe2f4f544ffe2e9a67140aeffc7267 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Fri, 22 Dec 2017 23:58:03 +0100 Subject: [PATCH 05/12] Update repository url in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4e8a830..8f81a6e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "engines": { "node": ">=6.4.0" }, - "repository": "https://github.com/mthadley/metal-soy-critic", + "repository": "https://github.com/metal/metal-soy-critic", "main": "./lib/index.js", "files": [ "lib" From 0b1249e2cd93f367d890c3835edcdec320e21077 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sat, 23 Dec 2017 00:26:45 +0100 Subject: [PATCH 06/12] Update README --- README.md | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1b27c3f..c500aa9 100644 --- a/README.md +++ b/README.md @@ -30,37 +30,42 @@ By default, `mcritic` will recursively search the current and parent folders for ```json { - "callToImportRegex": "(\\S+)", - "callToImportReplace": "{$1|param}" + "callToImport": [ + { + "regex": "(\\S+)", + "replace": "{$1|param}" + } + ] } ``` Here are the currently supported **settings**: -### `callToImportRegex` +### `callToImport` -This property is used to provide matches for `callToImportReplace`. This should be a standard javascript regex that contains capture groups to be referenced in `callToImportReplace`. +This property is used to provide a list of replacement configurations. Each list item must contain two properties: -|Type|Default| -|----|-------| -|string|`"(.*)"`| +- `regex` + + This property is used to provide matches for `replace`. This should be a standard javascript regex that contains capture groups to be referenced in `replace`. + +- `replace` -### `callToImportReplace` + This property uses match groups defined in `regex` to translate a component name in a soy template to its corresponding import name when validating their import. -This property uses match groups defined in `callToImportRegex` to translate a component name in a soy template to its corresponding import name when validating their import. + When referencing match groups from `regex`, interpolation should be in the form of `{$n}`, where `n` is the match group number. An example would be `"{$1}.js"`. -When referencing match groups from `callToImportRegex`, interpolation should be in the form of `{$n}`, where `n` is the match group number. An example would be `"{$1}.js"`. + Interpolations can also contain named string transformations delimited by a `|`. This transformation corresponds to the functions provided by [`change-case`](https://www.npmjs.com/package/change-case). -Interpolations can also contain named string transformations delimited by a `|`. This transformation corresponds to the functions provided by [`change-case`](https://www.npmjs.com/package/change-case). + Examples: + * `"{$1|lower|snake}.js"` + * `"{$2}-{$1}"` + * `"{$1|dot}.js"` -Examples: -* `"{$1|lower|snake}.js"` -* `"{$2}-{$1}"` -* `"{$1|dot}.js"` |Type|Default| |----|-------| -|string|`"{$1}"`| +|array|`"[{"regex": "(.*)", "replace": "{$1}"}]"`| ### `implicitParams` From 86d161677a4f876a217df324f0856d7a78a59562 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sat, 23 Dec 2017 00:35:43 +0100 Subject: [PATCH 07/12] SF --- src/__tests__/config.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/__tests__/config.ts b/src/__tests__/config.ts index 61fbfbc..e56ec93 100644 --- a/src/__tests__/config.ts +++ b/src/__tests__/config.ts @@ -61,7 +61,6 @@ describe('config', () => { expect(config.callToImport).toEqual([{regex: '(\\S+)', replace: '{$1|param}'}]); }); - }); describe('isRegex', () => { @@ -83,7 +82,7 @@ describe('config', () => { { regex: '(asd', replace: 'bar', - } + }, ], implicitParams: {}, }; From 55014004e263741d40cb47283c87a9629d00015b Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sat, 23 Dec 2017 00:41:52 +0100 Subject: [PATCH 08/12] Update travis config and some scripts --- .travis.yml | 15 ++++++++++----- package.json | 7 ++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e6e4b8..4f25546 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,12 @@ +before_install: + - nvm install 8 + +install: + - npm install + language: node_js -node_js: - - "node" - - "6" -script: - - npm test + +script: + - npm run compile - npm run lint + - npm run jest \ No newline at end of file diff --git a/package.json b/package.json index 8f81a6e..8f69346 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,11 @@ "lib" ], "scripts": { - "lint": "tslint src/**/*.ts", - "test": "npm run compile && jest", "compile": "tsc", - "prepublish": "npm run compile" + "jest": "jest", + "lint": "tslint src/**/*.ts", + "prepublish": "npm run compile", + "test": "npm run compile && jest" }, "jest": { "moduleFileExtensions": [ From 9979393447b9f3b60997e331c69da17310c90a86 Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sat, 23 Dec 2017 02:05:48 +0100 Subject: [PATCH 09/12] Import specifiers to add support for named exports --- src/validate-call-imports.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/validate-call-imports.ts b/src/validate-call-imports.ts index 8b47f68..0b8521c 100644 --- a/src/validate-call-imports.ts +++ b/src/validate-call-imports.ts @@ -25,8 +25,12 @@ function getImportPaths(ast: T.Node): Array { jsTraverse(ast, { ImportDeclaration(path) { importPaths.push(path.node.source.value); + }, + ImportSpecifier(path) { + importPaths.push(path.node.imported.name); } }); + return importPaths; } From f81d9c301f81d389ad1cf9ddcf08e3d3b4f5872e Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sat, 23 Dec 2017 02:10:54 +0100 Subject: [PATCH 10/12] Add test for support for named exports --- test/fixtures/CaseImport.js | 1 + test/fixtures/CaseImport.soy | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/test/fixtures/CaseImport.js b/test/fixtures/CaseImport.js index 0e434c9..7f8db61 100644 --- a/test/fixtures/CaseImport.js +++ b/test/fixtures/CaseImport.js @@ -2,6 +2,7 @@ import Component from 'metal-component'; import Soy from 'metal-soy'; import 'OtherComponent'; +import {OtherSubComponent} from 'OtherComponent'; import templates from './CaseImport.soy'; import {Config} from 'metal-state'; diff --git a/test/fixtures/CaseImport.soy b/test/fixtures/CaseImport.soy index a5452ed..77c968a 100644 --- a/test/fixtures/CaseImport.soy +++ b/test/fixtures/CaseImport.soy @@ -8,4 +8,8 @@ {call OtherComponent.render} {param foo: 'bar' /} {/call} + + {call OtherSubComponent.render} + {param foo: 'bar' /} + {/call} {/template} From cf432e34c8640a3a5156296640456606baaacdee Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sun, 24 Dec 2017 02:38:41 +0100 Subject: [PATCH 11/12] Use interface instead alias --- src/config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index c6a1dc7..a4bb535 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,9 +8,9 @@ const CONFIG_FILE_NAMES = [ '.soycriticrc.json', ]; -type CallToImportConfig = { - regex: string; - replace: string; +export interface CallToImportConfig { + regex: string + replace: string } export interface ImplicitParamsMap { From a3389847ae24324cbaf264fd5ba1b2ba38c09cda Mon Sep 17 00:00:00 2001 From: Carlos Lancha Date: Sun, 24 Dec 2017 02:46:25 +0100 Subject: [PATCH 12/12] Use for of instead for --- src/config.ts | 12 +++++------- src/validate-call-imports.ts | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/config.ts b/src/config.ts index a4bb535..6e55669 100644 --- a/src/config.ts +++ b/src/config.ts @@ -32,15 +32,13 @@ export function validateConfig(config: Config): Config { throw new Error('callToImport is not a valid config array.'); } - for (let i=0; i < config.callToImport.length; i++) { - let callToImportItem = config.callToImport[i]; - - if (!isRegex(callToImportItem.regex)) { - throw new Error(`callToImport.regex "${callToImportItem.regex}" is not a valid RegExp.`); + for (const item of config.callToImport) { + if (!isRegex(item.regex)) { + throw new Error(`callToImport.regex "${item.regex}" is not a valid RegExp.`); } - if (!isRegex(callToImportItem.replace)) { - throw new Error(`callToImport.replace "${callToImportItem.replace}" is not a valid replace string.`); + if (!isRegex(item.replace)) { + throw new Error(`callToImport.replace "${item.replace}" is not a valid replace string.`); } } diff --git a/src/validate-call-imports.ts b/src/validate-call-imports.ts index 0b8521c..aa3b2bf 100644 --- a/src/validate-call-imports.ts +++ b/src/validate-call-imports.ts @@ -40,8 +40,8 @@ export default function valdiateCallImports(soyContext: SoyContext, jsContext: J const missingImports = getExternalSoyCalls(soyContext) .filter(name => { - for (let i=0; i < config.callToImport.length; i++) { - let transformedName = transform(name, config.callToImport[i].regex, config.callToImport[i].replace); + for (const item of config.callToImport) { + let transformedName = transform(name, item.regex, item.replace); if (importNames.find(importName => importName.includes(transformedName))) { return false;