From c1b94d5cfce0da007cfeaa7ef3791ee9d5cf9df1 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 11 Jul 2023 17:23:36 +1000 Subject: [PATCH 01/24] chore: change components path --- src/controllers/make.js | 6 ++++-- src/core/config.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/controllers/make.js b/src/controllers/make.js index 3a4bd70..1824a6c 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -2,10 +2,12 @@ const {Controller} = require('../core/controller'); class MakeController extends Controller { async run() { - const prefix = this.config.subject === 'block' ? 'b' : 'p', + const + prefix = this.config.subject === 'block' ? 'b' : 'p', name = this.resolveName(this.config.name, prefix); - const source = this.vfs.resolve(__dirname, '../templates/component'), + const + source = this.vfs.resolve(__dirname, '../templates/component'), destination = this.vfs.resolve(this.config.path, name); await this.vfs.ensureDir(destination); diff --git a/src/core/config.js b/src/core/config.js index 74d85d0..7cea436 100644 --- a/src/core/config.js +++ b/src/core/config.js @@ -38,7 +38,7 @@ class Config { return './src/pages'; case 'block': - return './src/base'; + return './src/components'; default: return './'; From 0d21d793cff151d47c9571808f82c6ede82d29c1 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Thu, 13 Jul 2023 22:25:19 +1000 Subject: [PATCH 02/24] feat:vfs has been extended --- src/core/vfs.js | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/core/vfs.js b/src/core/vfs.js index 92fb268..c0ef307 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -177,6 +177,91 @@ class VirtualFileSystem { getFilesByGlobPattern(pattern) { return glob.sync(pattern); } + + /** + * Finds target name in directory recursive and returns path of first match + * + * @param {string} source + * @param {string} target + * @returns {string | undefined} + */ + findInDir(source, target) { + const + sourcePath = this.resolve(source); + + if (!this.isDirectory(sourcePath)) { + return sourcePath.split(path.sep).at(-1) === target ? sourcePath : undefined; + } + + const + stack = this.readdir(sourcePath); + + while (stack.length > 0) { + const + cur = stack.pop(), + curPath = this.resolve(sourcePath, cur); + + if (cur.split(path.sep).at(-1) === target) { + return curPath; + } + + if (this.isDirectory(curPath)) { + stack.push(...this.readdir(curPath).map((chunk) => `${cur}${path.sep}${chunk}`)); + } + } + + return undefined; + } + + /** + * Copy directory recursive + * + * @param {string} source + * @param {string} destination + * @param {string} [dataHandler] + * + * @returns {Promise} + */ + copyDir(source, destination, dataHandler = undefined) { + this.#copyDir(source, destination, dataHandler, []); + } + + /** + * Copy directory recursive + * + * @param {string} source + * @param {string} destination + * @param {string} [dataWriteHandler] + * @param {string} [pathStack] + * + * @returns {Promise} + */ + async #copyDir(source, destination, dataWriteHandler = undefined, pathStack = []) { + const + curPath = this.resolve(source, ...pathStack), + isDirectory = this.isDirectory(curPath); + + if (!isDirectory) { + const + fileData = this.readFile(curPath); + + await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); + + this.writeFile( + this.resolve(destination, ...pathStack), + dataWriteHandler(fileData) + ); + + return; + } + + const + dir = this.readdir(curPath); + + for (const file of dir) { + this.#copyDir(source, destination, dataWriteHandler, [...pathStack, file]); + } + } } exports.VirtualFileSystem = VirtualFileSystem; From c173cf0acd0549bc6137d31027101159355b6e69 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Thu, 13 Jul 2023 23:52:12 +1000 Subject: [PATCH 03/24] feat: update make-test function --- bin/cli.js | 11 +- src/application.js | 8 +- src/controllers/make-test.js | 208 +++++------------- src/core/interface.ts | 2 +- src/templates/test/block/mock-data.ts | 11 + src/templates/test/block/unit/main.ts | 31 +++ src/templates/test/component/simple/index.js | 48 ---- .../test/component/with-runners/index.js | 18 -- .../component/with-runners/runners/runner.js | 41 ---- src/templates/test/module/simple/index.js | 35 --- .../test/module/with-runners/index.js | 18 -- .../module/with-runners/runners/runner.js | 28 --- src/templates/test/page/mock-data.ts | 11 + src/templates/test/page/project/main.ts | 7 + 14 files changed, 124 insertions(+), 353 deletions(-) create mode 100644 src/templates/test/block/mock-data.ts create mode 100644 src/templates/test/block/unit/main.ts delete mode 100644 src/templates/test/component/simple/index.js delete mode 100644 src/templates/test/component/with-runners/index.js delete mode 100644 src/templates/test/component/with-runners/runners/runner.js delete mode 100644 src/templates/test/module/simple/index.js delete mode 100644 src/templates/test/module/with-runners/index.js delete mode 100644 src/templates/test/module/with-runners/runners/runner.js create mode 100644 src/templates/test/page/mock-data.ts create mode 100644 src/templates/test/page/project/main.ts diff --git a/bin/cli.js b/bin/cli.js index 2612184..21c5418 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -13,15 +13,16 @@ const {Application} = require('../src/application'); const options = yargs .command( - 'make-test [runners..]', + 'make-test ', 'Make test for module or component', (yargs) => { yargs - .positional('path', { - demandOption: true, - type: 'string' + .positional('subject', { + type: 'string', + choices: ['page', 'block'] }) - .positional('runners', { + .positional('target', { + demandOption: true, type: 'string' }); } diff --git a/src/application.js b/src/application.js index 7c90194..7a798ce 100644 --- a/src/application.js +++ b/src/application.js @@ -29,18 +29,18 @@ class Application { async run() { try { - const {command, subject} = this.config; + const + {commandNative: command, subject} = this.config; this.log.info(`Command:${command} ${subject}`); - const controller = - this.getControllerInstance( + const controller = this.getControllerInstance( `${ucfirst(camelize(`${command}-${subject}`))}Controller` ) || this.getControllerInstance(`${ucfirst(camelize(command))}Controller`); if (controller == null) { - throw new Error(`Unknown controller: ${controllerName}`); + throw new Error('Unknown controller'); } await controller.run(); diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index 1367289..6b57522 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -11,14 +11,7 @@ class MakeTestController extends Controller { */ ast; - /** - * Default name of component for module testing - * @type {string} - */ - defaultComponentName = 'b-dummy'; - async run() { - this.updateCases(this.config.runners); this.updateDemoPageDeps(); const source = this.vfs.resolve( @@ -26,154 +19,53 @@ class MakeTestController extends Controller { '..', 'templates', 'test', - this.component === this.moduleOrComponentName ? 'component' : 'module', - this.config.runners.length === 0 ? 'simple' : 'with-runners' + this.config.subject ); - const destination = this.vfs.resolve(this.config.path, 'test'); - - await this.copyTestFolder(source, destination); - } + let + destination = this.vfs.resolve(this.config.target); - /** - * Name of component tests being generated for - * @returns {string} - */ - get component() { - const dirName = this.config.path.split(path.sep).pop(); + if (destination.split(path.sep).length < 0) { + const + chunk = this.config.subject === 'page' ? 'pages' : 'components'; - if (/^b-/.test(dirName)) { - return dirName; + destination = this.vfs.findInDir(this.vfs.resolve('src', chunk), this.config.target); } - return this.defaultComponentName; - } - - /** - * Name of component or module for generating tests - * @returns {string} - */ - get moduleOrComponentName() { - if (this.component !== this.defaultComponentName) { - return this.component; - } + this.vfs.ensureDir(destination, 'test'); + destination = this.vfs.resolve(destination, 'test'); - return this.config.path.split(path.sep).pop(); + await this.copyTestFolder(source, destination); } /** * Copies test folder from source to destination with replacing component/module names * - * @param source - * @param destination + * @param {string} source + * @param {string} destination * * @returns {Promise} */ - async copyTestFolder(source, destination) { - await this.vfs.ensureDir(destination); - - const defName = - this.moduleOrComponentName === this.component ? 'b-name' : 'name'; - - const indexFileSource = this.vfs.resolve(source, 'index.js'), - indexFileDestination = this.vfs.resolve(destination, 'index.js'), - indexFileData = this.vfs.readFile(indexFileSource); - - this.vfs.writeFile( - indexFileDestination, - this.replaceNames(indexFileData, this.moduleOrComponentName, defName) + copyTestFolder(source, destination) { + this.vfs.ensureDir(destination); + + const + prefix = this.config.subject === 'page' ? 'p-' : 'b-', + name = destination.split(path.sep).at(-2).replace(RegExp(prefix), ''); + + const + sourcePath = this.vfs.resolve(source), + destinationPath = this.vfs.resolve(destination); + + this.vfs.copyDir( + sourcePath, + destinationPath, + (data) => this.replaceNames( + data, + [`${prefix}name`, `${prefix}${name}`], + ['r-name', name] + ) ); - - this.log.msg(`New file: ${indexFileDestination}`); - - const {runners} = this.config; - - if (runners.length === 0) { - return; - } - - const runnersSource = this.vfs.resolve(source, 'runners', 'runner.js'), - runnersDestination = this.vfs.resolve(destination, 'runners'), - runnerData = this.vfs.readFile(runnersSource); - - await this.vfs.ensureDir(runnersDestination); - - runners.forEach((runner) => { - const runnerFileDestination = this.vfs.resolve( - runnersDestination, - `${runner}.js` - ); - - this.vfs.writeFile( - runnerFileDestination, - this.replaceNames( - runnerData, - this.moduleOrComponentName, - defName, - runner - ) - ); - - this.log.msg(`New file: ${runnerFileDestination}`); - }); - } - - /** - * Updates `cases.js` by adding new cases for generated tests - * @param {string[]} runners - */ - updateCases(runners) { - const sourcePath = this.vfs.resolve('tests/cases.js'); - - if (!this.vfs.exists(sourcePath)) { - this.log.error( - `File ${sourcePath} does not exist.\nCreate it and write a basic structure of it in order to generate cases.` - ); - - return; - } - - const source = this.ast.createSourceFile(sourcePath); - - const commentString = `// ${this.moduleOrComponentName}`, - testEntryPath = this.vfs.pathByRoot( - this.vfs.resolve(this.config.path, 'test') - ); - - const caseStrings = []; - - if (runners.length === 0) { - caseStrings.push( - `\n\t'--test-entry ${this.vfs.removeTrailingSep(testEntryPath)}'` - ); - } else { - runners.forEach((runner) => { - caseStrings.push( - `\n\t'--test-entry ${this.vfs.removeTrailingSep( - testEntryPath - )} --runner ${runner}'` - ); - }); - } - - const casesNodeObject = this.ast.findASTNodeObject( - source, - (node) => ts.SyntaxKind[node.kind] === 'ArrayLiteralExpression' - ), - cases = casesNodeObject.elements, - insertPosition = cases.end; - - const sourceFile = this.vfs.readFile(sourcePath); - - const newFile = `${sourceFile.slice( - 0, - insertPosition - )},\n\n\t${commentString}${caseStrings.join(',')}${sourceFile.slice( - insertPosition - )}`; - - this.vfs.writeFile(sourcePath, newFile); - this.log.msg(`Update file: ${sourcePath}`); } /** @@ -251,29 +143,35 @@ class MakeTestController extends Controller { } /** - * Replaces all occurrences of `defName` with `newName` with different typings + * Replaces all occurrences of `defName` and `clearName` with `newName` and `clearNewName` with different typings * * @param {string} content - * @param {string} newName - * @param {string} defName - * @param {string | undefined} runner + * @param {[string, string]} defNameOptions + * @param {[string, string]} clearNameOptions * * @returns {string} */ - replaceNames(content, newName, defName = 'b-name', runner = undefined) { - const result = content - .replace(RegExp(defName, 'g'), newName) - .replace(RegExp(camelize(defName), 'g'), camelize(newName)) + replaceNames( + content, + [defName, newName], + [clearName, newClearName] + ) { + console.log('def', defName, newName); + console.log('clear', clearName, newClearName); + + return content + .replace( + RegExp(`${defName}|${clearName}`, 'g'), + (target) => target === defName ? newName : newClearName + ) + .replace( + RegExp(`${camelize(defName)}|${camelize(clearName)}`, 'g'), + (target) => target === camelize(defName) ? camelize(newName) : camelize(newClearName) + ) .replace( - RegExp(ucfirst(camelize(defName)), 'g'), - ucfirst(camelize(newName)) + RegExp(`${ucfirst(camelize(defName))}|${ucfirst(camelize(clearName))}`, 'g'), + (target) => target === ucfirst(camelize(defName)) ? ucfirst(camelize(newName)) : ucfirst(camelize(newClearName)) ); - - if (runner != null) { - return result.replace(/runner/g, runner); - } - - return result; } /** @override */ diff --git a/src/core/interface.ts b/src/core/interface.ts index 6fbb7de..74cd023 100644 --- a/src/core/interface.ts +++ b/src/core/interface.ts @@ -11,5 +11,5 @@ interface IConfig { reporter: 'json' | 'raw' | 'silent'; template: 'default' | 'mono' | 'functional'; extend: 'default' | 'i-block' | 'i-data' | 'i-dynamic-page' | 'i-static-page'; - runners?: string[]; + target?: string; } diff --git a/src/templates/test/block/mock-data.ts b/src/templates/test/block/mock-data.ts new file mode 100644 index 0000000..e9c906c --- /dev/null +++ b/src/templates/test/block/mock-data.ts @@ -0,0 +1,11 @@ +b-name + +bName + +BName + +r-name + +rName + +RName \ No newline at end of file diff --git a/src/templates/test/block/unit/main.ts b/src/templates/test/block/unit/main.ts new file mode 100644 index 0000000..d527547 --- /dev/null +++ b/src/templates/test/block/unit/main.ts @@ -0,0 +1,31 @@ +import type { JSHandle } from 'playwright'; + +import test from 'tests/config/unit/test'; +import Component from 'tests/helpers/component'; + +test.describe('', () => { + const scheme = [ + { + attrs: { + id: 'b-name-component' + } + } + ]; + + let + node: JSHandle, + component: JSHandle; + + test.beforeEach(async ({demoPage, page}) => { + await demoPage.goto(); + await Component.createComponent(page, 'b-name', scheme); + }); + + test('should be rendered', async ({page}) => { + node = await page.waitForSelector('#b-name-component'); + component = await node.evaluateHandle((ctx) => ctx['component']['componentName']); + + test.expect(node).toBeTruthy(); + await test.expect(component.jsonValue()).resolves.toBe('b-name'); + }); +}); diff --git a/src/templates/test/component/simple/index.js b/src/templates/test/component/simple/index.js deleted file mode 100644 index 205055f..0000000 --- a/src/templates/test/component/simple/index.js +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'); - -/** - * Tests for b-name - * - * @param {Playwright.Page} page - * @param {!Object} params - * - * @returns {!Promise} - */ -module.exports = async (page, params) => { - await h.utils.setup(page, params.context); - - describe('b-name', () => { - let - bNameComponent, - bNameNode; - - const scheme = [ - { - attrs: { - id: 'b-name-component' - } - } - ]; - - beforeEach(async () => { - await page.evaluate((scheme) => { - globalThis.removeCreatedComponents(); - globalThis.renderComponents('b-name', scheme); - }, scheme); - - bNameComponent = await h.component.getComponentById( - page, - 'b-name-component' - ); - - bNameNode = await page.$('#b-name-component'); - }); - - it('works', () => { - expect(bNameComponent).toBeTruthy(); - expect(bNameNode).toBeTruthy(); - }); - }); -}; diff --git a/src/templates/test/component/with-runners/index.js b/src/templates/test/component/with-runners/index.js deleted file mode 100644 index 29f4522..0000000 --- a/src/templates/test/component/with-runners/index.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'), - u = include('tests/utils'), - test = u.getCurrentTest(); - -/** - * Starts b-name tests - * - * @param {Playwright.Page} page - * @param {!Object} params - * - * @returns {!Promise} - */ -module.exports = async (page, params) => { - await h.utils.setup(page, params.context); - await test(page, params); -}; diff --git a/src/templates/test/component/with-runners/runners/runner.js b/src/templates/test/component/with-runners/runners/runner.js deleted file mode 100644 index 67d87df..0000000 --- a/src/templates/test/component/with-runners/runners/runner.js +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'); - -/** - * @param {Playwright.Page} page - */ -module.exports = (page) => { - describe('b-name runner', () => { - let - bNameComponent, - bNameNode; - - const scheme = [ - { - attrs: { - id: 'b-name-component' - } - } - ]; - - beforeEach(async () => { - await page.evaluate((scheme) => { - globalThis.removeCreatedComponents(); - globalThis.renderComponents('b-name', scheme); - }, scheme); - - bNameComponent = await h.component.getComponentById( - page, - 'b-name-component' - ); - - bNameNode = await page.$('#b-name-component'); - }); - - it('works', () => { - expect(bNameComponent).toBeTruthy(); - expect(bNameNode).toBeTruthy(); - }); - }); -}; diff --git a/src/templates/test/module/simple/index.js b/src/templates/test/module/simple/index.js deleted file mode 100644 index 80a6e6b..0000000 --- a/src/templates/test/module/simple/index.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'); - -/** - * Tests for name - * - * @param {Playwright.Page} page - * @param {!Object} params - * - * @returns {!Promise} - */ -module.exports = async (page, params) => { - await h.utils.setup(page, params.context); - - describe('name', () => { - let - bDummyComponent, - bDummyNode; - - beforeAll(async () => { - bDummyComponent = await h.component.getComponentById( - page, - 'dummy-component' - ); - - bDummyNode = await h.dom.waitForEl(page, '#dummy-component'); - }); - - it('works', () => { - expect(bDummyComponent).toBeTruthy(); - expect(bDummyNode).toBeTruthy(); - }); - }); -}; diff --git a/src/templates/test/module/with-runners/index.js b/src/templates/test/module/with-runners/index.js deleted file mode 100644 index 024ea81..0000000 --- a/src/templates/test/module/with-runners/index.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'), - u = include('tests/utils'), - test = u.getCurrentTest(); - -/** - * Starts name tests - * - * @param {Playwright.Page} page - * @param {!Object} params - * - * @returns {!Promise} - */ -module.exports = async (page, params) => { - await h.utils.setup(page, params.context); - await test(page, params); -}; diff --git a/src/templates/test/module/with-runners/runners/runner.js b/src/templates/test/module/with-runners/runners/runner.js deleted file mode 100644 index 2b18aa0..0000000 --- a/src/templates/test/module/with-runners/runners/runner.js +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-check - -const h = include('tests/helpers'); - -/** - * @param {Playwright.Page} page - */ -module.exports = (page) => { - describe('name runner', () => { - let - bDummyComponent, - bDummyNode; - - beforeAll(async () => { - bDummyComponent = await h.component.getComponentById( - page, - 'b-dummy-component' - ); - - bDummyNode = await h.dom.waitForEl(page, '#b-dummy-component'); - }); - - it('works', () => { - expect(bDummyComponent).toBeTruthy(); - expect(bDummyNode).toBeTruthy(); - }); - }); -}; diff --git a/src/templates/test/page/mock-data.ts b/src/templates/test/page/mock-data.ts new file mode 100644 index 0000000..156c1c5 --- /dev/null +++ b/src/templates/test/page/mock-data.ts @@ -0,0 +1,11 @@ +p-name + +pName + +PName + +r-name + +rName + +RName \ No newline at end of file diff --git a/src/templates/test/page/project/main.ts b/src/templates/test/page/project/main.ts new file mode 100644 index 0000000..fdde9b0 --- /dev/null +++ b/src/templates/test/page/project/main.ts @@ -0,0 +1,7 @@ +import test from 'tests/config/project/test'; + +test.describe('', () => { + test('should be rendered', async ({RName, page}) => { + await test.expect(page.locator('.p-name')).toBeVisible(); + }); +}); From d7b4fd197dc567dcbe7540ff884f77170d1950c1 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 14 Jul 2023 00:03:57 +1000 Subject: [PATCH 04/24] chore: fix pathes in tests --- tests/cli.test.js | 6 +-- tests/command.test.js | 54 +++++++-------------- tests/extend.test.js | 6 +-- tests/path.test.js | 14 +++--- tests/template.test.js | 104 ++++++++++++++++++++++------------------- 5 files changed, 86 insertions(+), 98 deletions(-) diff --git a/tests/cli.test.js b/tests/cli.test.js index 07a388e..9f4a57a 100644 --- a/tests/cli.test.js +++ b/tests/cli.test.js @@ -46,7 +46,7 @@ describe('Cli test', () => { }); app.run().then(() => { - expect(app.vfs.exists('./src/base/b-point/b-point.ss')).is.true; + expect(app.vfs.exists('./src/components/b-point/b-point.ss')).is.true; exec( 'node', @@ -61,8 +61,8 @@ describe('Cli test', () => { throw error; } - expect(app.vfs.exists('./src/base/b-point/b-point.ss')).is.false; - expect(app.vfs.exists('./src/base/b-time/b-time.ss')).is.true; + expect(app.vfs.exists('./src/components/b-point/b-point.ss')).is.false; + expect(app.vfs.exists('./src/components/b-time/b-time.ss')).is.true; done(); } diff --git a/tests/command.test.js b/tests/command.test.js index 3adb4e1..3090951 100644 --- a/tests/command.test.js +++ b/tests/command.test.js @@ -12,7 +12,7 @@ describe('Exec command', () => { await app.run(); - expect(app.vfs.exists('./src/base/b-test/b-test.ss')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; }); }); @@ -26,9 +26,9 @@ describe('Exec command', () => { await app.run(); - expect(app.vfs.exists('./src/base/b-test/b-test.ss')).is.true; - expect(app.vfs.exists('./src/base/b-test/CHANGELOG.md')).is.true; - expect(app.vfs.exists('./src/base/b-test/README.md')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; + expect(app.vfs.exists('./src/components/b-test/CHANGELOG.md')).is.true; + expect(app.vfs.exists('./src/components/b-test/README.md')).is.true; const app2 = getApplication({ command: 'rename', @@ -38,15 +38,15 @@ describe('Exec command', () => { await app2.run(); - expect(app2.vfs.exists('./src/base/b-test/b-test.ss')).is.false; - expect(app2.vfs.exists('./src/base/b-plot/b-plot.ss')).is.true; - expect(app2.vfs.exists('./src/base/b-plot/CHANGELOG.md')).is.true; - expect(app2.vfs.exists('./src/base/b-plot/README.md')).is.true; - expect(app2.vfs.readFile('./src/base/b-plot/b-plot.ts')).contains( + expect(app2.vfs.exists('./src/components/b-test/b-test.ss')).is.false; + expect(app2.vfs.exists('./src/components/b-plot/b-plot.ss')).is.true; + expect(app2.vfs.exists('./src/components/b-plot/CHANGELOG.md')).is.true; + expect(app2.vfs.exists('./src/components/b-plot/README.md')).is.true; + expect(app2.vfs.readFile('./src/components/b-plot/b-plot.ts')).contains( 'bPlot' ); - expect(app2.vfs.readFile('./src/base/b-plot/b-plot.styl')).contains( + expect(app2.vfs.readFile('./src/components/b-plot/b-plot.styl')).contains( 'b-plot' ); }); @@ -61,7 +61,7 @@ describe('Exec command', () => { await app.run(); - expect(app.vfs.readFile('./src/base/b-test/b-test.ts')).contains( + expect(app.vfs.readFile('./src/components/b-test/b-test.ts')).contains( 'extends iData' ); @@ -73,44 +73,24 @@ describe('Exec command', () => { }); await app2.run(); - expect(app2.vfs.readFile('./src/base/b-plot/b-plot.ts')).contains( + expect(app2.vfs.readFile('./src/components/b-plot/b-plot.ts')).contains( 'extends iData' ); }); }); describe('Make test', () => { - it('should create test without runners', async () => { + it('should create test without path', async () => { const app = getApplication({ - path: 'src/base/b-slider', command: 'make-test', - runners: [] - }); - - await app.run(); - - expect(app.vfs.exists('./src/base/b-slider/test/index.js')).is.true; - expect(app.vfs.exists('./src/base/b-slider/test/runners')).is.false; - }); - - it('should create test with runners', async () => { - const app = getApplication({ - path: 'src/base/b-slider', - command: 'make-test', - runners: ['analytics', 'events', 'render'] + subject: 'block', + target: 'b-slider' }); await app.run(); - expect(app.vfs.exists('./src/base/b-slider/test/index.js')).is.true; - expect(app.vfs.exists('./src/base/b-slider/test/runners/analytics.js')).is - .true; - - expect(app.vfs.exists('./src/base/b-slider/test/runners/events.js')).is - .true; - - expect(app.vfs.exists('./src/base/b-slider/test/runners/render.js')).is - .true; + expect(app.vfs.exists('./src/components/b-slider/test/mock-data.ts')).is.true; + expect(app.vfs.exists('./src/components/b-slider/test/unit/main.ts')).is.false; }); }); }); diff --git a/tests/extend.test.js b/tests/extend.test.js index be8e3d3..3fbaa77 100644 --- a/tests/extend.test.js +++ b/tests/extend.test.js @@ -13,12 +13,12 @@ describe('Change extend option', () => { await app.run(); - expect(app.vfs.exists('./src/base/b-test/b-test.ss')).is.true; - expect(app.vfs.readFile('./src/base/b-test/b-test.ts')).contains( + expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; + expect(app.vfs.readFile('./src/components/b-test/b-test.ts')).contains( 'i-data/i-data' ); - expect(app.vfs.readFile('./src/base/b-test/b-test.ts')).contains( + expect(app.vfs.readFile('./src/components/b-test/b-test.ts')).contains( 'extends iData' ); }); diff --git a/tests/path.test.js b/tests/path.test.js index daa05ce..3913d14 100644 --- a/tests/path.test.js +++ b/tests/path.test.js @@ -7,12 +7,12 @@ describe('Change path option', () => { command: 'make', subject: 'block', name: 'test', - path: './src/base/test/best/pop/' + path: './src/components/test/best/pop/' }); await app.run(); - expect(app.vfs.exists('./src/base/test/best/pop/b-test/b-test.ss')).is.true; + expect(app.vfs.exists('./src/components/test/best/pop/b-test/b-test.ss')).is.true; }); it('should change relative path inside .md files', async () => { @@ -20,17 +20,17 @@ describe('Change path option', () => { command: 'make', subject: 'block', name: 'test', - path: './src/base/test/best/pop/' + path: './src/components/test/best/pop/' }); await app.run(); expect( - app.vfs.readFile('./src/base/test/best/pop/b-test/b-test.ts') - ).contains('[[include:base/test/best/pop/b-test/README.md]]'); + app.vfs.readFile('./src/components/test/best/pop/b-test/b-test.ts') + ).contains('[[include:components/test/best/pop/b-test/README.md]]'); expect( - app.vfs.readFile('./src/base/test/best/pop/b-test/README.md') - ).contains('# base/test/best/pop/b-test'); + app.vfs.readFile('./src/components/test/best/pop/b-test/README.md') + ).contains('# components/test/best/pop/b-test'); }); }); diff --git a/tests/template.test.js b/tests/template.test.js index 05c32d3..555b77f 100644 --- a/tests/template.test.js +++ b/tests/template.test.js @@ -14,10 +14,10 @@ describe('Change template option', () => { await app.run(); - expect(app.vfs.exists('./src/base/b-test/b-test.ss')).is.true; - expect(app.vfs.exists('./src/base/b-test/b-test.styl')).is.true; - expect(app.vfs.exists('./src/base/b-test/b-test.ts')).is.false; - expect(app.vfs.readFile('./src/base/b-test/b-test.ss')).contains( + expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.styl')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.ts')).is.false; + expect(app.vfs.readFile('./src/components/b-test/b-test.ss')).contains( '- @@ignore' ); }); @@ -34,100 +34,108 @@ describe('Change template option', () => { await app.run(); - expect(app.vfs.exists('./src/base/b-test/b-test.ss')).is.true; - expect(app.vfs.exists('./src/base/b-test/b-test.styl')).is.true; - expect(app.vfs.exists('./src/base/b-test/b-test.ts')).is.true; - expect(app.vfs.readFile('./src/base/b-test/b-test.ts')).contains( + expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.styl')).is.true; + expect(app.vfs.exists('./src/components/b-test/b-test.ts')).is.true; + expect(app.vfs.readFile('./src/components/b-test/b-test.ts')).contains( '@component({functional: true})' ); }); }); }); - describe('Make test', () => { - describe('for component', () => { + describe('`make-test`', () => { + describe('`block`', () => { it('should provide name of component', async () => { const app = getApplication({ - path: 'src/base/b-slider', command: 'make-test', - runners: [] + subject: 'block', + target: 'src/components/b-test' }); await app.run(); const testFileText = app.vfs.readFile( - './src/base/b-slider/test/index.js' + './src/components/b-test/test/unit/main.ts' ); - expect(testFileText).contains('b-slider'); - expect(testFileText).contains('bSlider'); - expect(testFileText).not.contains('bDummy'); - expect(testFileText).not.contains('b-dummy'); + expect(testFileText).contains('b-test'); + expect(testFileText).contains('bTest'); expect(testFileText).not.contains('bName'); expect(testFileText).not.contains('b-name'); }); - it('should provide name of component in runner', async () => { + it('should make test for block by name', async () => { const app = getApplication({ - path: 'src/base/b-slider', + command: 'make', + subject: 'block', + name: 'b-foo' + }); + + const testApp = getApplication({ command: 'make-test', - runners: ['events'] + subject: 'block', + target: 'b-foo' }); await app.run(); + await testApp.run(); - const runnerFileText = app.vfs.readFile( - './src/base/b-slider/test/runners/events.js' + const testFileText = app.vfs.readFile( + './src/components/b-foo/test/unit/main.ts' ); - expect(runnerFileText).contains('b-slider'); - expect(runnerFileText).contains('bSlider'); - expect(runnerFileText).contains('events'); - expect(runnerFileText).not.contains('runner'); - expect(runnerFileText).not.contains('bDummy'); - expect(runnerFileText).not.contains('b-dummy'); - expect(runnerFileText).not.contains('bName'); - expect(runnerFileText).not.contains('b-name'); + expect(testFileText).contains('b-foo'); + expect(testFileText).contains('bFoo'); + expect(testFileText).not.contains('bName'); + expect(testFileText).not.contains('b-name'); }); }); - describe('for module', () => { - it('should provide name of module', async () => { + describe('`page`', () => { + it('should provide name of page', async () => { const app = getApplication({ - path: 'src/base/some-module', command: 'make-test', - runners: [] + subject: 'page', + target: 'src/pages/p-foo' }); await app.run(); const testFileText = app.vfs.readFile( - './src/base/some-module/test/index.js' + './src/pages/p-foo/test/project/main.ts' ); - expect(testFileText).contains('some-module'); - expect(testFileText).contains('bDummy'); - expect(testFileText).not.contains('name'); + expect(testFileText).contains('p-foo'); + expect(testFileText).contains('Foo'); + expect(testFileText).not.contains('p-name'); + expect(testFileText).not.contains('RName'); }); - it('should provide name of module in runner', async () => { + it('should make test for block by name', async () => { const app = getApplication({ - path: 'src/base/some-module', + command: 'make', + subject: 'page', + name: 'p-foo' + }); + + const testApp = getApplication({ command: 'make-test', - runners: ['events'] + subject: 'page', + target: 'p-foo' }); await app.run(); + await testApp.run(); - const runnerFileText = app.vfs.readFile( - './src/base/some-module/test/runners/events.js' + const testFileText = app.vfs.readFile( + './src/pages/p-foo/test/project/main.ts' ); - expect(runnerFileText).contains('some-module'); - expect(runnerFileText).contains('bDummy'); - expect(runnerFileText).contains('b-dummy'); - expect(runnerFileText).not.contains('runner'); - expect(runnerFileText).not.contains('name'); + expect(testFileText).contains('b-foo'); + expect(testFileText).contains('bFoo'); + expect(testFileText).not.contains('bName'); + expect(testFileText).not.contains('b-name'); }); }); }); From 34d46b786d22ed459f9ab5dc718b394b60295eae Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 14 Jul 2023 18:41:56 +1000 Subject: [PATCH 05/24] test: refactoring --- src/controllers/make-test.js | 13 +-- src/core/vfs.js | 12 +- src/templates/test/block/unit/main.ts | 4 +- tests/staff/helpers.js | 10 +- tests/template.test.js | 151 ++++++++++++-------------- 5 files changed, 94 insertions(+), 96 deletions(-) diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index 6b57522..ed2346e 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -25,14 +25,14 @@ class MakeTestController extends Controller { let destination = this.vfs.resolve(this.config.target); - if (destination.split(path.sep).length < 0) { + if (this.config.target.split(path.sep).length === 1) { const chunk = this.config.subject === 'page' ? 'pages' : 'components'; destination = this.vfs.findInDir(this.vfs.resolve('src', chunk), this.config.target); } - this.vfs.ensureDir(destination, 'test'); + await this.vfs.ensureDir(destination, 'test'); destination = this.vfs.resolve(destination, 'test'); await this.copyTestFolder(source, destination); @@ -46,8 +46,8 @@ class MakeTestController extends Controller { * * @returns {Promise} */ - copyTestFolder(source, destination) { - this.vfs.ensureDir(destination); + async copyTestFolder(source, destination) { + await this.vfs.ensureDir(destination); const prefix = this.config.subject === 'page' ? 'p-' : 'b-', @@ -57,7 +57,7 @@ class MakeTestController extends Controller { sourcePath = this.vfs.resolve(source), destinationPath = this.vfs.resolve(destination); - this.vfs.copyDir( + await this.vfs.copyDir( sourcePath, destinationPath, (data) => this.replaceNames( @@ -156,9 +156,6 @@ class MakeTestController extends Controller { [defName, newName], [clearName, newClearName] ) { - console.log('def', defName, newName); - console.log('clear', clearName, newClearName); - return content .replace( RegExp(`${defName}|${clearName}`, 'g'), diff --git a/src/core/vfs.js b/src/core/vfs.js index c0ef307..5c9ded0 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -218,12 +218,12 @@ class VirtualFileSystem { * * @param {string} source * @param {string} destination - * @param {string} [dataHandler] + * @param {Function} [dataWriteHandler] * * @returns {Promise} */ - copyDir(source, destination, dataHandler = undefined) { - this.#copyDir(source, destination, dataHandler, []); + copyDir(source, destination, dataWriteHandler = undefined) { + return this.#copyDir(source, destination, dataWriteHandler, []); } /** @@ -231,8 +231,8 @@ class VirtualFileSystem { * * @param {string} source * @param {string} destination - * @param {string} [dataWriteHandler] - * @param {string} [pathStack] + * @param {Function} [dataWriteHandler] + * @param {string[]} [pathStack] * * @returns {Promise} */ @@ -259,7 +259,7 @@ class VirtualFileSystem { dir = this.readdir(curPath); for (const file of dir) { - this.#copyDir(source, destination, dataWriteHandler, [...pathStack, file]); + await this.#copyDir(source, destination, dataWriteHandler, [...pathStack, file]); } } } diff --git a/src/templates/test/block/unit/main.ts b/src/templates/test/block/unit/main.ts index d527547..ef82642 100644 --- a/src/templates/test/block/unit/main.ts +++ b/src/templates/test/block/unit/main.ts @@ -3,6 +3,8 @@ import type { JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; import Component from 'tests/helpers/component'; +import type { RName } from 'src/components/b-name/b-name.ts'; + test.describe('', () => { const scheme = [ { @@ -14,7 +16,7 @@ test.describe('', () => { let node: JSHandle, - component: JSHandle; + component: JSHandle; test.beforeEach(async ({demoPage, page}) => { await demoPage.goto(); diff --git a/tests/staff/helpers.js b/tests/staff/helpers.js index b5a4d27..ede12b4 100644 --- a/tests/staff/helpers.js +++ b/tests/staff/helpers.js @@ -1,4 +1,5 @@ const {Application} = require('../../src/application'); +const {VirtualFileSystem} = require('../../src/core/vfs'); /** * @param {IConfig} options @@ -12,4 +13,11 @@ function getApplication(options) { }); } -module.exports.getApplication = getApplication; +/** + * @returns {VirtualFileSystem} + */ +function getVFS() { + return new VirtualFileSystem(); +} + +module.exports = {getApplication, getVFS}; diff --git a/tests/template.test.js b/tests/template.test.js index 555b77f..2ab6404 100644 --- a/tests/template.test.js +++ b/tests/template.test.js @@ -1,43 +1,56 @@ const {expect} = require('chai'); -const {getApplication} = require('./staff/helpers'); +const {getApplication, getVFS} = require('./staff/helpers'); describe('Change template option', () => { - describe('Make', () => { - describe('mono', () => { - it('should create mono component', async () => { + const + commonVfs = getVFS(); + + describe('`make`', () => { + const + componentName = 'b-test', + componentDir = commonVfs.resolve('src', 'components', componentName); + + after(() => { + if (commonVfs.exists(componentDir)) { + commonVfs.rmDir(componentDir); + } + }); + + describe('`mono`', () => { + it('should create `mono` component', async () => { const app = getApplication({ command: 'make', subject: 'block', - name: 'test', + name: componentName, template: 'mono' }); await app.run(); - expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; - expect(app.vfs.exists('./src/components/b-test/b-test.styl')).is.true; - expect(app.vfs.exists('./src/components/b-test/b-test.ts')).is.false; - expect(app.vfs.readFile('./src/components/b-test/b-test.ss')).contains( + expect(app.vfs.exists(`${componentDir}/${componentName}.ss`)).is.true; + expect(app.vfs.exists(`${componentDir}/${componentName}.styl`)).is.true; + expect(app.vfs.exists(`${componentDir}/${componentName}.ts`)).is.false; + expect(app.vfs.readFile(`${componentDir}/${componentName}.ss`)).contains( '- @@ignore' ); }); }); - describe('functional', () => { - it('should create functional component', async () => { + describe('`functional`', () => { + it('should create `functional` component', async () => { const app = getApplication({ command: 'make', subject: 'block', - name: 'test', + name: componentName, template: 'functional' }); await app.run(); - expect(app.vfs.exists('./src/components/b-test/b-test.ss')).is.true; - expect(app.vfs.exists('./src/components/b-test/b-test.styl')).is.true; - expect(app.vfs.exists('./src/components/b-test/b-test.ts')).is.true; - expect(app.vfs.readFile('./src/components/b-test/b-test.ts')).contains( + expect(app.vfs.exists(`${componentDir}/${componentName}.ss`)).is.true; + expect(app.vfs.exists(`${componentDir}/${componentName}.styl`)).is.true; + expect(app.vfs.exists(`${componentDir}/${componentName}.ts`)).is.true; + expect(app.vfs.readFile(`${componentDir}/${componentName}.ts`)).contains( '@component({functional: true})' ); }); @@ -45,97 +58,75 @@ describe('Change template option', () => { }); describe('`make-test`', () => { - describe('`block`', () => { - it('should provide name of component', async () => { - const app = getApplication({ - command: 'make-test', - subject: 'block', - target: 'src/components/b-test' - }); + const + componentDir = 'src/components/b-test', + pageDir = 'src/pages/p-test'; - await app.run(); + let + testFileText; - const testFileText = app.vfs.readFile( - './src/components/b-test/test/unit/main.ts' - ); + after(() => { + if (commonVfs.exists(componentDir)) { + commonVfs.rmDir(componentDir); + } - expect(testFileText).contains('b-test'); - expect(testFileText).contains('bTest'); - expect(testFileText).not.contains('bName'); - expect(testFileText).not.contains('b-name'); - }); + if (commonVfs.exists(pageDir)) { + commonVfs.rmDir(pageDir); + } + }); - it('should make test for block by name', async () => { + describe('`block`', () => { + beforeEach(async () => { const app = getApplication({ - command: 'make', - subject: 'block', - name: 'b-foo' - }); - - const testApp = getApplication({ command: 'make-test', subject: 'block', - target: 'b-foo' + target: componentDir }); await app.run(); - await testApp.run(); + testFileText = app.vfs.readFile(`${componentDir}/test/unit/main.ts`); + }); - const testFileText = app.vfs.readFile( - './src/components/b-foo/test/unit/main.ts' - ); + it('should provide name of component', () => { + expect(testFileText).contains('b-test'); + expect(testFileText).contains('Test'); + }); - expect(testFileText).contains('b-foo'); - expect(testFileText).contains('bFoo'); - expect(testFileText).not.contains('bName'); + it('should`t contain any replacers', () => { expect(testFileText).not.contains('b-name'); + expect(testFileText).not.contains('bName'); + expect(testFileText).not.contains('BName'); + expect(testFileText).not.contains('r-name'); + expect(testFileText).not.contains('rName'); + expect(testFileText).not.contains('RName'); }); }); describe('`page`', () => { - it('should provide name of page', async () => { + beforeEach(async () => { const app = getApplication({ command: 'make-test', subject: 'page', - target: 'src/pages/p-foo' + target: pageDir }); await app.run(); - const testFileText = app.vfs.readFile( - './src/pages/p-foo/test/project/main.ts' - ); - - expect(testFileText).contains('p-foo'); - expect(testFileText).contains('Foo'); - expect(testFileText).not.contains('p-name'); - expect(testFileText).not.contains('RName'); + testFileText = app.vfs.readFile(`${pageDir}/test/project/main.ts`); }); - it('should make test for block by name', async () => { - const app = getApplication({ - command: 'make', - subject: 'page', - name: 'p-foo' - }); - - const testApp = getApplication({ - command: 'make-test', - subject: 'page', - target: 'p-foo' - }); - - await app.run(); - await testApp.run(); - - const testFileText = app.vfs.readFile( - './src/pages/p-foo/test/project/main.ts' - ); + it('should provide name of page', () => { + expect(testFileText).contains('p-test'); + expect(testFileText).contains('Test'); + }); - expect(testFileText).contains('b-foo'); - expect(testFileText).contains('bFoo'); - expect(testFileText).not.contains('bName'); - expect(testFileText).not.contains('b-name'); + it('should`t contain any replacers', () => { + expect(testFileText).not.contains('p-name'); + expect(testFileText).not.contains('pName'); + expect(testFileText).not.contains('PName'); + expect(testFileText).not.contains('r-name'); + expect(testFileText).not.contains('rName'); + expect(testFileText).not.contains('RName'); }); }); }); From 81bbe4c1aac3eb1f081491f5b87bc14264ab1965 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 14 Jul 2023 22:40:44 +1000 Subject: [PATCH 06/24] refactor: copyDir function and make module refactoring --- src/controllers/make-test.js | 24 +++++++++++-------- src/controllers/make.js | 18 ++++++++++---- src/core/controller.js | 46 ++++-------------------------------- src/core/interface.ts | 6 +++++ src/core/vfs.js | 35 +++++++++++++++++---------- 5 files changed, 60 insertions(+), 69 deletions(-) diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index ed2346e..0fcb800 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -11,6 +11,7 @@ class MakeTestController extends Controller { */ ast; + /** @override */ async run() { this.updateDemoPageDeps(); @@ -27,9 +28,10 @@ class MakeTestController extends Controller { if (this.config.target.split(path.sep).length === 1) { const - chunk = this.config.subject === 'page' ? 'pages' : 'components'; + chunk = this.config.subject === 'page' ? 'pages' : 'components', + name = this.resolveName(this.config.target, this.prefix); - destination = this.vfs.findInDir(this.vfs.resolve('src', chunk), this.config.target); + destination = this.vfs.findInDir(this.vfs.resolve('src', chunk), name); } await this.vfs.ensureDir(destination, 'test'); @@ -39,7 +41,7 @@ class MakeTestController extends Controller { } /** - * Copies test folder from source to destination with replacing component/module names + * Copies tests files from source to destination and fills templates * * @param {string} source * @param {string} destination @@ -50,8 +52,7 @@ class MakeTestController extends Controller { await this.vfs.ensureDir(destination); const - prefix = this.config.subject === 'page' ? 'p-' : 'b-', - name = destination.split(path.sep).at(-2).replace(RegExp(prefix), ''); + clearName = destination.split(path.sep).at(-2).replace(RegExp(`${this.prefix}-`), ''); const sourcePath = this.vfs.resolve(source), @@ -60,11 +61,14 @@ class MakeTestController extends Controller { await this.vfs.copyDir( sourcePath, destinationPath, - (data) => this.replaceNames( - data, - [`${prefix}name`, `${prefix}${name}`], - ['r-name', name] - ) + { + onDataWrite: (data) => this.replaceNames( + data, + [`${this.prefix}-name`, `${this.prefix}-${clearName}`], + ['r-name', clearName] + ), + afterEachCopy: (path) => this.log.msg(`Create: ${path}`) + } ); } diff --git a/src/controllers/make.js b/src/controllers/make.js index 1824a6c..f6c3286 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -1,17 +1,27 @@ const {Controller} = require('../core/controller'); class MakeController extends Controller { + /** @override */ async run() { const - prefix = this.config.subject === 'block' ? 'b' : 'p', - name = this.resolveName(this.config.name, prefix); + name = this.resolveName(this.config.name, this.prefix); const - source = this.vfs.resolve(__dirname, '../templates/component'), + baseSource = this.vfs.resolve(__dirname, '../templates/component'), + templateSource = this.vfs.resolve(baseSource, this.config.template), destination = this.vfs.resolve(this.config.path, name); + const options = { + onDataWrite: (data) => this.replaceNames(data, name), + afterEachCopy: (fileName) => this.log.msg(`Create: ${fileName}`) + }; + await this.vfs.ensureDir(destination); - this.copyFolder(source, destination, name); + + await Promise.allSettled([ + this.vfs.copyDir(baseSource, destination, {...options, withFolders: false}), + this.vfs.copyDir(templateSource, destination, options) + ]); } } diff --git a/src/core/controller.js b/src/core/controller.js index d4a5f95..8ede11c 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -19,6 +19,10 @@ class Controller { */ log; + get prefix() { + return this.config.subject === 'page' ? 'p' : 'b'; + } + /** * @param {IConfig} config * @param {VirtualFileSystem} vfs @@ -39,48 +43,6 @@ class Controller { return /^[bp]-/.test(name) ? name : `${prefix}-${name}`; } - /** - * Copy files and directories from source to destination - * - * @param {string} source - * @param {string} destination - * @param {string} name - * @param {boolean} withFolders - * @private - */ - copyFolder(source, destination, name, withFolders = false) { - const files = this.vfs.readdir(source); - - for (const file of files) { - const fileName = this.vfs.resolve(source, file); - - if (this.vfs.isDirectory(fileName)) { - if (withFolders) { - this.log.msg(`Directory:${fileName}`); - this.vfs.ensureDir(this.vfs.resolve(destination, file)); - this.copyFolder( - fileName, - this.vfs.resolve(destination, file), - name, - true - ); - } else if (file === this.config.template) { - this.copyFolder(fileName, destination, name); - } - - continue; - } - - const data = this.vfs.readFile(fileName), - newFile = this.vfs.resolve(destination, this.replaceNames(file, name)); - - if (!this.vfs.exists(newFile) || this.config.override) { - this.log.msg(`File:${newFile}`); - this.vfs.writeFile(newFile, this.replaceNames(data, name)); - } - } - } - /** * Rename all names to target name * diff --git a/src/core/interface.ts b/src/core/interface.ts index 74cd023..3723f22 100644 --- a/src/core/interface.ts +++ b/src/core/interface.ts @@ -13,3 +13,9 @@ interface IConfig { extend: 'default' | 'i-block' | 'i-data' | 'i-dynamic-page' | 'i-static-page'; target?: string; } + +interface CopyDirOptions { + afterEachCopy(destPath: string): unknown; + onDataWrite(data: string): string | object; + withFolders: boolean; +} diff --git a/src/core/vfs.js b/src/core/vfs.js index 5c9ded0..852977b 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -214,43 +214,48 @@ class VirtualFileSystem { } /** - * Copy directory recursive + * Copies files and directories from source to destination * * @param {string} source * @param {string} destination - * @param {Function} [dataWriteHandler] + * @param {CopyDirOptions} [options] * * @returns {Promise} */ - copyDir(source, destination, dataWriteHandler = undefined) { - return this.#copyDir(source, destination, dataWriteHandler, []); + copyDir(source, destination, options) { + return this.#copyDir(source, destination, options); } /** - * Copy directory recursive + * Copies files and directories from source to destination * * @param {string} source * @param {string} destination - * @param {Function} [dataWriteHandler] + * @param {CopyDirOptions} [options] * @param {string[]} [pathStack] * * @returns {Promise} */ - async #copyDir(source, destination, dataWriteHandler = undefined, pathStack = []) { + async #copyDir(source, destination, options = {}, pathStack = []) { + const + {onDataWrite, afterEachCopy, withFolders = true} = options; + const curPath = this.resolve(source, ...pathStack), isDirectory = this.isDirectory(curPath); if (!isDirectory) { const - fileData = this.readFile(curPath); + fileData = this.readFile(curPath), + destPath = this.resolve(destination, ...pathStack); await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); - this.writeFile( - this.resolve(destination, ...pathStack), - dataWriteHandler(fileData) - ); + this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); + + if (typeof afterEachCopy === 'function') { + afterEachCopy(destPath); + } return; } @@ -259,7 +264,11 @@ class VirtualFileSystem { dir = this.readdir(curPath); for (const file of dir) { - await this.#copyDir(source, destination, dataWriteHandler, [...pathStack, file]); + if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { + continue; + } + + await this.#copyDir(source, destination, options, [...pathStack, file]); } } } From 6c002cc2ca926ebecfb058aac308788f9160a186 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 14 Jul 2023 23:18:20 +1000 Subject: [PATCH 07/24] docs: README.md refactoring --- README.md | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3ef21ae..6fa5d25 100644 --- a/README.md +++ b/README.md @@ -45,13 +45,13 @@ It will remove workspace folder, clear package-lock.json and components-lock.jso v4fire make block hello-world ``` -It will create `src/base/b-hello-world` component. +It will create `src/components/b-hello-world` component. ```bash v4fire make block b-hello-world ``` -Also, it will create `src/base/b-hello-world`. +Also, it will create `src/components/b-hello-world`. ```bash v4fire make page hello-world @@ -84,7 +84,7 @@ v4fire make block hello-world --template functional --extend i-data v4fire rename hello-world app-loader ``` -It will rename `src/base/b-hello-world` to `src/base/b-app-loader`. +It will rename `src/components/b-hello-world` to `src/components/b-app-loader`. ### Resolve changelog @@ -98,18 +98,28 @@ WARNING: Conflicts within the same record may not be resolved correctly! ### Make test ```bash -v4fire make-test src/base/b-slider +v4fire make-test block hello-world ``` +It will create tests for `src/components/b-hello-world` component if it exists. -You can generate test files for both component and module. -The tool also will take care of updating [demo-page](https://github.com/V4Fire/Client/blob/master/src/pages/p-v4-components-demo/index.js) -dependencies and adding new test cases to [test cases file](https://github.com/V4Fire/Client/blob/master/tests/cases.js). +```bash +v4fire make-test page slider +``` +It will create tests for `src/pages/p-slider` page if it exists. + +```bash +v4fire make-test block src/foo/bar/componentName +``` +It will create tests for component in `src/foo/bar/componentName` folder -For both component and module the tool generates `test/index.js` [file](src/templates/test/module/simple/index.js) -that performs basic test setup and executes simple test. +```bash +v4fire make-test page src/foo/bar/componentName +``` +It will create tests for page in `src/foo/bar/componentName` folder + +The tool also will take care of updating [demo-page](https://github.com/V4Fire/Client/blob/master/src/pages/p-v4-components-demo/index.js) -In case of _module_ test, the tool relies on `b-dummy` [component](https://github.com/V4Fire/Client/tree/master/src/base/b-dummy) -designed specifically for testing purposes. +The tool generates a `test` folder for both components and pages. The [template for component](src/templates/test/block) and [template for page](src/templates/test/block) contain the basic test setup and executes simple test. #### Runners @@ -118,7 +128,7 @@ and all test code locates in the `test/index.js` file. So if you'd like to have you can specify them just after the path to module or component being tested. ```bash -v4fire make-test src/base/b-slider analytics render events +v4fire make-test src/components/b-slider analytics render events ``` For each specified runner the tool will create `test/runner/runner-name` file. [Here is the example](src/templates/test/module/with-runners/runners/runner.js) From a0dbc2305fb5fbedac9363a9d61ef14427417c90 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 14 Jul 2023 23:24:54 +1000 Subject: [PATCH 08/24] fix: remove some test data --- src/templates/test/block/mock-data.ts | 11 ----------- src/templates/test/page/mock-data.ts | 11 ----------- 2 files changed, 22 deletions(-) diff --git a/src/templates/test/block/mock-data.ts b/src/templates/test/block/mock-data.ts index e9c906c..e69de29 100644 --- a/src/templates/test/block/mock-data.ts +++ b/src/templates/test/block/mock-data.ts @@ -1,11 +0,0 @@ -b-name - -bName - -BName - -r-name - -rName - -RName \ No newline at end of file diff --git a/src/templates/test/page/mock-data.ts b/src/templates/test/page/mock-data.ts index 156c1c5..e69de29 100644 --- a/src/templates/test/page/mock-data.ts +++ b/src/templates/test/page/mock-data.ts @@ -1,11 +0,0 @@ -p-name - -pName - -PName - -r-name - -rName - -RName \ No newline at end of file From 99469ee8de151abec679abc6105d8ca5453f82da Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Mon, 17 Jul 2023 15:16:18 +1000 Subject: [PATCH 09/24] docs: some fixes in documentation and better comments --- README.md | 10 +++++----- bin/cli.js | 14 +++++--------- src/controllers/make-test.js | 2 +- src/core/controller.js | 5 +++++ src/core/interface.ts | 6 +++--- src/core/vfs.js | 6 +++--- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 6fa5d25..daacfec 100644 --- a/README.md +++ b/README.md @@ -100,26 +100,26 @@ WARNING: Conflicts within the same record may not be resolved correctly! ```bash v4fire make-test block hello-world ``` -It will create tests for `src/components/b-hello-world` component if it exists. +It will generate simple tests for the `src/components/**/b-hello-world` component, if it exists. ```bash v4fire make-test page slider ``` -It will create tests for `src/pages/p-slider` page if it exists. +It will generate simple tests for the `src/pages/**/p-slider` page, if it exists. ```bash v4fire make-test block src/foo/bar/componentName ``` -It will create tests for component in `src/foo/bar/componentName` folder +It will generate simple `component` tests in the `src/foo/bar/componentName` folder ```bash v4fire make-test page src/foo/bar/componentName ``` -It will create tests for page in `src/foo/bar/componentName` folder +It will generate simple `page` tests in the `src/foo/bar/componentName` folder The tool also will take care of updating [demo-page](https://github.com/V4Fire/Client/blob/master/src/pages/p-v4-components-demo/index.js) -The tool generates a `test` folder for both components and pages. The [template for component](src/templates/test/block) and [template for page](src/templates/test/block) contain the basic test setup and executes simple test. +The tool generates a `test` folder for both components and pages. The [template for component](src/templates/test/block) and the [template for page](src/templates/test/block) contain the basic test setup and can execute these simple tests. #### Runners diff --git a/bin/cli.js b/bin/cli.js index 21c5418..c0e3c5f 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -14,7 +14,7 @@ const {Application} = require('../src/application'); const options = yargs .command( 'make-test ', - 'Make test for module or component', + 'Make test for page or component', (yargs) => { yargs .positional('subject', { @@ -149,16 +149,12 @@ const options = yargs .example('v4fire make block point', 'Make i-block b-point') .example('v4fire make page card', 'Make i-dynamic-page p-card') .example( - 'v4fire make-test src/core/view-history', - 'Make tests for view-history module' + 'v4fire make-test block slider', + 'Make tests for src/components/**/b-slider component, if it exists' ) .example( - 'v4fire make-test src/base/b-slider', - 'Make tests for b-slider component' - ) - .example( - 'v4fire make-test src/base/b-slider analytics render events', - 'Make tests for b-slider component with different runners' + 'v4fire make-test page src/[path]/p-test', + 'Make tests for src/[path]/p-test page' ) .example( 'v4fire resolve-changelog', diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index 0fcb800..5b98d85 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -41,7 +41,7 @@ class MakeTestController extends Controller { } /** - * Copies tests files from source to destination and fills templates + * Copies tests files from the source to the destination and fills templates * * @param {string} source * @param {string} destination diff --git a/src/core/controller.js b/src/core/controller.js index 8ede11c..98b9cfc 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -19,6 +19,11 @@ class Controller { */ log; + /** + * Prefix for a current subject + * + * @returns {string} + */ get prefix() { return this.config.subject === 'page' ? 'p' : 'b'; } diff --git a/src/core/interface.ts b/src/core/interface.ts index 3723f22..e8b1557 100644 --- a/src/core/interface.ts +++ b/src/core/interface.ts @@ -15,7 +15,7 @@ interface IConfig { } interface CopyDirOptions { - afterEachCopy(destPath: string): unknown; - onDataWrite(data: string): string | object; - withFolders: boolean; + afterEachCopy?(destPath: string): unknown; + onDataWrite?(data: string): string | object; + withFolders?: boolean; } diff --git a/src/core/vfs.js b/src/core/vfs.js index 852977b..569e755 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -179,7 +179,7 @@ class VirtualFileSystem { } /** - * Finds target name in directory recursive and returns path of first match + * Recursively searches for the target name in a directory and returns the path of the first match found * * @param {string} source * @param {string} target @@ -214,7 +214,7 @@ class VirtualFileSystem { } /** - * Copies files and directories from source to destination + * Copies files and directories from the source to the destination * * @param {string} source * @param {string} destination @@ -227,7 +227,7 @@ class VirtualFileSystem { } /** - * Copies files and directories from source to destination + * Copies files and directories from the source to the destination * * @param {string} source * @param {string} destination From 4cdfd59546c6ff6c8f959b061411012d9d824387 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Mon, 24 Jul 2023 12:06:37 +0300 Subject: [PATCH 10/24] refactoring --- bin/cli.js | 4 +- .../app/src/base/b-hello-world/index.js | 4 +- src/templates/component/index.js | 2 +- src/templates/test/block/unit/main.ts | 42 +++++++++---------- src/templates/test/page/project/main.ts | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/bin/cli.js b/bin/cli.js index c0e3c5f..2e1cf22 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -153,8 +153,8 @@ const options = yargs 'Make tests for src/components/**/b-slider component, if it exists' ) .example( - 'v4fire make-test page src/[path]/p-test', - 'Make tests for src/[path]/p-test page' + 'v4fire make-test page src/foo/bar/p-test', + 'Make tests for src/foo/bar/p-test page' ) .example( 'v4fire resolve-changelog', diff --git a/src/templates/app/src/base/b-hello-world/index.js b/src/templates/app/src/base/b-hello-world/index.js index c5d29f1..926efea 100644 --- a/src/templates/app/src/base/b-hello-world/index.js +++ b/src/templates/app/src/base/b-hello-world/index.js @@ -1,2 +1,2 @@ -package('b-hello-world') - .extends('i-block'); +package("b-hello-world") + .extends("i-block"); diff --git a/src/templates/component/index.js b/src/templates/component/index.js index 85af400..4af45a7 100644 --- a/src/templates/component/index.js +++ b/src/templates/component/index.js @@ -1,2 +1,2 @@ package('b-name') - .extends('i-block'); + .extends('i-block'); diff --git a/src/templates/test/block/unit/main.ts b/src/templates/test/block/unit/main.ts index ef82642..4a6cbc1 100644 --- a/src/templates/test/block/unit/main.ts +++ b/src/templates/test/block/unit/main.ts @@ -3,31 +3,31 @@ import type { JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; import Component from 'tests/helpers/component'; -import type { RName } from 'src/components/b-name/b-name.ts'; +import type RName from 'src/components/b-name/b-name.ts'; test.describe('', () => { - const scheme = [ - { - attrs: { - id: 'b-name-component' - } - } - ]; + const scheme = [ + { + attrs: { + id: 'b-name-component' + } + } + ]; - let - node: JSHandle, - component: JSHandle; + let + node: JSHandle, + component: JSHandle; - test.beforeEach(async ({demoPage, page}) => { - await demoPage.goto(); - await Component.createComponent(page, 'b-name', scheme); - }); + test.beforeEach(async ({ demoPage, page }) => { + await demoPage.goto(); + await Component.createComponent(page, 'b-name', scheme); + }); - test('should be rendered', async ({page}) => { - node = await page.waitForSelector('#b-name-component'); - component = await node.evaluateHandle((ctx) => ctx['component']['componentName']); + test('should be rendered', async ({ page }) => { + const + component = await Component.getComponentByQuery(page, '#b-name-component'), + componentName = await component.getProperty('componentName'); - test.expect(node).toBeTruthy(); - await test.expect(component.jsonValue()).resolves.toBe('b-name'); - }); + await test.expect(componentName.jsonValue()).resolves.toBe('b-name'); + }); }); diff --git a/src/templates/test/page/project/main.ts b/src/templates/test/page/project/main.ts index fdde9b0..044ba0d 100644 --- a/src/templates/test/page/project/main.ts +++ b/src/templates/test/page/project/main.ts @@ -1,7 +1,7 @@ import test from 'tests/config/project/test'; test.describe('', () => { - test('should be rendered', async ({RName, page}) => { + test('should be rendered', async ({ RName, page }) => { await test.expect(page.locator('.p-name')).toBeVisible(); }); }); From f5e201a2ecb233c1a194b910d52791d8995a97fa Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 25 Jul 2023 12:26:57 +0300 Subject: [PATCH 11/24] refactoring: review fixes --- src/controllers/make-test.js | 5 +- src/core/vfs.js | 95 ++++++++++-------------------------- yarn.lock | 41 ++++++++++++---- 3 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index 5b98d85..c6033e4 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -29,9 +29,10 @@ class MakeTestController extends Controller { if (this.config.target.split(path.sep).length === 1) { const chunk = this.config.subject === 'page' ? 'pages' : 'components', - name = this.resolveName(this.config.target, this.prefix); + name = this.resolveName(this.config.target, this.prefix), + globPattern = `${this.vfs.resolve('src', chunk)}/**/${name}`; - destination = this.vfs.findInDir(this.vfs.resolve('src', chunk), name); + destination = this.vfs.getFilesByGlobPattern(globPattern)[0]; } await this.vfs.ensureDir(destination, 'test'); diff --git a/src/core/vfs.js b/src/core/vfs.js index 569e755..bf52ec3 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -178,41 +178,6 @@ class VirtualFileSystem { return glob.sync(pattern); } - /** - * Recursively searches for the target name in a directory and returns the path of the first match found - * - * @param {string} source - * @param {string} target - * @returns {string | undefined} - */ - findInDir(source, target) { - const - sourcePath = this.resolve(source); - - if (!this.isDirectory(sourcePath)) { - return sourcePath.split(path.sep).at(-1) === target ? sourcePath : undefined; - } - - const - stack = this.readdir(sourcePath); - - while (stack.length > 0) { - const - cur = stack.pop(), - curPath = this.resolve(sourcePath, cur); - - if (cur.split(path.sep).at(-1) === target) { - return curPath; - } - - if (this.isDirectory(curPath)) { - stack.push(...this.readdir(curPath).map((chunk) => `${cur}${path.sep}${chunk}`)); - } - } - - return undefined; - } - /** * Copies files and directories from the source to the destination * @@ -223,52 +188,44 @@ class VirtualFileSystem { * @returns {Promise} */ copyDir(source, destination, options) { - return this.#copyDir(source, destination, options); - } + fs.copySync(); - /** - * Copies files and directories from the source to the destination - * - * @param {string} source - * @param {string} destination - * @param {CopyDirOptions} [options] - * @param {string[]} [pathStack] - * - * @returns {Promise} - */ - async #copyDir(source, destination, options = {}, pathStack = []) { - const - {onDataWrite, afterEachCopy, withFolders = true} = options; + return copy(source, destination, options); - const - curPath = this.resolve(source, ...pathStack), - isDirectory = this.isDirectory(curPath); + async function copy(source, destination, options = {}, pathStack = []) { + const + {onDataWrite, afterEachCopy, withFolders = true} = options; - if (!isDirectory) { const - fileData = this.readFile(curPath), - destPath = this.resolve(destination, ...pathStack); + curPath = this.resolve(source, ...pathStack), + isDirectory = this.isDirectory(curPath); + + if (!isDirectory) { + const + fileData = this.readFile(curPath), + destPath = this.resolve(destination, ...pathStack); - await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); + await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); - this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); + this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); - if (typeof afterEachCopy === 'function') { - afterEachCopy(destPath); + if (typeof afterEachCopy === 'function') { + afterEachCopy(destPath); + } + + return; } - return; - } + const + dir = this.readdir(curPath); - const - dir = this.readdir(curPath); + for (const file of dir) { + if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { + continue; + } - for (const file of dir) { - if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { - continue; + await this.copy(source, destination, options, [...pathStack, file]); } - - await this.#copyDir(source, destination, options, [...pathStack, file]); } } } diff --git a/yarn.lock b/yarn.lock index 4dc40e7..7593c4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7887,13 +7887,20 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.14.1, lru-cache@npm:^7.7.1": +"lru-cache@npm:^7.7.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 languageName: node linkType: hard +"lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.0.0 + resolution: "lru-cache@npm:10.0.0" + checksum: 18f101675fe283bc09cda0ef1e3cc83781aeb8373b439f086f758d1d91b28730950db785999cd060d3c825a8571c03073e8c14512b6655af2188d623031baf50 + languageName: node + linkType: hard + "lru-queue@npm:^0.1.0": version: 0.1.0 resolution: "lru-queue@npm:0.1.0" @@ -8131,11 +8138,11 @@ __metadata: linkType: hard "minimatch@npm:^8.0.2": - version: 8.0.3 - resolution: "minimatch@npm:8.0.3" + version: 8.0.4 + resolution: "minimatch@npm:8.0.4" dependencies: brace-expansion: ^2.0.1 - checksum: 8957d8105be6729bf1d3af9c410b2a38ffcf3cd17d4ffaf715b2aa4841490aaa82f1ebff785e71b5b97747199ccc61027db597495941cf46243d9a64382e1560 + checksum: 2e46cffb86bacbc524ad45a6426f338920c529dd13f3a732cc2cf7618988ee1aae88df4ca28983285aca9e0f45222019ac2d14ebd17c1edadd2ee12221ab801a languageName: node linkType: hard @@ -8206,13 +8213,27 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^4.0.0, minipass@npm:^4.0.2, minipass@npm:^4.2.4": +"minipass@npm:^4.0.0": version: 4.2.5 resolution: "minipass@npm:4.2.5" checksum: 4f9c19af23a5d4a9e7156feefc9110634b178a8cff8f8271af16ec5ebf7e221725a97429952c856f5b17b30c2065ebd24c81722d90c93d2122611d75b952b48f languageName: node linkType: hard +"minipass@npm:^4.2.4": + version: 4.2.8 + resolution: "minipass@npm:4.2.8" + checksum: 7f4914d5295a9a30807cae5227a37a926e6d910c03f315930fde52332cf0575dfbc20295318f91f0baf0e6bb11a6f668e30cde8027dea7a11b9d159867a3c830 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": + version: 7.0.2 + resolution: "minipass@npm:7.0.2" + checksum: 46776de732eb7cef2c7404a15fb28c41f5c54a22be50d47b03c605bf21f5c18d61a173c0a20b49a97e7a65f78d887245066410642551e45fffe04e9ac9e325bc + languageName: node + linkType: hard + "minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": version: 2.1.2 resolution: "minizlib@npm:2.1.2" @@ -8996,12 +9017,12 @@ __metadata: linkType: hard "path-scurry@npm:^1.6.1": - version: 1.6.3 - resolution: "path-scurry@npm:1.6.3" + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" dependencies: - lru-cache: ^7.14.1 - minipass: ^4.0.2 - checksum: 814ebd7f8df717e2381dc707ba3a3ddf84d0a4f9d653036c7554cb1fea632d4d78eb17dd5f4c85111b78ba8b8c0a5b59c756645c9d343bdacacda4ba8d1626c2 + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 languageName: node linkType: hard From 145a08a976c28f57b43a4082487729be719e5dc9 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Wed, 26 Jul 2023 17:35:45 +0300 Subject: [PATCH 12/24] handlebars templates --- package.json | 1 + src/core/handlebars.js | 43 +++++++++++++++++++ .../{package.json => package.json.handlebars} | 7 +-- src/templates/component/README.handlebars | 12 ++++++ src/templates/component/README.md | 11 ----- src/templates/component/b-name.styl | 7 --- src/templates/component/default/b-name.ts | 14 ------ .../b-name.ss => default/tpl-ss.handlebars} | 1 + .../component/default/tpl-ts.handlebars | 15 +++++++ src/templates/component/functional/b-name.ts | 14 ------ .../tpl-ss.handlebars} | 1 + .../component/functional/tpl-ts.handlebars | 15 +++++++ src/templates/component/index.handlebars | 3 ++ src/templates/component/index.js | 2 - .../mono/{b-name.ss => tpl-ss.handlebars} | 1 + src/templates/component/tpl-styl.handlebars | 8 ++++ src/templates/test/block/mock-data.ts | 0 src/templates/test/block/tpl.handlebars | 1 + src/templates/test/block/unit/main.ts | 33 -------------- src/templates/test/block/unit/tpl.handlebars | 34 +++++++++++++++ src/templates/test/page/mock-data.ts | 0 src/templates/test/page/project/main.ts | 7 --- .../test/page/project/tpl.handlebars | 7 +++ src/templates/test/page/tpl.handlebars | 1 + yarn.lock | 39 ++++++++++++++++- 25 files changed, 184 insertions(+), 93 deletions(-) create mode 100644 src/core/handlebars.js rename src/templates/app/{package.json => package.json.handlebars} (82%) create mode 100644 src/templates/component/README.handlebars delete mode 100644 src/templates/component/README.md delete mode 100644 src/templates/component/b-name.styl delete mode 100644 src/templates/component/default/b-name.ts rename src/templates/component/{functional/b-name.ss => default/tpl-ss.handlebars} (83%) create mode 100644 src/templates/component/default/tpl-ts.handlebars delete mode 100644 src/templates/component/functional/b-name.ts rename src/templates/component/{default/b-name.ss => functional/tpl-ss.handlebars} (83%) create mode 100644 src/templates/component/functional/tpl-ts.handlebars create mode 100644 src/templates/component/index.handlebars delete mode 100644 src/templates/component/index.js rename src/templates/component/mono/{b-name.ss => tpl-ss.handlebars} (84%) create mode 100644 src/templates/component/tpl-styl.handlebars delete mode 100644 src/templates/test/block/mock-data.ts create mode 100644 src/templates/test/block/tpl.handlebars delete mode 100644 src/templates/test/block/unit/main.ts create mode 100644 src/templates/test/block/unit/tpl.handlebars delete mode 100644 src/templates/test/page/mock-data.ts delete mode 100644 src/templates/test/page/project/main.ts create mode 100644 src/templates/test/page/project/tpl.handlebars create mode 100644 src/templates/test/page/tpl.handlebars diff --git a/package.json b/package.json index 2f89f24..61ec2a0 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "fs-extra": "11.1.1", "git-config-path": "2.0.0", "glob": "9.3.4", + "handlebars": "^4.7.7", "parse-git-config": "3.0.0", "typescript": "4.4.4", "yargs": "17.7.1" diff --git a/src/core/handlebars.js b/src/core/handlebars.js new file mode 100644 index 0000000..9fd147b --- /dev/null +++ b/src/core/handlebars.js @@ -0,0 +1,43 @@ +/* eslint-disable func-names */ +const {camelize, ucfirst} = require('./helpers'); +const Handlebars = require('handlebars'); + +module.exports.getOutputFileInfo = getOutputFileInfo; + +Handlebars.registerHelper('camelize', function (args) { + return Handlebars.SafeString(camelize(args.fn(this))); +}); + +Handlebars.registerHelper('capitalize', function (args) { + return Handlebars.SafeString(ucfirst(camelize(args.fn(this)))); +}); + +function getOutputFileInfo(path) { + const rl = readline.createInterface({ + input: fs.createReadStream(path) + }); + + let + resolve, + reject; + + const res = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + + rl.once('line', (line) => { + try { + const + {name} = /^{{!.*(name=(?[A-Za-z.\-_]+?)[^A-Za-z.].*}}$)/g.exec(line).groups, + {ext} = /^{{!.*(extension|ext=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; + + resolve({name, ext}); + + } catch (error) { + reject(error); + } + }); + + return res; +} diff --git a/src/templates/app/package.json b/src/templates/app/package.json.handlebars similarity index 82% rename from src/templates/app/package.json rename to src/templates/app/package.json.handlebars index ab6fd93..db86339 100644 --- a/src/templates/app/package.json +++ b/src/templates/app/package.json.handlebars @@ -1,7 +1,8 @@ +{{! name=package ext=json }} { - "name": "b-name", + "name": "{{name}}", "version": "1.0.0", - "description": "Description b-name", + "description": "Description {{name}}", "scripts": { "build": "gulp build:tsconfig && webpack --watch --debug false", "start": "node webview.app", @@ -9,7 +10,7 @@ }, "author": "@YourFullName", "keywords": [ - "b-name" + "{{name}}" ], "dependencies": { "@v4fire/client": "^3.0.0-rc.59", diff --git a/src/templates/component/README.handlebars b/src/templates/component/README.handlebars new file mode 100644 index 0000000..cf2c60f --- /dev/null +++ b/src/templates/component/README.handlebars @@ -0,0 +1,12 @@ +{{! name=README ext=md }} +# components/{{name}} + +[Changelog](./CHANGELOG.md) + +About {{#camelize}}{{name}}{{#capitalize}} + +## How to use + +``` +< {{name}} +``` diff --git a/src/templates/component/README.md b/src/templates/component/README.md deleted file mode 100644 index 0cd0ea9..0000000 --- a/src/templates/component/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# base/b-name - -[Changelog](./CHANGELOG.md) - -About bName - -## How to use - -``` -< b-name -``` diff --git a/src/templates/component/b-name.styl b/src/templates/component/b-name.styl deleted file mode 100644 index fe0cd8a..0000000 --- a/src/templates/component/b-name.styl +++ /dev/null @@ -1,7 +0,0 @@ -@import "super/i-block/i-block.styl" - -$p = { - -} - -b-name extends i-block diff --git a/src/templates/component/default/b-name.ts b/src/templates/component/default/b-name.ts deleted file mode 100644 index 5be15e9..0000000 --- a/src/templates/component/default/b-name.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * [[include:base/b-name/README.md]] - * @packageDocumentation - */ - -import iBlock, { component } from 'super/i-block/i-block'; - -export * from 'super/i-block/i-block'; - -/** - * BName - */ -@component() -export default class bName extends iBlock {} diff --git a/src/templates/component/functional/b-name.ss b/src/templates/component/default/tpl-ss.handlebars similarity index 83% rename from src/templates/component/functional/b-name.ss rename to src/templates/component/default/tpl-ss.handlebars index b0beaf4..d082fee 100644 --- a/src/templates/component/functional/b-name.ss +++ b/src/templates/component/default/tpl-ss.handlebars @@ -1,3 +1,4 @@ +{{! name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/default/tpl-ts.handlebars b/src/templates/component/default/tpl-ts.handlebars new file mode 100644 index 0000000..a1d7754 --- /dev/null +++ b/src/templates/component/default/tpl-ts.handlebars @@ -0,0 +1,15 @@ +{{! name=[[name]] ext=ts }} +/** + * [[include:components/{{name}}/README.md]] + * @packageDocumentation + */ + +import iBlock, { component } from 'super/i-block/i-block'; + +export * from 'super/i-block/i-block'; + +/** + * {{#capitalize}}{{name}}{{/capitalize}} + */ +@component() +export default class {{#camelize}}{{name}}{{/camelize}} extends iBlock {} diff --git a/src/templates/component/functional/b-name.ts b/src/templates/component/functional/b-name.ts deleted file mode 100644 index 408f203..0000000 --- a/src/templates/component/functional/b-name.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * [[include:base/b-name/README.md]] - * @packageDocumentation - */ - -import iBlock, { component } from 'super/i-block/i-block'; - -export * from 'super/i-block/i-block'; - -/** - * BName - */ -@component({functional: true}) -export default class bName extends iBlock {} diff --git a/src/templates/component/default/b-name.ss b/src/templates/component/functional/tpl-ss.handlebars similarity index 83% rename from src/templates/component/default/b-name.ss rename to src/templates/component/functional/tpl-ss.handlebars index b0beaf4..d082fee 100644 --- a/src/templates/component/default/b-name.ss +++ b/src/templates/component/functional/tpl-ss.handlebars @@ -1,3 +1,4 @@ +{{! name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/functional/tpl-ts.handlebars b/src/templates/component/functional/tpl-ts.handlebars new file mode 100644 index 0000000..119d78d --- /dev/null +++ b/src/templates/component/functional/tpl-ts.handlebars @@ -0,0 +1,15 @@ +{{! name=[[name]] ext=ts }} +/** + * [[include:components/{{name}}/README.md]] + * @packageDocumentation + */ + +import iBlock, { component } from 'super/i-block/i-block'; + +export * from 'super/i-block/i-block'; + +/** + * {{#capitalize}}{{name}}{{/capitalize}} + */ +@component({functional: true}) +export default class {{#camelize}}{{name}}{{/camelize}} extends iBlock {} diff --git a/src/templates/component/index.handlebars b/src/templates/component/index.handlebars new file mode 100644 index 0000000..1c7345a --- /dev/null +++ b/src/templates/component/index.handlebars @@ -0,0 +1,3 @@ +{{! name=index ext=js }} +package('{{name}}') + .extends('i-block'); diff --git a/src/templates/component/index.js b/src/templates/component/index.js deleted file mode 100644 index 4af45a7..0000000 --- a/src/templates/component/index.js +++ /dev/null @@ -1,2 +0,0 @@ -package('b-name') - .extends('i-block'); diff --git a/src/templates/component/mono/b-name.ss b/src/templates/component/mono/tpl-ss.handlebars similarity index 84% rename from src/templates/component/mono/b-name.ss rename to src/templates/component/mono/tpl-ss.handlebars index 47bfebd..2b3d694 100644 --- a/src/templates/component/mono/b-name.ss +++ b/src/templates/component/mono/tpl-ss.handlebars @@ -1,3 +1,4 @@ +{{! name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/tpl-styl.handlebars b/src/templates/component/tpl-styl.handlebars new file mode 100644 index 0000000..c38b9f1 --- /dev/null +++ b/src/templates/component/tpl-styl.handlebars @@ -0,0 +1,8 @@ +{{! name=[[name]] ext=ss }} +@import "super/i-block/i-block.styl" + +$p = { + +} + +{{name}} extends i-block diff --git a/src/templates/test/block/mock-data.ts b/src/templates/test/block/mock-data.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/templates/test/block/tpl.handlebars b/src/templates/test/block/tpl.handlebars new file mode 100644 index 0000000..74c288f --- /dev/null +++ b/src/templates/test/block/tpl.handlebars @@ -0,0 +1 @@ +{{! name=mock-data ext=ts }} \ No newline at end of file diff --git a/src/templates/test/block/unit/main.ts b/src/templates/test/block/unit/main.ts deleted file mode 100644 index 4a6cbc1..0000000 --- a/src/templates/test/block/unit/main.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { JSHandle } from 'playwright'; - -import test from 'tests/config/unit/test'; -import Component from 'tests/helpers/component'; - -import type RName from 'src/components/b-name/b-name.ts'; - -test.describe('', () => { - const scheme = [ - { - attrs: { - id: 'b-name-component' - } - } - ]; - - let - node: JSHandle, - component: JSHandle; - - test.beforeEach(async ({ demoPage, page }) => { - await demoPage.goto(); - await Component.createComponent(page, 'b-name', scheme); - }); - - test('should be rendered', async ({ page }) => { - const - component = await Component.getComponentByQuery(page, '#b-name-component'), - componentName = await component.getProperty('componentName'); - - await test.expect(componentName.jsonValue()).resolves.toBe('b-name'); - }); -}); diff --git a/src/templates/test/block/unit/tpl.handlebars b/src/templates/test/block/unit/tpl.handlebars new file mode 100644 index 0000000..2a92593 --- /dev/null +++ b/src/templates/test/block/unit/tpl.handlebars @@ -0,0 +1,34 @@ +{{! name=foo; extension=ts; }} +import type { JSHandle } from 'playwright'; + +import test from 'tests/config/unit/test'; +import Component from 'tests/helpers/component'; + +import type {{#camelize}}{{name}}{{/camelize}} from 'src/components/{{name}}/{{name}}.ts'; + +test.describe('<{{name}}>', () => { + const scheme = [ + { + attrs: { + id: '{{name}}-component' + } + } + ]; + + let + node: JSHandle, + component: JSHandle<{{#camelize}}{{name}}{{/camelize}}>; + + test.beforeEach(async ({ demoPage, page }) => { + await demoPage.goto(); + await Component.createComponent(page, '{{name}}', scheme); + }); + + test('should be rendered', async ({ page }) => { + const + component = await Component.getComponentByQuery(page, '#{{name}}-component'), + componentName = await component.getProperty('componentName'); + + await test.expect(componentName.jsonValue()).resolves.toBe('{{name}}'); + }); +}); diff --git a/src/templates/test/page/mock-data.ts b/src/templates/test/page/mock-data.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/templates/test/page/project/main.ts b/src/templates/test/page/project/main.ts deleted file mode 100644 index 044ba0d..0000000 --- a/src/templates/test/page/project/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import test from 'tests/config/project/test'; - -test.describe('', () => { - test('should be rendered', async ({ RName, page }) => { - await test.expect(page.locator('.p-name')).toBeVisible(); - }); -}); diff --git a/src/templates/test/page/project/tpl.handlebars b/src/templates/test/page/project/tpl.handlebars new file mode 100644 index 0000000..fd86d4e --- /dev/null +++ b/src/templates/test/page/project/tpl.handlebars @@ -0,0 +1,7 @@ +import test from 'tests/config/project/test'; + +test.describe('<{{name}}>', () => { + test('should be rendered', async ({ {{#capitalize}}{{name}}{{/capitalize}}, page }) => { + await test.expect(page.locator('.{{name}}')).toBeVisible(); + }); +}); diff --git a/src/templates/test/page/tpl.handlebars b/src/templates/test/page/tpl.handlebars new file mode 100644 index 0000000..74c288f --- /dev/null +++ b/src/templates/test/page/tpl.handlebars @@ -0,0 +1 @@ +{{! name=mock-data ext=ts }} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7593c4c..77ca3f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2433,6 +2433,7 @@ __metadata: fs-extra: 11.1.1 git-config-path: 2.0.0 glob: 9.3.4 + handlebars: ^4.7.7 mocha: 10.2.0 parse-git-config: 3.0.0 typescript: 4.4.4 @@ -6384,6 +6385,24 @@ __metadata: languageName: node linkType: hard +"handlebars@npm:^4.7.7": + version: 4.7.7 + resolution: "handlebars@npm:4.7.7" + dependencies: + minimist: ^1.2.5 + neo-async: ^2.6.0 + source-map: ^0.6.1 + uglify-js: ^3.1.4 + wordwrap: ^1.0.0 + dependenciesMeta: + uglify-js: + optional: true + bin: + handlebars: bin/handlebars + checksum: 1e79a43f5e18d15742977cb987923eab3e2a8f44f2d9d340982bcb69e1735ed049226e534d7c1074eaddaf37e4fb4f471a8adb71cddd5bc8cf3f894241df5cee + languageName: node + linkType: hard + "has-ansi@npm:^2.0.0": version: 2.0.0 resolution: "has-ansi@npm:2.0.0" @@ -8146,7 +8165,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.1.0, minimist@npm:^1.2.0, minimist@npm:^1.2.6": +"minimist@npm:^1.1.0, minimist@npm:^1.2.0, minimist@npm:^1.2.5, minimist@npm:^1.2.6": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -8421,7 +8440,7 @@ __metadata: languageName: node linkType: hard -"neo-async@npm:^2.6.2": +"neo-async@npm:^2.6.0, neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 @@ -10988,6 +11007,15 @@ __metadata: languageName: node linkType: hard +"uglify-js@npm:^3.1.4": + version: 3.17.4 + resolution: "uglify-js@npm:3.17.4" + bin: + uglifyjs: bin/uglifyjs + checksum: 7b3897df38b6fc7d7d9f4dcd658599d81aa2b1fb0d074829dd4e5290f7318dbca1f4af2f45acb833b95b1fe0ed4698662ab61b87e94328eb4c0a0d3435baf924 + languageName: node + linkType: hard + "unbox-primitive@npm:^1.0.2": version: 1.0.2 resolution: "unbox-primitive@npm:1.0.2" @@ -11614,6 +11642,13 @@ __metadata: languageName: node linkType: hard +"wordwrap@npm:^1.0.0": + version: 1.0.0 + resolution: "wordwrap@npm:1.0.0" + checksum: 2a44b2788165d0a3de71fd517d4880a8e20ea3a82c080ce46e294f0b68b69a2e49cff5f99c600e275c698a90d12c5ea32aff06c311f0db2eb3f1201f3e7b2a04 + languageName: node + linkType: hard + "workerpool@npm:6.2.1": version: 6.2.1 resolution: "workerpool@npm:6.2.1" From 4c1ee916a06f9be9d182b3fd6c6a9f754b5286bf Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Mon, 31 Jul 2023 12:31:01 +0300 Subject: [PATCH 13/24] temp --- src/components/b-foo/foo.ts | 14 +++++ src/controllers/index.js | 4 +- src/controllers/make.js | 119 ++++++++++++++++++++++++++++++++---- src/controllers/test.js | 91 +++++++++++++++++++++++++++ src/core/handlebars.js | 4 +- 5 files changed, 219 insertions(+), 13 deletions(-) create mode 100644 src/components/b-foo/foo.ts create mode 100644 src/controllers/test.js diff --git a/src/components/b-foo/foo.ts b/src/components/b-foo/foo.ts new file mode 100644 index 0000000..dc01ea7 --- /dev/null +++ b/src/components/b-foo/foo.ts @@ -0,0 +1,14 @@ +/** + * [[include:components/foo/README.md]] + * @packageDocumentation + */ + +import iBlock, { component } from 'super/i-block/i-block'; + +export * from 'super/i-block/i-block'; + +/** + * + */ +@component() +export default class extends iBlock {} diff --git a/src/controllers/index.js b/src/controllers/index.js index edddedf..b9c9b96 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -5,6 +5,7 @@ const ResolveChangelogController = require('./resolve-changelog'); const CreateWorkspaceController = require('./create-workspace'); const RemoveWorkspaceController = require('./remove-workspace'); const UpGitController = require('./up-yarn-git-dependencies'); +const TestController = require('./test'); module.exports = { MakeController, @@ -13,5 +14,6 @@ module.exports = { ResolveChangelogController, CreateWorkspaceController, UpGitController, - RemoveWorkspaceController + RemoveWorkspaceController, + TestController }; diff --git a/src/controllers/make.js b/src/controllers/make.js index f6c3286..d75d821 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -1,27 +1,124 @@ +require('../core/handlebars'); + +const readline = require('readline'); +const fs = require('fs'); const {Controller} = require('../core/controller'); +const Handlebars = require('handlebars'); +const path = require('path'); class MakeController extends Controller { + resolvedName; + /** @override */ async run() { - const - name = this.resolveName(this.config.name, this.prefix); + this.resolvedName = this.resolveName(this.config.name, this.prefix); const baseSource = this.vfs.resolve(__dirname, '../templates/component'), - templateSource = this.vfs.resolve(baseSource, this.config.template), - destination = this.vfs.resolve(this.config.path, name); + templateFolderSource = this.vfs.resolve(baseSource, this.config.template); + + this.copyDir(templateFolderSource, this.config.path, {name: this.config.name}); + } + + copyDir(source, destination, options) { + const copy = async (source, destination, options = {}, pathStack = []) => { + const + {onDataWrite, withFolders = true} = options; + + const + curPath = this.vfs.resolve(source, ...pathStack), + isDirectory = this.vfs.isDirectory(curPath); + + if (!isDirectory) { + const + destDirPath = this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1)), + fileExt = this.vfs.extname(pathStack.at(-1)); + + await this.vfs.ensureDir(this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); + + if (fileExt.includes('handlebars')) { + let + {name, ext} = await this.getOutputFileInfo(curPath), + p = this.vfs.resolve(destination, ...pathStack); + + console.log(pathStack); + + if (name === '[[name]]' || name == null) { + name = options.name; + const foo = p + .split(path.sep) + .slice(0, p.split(path.sep).length - 1); + + foo.push(`${name}.${ext}`); + p = foo.join(path.sep); + } + + console.log(curPath, p, {name}); + // await this.writeTemplate(curPath, p, {name}); + + return; + } - const options = { - onDataWrite: (data) => this.replaceNames(data, name), - afterEachCopy: (fileName) => this.log.msg(`Create: ${fileName}`) + this.vfs.writeFile( + this.vfs.resolve(destination, ...pathStack), + this.vfs.readFile(curPath) + ); + + return; + } + + const + dir = this.vfs.readdir(curPath); + + for (const file of dir) { + if (!withFolders && this.vfs.isDirectory(this.vfs.resolve(curPath, file))) { + continue; + } + + await copy(source, destination, options, [...pathStack, file]); + } }; + return copy(source, destination, options); + } + + getOutputFileInfo(path) { + const rl = readline.createInterface({ + input: fs.createReadStream(path) + }); + + let + resolve, + reject; + + const res = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + + rl.once('line', (line) => { + try { + const + {name} = /^{{!.*(name=(?[A-Za-z[\].\-_]+?)[^A-Za-z[\].\-_].*}}$)/g.exec(line).groups, + {ext} = /^{{!.*(extension|ext=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; + + resolve({name, ext}); + + } catch (error) { + reject(error); + } + }); + + return res; + } + + async writeTemplate(source, destination, options) { await this.vfs.ensureDir(destination); - await Promise.allSettled([ - this.vfs.copyDir(baseSource, destination, {...options, withFolders: false}), - this.vfs.copyDir(templateSource, destination, options) - ]); + this.vfs.writeFile( + destination, + Handlebars.compile(this.vfs.readFile(source))(options) + ); } } diff --git a/src/controllers/test.js b/src/controllers/test.js new file mode 100644 index 0000000..e37a1d1 --- /dev/null +++ b/src/controllers/test.js @@ -0,0 +1,91 @@ +const fs = require('fs'); +const Handlebars = require('handlebars'); +const {Controller} = require('../core/controller'); +const {getOutputFileInfo} = require('../core/handlebars'); +const path = require('path'); + +class TestController extends Controller { + /** @override */ + async run() { + const + name = this.resolveName(this.config.name, this.prefix); + + const + destination = this.vfs.resolve(this.config.path), + templateSource = path.resolve('src/templates/component/default'); + + // this.copyTemplate(templateSource, destination, name); + } + + async copyTemplate(targetPath, destPath, tempName) { + const + tempExt = this.vfs.extname(targetPath.split(path.sep).at(-1)); + + if (tempExt !== '.handlebars') { + this.vfs.ensureDir(destPath); + fs.copyFileSync(targetPath, destPath); + return; + } + + const + {name, ext} = await getOutputFileInfo(targetPath); + + let + fileName = `${name}.${ext}`; + + if (name === '[[name]]' || name == null) { + fileName = `${tempName}.${ext}`; + } + + console.log(fileName, tempName); + + // const + // dPath = this.vfs.resolve(destPath, fileName), + // raw = this.vfs.readFile(templatePath, 'utf-8'), + // data = Handlebars.template(raw)({name: tempName}); + + // this.vfs.writeFile(dPath, data); + } + + copyDir(source, destination, options) { + return copy(source, destination, options); + + async function copy(source, destination, options = {}, pathStack = []) { + const + {onDataWrite, afterEachCopy, withFolders = true} = options; + + const + curPath = this.resolve(source, ...pathStack), + isDirectory = this.isDirectory(curPath); + + if (!isDirectory) { + const + fileData = this.readFile(curPath), + destPath = this.resolve(destination, ...pathStack); + + await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); + + this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); + + if (typeof afterEachCopy === 'function') { + afterEachCopy(destPath); + } + + return; + } + + const + dir = this.readdir(curPath); + + for (const file of dir) { + if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { + continue; + } + + await this.copy(source, destination, options, [...pathStack, file]); + } + } + } +} + +module.exports = TestController; diff --git a/src/core/handlebars.js b/src/core/handlebars.js index 9fd147b..e91300e 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -1,5 +1,7 @@ /* eslint-disable func-names */ const {camelize, ucfirst} = require('./helpers'); +const readline = require('readline'); +const fs = require('fs'); const Handlebars = require('handlebars'); module.exports.getOutputFileInfo = getOutputFileInfo; @@ -29,7 +31,7 @@ function getOutputFileInfo(path) { rl.once('line', (line) => { try { const - {name} = /^{{!.*(name=(?[A-Za-z.\-_]+?)[^A-Za-z.].*}}$)/g.exec(line).groups, + {name} = /^{{!.*(name=(?[[\]A-Za-z.\-_]+?)[^A-Za-z.[\]].*}}$)/g.exec(line).groups, {ext} = /^{{!.*(extension|ext=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; resolve({name, ext}); From dc820bfecba7e1ce727845ab603fca1558ff1895 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Mon, 31 Jul 2023 12:31:01 +0300 Subject: [PATCH 14/24] chore: hb templates functionality --- bin/cli.js | 13 +- src/controllers/create-app.js | 32 +++++ src/controllers/index.js | 4 +- src/controllers/make-test.js | 77 ++---------- src/controllers/make.js | 117 ++---------------- src/core/controller.js | 103 ++++++++++++++- src/core/handlebars.js | 41 +++--- src/core/interface.ts | 4 +- src/templates/app/package.json.handlebars | 2 +- src/templates/component/README.handlebars | 8 +- .../component/default/tpl-ss.handlebars | 2 +- .../component/default/tpl-ts.handlebars | 2 +- .../component/functional/tpl-ss.handlebars | 2 +- .../component/functional/tpl-ts.handlebars | 2 +- src/templates/component/index.handlebars | 2 +- .../component/mono/tpl-ss.handlebars | 2 +- src/templates/component/tpl-styl.handlebars | 2 +- src/templates/test/block/mock-data.ts | 0 src/templates/test/block/tpl.handlebars | 1 - src/templates/test/block/unit/tpl.handlebars | 2 +- src/templates/test/page/mock-data.ts | 0 .../test/page/project/tpl.handlebars | 1 + src/templates/test/page/tpl.handlebars | 1 - 23 files changed, 206 insertions(+), 214 deletions(-) create mode 100644 src/controllers/create-app.js create mode 100644 src/templates/test/block/mock-data.ts delete mode 100644 src/templates/test/block/tpl.handlebars create mode 100644 src/templates/test/page/mock-data.ts delete mode 100644 src/templates/test/page/tpl.handlebars diff --git a/bin/cli.js b/bin/cli.js index 2e1cf22..9296d1c 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -12,6 +12,15 @@ const yargs = require('yargs'); const {Application} = require('../src/application'); const options = yargs + .command( + 'create-app [name]', + 'Make simple application by basic template', + (yargs) => { + yargs.positional('name', { + type: 'string' + }); + } + ) .command( 'make-test ', 'Make test for page or component', @@ -68,13 +77,13 @@ const options = yargs .command( 'make [path]', - 'Make block, page or app', + 'Make block or page', (yargs) => { yargs .positional('subject', { default: 'block', type: 'string', - choices: ['block', 'page', 'app'] + choices: ['block', 'page'] }) .positional('name', { demandOption: true, diff --git a/src/controllers/create-app.js b/src/controllers/create-app.js new file mode 100644 index 0000000..bab6bf7 --- /dev/null +++ b/src/controllers/create-app.js @@ -0,0 +1,32 @@ +const path = require('path'); +const {Controller} = require('../core/controller'); + +class CreateAppController extends Controller { + /** @override */ + async run() { + const + source = this.vfs.resolve(__dirname, '../templates/app'), + appName = this.config.name || 'v4fire-app', + appPath = appName.split(path.sep); + + let + destination = './'; + + if ( + appPath.length > 1 || + (appPath.length <= 1 && (!this.vfs.exists(this.config.name) || !this.vfs.isDirectory(this.config.name))) + ) { + this.vfs.resolve('./'); + + } else { + destination = this.vfs.resolve(...appPath); + } + + this.handlebarsOptions = {name: appName}; + + await this.vfs.ensureDir(destination); + await this.copyDir(source, destination, {withFolders: true}); + } +} + +module.exports = CreateAppController; diff --git a/src/controllers/index.js b/src/controllers/index.js index b9c9b96..cb45a4e 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -5,7 +5,7 @@ const ResolveChangelogController = require('./resolve-changelog'); const CreateWorkspaceController = require('./create-workspace'); const RemoveWorkspaceController = require('./remove-workspace'); const UpGitController = require('./up-yarn-git-dependencies'); -const TestController = require('./test'); +const CreateAppController = require('./create-app'); module.exports = { MakeController, @@ -15,5 +15,5 @@ module.exports = { CreateWorkspaceController, UpGitController, RemoveWorkspaceController, - TestController + CreateAppController }; diff --git a/src/controllers/make-test.js b/src/controllers/make-test.js index c6033e4..0d16f65 100644 --- a/src/controllers/make-test.js +++ b/src/controllers/make-test.js @@ -3,7 +3,6 @@ const ts = require('typescript'); const {Controller} = require('../core/controller'); const {AbstractSyntaxTree} = require('../core/ast'); -const {camelize, ucfirst} = require('../core/helpers'); class MakeTestController extends Controller { /** @@ -23,54 +22,27 @@ class MakeTestController extends Controller { this.config.subject ); + const + name = this.resolveName(this.config.target, this.prefix), + clearName = this.resolveName(this.config.target, this.prefix, false); + let - destination = this.vfs.resolve(this.config.target); + destination = this.config.target; - if (this.config.target.split(path.sep).length === 1) { + if (destination.split(path.sep).length === 1) { const chunk = this.config.subject === 'page' ? 'pages' : 'components', - name = this.resolveName(this.config.target, this.prefix), globPattern = `${this.vfs.resolve('src', chunk)}/**/${name}`; destination = this.vfs.getFilesByGlobPattern(globPattern)[0]; } - await this.vfs.ensureDir(destination, 'test'); - destination = this.vfs.resolve(destination, 'test'); - - await this.copyTestFolder(source, destination); - } + this.handlebarsOptions = {name, clearName}; - /** - * Copies tests files from the source to the destination and fills templates - * - * @param {string} source - * @param {string} destination - * - * @returns {Promise} - */ - async copyTestFolder(source, destination) { - await this.vfs.ensureDir(destination); - - const - clearName = destination.split(path.sep).at(-2).replace(RegExp(`${this.prefix}-`), ''); + destination = this.vfs.resolve(destination, 'test'); + await this.vfs.ensureDir(destination, 'test'); - const - sourcePath = this.vfs.resolve(source), - destinationPath = this.vfs.resolve(destination); - - await this.vfs.copyDir( - sourcePath, - destinationPath, - { - onDataWrite: (data) => this.replaceNames( - data, - [`${this.prefix}-name`, `${this.prefix}-${clearName}`], - ['r-name', clearName] - ), - afterEachCopy: (path) => this.log.msg(`Create: ${path}`) - } - ); + await this.copyDir(source, destination, {withFolders: true}); } /** @@ -147,35 +119,6 @@ class MakeTestController extends Controller { this.log.msg(`Update file: ${sourcePath}`); } - /** - * Replaces all occurrences of `defName` and `clearName` with `newName` and `clearNewName` with different typings - * - * @param {string} content - * @param {[string, string]} defNameOptions - * @param {[string, string]} clearNameOptions - * - * @returns {string} - */ - replaceNames( - content, - [defName, newName], - [clearName, newClearName] - ) { - return content - .replace( - RegExp(`${defName}|${clearName}`, 'g'), - (target) => target === defName ? newName : newClearName - ) - .replace( - RegExp(`${camelize(defName)}|${camelize(clearName)}`, 'g'), - (target) => target === camelize(defName) ? camelize(newName) : camelize(newClearName) - ) - .replace( - RegExp(`${ucfirst(camelize(defName))}|${ucfirst(camelize(clearName))}`, 'g'), - (target) => target === ucfirst(camelize(defName)) ? ucfirst(camelize(newName)) : ucfirst(camelize(newClearName)) - ); - } - /** @override */ constructor(config, vfs, log) { super(config, vfs, log); diff --git a/src/controllers/make.js b/src/controllers/make.js index d75d821..d3e6c7f 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -1,124 +1,23 @@ require('../core/handlebars'); -const readline = require('readline'); -const fs = require('fs'); -const {Controller} = require('../core/controller'); -const Handlebars = require('handlebars'); -const path = require('path'); - class MakeController extends Controller { resolvedName; /** @override */ async run() { - this.resolvedName = this.resolveName(this.config.name, this.prefix); - const - baseSource = this.vfs.resolve(__dirname, '../templates/component'), - templateFolderSource = this.vfs.resolve(baseSource, this.config.template); - - this.copyDir(templateFolderSource, this.config.path, {name: this.config.name}); - } - - copyDir(source, destination, options) { - const copy = async (source, destination, options = {}, pathStack = []) => { - const - {onDataWrite, withFolders = true} = options; - - const - curPath = this.vfs.resolve(source, ...pathStack), - isDirectory = this.vfs.isDirectory(curPath); - - if (!isDirectory) { - const - destDirPath = this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1)), - fileExt = this.vfs.extname(pathStack.at(-1)); - - await this.vfs.ensureDir(this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); - - if (fileExt.includes('handlebars')) { - let - {name, ext} = await this.getOutputFileInfo(curPath), - p = this.vfs.resolve(destination, ...pathStack); - - console.log(pathStack); - - if (name === '[[name]]' || name == null) { - name = options.name; - const foo = p - .split(path.sep) - .slice(0, p.split(path.sep).length - 1); - - foo.push(`${name}.${ext}`); - p = foo.join(path.sep); - } - - console.log(curPath, p, {name}); - // await this.writeTemplate(curPath, p, {name}); - - return; - } + name = this.resolveName(this.config.name, this.prefix), + source = this.vfs.resolve(__dirname, '../templates/component'), + secondarySource = this.vfs.resolve(__dirname, '../templates/component', this.config.template), + destination = this.vfs.resolve(this.config.path, name); - this.vfs.writeFile( - this.vfs.resolve(destination, ...pathStack), - this.vfs.readFile(curPath) - ); - - return; - } - - const - dir = this.vfs.readdir(curPath); - - for (const file of dir) { - if (!withFolders && this.vfs.isDirectory(this.vfs.resolve(curPath, file))) { - continue; - } - - await copy(source, destination, options, [...pathStack, file]); - } - }; - - return copy(source, destination, options); - } - - getOutputFileInfo(path) { - const rl = readline.createInterface({ - input: fs.createReadStream(path) - }); - - let - resolve, - reject; - - const res = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - rl.once('line', (line) => { - try { - const - {name} = /^{{!.*(name=(?[A-Za-z[\].\-_]+?)[^A-Za-z[\].\-_].*}}$)/g.exec(line).groups, - {ext} = /^{{!.*(extension|ext=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; - - resolve({name, ext}); - - } catch (error) { - reject(error); - } - }); - - return res; - } + this.handlebarsOptions = {name, clearName: this.config.name}; - async writeTemplate(source, destination, options) { + await this.vfs.ensureDir(secondarySource); await this.vfs.ensureDir(destination); - this.vfs.writeFile( - destination, - Handlebars.compile(this.vfs.readFile(source))(options) - ); + await this.copyDir(source, destination, {withFolders: false}); + await this.copyDir(secondarySource, destination, {withFolders: true}); } } diff --git a/src/core/controller.js b/src/core/controller.js index 98b9cfc..5a7a53f 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -1,3 +1,5 @@ +const path = require('path'); +const {getOutputFileInfo, Handlebars} = require('./handlebars'); const {camelize, ucfirst, gitUser} = require('./helpers'); /** @@ -19,6 +21,11 @@ class Controller { */ log; + /** + * @type {Dictionary} + */ + handlebarsOptions; + /** * Prefix for a current subject * @@ -42,10 +49,22 @@ class Controller { /** * @param {string} name * @param {string} [prefix] + * @param {boolean} [withPrefix] * @returns {string} */ - resolveName(name, prefix = 'b') { - return /^[bp]-/.test(name) ? name : `${prefix}-${name}`; + resolveName(name, prefix = 'b', withPrefix = true) { + let + localName = name; + + if (name.split(path.sep).length <= 1) { + localName = name.split(path.sep).at(-1); + } + + if (withPrefix) { + return /^[bp]-/.test(localName) ? localName : `${prefix}-${localName}`; + } + + return localName; } /** @@ -86,6 +105,86 @@ class Controller { return result; } + + /** + * Copies directory + * + * @param {string} source + * @param {string} destination + * @param {CopyDirOptions} options + * @returns {Promise} + */ + copyDir(source, destination, options) { + return this.copy(source, destination, options); + } + + /** + * Copies and resolves handlebars template + * + * @param {string} sourceFile + * @param {string} destinationFolder + * @returns {Promise} + */ + async copyTemplate(sourceFile, destinationFolder) { + let + {outputName, ext} = await getOutputFileInfo(sourceFile); + + if (outputName === '[[name]]' || outputName == null) { + outputName = this.handlebarsOptions.name; + } + + this.vfs.writeFile( + `${destinationFolder}${path.sep}${outputName}.${ext}`, + Handlebars.compile(this.vfs.readFile(sourceFile))(this.handlebarsOptions) + ); + } + + /** + * Copies directory + * + * @param {string} source + * @param {string} destination + * @param {CopyDirOptions} options + * @param {string[]} pathStack + * @returns {Promise} + */ + async copy(source, destination, options = {}, pathStack = []) { + const + {withFolders = true} = options; + + const + curSource = this.vfs.resolve(source, ...pathStack), + isDirectory = this.vfs.isDirectory(curSource); + + if (isDirectory) { + for (const file of this.vfs.readdir(curSource)) { + if (!withFolders && this.vfs.isDirectory(this.vfs.resolve(curSource, file))) { + continue; + } + + await this.copy(source, destination, options, [...pathStack, file]); + } + + return; + } + + const + curDestinationFolder = this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1)); + + await this.vfs.ensureDir(curDestinationFolder); + + if (this.vfs.extname(pathStack.at(-1)) === '.handlebars') { + console.log('copyTemplate', curSource); + await this.copyTemplate(curSource, curDestinationFolder); + return; + } + + console.log('copyFile', curSource); + this.vfs.writeFile( + this.vfs.resolve(destination, ...pathStack), + this.vfs.readFile(curSource) + ); + } } exports.Controller = Controller; diff --git a/src/core/handlebars.js b/src/core/handlebars.js index e91300e..600422a 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -4,22 +4,35 @@ const readline = require('readline'); const fs = require('fs'); const Handlebars = require('handlebars'); -module.exports.getOutputFileInfo = getOutputFileInfo; +Handlebars.registerHelper('camelize', function (options) { + return camelize(options.fn(this)); +}); -Handlebars.registerHelper('camelize', function (args) { - return Handlebars.SafeString(camelize(args.fn(this))); +Handlebars.registerHelper('capitalize', function (options) { + return ucfirst(camelize(options.fn(this))); }); -Handlebars.registerHelper('capitalize', function (args) { - return Handlebars.SafeString(ucfirst(camelize(args.fn(this)))); +Handlebars.registerHelper('wrapInCodeBlock', function (options) { + // eslint-disable-next-line prefer-template + return Handlebars.SafeString('```\n' + options.fn(this) + '\n```'); }); +module.exports.Handlebars = Handlebars; + +module.exports.getOutputFileInfo = getOutputFileInfo; + +/** + * Reads a handlebars template and returns output file info + * + * @param {string} path + * @returns {Promise<{ext: string; name?: string}>} + */ function getOutputFileInfo(path) { - const rl = readline.createInterface({ - input: fs.createReadStream(path) - }); + const rl = readline.createInterface({ + input: fs.createReadStream(path) + }); - let + let resolve, reject; @@ -28,18 +41,18 @@ function getOutputFileInfo(path) { reject = rej; }); - rl.once('line', (line) => { + rl.once('line', (line) => { try { const - {name} = /^{{!.*(name=(?[[\]A-Za-z.\-_]+?)[^A-Za-z.[\]].*}}$)/g.exec(line).groups, - {ext} = /^{{!.*(extension|ext=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; + outputName = /^{{!.*(output_name=(?[A-Za-z[\].\-_]+?)[^A-Za-z[\].\-_].*}}$)/g.exec(line).groups.name, + {ext} = /^{{!.*((extension|ext)=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; - resolve({name, ext}); + resolve({outputName, ext}); } catch (error) { reject(error); } - }); + }); return res; } diff --git a/src/core/interface.ts b/src/core/interface.ts index e8b1557..38d59f3 100644 --- a/src/core/interface.ts +++ b/src/core/interface.ts @@ -5,7 +5,7 @@ interface IConfig { path: string; name: string; newName?: string; - subject: 'block' | 'page' | 'app' | 'test'; + subject: 'block' | 'page'; command?: 'make' | 'rename'; _: [this['command']]; reporter: 'json' | 'raw' | 'silent'; @@ -15,7 +15,5 @@ interface IConfig { } interface CopyDirOptions { - afterEachCopy?(destPath: string): unknown; - onDataWrite?(data: string): string | object; withFolders?: boolean; } diff --git a/src/templates/app/package.json.handlebars b/src/templates/app/package.json.handlebars index db86339..d8aad31 100644 --- a/src/templates/app/package.json.handlebars +++ b/src/templates/app/package.json.handlebars @@ -1,4 +1,4 @@ -{{! name=package ext=json }} +{{! output_name=package ext=json }} { "name": "{{name}}", "version": "1.0.0", diff --git a/src/templates/component/README.handlebars b/src/templates/component/README.handlebars index cf2c60f..3f55607 100644 --- a/src/templates/component/README.handlebars +++ b/src/templates/component/README.handlebars @@ -1,12 +1,12 @@ -{{! name=README ext=md }} +{{! output_name=README ext=md }} # components/{{name}} [Changelog](./CHANGELOG.md) -About {{#camelize}}{{name}}{{#capitalize}} +About {{#camelize}}{{name}}{{/camelize}} ## How to use -``` +{{#wrapInCodeBlock}} < {{name}} -``` +{{/wrapInCodeBlock}} \ No newline at end of file diff --git a/src/templates/component/default/tpl-ss.handlebars b/src/templates/component/default/tpl-ss.handlebars index d082fee..955fffb 100644 --- a/src/templates/component/default/tpl-ss.handlebars +++ b/src/templates/component/default/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ss }} +{{! output_name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/default/tpl-ts.handlebars b/src/templates/component/default/tpl-ts.handlebars index a1d7754..c24dcd9 100644 --- a/src/templates/component/default/tpl-ts.handlebars +++ b/src/templates/component/default/tpl-ts.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ts }} +{{! output_name=[[name]] ext=ts }} /** * [[include:components/{{name}}/README.md]] * @packageDocumentation diff --git a/src/templates/component/functional/tpl-ss.handlebars b/src/templates/component/functional/tpl-ss.handlebars index d082fee..955fffb 100644 --- a/src/templates/component/functional/tpl-ss.handlebars +++ b/src/templates/component/functional/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ss }} +{{! output_name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/functional/tpl-ts.handlebars b/src/templates/component/functional/tpl-ts.handlebars index 119d78d..26da588 100644 --- a/src/templates/component/functional/tpl-ts.handlebars +++ b/src/templates/component/functional/tpl-ts.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ts }} +{{! output_name=[[name]] ext=ts }} /** * [[include:components/{{name}}/README.md]] * @packageDocumentation diff --git a/src/templates/component/index.handlebars b/src/templates/component/index.handlebars index 1c7345a..c9f5649 100644 --- a/src/templates/component/index.handlebars +++ b/src/templates/component/index.handlebars @@ -1,3 +1,3 @@ -{{! name=index ext=js }} +{{! output_name=index ext=js }} package('{{name}}') .extends('i-block'); diff --git a/src/templates/component/mono/tpl-ss.handlebars b/src/templates/component/mono/tpl-ss.handlebars index 2b3d694..57e5b36 100644 --- a/src/templates/component/mono/tpl-ss.handlebars +++ b/src/templates/component/mono/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ss }} +{{! output_name=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/tpl-styl.handlebars b/src/templates/component/tpl-styl.handlebars index c38b9f1..77f89d2 100644 --- a/src/templates/component/tpl-styl.handlebars +++ b/src/templates/component/tpl-styl.handlebars @@ -1,4 +1,4 @@ -{{! name=[[name]] ext=ss }} +{{! output_name=[[name]] ext=ss }} @import "super/i-block/i-block.styl" $p = { diff --git a/src/templates/test/block/mock-data.ts b/src/templates/test/block/mock-data.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/templates/test/block/tpl.handlebars b/src/templates/test/block/tpl.handlebars deleted file mode 100644 index 74c288f..0000000 --- a/src/templates/test/block/tpl.handlebars +++ /dev/null @@ -1 +0,0 @@ -{{! name=mock-data ext=ts }} \ No newline at end of file diff --git a/src/templates/test/block/unit/tpl.handlebars b/src/templates/test/block/unit/tpl.handlebars index 2a92593..ff9892d 100644 --- a/src/templates/test/block/unit/tpl.handlebars +++ b/src/templates/test/block/unit/tpl.handlebars @@ -1,4 +1,4 @@ -{{! name=foo; extension=ts; }} +{{! output_name=foo; extension=ts; }} import type { JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; diff --git a/src/templates/test/page/mock-data.ts b/src/templates/test/page/mock-data.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/templates/test/page/project/tpl.handlebars b/src/templates/test/page/project/tpl.handlebars index fd86d4e..7f2b6df 100644 --- a/src/templates/test/page/project/tpl.handlebars +++ b/src/templates/test/page/project/tpl.handlebars @@ -1,3 +1,4 @@ +{{! output_name=foo; extension=ts; }} import test from 'tests/config/project/test'; test.describe('<{{name}}>', () => { diff --git a/src/templates/test/page/tpl.handlebars b/src/templates/test/page/tpl.handlebars deleted file mode 100644 index 74c288f..0000000 --- a/src/templates/test/page/tpl.handlebars +++ /dev/null @@ -1 +0,0 @@ -{{! name=mock-data ext=ts }} \ No newline at end of file From 7f0797625b4d3ddf239aa9cc0bdca01db4cc14b4 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 1 Aug 2023 17:55:35 +0300 Subject: [PATCH 15/24] refactor: remove part of useless code --- bin/cli.js | 6 +-- src/controllers/create-app.js | 10 ++-- src/controllers/make.js | 2 - src/controllers/test.js | 91 ----------------------------------- src/core/controller.js | 26 +++++----- src/core/handlebars.js | 25 +++++++--- src/core/vfs.js | 51 -------------------- 7 files changed, 39 insertions(+), 172 deletions(-) delete mode 100644 src/controllers/test.js diff --git a/bin/cli.js b/bin/cli.js index 9296d1c..5c9067e 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -13,10 +13,10 @@ const {Application} = require('../src/application'); const options = yargs .command( - 'create-app [name]', - 'Make simple application by basic template', + 'create-app [target]', + 'Make simple application using basic v4fire template', (yargs) => { - yargs.positional('name', { + yargs.positional('target', { type: 'string' }); } diff --git a/src/controllers/create-app.js b/src/controllers/create-app.js index bab6bf7..cef9b51 100644 --- a/src/controllers/create-app.js +++ b/src/controllers/create-app.js @@ -6,16 +6,14 @@ class CreateAppController extends Controller { async run() { const source = this.vfs.resolve(__dirname, '../templates/app'), - appName = this.config.name || 'v4fire-app', - appPath = appName.split(path.sep); + appName = this.config.target || 'v4fire-app', + appPath = appName.split(path.sep), + directoryExists = this.vfs.exists(this.config.target) && this.vfs.isDirectory(this.config.target); let destination = './'; - if ( - appPath.length > 1 || - (appPath.length <= 1 && (!this.vfs.exists(this.config.name) || !this.vfs.isDirectory(this.config.name))) - ) { + if (appPath.length <= 1 && !directoryExists) { this.vfs.resolve('./'); } else { diff --git a/src/controllers/make.js b/src/controllers/make.js index d3e6c7f..2c77d35 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -1,5 +1,3 @@ -require('../core/handlebars'); - class MakeController extends Controller { resolvedName; diff --git a/src/controllers/test.js b/src/controllers/test.js deleted file mode 100644 index e37a1d1..0000000 --- a/src/controllers/test.js +++ /dev/null @@ -1,91 +0,0 @@ -const fs = require('fs'); -const Handlebars = require('handlebars'); -const {Controller} = require('../core/controller'); -const {getOutputFileInfo} = require('../core/handlebars'); -const path = require('path'); - -class TestController extends Controller { - /** @override */ - async run() { - const - name = this.resolveName(this.config.name, this.prefix); - - const - destination = this.vfs.resolve(this.config.path), - templateSource = path.resolve('src/templates/component/default'); - - // this.copyTemplate(templateSource, destination, name); - } - - async copyTemplate(targetPath, destPath, tempName) { - const - tempExt = this.vfs.extname(targetPath.split(path.sep).at(-1)); - - if (tempExt !== '.handlebars') { - this.vfs.ensureDir(destPath); - fs.copyFileSync(targetPath, destPath); - return; - } - - const - {name, ext} = await getOutputFileInfo(targetPath); - - let - fileName = `${name}.${ext}`; - - if (name === '[[name]]' || name == null) { - fileName = `${tempName}.${ext}`; - } - - console.log(fileName, tempName); - - // const - // dPath = this.vfs.resolve(destPath, fileName), - // raw = this.vfs.readFile(templatePath, 'utf-8'), - // data = Handlebars.template(raw)({name: tempName}); - - // this.vfs.writeFile(dPath, data); - } - - copyDir(source, destination, options) { - return copy(source, destination, options); - - async function copy(source, destination, options = {}, pathStack = []) { - const - {onDataWrite, afterEachCopy, withFolders = true} = options; - - const - curPath = this.resolve(source, ...pathStack), - isDirectory = this.isDirectory(curPath); - - if (!isDirectory) { - const - fileData = this.readFile(curPath), - destPath = this.resolve(destination, ...pathStack); - - await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); - - this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); - - if (typeof afterEachCopy === 'function') { - afterEachCopy(destPath); - } - - return; - } - - const - dir = this.readdir(curPath); - - for (const file of dir) { - if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { - continue; - } - - await this.copy(source, destination, options, [...pathStack, file]); - } - } - } -} - -module.exports = TestController; diff --git a/src/core/controller.js b/src/core/controller.js index 5a7a53f..366c396 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -67,6 +67,18 @@ class Controller { return localName; } + /** + * Copies directory + * + * @param {string} source + * @param {string} destination + * @param {CopyDirOptions} options + * @returns {Promise} + */ + copyDir(source, destination, options) { + return this.copy(source, destination, options); + } + /** * Rename all names to target name * @@ -106,24 +118,13 @@ class Controller { return result; } - /** - * Copies directory - * - * @param {string} source - * @param {string} destination - * @param {CopyDirOptions} options - * @returns {Promise} - */ - copyDir(source, destination, options) { - return this.copy(source, destination, options); - } - /** * Copies and resolves handlebars template * * @param {string} sourceFile * @param {string} destinationFolder * @returns {Promise} + * @protected */ async copyTemplate(sourceFile, destinationFolder) { let @@ -147,6 +148,7 @@ class Controller { * @param {CopyDirOptions} options * @param {string[]} pathStack * @returns {Promise} + * @protected */ async copy(source, destination, options = {}, pathStack = []) { const diff --git a/src/core/handlebars.js b/src/core/handlebars.js index 600422a..9ed1d84 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -1,31 +1,38 @@ /* eslint-disable func-names */ -const {camelize, ucfirst} = require('./helpers'); -const readline = require('readline'); const fs = require('fs'); +const readline = require('readline'); const Handlebars = require('handlebars'); +const {camelize, ucfirst} = require('./helpers'); + +/** + * Camelize string + * @param {string} str + */ Handlebars.registerHelper('camelize', function (options) { return camelize(options.fn(this)); }); +/** + * Camelize string and upper case first char + */ Handlebars.registerHelper('capitalize', function (options) { return ucfirst(camelize(options.fn(this))); }); +/** + * Wrap content in these quotes ``` + */ Handlebars.registerHelper('wrapInCodeBlock', function (options) { // eslint-disable-next-line prefer-template return Handlebars.SafeString('```\n' + options.fn(this) + '\n```'); }); -module.exports.Handlebars = Handlebars; - -module.exports.getOutputFileInfo = getOutputFileInfo; - /** * Reads a handlebars template and returns output file info * * @param {string} path - * @returns {Promise<{ext: string; name?: string}>} + * @returns {Promise<{ext: string; outputName?: string}>} */ function getOutputFileInfo(path) { const rl = readline.createInterface({ @@ -56,3 +63,7 @@ function getOutputFileInfo(path) { return res; } + +module.exports.Handlebars = Handlebars; + +module.exports.getOutputFileInfo = getOutputFileInfo; \ No newline at end of file diff --git a/src/core/vfs.js b/src/core/vfs.js index bf52ec3..92fb268 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -177,57 +177,6 @@ class VirtualFileSystem { getFilesByGlobPattern(pattern) { return glob.sync(pattern); } - - /** - * Copies files and directories from the source to the destination - * - * @param {string} source - * @param {string} destination - * @param {CopyDirOptions} [options] - * - * @returns {Promise} - */ - copyDir(source, destination, options) { - fs.copySync(); - - return copy(source, destination, options); - - async function copy(source, destination, options = {}, pathStack = []) { - const - {onDataWrite, afterEachCopy, withFolders = true} = options; - - const - curPath = this.resolve(source, ...pathStack), - isDirectory = this.isDirectory(curPath); - - if (!isDirectory) { - const - fileData = this.readFile(curPath), - destPath = this.resolve(destination, ...pathStack); - - await this.ensureDir(this.resolve(destination, ...pathStack.slice(0, pathStack.length - 1))); - - this.writeFile(destPath, typeof onDataWrite === 'function' ? onDataWrite(fileData) : undefined); - - if (typeof afterEachCopy === 'function') { - afterEachCopy(destPath); - } - - return; - } - - const - dir = this.readdir(curPath); - - for (const file of dir) { - if (!withFolders && this.isDirectory(this.resolve(curPath, file))) { - continue; - } - - await this.copy(source, destination, options, [...pathStack, file]); - } - } - } } exports.VirtualFileSystem = VirtualFileSystem; From bfb99153c31c9479c882e9a0b2d8a6f95a3e2d06 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 1 Aug 2023 18:00:14 +0300 Subject: [PATCH 16/24] docs: update readme --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index daacfec..c60384f 100644 --- a/README.md +++ b/README.md @@ -8,15 +8,20 @@ v4fire -h ## Usage -### Make app +### Create app It is the easiest way to start use V4Fire ```bash -v4fire make app my-app && cd my-app && npm run build +v4fire create-app my-app && yarn build ``` -It will create application ready for work. +It will create application ready for work in the current directory. + +```bash +v4fire create-app my-app/foo/bar && cd my-app/foo/bar && yarn build +``` +It will create application ready for work in the target directory. ### Create a workspace From b6f1054a0ab2c8b61d03da443440b9b32a985a27 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 1 Aug 2023 18:01:43 +0300 Subject: [PATCH 17/24] chore: remove test data --- src/components/b-foo/foo.ts | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 src/components/b-foo/foo.ts diff --git a/src/components/b-foo/foo.ts b/src/components/b-foo/foo.ts deleted file mode 100644 index dc01ea7..0000000 --- a/src/components/b-foo/foo.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * [[include:components/foo/README.md]] - * @packageDocumentation - */ - -import iBlock, { component } from 'super/i-block/i-block'; - -export * from 'super/i-block/i-block'; - -/** - * - */ -@component() -export default class extends iBlock {} From 84aabfd91efe2ab9c79354494b88115399bcc64c Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 1 Aug 2023 18:29:28 +0300 Subject: [PATCH 18/24] refactor: fix templates --- src/controllers/make.js | 2 ++ src/core/controller.js | 10 +++------- src/templates/test/block/unit/tpl.handlebars | 2 +- src/templates/test/page/project/tpl.handlebars | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/controllers/make.js b/src/controllers/make.js index 2c77d35..3d5cefa 100644 --- a/src/controllers/make.js +++ b/src/controllers/make.js @@ -1,3 +1,5 @@ +const {Controller} = require('../core/controller'); + class MakeController extends Controller { resolvedName; diff --git a/src/core/controller.js b/src/core/controller.js index 366c396..9619f63 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -53,18 +53,14 @@ class Controller { * @returns {string} */ resolveName(name, prefix = 'b', withPrefix = true) { - let - localName = name; - - if (name.split(path.sep).length <= 1) { - localName = name.split(path.sep).at(-1); - } + const + localName = name.split(path.sep).length === 1 ? name : name.split(path.sep).at(-1); if (withPrefix) { return /^[bp]-/.test(localName) ? localName : `${prefix}-${localName}`; } - return localName; + return name.split(path.sep).at(-1).replace(/^[bp]-/g, ''); } /** diff --git a/src/templates/test/block/unit/tpl.handlebars b/src/templates/test/block/unit/tpl.handlebars index ff9892d..426b8d8 100644 --- a/src/templates/test/block/unit/tpl.handlebars +++ b/src/templates/test/block/unit/tpl.handlebars @@ -1,4 +1,4 @@ -{{! output_name=foo; extension=ts; }} +{{! output_name=main; extension=ts; }} import type { JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; diff --git a/src/templates/test/page/project/tpl.handlebars b/src/templates/test/page/project/tpl.handlebars index 7f2b6df..9b1a986 100644 --- a/src/templates/test/page/project/tpl.handlebars +++ b/src/templates/test/page/project/tpl.handlebars @@ -1,8 +1,8 @@ -{{! output_name=foo; extension=ts; }} +{{! output_name=main; extension=ts; }} import test from 'tests/config/project/test'; test.describe('<{{name}}>', () => { - test('should be rendered', async ({ {{#capitalize}}{{name}}{{/capitalize}}, page }) => { + test('should be rendered', async ({ {{#camelize}}{{name}}{{/camelize}}, page }) => { await test.expect(page.locator('.{{name}}')).toBeVisible(); }); }); From 7c3b02d98ea06faf2708a2a0f3b9c29faae0eeb1 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 1 Aug 2023 18:30:48 +0300 Subject: [PATCH 19/24] chore: lil fix --- src/core/handlebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/handlebars.js b/src/core/handlebars.js index 9ed1d84..a94d26c 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -66,4 +66,4 @@ function getOutputFileInfo(path) { module.exports.Handlebars = Handlebars; -module.exports.getOutputFileInfo = getOutputFileInfo; \ No newline at end of file +module.exports.getOutputFileInfo = getOutputFileInfo; From ba8a441539a7ac11ba67f44b44f6f796a1314be9 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Fri, 4 Aug 2023 16:24:43 +0300 Subject: [PATCH 20/24] chore: review fixes --- package.json | 2 +- src/core/controller.js | 11 ++--- src/core/handlebars.js | 49 +++++++------------ src/core/helpers.js | 36 ++++++++++++-- src/core/vfs.js | 9 ++++ src/templates/app/package.json.handlebars | 2 +- src/templates/component/README.handlebars | 2 +- .../component/default/tpl-ss.handlebars | 2 +- .../component/default/tpl-ts.handlebars | 2 +- .../component/functional/tpl-ss.handlebars | 2 +- .../component/functional/tpl-ts.handlebars | 2 +- src/templates/component/index.handlebars | 2 +- .../component/mono/tpl-ss.handlebars | 2 +- src/templates/component/tpl-styl.handlebars | 2 +- src/templates/test/block/unit/tpl.handlebars | 2 +- .../test/page/project/tpl.handlebars | 2 +- 16 files changed, 77 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 61ec2a0..a83320e 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "fs-extra": "11.1.1", "git-config-path": "2.0.0", "glob": "9.3.4", - "handlebars": "^4.7.7", + "handlebars": "4.7.7", "parse-git-config": "3.0.0", "typescript": "4.4.4", "yargs": "17.7.1" diff --git a/src/core/controller.js b/src/core/controller.js index 9619f63..c05d1fa 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -122,7 +122,7 @@ class Controller { * @returns {Promise} * @protected */ - async copyTemplate(sourceFile, destinationFolder) { + async resolveTemplate(sourceFile, destinationFolder) { let {outputName, ext} = await getOutputFileInfo(sourceFile); @@ -167,17 +167,16 @@ class Controller { } const - curDestinationFolder = this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1)); + curDestinationFolder = this.vfs.resolve(destination, ...pathStack.slice(0, pathStack.length - 1)), + extname = this.vfs.extname(pathStack.at(-1)); await this.vfs.ensureDir(curDestinationFolder); - if (this.vfs.extname(pathStack.at(-1)) === '.handlebars') { - console.log('copyTemplate', curSource); - await this.copyTemplate(curSource, curDestinationFolder); + if (extname === '.handlebars' || extname === '.hbs') { + await this.resolveTemplate(curSource, curDestinationFolder); return; } - console.log('copyFile', curSource); this.vfs.writeFile( this.vfs.resolve(destination, ...pathStack), this.vfs.readFile(curSource) diff --git a/src/core/handlebars.js b/src/core/handlebars.js index a94d26c..f62d236 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -1,9 +1,7 @@ /* eslint-disable func-names */ -const fs = require('fs'); -const readline = require('readline'); const Handlebars = require('handlebars'); -const {camelize, ucfirst} = require('./helpers'); +const {camelize, ucfirst, readFirstLine} = require('./helpers'); /** * Camelize string @@ -34,34 +32,23 @@ Handlebars.registerHelper('wrapInCodeBlock', function (options) { * @param {string} path * @returns {Promise<{ext: string; outputName?: string}>} */ -function getOutputFileInfo(path) { - const rl = readline.createInterface({ - input: fs.createReadStream(path) - }); - - let - resolve, - reject; - - const res = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - - rl.once('line', (line) => { - try { - const - outputName = /^{{!.*(output_name=(?[A-Za-z[\].\-_]+?)[^A-Za-z[\].\-_].*}}$)/g.exec(line).groups.name, - {ext} = /^{{!.*((extension|ext)=(?[A-Za-z.]+?)[^A-Za-z.].*}}$)/g.exec(line).groups; - - resolve({outputName, ext}); - - } catch (error) { - reject(error); - } - }); - - return res; +async function getOutputFileInfo(path) { + const + line = await readFirstLine(path), + opts = line.split(/\s/); + + opts.pop(); + opts.shift(); + + return opts.reduce((acc, el) => { + const + tuple = el.split('='); + + return { + ...acc, + [tuple[0]]: tuple[1] + }; + }, {}); } module.exports.Handlebars = Handlebars; diff --git a/src/core/helpers.js b/src/core/helpers.js index 449f638..cc3fb46 100644 --- a/src/core/helpers.js +++ b/src/core/helpers.js @@ -1,3 +1,8 @@ +const fs = require('fs'); +const readline = require('readline'); +const gitconfig = require('git-config-path'); +const parse = require('parse-git-config'); + /** * Camelize string * @param {string} str @@ -11,9 +16,6 @@ exports.camelize = (str) => */ exports.ucfirst = (str) => str[0].toUpperCase() + str.substr(1); -const gitconfig = require('git-config-path'), - parse = require('parse-git-config'); - /** * Current user name */ @@ -36,3 +38,31 @@ exports.gitUser = (() => { email: config.user.name || config.user.email || defaultUser.email }; })(); + +/** + * Read the first line from the file + * @param {string} path + */ +exports.readFirstLine = (path) => { + const rl = readline.createInterface({ + input: fs.createReadStream(path) + }); + + let + resolve, + reject; + + const res = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + + try { + rl.once('line', (line) => resolve(line)); + + } catch (error) { + reject(error); + } + + return res; +}; diff --git a/src/core/vfs.js b/src/core/vfs.js index 92fb268..371e1f4 100644 --- a/src/core/vfs.js +++ b/src/core/vfs.js @@ -106,6 +106,15 @@ class VirtualFileSystem { return fs.readdirSync(filepath); } + /** + * Copy directory + * + * @param {string} filepath + */ + copyDir(filepath) { + return fs.cpSync() + } + /** * Remove directory * diff --git a/src/templates/app/package.json.handlebars b/src/templates/app/package.json.handlebars index d8aad31..d1cf5ee 100644 --- a/src/templates/app/package.json.handlebars +++ b/src/templates/app/package.json.handlebars @@ -1,4 +1,4 @@ -{{! output_name=package ext=json }} +{{! outputName=package ext=json }} { "name": "{{name}}", "version": "1.0.0", diff --git a/src/templates/component/README.handlebars b/src/templates/component/README.handlebars index 3f55607..82f096f 100644 --- a/src/templates/component/README.handlebars +++ b/src/templates/component/README.handlebars @@ -1,4 +1,4 @@ -{{! output_name=README ext=md }} +{{! outputName=README ext=md }} # components/{{name}} [Changelog](./CHANGELOG.md) diff --git a/src/templates/component/default/tpl-ss.handlebars b/src/templates/component/default/tpl-ss.handlebars index 955fffb..831b169 100644 --- a/src/templates/component/default/tpl-ss.handlebars +++ b/src/templates/component/default/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ss }} +{{! outputName=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/default/tpl-ts.handlebars b/src/templates/component/default/tpl-ts.handlebars index c24dcd9..9dc534a 100644 --- a/src/templates/component/default/tpl-ts.handlebars +++ b/src/templates/component/default/tpl-ts.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ts }} +{{! outputName=[[name]] ext=ts }} /** * [[include:components/{{name}}/README.md]] * @packageDocumentation diff --git a/src/templates/component/functional/tpl-ss.handlebars b/src/templates/component/functional/tpl-ss.handlebars index 955fffb..831b169 100644 --- a/src/templates/component/functional/tpl-ss.handlebars +++ b/src/templates/component/functional/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ss }} +{{! outputName=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/functional/tpl-ts.handlebars b/src/templates/component/functional/tpl-ts.handlebars index 26da588..342a36b 100644 --- a/src/templates/component/functional/tpl-ts.handlebars +++ b/src/templates/component/functional/tpl-ts.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ts }} +{{! outputName=[[name]] ext=ts }} /** * [[include:components/{{name}}/README.md]] * @packageDocumentation diff --git a/src/templates/component/index.handlebars b/src/templates/component/index.handlebars index c9f5649..27d71ae 100644 --- a/src/templates/component/index.handlebars +++ b/src/templates/component/index.handlebars @@ -1,3 +1,3 @@ -{{! output_name=index ext=js }} +{{! outputName=index ext=js }} package('{{name}}') .extends('i-block'); diff --git a/src/templates/component/mono/tpl-ss.handlebars b/src/templates/component/mono/tpl-ss.handlebars index 57e5b36..810e71e 100644 --- a/src/templates/component/mono/tpl-ss.handlebars +++ b/src/templates/component/mono/tpl-ss.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ss }} +{{! outputName=[[name]] ext=ss }} - namespace [%fileName%] - include 'super/i-block'|b as placeholder diff --git a/src/templates/component/tpl-styl.handlebars b/src/templates/component/tpl-styl.handlebars index 77f89d2..04c51b0 100644 --- a/src/templates/component/tpl-styl.handlebars +++ b/src/templates/component/tpl-styl.handlebars @@ -1,4 +1,4 @@ -{{! output_name=[[name]] ext=ss }} +{{! outputName=[[name]] ext=ss }} @import "super/i-block/i-block.styl" $p = { diff --git a/src/templates/test/block/unit/tpl.handlebars b/src/templates/test/block/unit/tpl.handlebars index 426b8d8..2b0fe33 100644 --- a/src/templates/test/block/unit/tpl.handlebars +++ b/src/templates/test/block/unit/tpl.handlebars @@ -1,4 +1,4 @@ -{{! output_name=main; extension=ts; }} +{{! outputName=main ext=ts }} import type { JSHandle } from 'playwright'; import test from 'tests/config/unit/test'; diff --git a/src/templates/test/page/project/tpl.handlebars b/src/templates/test/page/project/tpl.handlebars index 9b1a986..5454d3e 100644 --- a/src/templates/test/page/project/tpl.handlebars +++ b/src/templates/test/page/project/tpl.handlebars @@ -1,4 +1,4 @@ -{{! output_name=main; extension=ts; }} +{{! outputName=main ext=ts }} import test from 'tests/config/project/test'; test.describe('<{{name}}>', () => { From f4e51633c5036ee28a7eaf91da58ac5bcd444155 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Tue, 8 Aug 2023 16:57:55 +0300 Subject: [PATCH 21/24] chore: fixes --- src/application.js | 2 +- src/core/controller.js | 6 +++++- src/core/handlebars.js | 5 ++++- src/templates/component/README.handlebars | 2 +- yarn.lock | 4 ++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/application.js b/src/application.js index 7a798ce..7310397 100644 --- a/src/application.js +++ b/src/application.js @@ -32,7 +32,7 @@ class Application { const {commandNative: command, subject} = this.config; - this.log.info(`Command:${command} ${subject}`); + this.log.info(`Command: ${command} ${subject}`); const controller = this.getControllerInstance( `${ucfirst(camelize(`${command}-${subject}`))}Controller` diff --git a/src/core/controller.js b/src/core/controller.js index c05d1fa..6269e7f 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -155,14 +155,18 @@ class Controller { isDirectory = this.vfs.isDirectory(curSource); if (isDirectory) { + const + promises = []; + for (const file of this.vfs.readdir(curSource)) { if (!withFolders && this.vfs.isDirectory(this.vfs.resolve(curSource, file))) { continue; } - await this.copy(source, destination, options, [...pathStack, file]); + promises.push(this.copy(source, destination, options, [...pathStack, file])); } + await Promise.all(promises); return; } diff --git a/src/core/handlebars.js b/src/core/handlebars.js index f62d236..2263252 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -27,7 +27,10 @@ Handlebars.registerHelper('wrapInCodeBlock', function (options) { }); /** - * Reads a handlebars template and returns output file info + * Reads the handlebars template that returns output file info + * The first line of the template contains information about the file name and extension + * The format looks like this: {{! name=index ext=ts }} + * Tt will be parsed into this: {name: 'index', ext: 'ts'} * * @param {string} path * @returns {Promise<{ext: string; outputName?: string}>} diff --git a/src/templates/component/README.handlebars b/src/templates/component/README.handlebars index 82f096f..e1ecf45 100644 --- a/src/templates/component/README.handlebars +++ b/src/templates/component/README.handlebars @@ -9,4 +9,4 @@ About {{#camelize}}{{name}}{{/camelize}} {{#wrapInCodeBlock}} < {{name}} -{{/wrapInCodeBlock}} \ No newline at end of file +{{/wrapInCodeBlock}} diff --git a/yarn.lock b/yarn.lock index 77ca3f7..e6783c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2433,7 +2433,7 @@ __metadata: fs-extra: 11.1.1 git-config-path: 2.0.0 glob: 9.3.4 - handlebars: ^4.7.7 + handlebars: 4.7.7 mocha: 10.2.0 parse-git-config: 3.0.0 typescript: 4.4.4 @@ -6385,7 +6385,7 @@ __metadata: languageName: node linkType: hard -"handlebars@npm:^4.7.7": +"handlebars@npm:4.7.7": version: 4.7.7 resolution: "handlebars@npm:4.7.7" dependencies: From 8205d2bee445c28dab7b85ec314d37161e33eceb Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Thu, 10 Aug 2023 11:40:42 +0300 Subject: [PATCH 22/24] chore: fixes --- src/core/controller.js | 2 +- src/core/handlebars.js | 7 ++----- src/templates/app/src/base/b-hello-world/index.js | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/core/controller.js b/src/core/controller.js index 6269e7f..10e10d3 100644 --- a/src/core/controller.js +++ b/src/core/controller.js @@ -115,7 +115,7 @@ class Controller { } /** - * Copies and resolves handlebars template + * Copies and resolves template * * @param {string} sourceFile * @param {string} destinationFolder diff --git a/src/core/handlebars.js b/src/core/handlebars.js index 2263252..26a5258 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -27,7 +27,7 @@ Handlebars.registerHelper('wrapInCodeBlock', function (options) { }); /** - * Reads the handlebars template that returns output file info + * Reads the template that returns output file info * The first line of the template contains information about the file name and extension * The format looks like this: {{! name=index ext=ts }} * Tt will be parsed into this: {name: 'index', ext: 'ts'} @@ -38,10 +38,7 @@ Handlebars.registerHelper('wrapInCodeBlock', function (options) { async function getOutputFileInfo(path) { const line = await readFirstLine(path), - opts = line.split(/\s/); - - opts.pop(); - opts.shift(); + opts = line.slice(4, -3).trim().split(/\s+/); return opts.reduce((acc, el) => { const diff --git a/src/templates/app/src/base/b-hello-world/index.js b/src/templates/app/src/base/b-hello-world/index.js index 926efea..660317c 100644 --- a/src/templates/app/src/base/b-hello-world/index.js +++ b/src/templates/app/src/base/b-hello-world/index.js @@ -1,2 +1,2 @@ -package("b-hello-world") - .extends("i-block"); +package('b-hello-world') + .extends('i-block'); From daa0e81af9a8f33817a2cd298ce8a907ca8e4c12 Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Thu, 10 Aug 2023 13:02:35 +0300 Subject: [PATCH 23/24] docs: write CHANGELOG and up package version --- CHANGELOG.md | 20 ++++++++++++++++++++ package.json | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4db92c..dd50f37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,26 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ +## v2.0.0 (2023-08-10) + +#### :boom: [Breaking Change] + +* `make-test` - the command interface has been changed +* `make` - support for the `make app` has been removed + +#### :rocket: [New Feature] + +* `create-app` - the function has been added for the easy creation of v4fire app + +#### :house: Internal + +* Moved to using Handlebars templates + +#### :memo: [Documentation] + +* `help` - documentation has been updated +* README.md has been updated + ## v1.5.2 (2023-04-14) #### :bug: Bug Fix diff --git a/package.json b/package.json index a83320e..682c5b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@v4fire/cli", - "version": "1.6.0", + "version": "2.0.0", "description": "Tools for creating V4Fire blocks and pages from CLI", "main": "index.js", "bin": { From 9d1d293660d2e2df8c41a552c2ab20dd30d052dc Mon Sep 17 00:00:00 2001 From: misbiheyv Date: Thu, 10 Aug 2023 13:07:58 +0300 Subject: [PATCH 24/24] fix letter --- src/core/handlebars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/handlebars.js b/src/core/handlebars.js index 26a5258..b792d80 100644 --- a/src/core/handlebars.js +++ b/src/core/handlebars.js @@ -30,7 +30,7 @@ Handlebars.registerHelper('wrapInCodeBlock', function (options) { * Reads the template that returns output file info * The first line of the template contains information about the file name and extension * The format looks like this: {{! name=index ext=ts }} - * Tt will be parsed into this: {name: 'index', ext: 'ts'} + * It will be parsed into this: {name: 'index', ext: 'ts'} * * @param {string} path * @returns {Promise<{ext: string; outputName?: string}>}