import {Plugin, Notice, addIcon, View, MarkdownView} from "obsidian"
import ExtractHighlightsPluginSettings from "./ExtractHighlightsPluginSettings"
import ExtractHighlightsPluginSettingsTab from "./ExtractHighlightsPluginSettingsTab"
import {Position} from "codemirror";
addIcon('target', '')
export default class ExtractHighlightsPlugin extends Plugin {
public settings: ExtractHighlightsPluginSettings;
public statusBar: HTMLElement
public counter: 0;
private editor: CodeMirror.Editor;
async onload() {
this.counter = 0;
this.loadSettings();
this.addSettingTab(new ExtractHighlightsPluginSettingsTab(this.app, this));
this.statusBar = this.addStatusBarItem()
this.addRibbonIcon('target', 'Extract Highlights', () => {
this.extractHighlights();
});
this.registerEvent(
this.app.on('codemirror', (cm: CodeMirror.Editor | MarkdownView) => {
if ('sourceMode' in cm) {
this.editor = cm.sourceMode.cmEditor;
} else {
this.editor = cm;
}
}),
);
this.addCommand({
id: "shortcut-extract-highlights",
name: "Shortcut for extracting highlights",
callback: () => this.extractHighlights(),
hotkeys: [
{
modifiers: ["Alt", "Shift"],
key: "±",
},
],
});
this.addCommand({
id: "shortcut-highlight-sentence",
name: "Shortcut for highlighting sentence cursor is in",
callback: () => this.toggleLineHighlight(),
hotkeys: [
{
modifiers: ["Alt", "Shift"],
key: "—",
},
],
});
}
loadSettings() {
this.settings = new ExtractHighlightsPluginSettings();
(async () => {
const loadedSettings = await this.loadData();
if (loadedSettings) {
console.log("Found existing settings file");
this.settings.headlineText = loadedSettings.headlineText;
this.settings.addFootnotes = loadedSettings.addFootnotes;
} else {
console.log("No settings file found, saving...");
this.saveData(this.settings);
}
})();
}
extractHighlights(): void {
let activeLeaf: any = this.app.workspace.activeLeaf ?? null
try {
if (activeLeaf?.view?.data) {
let highlightsText = this.processHighlights(activeLeaf.view);
let saveStatus = this.saveToClipboard(highlightsText);
new Notice(saveStatus);
} else {
new Notice("No highlights to extract.");
}
} catch (e) {
console.log(e.message)
}
}
toggleLineHighlight() {
const cursorPosition = this.editor.getCursor();
const ch = cursorPosition.ch;
const line = cursorPosition.line;
const lineText = this.editor.getLine(cursorPosition.line);
const allTextLeftOfCursor = lineText.substr(0, cursorPosition.ch);
let periodIndexLeftOfCursor = allTextLeftOfCursor.lastIndexOf(".");
if(periodIndexLeftOfCursor == -1) { periodIndexLeftOfCursor = 0; }
let sentenceUntilLeftOfCursor = allTextLeftOfCursor.substr(periodIndexLeftOfCursor, ch - periodIndexLeftOfCursor);
if(sentenceUntilLeftOfCursor.startsWith(". ")) { sentenceUntilLeftOfCursor = sentenceUntilLeftOfCursor.replace(". ", "")}
const allTextRightOfCursor = lineText.substr(cursorPosition.ch);
let periodIndexRightOfCursor = allTextRightOfCursor.indexOf(".");
if(periodIndexRightOfCursor == -1) {periodIndexRightOfCursor = allTextRightOfCursor.length};
let sentenceUntilRightOfCursor = allTextRightOfCursor.substr(0, periodIndexRightOfCursor + 1);
let currentSentence = sentenceUntilLeftOfCursor + sentenceUntilRightOfCursor;
let absolutePeriodIndexRightOfCursor = periodIndexRightOfCursor + allTextLeftOfCursor.length;
currentSentence = "==" + currentSentence + "==";
let replaceOffset = periodIndexLeftOfCursor;
if(allTextLeftOfCursor.contains(".")) {
replaceOffset = periodIndexLeftOfCursor + 2
}
this.editor.replaceRange(currentSentence, {line: line, ch: replaceOffset}, {line: line, ch: absolutePeriodIndexRightOfCursor + 1});
this.editor.setCursor(cursorPosition);
}
toggleFullLine() {
const cursorPosition = this.editor.getCursor();
let lineText = this.editor.getLine(cursorPosition.line);
let highlightedLine = "";
let startPosition: Position;
let endPosition: Position;
if(lineText.startsWith("==") && lineText.endsWith("==")) {
highlightedLine = lineText.replace(/==/g, "");
startPosition = {line: cursorPosition.line, ch: 0};
endPosition = {line: cursorPosition.line, ch: highlightedLine.length + 4};
} else {
highlightedLine = "==" + lineText + "==";
startPosition = {line: cursorPosition.line, ch: 0};
endPosition = {line: cursorPosition.line, ch: highlightedLine.length};
}
this.editor.replaceRange(highlightedLine, startPosition, endPosition);
this.editor.setCursor(cursorPosition);
}
processHighlights(view: any): string {
var re;
if(this.settings.useBoldForHighlights) {
re = /(==|\|\*\*)([\s\S]*?)(==|\<\/mark\>|\*\*)/g;
} else {
re = /(==|\)([\s\S]*?)(==|\<\/mark\>)/g;
}
let data = view.data;
let basename = view.file.basename;
let matches = data.match(re);
this.counter += 1;
console.log(matches.length);
var result = "";
if (matches != null) {
if(this.settings.headlineText != "") {
let text = this.settings.headlineText.replace(/\$NOTE_TITLE/, `${basename}`)
result += `## ${text}\n`;
}
for (let entry of matches) {
var removeNewline = entry.replace(/\n/g, " ");
let removeHighlightStart = removeNewline.replace(/==/g, "")
let removeHighlightEnd = removeHighlightStart.replace(/\/g, "")
let removeMarkClosing = removeHighlightEnd.replace(/\<\/mark\>/g, "")
let removeBold = removeMarkClosing.replace(/\*\*/g, "")
let removeDoubleSpaces = removeBold.replace(" ", " ");
removeDoubleSpaces = removeDoubleSpaces.replace(" ", " ");
removeDoubleSpaces = removeDoubleSpaces.trim();
result += "- " + removeDoubleSpaces
if(this.settings.addFootnotes) {
result += `[^${this.counter}]`;
}
result += "\n";
}
if(this.settings.addFootnotes) {
result += "\n"
result += `[^${this.counter}]: [[${basename}]]\n`
}
result += "\n";
}
return result;
}
saveToClipboard(data: string): string {
if (data.length > 0) {
navigator.clipboard.writeText(data);
return "Highlights copied to clipboard!";
} else {
return "No highlights found";
}
}
}