Fix unimplemented login route with # prefix
Fix IDE service routing and path normalization Refactor IDE services and add session rotation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
183
node_modules/@jqhtml/vscode-extension/out/definitionProvider.js
generated
vendored
183
node_modules/@jqhtml/vscode-extension/out/definitionProvider.js
generated
vendored
@@ -69,6 +69,19 @@ class JqhtmlDefinitionProvider {
|
||||
console.log(`JQHTML: In $ attribute context:`, dollarAttrResult);
|
||||
return yield this.handleDollarAttributeDefinition(document, position, dollarAttrResult);
|
||||
}
|
||||
// IMPORTANT: Check for slot syntax BEFORE extracting word
|
||||
// This prevents slot names from being treated as component names
|
||||
// Check if we're in a slot tag by looking for <# or </# before cursor
|
||||
const beforeCursor = line.substring(0, position.character);
|
||||
if (beforeCursor.match(/<\/?#\s*[A-Z][A-Za-z0-9_]*$/)) {
|
||||
// We're in a slot tag - extract the full slot name from the line
|
||||
const slotNameMatch = line.match(/<\/?#\s*([A-Z][A-Za-z0-9_]*)/);
|
||||
if (slotNameMatch) {
|
||||
const slotName = slotNameMatch[1];
|
||||
console.log(`JQHTML: Detected slot tag syntax for slot: ${slotName}`);
|
||||
return yield this.handleSlotDefinition(document, position, slotName);
|
||||
}
|
||||
}
|
||||
// Get the word at the cursor position
|
||||
const wordRange = document.getWordRangeAtPosition(position, /[A-Z][A-Za-z0-9_]*/);
|
||||
if (!wordRange) {
|
||||
@@ -119,11 +132,6 @@ class JqhtmlDefinitionProvider {
|
||||
if (beforeWord.match(/<\/\s*$/) || beforeWord.match(/<\/Define:\s*$/)) {
|
||||
isInTagContext = true;
|
||||
}
|
||||
// Check for slot syntax: <#slotname> or </#slotname>
|
||||
if (beforeWord.match(/<#\s*$/) || beforeWord.match(/<\/#\s*$/)) {
|
||||
// This is a slot, not a component
|
||||
return undefined;
|
||||
}
|
||||
if (!isInTagContext) {
|
||||
// Also check if cursor is inside the tag name (not in attributes)
|
||||
const afterWord = line.substring(wordRange.end.character);
|
||||
@@ -483,6 +491,171 @@ class JqhtmlDefinitionProvider {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Handle goto definition for slot tags (<#SlotName>)
|
||||
*
|
||||
* IMPLEMENTATION SCOPE (Narrow, for now):
|
||||
* - Handles direct extends="ComponentName" on <Define:> tags
|
||||
* - Handles direct <ComponentName> invocation tags
|
||||
* - Does NOT traverse full inheritance chain (TODO: add later)
|
||||
* - Just looks for direct parent component
|
||||
*
|
||||
* LOGIC:
|
||||
* 1. Extract slot name from cursor position
|
||||
* 2. Find parent component:
|
||||
* - If inside <Define extends="Parent">, use Parent
|
||||
* - If inside <Parent> invocation, use Parent
|
||||
* 3. Find Parent.jqhtml file
|
||||
* 4. Search for <%= content('SlotName') %>
|
||||
* 5. Navigate to that line
|
||||
*/
|
||||
handleSlotDefinition(document, position, slotName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
console.log(`JQHTML: Handling slot definition for: ${slotName}`);
|
||||
// Find the parent component that defines this slot
|
||||
const parentComponentName = this.findParentComponentForSlot(document, position);
|
||||
if (!parentComponentName) {
|
||||
console.log(`JQHTML: Could not determine parent component for slot`);
|
||||
return undefined;
|
||||
}
|
||||
console.log(`JQHTML: Parent component for slot: ${parentComponentName}`);
|
||||
// Debug: Show what's in the index
|
||||
const allComponents = this.componentIndex.getAllComponentNames();
|
||||
console.log(`JQHTML: Index currently contains ${allComponents.length} components:`, allComponents.join(', '));
|
||||
// Find the parent component definition file
|
||||
const parentComponent = this.componentIndex.findComponent(parentComponentName);
|
||||
if (!parentComponent) {
|
||||
console.log(`JQHTML: Parent component '${parentComponentName}' not found in index`);
|
||||
return undefined;
|
||||
}
|
||||
console.log(`JQHTML: Found parent component file: ${parentComponent.uri.fsPath}`);
|
||||
// Search for content('SlotName') in the parent component file
|
||||
const slotUsageLocation = yield this.findSlotUsageInTemplate(parentComponent.uri, slotName);
|
||||
if (!slotUsageLocation) {
|
||||
console.log(`JQHTML: Slot usage content('${slotName}') not found in ${parentComponent.uri.fsPath}`);
|
||||
return undefined;
|
||||
}
|
||||
console.log(`JQHTML: Found slot usage at line ${slotUsageLocation.range.start.line + 1}`);
|
||||
return slotUsageLocation;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Find the parent component that should define this slot
|
||||
*
|
||||
* Looks for either:
|
||||
* 1. <Define:ChildComponent extends="ParentComponent"> - check if slots are top-level
|
||||
* 2. <ParentComponent> - find enclosing component invocation tag
|
||||
*/
|
||||
findParentComponentForSlot(document, position) {
|
||||
const currentLine = position.line;
|
||||
// Strategy 1: Look for <Define extends="ParentComponent"> where slots are at top level
|
||||
// Scan upward to find the Define tag
|
||||
let defineTagStartLine = -1;
|
||||
for (let i = currentLine; i >= 0; i--) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
// Check if we found a <Define:ComponentName
|
||||
if (lineText.match(/<Define:([A-Z][A-Za-z0-9_]*)/)) {
|
||||
defineTagStartLine = i;
|
||||
console.log(`JQHTML: Found <Define: tag at line ${i + 1}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we found a Define tag, look for extends attribute in the tag (may be multi-line)
|
||||
if (defineTagStartLine >= 0) {
|
||||
// Collect all lines from Define tag start until we find the closing >
|
||||
let tagContent = '';
|
||||
for (let i = defineTagStartLine; i < document.lineCount; i++) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
tagContent += lineText + ' ';
|
||||
// Stop when we find the closing > of the opening tag
|
||||
if (lineText.includes('>')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Now check if this multi-line tag has extends attribute
|
||||
const extendsMatch = tagContent.match(/\bextends\s*=\s*["']([A-Z][A-Za-z0-9_]*)["']/);
|
||||
if (extendsMatch) {
|
||||
const parentComponentName = extendsMatch[1];
|
||||
console.log(`JQHTML: Found extends="${parentComponentName}" in Define tag`);
|
||||
// TODO: Verify that the slot is at top level (not nested inside other tags)
|
||||
// For now, we assume if we found a Define with extends, that's the parent
|
||||
return parentComponentName;
|
||||
}
|
||||
else {
|
||||
console.log(`JQHTML: Define tag found but no extends attribute`);
|
||||
}
|
||||
}
|
||||
// Strategy 2: Look for enclosing <ParentComponent> invocation tag
|
||||
// Scan upward to find opening tag
|
||||
let tagStack = [];
|
||||
for (let i = currentLine; i >= 0; i--) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
// Find all component tags on this line (both opening and closing)
|
||||
// Component tags: <ComponentName> or </ComponentName>
|
||||
const tagRegex = /<\/?([A-Z][A-Za-z0-9_]*)[^>]*>/g;
|
||||
let match;
|
||||
// Collect all tags on this line
|
||||
const tagsOnLine = [];
|
||||
while ((match = tagRegex.exec(lineText)) !== null) {
|
||||
const fullMatch = match[0];
|
||||
const componentName = match[1];
|
||||
const isClosing = fullMatch.startsWith('</');
|
||||
tagsOnLine.push({ tag: componentName, isClosing });
|
||||
}
|
||||
// Process tags in reverse order (right to left on the line)
|
||||
for (let j = tagsOnLine.length - 1; j >= 0; j--) {
|
||||
const { tag, isClosing } = tagsOnLine[j];
|
||||
if (isClosing) {
|
||||
// Closing tag - add to stack
|
||||
tagStack.push(tag);
|
||||
}
|
||||
else {
|
||||
// Opening tag
|
||||
if (tagStack.length > 0 && tagStack[tagStack.length - 1] === tag) {
|
||||
// This opening tag matches the last closing tag on stack - they cancel out
|
||||
tagStack.pop();
|
||||
}
|
||||
else {
|
||||
// This is an unclosed opening tag - this is our parent!
|
||||
console.log(`JQHTML: Found enclosing component invocation: <${tag}>`);
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`JQHTML: No parent component found for slot`);
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* Search for <%= content('SlotName') %> in a template file
|
||||
*/
|
||||
findSlotUsageInTemplate(templateUri, slotName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const templateDoc = yield vscode.workspace.openTextDocument(templateUri);
|
||||
const templateText = templateDoc.getText();
|
||||
// Search for content('SlotName') or content("SlotName")
|
||||
// Also handle optional whitespace
|
||||
const contentRegex = new RegExp(`<%=\\s*content\\s*\\(\\s*['"]${slotName}['"]\\s*\\)`, 'g');
|
||||
const match = contentRegex.exec(templateText);
|
||||
if (match) {
|
||||
const matchPosition = templateDoc.positionAt(match.index);
|
||||
console.log(`JQHTML: Found content('${slotName}') at line ${matchPosition.line + 1}`);
|
||||
// Return location pointing to the slot name within content('SlotName')
|
||||
const slotNameStartIndex = match.index + match[0].indexOf(slotName);
|
||||
const slotNamePosition = templateDoc.positionAt(slotNameStartIndex);
|
||||
const slotNameRange = new vscode.Range(slotNamePosition, new vscode.Position(slotNamePosition.line, slotNamePosition.character + slotName.length));
|
||||
return new vscode.Location(templateUri, slotNameRange);
|
||||
}
|
||||
console.log(`JQHTML: No content('${slotName}') found in template`);
|
||||
return undefined;
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`JQHTML: Error reading template file:`, error);
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.JqhtmlDefinitionProvider = JqhtmlDefinitionProvider;
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user