feat: add open modal support, refactor client, change setting naming
This commit is contained in:
+18
-12
@@ -1,5 +1,4 @@
|
|||||||
import { Notice, requestUrl } from 'obsidian';
|
import { Notice, requestUrl } from 'obsidian';
|
||||||
import Cite from "./main";
|
|
||||||
|
|
||||||
type ZoteroItemResponse = {
|
type ZoteroItemResponse = {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -19,16 +18,25 @@ type ZoteroItemResponse = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CiteClient {
|
export class ZoteroClient {
|
||||||
|
|
||||||
private baseURL: string;
|
|
||||||
private userID: number;
|
private userID: number;
|
||||||
private style: string;
|
private baseURL: string;
|
||||||
|
private style?: string;
|
||||||
|
private baseParams: URLSearchParams;
|
||||||
|
|
||||||
constructor(port: string, style: string){
|
constructor(port: string);
|
||||||
this.baseURL = `http://127.0.0.1:${port}/api`;
|
constructor(port: string, style: string);
|
||||||
|
constructor(port: string, style?: string) {
|
||||||
this.userID = 0;
|
this.userID = 0;
|
||||||
|
this.baseURL = `http://127.0.0.1:${port}/api/users/${this.userID}`;
|
||||||
this.style = style;
|
this.style = style;
|
||||||
|
this.baseParams = new URLSearchParams();
|
||||||
|
if (this.style) {
|
||||||
|
this.baseParams.set("style", this.style);
|
||||||
|
}
|
||||||
|
this.baseParams.set("format", "json");
|
||||||
|
this.baseParams.set("include", "citation,bib,data");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async request<T>(url: string): Promise<T> {
|
private async request<T>(url: string): Promise<T> {
|
||||||
@@ -58,15 +66,13 @@ export class CiteClient {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllCitations(): Promise<ZoteroItemResponse[]> {
|
async getItems(): Promise<ZoteroItemResponse[]> {
|
||||||
const url = `${this.baseURL}/users/${this.userID}/items?format=json&include=citation,data&style=${this.style}`
|
const url = `${this.baseURL}/items?${this.baseParams.toString()}`;
|
||||||
console.log(url)
|
|
||||||
return this.request<ZoteroItemResponse[]>(url);
|
return this.request<ZoteroItemResponse[]>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllBibliographies(): Promise<ZoteroItemResponse[]> {
|
async getItemsTop(): Promise<ZoteroItemResponse[]> {
|
||||||
const url = `${this.baseURL}/users/${this.userID}/items?format=json&include=bib,data&style=${this.style}`
|
const url = `${this.baseURL}/items/top?${this.baseParams.toString()}`;
|
||||||
console.log(url)
|
|
||||||
return this.request<ZoteroItemResponse[]>(url);
|
return this.request<ZoteroItemResponse[]>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-2
@@ -1,6 +1,6 @@
|
|||||||
import { App, Editor, MarkdownView, Modal, Plugin, Notice } from 'obsidian';
|
import { App, Editor, MarkdownView, Modal, Plugin, Notice } from 'obsidian';
|
||||||
import { DEFAULT_SETTINGS, CiteSettings, CiteSettingTab } from "./settings";
|
import { DEFAULT_SETTINGS, CiteSettings, CiteSettingTab } from "./settings";
|
||||||
import { CiteModal } from "./modals"
|
import { CiteModal, OpenModal } from "./modals"
|
||||||
|
|
||||||
export default class Cite extends Plugin {
|
export default class Cite extends Plugin {
|
||||||
settings: CiteSettings;
|
settings: CiteSettings;
|
||||||
@@ -25,6 +25,22 @@ export default class Cite extends Plugin {
|
|||||||
}).open();
|
}).open();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addRibbonIcon('scroll-text', 'insert bibliography', (evt: MouseEvent) => {
|
||||||
|
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||||
|
|
||||||
|
if (!view) {
|
||||||
|
new Notice("No active Markdown view");
|
||||||
|
console.log("No active Markdown view");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = view.editor;
|
||||||
|
|
||||||
|
new CiteModal(this.app, this.settings.portSetting, this.settings.linkSetting, this.settings.styleSetting, "bibliography", (citation: string) => {
|
||||||
|
editor.replaceSelection(citation);
|
||||||
|
}).open();
|
||||||
|
});
|
||||||
|
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: 'citation-command',
|
id: 'citation-command',
|
||||||
name: 'insert citation',
|
name: 'insert citation',
|
||||||
@@ -41,12 +57,20 @@ export default class Cite extends Plugin {
|
|||||||
name: 'insert bibliography',
|
name: 'insert bibliography',
|
||||||
editorCallback: (editor: Editor, view: MarkdownView) => {
|
editorCallback: (editor: Editor, view: MarkdownView) => {
|
||||||
const selection = editor.getSelection();
|
const selection = editor.getSelection();
|
||||||
new CiteModal(this.app, this.settings.portSetting, this.settings.linkSetting, this.settings.styleSetting, "bibliography",(bibliography: string) => {
|
new CiteModal(this.app, this.settings.portSetting, this.settings.linkSetting, this.settings.styleSetting, "bibliography", (bibliography: string) => {
|
||||||
editor.replaceSelection(bibliography);
|
editor.replaceSelection(bibliography);
|
||||||
}).open();
|
}).open();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.addCommand({
|
||||||
|
id: 'open-command',
|
||||||
|
name: 'open',
|
||||||
|
callback: () => {
|
||||||
|
new OpenModal(this.app, this.settings.portSetting).open();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.addSettingTab(new CiteSettingTab(this.app, this));
|
this.addSettingTab(new CiteSettingTab(this.app, this));
|
||||||
|
|
||||||
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
|
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
|
||||||
|
|||||||
+101
-8
@@ -1,10 +1,104 @@
|
|||||||
|
import { shell } from "electron";
|
||||||
import { App, FuzzyMatch, FuzzySuggestModal, renderResults, Notice } from 'obsidian';
|
import { App, FuzzyMatch, FuzzySuggestModal, renderResults, Notice } from 'obsidian';
|
||||||
import {CiteClient, ZoteroItemResponse} from "./clients"
|
import { ZoteroClient } from "./clients";
|
||||||
|
import type { ZoteroItemResponse } from "./clients";
|
||||||
|
|
||||||
|
export class OpenModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
||||||
|
private client: ZoteroClient;
|
||||||
|
private items: ZoteroItemResponse[] = [];
|
||||||
|
private zoteroBaseUrl;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
app: App,
|
||||||
|
port: string,
|
||||||
|
) {
|
||||||
|
super(app);
|
||||||
|
this.client = new ZoteroClient(port);
|
||||||
|
this.setPlaceholder("Loading references...");
|
||||||
|
this.zoteroBaseUrl = "zotero://select/library/items/";
|
||||||
|
}
|
||||||
|
|
||||||
|
async onOpen(){
|
||||||
|
super.onOpen();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.items = await this.client.getItemsTop();
|
||||||
|
this.setPlaceholder("Search Zotero...");
|
||||||
|
this.inputEl.disabled = false;
|
||||||
|
this.inputEl.focus();
|
||||||
|
this.updateSuggestions();
|
||||||
|
} catch (error) {
|
||||||
|
new Notice("Failed to load citations/bibliographies from Zotero. Maybe you forgot to turn on or configure Zotero.");
|
||||||
|
console.error(error);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private getTitle(item: ZoteroItemResponse): string {
|
||||||
|
return item.data?.title ?? "Untitled";
|
||||||
|
}
|
||||||
|
|
||||||
|
private getYear(item: ZoteroItemResponse): string {
|
||||||
|
const date = item.data?.date;
|
||||||
|
if (!date) return "n.d.";
|
||||||
|
|
||||||
|
const match = date.match(/\b\d{4}\b/);
|
||||||
|
return match ? match[0] : "n.d.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAuthor(item: ZoteroItemResponse): string {
|
||||||
|
const creators = item.data?.creators;
|
||||||
|
if (!creators || creators.length === 0) return "Unknown author";
|
||||||
|
|
||||||
|
const first = creators[0];
|
||||||
|
|
||||||
|
if (first.name) return first.name;
|
||||||
|
if (first.firstName && first.lastName) return `${first.firstName} ${first.lastName}`;
|
||||||
|
if (first.lastName) return first.lastName;
|
||||||
|
|
||||||
|
return "Unknown author";
|
||||||
|
}
|
||||||
|
|
||||||
|
private getKey(item: ZoteroItemResponse): string {
|
||||||
|
return item.key ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
getItems(): ZoteroItemResponse[] {
|
||||||
|
return this.items;
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemText(item: ZoteroItemResponse): string {
|
||||||
|
return `${this.getTitle(item)} ${this.getAuthor(item)} ${this.getYear(item)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSuggestion(match: FuzzyMatch<ZoteroItemResponse>, el: HTMLElement) {
|
||||||
|
const { item } = match;
|
||||||
|
|
||||||
|
const title = this.getTitle(item);
|
||||||
|
const author = this.getAuthor(item);
|
||||||
|
const year = this.getYear(item);
|
||||||
|
|
||||||
|
const titleEl = el.createDiv();
|
||||||
|
renderResults(titleEl, title, match.match);
|
||||||
|
|
||||||
|
const subtitleEl = el.createEl("small");
|
||||||
|
const offset = -(title.length + 1);
|
||||||
|
renderResults(subtitleEl, `${author}, ${year}`, match.match, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChooseItem(item: ZoteroItemResponse) {
|
||||||
|
if (!this.getKey(item)) return;
|
||||||
|
const uri = `${this.zoteroBaseUrl}${this.getKey(item)}`;
|
||||||
|
shell.openExternal(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
export class CiteModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
export class CiteModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
||||||
|
|
||||||
private onChoose: (citation: string) => void;
|
private onChoose: (reference: string) => void;
|
||||||
private client: CiteClient;
|
private client: ZoteroClient;
|
||||||
private items: ZoteroItemResponse[] = [];
|
private items: ZoteroItemResponse[] = [];
|
||||||
private zoteroBaseUrl: string;
|
private zoteroBaseUrl: string;
|
||||||
private createLink: boolean;
|
private createLink: boolean;
|
||||||
@@ -16,10 +110,10 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
|||||||
createLink: boolean,
|
createLink: boolean,
|
||||||
style: string,
|
style: string,
|
||||||
mode: string,
|
mode: string,
|
||||||
onChoose: (citation: string) => void,
|
onChoose: (reference: string) => void,
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.client = new CiteClient(port, style);
|
this.client = new ZoteroClient(port, style);
|
||||||
this.onChoose = onChoose;
|
this.onChoose = onChoose;
|
||||||
this.setPlaceholder("Loading citations...");
|
this.setPlaceholder("Loading citations...");
|
||||||
this.zoteroBaseUrl = "zotero://select/library/items/";
|
this.zoteroBaseUrl = "zotero://select/library/items/";
|
||||||
@@ -32,9 +126,9 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.mode === "citation"){
|
if (this.mode === "citation"){
|
||||||
this.items = await this.client.getAllCitations();
|
this.items = await this.client.getItemsTop();
|
||||||
} else if (this.mode === "bibliography"){
|
} else if (this.mode === "bibliography"){
|
||||||
this.items = await this.client.getAllBibliographies();
|
this.items = await this.client.getItemsTop();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown mode: ${this.mode}`);
|
throw new Error(`Unknown mode: ${this.mode}`);
|
||||||
}
|
}
|
||||||
@@ -109,7 +203,6 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItemResponse> {
|
|||||||
renderResults(subtitleEl, `${author}, ${year}`, match.match, offset);
|
renderResults(subtitleEl, `${author}, ${year}`, match.match, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onChooseItem(item: ZoteroItemResponse) {
|
onChooseItem(item: ZoteroItemResponse) {
|
||||||
|
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|||||||
+1
-2
@@ -1,5 +1,4 @@
|
|||||||
import {App, PluginSettingTab, Setting } from "obsidian";
|
import {App, PluginSettingTab, Setting } from "obsidian";
|
||||||
import Cite from "./main";
|
|
||||||
|
|
||||||
export interface CiteSettings {
|
export interface CiteSettings {
|
||||||
portSetting: string;
|
portSetting: string;
|
||||||
@@ -49,7 +48,7 @@ export class CiteSettingTab extends PluginSettingTab {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName('Add link to library')
|
.setName('URI')
|
||||||
.setDesc('zotero://select/library/items/...')
|
.setDesc('zotero://select/library/items/...')
|
||||||
.addToggle(toggle => toggle
|
.addToggle(toggle => toggle
|
||||||
.setValue(this.plugin.settings.linkSetting)
|
.setValue(this.plugin.settings.linkSetting)
|
||||||
|
|||||||
Reference in New Issue
Block a user