@rushstack/localization-utilities 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,9 +45,21 @@ export declare interface IParseFileOptions {
45
45
  /**
46
46
  * @public
47
47
  */
48
- export declare interface IParseLocFileOptions extends IParseFileOptions {
49
- terminal: ITerminal;
48
+ export declare interface IParseLocFileOptions extends IParseFileOptions, IParseResxOptionsBase {
50
49
  parser?: ParserKind;
50
+ }
51
+
52
+ /**
53
+ * @public
54
+ */
55
+ export declare interface IParseResxOptions extends IParseFileOptions, IParseResxOptionsBase {
56
+ }
57
+
58
+ /**
59
+ * @public
60
+ */
61
+ export declare interface IParseResxOptionsBase {
62
+ terminal: ITerminal;
51
63
  resxNewlineNormalization: NewlineKind | undefined;
52
64
  ignoreMissingResxComments: boolean | undefined;
53
65
  }
@@ -71,6 +83,10 @@ export declare interface IPseudolocaleOptions {
71
83
  }
72
84
 
73
85
  /**
86
+ * @deprecated
87
+ *
88
+ * This has superseded by {@link IParseResxOptions}
89
+ *
74
90
  * @public
75
91
  */
76
92
  export declare interface IResxReaderOptions {
@@ -115,17 +131,30 @@ export declare function parseLocJson({ content, filePath, ignoreString }: IParse
115
131
  */
116
132
  export declare function parseResJson({ content, ignoreString, filePath }: IParseFileOptions): ILocalizationFile;
117
133
 
134
+ /**
135
+ * @public
136
+ */
137
+ export declare function parseResx(options: IParseResxOptions): ILocalizationFile;
138
+
118
139
  /**
119
140
  * @public
120
141
  */
121
142
  export declare type ParserKind = 'resx' | 'loc.json' | 'resjson';
122
143
 
123
144
  /**
145
+ * @deprecated
146
+ *
147
+ * Use {@link parseResx} instead.
148
+ *
124
149
  * @public
125
150
  */
126
151
  export declare function readResxAsLocFile(resxContents: string, options: IResxReaderOptions): ILocalizationFile;
127
152
 
128
153
  /**
154
+ * @deprecated
155
+ *
156
+ * Use {@link parseResx} instead.
157
+ *
129
158
  * @public
130
159
  */
131
160
  export declare function readResxFileAsLocFile(options: IResxReaderOptions): ILocalizationFile;
@@ -1,6 +1,10 @@
1
1
  import { ITerminal, NewlineKind } from '@rushstack/node-core-library';
2
- import type { ILocalizationFile, IgnoreStringFunction } from './interfaces';
2
+ import type { IgnoreStringFunction, ILocalizationFile } from './interfaces';
3
3
  /**
4
+ * @deprecated
5
+ *
6
+ * This has superseded by {@link IParseResxOptions}
7
+ *
4
8
  * @public
5
9
  */
6
10
  export interface IResxReaderOptions {
@@ -15,11 +19,19 @@ export interface IResxReaderOptions {
15
19
  ignoreString?: IgnoreStringFunction;
16
20
  }
17
21
  /**
22
+ * @deprecated
23
+ *
24
+ * Use {@link parseResx} instead.
25
+ *
18
26
  * @public
19
27
  */
20
28
  export declare function readResxFileAsLocFile(options: IResxReaderOptions): ILocalizationFile;
21
29
  /**
30
+ * @deprecated
31
+ *
32
+ * Use {@link parseResx} instead.
33
+ *
22
34
  * @public
23
35
  */
24
36
  export declare function readResxAsLocFile(resxContents: string, options: IResxReaderOptions): ILocalizationFile;
25
- //# sourceMappingURL=ResxReader.d.ts.map
37
+ //# sourceMappingURL=LegacyResxReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegacyResxReader.d.ts","sourceRoot":"","sources":["../src/LegacyResxReader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,SAAS,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAElF,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG5E;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,oBAAoB,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9C,oBAAoB,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CASpF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAQtG"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.readResxAsLocFile = exports.readResxFileAsLocFile = void 0;
6
+ const node_core_library_1 = require("@rushstack/node-core-library");
7
+ const parseResx_1 = require("./parsers/parseResx");
8
+ /**
9
+ * @deprecated
10
+ *
11
+ * Use {@link parseResx} instead.
12
+ *
13
+ * @public
14
+ */
15
+ function readResxFileAsLocFile(options) {
16
+ const content = node_core_library_1.FileSystem.readFile(options.resxFilePath);
17
+ return (0, parseResx_1.parseResx)({
18
+ ...options,
19
+ content,
20
+ filePath: options.resxFilePath,
21
+ resxNewlineNormalization: options.newlineNormalization,
22
+ ignoreMissingResxComments: !options.warnOnMissingComment
23
+ });
24
+ }
25
+ exports.readResxFileAsLocFile = readResxFileAsLocFile;
26
+ /**
27
+ * @deprecated
28
+ *
29
+ * Use {@link parseResx} instead.
30
+ *
31
+ * @public
32
+ */
33
+ function readResxAsLocFile(resxContents, options) {
34
+ return (0, parseResx_1.parseResx)({
35
+ ...options,
36
+ content: resxContents,
37
+ filePath: options.resxFilePath,
38
+ resxNewlineNormalization: options.newlineNormalization,
39
+ ignoreMissingResxComments: !options.warnOnMissingComment
40
+ });
41
+ }
42
+ exports.readResxAsLocFile = readResxAsLocFile;
43
+ //# sourceMappingURL=LegacyResxReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegacyResxReader.js","sourceRoot":"","sources":["../src/LegacyResxReader.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAkF;AAGlF,mDAAgD;AAqBhD;;;;;;GAMG;AACH,SAAgB,qBAAqB,CAAC,OAA2B;IAC/D,MAAM,OAAO,GAAW,8BAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAClE,OAAO,IAAA,qBAAS,EAAC;QACf,GAAG,OAAO;QACV,OAAO;QACP,QAAQ,EAAE,OAAO,CAAC,YAAY;QAC9B,wBAAwB,EAAE,OAAO,CAAC,oBAAoB;QACtD,yBAAyB,EAAE,CAAC,OAAO,CAAC,oBAAoB;KACzD,CAAC,CAAC;AACL,CAAC;AATD,sDASC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,YAAoB,EAAE,OAA2B;IACjF,OAAO,IAAA,qBAAS,EAAC;QACf,GAAG,OAAO;QACV,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,OAAO,CAAC,YAAY;QAC9B,wBAAwB,EAAE,OAAO,CAAC,oBAAoB;QACtD,yBAAyB,EAAE,CAAC,OAAO,CAAC,oBAAoB;KACzD,CAAC,CAAC;AACL,CAAC;AARD,8CAQC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { FileSystem, ITerminal, NewlineKind } from '@rushstack/node-core-library';\n\nimport type { IgnoreStringFunction, ILocalizationFile } from './interfaces';\nimport { parseResx } from './parsers/parseResx';\n\n/**\n * @deprecated\n *\n * This has superseded by {@link IParseResxOptions}\n *\n * @public\n */\nexport interface IResxReaderOptions {\n resxFilePath: string;\n terminal: ITerminal;\n newlineNormalization: NewlineKind | undefined;\n warnOnMissingComment: boolean;\n /**\n * Optionally, provide a function that will be called for each string. If the function returns `true`\n * the string will not be included.\n */\n ignoreString?: IgnoreStringFunction;\n}\n\n/**\n * @deprecated\n *\n * Use {@link parseResx} instead.\n *\n * @public\n */\nexport function readResxFileAsLocFile(options: IResxReaderOptions): ILocalizationFile {\n const content: string = FileSystem.readFile(options.resxFilePath);\n return parseResx({\n ...options,\n content,\n filePath: options.resxFilePath,\n resxNewlineNormalization: options.newlineNormalization,\n ignoreMissingResxComments: !options.warnOnMissingComment\n });\n}\n\n/**\n * @deprecated\n *\n * Use {@link parseResx} instead.\n *\n * @public\n */\nexport function readResxAsLocFile(resxContents: string, options: IResxReaderOptions): ILocalizationFile {\n return parseResx({\n ...options,\n content: resxContents,\n filePath: options.resxFilePath,\n resxNewlineNormalization: options.newlineNormalization,\n ignoreMissingResxComments: !options.warnOnMissingComment\n });\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { ITerminal, NewlineKind } from '@rushstack/node-core-library';
2
1
  import type { ILocalizationFile, IParseFileOptions } from './interfaces';
2
+ import { IParseResxOptionsBase } from './parsers/parseResx';
3
3
  /**
4
4
  * @public
5
5
  */
@@ -7,11 +7,8 @@ export declare type ParserKind = 'resx' | 'loc.json' | 'resjson';
7
7
  /**
8
8
  * @public
9
9
  */
10
- export interface IParseLocFileOptions extends IParseFileOptions {
11
- terminal: ITerminal;
10
+ export interface IParseLocFileOptions extends IParseFileOptions, IParseResxOptionsBase {
12
11
  parser?: ParserKind;
13
- resxNewlineNormalization: NewlineKind | undefined;
14
- ignoreMissingResxComments: boolean | undefined;
15
12
  }
16
13
  export declare function selectParserByFilePath(filePath: string): ParserKind;
17
14
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"LocFileParser.d.ts","sourceRoot":"","sources":["../src/LocFileParser.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,KAAK,EAAwB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAK/F;;GAEG;AACH,oBAAY,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,wBAAwB,EAAE,WAAW,GAAG,SAAS,CAAC;IAClD,yBAAyB,EAAE,OAAO,GAAG,SAAS,CAAC;CAChD;AAUD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAUnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,iBAAiB,CAiD7E"}
1
+ {"version":3,"file":"LocFileParser.d.ts","sourceRoot":"","sources":["../src/LocFileParser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAwB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG/F,OAAO,EAAE,qBAAqB,EAAa,MAAM,qBAAqB,CAAC;AAEvE;;GAEG;AACH,oBAAY,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB,EAAE,qBAAqB;IACpF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAUD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAUnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,iBAAiB,CA2C7E"}
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.parseLocFile = exports.selectParserByFilePath = void 0;
6
6
  const parseLocJson_1 = require("./parsers/parseLocJson");
7
7
  const parseResJson_1 = require("./parsers/parseResJson");
8
- const ResxReader_1 = require("./ResxReader");
8
+ const parseResx_1 = require("./parsers/parseResx");
9
9
  const parseCache = new Map();
10
10
  function selectParserByFilePath(filePath) {
11
11
  if (/\.resx$/i.test(filePath)) {
@@ -38,13 +38,7 @@ function parseLocFile(options) {
38
38
  let parsedFile;
39
39
  switch (parser) {
40
40
  case 'resx': {
41
- parsedFile = (0, ResxReader_1.readResxAsLocFile)(options.content, {
42
- terminal: options.terminal,
43
- resxFilePath: options.filePath,
44
- newlineNormalization: options.resxNewlineNormalization,
45
- warnOnMissingComment: !options.ignoreMissingResxComments,
46
- ignoreString: options.ignoreString
47
- });
41
+ parsedFile = (0, parseResx_1.parseResx)(options);
48
42
  break;
49
43
  }
50
44
  case 'loc.json': {
@@ -1 +1 @@
1
- {"version":3,"file":"LocFileParser.js","sourceRoot":"","sources":["../src/LocFileParser.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAK3D,yDAAsD;AACtD,yDAAsD;AACtD,6CAAiD;AAuBjD,MAAM,UAAU,GAAkC,IAAI,GAAG,EAA4B,CAAC;AAEtF,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC7B,OAAO,MAAM,CAAC;KACf;SAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAChD,OAAO,UAAU,CAAC;KACnB;SAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACvC,OAAO,SAAS,CAAC;KAClB;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;KACpE;AACH,CAAC;AAVD,wDAUC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,OAA6B;IACxD,MAAM,EAAE,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,OAAO,CAAC;IAEtE,MAAM,YAAY,GAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,IAAI,OAAO,CAAC,wBAAwB,IAAI,MAAM,EAAE,CAAC;IAC3G,MAAM,eAAe,GAAiC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACnF,IAAI,eAAe,EAAE;QACnB,IACE,eAAe,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO;YAC3C,eAAe,CAAC,YAAY,KAAK,OAAO,CAAC,YAAY,EACrD;YACA,OAAO,eAAe,CAAC,UAAU,CAAC;SACnC;KACF;IAED,IAAI,UAA6B,CAAC;IAClC,QAAQ,MAAM,EAAE;QACd,KAAK,MAAM,CAAC,CAAC;YACX,UAAU,GAAG,IAAA,8BAAiB,EAAC,OAAO,CAAC,OAAO,EAAE;gBAC9C,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,YAAY,EAAE,OAAO,CAAC,QAAQ;gBAC9B,oBAAoB,EAAE,OAAO,CAAC,wBAAwB;gBACtD,oBAAoB,EAAE,CAAC,OAAO,CAAC,yBAAyB;gBACxD,YAAY,EAAE,OAAO,CAAC,YAAY;aACnC,CAAC,CAAC;YACH,MAAM;SACP;QAED,KAAK,UAAU,CAAC,CAAC;YACf,UAAU,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAAC;YACnC,MAAM;SACP;QAED,KAAK,SAAS,CAAC,CAAC;YACd,UAAU,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAAC;YACnC,MAAM;SACP;QAED,OAAO,CAAC,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;SAClD;KACF;IAED,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE;QAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU;QACV,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AAjDD,oCAiDC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { ITerminal, NewlineKind } from '@rushstack/node-core-library';\n\nimport type { IgnoreStringFunction, ILocalizationFile, IParseFileOptions } from './interfaces';\nimport { parseLocJson } from './parsers/parseLocJson';\nimport { parseResJson } from './parsers/parseResJson';\nimport { readResxAsLocFile } from './ResxReader';\n\n/**\n * @public\n */\nexport type ParserKind = 'resx' | 'loc.json' | 'resjson';\n\n/**\n * @public\n */\nexport interface IParseLocFileOptions extends IParseFileOptions {\n terminal: ITerminal;\n parser?: ParserKind;\n resxNewlineNormalization: NewlineKind | undefined;\n ignoreMissingResxComments: boolean | undefined;\n}\n\ninterface IParseCacheEntry {\n content: string;\n parsedFile: ILocalizationFile;\n ignoreString: IgnoreStringFunction | undefined;\n}\n\nconst parseCache: Map<string, IParseCacheEntry> = new Map<string, IParseCacheEntry>();\n\nexport function selectParserByFilePath(filePath: string): ParserKind {\n if (/\\.resx$/i.test(filePath)) {\n return 'resx';\n } else if (/\\.(resx|loc)\\.json$/i.test(filePath)) {\n return 'loc.json';\n } else if (/\\.resjson$/i.test(filePath)) {\n return 'resjson';\n } else {\n throw new Error(`Unsupported file extension in file: ${filePath}`);\n }\n}\n\n/**\n * @public\n */\nexport function parseLocFile(options: IParseLocFileOptions): ILocalizationFile {\n const { parser = selectParserByFilePath(options.filePath) } = options;\n\n const fileCacheKey: string = `${options.filePath}?${parser}&${options.resxNewlineNormalization || 'none'}`;\n const parseCacheEntry: IParseCacheEntry | undefined = parseCache.get(fileCacheKey);\n if (parseCacheEntry) {\n if (\n parseCacheEntry.content === options.content &&\n parseCacheEntry.ignoreString === options.ignoreString\n ) {\n return parseCacheEntry.parsedFile;\n }\n }\n\n let parsedFile: ILocalizationFile;\n switch (parser) {\n case 'resx': {\n parsedFile = readResxAsLocFile(options.content, {\n terminal: options.terminal,\n resxFilePath: options.filePath,\n newlineNormalization: options.resxNewlineNormalization,\n warnOnMissingComment: !options.ignoreMissingResxComments,\n ignoreString: options.ignoreString\n });\n break;\n }\n\n case 'loc.json': {\n parsedFile = parseLocJson(options);\n break;\n }\n\n case 'resjson': {\n parsedFile = parseResJson(options);\n break;\n }\n\n default: {\n throw new Error(`Unsupported parser: ${parser}`);\n }\n }\n\n parseCache.set(fileCacheKey, {\n content: options.content,\n parsedFile,\n ignoreString: options.ignoreString\n });\n\n return parsedFile;\n}\n"]}
1
+ {"version":3,"file":"LocFileParser.js","sourceRoot":"","sources":["../src/LocFileParser.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAG3D,yDAAsD;AACtD,yDAAsD;AACtD,mDAAuE;AAoBvE,MAAM,UAAU,GAAkC,IAAI,GAAG,EAA4B,CAAC;AAEtF,SAAgB,sBAAsB,CAAC,QAAgB;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC7B,OAAO,MAAM,CAAC;KACf;SAAM,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAChD,OAAO,UAAU,CAAC;KACnB;SAAM,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACvC,OAAO,SAAS,CAAC;KAClB;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,EAAE,CAAC,CAAC;KACpE;AACH,CAAC;AAVD,wDAUC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,OAA6B;IACxD,MAAM,EAAE,MAAM,GAAG,sBAAsB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,OAAO,CAAC;IAEtE,MAAM,YAAY,GAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,IAAI,OAAO,CAAC,wBAAwB,IAAI,MAAM,EAAE,CAAC;IAC3G,MAAM,eAAe,GAAiC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACnF,IAAI,eAAe,EAAE;QACnB,IACE,eAAe,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO;YAC3C,eAAe,CAAC,YAAY,KAAK,OAAO,CAAC,YAAY,EACrD;YACA,OAAO,eAAe,CAAC,UAAU,CAAC;SACnC;KACF;IAED,IAAI,UAA6B,CAAC;IAClC,QAAQ,MAAM,EAAE;QACd,KAAK,MAAM,CAAC,CAAC;YACX,UAAU,GAAG,IAAA,qBAAS,EAAC,OAAO,CAAC,CAAC;YAChC,MAAM;SACP;QAED,KAAK,UAAU,CAAC,CAAC;YACf,UAAU,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAAC;YACnC,MAAM;SACP;QAED,KAAK,SAAS,CAAC,CAAC;YACd,UAAU,GAAG,IAAA,2BAAY,EAAC,OAAO,CAAC,CAAC;YACnC,MAAM;SACP;QAED,OAAO,CAAC,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;SAClD;KACF;IAED,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE;QAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU;QACV,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AA3CD,oCA2CC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { IgnoreStringFunction, ILocalizationFile, IParseFileOptions } from './interfaces';\nimport { parseLocJson } from './parsers/parseLocJson';\nimport { parseResJson } from './parsers/parseResJson';\nimport { IParseResxOptionsBase, parseResx } from './parsers/parseResx';\n\n/**\n * @public\n */\nexport type ParserKind = 'resx' | 'loc.json' | 'resjson';\n\n/**\n * @public\n */\nexport interface IParseLocFileOptions extends IParseFileOptions, IParseResxOptionsBase {\n parser?: ParserKind;\n}\n\ninterface IParseCacheEntry {\n content: string;\n parsedFile: ILocalizationFile;\n ignoreString: IgnoreStringFunction | undefined;\n}\n\nconst parseCache: Map<string, IParseCacheEntry> = new Map<string, IParseCacheEntry>();\n\nexport function selectParserByFilePath(filePath: string): ParserKind {\n if (/\\.resx$/i.test(filePath)) {\n return 'resx';\n } else if (/\\.(resx|loc)\\.json$/i.test(filePath)) {\n return 'loc.json';\n } else if (/\\.resjson$/i.test(filePath)) {\n return 'resjson';\n } else {\n throw new Error(`Unsupported file extension in file: ${filePath}`);\n }\n}\n\n/**\n * @public\n */\nexport function parseLocFile(options: IParseLocFileOptions): ILocalizationFile {\n const { parser = selectParserByFilePath(options.filePath) } = options;\n\n const fileCacheKey: string = `${options.filePath}?${parser}&${options.resxNewlineNormalization || 'none'}`;\n const parseCacheEntry: IParseCacheEntry | undefined = parseCache.get(fileCacheKey);\n if (parseCacheEntry) {\n if (\n parseCacheEntry.content === options.content &&\n parseCacheEntry.ignoreString === options.ignoreString\n ) {\n return parseCacheEntry.parsedFile;\n }\n }\n\n let parsedFile: ILocalizationFile;\n switch (parser) {\n case 'resx': {\n parsedFile = parseResx(options);\n break;\n }\n\n case 'loc.json': {\n parsedFile = parseLocJson(options);\n break;\n }\n\n case 'resjson': {\n parsedFile = parseResJson(options);\n break;\n }\n\n default: {\n throw new Error(`Unsupported parser: ${parser}`);\n }\n }\n\n parseCache.set(fileCacheKey, {\n content: options.content,\n parsedFile,\n ignoreString: options.ignoreString\n });\n\n return parsedFile;\n}\n"]}
@@ -20,7 +20,7 @@ export interface ITypingsGeneratorOptions {
20
20
  *
21
21
  * @public
22
22
  */
23
- export declare class LocFileTypingsGenerator extends StringValuesTypingsGenerator {
23
+ export declare class TypingsGenerator extends StringValuesTypingsGenerator {
24
24
  constructor(options: ITypingsGeneratorOptions);
25
25
  }
26
- //# sourceMappingURL=LocFileTypingsGenerator.d.ts.map
26
+ //# sourceMappingURL=TypingsGenerator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypingsGenerator.d.ts","sourceRoot":"","sources":["../src/TypingsGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAsB,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,cAAc,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wBAAwB,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACnD,yBAAyB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,cAAc,CAAC,EAAE,CACf,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,KACf,MAAM,GAAG,SAAS,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,4BAA4B;gBAC7C,OAAO,EAAE,wBAAwB;CAkCrD"}
@@ -2,7 +2,7 @@
2
2
  // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
3
  // See LICENSE in the project root for license information.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.LocFileTypingsGenerator = void 0;
5
+ exports.TypingsGenerator = void 0;
6
6
  const typings_generator_1 = require("@rushstack/typings-generator");
7
7
  const LocFileParser_1 = require("./LocFileParser");
8
8
  /**
@@ -10,7 +10,7 @@ const LocFileParser_1 = require("./LocFileParser");
10
10
  *
11
11
  * @public
12
12
  */
13
- class LocFileTypingsGenerator extends typings_generator_1.StringValuesTypingsGenerator {
13
+ class TypingsGenerator extends typings_generator_1.StringValuesTypingsGenerator {
14
14
  constructor(options) {
15
15
  const { ignoreString, processComment } = options;
16
16
  super({
@@ -42,5 +42,5 @@ class LocFileTypingsGenerator extends typings_generator_1.StringValuesTypingsGen
42
42
  });
43
43
  }
44
44
  }
45
- exports.LocFileTypingsGenerator = LocFileTypingsGenerator;
46
- //# sourceMappingURL=LocFileTypingsGenerator.js.map
45
+ exports.TypingsGenerator = TypingsGenerator;
46
+ //# sourceMappingURL=TypingsGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypingsGenerator.js","sourceRoot":"","sources":["../src/TypingsGenerator.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAgG;AAIhG,mDAA+C;AAqB/C;;;;GAIG;AACH,MAAa,gBAAiB,SAAQ,gDAA4B;IAChE,YAAmB,OAAiC;QAClD,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QACjD,KAAK,CAAC;YACJ,GAAG,OAAO;YACV,cAAc,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC;YAChE,uBAAuB,EAAE,CAAC,YAAoB,EAAE,QAAgB,EAAE,YAAoB,EAAE,EAAE;gBACxF,MAAM,WAAW,GAAsB,IAAA,4BAAY,EAAC;oBAClD,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,YAAY;oBACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAS;oBACjC,wBAAwB,EAAE,OAAO,CAAC,wBAAwB;oBAC1D,yBAAyB,EAAE,OAAO,CAAC,yBAAyB;oBAC5D,YAAY;iBACb,CAAC,CAAC;gBAEH,MAAM,OAAO,GAAyB,EAAE,CAAC;gBAEzC,wCAAwC;gBACxC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;oBACpC,IAAI,OAAO,GAAuB,WAAW,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;oBAClE,IAAI,cAAc,EAAE;wBAClB,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;qBAC7D;oBAED,OAAO,CAAC,IAAI,CAAC;wBACX,UAAU,EAAE,UAAU;wBACtB,OAAO;qBACR,CAAC,CAAC;iBACJ;gBAED,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAnCD,4CAmCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { StringValuesTypingsGenerator, IStringValueTyping } from '@rushstack/typings-generator';\nimport { ITerminal, NewlineKind } from '@rushstack/node-core-library';\n\nimport type { IgnoreStringFunction, ILocalizationFile } from './interfaces';\nimport { parseLocFile } from './LocFileParser';\n\n/**\n * @public\n */\nexport interface ITypingsGeneratorOptions {\n srcFolder: string;\n generatedTsFolder: string;\n terminal?: ITerminal;\n exportAsDefault?: boolean;\n globsToIgnore?: string[];\n resxNewlineNormalization?: NewlineKind | undefined;\n ignoreMissingResxComments?: boolean | undefined;\n ignoreString?: IgnoreStringFunction;\n processComment?: (\n comment: string | undefined,\n resxFilePath: string,\n stringName: string\n ) => string | undefined;\n}\n\n/**\n * This is a simple tool that generates .d.ts files for .loc.json, .resx.json, .resjson, and .resx files.\n *\n * @public\n */\nexport class TypingsGenerator extends StringValuesTypingsGenerator {\n public constructor(options: ITypingsGeneratorOptions) {\n const { ignoreString, processComment } = options;\n super({\n ...options,\n fileExtensions: ['.resx', '.resx.json', '.loc.json', '.resjson'],\n parseAndGenerateTypings: (fileContents: string, filePath: string, resxFilePath: string) => {\n const locFileData: ILocalizationFile = parseLocFile({\n filePath: filePath,\n content: fileContents,\n terminal: this._options.terminal!,\n resxNewlineNormalization: options.resxNewlineNormalization,\n ignoreMissingResxComments: options.ignoreMissingResxComments,\n ignoreString\n });\n\n const typings: IStringValueTyping[] = [];\n\n // eslint-disable-next-line guard-for-in\n for (const stringName in locFileData) {\n let comment: string | undefined = locFileData[stringName].comment;\n if (processComment) {\n comment = processComment(comment, resxFilePath, stringName);\n }\n\n typings.push({\n exportName: stringName,\n comment\n });\n }\n\n return { typings };\n }\n });\n }\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export type { ILocalizationFile, ILocalizedString, IPseudolocaleOptions, IParseFileOptions, IgnoreStringFunction } from './interfaces';
2
2
  export { parseLocJson } from './parsers/parseLocJson';
3
3
  export { parseResJson } from './parsers/parseResJson';
4
+ export { parseResx, IParseResxOptions, IParseResxOptionsBase } from './parsers/parseResx';
4
5
  export { parseLocFile, IParseLocFileOptions, ParserKind } from './LocFileParser';
5
- export { ITypingsGeneratorOptions, LocFileTypingsGenerator as TypingsGenerator } from './LocFileTypingsGenerator';
6
- export { readResxFileAsLocFile, readResxAsLocFile, IResxReaderOptions } from './ResxReader';
6
+ export { ITypingsGeneratorOptions, TypingsGenerator } from './TypingsGenerator';
7
+ export { readResxFileAsLocFile, readResxAsLocFile, IResxReaderOptions } from './LegacyResxReader';
7
8
  export { getPseudolocalizer } from './Pseudolocalization';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EACL,wBAAwB,EACxB,uBAAuB,IAAI,gBAAgB,EAC5C,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
package/lib/index.js CHANGED
@@ -2,18 +2,20 @@
2
2
  // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
3
  // See LICENSE in the project root for license information.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.getPseudolocalizer = exports.readResxAsLocFile = exports.readResxFileAsLocFile = exports.TypingsGenerator = exports.parseLocFile = exports.parseResJson = exports.parseLocJson = void 0;
5
+ exports.getPseudolocalizer = exports.readResxAsLocFile = exports.readResxFileAsLocFile = exports.TypingsGenerator = exports.parseLocFile = exports.parseResx = exports.parseResJson = exports.parseLocJson = void 0;
6
6
  var parseLocJson_1 = require("./parsers/parseLocJson");
7
7
  Object.defineProperty(exports, "parseLocJson", { enumerable: true, get: function () { return parseLocJson_1.parseLocJson; } });
8
8
  var parseResJson_1 = require("./parsers/parseResJson");
9
9
  Object.defineProperty(exports, "parseResJson", { enumerable: true, get: function () { return parseResJson_1.parseResJson; } });
10
+ var parseResx_1 = require("./parsers/parseResx");
11
+ Object.defineProperty(exports, "parseResx", { enumerable: true, get: function () { return parseResx_1.parseResx; } });
10
12
  var LocFileParser_1 = require("./LocFileParser");
11
13
  Object.defineProperty(exports, "parseLocFile", { enumerable: true, get: function () { return LocFileParser_1.parseLocFile; } });
12
- var LocFileTypingsGenerator_1 = require("./LocFileTypingsGenerator");
13
- Object.defineProperty(exports, "TypingsGenerator", { enumerable: true, get: function () { return LocFileTypingsGenerator_1.LocFileTypingsGenerator; } });
14
- var ResxReader_1 = require("./ResxReader");
15
- Object.defineProperty(exports, "readResxFileAsLocFile", { enumerable: true, get: function () { return ResxReader_1.readResxFileAsLocFile; } });
16
- Object.defineProperty(exports, "readResxAsLocFile", { enumerable: true, get: function () { return ResxReader_1.readResxAsLocFile; } });
14
+ var TypingsGenerator_1 = require("./TypingsGenerator");
15
+ Object.defineProperty(exports, "TypingsGenerator", { enumerable: true, get: function () { return TypingsGenerator_1.TypingsGenerator; } });
16
+ var LegacyResxReader_1 = require("./LegacyResxReader");
17
+ Object.defineProperty(exports, "readResxFileAsLocFile", { enumerable: true, get: function () { return LegacyResxReader_1.readResxFileAsLocFile; } });
18
+ Object.defineProperty(exports, "readResxAsLocFile", { enumerable: true, get: function () { return LegacyResxReader_1.readResxAsLocFile; } });
17
19
  var Pseudolocalization_1 = require("./Pseudolocalization");
18
20
  Object.defineProperty(exports, "getPseudolocalizer", { enumerable: true, get: function () { return Pseudolocalization_1.getPseudolocalizer; } });
19
21
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAS3D,uDAAsD;AAA7C,4GAAA,YAAY,OAAA;AACrB,uDAAsD;AAA7C,4GAAA,YAAY,OAAA;AACrB,iDAAiF;AAAxE,6GAAA,YAAY,OAAA;AACrB,qEAGmC;AADjC,2HAAA,uBAAuB,OAAoB;AAE7C,2CAA4F;AAAnF,mHAAA,qBAAqB,OAAA;AAAE,+GAAA,iBAAiB,OAAA;AACjD,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport type {\n ILocalizationFile,\n ILocalizedString,\n IPseudolocaleOptions,\n IParseFileOptions,\n IgnoreStringFunction\n} from './interfaces';\nexport { parseLocJson } from './parsers/parseLocJson';\nexport { parseResJson } from './parsers/parseResJson';\nexport { parseLocFile, IParseLocFileOptions, ParserKind } from './LocFileParser';\nexport {\n ITypingsGeneratorOptions,\n LocFileTypingsGenerator as TypingsGenerator\n} from './LocFileTypingsGenerator';\nexport { readResxFileAsLocFile, readResxAsLocFile, IResxReaderOptions } from './ResxReader';\nexport { getPseudolocalizer } from './Pseudolocalization';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAS3D,uDAAsD;AAA7C,4GAAA,YAAY,OAAA;AACrB,uDAAsD;AAA7C,4GAAA,YAAY,OAAA;AACrB,iDAA0F;AAAjF,sGAAA,SAAS,OAAA;AAClB,iDAAiF;AAAxE,6GAAA,YAAY,OAAA;AACrB,uDAAgF;AAA7C,oHAAA,gBAAgB,OAAA;AACnD,uDAAkG;AAAzF,yHAAA,qBAAqB,OAAA;AAAE,qHAAA,iBAAiB,OAAA;AACjD,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport type {\n ILocalizationFile,\n ILocalizedString,\n IPseudolocaleOptions,\n IParseFileOptions,\n IgnoreStringFunction\n} from './interfaces';\nexport { parseLocJson } from './parsers/parseLocJson';\nexport { parseResJson } from './parsers/parseResJson';\nexport { parseResx, IParseResxOptions, IParseResxOptionsBase } from './parsers/parseResx';\nexport { parseLocFile, IParseLocFileOptions, ParserKind } from './LocFileParser';\nexport { ITypingsGeneratorOptions, TypingsGenerator } from './TypingsGenerator';\nexport { readResxFileAsLocFile, readResxAsLocFile, IResxReaderOptions } from './LegacyResxReader';\nexport { getPseudolocalizer } from './Pseudolocalization';\n"]}
@@ -0,0 +1,20 @@
1
+ import { ITerminal, NewlineKind } from '@rushstack/node-core-library';
2
+ import type { ILocalizationFile, IParseFileOptions } from '../interfaces';
3
+ /**
4
+ * @public
5
+ */
6
+ export interface IParseResxOptions extends IParseFileOptions, IParseResxOptionsBase {
7
+ }
8
+ /**
9
+ * @public
10
+ */
11
+ export interface IParseResxOptionsBase {
12
+ terminal: ITerminal;
13
+ resxNewlineNormalization: NewlineKind | undefined;
14
+ ignoreMissingResxComments: boolean | undefined;
15
+ }
16
+ /**
17
+ * @public
18
+ */
19
+ export declare function parseResx(options: IParseResxOptions): ILocalizationFile;
20
+ //# sourceMappingURL=parseResx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseResx.d.ts","sourceRoot":"","sources":["../../src/parsers/parseResx.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAQ,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG5E,OAAO,KAAK,EAAoB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAI5F;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB,EAAE,qBAAqB;CAAG;AAEtF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,SAAS,CAAC;IACpB,wBAAwB,EAAE,WAAW,GAAG,SAAS,CAAC;IAClD,yBAAyB,EAAE,OAAO,GAAG,SAAS,CAAC;CAChD;AAaD;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAkBvE"}
@@ -2,22 +2,14 @@
2
2
  // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
3
  // See LICENSE in the project root for license information.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.readResxAsLocFile = exports.readResxFileAsLocFile = void 0;
5
+ exports.parseResx = void 0;
6
6
  const node_core_library_1 = require("@rushstack/node-core-library");
7
7
  const xmldoc_1 = require("xmldoc");
8
8
  const STRING_NAME_RESX = /^[A-z_$][A-z0-9_$]*$/;
9
9
  /**
10
10
  * @public
11
11
  */
12
- function readResxFileAsLocFile(options) {
13
- const resxContents = node_core_library_1.FileSystem.readFile(options.resxFilePath);
14
- return readResxAsLocFile(resxContents, options);
15
- }
16
- exports.readResxFileAsLocFile = readResxFileAsLocFile;
17
- /**
18
- * @public
19
- */
20
- function readResxAsLocFile(resxContents, options) {
12
+ function parseResx(options) {
21
13
  const writeError = options.terminal.writeErrorLine.bind(options.terminal);
22
14
  const writeWarning = options.terminal.writeWarningLine.bind(options.terminal);
23
15
  const loggingFunctions = {
@@ -32,14 +24,13 @@ function readResxAsLocFile(resxContents, options) {
32
24
  };
33
25
  return _readResxAsLocFileInternal({
34
26
  ...options,
35
- resxContents,
36
27
  loggingFunctions
37
28
  });
38
29
  }
39
- exports.readResxAsLocFile = readResxAsLocFile;
30
+ exports.parseResx = parseResx;
40
31
  function _readResxAsLocFileInternal(options) {
41
32
  const { ignoreString } = options;
42
- const xmlDocument = new xmldoc_1.XmlDocument(options.resxContents);
33
+ const xmlDocument = new xmldoc_1.XmlDocument(options.content);
43
34
  if (xmlDocument.name !== 'root') {
44
35
  _logErrorWithLocation(options, `Expected RESX to have a "root" element, found "${xmlDocument.name}"`, xmlDocument);
45
36
  }
@@ -61,7 +52,7 @@ function _readResxAsLocFileInternal(options) {
61
52
  _logErrorWithLocation(options, `Duplicate string value "${stringName}"`, childNode);
62
53
  }
63
54
  const locString = _readDataElement(options, childNode);
64
- if (locString && !(ignoreString === null || ignoreString === void 0 ? void 0 : ignoreString(options.resxFilePath, stringName))) {
55
+ if (locString && !(ignoreString === null || ignoreString === void 0 ? void 0 : ignoreString(options.filePath, stringName))) {
65
56
  locFile[stringName] = locString;
66
57
  }
67
58
  }
@@ -107,8 +98,8 @@ function _readDataElement(options, dataElement) {
107
98
  else {
108
99
  foundValueElement = true;
109
100
  value = _readTextElement(options, childNode);
110
- if (value && options.newlineNormalization) {
111
- value = node_core_library_1.Text.convertTo(value, options.newlineNormalization);
101
+ if (value && options.resxNewlineNormalization) {
102
+ value = node_core_library_1.Text.convertTo(value, options.resxNewlineNormalization);
112
103
  }
113
104
  }
114
105
  break;
@@ -145,7 +136,7 @@ function _readDataElement(options, dataElement) {
145
136
  _logErrorWithLocation(options, 'Missing string value in <data> element', dataElement);
146
137
  }
147
138
  else {
148
- if (comment === undefined && options.warnOnMissingComment) {
139
+ if (comment === undefined && options.ignoreMissingResxComments === false) {
149
140
  _logWarningWithLocation(options, 'Missing string comment in <data> element', dataElement);
150
141
  }
151
142
  return {
@@ -181,18 +172,18 @@ function _readTextElement(options, element) {
181
172
  }
182
173
  function _logErrorWithLocation(options, message, element) {
183
174
  if (element) {
184
- options.loggingFunctions.logFileError(message, options.resxFilePath, element.line + 1, element.column + 1);
175
+ options.loggingFunctions.logFileError(message, options.filePath, element.line + 1, element.column + 1);
185
176
  }
186
177
  else {
187
- options.loggingFunctions.logFileError(message, options.resxFilePath);
178
+ options.loggingFunctions.logFileError(message, options.filePath);
188
179
  }
189
180
  }
190
181
  function _logWarningWithLocation(options, message, element) {
191
182
  if (element) {
192
- options.loggingFunctions.logFileWarning(message, options.resxFilePath, element.line + 1, element.column + 1);
183
+ options.loggingFunctions.logFileWarning(message, options.filePath, element.line + 1, element.column + 1);
193
184
  }
194
185
  else {
195
- options.loggingFunctions.logFileWarning(message, options.resxFilePath);
186
+ options.loggingFunctions.logFileWarning(message, options.filePath);
196
187
  }
197
188
  }
198
189
  function _logWithLocation(loggingFn, message, filePath, line, position) {
@@ -208,4 +199,4 @@ function _logWithLocation(loggingFn, message, filePath, line, position) {
208
199
  }
209
200
  loggingFn(`${location}: ${message}`);
210
201
  }
211
- //# sourceMappingURL=ResxReader.js.map
202
+ //# sourceMappingURL=parseResx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseResx.js","sourceRoot":"","sources":["../../src/parsers/parseResx.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { ITerminal, Text, NewlineKind } from '@rushstack/node-core-library';\nimport { XmlDocument, XmlElement } from 'xmldoc';\n\nimport type { ILocalizedString, ILocalizationFile, IParseFileOptions } from '../interfaces';\n\nconst STRING_NAME_RESX: RegExp = /^[A-z_$][A-z0-9_$]*$/;\n\n/**\n * @public\n */\nexport interface IParseResxOptions extends IParseFileOptions, IParseResxOptionsBase {}\n\n/**\n * @public\n */\nexport interface IParseResxOptionsBase {\n terminal: ITerminal;\n resxNewlineNormalization: NewlineKind | undefined;\n ignoreMissingResxComments: boolean | undefined;\n}\n\ninterface ILoggingFunctions {\n logError: (message: string) => void;\n logWarning: (message: string) => void;\n logFileError: (message: string, filePath: string, line?: number, position?: number) => void;\n logFileWarning: (message: string, filePath: string, line?: number, position?: number) => void;\n}\n\ninterface IResxReaderOptionsInternal extends Omit<IParseResxOptions, 'terminal'> {\n loggingFunctions: ILoggingFunctions;\n}\n\n/**\n * @public\n */\nexport function parseResx(options: IParseResxOptions): ILocalizationFile {\n const writeError: (message: string) => void = options.terminal.writeErrorLine.bind(options.terminal);\n const writeWarning: (message: string) => void = options.terminal.writeWarningLine.bind(options.terminal);\n const loggingFunctions: ILoggingFunctions = {\n logError: (message: string) => writeError(message),\n logWarning: (message: string) => writeWarning(message),\n logFileError: (message: string, filePath: string, line?: number, position?: number) => {\n _logWithLocation(writeError, message, filePath, line, position);\n },\n logFileWarning: (message: string, filePath: string, line?: number, position?: number) => {\n _logWithLocation(writeWarning, message, filePath, line, position);\n }\n };\n\n return _readResxAsLocFileInternal({\n ...options,\n loggingFunctions\n });\n}\n\nfunction _readResxAsLocFileInternal(options: IResxReaderOptionsInternal): ILocalizationFile {\n const { ignoreString } = options;\n const xmlDocument: XmlDocument = new XmlDocument(options.content);\n\n if (xmlDocument.name !== 'root') {\n _logErrorWithLocation(\n options,\n `Expected RESX to have a \"root\" element, found \"${xmlDocument.name}\"`,\n xmlDocument\n );\n }\n\n const locFile: ILocalizationFile = {};\n\n for (const childNode of xmlDocument.children) {\n switch (childNode.type) {\n case 'element': {\n switch (childNode.name) {\n case 'data': {\n const stringName: string = childNode.attr.name;\n if (!stringName) {\n _logErrorWithLocation(options, 'Unexpected missing or empty string name', childNode);\n } else if (!STRING_NAME_RESX.test(stringName)) {\n _logErrorWithLocation(options, `Invalid string name \"${stringName}\"`, childNode);\n } else {\n if (locFile.hasOwnProperty(stringName)) {\n _logErrorWithLocation(options, `Duplicate string value \"${stringName}\"`, childNode);\n }\n\n const locString: ILocalizedString | undefined = _readDataElement(options, childNode);\n\n if (locString && !ignoreString?.(options.filePath, stringName)) {\n locFile[stringName] = locString;\n }\n }\n\n break;\n }\n\n // Other allowed elements\n case 'xsd:schema':\n case 'resheader':\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected RESX element ${childNode.name}`, childNode);\n }\n\n break;\n }\n\n case 'text': {\n if (childNode.text.trim() !== '') {\n _logErrorWithLocation(options, 'Found unexpected non-empty text node in RESX');\n }\n\n break;\n }\n\n case 'comment':\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected ${childNode.type} child in RESX`);\n break;\n }\n }\n\n return locFile;\n}\n\nfunction _readDataElement(\n options: IResxReaderOptionsInternal,\n dataElement: XmlElement\n): ILocalizedString | undefined {\n let foundCommentElement: boolean = false;\n let foundValueElement: boolean = false;\n let comment: string | undefined = undefined;\n let value: string | undefined = undefined;\n\n for (const childNode of dataElement.children) {\n switch (childNode.type) {\n case 'element': {\n switch (childNode.name) {\n case 'value': {\n if (foundValueElement) {\n _logErrorWithLocation(options, 'Duplicate <value> element found', childNode);\n } else {\n foundValueElement = true;\n value = _readTextElement(options, childNode);\n if (value && options.resxNewlineNormalization) {\n value = Text.convertTo(value, options.resxNewlineNormalization);\n }\n }\n\n break;\n }\n\n case 'comment': {\n if (foundCommentElement) {\n _logErrorWithLocation(options, 'Duplicate <comment> element found', childNode);\n } else {\n foundCommentElement = true;\n comment = _readTextElement(options, childNode);\n }\n\n break;\n }\n\n default:\n _logErrorWithLocation(options, `Unexpected RESX element ${childNode.name}`, childNode);\n break;\n }\n\n break;\n }\n\n case 'text': {\n if (childNode.text.trim() !== '') {\n _logErrorWithLocation(\n options,\n 'Found unexpected non-empty text node in RESX <data> element',\n dataElement\n );\n }\n\n break;\n }\n\n case 'comment':\n break;\n\n default:\n _logErrorWithLocation(\n options,\n `Unexpected ${childNode.type} child in RESX <data> element`,\n dataElement\n );\n }\n }\n\n if (!foundValueElement) {\n _logErrorWithLocation(options, 'Missing string value in <data> element', dataElement);\n } else {\n if (comment === undefined && options.ignoreMissingResxComments === false) {\n _logWarningWithLocation(options, 'Missing string comment in <data> element', dataElement);\n }\n\n return {\n value: value || '',\n comment\n };\n }\n}\n\nfunction _readTextElement(options: IResxReaderOptionsInternal, element: XmlElement): string | undefined {\n let foundText: string | undefined = undefined;\n\n for (const childNode of element.children) {\n switch (childNode.type) {\n case 'cdata':\n case 'text': {\n if (foundText !== undefined) {\n _logErrorWithLocation(options, 'More than one child node found containing text content', element);\n break;\n }\n\n foundText = childNode.type === 'text' ? childNode.text : childNode.cdata;\n break;\n }\n\n case 'comment':\n break;\n\n case 'element':\n _logErrorWithLocation(options, `Unexpected element`, childNode);\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected ${element.type} child`, element);\n break;\n }\n }\n\n return foundText;\n}\n\nfunction _logErrorWithLocation(\n options: IResxReaderOptionsInternal,\n message: string,\n element?: XmlElement | XmlDocument\n): void {\n if (element) {\n options.loggingFunctions.logFileError(message, options.filePath, element.line + 1, element.column + 1);\n } else {\n options.loggingFunctions.logFileError(message, options.filePath);\n }\n}\n\nfunction _logWarningWithLocation(\n options: IResxReaderOptionsInternal,\n message: string,\n element?: XmlElement | XmlDocument\n): void {\n if (element) {\n options.loggingFunctions.logFileWarning(message, options.filePath, element.line + 1, element.column + 1);\n } else {\n options.loggingFunctions.logFileWarning(message, options.filePath);\n }\n}\n\nfunction _logWithLocation(\n loggingFn: (message: string) => void,\n message: string,\n filePath: string,\n line?: number,\n position?: number\n): void {\n let location: string;\n if (position !== undefined) {\n location = `${filePath}(${line},${position})`;\n } else if (line !== undefined) {\n location = `${filePath}(${line})`;\n } else {\n location = filePath;\n }\n\n loggingFn(`${location}: ${message}`);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/localization-utilities",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "This plugin contains some useful functions for localization.",
5
5
  "main": "lib/index.js",
6
6
  "typings": "dist/localization-utilities.d.ts",
@@ -1 +0,0 @@
1
- {"version":3,"file":"LocFileTypingsGenerator.d.ts","sourceRoot":"","sources":["../src/LocFileTypingsGenerator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAsB,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,cAAc,CAAC;AAG5E;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wBAAwB,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACnD,yBAAyB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChD,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,cAAc,CAAC,EAAE,CACf,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,KACf,MAAM,GAAG,SAAS,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,4BAA4B;gBACpD,OAAO,EAAE,wBAAwB;CAkCrD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"LocFileTypingsGenerator.js","sourceRoot":"","sources":["../src/LocFileTypingsGenerator.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAgG;AAIhG,mDAA+C;AAqB/C;;;;GAIG;AACH,MAAa,uBAAwB,SAAQ,gDAA4B;IACvE,YAAmB,OAAiC;QAClD,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QACjD,KAAK,CAAC;YACJ,GAAG,OAAO;YACV,cAAc,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,CAAC;YAChE,uBAAuB,EAAE,CAAC,YAAoB,EAAE,QAAgB,EAAE,YAAoB,EAAE,EAAE;gBACxF,MAAM,WAAW,GAAsB,IAAA,4BAAY,EAAC;oBAClD,QAAQ,EAAE,QAAQ;oBAClB,OAAO,EAAE,YAAY;oBACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAS;oBACjC,wBAAwB,EAAE,OAAO,CAAC,wBAAwB;oBAC1D,yBAAyB,EAAE,OAAO,CAAC,yBAAyB;oBAC5D,YAAY;iBACb,CAAC,CAAC;gBAEH,MAAM,OAAO,GAAyB,EAAE,CAAC;gBAEzC,wCAAwC;gBACxC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;oBACpC,IAAI,OAAO,GAAuB,WAAW,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;oBAClE,IAAI,cAAc,EAAE;wBAClB,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;qBAC7D;oBAED,OAAO,CAAC,IAAI,CAAC;wBACX,UAAU,EAAE,UAAU;wBACtB,OAAO;qBACR,CAAC,CAAC;iBACJ;gBAED,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF;AAnCD,0DAmCC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { StringValuesTypingsGenerator, IStringValueTyping } from '@rushstack/typings-generator';\nimport { ITerminal, NewlineKind } from '@rushstack/node-core-library';\n\nimport type { IgnoreStringFunction, ILocalizationFile } from './interfaces';\nimport { parseLocFile } from './LocFileParser';\n\n/**\n * @public\n */\nexport interface ITypingsGeneratorOptions {\n srcFolder: string;\n generatedTsFolder: string;\n terminal?: ITerminal;\n exportAsDefault?: boolean;\n globsToIgnore?: string[];\n resxNewlineNormalization?: NewlineKind | undefined;\n ignoreMissingResxComments?: boolean | undefined;\n ignoreString?: IgnoreStringFunction;\n processComment?: (\n comment: string | undefined,\n resxFilePath: string,\n stringName: string\n ) => string | undefined;\n}\n\n/**\n * This is a simple tool that generates .d.ts files for .loc.json, .resx.json, .resjson, and .resx files.\n *\n * @public\n */\nexport class LocFileTypingsGenerator extends StringValuesTypingsGenerator {\n public constructor(options: ITypingsGeneratorOptions) {\n const { ignoreString, processComment } = options;\n super({\n ...options,\n fileExtensions: ['.resx', '.resx.json', '.loc.json', '.resjson'],\n parseAndGenerateTypings: (fileContents: string, filePath: string, resxFilePath: string) => {\n const locFileData: ILocalizationFile = parseLocFile({\n filePath: filePath,\n content: fileContents,\n terminal: this._options.terminal!,\n resxNewlineNormalization: options.resxNewlineNormalization,\n ignoreMissingResxComments: options.ignoreMissingResxComments,\n ignoreString\n });\n\n const typings: IStringValueTyping[] = [];\n\n // eslint-disable-next-line guard-for-in\n for (const stringName in locFileData) {\n let comment: string | undefined = locFileData[stringName].comment;\n if (processComment) {\n comment = processComment(comment, resxFilePath, stringName);\n }\n\n typings.push({\n exportName: stringName,\n comment\n });\n }\n\n return { typings };\n }\n });\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ResxReader.d.ts","sourceRoot":"","sources":["../src/ResxReader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,SAAS,EAAQ,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGxF,OAAO,KAAK,EAAoB,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAI9F;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,oBAAoB,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9C,oBAAoB,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACrC;AAcD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAGpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAmBtG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ResxReader.js","sourceRoot":"","sources":["../src/ResxReader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { FileSystem, ITerminal, Text, NewlineKind } from '@rushstack/node-core-library';\nimport { XmlDocument, XmlElement } from 'xmldoc';\n\nimport type { ILocalizedString, ILocalizationFile, IgnoreStringFunction } from './interfaces';\n\nconst STRING_NAME_RESX: RegExp = /^[A-z_$][A-z0-9_$]*$/;\n\n/**\n * @public\n */\nexport interface IResxReaderOptions {\n resxFilePath: string;\n terminal: ITerminal;\n newlineNormalization: NewlineKind | undefined;\n warnOnMissingComment: boolean;\n /**\n * Optionally, provide a function that will be called for each string. If the function returns `true`\n * the string will not be included.\n */\n ignoreString?: IgnoreStringFunction;\n}\n\ninterface ILoggingFunctions {\n logError: (message: string) => void;\n logWarning: (message: string) => void;\n logFileError: (message: string, filePath: string, line?: number, position?: number) => void;\n logFileWarning: (message: string, filePath: string, line?: number, position?: number) => void;\n}\n\ninterface IResxReaderOptionsInternal extends Omit<IResxReaderOptions, 'terminal'> {\n resxContents: string;\n loggingFunctions: ILoggingFunctions;\n}\n\n/**\n * @public\n */\nexport function readResxFileAsLocFile(options: IResxReaderOptions): ILocalizationFile {\n const resxContents: string = FileSystem.readFile(options.resxFilePath);\n return readResxAsLocFile(resxContents, options);\n}\n\n/**\n * @public\n */\nexport function readResxAsLocFile(resxContents: string, options: IResxReaderOptions): ILocalizationFile {\n const writeError: (message: string) => void = options.terminal.writeErrorLine.bind(options.terminal);\n const writeWarning: (message: string) => void = options.terminal.writeWarningLine.bind(options.terminal);\n const loggingFunctions: ILoggingFunctions = {\n logError: (message: string) => writeError(message),\n logWarning: (message: string) => writeWarning(message),\n logFileError: (message: string, filePath: string, line?: number, position?: number) => {\n _logWithLocation(writeError, message, filePath, line, position);\n },\n logFileWarning: (message: string, filePath: string, line?: number, position?: number) => {\n _logWithLocation(writeWarning, message, filePath, line, position);\n }\n };\n\n return _readResxAsLocFileInternal({\n ...options,\n resxContents,\n loggingFunctions\n });\n}\n\nfunction _readResxAsLocFileInternal(options: IResxReaderOptionsInternal): ILocalizationFile {\n const { ignoreString } = options;\n const xmlDocument: XmlDocument = new XmlDocument(options.resxContents);\n\n if (xmlDocument.name !== 'root') {\n _logErrorWithLocation(\n options,\n `Expected RESX to have a \"root\" element, found \"${xmlDocument.name}\"`,\n xmlDocument\n );\n }\n\n const locFile: ILocalizationFile = {};\n\n for (const childNode of xmlDocument.children) {\n switch (childNode.type) {\n case 'element': {\n switch (childNode.name) {\n case 'data': {\n const stringName: string = childNode.attr.name;\n if (!stringName) {\n _logErrorWithLocation(options, 'Unexpected missing or empty string name', childNode);\n } else if (!STRING_NAME_RESX.test(stringName)) {\n _logErrorWithLocation(options, `Invalid string name \"${stringName}\"`, childNode);\n } else {\n if (locFile.hasOwnProperty(stringName)) {\n _logErrorWithLocation(options, `Duplicate string value \"${stringName}\"`, childNode);\n }\n\n const locString: ILocalizedString | undefined = _readDataElement(options, childNode);\n\n if (locString && !ignoreString?.(options.resxFilePath, stringName)) {\n locFile[stringName] = locString;\n }\n }\n\n break;\n }\n\n // Other allowed elements\n case 'xsd:schema':\n case 'resheader':\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected RESX element ${childNode.name}`, childNode);\n }\n\n break;\n }\n\n case 'text': {\n if (childNode.text.trim() !== '') {\n _logErrorWithLocation(options, 'Found unexpected non-empty text node in RESX');\n }\n\n break;\n }\n\n case 'comment':\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected ${childNode.type} child in RESX`);\n break;\n }\n }\n\n return locFile;\n}\n\nfunction _readDataElement(\n options: IResxReaderOptionsInternal,\n dataElement: XmlElement\n): ILocalizedString | undefined {\n let foundCommentElement: boolean = false;\n let foundValueElement: boolean = false;\n let comment: string | undefined = undefined;\n let value: string | undefined = undefined;\n\n for (const childNode of dataElement.children) {\n switch (childNode.type) {\n case 'element': {\n switch (childNode.name) {\n case 'value': {\n if (foundValueElement) {\n _logErrorWithLocation(options, 'Duplicate <value> element found', childNode);\n } else {\n foundValueElement = true;\n value = _readTextElement(options, childNode);\n if (value && options.newlineNormalization) {\n value = Text.convertTo(value, options.newlineNormalization);\n }\n }\n\n break;\n }\n\n case 'comment': {\n if (foundCommentElement) {\n _logErrorWithLocation(options, 'Duplicate <comment> element found', childNode);\n } else {\n foundCommentElement = true;\n comment = _readTextElement(options, childNode);\n }\n\n break;\n }\n\n default:\n _logErrorWithLocation(options, `Unexpected RESX element ${childNode.name}`, childNode);\n break;\n }\n\n break;\n }\n\n case 'text': {\n if (childNode.text.trim() !== '') {\n _logErrorWithLocation(\n options,\n 'Found unexpected non-empty text node in RESX <data> element',\n dataElement\n );\n }\n\n break;\n }\n\n case 'comment':\n break;\n\n default:\n _logErrorWithLocation(\n options,\n `Unexpected ${childNode.type} child in RESX <data> element`,\n dataElement\n );\n }\n }\n\n if (!foundValueElement) {\n _logErrorWithLocation(options, 'Missing string value in <data> element', dataElement);\n } else {\n if (comment === undefined && options.warnOnMissingComment) {\n _logWarningWithLocation(options, 'Missing string comment in <data> element', dataElement);\n }\n\n return {\n value: value || '',\n comment\n };\n }\n}\n\nfunction _readTextElement(options: IResxReaderOptionsInternal, element: XmlElement): string | undefined {\n let foundText: string | undefined = undefined;\n\n for (const childNode of element.children) {\n switch (childNode.type) {\n case 'cdata':\n case 'text': {\n if (foundText !== undefined) {\n _logErrorWithLocation(options, 'More than one child node found containing text content', element);\n break;\n }\n\n foundText = childNode.type === 'text' ? childNode.text : childNode.cdata;\n break;\n }\n\n case 'comment':\n break;\n\n case 'element':\n _logErrorWithLocation(options, `Unexpected element`, childNode);\n break;\n\n default:\n _logErrorWithLocation(options, `Unexpected ${element.type} child`, element);\n break;\n }\n }\n\n return foundText;\n}\n\nfunction _logErrorWithLocation(\n options: IResxReaderOptionsInternal,\n message: string,\n element?: XmlElement | XmlDocument\n): void {\n if (element) {\n options.loggingFunctions.logFileError(\n message,\n options.resxFilePath,\n element.line + 1,\n element.column + 1\n );\n } else {\n options.loggingFunctions.logFileError(message, options.resxFilePath);\n }\n}\n\nfunction _logWarningWithLocation(\n options: IResxReaderOptionsInternal,\n message: string,\n element?: XmlElement | XmlDocument\n): void {\n if (element) {\n options.loggingFunctions.logFileWarning(\n message,\n options.resxFilePath,\n element.line + 1,\n element.column + 1\n );\n } else {\n options.loggingFunctions.logFileWarning(message, options.resxFilePath);\n }\n}\n\nfunction _logWithLocation(\n loggingFn: (message: string) => void,\n message: string,\n filePath: string,\n line?: number,\n position?: number\n): void {\n let location: string;\n if (position !== undefined) {\n location = `${filePath}(${line},${position})`;\n } else if (line !== undefined) {\n location = `${filePath}(${line})`;\n } else {\n location = filePath;\n }\n\n loggingFn(`${location}: ${message}`);\n}\n"]}