Initial commit
This commit is contained in:
121
out/analyzer/CSSAnalyzer.js
Normal file
121
out/analyzer/CSSAnalyzer.js
Normal file
@@ -0,0 +1,121 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CSSAnalyzer = void 0;
|
||||
class CSSAnalyzer {
|
||||
extractSelectors(document) {
|
||||
const selectors = new Map();
|
||||
const text = document.getText();
|
||||
// Parse CSS/SCSS using regex-based approach
|
||||
this.parseStylesheet(text, selectors);
|
||||
return selectors;
|
||||
}
|
||||
parseStylesheet(text, selectors) {
|
||||
const lines = text.split('\n');
|
||||
let inComment = false;
|
||||
let inRule = false;
|
||||
let braceCount = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
// Handle multi-line comments
|
||||
if (inComment) {
|
||||
const commentEnd = line.indexOf('*/');
|
||||
if (commentEnd !== -1) {
|
||||
inComment = false;
|
||||
line = line.substring(commentEnd + 2);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Remove single-line comments
|
||||
const commentStart = line.indexOf('//');
|
||||
if (commentStart !== -1) {
|
||||
line = line.substring(0, commentStart);
|
||||
}
|
||||
// Handle multi-line comment start
|
||||
const multiCommentStart = line.indexOf('/*');
|
||||
if (multiCommentStart !== -1) {
|
||||
const multiCommentEnd = line.indexOf('*/', multiCommentStart);
|
||||
if (multiCommentEnd !== -1) {
|
||||
line = line.substring(0, multiCommentStart) + line.substring(multiCommentEnd + 2);
|
||||
}
|
||||
else {
|
||||
inComment = true;
|
||||
line = line.substring(0, multiCommentStart);
|
||||
}
|
||||
}
|
||||
// Count braces to track nesting
|
||||
const openBraces = (line.match(/\{/g) || []).length;
|
||||
const closeBraces = (line.match(/\}/g) || []).length;
|
||||
// If we're not in a rule and line contains a selector pattern
|
||||
if (!inRule && braceCount === 0) {
|
||||
const selectorMatch = this.extractSelectorFromLine(line, i);
|
||||
if (selectorMatch) {
|
||||
selectors.set(selectorMatch.selector, {
|
||||
line: i,
|
||||
character: selectorMatch.character,
|
||||
length: selectorMatch.length
|
||||
});
|
||||
}
|
||||
}
|
||||
braceCount += openBraces - closeBraces;
|
||||
inRule = braceCount > 0;
|
||||
}
|
||||
}
|
||||
extractSelectorFromLine(line, lineNumber) {
|
||||
// Remove leading/trailing whitespace
|
||||
const trimmed = line.trim();
|
||||
// Skip empty lines, variables, imports, mixins, etc.
|
||||
if (!trimmed ||
|
||||
trimmed.startsWith('$') ||
|
||||
trimmed.startsWith('@') ||
|
||||
trimmed.startsWith('//') ||
|
||||
trimmed.startsWith('/*') ||
|
||||
!trimmed.includes('{')) {
|
||||
return null;
|
||||
}
|
||||
// Extract selector part (everything before the opening brace)
|
||||
const braceIndex = trimmed.indexOf('{');
|
||||
if (braceIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
const selectorPart = trimmed.substring(0, braceIndex).trim();
|
||||
// Validate that this looks like a CSS selector
|
||||
if (this.isValidSelector(selectorPart)) {
|
||||
const character = line.indexOf(selectorPart);
|
||||
return {
|
||||
selector: selectorPart,
|
||||
character: character >= 0 ? character : 0,
|
||||
length: selectorPart.length
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
isValidSelector(selector) {
|
||||
// Skip SCSS control structures and mixins
|
||||
if (selector.startsWith('@') ||
|
||||
selector.includes('@if') ||
|
||||
selector.includes('@for') ||
|
||||
selector.includes('@while') ||
|
||||
selector.includes('@each') ||
|
||||
selector.includes('@mixin') ||
|
||||
selector.includes('@include')) {
|
||||
return false;
|
||||
}
|
||||
// Basic CSS selector patterns
|
||||
const selectorPatterns = [
|
||||
/^[.#]?[a-zA-Z_-][a-zA-Z0-9_-]*/,
|
||||
/^::[a-zA-Z-]+/,
|
||||
/^:[a-zA-Z-]+/,
|
||||
/^\[.*\]/,
|
||||
/^[*]/, // Universal selector
|
||||
];
|
||||
// Check if selector matches any valid pattern
|
||||
return selectorPatterns.some(pattern => pattern.test(selector.trim())) ||
|
||||
selector.includes('.') ||
|
||||
selector.includes('#') ||
|
||||
selector.includes(':');
|
||||
}
|
||||
}
|
||||
exports.CSSAnalyzer = CSSAnalyzer;
|
||||
//# sourceMappingURL=CSSAnalyzer.js.map
|
||||
Reference in New Issue
Block a user