From 111e84870951381d312add98b85b53a948467992 Mon Sep 17 00:00:00 2001 From: Vitaly Zakutny Date: Wed, 22 Nov 2023 00:07:40 +0300 Subject: [PATCH 1/3] chore: refactor modified functions, utils and tests --- packages/xml-locales/src/modifiers/add.ts | 91 +++---------- packages/xml-locales/src/modifiers/change.ts | 83 +++--------- packages/xml-locales/src/modifiers/delete.ts | 82 +++--------- packages/xml-locales/src/modifiers/sort.ts | 27 ++-- packages/xml-locales/src/utils/files.ts | 126 ------------------ packages/xml-locales/src/utils/helpers.ts | 61 +++++++++ packages/xml-locales/src/utils/index.ts | 5 +- packages/xml-locales/src/utils/types.ts | 38 ++++++ packages/xml-locales/src/utils/xml.ts | 75 ----------- .../tests/mock/locales/strings-en.xml | 7 - .../tests/mock/locales/strings.xml | 7 - packages/xml-locales/tests/utils.test.ts | 22 +-- 12 files changed, 175 insertions(+), 449 deletions(-) delete mode 100644 packages/xml-locales/src/utils/files.ts create mode 100644 packages/xml-locales/src/utils/helpers.ts delete mode 100644 packages/xml-locales/src/utils/xml.ts delete mode 100644 packages/xml-locales/tests/mock/locales/strings-en.xml delete mode 100644 packages/xml-locales/tests/mock/locales/strings.xml diff --git a/packages/xml-locales/src/modifiers/add.ts b/packages/xml-locales/src/modifiers/add.ts index b03bff2..806e555 100644 --- a/packages/xml-locales/src/modifiers/add.ts +++ b/packages/xml-locales/src/modifiers/add.ts @@ -1,79 +1,30 @@ -import { checkKeyExist, replaceValue } from '../utils/files.js'; -// import { hasConflict } from '../../../cli/src/utils/queries.js'; +import { checkKeyExist, replaceValue } from '../utils/helpers.js'; import { sort } from './sort.js'; -import type { XmlJson } from '../utils/types.js'; +import type { AddOptions } from '../utils/types.js'; -export function add(options: { - key: string; - value: string; - directory: string; - sort?: 'asc' | 'desc'; - accept: boolean; -}) { - let REPLACE_ALL = false; - let NEED_REPLACE = false; +export function add({ key, value, sortDirection, jsonXml }: AddOptions) { + const { + resources: { string } + } = jsonXml; - return async function ({ - filePath, - jsonXml - }: { - filePath: string; - jsonXml: XmlJson; - }) { - const { key, value, sort: sortDirection, accept } = options; + const hasKey = checkKeyExist(key, string); - if (accept) { - REPLACE_ALL = true; - } + if (hasKey) { + const replacedStrings = replaceValue(string, key, value); - const { - resources: { string } - } = jsonXml; + jsonXml.resources.string = replacedStrings; + } - const hasKey = checkKeyExist(key, string); + if (!hasKey) { + jsonXml.resources.string.push({ + key_name: key, + '#text': value + }); + } - // if (!REPLACE_ALL && hasKey) { - // const answer = await hasConflict(filePath); + if (sortDirection) { + sort({ sortDirection, jsonXml }); + } - // switch (answer) { - // case 'yes': { - // NEED_REPLACE = true; - // break; - // } - // case 'all': { - // REPLACE_ALL = true; - // break; - // } - // case 'skip': { - // NEED_REPLACE = false; - // break; - // } - - // default: - // console.log('Cancelled'); - // return; - // } - // } - - const needReplace = REPLACE_ALL || NEED_REPLACE; - - if (needReplace) { - const replacedStrings = replaceValue(string, key, value); - - jsonXml.resources.string = replacedStrings; - } - - if (!hasKey) { - jsonXml.resources.string.push({ - key_name: key, - '#text': value - }); - } - - if (sortDirection) { - sort({ direction: sortDirection })({ jsonXml }); - } - - return jsonXml; - }; + return jsonXml; } diff --git a/packages/xml-locales/src/modifiers/change.ts b/packages/xml-locales/src/modifiers/change.ts index afaf9e3..6e583ee 100644 --- a/packages/xml-locales/src/modifiers/change.ts +++ b/packages/xml-locales/src/modifiers/change.ts @@ -1,71 +1,28 @@ -import { checkKeyValueExist, replace } from '../utils/files.js'; -// import { hasConflict } from '../../../cli/src/utils/queries.js'; +import { checkKeyValueExist, replace } from '../utils/helpers.js'; import { sort } from './sort.js'; -import type { XmlJson } from '../utils/types.js'; +import type { ChangeOptions } from '../utils/types.js'; -export function change(options: { - oldKey: string; - newKey: string; - sort?: 'asc' | 'desc'; - accept: boolean; -}) { - let REPLACE_ALL = false; - let NEED_REPLACE = false; +export function change({ + oldKey, + newKey, + sortDirection, + jsonXml +}: ChangeOptions) { + const { + resources: { string } + } = jsonXml; - return async function ({ - filePath, - jsonXml - }: { - filePath: string; - jsonXml: XmlJson; - }) { - const { oldKey, newKey, sort: sortDirection, accept } = options; + const hasKey = checkKeyValueExist(oldKey, string); - if (accept) { - REPLACE_ALL = true; - } + if (hasKey) { + const replacedStrings = replace(string, oldKey, newKey); - const { - resources: { string } - } = jsonXml; + jsonXml.resources.string = replacedStrings; + } - const hasKey = checkKeyValueExist(oldKey, string); + if (sortDirection) { + sort({ sortDirection, jsonXml }); + } - // if (!REPLACE_ALL && hasKey) { - // const answer = await hasConflict(filePath); - - // switch (answer) { - // case 'yes': { - // NEED_REPLACE = true; - // break; - // } - // case 'all': { - // REPLACE_ALL = true; - // break; - // } - // case 'skip': { - // NEED_REPLACE = false; - // break; - // } - - // default: - // console.log('Cancelled'); - // return; - // } - // } - - const needReplace = REPLACE_ALL || NEED_REPLACE; - - if (needReplace) { - const replacedStrings = replace(string, oldKey, newKey); - - jsonXml.resources.string = replacedStrings; - } - - if (sortDirection) { - sort({ direction: sortDirection })({ jsonXml }); - } - - return jsonXml; - }; + return jsonXml; } diff --git a/packages/xml-locales/src/modifiers/delete.ts b/packages/xml-locales/src/modifiers/delete.ts index 58179e4..0cc13ec 100644 --- a/packages/xml-locales/src/modifiers/delete.ts +++ b/packages/xml-locales/src/modifiers/delete.ts @@ -1,72 +1,26 @@ -// import { checkKeyValueExist } from '../utils/files.js'; -// import { deleteAnswer } from '../../../cli/src/utils/queries.js'; +import { checkKeyValueExist } from '../utils/helpers.js'; import { sort } from './sort.js'; -import type { XmlJson } from '../utils/types.js'; +import type { DeleteOptions } from '../utils/types.js'; -export function del(options: { - keyValue: string; - sort?: 'asc' | 'desc'; - accept: boolean; -}) { - let DELETE_ALL = false; - let NEED_DELETE = false; +export function del({ keyValue, sort: sortDirection, jsonXml }: DeleteOptions) { + const { + resources: { string } + } = jsonXml; - return async function delString({ - filePath, - jsonXml - }: { - filePath: string; - jsonXml: XmlJson; - }) { - const { keyValue, sort: sortDirection, accept } = options; + const hasKeyValue = checkKeyValueExist(keyValue, string); - if (accept) { - DELETE_ALL = true; - } + if (hasKeyValue) { + const filteredStrings = string.filter( + (element) => + element['#text'] !== keyValue && element.key_name !== keyValue + ); - const { - resources: { string } - } = jsonXml; + jsonXml.resources.string = filteredStrings; + } - // const hasKeyValue = checkKeyValueExist(keyValue, string); - // if (!accept && !DELETE_ALL && hasKeyValue) { - // const answer = await deleteAnswer(filePath); + if (sortDirection) { + sort({ sortDirection, jsonXml }); + } - // switch (answer) { - // case 'yes': { - // NEED_DELETE = true; - // break; - // } - // case 'all': { - // DELETE_ALL = true; - // break; - // } - // case 'skip': { - // NEED_DELETE = false; - // break; - // } - - // default: - // console.log('Cancelled'); - // return; - // } - // } - - const needDelete = DELETE_ALL || NEED_DELETE; - - if (needDelete) { - const filteredStrings = string.filter( - (element) => - element['#text'] !== keyValue && element.key_name !== keyValue - ); - - jsonXml.resources.string = filteredStrings; - } - - if (sortDirection) { - sort({ direction: sortDirection })({ jsonXml }); - } - - return jsonXml; - }; + return jsonXml; } diff --git a/packages/xml-locales/src/modifiers/sort.ts b/packages/xml-locales/src/modifiers/sort.ts index f5d8c51..532b4a1 100644 --- a/packages/xml-locales/src/modifiers/sort.ts +++ b/packages/xml-locales/src/modifiers/sort.ts @@ -1,9 +1,10 @@ -import type { StringElement, XmlJson } from '../utils/types.js'; +import type { + SortDirection, + SortOptions, + StringElement +} from '../utils/types.js'; -export function sortBy( - strElements: StringElement[], - direction: 'asc' | 'desc' -) { +export function sortBy(strElements: StringElement[], direction: SortDirection) { const { compare } = new Intl.Collator(); const compareFn = (a: StringElement, b: StringElement) => { @@ -19,15 +20,13 @@ export function sortBy( return sortedElements; } -export function sort({ direction }: { direction: 'asc' | 'desc' }) { - return function ({ jsonXml }: { jsonXml: XmlJson }) { - const { - resources: { string } - } = jsonXml; +export function sort({ sortDirection, jsonXml }: SortOptions) { + const { + resources: { string } + } = jsonXml; - const sortedString = sortBy(string, direction); - jsonXml.resources.string = sortedString; + const sortedString = sortBy(string, sortDirection); + jsonXml.resources.string = sortedString; - return jsonXml; - }; + return jsonXml; } diff --git a/packages/xml-locales/src/utils/files.ts b/packages/xml-locales/src/utils/files.ts deleted file mode 100644 index 54be924..0000000 --- a/packages/xml-locales/src/utils/files.ts +++ /dev/null @@ -1,126 +0,0 @@ -import fs from 'node:fs'; -import { readFile } from 'node:fs/promises'; -import path from 'node:path'; - -import { Xml } from './xml.js'; -import type { StringElement, XmlJson } from './types.js'; - -export function getFilesFromDir(dirName: string) { - return new Promise((resolve, reject) => { - fs.readdir(dirName, (err, files) => { - if (err) { - reject(err); - return; - } - - const allFileIsXML = files.every((file) => file.endsWith('xml')); - - if (!allFileIsXML) { - reject('Not all files have *.xml extension'); - return; - } - resolve(files); - }); - }); -} - -export function checkKeyExist(key: string, strElements: StringElement[]) { - return strElements.find( - ({ key_name }: { key_name: string }) => key_name === key - ); -} - -export function checkKeyValueExist( - keyValue: string, - strElement: StringElement[] -) { - return strElement.find( - (element) => element['#text'] === keyValue || element.key_name === keyValue - ); -} - -export function replaceValue( - strElements: StringElement[], - key: string, - newValue: string -) { - const replacedStrings = strElements.map((element) => { - if (element.key_name === key) { - return { - ...element, - '#text': newValue - }; - } - - return element; - }); - - return replacedStrings; -} - -export function replace( - strElements: StringElement[], - oldKeyValue: string, - newKeyValue: string -) { - const replaced = strElements.map((element) => { - if (element.key_name === oldKeyValue) { - return { - ...element, - key_name: newKeyValue - }; - } - - if (element['#text'] === oldKeyValue) { - return { - ...element, - '#text': newKeyValue - }; - } - - return element; - }); - - return replaced; -} - -export async function modificationFile( - callback: ({ - filePath, - jsonXml - }: { - filePath: string; - jsonXml: XmlJson; - }) => Promise | XmlJson, - directory: string = './' -) { - try { - const files = await getFilesFromDir(directory); - - for (const fileName of files) { - const xml = new Xml(); - - const filePath = path.join(directory, fileName); - const fileData = await readFile(filePath, 'utf-8'); - - const jsonXml = xml.xmlToJson(fileData); - - const modifiedJson = await callback({ filePath, jsonXml }); - - if (!modifiedJson) { - throw Error('Error during file modified'); - } - const xmlString = xml.jsonToXml(modifiedJson); - - fs.writeFile(filePath, xmlString, (err) => { - if (err) { - console.log(`Error at write file ${fileName}`); - - return; - } - }); - } - } catch (e) { - console.log(e); - } -} diff --git a/packages/xml-locales/src/utils/helpers.ts b/packages/xml-locales/src/utils/helpers.ts new file mode 100644 index 0000000..9deabfe --- /dev/null +++ b/packages/xml-locales/src/utils/helpers.ts @@ -0,0 +1,61 @@ +import type { StringElement } from './types.js'; + +export function checkKeyExist(key: string, strElements: StringElement[]) { + return strElements.find( + ({ key_name }: { key_name: string }) => key_name === key + ); +} + +export function checkKeyValueExist( + keyValue: string, + strElement: StringElement[] +) { + return strElement.find( + (element) => element['#text'] === keyValue || element.key_name === keyValue + ); +} + +export function replaceValue( + strElements: StringElement[], + key: string, + newValue: string +) { + const replacedStrings = strElements.map((element) => { + if (element.key_name === key) { + return { + ...element, + '#text': newValue + }; + } + + return element; + }); + + return replacedStrings; +} + +export function replace( + strElements: StringElement[], + oldKeyValue: string, + newKeyValue: string +) { + const replaced = strElements.map((element) => { + if (element.key_name === oldKeyValue) { + return { + ...element, + key_name: newKeyValue + }; + } + + if (element['#text'] === oldKeyValue) { + return { + ...element, + '#text': newKeyValue + }; + } + + return element; + }); + + return replaced; +} diff --git a/packages/xml-locales/src/utils/index.ts b/packages/xml-locales/src/utils/index.ts index aac0983..93fa190 100644 --- a/packages/xml-locales/src/utils/index.ts +++ b/packages/xml-locales/src/utils/index.ts @@ -1,3 +1,2 @@ -export * from './files.js'; -export * from './xml.js'; -export * from './types.js'; +export * from './helpers.js'; +export type * from './types.js'; diff --git a/packages/xml-locales/src/utils/types.ts b/packages/xml-locales/src/utils/types.ts index af90d2b..3aa2dd4 100644 --- a/packages/xml-locales/src/utils/types.ts +++ b/packages/xml-locales/src/utils/types.ts @@ -8,3 +8,41 @@ export interface XmlJson { string: StringElement[]; }; } + +export interface RawXmlJson { + resources: { + string: StringElement | StringElement[]; + }; +} + +export type SortDirection = 'asc' | 'desc'; + +export interface BaseOptions { + jsonXml: XmlJson; + sortDirection?: SortDirection; +} + +export interface AddOptions extends BaseOptions { + key: string; + value: string; +} + +export interface DeleteOptions extends BaseOptions { + keyValue: string; + sort?: SortDirection; +} + +export interface ChangeOptions extends BaseOptions { + oldKey: string; + newKey: string; +} + +export interface SortOptions extends BaseOptions { + sortDirection: SortDirection; +} + +export type ModifierOptions = + | AddOptions + | DeleteOptions + | ChangeOptions + | SortOptions; diff --git a/packages/xml-locales/src/utils/xml.ts b/packages/xml-locales/src/utils/xml.ts deleted file mode 100644 index af65384..0000000 --- a/packages/xml-locales/src/utils/xml.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { XMLBuilder, XMLParser } from 'fast-xml-parser'; -import xmlFormatter from 'xml-formatter'; -import type { - X2jOptionsOptional, - XmlBuilderOptionsOptional -} from 'fast-xml-parser'; -import type { XMLFormatterOptions } from 'xml-formatter'; - -import type { XmlJson } from './types.js'; - -interface XmlConstructor { - parserOptions?: X2jOptionsOptional; - builderOptions?: XmlBuilderOptionsOptional; - formateOptions?: XMLFormatterOptions; -} - -const defaultParserOptions: X2jOptionsOptional = { - trimValues: true, - ignoreDeclaration: true, - attributeNamePrefix: 'key_', - alwaysCreateTextNode: true, - ignoreAttributes: false -}; - -const defaultBuilderOptions: XmlBuilderOptionsOptional = { - ignoreAttributes: false, - attributeNamePrefix: 'key_' -}; - -const defaultFormatterOptions: XMLFormatterOptions = { - collapseContent: true, - indentation: ' ' -}; - -const defaultXmlOptions: XmlConstructor = { - parserOptions: defaultParserOptions, - builderOptions: defaultBuilderOptions, - formateOptions: defaultFormatterOptions -}; - -export class Xml { - private parser: XMLParser; - private builder: XMLBuilder; - private formatter: (xmlString: string) => string; - - constructor(xmlOptions?: XmlConstructor) { - const { parserOptions, builderOptions, formateOptions } = { - ...(xmlOptions || {}), - ...defaultXmlOptions - }; - - this.parser = new XMLParser(parserOptions); - this.builder = new XMLBuilder(builderOptions); - this.formatter = (xmlString: string) => - xmlFormatter(xmlString, formateOptions); - } - - xmlToJson(xmlData: string): XmlJson { - return this.parser.parse(xmlData); - } - - jsonToXml(xmlJson: XmlJson, needFormate: boolean = true): string { - const xmlString = this.builder.build(xmlJson); - - if (needFormate) { - return this.formate(xmlString); - } - - return xmlString; - } - - formate(xmlString: string): string { - return this.formatter(xmlString); - } -} diff --git a/packages/xml-locales/tests/mock/locales/strings-en.xml b/packages/xml-locales/tests/mock/locales/strings-en.xml deleted file mode 100644 index 2ea6e6b..0000000 --- a/packages/xml-locales/tests/mock/locales/strings-en.xml +++ /dev/null @@ -1,7 +0,0 @@ - - Enter - Camera or layout name - Search by name - Frame - vvv - \ No newline at end of file diff --git a/packages/xml-locales/tests/mock/locales/strings.xml b/packages/xml-locales/tests/mock/locales/strings.xml deleted file mode 100644 index 2ea6e6b..0000000 --- a/packages/xml-locales/tests/mock/locales/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - Enter - Camera or layout name - Search by name - Frame - vvv - \ No newline at end of file diff --git a/packages/xml-locales/tests/utils.test.ts b/packages/xml-locales/tests/utils.test.ts index 4baf48a..9475b05 100644 --- a/packages/xml-locales/tests/utils.test.ts +++ b/packages/xml-locales/tests/utils.test.ts @@ -1,34 +1,16 @@ -import path from 'node:path'; import { describe, expect, test } from 'vitest'; import { checkKeyExist, checkKeyValueExist, - getFilesFromDir, replace, replaceValue -} from '../src/utils/files'; +} from '../src/utils/helpers.js'; import { REPLACED_KEY_ELEMENTS, REPLACED_VALUE_ELEMENTS, STRING_ELEMENTS -} from './mock/data/stringElements'; - -const __dirname = new URL('.', import.meta.url).pathname; - -describe('Get xml files path', () => { - test('Files in mock folder', async () => { - const paths = await getFilesFromDir( - path.resolve(__dirname, 'mock', 'locales') - ); - expect(paths).toMatchObject(['strings-en.xml', 'strings.xml']); - }); - - test('Folder have not xml files', async () => { - const paths = getFilesFromDir(path.resolve(__dirname, '..', 'src')); - expect(paths).rejects.toThrow('Not all files have *.xml extension'); - }); -}); +} from './mock/data/stringElements.js'; describe('checkKeyExist', () => { test('has key', () => { From 6691ad3b63c81c801c4a0816d30e0df63eba7fd1 Mon Sep 17 00:00:00 2001 From: Vitaly Zakutny Date: Wed, 22 Nov 2023 00:12:39 +0300 Subject: [PATCH 2/3] chore: delete unused packages from core package --- packages/xml-locales/package.json | 4 ---- pnpm-lock.yaml | 15 +++++++-------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/xml-locales/package.json b/packages/xml-locales/package.json index c855854..bdb173d 100644 --- a/packages/xml-locales/package.json +++ b/packages/xml-locales/package.json @@ -33,9 +33,5 @@ "build": "tsup", "test": "vitest run --coverage", "test:watch": "vitest --ui --watch --coverage" - }, - "dependencies": { - "fast-xml-parser": "4.3.2", - "xml-formatter": "3.6.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce2b345..7c1fe8b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,12 @@ importers: '@types/yargs': specifier: 17.0.32 version: 17.0.32 + fast-xml-parser: + specifier: ^4.3.2 + version: 4.3.2 + xml-formatter: + specifier: ^3.6.0 + version: 3.6.0 xml-locales: specifier: workspace:0.0.2 version: link:../xml-locales @@ -57,14 +63,7 @@ importers: specifier: 17.7.2 version: 17.7.2 - packages/xml-locales: - dependencies: - fast-xml-parser: - specifier: 4.3.2 - version: 4.3.2 - xml-formatter: - specifier: 3.6.0 - version: 3.6.0 + packages/xml-locales: {} packages: From 6b531c7c48f7035e7fb3b3cce0139f6b6f0cef01 Mon Sep 17 00:00:00 2001 From: Vitaly Zakutny Date: Wed, 22 Nov 2023 00:19:46 +0300 Subject: [PATCH 3/3] bump versions --- packages/cli/CHANGELOG.md | 7 +++++++ packages/cli/package.json | 6 ++++-- packages/xml-locales/CHANGELOG.md | 6 ++++++ packages/xml-locales/package.json | 2 +- pnpm-lock.yaml | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 945383d..fc772a1 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,12 @@ # @xml-locales/cli +## 0.0.5 + +### Patch Changes + +- Updated dependencies + - xml-locales@0.0.3 + ## 0.0.4 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 1c3e0e9..0dc53ba 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@xml-locales/cli", - "version": "0.0.4", + "version": "0.0.5", "type": "module", "bin": { "xml-locales": "./dist/bin.js" @@ -28,7 +28,9 @@ "dependencies": { "@inquirer/prompts": "3.3.0", "@types/yargs": "17.0.32", - "xml-locales": "workspace:0.0.2", + "fast-xml-parser": "^4.3.2", + "xml-formatter": "^3.6.0", + "xml-locales": "workspace:0.0.3", "yargs": "17.7.2" } } diff --git a/packages/xml-locales/CHANGELOG.md b/packages/xml-locales/CHANGELOG.md index 5e613f1..18fd83b 100644 --- a/packages/xml-locales/CHANGELOG.md +++ b/packages/xml-locales/CHANGELOG.md @@ -1,5 +1,11 @@ # xml-locales +## 0.0.3 + +### Patch Changes + +- refactor modifiers functions, utils and tests + ## 0.0.2 ### Patch Changes diff --git a/packages/xml-locales/package.json b/packages/xml-locales/package.json index bdb173d..3d19d5c 100644 --- a/packages/xml-locales/package.json +++ b/packages/xml-locales/package.json @@ -1,7 +1,7 @@ { "name": "xml-locales", "description": "Tool for locales in xml files", - "version": "0.0.2", + "version": "0.0.3", "type": "module", "keywords": [ "xml-locales", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c1fe8b..d58f7e4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,7 +57,7 @@ importers: specifier: ^3.6.0 version: 3.6.0 xml-locales: - specifier: workspace:0.0.2 + specifier: workspace:0.0.3 version: link:../xml-locales yargs: specifier: 17.7.2