From 8f938c10abdb50defb453a60506a035d6de1d70a Mon Sep 17 00:00:00 2001 From: kdhardin Date: Thu, 7 Nov 2019 12:24:42 -0700 Subject: [PATCH 1/4] Add current date/time template variables. --- README.md | 16 +++++++- src/fileCreator/createFiles.ts | 4 +- src/fileCreator/transforms.ts | 68 ++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6aadbae..8403ec3 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,8 @@ Examples: | Helper Name | Example Use In Templates | Example Use in File/Folder Names | Sample Result | |----------------|--------------------------|----------------------------------|-------------------------| | {none} | {{name}} | \_\_name\_\_ | {No transform applied} | -| upperCase | {{upperCase name}} | \_\_upperCase_name\_\_ | THIS IS UPPERCASE | -| lowerCase | {{lowerCase name}} | \_\_lowerCase_name\_\_ | this is lowercase | +| upperCase | {{upperCase name}} | \_\_upperCase_name\_\_ | THIS IS UPPERCASE | +| lowerCase | {{lowerCase name}} | \_\_lowerCase_name\_\_ | this is lowercase | | camelCase | {{camelCase name}} | \_\_camelCase_name\_\_ | thisIsCamelCase | | pascalCase | {{pascalCase name}} | \_\_pascalCase_name\_\_ | ThisIsPascalCase | | snakeCase | {{snakeCase name}} | \_\_snakeCase_name\_\_ | this_is_snake_case | @@ -68,6 +68,18 @@ Examples: | kebabCase | {{kebabCase name}} | \_\_kebabCase_name\_\_ | this-is-kebab-case | | lowerDotCase | {{lowerDotCase name}} | \_\_lowerDotCase_name\_\_ | this.is.lower.dot.case | +## Date/Time Template Variables + +| Variable Name | Example Use In Templates | Example Use in File/Folder Names | Sample Result | +|----------------|--------------------------|----------------------------------|-------------------------| +| currentYear | {{currentYear}} | \_\_currentYear\_\_ | YYYY | +| currentMonth | {{currentMonth}} | \_\_currentMonth\_\_ | MM | +| currentDate | {{currentDate}} | \_\_currentDate\_\_ | DD | +| currentDay | {{currentDay}} | \_\_currentDay\_\_ | d | +| currentHour | {{currentHour}} | \_\_currentHour\_\_ | HH | +| currentMin | {{currentMin}} | \_\_currentMin\_\_ | mm | +| currentSec | {{currentSec}} | \_\_currentSec\_\_ | ss | + ## Dynamic Template Variables Dynamic Template Variables provide template replacements at the time of file creation in addition to the standard name. The dynamic replacement token should conform to the format of `{{ $ }}` (we will search for a `$` within `{{ }}`). diff --git a/src/fileCreator/createFiles.ts b/src/fileCreator/createFiles.ts index c360f73..805a00a 100644 --- a/src/fileCreator/createFiles.ts +++ b/src/fileCreator/createFiles.ts @@ -10,7 +10,7 @@ import { IDynamicTemplateValues, IUserInput } from "../inputs"; import { getFolderNamesAtDirectory } from "../utilities/getTemplateFilesAndFolders"; import { getTemplateFileNamesAtTemplateDirectory } from "../utilities/getTemplateFilesAndFolders"; import { sanitizedName } from "./inputSanitizer"; -import { replaceStringUsingTransforms, replaceTemplateContent } from "./transforms"; +import { setCurrentDate, replaceStringUsingTransforms, replaceTemplateContent } from "./transforms"; export async function createFiles(userInput: IUserInput, inDirectory: string): Promise { @@ -20,6 +20,8 @@ export async function createFiles(userInput: IUserInput, inDirectory: string): P const temporaryDirectory = await fs.mkdtemp(path.join(os.tmpdir(), "blueprint-")); + setCurrentDate(new Date()); + await createFilesFromTemplateInDirectory( userInput.selectedTemplatePath, temporaryDirectory, diff --git a/src/fileCreator/transforms.ts b/src/fileCreator/transforms.ts index 6c0d959..68e853e 100644 --- a/src/fileCreator/transforms.ts +++ b/src/fileCreator/transforms.ts @@ -5,6 +5,11 @@ import * as _ from "lodash"; import { IDynamicTemplateValues } from "../inputs"; let handlebarsInitialized = false; +let currentDate: Date = new Date(); + +export function setCurrentDate(date: Date) { + currentDate = date; +} export function initializeHandlebars() { handlebars.registerHelper({ @@ -32,6 +37,27 @@ export function initializeHandlebars() { upperSnakeCase: (input) => { return _.snakeCase(input).toUpperCase(); }, + currentYear: (input) => { + return getYear(currentDate); + }, + currentMonth: (input) => { + return getMonth(currentDate); + }, + currentDate: (input) => { + return getDayOfMonth(currentDate); + }, + currentDay: (input) => { + return getDay(currentDate); + }, + currentHour: (input) => { + return getHours(currentDate); + }, + currentMin: (input) => { + return getMinutes(currentDate); + }, + currentSec: (input) => { + return getSeconds(currentDate); + }, }); } @@ -73,6 +99,13 @@ export function replaceStringUsingTransforms(stringToReplace: string, name: stri result = replaceAll(result, "__upperCase_name__", _.upperCase(name)); result = replaceAll(result, "__lowerCase_name__", _.lowerCase(name)); result = replaceAll(result, "__upperSnakeCase_name__", _.snakeCase(name).toUpperCase()); + result = replaceAll(result, "__currentYear__", getYear(currentDate)); + result = replaceAll(result, "__currentMonth__", getMonth(currentDate)); + result = replaceAll(result, "__currentDate__", getDayOfMonth(currentDate)); + result = replaceAll(result, "__currentDay__", getDay(currentDate)); + result = replaceAll(result, "__currentHour__", getHours(currentDate)); + result = replaceAll(result, "__currentMin__", getMinutes(currentDate)); + result = replaceAll(result, "__currentSec__", getSeconds(currentDate)); return result; } @@ -83,3 +116,38 @@ function escapeRegExp(str): string { function replaceAll(str, find, replace): string { return str.replace(new RegExp(escapeRegExp(find), "g"), replace); } + +function getYear(date: Date): string { + return date.getFullYear().toString(); +} + +function getMonth(date: Date): string { + return padDateComponentToTwoChars((date.getMonth() + 1).toString()); +} + +function getDayOfMonth(date: Date): string { + return padDateComponentToTwoChars(date.getDate().toString()); +} + +function getDay(date: Date): string { + return date.getDay().toString(); +} + +function getHours(date: Date): string { + return padDateComponentToTwoChars(date.getHours().toString()); +} + +function getMinutes(date: Date): string { + return padDateComponentToTwoChars(date.getMinutes().toString()); +} + +function getSeconds(date: Date): string { + return padDateComponentToTwoChars(date.getSeconds().toString()); +} + +function padDateComponentToTwoChars(str: string): string { + if (str.length < 2) { + str = '0' + str; + } + return str; +} From 28ca46e4b8f98494d47d3100c7bdf403462e9ba3 Mon Sep 17 00:00:00 2001 From: kdhardin Date: Mon, 9 Dec 2019 14:51:59 -0700 Subject: [PATCH 2/4] Added date/time variable unit test coverage. --- src/extension.ts | 2 +- src/fileCreator/createFiles.ts | 4 +- test/extension.test.ts | 37 +++++++++++++++---- .../1965-10-31-0-dateComponents | 4 ++ .../datetime-simple/22_43_54-timeComponents | 3 ++ .../04_05_06-timeComponents | 3 ++ .../1-02-03-6-dateComponents | 4 ++ ...currentMin_____currentSec__-timeComponents | 3 ++ ...urrentDate__-__currentDay__-dateComponents | 4 ++ 9 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 test/integrationTests/expectedOutput/datetime-simple/1965-10-31-0-dateComponents create mode 100644 test/integrationTests/expectedOutput/datetime-simple/22_43_54-timeComponents create mode 100644 test/integrationTests/expectedOutput/datetime-zeropadding/04_05_06-timeComponents create mode 100644 test/integrationTests/expectedOutput/datetime-zeropadding/1-02-03-6-dateComponents create mode 100644 test/integrationTests/templates/datetime/__currentHour_____currentMin_____currentSec__-timeComponents create mode 100644 test/integrationTests/templates/datetime/__currentYear__-__currentMonth__-__currentDate__-__currentDay__-dateComponents diff --git a/src/extension.ts b/src/extension.ts index 6bfaaa9..671a881 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -24,7 +24,7 @@ export function activate(context: vscode.ExtensionContext) { try { const userInput = await getUserInput(templateFolderRawPaths); - await createFiles(userInput, directoryPath); + await createFiles(userInput, directoryPath, new Date()); } catch (error) { handleError(error); } diff --git a/src/fileCreator/createFiles.ts b/src/fileCreator/createFiles.ts index 805a00a..ccb509c 100644 --- a/src/fileCreator/createFiles.ts +++ b/src/fileCreator/createFiles.ts @@ -12,7 +12,7 @@ import { getTemplateFileNamesAtTemplateDirectory } from "../utilities/getTemplat import { sanitizedName } from "./inputSanitizer"; import { setCurrentDate, replaceStringUsingTransforms, replaceTemplateContent } from "./transforms"; -export async function createFiles(userInput: IUserInput, inDirectory: string): Promise { +export async function createFiles(userInput: IUserInput, inDirectory: string, date: Date): Promise { const options = getTemplateManifestAtTemplateDirectory(userInput.selectedTemplatePath); @@ -20,7 +20,7 @@ export async function createFiles(userInput: IUserInput, inDirectory: string): P const temporaryDirectory = await fs.mkdtemp(path.join(os.tmpdir(), "blueprint-")); - setCurrentDate(new Date()); + setCurrentDate(date); await createFilesFromTemplateInDirectory( userInput.selectedTemplatePath, diff --git a/test/extension.test.ts b/test/extension.test.ts index 992ed26..d2fbb7b 100644 --- a/test/extension.test.ts +++ b/test/extension.test.ts @@ -28,8 +28,8 @@ suite("Extension Tests", () => { fs.removeSync(outPath); }; - const runTestForTemplateNamed = async (templateName: string, dynamicTemplateValues: IDynamicTemplateValues) => { - const directoryPath = path.join(outPath, templateName); + const runTestForTemplateNamed = async (templateName: string, outName: string, dynamicTemplateValues: IDynamicTemplateValues, testDate: Date) => { + const directoryPath = path.join(outPath, outName); const userInput: IUserInput = { inputName: "MY User Input", @@ -37,7 +37,7 @@ suite("Extension Tests", () => { dynamicTemplateValues, }; - return createFiles(userInput, directoryPath).then(() => { + return createFiles(userInput, directoryPath, testDate).then(() => { // Ensure at least one file was created assert.equal(fs.readdirSync(expectedOutputPath).length > 0, true); @@ -46,7 +46,7 @@ suite("Extension Tests", () => { noDiffSet: true }; const result = dirCompare.compareSync( - path.join(expectedOutputPath, templateName), + path.join(expectedOutputPath, outName), directoryPath, options ); @@ -60,21 +60,21 @@ suite("Extension Tests", () => { // Defines a Mocha unit test test("includesImages", (done) => { beforeEach(); - runTestForTemplateNamed("includesImages", {}).then(() => { + runTestForTemplateNamed("includesImages", "includesImages", {}, new Date()).then(() => { done(); }); }); test("nestedFolders", (done) => { beforeEach(); - runTestForTemplateNamed("nestedFolders", {}).then(() => { + runTestForTemplateNamed("nestedFolders", "nestedFolders", {}, new Date()).then(() => { done(); }); }); test("transforms", (done) => { beforeEach(); - runTestForTemplateNamed("transforms", {}).then(() => { + runTestForTemplateNamed("transforms", "transforms", {}, new Date()).then(() => { done(); }); }); @@ -94,7 +94,28 @@ suite("Extension Tests", () => { } }; - runTestForTemplateNamed("dynamicTemplateVariables", dynamicTemplateValues).then(() => { + runTestForTemplateNamed("dynamicTemplateVariables", "dynamicTemplateVariables", dynamicTemplateValues, new Date()).then(() => { + done(); + }); + }); + + test("datetime-simple", (done) => { + beforeEach(); + + const testDate = new Date("1965-10-31 22:43:54"); + + runTestForTemplateNamed("datetime", "datetime-simple", {}, testDate).then(() => { + done(); + }); + }); + + test("datetime-zeropadding", (done) => { + beforeEach(); + + const testDate = new Date("0100-02-03 04:05:06"); + testDate.setFullYear(1); + + runTestForTemplateNamed("datetime", "datetime-zeropadding", {}, testDate).then(() => { done(); }); }); diff --git a/test/integrationTests/expectedOutput/datetime-simple/1965-10-31-0-dateComponents b/test/integrationTests/expectedOutput/datetime-simple/1965-10-31-0-dateComponents new file mode 100644 index 0000000..d0eb73c --- /dev/null +++ b/test/integrationTests/expectedOutput/datetime-simple/1965-10-31-0-dateComponents @@ -0,0 +1,4 @@ +Year: 1965 +Month: 10 +Date: 31 +Day of week: 0 \ No newline at end of file diff --git a/test/integrationTests/expectedOutput/datetime-simple/22_43_54-timeComponents b/test/integrationTests/expectedOutput/datetime-simple/22_43_54-timeComponents new file mode 100644 index 0000000..88fb6c6 --- /dev/null +++ b/test/integrationTests/expectedOutput/datetime-simple/22_43_54-timeComponents @@ -0,0 +1,3 @@ +Hour: 22 +Minute: 43 +Second: 54 \ No newline at end of file diff --git a/test/integrationTests/expectedOutput/datetime-zeropadding/04_05_06-timeComponents b/test/integrationTests/expectedOutput/datetime-zeropadding/04_05_06-timeComponents new file mode 100644 index 0000000..3032f11 --- /dev/null +++ b/test/integrationTests/expectedOutput/datetime-zeropadding/04_05_06-timeComponents @@ -0,0 +1,3 @@ +Hour: 04 +Minute: 05 +Second: 06 \ No newline at end of file diff --git a/test/integrationTests/expectedOutput/datetime-zeropadding/1-02-03-6-dateComponents b/test/integrationTests/expectedOutput/datetime-zeropadding/1-02-03-6-dateComponents new file mode 100644 index 0000000..36d4a9c --- /dev/null +++ b/test/integrationTests/expectedOutput/datetime-zeropadding/1-02-03-6-dateComponents @@ -0,0 +1,4 @@ +Year: 1 +Month: 02 +Date: 03 +Day of week: 6 \ No newline at end of file diff --git a/test/integrationTests/templates/datetime/__currentHour_____currentMin_____currentSec__-timeComponents b/test/integrationTests/templates/datetime/__currentHour_____currentMin_____currentSec__-timeComponents new file mode 100644 index 0000000..7fc1baf --- /dev/null +++ b/test/integrationTests/templates/datetime/__currentHour_____currentMin_____currentSec__-timeComponents @@ -0,0 +1,3 @@ +Hour: {{currentHour}} +Minute: {{currentMin}} +Second: {{currentSec}} \ No newline at end of file diff --git a/test/integrationTests/templates/datetime/__currentYear__-__currentMonth__-__currentDate__-__currentDay__-dateComponents b/test/integrationTests/templates/datetime/__currentYear__-__currentMonth__-__currentDate__-__currentDay__-dateComponents new file mode 100644 index 0000000..938d70d --- /dev/null +++ b/test/integrationTests/templates/datetime/__currentYear__-__currentMonth__-__currentDate__-__currentDay__-dateComponents @@ -0,0 +1,4 @@ +Year: {{currentYear}} +Month: {{currentMonth}} +Date: {{currentDate}} +Day of week: {{currentDay}} \ No newline at end of file From 5a628eee464a70b3fc0b90179dda5dbfc35cc332 Mon Sep 17 00:00:00 2001 From: kdhardin Date: Wed, 18 Dec 2019 16:34:41 -0700 Subject: [PATCH 3/4] Fixed lint errors. --- src/fileCreator/createFiles.ts | 2 +- src/fileCreator/transforms.ts | 44 +++++++++++++++++----------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/fileCreator/createFiles.ts b/src/fileCreator/createFiles.ts index ccb509c..8eb1394 100644 --- a/src/fileCreator/createFiles.ts +++ b/src/fileCreator/createFiles.ts @@ -10,7 +10,7 @@ import { IDynamicTemplateValues, IUserInput } from "../inputs"; import { getFolderNamesAtDirectory } from "../utilities/getTemplateFilesAndFolders"; import { getTemplateFileNamesAtTemplateDirectory } from "../utilities/getTemplateFilesAndFolders"; import { sanitizedName } from "./inputSanitizer"; -import { setCurrentDate, replaceStringUsingTransforms, replaceTemplateContent } from "./transforms"; +import { replaceStringUsingTransforms, replaceTemplateContent, setCurrentDate } from "./transforms"; export async function createFiles(userInput: IUserInput, inDirectory: string, date: Date): Promise { diff --git a/src/fileCreator/transforms.ts b/src/fileCreator/transforms.ts index 68e853e..9911e52 100644 --- a/src/fileCreator/transforms.ts +++ b/src/fileCreator/transforms.ts @@ -16,6 +16,27 @@ export function initializeHandlebars() { camelCase: (input) => { return _.camelCase(input); }, + currentDate: (input) => { + return getDayOfMonth(currentDate); + }, + currentDay: (input) => { + return getDay(currentDate); + }, + currentHour: (input) => { + return getHours(currentDate); + }, + currentMin: (input) => { + return getMinutes(currentDate); + }, + currentMonth: (input) => { + return getMonth(currentDate); + }, + currentSec: (input) => { + return getSeconds(currentDate); + }, + currentYear: (input) => { + return getYear(currentDate); + }, kebabCase: (input) => { return _.kebabCase(input); }, @@ -37,27 +58,6 @@ export function initializeHandlebars() { upperSnakeCase: (input) => { return _.snakeCase(input).toUpperCase(); }, - currentYear: (input) => { - return getYear(currentDate); - }, - currentMonth: (input) => { - return getMonth(currentDate); - }, - currentDate: (input) => { - return getDayOfMonth(currentDate); - }, - currentDay: (input) => { - return getDay(currentDate); - }, - currentHour: (input) => { - return getHours(currentDate); - }, - currentMin: (input) => { - return getMinutes(currentDate); - }, - currentSec: (input) => { - return getSeconds(currentDate); - }, }); } @@ -147,7 +147,7 @@ function getSeconds(date: Date): string { function padDateComponentToTwoChars(str: string): string { if (str.length < 2) { - str = '0' + str; + str = "0" + str; } return str; } From 5e216fa30f7282c083298299e10a9a14558d6d8d Mon Sep 17 00:00:00 2001 From: kdhardin Date: Tue, 24 Dec 2019 14:18:22 -0700 Subject: [PATCH 4/4] Updated CHANGELOG.md for new date/time insertion capabilities. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c0aa9b..ea45cb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +* Adds ability to insert current date/time into templates at the time of file creation. + ## [3.0.0 - 2019-01-02] * Adds ability to provide dynamic template replacements at the time of file creation