Merge pull request #18 from GladeDiviney/pathnames

support link paths
This commit is contained in:
Ryan Mellmer 2025-06-05 20:39:15 -07:00 committed by GitHub
commit 61754fff07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 118 additions and 120 deletions

View file

@ -8,63 +8,58 @@ export async function replaceEmbed(app: App, embed: Node, settings: LinkRangeSet
const res = checkLink(app, embedHtml, settings, true, "src"); const res = checkLink(app, embedHtml, settings, true, "src");
const isLinkRange = res !== null && res.h2 !== undefined; const isLinkRange = res !== null && res.h2 !== undefined;
if (isLinkRange) { const file = res?.file
if (isLinkRange && file !== undefined) {
const { vault } = app; const { vault } = app;
const foundNote : TFile | undefined = app.vault.getMarkdownFiles().filter( embedHtml.childNodes.forEach(x => {
x => x.basename == res.note x.remove()
).first() })
if (foundNote) { const linkRange = embedHtml.querySelectorAll("div.link-range-embed")
embedHtml.childNodes.forEach(x => {
x.remove() linkRange.forEach(x => {
x.remove()
})
if (isMarkdownPost) {
// prevent default embed functionality for markdown post processor
embedHtml.removeClasses(["internal-embed"])
// create a child div under embedHtml to place content inside
embedHtml = embedHtml.createDiv({
cls: ["internal-embed", "markdown-embed", "inline-embed", "is-loaded", "link-range-embed"]
}) })
const linkRange = embedHtml.querySelectorAll("div.link-range-embed")
linkRange.forEach(x => {
x.remove()
})
if (isMarkdownPost) {
// prevent default embed functionality for markdown post processor
embedHtml.removeClasses(["internal-embed"])
// create a child div under embedHtml to place content inside
embedHtml = embedHtml.createDiv({
cls: ["internal-embed", "markdown-embed", "inline-embed", "is-loaded", "link-range-embed"]
})
}
embedHtml.setText("")
embedHtml.createEl("h2", {
text: res.altText
})
const linkDiv = embedHtml.createDiv({
cls: ["markdown-embed-link"],
});
setIcon(linkDiv, 'link')
linkDiv.onClickEvent((ev: MouseEvent) => {
const leaf = app.workspace.getMostRecentLeaf();
leaf?.openFile(foundNote, {
state: {
scroll: res.h1Line
}
});
})
const fileContent = await vault.cachedRead(foundNote);
let lines = fileContent.split("\n");
lines = lines.slice(res.h1Line, res.h2Line);
const contentDiv = embedHtml.createDiv({
cls: ["markdown-embed-content"]
})
MarkdownRenderer.renderMarkdown(lines.join("\n"), contentDiv, "", null!)
} }
embedHtml.setText("")
embedHtml.createEl("h2", {
text: res.altText
})
const linkDiv = embedHtml.createDiv({
cls: ["markdown-embed-link"],
});
setIcon(linkDiv, 'link')
linkDiv.onClickEvent((ev: MouseEvent) => {
const leaf = app.workspace.getMostRecentLeaf();
leaf?.openFile(file, {
state: {
scroll: res.h1Line
}
});
})
const fileContent = await vault.cachedRead(file);
let lines = fileContent.split("\n");
lines = lines.slice(res.h1Line, res.h2Line);
const contentDiv = embedHtml.createDiv({
cls: ["markdown-embed-content"]
})
MarkdownRenderer.renderMarkdown(lines.join("\n"), contentDiv, "", null!)
} }
} }

View file

@ -1,19 +1,17 @@
import { App, TFile } from "obsidian"; import { App, TFile } from "obsidian";
import { LinkRangeSettings, Pattern } from "./settings"; import { LinkRangeSettings, Pattern } from "./settings";
import * as path from 'path';
export interface ParsedLink { export interface ParsedLink {
note: string; note: string;
h1: string; h1: string;
h2?: string; h2?: string;
altText?: string; altText?: string;
file?: TFile;
h1Line?: number; h1Line?: number;
h2Line?: number; h2Line?: number;
} }
const NOTE_PLACEHOLDER = "$note"
const H1_PLACEHOLDER = "$h1"
const H2_PLACEHOLDER = "$h2"
export function checkLinkText(href: string, settings: LinkRangeSettings): ParsedLink | null { export function checkLinkText(href: string, settings: LinkRangeSettings): ParsedLink | null {
const linkRegex = /([^#|]*)#?([^#|]*)?\|?(.*)?/; const linkRegex = /([^#|]*)#?([^#|]*)?\|?(.*)?/;
@ -36,19 +34,18 @@ export function checkLinkText(href: string, settings: LinkRangeSettings): Parsed
altText = matches[3] altText = matches[3]
} }
else { else {
let pattern = findPatternForFile(note, settings); const pattern = findPatternForFile(note, settings);
const baseNote = path.basename(note)
let headingVisual = pattern.headingVisual === '' ? '#' : pattern.headingVisual; const headingVisual = pattern.headingVisual === '' ? '#' : pattern.headingVisual;
let headingSeparatorVisual = pattern.headingSeparatorVisual === '' ? settings.headingSeparator : pattern.headingSeparatorVisual; const headingSeparatorVisual = pattern.headingSeparatorVisual === '' ? settings.headingSeparator : pattern.headingSeparatorVisual;
if (h2 !== undefined) { if (h2 !== undefined) {
altText = `${note}${headingVisual}${h1}${headingSeparatorVisual}${h2}` altText = `${baseNote}${headingVisual}${h1}${headingSeparatorVisual}${h2}`
} }
else { else {
altText = `${note}${headingVisual}${h1}` altText = `${baseNote}${headingVisual}${h1}`
} }
} }
return { note, h1, h2, altText } return { note, h1, h2, altText }
} }
@ -63,63 +60,69 @@ export function checkLink(app :App, linkHTML: HTMLElement, settings: LinkRangeSe
const alt = linkHTML.getAttribute("alt") const alt = linkHTML.getAttribute("alt")
if (res && app.metadataCache != null) { if (!res || app.metadataCache == null) {
// non-standard alt text, must be user provided via "|" return null;
if (alt != null && !alt.contains(res.note)) {
res.altText = alt
}
if (!isEmbed && !linkHTML.innerText.contains(res.note)) {
res.altText = linkHTML.innerText
}
const foundNote : TFile | undefined = app.vault.getMarkdownFiles().filter(
x => x.basename == res.note
).first()
if (foundNote) {
const meta = app.metadataCache.getFileCache(foundNote);
if (meta == undefined || meta?.headings == undefined) {
return null;
}
const h1Line = meta?.headings?.filter(
h => h.heading == res.h1
).first()?.position.start.line;
let h2Line = null;
if (settings.endInclusive) {
let h2LineIndex = meta?.headings?.findIndex(
h => h.heading == res.h2
)
if (meta?.headings?.length > h2LineIndex) {
h2LineIndex += 1
}
h2Line = meta?.headings?.at(h2LineIndex)?.position.end.line
}
else {
h2Line = meta?.headings?.filter(
h => h.heading == res.h2
).first()?.position.end.line;
}
if (h1Line == undefined) {
return null;
}
res.h1Line = h1Line
res.h2Line = h2Line
return res;
}
} }
return null; // non-standard alt text, must be user provided via "|"
if (alt != null && !alt.contains(res.note)) {
res.altText = alt
}
if (!isEmbed && !linkHTML.innerText.contains(res.note)) {
res.altText = linkHTML.innerText
}
// Locate the referenced file, including partial paths
const partialPath = res.note + ".md"
const basePart = path.basename(res.note)
const file : TFile | undefined = app.vault.getMarkdownFiles().filter(
x => x.basename == basePart && x.path.endsWith(partialPath)
).first()
if (!file) {
return null
}
res.file = file
const meta = app.metadataCache.getFileCache(file);
if (meta == undefined || meta?.headings == undefined) {
return null;
}
const h1Line = meta?.headings?.filter(
h => h.heading == res.h1
).first()?.position.start.line;
let h2Line = null;
if (settings.endInclusive) {
let h2LineIndex = meta?.headings?.findIndex(
h => h.heading == res.h2
)
if (meta?.headings?.length > h2LineIndex) {
h2LineIndex += 1
}
h2Line = meta?.headings?.at(h2LineIndex)?.position.end.line
}
else {
h2Line = meta?.headings?.filter(
h => h.heading == res.h2
).first()?.position.end.line;
}
if (h1Line == undefined) {
return null;
}
res.h1Line = h1Line
res.h2Line = h2Line
return res;
} }
export function postProcessorUpdate(app: App) { export function postProcessorUpdate(app: App) {