From af0d897020677cbd38d026e231bf5657f57cadbd Mon Sep 17 00:00:00 2001 From: 18alantom <2.alan.tom@gmail.com> Date: Sun, 17 Apr 2022 11:19:18 +0530 Subject: [PATCH] chore: type generateTranslations - shift csvParser to utils --- frappe/utils/translation.ts | 4 +- package.json | 2 +- ...ranslations.js => generateTranslations.ts} | 92 ++++++++++--------- src/dataImport.ts | 6 +- tsconfig.json | 8 +- {src => utils}/csvParser.ts | 0 .../helpers.js => utils/translationHelpers.ts | 47 +++++----- 7 files changed, 85 insertions(+), 74 deletions(-) rename scripts/{generateTranslations.js => generateTranslations.ts} (68%) rename {src => utils}/csvParser.ts (100%) rename scripts/helpers.js => utils/translationHelpers.ts (59%) diff --git a/frappe/utils/translation.ts b/frappe/utils/translation.ts index ccf5de0e..f9073504 100644 --- a/frappe/utils/translation.ts +++ b/frappe/utils/translation.ts @@ -4,7 +4,7 @@ import { getIndexList, getSnippets, getWhitespaceSanitized, -} from '../../scripts/helpers'; +} from '../../utils/translationHelpers'; import { ValueError } from './errors'; type TranslationArgs = boolean | number | string; @@ -35,7 +35,7 @@ class TranslationString { } #translate() { - let indexFormat = getIndexFormat(this.args[0]); + let indexFormat = getIndexFormat(this.args[0] as string); indexFormat = getWhitespaceSanitized(indexFormat); const translatedIndexFormat = diff --git a/package.json b/package.json index dae51cd5..de560894 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "electron:serve": "vue-cli-service electron:serve", "postinstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps", - "script:translate": "node scripts/generateTranslations.js", + "script:translate": "ts-node -O '{\"module\":\"commonjs\"}' scripts/generateTranslations.ts", "test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha --reporter nyan --require ts-node/register --require tsconfig-paths/register ./**/tests/**/*.spec.ts" }, "dependencies": { diff --git a/scripts/generateTranslations.js b/scripts/generateTranslations.ts similarity index 68% rename from scripts/generateTranslations.js rename to scripts/generateTranslations.ts index 602b4a71..c082efeb 100644 --- a/scripts/generateTranslations.js +++ b/scripts/generateTranslations.ts @@ -1,25 +1,29 @@ -const fs = require('fs/promises'); -const path = require('path'); -const { +import fs from 'fs/promises'; +import path from 'path'; +import { getIndexFormat, getWhitespaceSanitized, - wrap, splitCsvLine, -} = require('./helpers'); + wrap, +} from '../utils/translationHelpers'; const translationsFolder = path.resolve(__dirname, '..', 'translations'); const PATTERN = /(? { + const contents: string[] = await fs.readdir(root); + const files: string[] = []; + const promises: Promise[] = []; - for (let c of contents) { + for (const c of contents) { const absPath = path.resolve(root, c); const isDir = (await fs.stat(absPath)).isDirectory(); @@ -37,12 +41,12 @@ async function getFileList(root, ignoreList) { return files; } -async function getFileContents(fileList) { - const contents = []; - const promises = []; - for (let file of fileList) { - const pr = fs.readFile(file, { encoding: 'utf-8' }).then((c) => { - contents.push([file, c]); +async function getFileContents(fileList: string[]): Promise { + const contents: Content[] = []; + const promises: Promise[] = []; + for (const fileName of fileList) { + const pr = fs.readFile(fileName, { encoding: 'utf-8' }).then((content) => { + contents.push({ fileName, content }); }); promises.push(pr); } @@ -50,16 +54,18 @@ async function getFileContents(fileList) { return contents; } -async function getAllTStringsMap(contents) { - const strings = new Map(); - const promises = []; +async function getAllTStringsMap( + contents: Content[] +): Promise> { + const strings: Map = new Map(); + const promises: Promise[] = []; - contents.forEach(([f, c]) => { - const pr = getTStrings(c).then((ts) => { + contents.forEach(({ fileName, content }) => { + const pr = getTStrings(content).then((ts) => { if (ts.length === 0) { return; } - strings.set(f, ts); + strings.set(fileName, ts); }); promises.push(pr); }); @@ -68,24 +74,24 @@ async function getAllTStringsMap(contents) { return strings; } -function getTStrings(content) { +function getTStrings(content: string): Promise { return new Promise((resolve) => { const tStrings = tStringFinder(content); resolve(tStrings); }); } -function tStringFinder(content) { +function tStringFinder(content: string): string[] { return [...content.matchAll(PATTERN)].map(([_, t]) => { t = getIndexFormat(t); return getWhitespaceSanitized(t); }); } -function mapToTStringArray(tMap) { - const tSet = new Set(); - for (let k of tMap.keys()) { - tMap.get(k).forEach((s) => tSet.add(s)); +function mapToTStringArray(tMap: Map): string[] { + const tSet: Set = new Set(); + for (const k of tMap.keys()) { + tMap.get(k)!.forEach((s) => tSet.add(s)); } const tArray = [...tSet]; return tArray.sort(); @@ -129,14 +135,14 @@ function getLanguageCode() { return process.argv[i + 1] ?? ''; } -function getTranslationFilePath(languageCode) { +function getTranslationFilePath(languageCode: string) { return path.resolve(translationsFolder, `${languageCode}.csv`); } -async function regenerateTranslation(tArray, path) { +async function regenerateTranslation(tArray: string[], path: string) { // Removes old strings, adds new strings const contents = await fs.readFile(path, { encoding: 'utf-8' }); - const map = new Map(); + const map: Map = new Map(); // Populate map contents @@ -162,9 +168,9 @@ async function regenerateTranslation(tArray, path) { console.log(`\tregenerated: ${path}`); } -async function regenerateTranslations(languageCode, tArray) { +async function regenerateTranslations(languageCode: string, tArray: string[]) { // regenerate one file - if (languageCode) { + if (languageCode.length === 0) { const path = getTranslationFilePath(languageCode); regenerateTranslation(tArray, path); return; @@ -180,7 +186,7 @@ async function regenerateTranslations(languageCode, tArray) { ); } -async function writeTranslations(languageCode, tArray) { +async function writeTranslations(languageCode: string, tArray: string[]) { const path = getTranslationFilePath(languageCode); try { const stat = await fs.stat(path); @@ -194,7 +200,7 @@ async function writeTranslations(languageCode, tArray) { ); regenerateTranslations(languageCode, tArray); } catch (err) { - if (err.errno !== -2) { + if ((err as NodeJS.ErrnoException).code !== 'ENOENT') { throw err; } @@ -204,6 +210,8 @@ async function writeTranslations(languageCode, tArray) { } } +type Content = { fileName: string; content: string }; + async function run() { if (printHelp()) { return; @@ -214,15 +222,15 @@ async function run() { const languageCode = getLanguageCode(); console.log(); - const fileList = await getFileList(root, ignoreList); - const contents = await getFileContents(fileList); - const tMap = await getAllTStringsMap(contents); - const tArray = mapToTStringArray(tMap); + const fileList: string[] = await getFileList(root, ignoreList); + const contents: Content[] = await getFileContents(fileList); + const tMap: Map = await getAllTStringsMap(contents); + const tArray: string[] = mapToTStringArray(tMap); try { await fs.stat(translationsFolder); } catch (err) { - if (err.errno !== -2) { + if ((err as NodeJS.ErrnoException).code !== 'ENOENT') { throw err; } diff --git a/src/dataImport.ts b/src/dataImport.ts index 2c6e72dc..ab18f3b7 100644 --- a/src/dataImport.ts +++ b/src/dataImport.ts @@ -3,7 +3,7 @@ import { DocValueMap } from 'frappe/core/types'; import Doc from 'frappe/model/doc'; import { isNameAutoSet } from 'frappe/model/naming'; import { FieldType, FieldTypeEnum } from 'schemas/types'; -import { parseCSV } from './csvParser'; +import { parseCSV } from '../utils/csvParser'; import telemetry from './telemetry/telemetry'; import { Noun, Verb } from './telemetry/types'; @@ -426,11 +426,11 @@ export class Importer { } handleError(doc: Doc, err: Error, status: Status): Status { - const messages = [frappe.t`Could not import ${this.doctype} ${doc.name}.`]; + const messages = [frappe.t`Could not import ${this.doctype} ${doc.name!}.`]; const message = err.message; if (message?.includes('UNIQUE constraint failed')) { - messages.push(frappe.t`${doc.name} already exists.`); + messages.push(frappe.t`${doc.name!} already exists.`); } else if (message) { messages.push(message); } diff --git a/tsconfig.json b/tsconfig.json index e3a8ea0f..eb9a7256 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,9 @@ }, "lib": ["esnext", "dom", "dom.iterable", "scripthost"] }, + "ts-node": { + "files": true + }, "include": [ "src/**/*.ts", "src/**/*.tsx", @@ -37,7 +40,10 @@ "patches/**/*.js", "reports/**/*.ts", "accounting/**/*.ts", - "accounting/**/*.ts" + "accounting/**/*.ts", + + "scripts/**/*.ts", + "utils/csvParser.ts" ], "exclude": ["node_modules"] } diff --git a/src/csvParser.ts b/utils/csvParser.ts similarity index 100% rename from src/csvParser.ts rename to utils/csvParser.ts diff --git a/scripts/helpers.js b/utils/translationHelpers.ts similarity index 59% rename from scripts/helpers.js rename to utils/translationHelpers.ts index f84523f5..a028ef6b 100644 --- a/scripts/helpers.js +++ b/utils/translationHelpers.ts @@ -1,9 +1,11 @@ -function getIndexFormat(inp) { +export function getIndexFormat(inp: string | string[]) { // converts: // ['This is an ', ,' interpolated ',' string.'] and // 'This is an ${variableA} interpolated ${variableB} string.' // to 'This is an ${0} interpolated ${1} string.' - let string, snippets; + let string: string | undefined = undefined; + let snippets: string[] | undefined = undefined; + if (typeof inp === 'string') { string = inp; } else if (inp instanceof Array) { @@ -13,7 +15,7 @@ function getIndexFormat(inp) { } if (snippets === undefined) { - snippets = getSnippets(string); + snippets = getSnippets(string as string); } if (snippets.length === 1) { @@ -22,41 +24,45 @@ function getIndexFormat(inp) { let str = ''; snippets.forEach((s, i) => { - if (i === snippets.length - 1) { + if (i === snippets!.length - 1) { str += s; return; } str += s + '${' + i + '}'; }); + return str; } -function getSnippets(string) { +export function getSnippets(str: string) { let start = 0; - const snippets = [...string.matchAll(/\${[^}]+}/g)].map((m) => { - let end = m.index; - let snip = string.slice(start, end); + const snippets = [...str.matchAll(/\${[^}]+}/g)].map((m) => { + const end = m.index; + if (end === undefined) { + return ''; + } + const snip = str.slice(start, end); start = end + m[0].length; return snip; }); - snippets.push(string.slice(start)); + snippets.push(str.slice(start)); return snippets; } -function getWhitespaceSanitized(s) { - return s.replace(/\s+/g, ' ').trim(); +export function getWhitespaceSanitized(str: string) { + return str.replace(/\s+/g, ' ').trim(); } -function getIndexList(s) { - return [...s.matchAll(/\${([^}]+)}/g)].map(([_, i]) => parseInt(i)); +export function getIndexList(str: string) { + return [...str.matchAll(/\${([^}]+)}/g)].map(([_, i]) => parseInt(i)); } -function wrap(s) { - return '`' + s + '`'; +export function wrap(str: string) { + return '`' + str + '`'; } -function splitCsvLine(line) { +export function splitCsvLine(line: string) { let t = true; const chars = [...line]; const indices = chars @@ -82,12 +88,3 @@ function splitCsvLine(line) { splits.push(line.slice(s).trim()); return splits.filter((s) => s !== ',' && s !== ''); } - -module.exports = { - getIndexFormat, - getWhitespaceSanitized, - getSnippets, - getIndexList, - wrap, - splitCsvLine, -};