This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community. Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it. https://www.freifunk-altdorf.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

408 lines
11 KiB

'use strict';
/**
* StyleSheets represents the StyleSheets found in the source code.
* @constructor
*/
function StyleSheets() {
this.styleSheets = {};
}
/**
* Add adds a StyleSheet to our StyleSheets collections.
*
* @param {string} styleSheetName - The name of the StyleSheet.
* @param {object} properties - The collection of rules in the styleSheet.
*/
StyleSheets.prototype.add = function (styleSheetName, properties) {
this.styleSheets[styleSheetName] = properties;
};
/**
* MarkAsUsed marks a rule as used in our source code by removing it from the
* specified StyleSheet rules.
*
* @param {string} fullyQualifiedName - The fully qualified name of the rule.
* for example 'styles.text'
*/
StyleSheets.prototype.markAsUsed = function (fullyQualifiedName) {
const nameSplit = fullyQualifiedName.split('.');
const styleSheetName = nameSplit[0];
const styleSheetProperty = nameSplit[1];
if (this.styleSheets[styleSheetName]) {
this.styleSheets[styleSheetName] = this
.styleSheets[styleSheetName]
.filter(property => property.key.name !== styleSheetProperty);
}
};
/**
* GetUnusedReferences returns all collected StyleSheets and their
* unmarked rules.
*/
StyleSheets.prototype.getUnusedReferences = function () {
return this.styleSheets;
};
/**
* AddColorLiterals adds an array of expressions that contain color literals
* to the ColorLiterals collection
* @param {array} expressions - an array of expressions containing color literals
*/
StyleSheets.prototype.addColorLiterals = function (expressions) {
if (!this.colorLiterals) {
this.colorLiterals = [];
}
this.colorLiterals = this.colorLiterals.concat(expressions);
};
/**
* GetColorLiterals returns an array of collected color literals expressions
* @returns {Array}
*/
StyleSheets.prototype.getColorLiterals = function () {
return this.colorLiterals;
};
/**
* AddObjectexpressions adds an array of expressions to the ObjectExpressions collection
* @param {Array} expressions - an array of expressions containing ObjectExpressions in
* inline styles
*/
StyleSheets.prototype.addObjectExpressions = function (expressions) {
if (!this.objectExpressions) {
this.objectExpressions = [];
}
this.objectExpressions = this.objectExpressions.concat(expressions);
};
/**
* GetObjectExpressions returns an array of collected object expressiosn used in inline styles
* @returns {Array}
*/
StyleSheets.prototype.getObjectExpressions = function () {
return this.objectExpressions;
};
let currentContent;
const getSourceCode = node => currentContent
.getSourceCode(node)
.getText(node);
const astHelpers = {
containsStyleSheetObject: function (node) {
return Boolean(
node &&
node.init &&
node.init.callee &&
node.init.callee.object &&
node.init.callee.object.name === 'StyleSheet'
);
},
containsCreateCall: function (node) {
return Boolean(
node &&
node.init &&
node.init.callee &&
node.init.callee.property &&
node.init.callee.property.name === 'create'
);
},
isStyleSheetDeclaration: function (node) {
return Boolean(
astHelpers.containsStyleSheetObject(node) &&
astHelpers.containsCreateCall(node)
);
},
getStyleSheetName: function (node) {
if (
node &&
node.id
) {
return node.id.name;
}
},
getStyleDeclarations: function (node) {
if (
node &&
node.init &&
node.init.arguments &&
node.init.arguments[0] &&
node.init.arguments[0].properties
) {
return node
.init
.arguments[0]
.properties
.filter(property => property.type === 'Property');
}
return [];
},
isStyleAttribute: function (node) {
return Boolean(
node.type === 'JSXAttribute' &&
node.name &&
node.name.name &&
node.name.name.toLowerCase().includes('style')
);
},
collectStyleObjectExpressions: function (node, context) {
currentContent = context;
if (astHelpers.hasArrayOfStyleReferences(node)) {
const styleReferenceContainers = node
.expression
.elements;
return astHelpers.collectStyleObjectExpressionFromContainers(
styleReferenceContainers
);
} else if (node && node.expression) {
return astHelpers.getStyleObjectExpressionFromNode(node.expression);
}
return [];
},
collectColorLiterals: function (node, context) {
if (!node) {
return [];
}
currentContent = context;
if (astHelpers.hasArrayOfStyleReferences(node)) {
const styleReferenceContainers = node
.expression
.elements;
return astHelpers.collectColorLiteralsFromContainers(
styleReferenceContainers
);
}
if (node.type === 'ObjectExpression') {
return astHelpers.getColorLiteralsFromNode(node);
}
return astHelpers.getColorLiteralsFromNode(node.expression);
},
collectStyleObjectExpressionFromContainers: function (nodes) {
let objectExpressions = [];
nodes.forEach((node) => {
objectExpressions = objectExpressions
.concat(astHelpers.getStyleObjectExpressionFromNode(node));
});
return objectExpressions;
},
collectColorLiteralsFromContainers: function (nodes) {
let colorLiterals = [];
nodes.forEach((node) => {
colorLiterals = colorLiterals
.concat(astHelpers.getColorLiteralsFromNode(node));
});
return colorLiterals;
},
getStyleReferenceFromNode: function (node) {
let styleReference;
let leftStyleReferences;
let rightStyleReferences;
if (!node) {
return [];
}
switch (node.type) {
case 'MemberExpression':
styleReference = astHelpers.getStyleReferenceFromExpression(node);
return [styleReference];
case 'LogicalExpression':
leftStyleReferences = astHelpers.getStyleReferenceFromNode(node.left);
rightStyleReferences = astHelpers.getStyleReferenceFromNode(node.right);
return [].concat(leftStyleReferences).concat(rightStyleReferences);
case 'ConditionalExpression':
leftStyleReferences = astHelpers.getStyleReferenceFromNode(node.consequent);
rightStyleReferences = astHelpers.getStyleReferenceFromNode(node.alternate);
return [].concat(leftStyleReferences).concat(rightStyleReferences);
default:
return [];
}
},
getStyleObjectExpressionFromNode: function (node) {
let leftStyleObjectExpression;
let rightStyleObjectExpression;
if (!node) {
return [];
}
if (node.type === 'ObjectExpression') {
return [astHelpers.getStyleObjectFromExpression(node)];
}
switch (node.type) {
case 'LogicalExpression':
leftStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.left);
rightStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.right);
return [].concat(leftStyleObjectExpression).concat(rightStyleObjectExpression);
case 'ConditionalExpression':
leftStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.consequent);
rightStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.alternate);
return [].concat(leftStyleObjectExpression).concat(rightStyleObjectExpression);
default:
return [];
}
},
getColorLiteralsFromNode: function (node) {
let leftColorLiterals;
let rightColorLiterals;
if (!node) {
return [];
}
if (node.type === 'ObjectExpression') {
return [astHelpers.getColorLiteralsFromExpression(node)];
}
switch (node.type) {
case 'LogicalExpression':
leftColorLiterals = astHelpers.getColorLiteralsFromNode(node.left);
rightColorLiterals = astHelpers.getColorLiteralsFromNode(node.right);
return [].concat(leftColorLiterals).concat(rightColorLiterals);
case 'ConditionalExpression':
leftColorLiterals = astHelpers.getColorLiteralsFromNode(node.consequent);
rightColorLiterals = astHelpers.getColorLiteralsFromNode(node.alternate);
return [].concat(leftColorLiterals).concat(rightColorLiterals);
default:
return [];
}
},
hasArrayOfStyleReferences: function (node) {
return node && Boolean(
node.type === 'JSXExpressionContainer' &&
node.expression &&
node.expression.type === 'ArrayExpression'
);
},
getStyleReferenceFromExpression: function (node) {
const result = [];
const name = astHelpers.getObjectName(node);
if (name) {
result.push(name);
}
const property = astHelpers.getPropertyName(node);
if (property) {
result.push(property);
}
return result.join('.');
},
getStyleObjectFromExpression: function (node) {
const obj = {};
let invalid = false;
if (node.properties && node.properties.length) {
node.properties.forEach((p) => {
if (!p.value || !p.key) {
return;
}
if (p.value.type === 'Literal') {
invalid = true;
obj[p.key.name] = p.value.value;
} else if (p.value.type === 'ConditionalExpression') {
const innerNode = p.value;
if (innerNode.consequent.type === 'Literal' || innerNode.alternate.type === 'Literal') {
invalid = true;
obj[p.key.name] = getSourceCode(innerNode);
}
} else if (p.value.type === 'UnaryExpression' && p.value.operator === '-') {
invalid = true;
obj[p.key.name] = -1 * p.value.argument.value;
} else if (p.value.type === 'UnaryExpression' && p.value.operator === '+') {
invalid = true;
obj[p.key.name] = p.value.argument.value;
}
});
}
return invalid ? { expression: obj, node: node } : undefined;
},
getColorLiteralsFromExpression: function (node) {
const obj = {};
let invalid = false;
if (node.properties && node.properties.length) {
node.properties.forEach((p) => {
if (p.key && p.key.name && p.key.name.toLowerCase().indexOf('color') !== -1) {
if (p.value.type === 'Literal') {
invalid = true;
obj[p.key.name] = p.value.value;
} else if (p.value.type === 'ConditionalExpression') {
const innerNode = p.value;
if (innerNode.consequent.type === 'Literal' || innerNode.alternate.type === 'Literal') {
invalid = true;
obj[p.key.name] = getSourceCode(innerNode);
}
}
}
});
}
return invalid ? { expression: obj, node: node } : undefined;
},
getObjectName: function (node) {
if (
node &&
node.object &&
node.object.name
) {
return node.object.name;
}
},
getPropertyName: function (node) {
if (
node &&
node.property &&
node.property.name
) {
return node.property.name;
}
},
getPotentialStyleReferenceFromMemberExpression: function (node) {
if (
node &&
node.object &&
node.object.type === 'Identifier' &&
node.object.name &&
node.property &&
node.property.type === 'Identifier' &&
node.property.name &&
node.parent.type !== 'MemberExpression'
) {
return [node.object.name, node.property.name].join('.');
}
},
};
module.exports.astHelpers = astHelpers;
module.exports.StyleSheets = StyleSheets;