in packages/Ludown/lib/helpers.js [100:253]
splitFileBySections : function(fileContent, log) {
fileContent = helpers.sanitizeNewLines(fileContent);
let linesInFile = fileContent.split(NEWLINE);
let currentSection = '';
let middleOfSection = false;
let sectionsInFile = [];
let currentSectionType = null; //PARSERCONSTS
let inQnAAnswer = false;
let lineIndex = 0;
for(lineIndex in linesInFile) {
let currentLine = linesInFile[lineIndex].trim();
// QnA answer can be multi-line markdown. So (re)set the in answer flag
if(currentLine.indexOf(PARSERCONSTS.ANSWER) === 0) {
inQnAAnswer = !inQnAAnswer;
}
// if in QnA answer, just add the new line.
if(inQnAAnswer) {
currentSection += currentLine + NEWLINE;
continue;
}
// skip line if it is just a comment
if(currentLine.indexOf(PARSERCONSTS.COMMENT) === 0) {
// Add support to parse application metadata if found
let info = currentLine.split(/>[ ]*!#/g);
if (info === undefined || info.length === 1) continue;
if (currentSection !== null) {
let previousSection = currentSection.substring(0, currentSection.lastIndexOf(NEWLINE));
try {
sectionsInFile = validateAndPushCurrentBuffer(previousSection, sectionsInFile, currentSectionType, lineIndex, log);
} catch (err) {
throw (err);
}
}
currentSection = PARSERCONSTS.MODELINFO + info[1].trim() + NEWLINE;
currentSectionType = PARSERCONSTS.MODELINFO;
continue;
}
// skip line if it is blank
if(currentLine === '') continue;
// is this a FILEREF or URLREF section?
if((currentLine.indexOf(PARSERCONSTS.FILEREF) === 0) ||
(currentLine.indexOf(PARSERCONSTS.URLREF) === 0) ||
(currentLine.indexOf(PARSERCONSTS.URLORFILEREF) === 0)) {
// handle anything in currentSection buffer
if(currentSection !== null) {
var previousSection = currentSection.substring(0, currentSection.lastIndexOf(NEWLINE));
try {
sectionsInFile = validateAndPushCurrentBuffer(previousSection, sectionsInFile, currentSectionType, lineIndex, log);
} catch (err) {
throw(err);
}
}
currentSection = null;
sectionsInFile.push(currentLine);
middleOfSection = false;
} else if((currentLine.indexOf(PARSERCONSTS.INTENT) === 0)) {
if(currentLine.indexOf(' ') === -1) {
++lineIndex;
throw(new exception(retCode.errorCode.INVALID_INTENT, 'Error: Line #' + lineIndex + '. "' + currentLine + '" does not have valid intent definition'));
}
// handle anything in currentSection buffer
if(currentSection !== null) {
let previousSection = currentSection.substring(0, currentSection.lastIndexOf(NEWLINE));
try {
sectionsInFile = validateAndPushCurrentBuffer(previousSection, sectionsInFile, currentSectionType, lineIndex, log);
} catch (err) {
throw(err);
}
}
middleOfSection = true;
currentSectionType = PARSERCONSTS.INTENT;
currentSection = currentLine + NEWLINE;
} else if((currentLine.indexOf(PARSERCONSTS.ENTITY) === 0)) {
// handle anything in currentSection buffer
if(currentSection !== null) {
let previousSection = currentSection.substring(0, currentSection.lastIndexOf(NEWLINE));
try {
sectionsInFile = validateAndPushCurrentBuffer(previousSection, sectionsInFile, currentSectionType, lineIndex, log);
} catch (err) {
throw(err);
}
}
// is this a valid entity definition?
// Entities must have $<entityName>:<entityType> format
// List entities have $<entityName>:<normalizedvalue>= format
// Phrase list entities have $<entityName>:phraseList format
// only list entity and phrase list entity types can have multi-line definition
if(currentLine.toLowerCase().includes(':')) {
// get entity name and type
// Fix for #1137.
// Current code did not account for ':' in normalized values of list entities
let entityDef = currentLine.replace(PARSERCONSTS.ENTITY, '');
let entityType = entityDef.slice(entityDef.indexOf(':') + 1).trim();
// is entityType a phraseList?
if(entityType.trim().toLowerCase().includes('phraselist') || entityType.trim().toLowerCase().includes('qna-alterations')) {
middleOfSection = true;
currentSectionType = PARSERCONSTS.ENTITY;
currentSection = currentLine + NEWLINE;
} else if(LUISBuiltInTypes.includes(entityType.trim()) || entityType.trim().toLowerCase() === 'simple') {
// this is a built in type definition. Just add it.
sectionsInFile.push(currentLine);
middleOfSection = false;
currentSection = null;
} else if((currentLine.indexOf('=') >= 0)) {
let getRolesAndType = this.getRolesAndType(entityType);
// this is a list entity type
if(getRolesAndType.entityType.trim().endsWith('=')){
middleOfSection = true;
currentSectionType = PARSERCONSTS.ENTITY;
currentSection = currentLine + NEWLINE;
} else {
// this has inline role definition
sectionsInFile.push(currentLine);
middleOfSection = false;
currentSection = null;
}
} else if (entityType.startsWith('/') && entityType.endsWith('/')) {
// this is a regex entity.
sectionsInFile.push(currentLine);
middleOfSection = false;
currentSection = null;
} else if (entityType.startsWith('[') && entityType.endsWith(']')) {
// this is a composite entity.
sectionsInFile.push(currentLine);
middleOfSection = false;
currentSection = null;
} else {
throw (new exception(retCode.errorCode.INVALID_INPUT, '[ERROR] Invalid entity definition for ' + currentLine));
}
} else {
throw (new exception(retCode.errorCode.INVALID_INPUT, '[ERROR] Invalid entity definition for ' + currentLine));
}
} else {
if(middleOfSection) {
currentSection += currentLine + NEWLINE;
} else {
++lineIndex;
throw(new exception(retCode.errorCode.INVALID_LINE,'Error: Line #' + lineIndex + ' is not part of a Intent/ Entity/ QnA'));
}
}
}
// handle anything in currentSection buffer
if(currentSection !== null) {
let previousSection = currentSection.substring(0, currentSection.lastIndexOf(NEWLINE));
try {
sectionsInFile = validateAndPushCurrentBuffer(previousSection, sectionsInFile, currentSectionType, lineIndex, log);
} catch (err) {
throw (err);
}
}
return sectionsInFile;
},