generated from obsidianmd/obsidian-sample-plugin
-
-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Description
I made couple of modifications in the code to be able to select text when copying a block link so when it is pasted the text is shown as an alias of the file link.
Case
- We want to copy a unique text "field-to-field discrete PINNs by leveraging convolution operations and numerical discretizations" as a block link
- We select the text and right-click and pick the new menu option "Copy text link to block":
Voila!
Changes required
- Line 45, add this line:
const aliasText = editor.getSelection();
- Line 55 add a comma at the end; line 56 add
aliasText
- Line 68, add this menu.addItem
menu.addItem((item) => {
item
.setTitle(isHeading ? "Copy link to heading" : "Copy text link to block")
.setIcon("links-coming-in")
.onClick(() => onClick(false));
});
-
Line 88, add
let aliasText = ""
-
Line 93, add this
addCommand
this.addCommand({
id: "copy-text-link-to-block",
name: "Copy text as link to current block or heading",
editorCheckCallback: (isChecking, editor: Editor, view: MarkdownView) => {
let aliasText = editor.getSelection();
return this.handleCommand(isChecking, editor, view, false, aliasText);
},
});
-
Line 106, add
let aliasText = ""
-
Line 117, add
aliasText: string
-
Line 137, add
aliasText
-
Line 185, 186, add a comma and
aliasText: string
-
Line 196
"#^" + blockId, (aliasText.length > 0 ? aliasText : "")
- Line 217
"#^" + id, (aliasText.length > 0 ? aliasText : "")
Modified main.ts attached:
import {
Editor,
EditorPosition,
HeadingCache,
ListItemCache,
MarkdownView,
Plugin,
SectionCache,
TFile,
} from "obsidian";
function generateId(): string {
return Math.random().toString(36).substr(2, 6);
}
const illegalHeadingCharsRegex = /[!"#$%&()*+,.:;<=>?@^`{|}~\/\[\]\\]/g;
function sanitizeHeading(heading: string) {
return heading
.replace(illegalHeadingCharsRegex, " ")
.replace(/\s+/g, " ")
.trim();
}
function shouldInsertAfter(block: ListItemCache | SectionCache) {
if ((block as any).type) {
return [
"blockquote",
"code",
"table",
"comment",
"footnoteDefinition",
].includes((block as SectionCache).type);
}
}
export default class MyPlugin extends Plugin {
async onload() {
this.registerEvent(
this.app.workspace.on("editor-menu", (menu, editor, view) => {
const block = this.getBlock(editor, view.file);
if (!block) return;
const isHeading = !!(block as any).heading;
const aliasText = editor.getSelection();
const onClick = (isEmbed: boolean) => {
if (isHeading) {
this.handleHeading(view.file, block as HeadingCache, isEmbed);
} else {
this.handleBlock(
view.file,
editor,
block as SectionCache | ListItemCache,
isEmbed,
aliasText
);
}
};
menu.addItem((item) => {
item
.setTitle(isHeading ? "Copy link to heading" : "Copy link to block")
.setIcon("links-coming-in")
.onClick(() => onClick(false));
});
menu.addItem((item) => {
item
.setTitle(isHeading ? "Copy link to heading" : "Copy text link to block")
.setIcon("links-coming-in")
.onClick(() => onClick(false));
});
menu.addItem((item) => {
item
.setTitle(isHeading ? "Copy heading embed" : "Copy block embed")
.setIcon("links-coming-in")
.onClick(() => onClick(true));
});
})
);
this.addCommand({
id: "copy-link-to-block",
name: "Copy link to current block or heading",
editorCheckCallback: (isChecking, editor, view) => {
let aliasText = ""
return this.handleCommand(isChecking, editor, view, false, aliasText);
},
});
this.addCommand({
id: "copy-text-link-to-block",
name: "Copy text as link to current block or heading",
editorCheckCallback: (isChecking, editor: Editor, view: MarkdownView) => {
let aliasText = editor.getSelection();
return this.handleCommand(isChecking, editor, view, false, aliasText);
},
});
this.addCommand({
id: "copy-embed-to-block",
name: "Copy embed to current block or heading",
editorCheckCallback: (isChecking, editor, view) => {
let aliasText = ""
return this.handleCommand(isChecking, editor, view, true, aliasText);
},
});
}
handleCommand(
isChecking: boolean,
editor: Editor,
view: MarkdownView,
isEmbed: boolean,
aliasText: string
) {
if (isChecking) {
return !!this.getBlock(editor, view.file);
}
const block = this.getBlock(editor, view.file);
if (!block) return;
const isHeading = !!(block as any).heading;
if (isHeading) {
this.handleHeading(view.file, block as HeadingCache, isEmbed);
} else {
this.handleBlock(
view.file,
editor,
block as SectionCache | ListItemCache,
isEmbed,
aliasText
);
}
}
getBlock(editor: Editor, file: TFile) {
const cursor = editor.getCursor("to");
const fileCache = this.app.metadataCache.getFileCache(file);
let block: ListItemCache | HeadingCache | SectionCache = (
fileCache?.sections || []
).find((section) => {
return (
section.position.start.line <= cursor.line &&
section.position.end.line >= cursor.line
);
});
if (block?.type === "list") {
block = (fileCache?.listItems || []).find((item) => {
return (
item.position.start.line <= cursor.line &&
item.position.end.line >= cursor.line
);
});
} else if (block?.type === "heading") {
block = fileCache.headings.find((heading) => {
return heading.position.start.line === block.position.start.line;
});
}
return block;
}
handleHeading(file: TFile, block: HeadingCache, isEmbed: boolean) {
navigator.clipboard.writeText(
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
file,
"",
"#" + sanitizeHeading(block.heading)
)}`
);
}
handleBlock(
file: TFile,
editor: Editor,
block: ListItemCache | SectionCache,
isEmbed: boolean,
aliasText: string
) {
const blockId = block.id;
// Copy existing block id
if (blockId) {
return navigator.clipboard.writeText(
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
file,
"",
"#^" + blockId, (aliasText.length > 0 ? aliasText : "")
)}`
);
}
// Add a block id
const sectionEnd = block.position.end;
const end: EditorPosition = {
ch: sectionEnd.col,
line: sectionEnd.line,
};
const id = generateId();
const spacer = shouldInsertAfter(block) ? "\n\n" : " ";
editor.replaceRange(`${spacer}^${id}`, end);
navigator.clipboard.writeText(
`${isEmbed ? "!" : ""}${this.app.fileManager.generateMarkdownLink(
file,
"",
// "#^" + id, "add-block-id"
"#^" + id, (aliasText.length > 0 ? aliasText : "")
)}`
);
}
}
greetclammy and nicolnt
Metadata
Metadata
Assignees
Labels
No labels