initial
This commit is contained in:
233
static/components/Results.js
Normal file
233
static/components/Results.js
Normal file
@@ -0,0 +1,233 @@
|
||||
// Results Component
|
||||
import { LoadingProgress } from './LoadingProgress.js';
|
||||
|
||||
export class Results {
|
||||
constructor() {
|
||||
this.container = document.getElementById('results');
|
||||
this.loadingProgress = new LoadingProgress(this.container);
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
// Show welcome message initially
|
||||
this.showWelcome();
|
||||
}
|
||||
|
||||
showWelcome() {
|
||||
if (this.container) {
|
||||
this.container.innerHTML = `
|
||||
<div class="welcome-message">
|
||||
<h1>Python Documentation</h1>
|
||||
<p>Search for any Python object in the sidebar to view its documentation.</p>
|
||||
<p>Select a language to automatically translate the documentation.</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
showLoading(message = 'Loading documentation...', showProgress = true) {
|
||||
if (this.container) {
|
||||
this.loadingProgress.show(message, showProgress);
|
||||
}
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
if (this.loadingProgress) {
|
||||
this.loadingProgress.complete();
|
||||
}
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
if (this.container) {
|
||||
this.container.innerHTML = `<div class="error-message">${message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
displayDocumentation(data) {
|
||||
if (!this.container) return;
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
|
||||
// Header with title
|
||||
const header = document.createElement('div');
|
||||
header.className = 'doc-header';
|
||||
|
||||
const title = document.createElement('h1');
|
||||
title.className = 'doc-title';
|
||||
title.textContent = data.object_name;
|
||||
|
||||
const meta = document.createElement('div');
|
||||
meta.className = 'doc-meta';
|
||||
meta.innerHTML = `
|
||||
<span class="type-badge">${data.object_type || 'unknown'}</span>
|
||||
${data.cached ? '<span class="doc-badge">Cached</span>' : ''}
|
||||
`;
|
||||
|
||||
header.appendChild(title);
|
||||
header.appendChild(meta);
|
||||
wrapper.appendChild(header);
|
||||
|
||||
// Signature
|
||||
if (data.signature) {
|
||||
const signature = document.createElement('div');
|
||||
signature.className = 'doc-signature';
|
||||
signature.textContent = data.signature;
|
||||
wrapper.appendChild(signature);
|
||||
}
|
||||
|
||||
// Main documentation content
|
||||
const docText = data.translated || data.original;
|
||||
|
||||
if (docText) {
|
||||
const docSection = document.createElement('section');
|
||||
docSection.className = 'doc-section';
|
||||
|
||||
const docTextEl = document.createElement('div');
|
||||
docTextEl.className = 'doc-text';
|
||||
docTextEl.textContent = docText;
|
||||
|
||||
docSection.appendChild(docTextEl);
|
||||
wrapper.appendChild(docSection);
|
||||
}
|
||||
|
||||
// Show original if translation exists (collapsible)
|
||||
if (data.translated && data.original) {
|
||||
const originalSection = document.createElement('details');
|
||||
originalSection.className = 'doc-section';
|
||||
originalSection.innerHTML = `
|
||||
<summary style="cursor: pointer; font-weight: 500; margin-bottom: 0.5rem; color: var(--text-secondary);">
|
||||
Original Documentation (English)
|
||||
</summary>
|
||||
<div class="doc-text" style="margin-top: 0.5rem;">${data.original}</div>
|
||||
`;
|
||||
wrapper.appendChild(originalSection);
|
||||
}
|
||||
|
||||
if (!data.original && !data.translated) {
|
||||
const noDoc = document.createElement('div');
|
||||
noDoc.className = 'doc-text';
|
||||
noDoc.textContent = 'No documentation available for this object.';
|
||||
wrapper.appendChild(noDoc);
|
||||
}
|
||||
|
||||
this.container.innerHTML = '';
|
||||
this.container.appendChild(wrapper);
|
||||
}
|
||||
|
||||
displayCourse(courseData) {
|
||||
if (!this.container) return;
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'course-content';
|
||||
|
||||
const title = document.createElement('h1');
|
||||
title.textContent = courseData.title || 'Python Course';
|
||||
wrapper.appendChild(title);
|
||||
|
||||
if (courseData.sections && courseData.sections.length > 0) {
|
||||
courseData.sections.forEach(section => {
|
||||
const sectionDiv = this.createCourseSection(section);
|
||||
wrapper.appendChild(sectionDiv);
|
||||
});
|
||||
}
|
||||
|
||||
this.container.innerHTML = '';
|
||||
this.container.appendChild(wrapper);
|
||||
}
|
||||
|
||||
createCourseSection(section) {
|
||||
const sectionDiv = document.createElement('section');
|
||||
sectionDiv.className = 'course-section';
|
||||
sectionDiv.id = `section-${section.id || section.title.toLowerCase().replace(/\s+/g, '-')}`;
|
||||
|
||||
// Parse and render markdown
|
||||
if (section.markdown) {
|
||||
// Configure marked options
|
||||
if (typeof marked !== 'undefined') {
|
||||
marked.setOptions({
|
||||
highlight: function(code, lang) {
|
||||
if (typeof hljs !== 'undefined' && lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return hljs.highlight(code, { language: lang }).value;
|
||||
} catch (err) {
|
||||
console.error('Highlight error:', err);
|
||||
}
|
||||
}
|
||||
if (typeof hljs !== 'undefined') {
|
||||
return hljs.highlightAuto(code).value;
|
||||
}
|
||||
return code;
|
||||
},
|
||||
breaks: true,
|
||||
gfm: true
|
||||
});
|
||||
|
||||
// Convert markdown to HTML
|
||||
const htmlContent = marked.parse(section.markdown);
|
||||
|
||||
// Create a container for the markdown content
|
||||
const contentDiv = document.createElement('div');
|
||||
contentDiv.className = 'markdown-content';
|
||||
contentDiv.innerHTML = htmlContent;
|
||||
|
||||
// Add IDs to headings for navigation
|
||||
contentDiv.querySelectorAll('h1, h2, h3, h4').forEach((heading) => {
|
||||
const text = heading.textContent.trim();
|
||||
const id = text.toLowerCase()
|
||||
.replace(/[^\w\s-]/g, '')
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.trim();
|
||||
heading.id = id;
|
||||
});
|
||||
|
||||
// Highlight code blocks
|
||||
if (typeof hljs !== 'undefined') {
|
||||
contentDiv.querySelectorAll('pre code').forEach((block) => {
|
||||
hljs.highlightElement(block);
|
||||
});
|
||||
}
|
||||
|
||||
sectionDiv.appendChild(contentDiv);
|
||||
}
|
||||
} else if (section.content && section.content.length > 0) {
|
||||
// Fallback to old format
|
||||
section.content.forEach(item => {
|
||||
if (item.startsWith('```')) {
|
||||
const codeDiv = document.createElement('pre');
|
||||
codeDiv.className = 'doc-signature';
|
||||
codeDiv.textContent = item.replace(/```python\n?/g, '').replace(/```/g, '').trim();
|
||||
sectionDiv.appendChild(codeDiv);
|
||||
} else {
|
||||
const itemDiv = document.createElement('p');
|
||||
itemDiv.className = 'doc-text';
|
||||
itemDiv.textContent = item;
|
||||
sectionDiv.appendChild(itemDiv);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return sectionDiv;
|
||||
}
|
||||
|
||||
scrollToSection(section) {
|
||||
const sectionId = section.id || section.title.toLowerCase().replace(/\s+/g, '-');
|
||||
const sectionElement = document.getElementById(`section-${sectionId}`);
|
||||
if (sectionElement) {
|
||||
sectionElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find by heading ID
|
||||
const headingId = section.title.toLowerCase()
|
||||
.replace(/[^\w\s-]/g, '')
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.trim();
|
||||
const headingElement = document.getElementById(headingId);
|
||||
if (headingElement) {
|
||||
headingElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user