mirror of
https://github.com/fbarrca/obsidian-inlineAI.git
synced 2026-07-22 11:50:24 +00:00
Add InlineAI conflict detection and styling to diff extension
This commit is contained in:
parent
5562c50620
commit
0b36cd27c8
2 changed files with 92 additions and 31 deletions
|
|
@ -14,9 +14,11 @@ import { RangeSetBuilder } from "@codemirror/state";
|
|||
*
|
||||
* - Current Conflict: [- ... -]
|
||||
* - Incoming Conflict: {+ ... +}
|
||||
* - Selected for InlineAI: <<InlineAI<< ... >>InlineAI>>
|
||||
*/
|
||||
const CURRENT_CONFLICT_REGEX = /\[-[\s\S]*?-\]/g;
|
||||
const INCOMING_CONFLICT_REGEX = /\{\+[\s\S]*?\+\}/g;
|
||||
const CURRENT_CONFLICT_REGEX = /\[-([\s\S]*?)-\]/g;
|
||||
const INCOMING_CONFLICT_REGEX = /\{\+([\s\S]*?)\+\}/g;
|
||||
const INLINE_AI_CONFLICT_REGEX = /<<InlineAI<<([\s\S]*?)>>InlineAI>>/g; // Added regex for InlineAI
|
||||
|
||||
/**
|
||||
* Define decorations with corresponding CSS classes.
|
||||
|
|
@ -29,8 +31,20 @@ const incomingConflictDecoration = Decoration.mark({
|
|||
class: "cm-conflict-incoming",
|
||||
});
|
||||
|
||||
const selectedForInlineAIDecoration = Decoration.mark({
|
||||
// Renamed for clarity
|
||||
class: "cm-selected-inline",
|
||||
});
|
||||
|
||||
// Decoration to hide conflict markers
|
||||
const hideDecoration = Decoration.replace({
|
||||
// This decoration replaces the matched text with nothing, effectively hiding it
|
||||
// The `inclusive: false` ensures it doesn't affect surrounding text
|
||||
inclusive: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* ViewPlugin to detect and decorate conflict markers.
|
||||
* ViewPlugin to detect and decorate conflict markers, including InlineAI markers.
|
||||
*/
|
||||
const conflictMarkersPlugin = ViewPlugin.fromClass(
|
||||
class {
|
||||
|
|
@ -50,53 +64,94 @@ const conflictMarkersPlugin = ViewPlugin.fromClass(
|
|||
const builder = new RangeSetBuilder<Decoration>();
|
||||
const text = view.state.doc.toString();
|
||||
|
||||
// Collect all matches for current and incoming conflicts
|
||||
const conflicts: {
|
||||
// Array to hold all decorations to be added
|
||||
type DecorationEntry = {
|
||||
from: number;
|
||||
to: number;
|
||||
decoration: Decoration;
|
||||
}[] = [];
|
||||
};
|
||||
|
||||
const decorationsToAdd: DecorationEntry[] = [];
|
||||
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
// Match Current Conflicts
|
||||
while ((match = CURRENT_CONFLICT_REGEX.exec(text)) !== null) {
|
||||
// Helper function to collect decorations
|
||||
const collectConflict = (
|
||||
match: RegExpExecArray,
|
||||
prefixLength: number,
|
||||
suffixLength: number,
|
||||
decoration: Decoration
|
||||
) => {
|
||||
const start = match.index;
|
||||
const end = match.index + match[0].length;
|
||||
conflicts.push({
|
||||
from: start,
|
||||
to: end,
|
||||
decoration: currentConflictDecoration,
|
||||
const innerStart = start + prefixLength;
|
||||
const innerEnd = end - suffixLength;
|
||||
|
||||
// Add decoration to highlight the inner content
|
||||
decorationsToAdd.push({
|
||||
from: innerStart,
|
||||
to: innerEnd,
|
||||
decoration,
|
||||
});
|
||||
|
||||
// Add decorations to hide the prefix and suffix
|
||||
decorationsToAdd.push({
|
||||
from: start,
|
||||
to: start + prefixLength,
|
||||
decoration: hideDecoration,
|
||||
});
|
||||
decorationsToAdd.push({
|
||||
from: end - suffixLength,
|
||||
to: end,
|
||||
decoration: hideDecoration,
|
||||
});
|
||||
};
|
||||
|
||||
// Match Current Conflicts
|
||||
while ((match = CURRENT_CONFLICT_REGEX.exec(text)) !== null) {
|
||||
collectConflict(match, 0, 0, currentConflictDecoration); // '[-' and '-]'
|
||||
}
|
||||
|
||||
// Match Incoming Conflicts
|
||||
while ((match = INCOMING_CONFLICT_REGEX.exec(text)) !== null) {
|
||||
const start = match.index;
|
||||
const end = match.index + match[0].length;
|
||||
conflicts.push({
|
||||
from: start,
|
||||
to: end,
|
||||
decoration: incomingConflictDecoration,
|
||||
});
|
||||
collectConflict(match, 0, 0, incomingConflictDecoration); // '{+' and '+}'
|
||||
}
|
||||
|
||||
// Sort conflicts by start position
|
||||
conflicts.sort((a, b) => a.from - b.from);
|
||||
// Match InlineAI Conflicts
|
||||
while ((match = INLINE_AI_CONFLICT_REGEX.exec(text)) !== null) {
|
||||
// collectConflict(match, 12, 12, selectedForInlineAIDecoration); // '<<InlineAI<<' and '>>InlineAI>>'
|
||||
collectConflict(match, 0, 0, selectedForInlineAIDecoration); // '<<InlineAI<<' and '>>InlineAI>>'
|
||||
}
|
||||
|
||||
// Check for overlapping conflicts and handle accordingly
|
||||
for (let i = 0; i < conflicts.length; i++) {
|
||||
if (i > 0 && conflicts[i].from < conflicts[i - 1].to) {
|
||||
// Sort all decorations by 'from' position and 'startSide'
|
||||
decorationsToAdd.sort((a, b) => {
|
||||
if (a.from !== b.from) {
|
||||
return a.from - b.from;
|
||||
}
|
||||
// Optional: Define startSide if necessary. Codemirror's RangeSetBuilder handles this internally.
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Check for overlapping decorations and handle accordingly
|
||||
let lastAddedTo = -1;
|
||||
for (const deco of decorationsToAdd) {
|
||||
if (deco.from < lastAddedTo) {
|
||||
console.warn(
|
||||
"Overlapping conflict markers detected. Skipping overlapping decoration."
|
||||
`Overlapping conflict markers detected between positions ${
|
||||
deco.from
|
||||
} and ${lastAddedTo}. Skipping overlapping decoration. Nearby text: "${text.slice(
|
||||
deco.from - 10,
|
||||
deco.to + 10
|
||||
)} Tried to add decoration: ${
|
||||
deco.decoration.spec.classList
|
||||
}`
|
||||
);
|
||||
continue; // Skip overlapping decorations to prevent errors
|
||||
}
|
||||
builder.add(
|
||||
conflicts[i].from,
|
||||
conflicts[i].to,
|
||||
conflicts[i].decoration
|
||||
);
|
||||
builder.add(deco.from, deco.to, deco.decoration);
|
||||
if (deco.to > lastAddedTo) {
|
||||
lastAddedTo = deco.to;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.finish();
|
||||
|
|
|
|||
|
|
@ -89,4 +89,10 @@ If your plugin does not need CSS, delete this file.
|
|||
/* border-left: 4px solid green; */
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
|
||||
.cm-selected-inline {
|
||||
background-color: var(--text-highlight-bg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue