✨ MAJOR FEATURES: • Auto-zoom intelligence với smart bounds fitting • Enhanced 3D GPS markers với pulsing effects • Professional route display với 6-layer rendering • Status-based parking icons với availability indicators • Production-ready build optimizations 🗺️ AUTO-ZOOM FEATURES: • Smart bounds fitting cho GPS + selected parking • Adaptive padding (50px) cho visual balance • Max zoom control (level 16) để tránh quá gần • Dynamic centering khi không có selection 🎨 ENHANCED VISUALS: • 3D GPS marker với multi-layer pulse effects • Advanced parking icons với status colors • Selection highlighting với animation • Dimming system cho non-selected items 🛣️ ROUTE SYSTEM: • OpenRouteService API integration • Multi-layer route rendering (glow, shadow, main, animated) • Real-time distance & duration calculation • Visual route info trong popup 📱 PRODUCTION READY: • SSR safe với dynamic imports • Build errors resolved • Global deployment via Vercel • Optimized performance 🌍 DEPLOYMENT: • Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app • Bundle size: 22.8 kB optimized • Global CDN distribution • HTTPS enabled 💾 VERSION CONTROL: • MapView-v2.0.tsx backup created • MAPVIEW_VERSIONS.md documentation • Full version history tracking
175 lines
6.5 KiB
JavaScript
175 lines
6.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.MetadataManager = void 0;
|
|
const typescript_1 = require("typescript");
|
|
class MetadataManager {
|
|
constructor(content) {
|
|
this.content = content;
|
|
}
|
|
insert(metadata, symbol, staticOptions) {
|
|
const source = (0, typescript_1.createSourceFile)('filename.ts', this.content, typescript_1.ScriptTarget.ES2017);
|
|
const moduleDecoratorNode = this.findFirstDecoratorMetadata(source, 'Module');
|
|
if (!moduleDecoratorNode) {
|
|
return;
|
|
}
|
|
const matchingProperties = moduleDecoratorNode.properties
|
|
.filter((prop) => prop.kind === typescript_1.SyntaxKind.PropertyAssignment)
|
|
.filter((prop) => {
|
|
const name = prop.name;
|
|
switch (name.kind) {
|
|
case typescript_1.SyntaxKind.Identifier:
|
|
return name.getText(source) === metadata;
|
|
case typescript_1.SyntaxKind.StringLiteral:
|
|
return name.text === metadata;
|
|
default:
|
|
return false;
|
|
}
|
|
});
|
|
symbol = this.mergeSymbolAndExpr(symbol, staticOptions);
|
|
const addBlankLinesIfDynamic = () => {
|
|
symbol = staticOptions ? this.addBlankLines(symbol) : symbol;
|
|
};
|
|
if (matchingProperties.length === 0) {
|
|
const expr = moduleDecoratorNode;
|
|
if (expr.properties.length === 0) {
|
|
addBlankLinesIfDynamic();
|
|
return this.insertMetadataToEmptyModuleDecorator(expr, metadata, symbol);
|
|
}
|
|
else {
|
|
addBlankLinesIfDynamic();
|
|
return this.insertNewMetadataToDecorator(expr, source, metadata, symbol);
|
|
}
|
|
}
|
|
else {
|
|
return this.insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions);
|
|
}
|
|
}
|
|
findFirstDecoratorMetadata(source, identifier) {
|
|
for (const node of this.getSourceNodes(source)) {
|
|
const isDecoratorFactoryNode = node.kind === typescript_1.SyntaxKind.Decorator &&
|
|
node.expression.kind === typescript_1.SyntaxKind.CallExpression;
|
|
if (!isDecoratorFactoryNode)
|
|
continue;
|
|
const expr = node.expression;
|
|
const isExpectedExpression = expr.arguments[0]?.kind === typescript_1.SyntaxKind.ObjectLiteralExpression;
|
|
if (!isExpectedExpression)
|
|
continue;
|
|
if (expr.expression.kind === typescript_1.SyntaxKind.Identifier) {
|
|
const escapedText = expr.expression.escapedText;
|
|
const isTargetIdentifier = escapedText
|
|
? escapedText.toLowerCase() === identifier.toLowerCase()
|
|
: true;
|
|
if (isTargetIdentifier) {
|
|
return expr.arguments[0];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
getSourceNodes(sourceFile) {
|
|
const nodes = [sourceFile];
|
|
const result = [];
|
|
while (nodes.length > 0) {
|
|
const node = nodes.shift();
|
|
if (node) {
|
|
result.push(node);
|
|
if (node.getChildCount(sourceFile) >= 0) {
|
|
nodes.unshift(...node.getChildren(sourceFile));
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
insertMetadataToEmptyModuleDecorator(expr, metadata, symbol) {
|
|
const position = expr.getEnd() - 1;
|
|
const toInsert = ` ${metadata}: [${symbol}]`;
|
|
return this.content.split('').reduce((content, char, index) => {
|
|
if (index === position) {
|
|
return `${content}\n${toInsert}\n${char}`;
|
|
}
|
|
else {
|
|
return `${content}${char}`;
|
|
}
|
|
}, '');
|
|
}
|
|
insertNewMetadataToDecorator(expr, source, metadata, symbol) {
|
|
const node = expr.properties[expr.properties.length - 1];
|
|
const position = node.getEnd();
|
|
const text = node.getFullText(source);
|
|
const matches = text.match(/^\r?\n\s*/);
|
|
let toInsert;
|
|
if (matches) {
|
|
toInsert = `,${matches[0]}${metadata}: [${symbol}]`;
|
|
}
|
|
else {
|
|
toInsert = `, ${metadata}: [${symbol}]`;
|
|
}
|
|
return this.content.split('').reduce((content, char, index) => {
|
|
if (index === position) {
|
|
return `${content}${toInsert}${char}`;
|
|
}
|
|
else {
|
|
return `${content}${char}`;
|
|
}
|
|
}, '');
|
|
}
|
|
insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions) {
|
|
const assignment = matchingProperties[0];
|
|
let node;
|
|
const arrLiteral = assignment.initializer;
|
|
if (!arrLiteral.elements) {
|
|
return this.content;
|
|
}
|
|
if (arrLiteral.elements.length === 0) {
|
|
node = arrLiteral;
|
|
}
|
|
else {
|
|
node = arrLiteral.elements;
|
|
}
|
|
if (Array.isArray(node)) {
|
|
const nodeArray = node;
|
|
const symbolsArray = nodeArray.map((childNode) => childNode.getText(source));
|
|
if (symbolsArray.includes(symbol)) {
|
|
return this.content;
|
|
}
|
|
node = node[node.length - 1];
|
|
}
|
|
let toInsert;
|
|
let position = node.getEnd();
|
|
if (node.kind === typescript_1.SyntaxKind.ArrayLiteralExpression) {
|
|
position--;
|
|
toInsert = staticOptions ? this.addBlankLines(symbol) : `${symbol}`;
|
|
}
|
|
else {
|
|
const text = node.getFullText(source);
|
|
const itemSeparator = (text.match(/^\r?\n(\r?)\s+/) ||
|
|
text.match(/^\r?\n/) ||
|
|
' ')[0];
|
|
toInsert = `,${itemSeparator}${symbol}`;
|
|
}
|
|
return this.content.split('').reduce((content, char, index) => {
|
|
if (index === position) {
|
|
return `${content}${toInsert}${char}`;
|
|
}
|
|
else {
|
|
return `${content}${char}`;
|
|
}
|
|
}, '');
|
|
}
|
|
mergeSymbolAndExpr(symbol, staticOptions) {
|
|
if (!staticOptions) {
|
|
return symbol;
|
|
}
|
|
const spacing = 6;
|
|
let options = JSON.stringify(staticOptions.value, null, spacing);
|
|
options = options.replace(/\"([^(\")"]+)\":/g, '$1:');
|
|
options = options.replace(/\"/g, `'`);
|
|
options = options.slice(0, options.length - 1) + ' }';
|
|
symbol += `.${staticOptions.name}(${options})`;
|
|
return symbol;
|
|
}
|
|
addBlankLines(expr) {
|
|
return `\n ${expr}\n `;
|
|
}
|
|
}
|
|
exports.MetadataManager = MetadataManager;
|