Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit b8dd193

Browse files
authored
Merge pull request #156 from microsoft/emimunoz/config
Fix for ludown sort
2 parents 2132729 + 47252a5 commit b8dd193

File tree

16 files changed

+293
-222
lines changed

16 files changed

+293
-222
lines changed

packages/luis/README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ USAGE
3030
<!-- commands -->
3131
* [`bf luis:convert`](#bf-luisconvert)
3232
* [`bf luis:translate`](#bf-luistranslate)
33-
* [`bf qnamaker:convert [FILE]`](#bf-qnamakerconvert-file)
34-
* [`bf qnamker:convert`](#bf-qnamkerconvert)
33+
* [`bf qnamaker:convert`](#bf-qnamakerconvert)
34+
* [`bf qnamaker:translate [FILE]`](#bf-qnamakertranslate-file)
3535

3636
## `bf luis:convert`
3737

@@ -77,39 +77,39 @@ OPTIONS
7777

7878
_See code: [src/commands/luis/translate.ts](https://github.com/microsoft/botframework-cli/blob/v1.0.0/src/commands/luis/translate.ts)_
7979

80-
## `bf qnamaker:convert [FILE]`
80+
## `bf qnamaker:convert`
8181

82-
describe the command here
82+
Convert .lu file(s) to a QnA application JSON model or vice versa
8383

8484
```
8585
USAGE
86-
$ bf qnamaker:convert [FILE]
86+
$ bf qnamaker:convert
8787
8888
OPTIONS
89-
-f, --force
90-
-h, --help show CLI help
91-
-n, --name=name name to print
89+
--alterations Indicates if files is QnA Alterations
90+
--in=in (required) Source .qna file(s) or QnA KB JSON file
91+
--log Enables log messages
92+
--name=name Name of the QnA KB
93+
--out=out Output file or folder name. If not specified stdout will be used as output
94+
--recurse Indicates if sub-folders need to be considered to file .qna file(s)
95+
--sort When set, questions collections are alphabetically sorted are alphabetically sorted in .lu files
9296
```
9397

9498
_See code: [src/commands/qnamaker/convert.ts](https://github.com/microsoft/botframework-cli/blob/v1.0.0/src/commands/qnamaker/convert.ts)_
9599

96-
## `bf qnamker:convert`
100+
## `bf qnamaker:translate [FILE]`
97101

98102
describe the command here
99103

100104
```
101105
USAGE
102-
$ bf qnamker:convert
106+
$ bf qnamaker:translate [FILE]
103107
104108
OPTIONS
105-
--alterations Indicates if files is QnA Alterations
106-
--in=in (required) Source .qna file(s) or QnA KB JSON file
107-
--log Enables log messages
108-
--name=name Name of the QnA KB
109-
--out=out Output file or folder name. If not specified stdout will be used as output
110-
--recurse Indicates if sub-folders need to be considered to file .qna file(s)
111-
--sort When set, questions collections are alphabetically sorted are alphabetically sorted in .lu files
109+
-f, --force
110+
-h, --help show CLI help
111+
-n, --name=name name to print
112112
```
113113

114-
_See code: [src/commands/qnamker/convert.ts](https://github.com/microsoft/botframework-cli/blob/v1.0.0/src/commands/qnamker/convert.ts)_
114+
_See code: [src/commands/qnamaker/translate.ts](https://github.com/microsoft/botframework-cli/blob/v1.0.0/src/commands/qnamaker/translate.ts)_
115115
<!-- commandsstop -->

packages/luis/parser/converters/luistoluconverter.js

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const path = require('path')
44
const txtfile = require('./../lufile/read-text-file')
55
const luisFile = require('./../luisfile/parseLuisFile')
66
const helperClasses = require('./../lufile/classes/hclasses')
7-
const exception = ('./../lufile/classes/exception')
7+
const exception = require('./../lufile/classes/exception')
88
const retCode = require('./../lufile/enums/CLI-errors')
99

1010
module.exports = {
@@ -105,7 +105,7 @@ module.exports = {
105105
});
106106
fileContent += NEWLINE;
107107
}
108-
108+
109109
if(LUISJSON.prebuiltEntities && LUISJSON.prebuiltEntities.length >= 0){
110110
fileContent += '> # PREBUILT Entity definitions' + NEWLINE + NEWLINE;
111111
LUISJSON.prebuiltEntities.forEach(function(entity) {
@@ -182,7 +182,6 @@ const parseLuis = async function(luisObject, src, sort){
182182
if (sort) {
183183
await sortLUISJSON(LUISJSON.model)
184184
}
185-
186185
return LUISJSON
187186
}
188187

@@ -266,22 +265,38 @@ constructModelDescFromLUISJSON = async function(LUISJSON) {
266265
*/
267266
const sortLUISJSON = async function(LUISJSON) {
268267
// sort intents first
269-
LUISJSON.intents.sort(sortComparers.compareNameFn);
270-
LUISJSON.composites.sort(sortComparers.compareNameFn);
271-
LUISJSON.entities.sort(sortComparers.compareNameFn);
272-
LUISJSON.closedLists.sort(sortComparers.compareNameFn);
273-
LUISJSON.regex_entities.sort(sortComparers.compareNameFn);
274-
LUISJSON.model_features.sort(sortComparers.compareNameFn);
275-
LUISJSON.patternAnyEntities.sort(sortComparers.compareNameFn);
276-
LUISJSON.prebuiltEntities.sort(sortComparers.compareNameFn);
277-
LUISJSON.utterances.sort(sortComparers.compareIntentFn);
268+
try {
269+
LUISJSON.intents.sort(sortComparers.compareNameFn);
270+
LUISJSON.composites.sort(sortComparers.compareNameFn);
271+
LUISJSON.entities.sort(sortComparers.compareNameFn);
272+
LUISJSON.closedLists.sort(sortComparers.compareNameFn);
273+
LUISJSON.regex_entities.sort(sortComparers.compareNameFn);
274+
LUISJSON.model_features.sort(sortComparers.compareNameFn);
275+
LUISJSON.patternAnyEntities.sort(sortComparers.compareNameFn);
276+
LUISJSON.prebuiltEntities.sort(sortComparers.compareNameFn);
277+
LUISJSON.utterances.sort(sortComparers.compareIntentFn);
278+
} catch (e) {
279+
throw (new exception(retCode.errorCode.INVALID_INPUT, 'Sorry, invalid LUIS json object'));
280+
}
278281
}
279282

280-
const sortComparers = {
283+
const sortComparers = {
281284
compareNameFn : function(a, b) {
282-
return a.name.toUpperCase() > b.name.toUpperCase();
285+
return compareString(a.name.toUpperCase(), b.name.toUpperCase())
283286
},
284287
compareIntentFn : function(a, b) {
285-
return a.intent.toUpperCase() > b.intent.toUpperCase();
288+
return compareString(a.intent.toUpperCase(), b.intent.toUpperCase())
286289
}
290+
}
291+
292+
const compareString = function(a, b) {
293+
if (a < b) {
294+
return -1;
295+
}
296+
297+
if (a > b) {
298+
return 1;
299+
}
300+
301+
return 0;
287302
}

packages/luis/parser/converters/qnajsontoqnaconverter.js

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const path = require('path')
44
const txtfile = require('./../lufile/read-text-file')
55
const qnaFile = require('./../qnafile/parseQnAFile')
66
const helperClasses = require('./../lufile/classes/hclasses')
7-
const exception = ('./../lufile/classes/exception')
7+
const exception = require('./../lufile/classes/exception')
88
const retCode = require('./../lufile/enums/CLI-errors')
99

1010
module.exports = {
@@ -28,7 +28,7 @@ module.exports = {
2828
*/
2929
constructMdFromQnAAlterationJSON: function(QnAAltJSON) {
3030
let fileContent = '> # QnA Alterations' + NEWLINE + NEWLINE;
31-
if(QnAAltJSON.wordAlterations.length > 0) {
31+
if(QnAAltJSON.wordAlterations && QnAAltJSON.wordAlterations.length > 0) {
3232
QnAAltJSON.wordAlterations.forEach(function(alteration) {
3333
fileContent += '$' + alteration.alterations[0] + ' : ' + 'qna-alterations = ' + NEWLINE;
3434
alteration.alterations.splice(0, 1);
@@ -102,21 +102,29 @@ const parseQnA= async function(qnaObject, src, sort, isAlterations){
102102
* @param {Object} QnAJSON
103103
*/
104104
const sortQnAJSON = function(QnAJSON) {
105-
(QnAJSON.qnaList || []).forEach(pair => {
106-
pair.questions.sort(sortComparers.compareFn);
107-
});
108-
QnAJSON.qnaList.sort(sortComparers.compareQn);
105+
try {
106+
(QnAJSON.qnaList || []).forEach(pair => {
107+
pair.questions.sort(sortComparers.compareFn);
108+
});
109+
QnAJSON.qnaList.sort(sortComparers.compareQn);
110+
} catch (e) {
111+
throw (new exception(retCode.errorCode.INVALID_INPUT, 'Sorry, invalid QnA Maker json object'));
112+
}
109113
};
110114

111115
/**
112116
* Helper function to return sorted QnA Alterations pair
113117
* @param {Object} QnAAltJSON
114118
*/
115119
const sortQnAAltJSON = function(QnAAltJSON) {
116-
(QnAAltJSON.wordAlterations || []).forEach(word => {
117-
word.alterations.sort(sortComparers.compareFn);
118-
});
119-
QnAAltJSON.wordAlterations.sort(sortComparers.compareAltName);
120+
try {
121+
(QnAAltJSON.wordAlterations || []).forEach(word => {
122+
word.alterations.sort(sortComparers.compareFn);
123+
});
124+
QnAAltJSON.wordAlterations.sort(sortComparers.compareAltName);
125+
} catch (e) {
126+
throw (new exception(retCode.errorCode.INVALID_INPUT, 'Sorry, invalid QnA Maker json object'));
127+
}
120128
};
121129

122130
/**
@@ -125,14 +133,26 @@ const sortQnAAltJSON = function(QnAAltJSON) {
125133
const sortComparers = {
126134

127135
compareAltName : function(a, b) {
128-
return a.alterations[0].toUpperCase() > b.alterations[0].toUpperCase();
136+
return compareString(a.alterations[0].toUpperCase(), b.alterations[0].toUpperCase())
129137
},
130138
compareFn : function(a, b) {
131-
return a.toUpperCase() > b.toUpperCase();
139+
return compareString(a.toUpperCase(), b.toUpperCase())
132140
},
133141
compareQn : function(a, b) {
134-
return a.questions[0].toUpperCase() > b.questions[0].toUpperCase();
142+
return compareString(a.questions[0].toUpperCase(), b.questions[0].toUpperCase())
143+
}
144+
}
145+
146+
const compareString = function(a, b) {
147+
if (a < b) {
148+
return -1;
149+
}
150+
151+
if (a > b) {
152+
return 1;
135153
}
154+
155+
return 0;
136156
}
137157

138158
const openFileAndReadContent = async function(file) {

packages/luis/parser/luisfile/parseLuisFile.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const exception = ('./../lufile/classes/exception')
1+
const exception = require('./../lufile/classes/exception')
22
const helpers = require('./../lufile/helpers');
33
const retCode = require('./../lufile/enums/CLI-errors');
44
const helperClass = require('./../lufile/classes/hclasses');
@@ -12,9 +12,7 @@ module.exports = {
1212
} catch (err) {
1313
throw (new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, error parsing file as LUIS JSON: ' + file));
1414
}
15-
if(!await validateLUISJSON(LUISJSON)){
16-
throw(new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, invalid input LUIS JSON. Cannot convert to .lu file.'));
17-
}
15+
await validateLUISJSON(LUISJSON)
1816
return LUISJSON;
1917
},
2018
/**
@@ -175,10 +173,9 @@ module.exports = {
175173

176174
const validateLUISJSON = async function(LUISJSON) {
177175
if(!LUISJSON.intents && !LUISJSON.entities) {
178-
return false;
176+
throw new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, input LUIS JSON file has no intents and entities');
179177
}
180178
if(LUISJSON.regex_features && LUISJSON.regex_features.length !== 0) {
181-
throw(new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, input LUIS JSON file has references to regex_features. Cannot convert to .lu file.'));
179+
throw new exception(retCode.errorCode.INVALID_INPUT_FILE, 'Sorry, input LUIS JSON file has references to regex_features. Cannot convert to .lu file.');
182180
}
183-
return true;
184181
}

packages/luis/parser/translator/lutranslate.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,28 @@ const retCode = require('./../lufile/enums/CLI-errors')
66
const translateHelpers = require('./../lufile/translate-helpers')
77

88
module.exports = {
9-
translateLu: async function(files, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
9+
translateLuFile: async function(files, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
1010
let translation = {}
1111
let i = 0
1212
while(files.length > i) {
1313
let file = files[i++] + ''
1414
try {
15-
translation[path.basename(file)] = await parseFile(file, translate_key, to_lang, src_lang, translate_comments, translate_link_text)
15+
let luObject = await parseFile(file)
16+
translation[path.basename(file)] = await this.translateLuObj(luObject, translate_key, to_lang, src_lang, translate_comments, translate_link_text)
1617
} catch (err) {
1718
throw(err);
1819
}
1920
}
2021
return translation
22+
},
23+
translateLuObj: async function(luObject, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
24+
let translation = {}
25+
try {
26+
translation = await translateLuObject(luObject, translate_key, to_lang, src_lang, translate_comments, translate_link_text)
27+
} catch (err) {
28+
throw(err);
29+
}
30+
return translation
2131
}
2232
}
2333

@@ -32,26 +42,29 @@ module.exports = {
3242
* @returns {void} nothing
3343
* @throws {exception} Throws on errors. exception object includes errCode and text.
3444
*/
35-
async function parseFile(file, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
45+
async function parseFile(file) {
3646
if(!fs.existsSync(path.resolve(file))) {
3747
throw(new exception(retCode.errorCode.FILE_OPEN_ERROR, 'Sorry unable to open [' + file + ']'));
3848
}
3949
let fileContent = txtfile.readSync(file);
4050
if (!fileContent) {
4151
throw(new exception(retCode.errorCode.FILE_OPEN_ERROR, 'Sorry, error reading file:' + file));
4252
}
53+
return fileContent
54+
}
4355

56+
async function translateLuObject(luObject, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
4457
let parsedLocContent = ''
4558
let result = {}
4659
// Support multi-language specification for targets.
4760
// Accepted formats are space or comma separated list of target language codes.
4861
// Tokenize to_lang
49-
let toLang = to_lang.split(/[, ]/g);
62+
let toLang = to_lang.split(/[, ]/g)
5063
for (idx in toLang) {
5164
let tgt_lang = toLang[idx].trim();
5265
if (tgt_lang === '') continue;
5366
try {
54-
parsedLocContent = await translateHelpers.parseAndTranslate(fileContent, translate_key, tgt_lang, src_lang, translate_comments, translate_link_text, false, undefined)
67+
parsedLocContent = await translateHelpers.parseAndTranslate(luObject, translate_key, tgt_lang, src_lang, translate_comments, translate_link_text, false)
5568
} catch (err) {
5669
throw(err);
5770
}

0 commit comments

Comments
 (0)