Browse Source

fix: editor correctly identifying and highlighting index events

master
limina1 6 months ago
parent
commit
27382f4b86
  1. 95
      src/lib/components/ZettelEditor.svelte

95
src/lib/components/ZettelEditor.svelte

@ -57,11 +57,11 @@ import Asciidoctor from "asciidoctor"; @@ -57,11 +57,11 @@ import Asciidoctor from "asciidoctor";
// Note: updateEditorContent() is only called manually when needed
// The automatic effect was causing feedback loops with user typing
// Effect to update syntax highlighting when parsedSections change
// Effect to update syntax highlighting when parsing results change
$effect(() => {
if (editorView && parsedSections) {
if (editorView && (parsedSections || publicationResult?.metadata?.eventStructure)) {
editorView.dispatch({
effects: updateHighlighting.of(parsedSections)
effects: updateHighlighting.of(parsedSections || [])
});
}
});
@ -317,16 +317,37 @@ import Asciidoctor from "asciidoctor"; @@ -317,16 +317,37 @@ import Asciidoctor from "asciidoctor";
// Analyze document structure for ambiguity detection
const documentStructure = analyzeDocumentStructure(lines);
// Create a map of header text to section info for fast lookup
// Create a map of header text to section info for fast lookup from actual event structure
const sectionMap = new Map();
if (sections) {
sections.forEach(section => {
if (section.title) {
sectionMap.set(section.title.toLowerCase().trim(), {
level: section.level,
if (publicationResult?.metadata?.eventStructure) {
// Flatten the event structure to get all nodes with their actual event types
const flattenEventStructure = (nodes: any[], result: any[] = []): any[] => {
for (const node of nodes) {
result.push(node);
if (node.children && node.children.length > 0) {
flattenEventStructure(node.children, result);
}
}
return result;
};
const allEventNodes = flattenEventStructure(publicationResult.metadata.eventStructure);
// Debug: log the event structure
console.log('Event structure nodes for highlighting:', allEventNodes.map(n => ({
title: n.title,
level: n.level,
eventType: n.eventType,
eventKind: n.eventKind
})));
allEventNodes.forEach(node => {
if (node.title) {
sectionMap.set(node.title.toLowerCase().trim(), {
level: node.level,
isEventTitle: true,
eventType: section.eventType,
eventKind: section.eventKind
eventType: node.eventType,
eventKind: node.eventKind
});
}
});
@ -347,24 +368,28 @@ import Asciidoctor from "asciidoctor"; @@ -347,24 +368,28 @@ import Asciidoctor from "asciidoctor";
const sectionInfo = sectionMap.get(headerText);
let className: string;
if (sectionInfo && sectionInfo.isEventTitle) {
// Event title - different colors based on event type
if (sectionInfo.eventKind === 30040) {
// Determine highlighting based on structural analysis first
if (level === 1) {
// Document title is always an index event (blue)
className = 'cm-header-index-event';
} else if (sectionInfo.eventKind === 30041) {
} else if (level === parseLevel) {
// Headers at parse level are content events (green)
className = 'cm-header-content-event';
} else if (level < parseLevel) {
// Headers above parse level that could have children are index events (blue)
// Check if this header has children by looking ahead in the document
const hasChildren = headerHasChildren(lines, i, level);
if (hasChildren) {
className = 'cm-header-index-event'; // Blue for sections with children
} else {
className = 'cm-header-event-title';
className = 'cm-header-content-event'; // Green for sections without children
}
} else {
// Check for ambiguous syntax patterns
if (isAmbiguousHeader(level, headerText, documentStructure, parseLevel)) {
} else if (isAmbiguousHeader(level, headerText, documentStructure, parseLevel)) {
className = 'cm-header-potential-event'; // Amber for ambiguous
} else if (level <= parseLevel) {
className = 'cm-header-potential-event'; // Amber for at parse level but not extracted
} else if (level > parseLevel) {
className = 'cm-header-subcontent'; // Gray for subheaders below parse level
} else {
className = 'cm-header-subcontent'; // Gray for subheaders
}
className = 'cm-header-potential-event'; // Amber for unclear cases
}
ranges.push({
@ -412,6 +437,30 @@ import Asciidoctor from "asciidoctor"; @@ -412,6 +437,30 @@ import Asciidoctor from "asciidoctor";
};
}
// Check if a header has children by looking ahead in the document
function headerHasChildren(lines: string[], headerIndex: number, headerLevel: number): boolean {
// Look ahead to see if there are any headers at a deeper level
for (let i = headerIndex + 1; i < lines.length; i++) {
const line = lines[i];
const headerMatch = line.match(/^(=+)\s+(.+)$/);
if (headerMatch) {
const nextLevel = headerMatch[1].length;
if (nextLevel > headerLevel) {
// Found a deeper header - this header has children
return true;
} else if (nextLevel <= headerLevel) {
// Found a header at the same or higher level - no children
return false;
}
}
}
// Reached end of document with no headers found - no children
return false;
}
// Check if a header represents ambiguous syntax
function isAmbiguousHeader(
level: number,

Loading…
Cancel
Save