159 lines
5.3 KiB
TypeScript
159 lines
5.3 KiB
TypeScript
|
|
/**
|
||
|
|
* Update mapping blocks for specific links without prompting for all links.
|
||
|
|
* Used when user changes specific links (single-link, selection-links, create-link).
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { App, TFile } from "obsidian";
|
||
|
|
import type { MindnetSettings } from "../settings";
|
||
|
|
import { splitIntoSections, type NoteSection } from "./sectionParser";
|
||
|
|
import { parseEdgesFromCallouts } from "../parser/parseEdgesFromCallouts";
|
||
|
|
import {
|
||
|
|
extractExistingMappings,
|
||
|
|
removeWrapperBlock,
|
||
|
|
type SectionMappingState,
|
||
|
|
} from "./mappingExtractor";
|
||
|
|
import {
|
||
|
|
buildMappingBlock,
|
||
|
|
insertMappingBlock,
|
||
|
|
type MappingBuilderOptions,
|
||
|
|
} from "./mappingBuilder";
|
||
|
|
import { convertRelLinksToEdges } from "../parser/parseRelLinks";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update mapping blocks for sections containing rel: links, without prompting.
|
||
|
|
* Only processes links that are already in [[rel:type|link]] format.
|
||
|
|
*/
|
||
|
|
export async function updateMappingBlocksForRelLinks(
|
||
|
|
app: App,
|
||
|
|
file: TFile,
|
||
|
|
settings: MindnetSettings
|
||
|
|
): Promise<void> {
|
||
|
|
let content = await app.vault.read(file);
|
||
|
|
const lines = content.split(/\r?\n/);
|
||
|
|
|
||
|
|
// Convert [[rel:type|link]] links to normal [[link]] and extract edge mappings
|
||
|
|
const { convertedContent, edgeMappings: relLinkMappings } = convertRelLinksToEdges(content);
|
||
|
|
content = convertedContent;
|
||
|
|
|
||
|
|
if (relLinkMappings.size === 0) {
|
||
|
|
// No rel: links to process
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(`[UpdateMappingBlocks] Converting ${relLinkMappings.size} rel: links to edge mappings`);
|
||
|
|
|
||
|
|
// Split into sections
|
||
|
|
const sections = splitIntoSections(content);
|
||
|
|
|
||
|
|
// Process sections in reverse order (to preserve line indices when modifying)
|
||
|
|
const modifiedSections: Array<{ section: NoteSection; newContent: string }> = [];
|
||
|
|
|
||
|
|
for (const section of sections) {
|
||
|
|
if (section.links.length === 0) {
|
||
|
|
// No links, skip
|
||
|
|
modifiedSections.push({
|
||
|
|
section,
|
||
|
|
newContent: section.content,
|
||
|
|
});
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Extract existing mappings
|
||
|
|
const mappingState = extractExistingMappings(
|
||
|
|
section.content,
|
||
|
|
settings.mappingWrapperCalloutType,
|
||
|
|
settings.mappingWrapperTitle
|
||
|
|
);
|
||
|
|
|
||
|
|
// Merge rel: link mappings (from [[rel:type|link]] format) into existing mappings
|
||
|
|
// These take precedence over file content mappings (update even if already mapped)
|
||
|
|
for (const [linkBasename, edgeType] of relLinkMappings.entries()) {
|
||
|
|
// Check if this link exists in this section
|
||
|
|
const normalizedBasename = linkBasename.split("|")[0]?.split("#")[0]?.trim() || linkBasename;
|
||
|
|
if (section.links.some(link => {
|
||
|
|
const normalizedLink = link.split("|")[0]?.split("#")[0]?.trim() || link;
|
||
|
|
return normalizedLink === normalizedBasename || link === normalizedBasename;
|
||
|
|
})) {
|
||
|
|
// Always update rel: link mappings (they represent user's explicit choice)
|
||
|
|
mappingState.existingMappings.set(normalizedBasename, edgeType);
|
||
|
|
console.log(`[UpdateMappingBlocks] Updated rel: link mapping: ${normalizedBasename} -> ${edgeType}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Remove wrapper block if exists
|
||
|
|
let sectionContentWithoutWrapper = section.content;
|
||
|
|
if (mappingState.wrapperBlockStartLine !== null && mappingState.wrapperBlockEndLine !== null) {
|
||
|
|
sectionContentWithoutWrapper = removeWrapperBlock(
|
||
|
|
section.content,
|
||
|
|
mappingState.wrapperBlockStartLine,
|
||
|
|
mappingState.wrapperBlockEndLine
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build mapping block with updated mappings
|
||
|
|
const mappingOptions: MappingBuilderOptions = {
|
||
|
|
wrapperCalloutType: settings.mappingWrapperCalloutType,
|
||
|
|
wrapperTitle: settings.mappingWrapperTitle,
|
||
|
|
wrapperFolded: settings.mappingWrapperFolded,
|
||
|
|
defaultEdgeType: settings.defaultEdgeType,
|
||
|
|
assignUnmapped: "none", // Don't assign unmapped links, just use existing mappings
|
||
|
|
};
|
||
|
|
|
||
|
|
const mappingBlock = buildMappingBlock(
|
||
|
|
section.links,
|
||
|
|
mappingState.existingMappings,
|
||
|
|
mappingOptions
|
||
|
|
);
|
||
|
|
|
||
|
|
if (mappingBlock) {
|
||
|
|
const newContent = insertMappingBlock(sectionContentWithoutWrapper, mappingBlock);
|
||
|
|
modifiedSections.push({
|
||
|
|
section,
|
||
|
|
newContent,
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
// No mapping block needed
|
||
|
|
modifiedSections.push({
|
||
|
|
section,
|
||
|
|
newContent: sectionContentWithoutWrapper,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reconstruct file content with modified sections
|
||
|
|
let newContent = "";
|
||
|
|
let currentLine = 0;
|
||
|
|
|
||
|
|
for (let i = 0; i < modifiedSections.length; i++) {
|
||
|
|
const { section, newContent: sectionNewContent } = modifiedSections[i]!;
|
||
|
|
|
||
|
|
// Add lines before this section
|
||
|
|
if (currentLine < section.startLine) {
|
||
|
|
newContent += lines.slice(currentLine, section.startLine).join("\n");
|
||
|
|
if (currentLine < section.startLine) {
|
||
|
|
newContent += "\n";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add modified section content
|
||
|
|
newContent += sectionNewContent;
|
||
|
|
|
||
|
|
currentLine = section.endLine;
|
||
|
|
|
||
|
|
// Add newline between sections (except for last section)
|
||
|
|
if (i < modifiedSections.length - 1) {
|
||
|
|
newContent += "\n";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add remaining lines after last section
|
||
|
|
if (currentLine < lines.length) {
|
||
|
|
newContent += "\n" + lines.slice(currentLine).join("\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
// Write back to file
|
||
|
|
await app.vault.modify(file, newContent);
|
||
|
|
|
||
|
|
console.log(`[UpdateMappingBlocks] Updated mapping blocks for ${modifiedSections.length} sections`);
|
||
|
|
}
|