354 lines
8.4 KiB
JavaScript
354 lines
8.4 KiB
JavaScript
//
|
|
//#region Imports ...
|
|
const XFileTools = require('../tools/x-file.tools');
|
|
const XValueTools = require('../tools/x-value.tools');
|
|
const XBaseDescriptor = require('./x-base.descriptor');
|
|
const XContentDescriptor = require('./x-content.descriptor');
|
|
//#endregion
|
|
|
|
/**
|
|
* check an object instance is ConstDescriptor or not ...
|
|
*
|
|
* @param {any} object proposed object to check ...
|
|
* @returns
|
|
*/
|
|
function isDescriptor(object) {
|
|
//
|
|
if (!object) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
let result = false;
|
|
result =
|
|
object.hasOwnProperty('raw') &&
|
|
object.hasOwnProperty('name') &&
|
|
object.hasOwnProperty('content') &&
|
|
object.hasOwnProperty('isExported');
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* retrieve base or filled ConstDescriptor object instance ...
|
|
*
|
|
* @param {any} value a value provider object ...
|
|
* @returns an instance of ConstDescriptor object ...
|
|
*/
|
|
function createDescriptor(value) {
|
|
//
|
|
let result = {
|
|
raw: '',
|
|
name: '',
|
|
type: '',
|
|
content: {
|
|
...XContentDescriptor.createDescriptor()
|
|
},
|
|
isExported: false,
|
|
};
|
|
|
|
//
|
|
//#region Apply Value ...
|
|
if (value) {
|
|
//
|
|
//#region raw ...
|
|
if (XValueTools.isValidArg(value.raw)) {
|
|
result.raw = value.raw;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region name ...
|
|
if (XValueTools.isValidArg(value.name)) {
|
|
result.name = value.name;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region type ...
|
|
if (XValueTools.isValidArg(value.type)) {
|
|
result.type = value.type;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region content ...
|
|
if (
|
|
value.content &&
|
|
XContentDescriptor.isDescriptor(value.content)
|
|
) {
|
|
result.content = { ...value.content };
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region isExported ...
|
|
if (!!value.isExported) {
|
|
result.isExported = value.isExported;
|
|
}
|
|
//#endregion
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* converts an instance of Descriptor to Expression ...
|
|
*
|
|
* @param descriptor an instance of ConstDescriptor ...
|
|
* @returns creator string ...
|
|
*/
|
|
function toExpression(descriptor = createDescriptor()) {
|
|
//
|
|
let result = '';
|
|
|
|
//
|
|
// Validate Arg ...
|
|
if (!isDescriptor(descriptor)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result += (
|
|
!!descriptor.isExported ?
|
|
XBaseDescriptor.ExpressionKeys.Export + ' ' :
|
|
''
|
|
) +
|
|
XBaseDescriptor.ExpressionKeys.Const +
|
|
' ' +
|
|
descriptor.name +
|
|
(
|
|
XValueTools.isValidArg(descriptor.type) ?
|
|
': ' +
|
|
descriptor.type :
|
|
''
|
|
) +
|
|
' = ';
|
|
|
|
//
|
|
let contentExpression = XContentDescriptor.toExpression(descriptor.content, ':');
|
|
if (XValueTools.isValidArg(contentExpression)) {
|
|
result += contentExpression;
|
|
}
|
|
|
|
//
|
|
result += ';';
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* extract all exists ConstDescriptors ...
|
|
*
|
|
* @param {string} file a file path ...
|
|
* @returns a collection of ConstDescriptors ...
|
|
*/
|
|
async function extractDescriptors(file = '') {
|
|
//
|
|
if (!XFileTools.isFileExists(file)) {
|
|
return [];
|
|
}
|
|
|
|
//
|
|
const fileContent = await XFileTools.readFile(file);
|
|
if (!XValueTools.isValidArg(fileContent)) {
|
|
return [];
|
|
}
|
|
|
|
//
|
|
let result = [
|
|
createDescriptor()
|
|
];
|
|
result.pop();
|
|
|
|
//
|
|
result = extractDescriptorsFromContent(fileContent);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* extract all exists ConstDescriptors ...
|
|
*
|
|
* @param {string} content a file content ...
|
|
* @returns a collection of ConstDescriptors ...
|
|
*/
|
|
function extractDescriptorsFromContent(content = '') {
|
|
//
|
|
// Prepare result ...
|
|
let result = [
|
|
createDescriptor()
|
|
];
|
|
result.pop();
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
!XValueTools.isValidArg(content) ||
|
|
!content.includes(XBaseDescriptor.ExpressionKeys.Const)
|
|
) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract all Key Indexes ...
|
|
const keyIndexes = XBaseDescriptor.
|
|
extractValidIdentifierIndexes(XBaseDescriptor.ExpressionKeys.Const, content);
|
|
|
|
//
|
|
// Validate Keys Exists on Content ...
|
|
if (!XValueTools.hasChildArray(keyIndexes)) {
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through indexes ...
|
|
for (let index of keyIndexes) {
|
|
//
|
|
let startIndex = index - 1;
|
|
let endIndex = index + XBaseDescriptor.ExpressionKeys.Const.length + 1;
|
|
|
|
//
|
|
// create an empty instance of descriptor ...
|
|
let descriptor = {
|
|
...createDescriptor()
|
|
}
|
|
|
|
//
|
|
//#region Name and Type extractor ...
|
|
const nameEndIndex = content.indexOf('=', index);
|
|
identifier = content
|
|
.substring(index + XBaseDescriptor.ExpressionKeys.Const.length, nameEndIndex)
|
|
.trim();
|
|
if (XValueTools.isValidArg(identifier)) {
|
|
//
|
|
// Check to Extract Type ...
|
|
if (identifier.includes(':')) {
|
|
//
|
|
startIndex = 0;
|
|
endIndex = identifier.indexOf(':', startIndex);
|
|
|
|
//
|
|
descriptor.name = identifier
|
|
.substring(startIndex, endIndex)
|
|
.trim();
|
|
|
|
//
|
|
// Type extraction ...
|
|
startIndex = endIndex + 1;
|
|
descriptor.type = identifier
|
|
.substring(startIndex)
|
|
.trim();
|
|
} else {
|
|
descriptor.name = identifier;
|
|
}
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Extract isExported ...
|
|
const isExported = XBaseDescriptor.checkIsExported(index, content);
|
|
descriptor.isExported = isExported;
|
|
if (isExported) {
|
|
startIndex = index - XBaseDescriptor.ExpressionKeys.Export.length - 1;
|
|
} else {
|
|
startIndex = index;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Extract raw content ...
|
|
identifier = content.substring(startIndex);
|
|
startIndex = 0;
|
|
endIndex = XValueTools.findNearestIndex(
|
|
[
|
|
';',
|
|
'{',
|
|
'[',
|
|
'\n'
|
|
],
|
|
identifier,
|
|
0 // nameEndIndex - startIndex
|
|
);
|
|
const nearestChar = identifier.charAt(endIndex);
|
|
if (nearestChar === '{') {
|
|
//
|
|
const closedItemsIndexes = XValueTools.findClosedContent('{', '}', identifier, endIndex);
|
|
if (!XValueTools.hasChildArray(closedItemsIndexes)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
endIndex = closedItemsIndexes[0].end;
|
|
} else if (nearestChar === '[') {
|
|
//
|
|
const closedItemsIndexes = XValueTools.findClosedContent('[', ']', identifier, endIndex);
|
|
if (!XValueTools.hasChildArray(closedItemsIndexes)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
endIndex = closedItemsIndexes[0].end;
|
|
}
|
|
|
|
//
|
|
identifier = identifier
|
|
.substring(startIndex, endIndex + 1)
|
|
.trim();
|
|
if (XValueTools.isValidArg(identifier)) {
|
|
descriptor.raw = identifier;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Parse Content ...
|
|
startIndex = identifier.indexOf('=', 0);
|
|
let contentContainer = identifier
|
|
.substring(startIndex + 1)
|
|
.trim()
|
|
|
|
//
|
|
// Clear Content ...
|
|
contentContainer = XBaseDescriptor
|
|
.clearContent(contentContainer);
|
|
|
|
//
|
|
const contentType = XBaseDescriptor.getContentType(contentContainer);
|
|
const parsedContents = XBaseDescriptor.parseContent(contentContainer) || [];
|
|
const contentDescriptor = XContentDescriptor.createDescriptor();
|
|
|
|
//
|
|
contentDescriptor.type = contentType;
|
|
contentDescriptor.childs = [
|
|
...parsedContents
|
|
];
|
|
|
|
//
|
|
descriptor.content = {
|
|
...contentDescriptor
|
|
};
|
|
//#endregion
|
|
|
|
//
|
|
result.push(descriptor);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Module Exports ...
|
|
module.exports = {
|
|
//
|
|
isDescriptor,
|
|
toExpression,
|
|
createDescriptor,
|
|
extractDescriptors,
|
|
extractDescriptorsFromContent,
|
|
} |