feat: add secondary search parameter
This commit is contained in:
+19
-22
@@ -1,27 +1,25 @@
|
|||||||
import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian';
|
import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian';
|
||||||
import { ZoteroClient } from "./ZoteroClient";
|
import { ZoteroClient } from "./ZoteroClient";
|
||||||
import { ZoteroAnnotation } from "./ZoteroAnnotation";
|
|
||||||
import { loadAnnotations, renderZoteroAnnotation } from "./Utils"
|
import { loadAnnotations, renderZoteroAnnotation } from "./Utils"
|
||||||
|
import { Settings } from "./Settings";
|
||||||
|
|
||||||
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
||||||
|
|
||||||
export class AnnotationModal extends FuzzySuggestModal<ZoteroAnnotation> {
|
export class AnnotationModal extends FuzzySuggestModal<ZoteroItem> {
|
||||||
private client: ZoteroClient;
|
private client: ZoteroClient;
|
||||||
private annotations: ZoteroAnnotation[] = [];
|
private annotations: ZoteroItem[] = [];
|
||||||
private createLink: boolean;
|
private onChoose: (item: string) => void;
|
||||||
private onChoose: (annotations: string) => void;
|
private settings: Settings;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
app: App,
|
app: App,
|
||||||
port: string,
|
settings: Settings,
|
||||||
createLink: boolean,
|
onChoose: (item: string) => void,
|
||||||
style: string,
|
|
||||||
onChoose: (annotations: string) => void,
|
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.client = new ZoteroClient(port, style);
|
this.settings = settings;
|
||||||
|
this.client = new ZoteroClient(this.settings.port, this.settings.style);
|
||||||
this.setPlaceholder("Loading...");
|
this.setPlaceholder("Loading...");
|
||||||
this.createLink = createLink
|
|
||||||
this.onChoose = onChoose;
|
this.onChoose = onChoose;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,28 +28,27 @@ export class AnnotationModal extends FuzzySuggestModal<ZoteroAnnotation> {
|
|||||||
super.onOpen();
|
super.onOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
getItems(): ZoteroAnnotation[] {
|
getItems(): ZoteroItem[] {
|
||||||
return this.annotations;
|
return this.annotations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getItemText(item: ZoteroItem): string {
|
||||||
getItemText(annotation: ZoteroAnnotation): string {
|
return `${item.annotationText} ${item.parentItem[this.settings.search]}`;
|
||||||
return annotation.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSuggestion(match: FuzzyMatch<ZoteroAnnotation>, el: HTMLElement) {
|
renderSuggestion(match: FuzzyMatch<ZoteroItem>, el: HTMLElement) {
|
||||||
renderZoteroAnnotation(match, el);
|
renderZoteroAnnotation(match, el, this.settings.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onChooseItem(annotation: ZoteroAnnotation) {
|
async onChooseItem(item: ZoteroItem) {
|
||||||
|
|
||||||
let citation = annotation.parentItem.citation;
|
let citation = item.parentItem.citation ?? "";
|
||||||
|
|
||||||
if (this.createLink) {
|
if (this.settings.link) {
|
||||||
citation = `[${citation}](${ZOTERO_BASE_URL}${annotation.parentItemKey})`;
|
citation = `[${citation}](${ZOTERO_BASE_URL}${item.parentItemKey})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onChoose(`"${annotation.text}" ${citation}`);
|
this.onChoose(`"${item.annotationText}" ${citation}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-9
@@ -2,6 +2,7 @@ import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian';
|
|||||||
import { ZoteroClient } from "./ZoteroClient";
|
import { ZoteroClient } from "./ZoteroClient";
|
||||||
import { ZoteroItem } from "./ZoteroItem";
|
import { ZoteroItem } from "./ZoteroItem";
|
||||||
import { loadItems, renderZoteroItem } from "./Utils"
|
import { loadItems, renderZoteroItem } from "./Utils"
|
||||||
|
import { Settings } from "./Settings";
|
||||||
|
|
||||||
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
||||||
|
|
||||||
@@ -10,21 +11,19 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItem> {
|
|||||||
private onChoose: (reference: string) => void;
|
private onChoose: (reference: string) => void;
|
||||||
private client: ZoteroClient;
|
private client: ZoteroClient;
|
||||||
private items: ZoteroItem[] = [];
|
private items: ZoteroItem[] = [];
|
||||||
private createLink: boolean;
|
private settings: Settings;
|
||||||
private mode: string;
|
private mode: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
app: App,
|
app: App,
|
||||||
port: string,
|
settings: Settings,
|
||||||
createLink: boolean,
|
|
||||||
style: string,
|
|
||||||
mode: string,
|
mode: string,
|
||||||
onChoose: (reference: string) => void,
|
onChoose: (reference: string) => void,
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.setPlaceholder("Loading...");
|
this.setPlaceholder("Loading...");
|
||||||
this.client = new ZoteroClient(port, style);
|
this.settings = settings;
|
||||||
this.createLink = createLink;
|
this.client = new ZoteroClient(this.settings.port, this.settings.style);
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.onChoose = onChoose;
|
this.onChoose = onChoose;
|
||||||
}
|
}
|
||||||
@@ -39,11 +38,11 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getItemText(item: ZoteroItem): string {
|
getItemText(item: ZoteroItem): string {
|
||||||
return item.toString();
|
return `${item.title} ${item[this.settings.search]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSuggestion(match: FuzzyMatch<ZoteroItem>, el: HTMLElement) {
|
renderSuggestion(match: FuzzyMatch<ZoteroItem>, el: HTMLElement) {
|
||||||
renderZoteroItem(match, el);
|
renderZoteroItem(match, el, this.settings.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChooseItem(item: ZoteroItem) {
|
onChooseItem(item: ZoteroItem) {
|
||||||
@@ -58,7 +57,7 @@ export class CiteModal extends FuzzySuggestModal<ZoteroItem> {
|
|||||||
throw new Error(`Unknown mode: ${this.mode}`);
|
throw new Error(`Unknown mode: ${this.mode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.createLink) {
|
if (!this.settings.link) {
|
||||||
this.onChoose(output);
|
this.onChoose(output);
|
||||||
} else {
|
} else {
|
||||||
this.onChoose(`[${output}](${ZOTERO_BASE_URL}${item.key})`);
|
this.onChoose(`[${output}](${ZOTERO_BASE_URL}${item.key})`);
|
||||||
|
|||||||
+7
-4
@@ -3,19 +3,22 @@ import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian';
|
|||||||
import { ZoteroClient } from "./ZoteroClient";
|
import { ZoteroClient } from "./ZoteroClient";
|
||||||
import { ZoteroItem } from "./ZoteroItem";
|
import { ZoteroItem } from "./ZoteroItem";
|
||||||
import { loadItems, renderZoteroItem } from "./Utils"
|
import { loadItems, renderZoteroItem } from "./Utils"
|
||||||
|
import { Settings } from "./Settings";
|
||||||
|
|
||||||
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
const ZOTERO_BASE_URL = "zotero://select/library/items/";
|
||||||
|
|
||||||
export class OpenModal extends FuzzySuggestModal<ZoteroItem> {
|
export class OpenModal extends FuzzySuggestModal<ZoteroItem> {
|
||||||
private client: ZoteroClient;
|
private client: ZoteroClient;
|
||||||
private items: ZoteroItem[] = [];
|
private items: ZoteroItem[] = [];
|
||||||
|
private settings: Settings
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
app: App,
|
app: App,
|
||||||
port: string,
|
settings: Settings,
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
this.client = new ZoteroClient(port);
|
this.settings = settings;
|
||||||
|
this.client = new ZoteroClient(this.settings.port);
|
||||||
this.setPlaceholder("Loading...");
|
this.setPlaceholder("Loading...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,11 +32,11 @@ export class OpenModal extends FuzzySuggestModal<ZoteroItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getItemText(item: ZoteroItem): string {
|
getItemText(item: ZoteroItem): string {
|
||||||
return item.toString();
|
return `${item.title} ${item[this.settings.search]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSuggestion(match: FuzzyMatch<ZoteroItem>, el: HTMLElement) {
|
renderSuggestion(match: FuzzyMatch<ZoteroItem>, el: HTMLElement) {
|
||||||
renderZoteroItem(match, el);
|
renderZoteroItem(match, el, this.settings.search);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChooseItem(item: ZoteroItem) {
|
onChooseItem(item: ZoteroItem) {
|
||||||
|
|||||||
@@ -1,16 +1,5 @@
|
|||||||
import {App, PluginSettingTab, Setting } from "obsidian";
|
import {App, PluginSettingTab, Setting } from "obsidian";
|
||||||
|
import { ZoteroFields } from "./ZoteroFields";
|
||||||
export interface Settings {
|
|
||||||
portSetting: string;
|
|
||||||
styleSetting: string;
|
|
||||||
linkSetting: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: Settings = {
|
|
||||||
portSetting: '23119',
|
|
||||||
styleSetting: 'apa',
|
|
||||||
linkSetting: true
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SettingTab extends PluginSettingTab {
|
export class SettingTab extends PluginSettingTab {
|
||||||
plugin: Cite;
|
plugin: Cite;
|
||||||
@@ -30,9 +19,9 @@ export class SettingTab extends PluginSettingTab {
|
|||||||
.setDesc('http://localhost:<PORT>/api/')
|
.setDesc('http://localhost:<PORT>/api/')
|
||||||
.addText(text => text
|
.addText(text => text
|
||||||
.setPlaceholder('Enter a Port')
|
.setPlaceholder('Enter a Port')
|
||||||
.setValue(this.plugin.settings.portSetting)
|
.setValue(this.plugin.settings.port)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value) => {
|
||||||
this.plugin.settings.portSetting = value;
|
this.plugin.settings.port = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -41,9 +30,9 @@ export class SettingTab extends PluginSettingTab {
|
|||||||
.setDesc('https://www.zotero.org/styles?q=<STYLE>')
|
.setDesc('https://www.zotero.org/styles?q=<STYLE>')
|
||||||
.addText(text => text
|
.addText(text => text
|
||||||
.setPlaceholder('Enter a Style')
|
.setPlaceholder('Enter a Style')
|
||||||
.setValue(this.plugin.settings.styleSetting)
|
.setValue(this.plugin.settings.style)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value) => {
|
||||||
this.plugin.settings.styleSetting = value;
|
this.plugin.settings.style = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -51,14 +40,28 @@ export class SettingTab extends PluginSettingTab {
|
|||||||
.setName('URI')
|
.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.link)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value) => {
|
||||||
this.plugin.settings.linkSetting = value;
|
this.plugin.settings.link = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
this.display();
|
this.display();
|
||||||
})
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName('Search')
|
||||||
|
.setDesc('secondary search field')
|
||||||
|
.addDropdown(dropdown => {
|
||||||
|
ZoteroFields.forEach (opt => {
|
||||||
|
dropdown.addOption(opt, opt);
|
||||||
|
});
|
||||||
|
|
||||||
|
dropdown
|
||||||
|
.setValue(this.plugin.settings.search)
|
||||||
|
.onChange(async (value) => {
|
||||||
|
this.plugin.settings.search = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export interface Settings {
|
||||||
|
port: string;
|
||||||
|
style: string;
|
||||||
|
link: boolean;
|
||||||
|
search: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DEFAULT_SETTINGS: Settings = {
|
||||||
|
port: '23119',
|
||||||
|
style: 'apa',
|
||||||
|
link: true,
|
||||||
|
search: "creators",
|
||||||
|
}
|
||||||
|
|
||||||
+35
-9
@@ -2,7 +2,8 @@ import { renderResults, Notice } from "obsidian";
|
|||||||
|
|
||||||
export function renderZoteroItem(
|
export function renderZoteroItem(
|
||||||
match: FuzzyMatch<ZoteroItem>,
|
match: FuzzyMatch<ZoteroItem>,
|
||||||
el: HTMLElement
|
el: HTMLElement,
|
||||||
|
property: string
|
||||||
) {
|
) {
|
||||||
const { item } = match;
|
const { item } = match;
|
||||||
|
|
||||||
@@ -13,24 +14,49 @@ export function renderZoteroItem(
|
|||||||
const offset = -(item.title.length + 1);
|
const offset = -(item.title.length + 1);
|
||||||
renderResults(
|
renderResults(
|
||||||
subtitleEl,
|
subtitleEl,
|
||||||
`${item.creators}, ${item.year}`,
|
`${item[property]}`,
|
||||||
match.match,
|
match.match,
|
||||||
offset
|
offset
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderZoteroAnnotation(
|
export function renderZoteroAnnotation(
|
||||||
match: FuzzyMatch<ZoteroAnnotation>,
|
match: FuzzyMatch<ZoteroItem>,
|
||||||
el: HTMLElement
|
el: HTMLElement,
|
||||||
|
property: string
|
||||||
) {
|
) {
|
||||||
const { item: annotation } = match;
|
const { item } = match;
|
||||||
|
|
||||||
const titleEl = el.createDiv();
|
const titleEl = el.createDiv();
|
||||||
renderResults(titleEl, annotation.text, match.match);
|
renderResults(titleEl, item.annotationText, match.match);
|
||||||
|
|
||||||
const subtitleEl = el.createEl("small");
|
const subtitleEl = el.createEl("small");
|
||||||
const offset = -(annotation.text.length + 1);
|
const offset = -(item.annotationText.length + 1);
|
||||||
renderResults(subtitleEl, annotation.parentItem.toStringShort(), match.match, offset);
|
|
||||||
|
const annotationProperties = [
|
||||||
|
"attachmentItemKey",
|
||||||
|
"parentItemKey",
|
||||||
|
"parentItem",
|
||||||
|
"annotationText",
|
||||||
|
"annotationComment",
|
||||||
|
"annotationColor",
|
||||||
|
"pageLabel",
|
||||||
|
]
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
|
||||||
|
if (annotationProperties.includes(property)){
|
||||||
|
output = `${item[property]}`;
|
||||||
|
} else {
|
||||||
|
output = `${item.parentItem[property]}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderResults(
|
||||||
|
subtitleEl,
|
||||||
|
output,
|
||||||
|
match.match,
|
||||||
|
offset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadItems(
|
export async function loadItems(
|
||||||
@@ -56,7 +82,7 @@ export async function loadItems(
|
|||||||
|
|
||||||
export async function loadAnnotations(
|
export async function loadAnnotations(
|
||||||
client: ZoteroClient,
|
client: ZoteroClient,
|
||||||
): Promise<ZoteroAnnotation[]> {
|
): Promise<ZoteroItem[]> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const annotations = await client.getAnnotations();
|
const annotations = await client.getAnnotations();
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import type { ZoteroResponse } from "./ZoteroResponse";
|
|
||||||
import { ZoteroItem } from "./ZoteroItem";
|
|
||||||
|
|
||||||
export class ZoteroAnnotation {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public key: string,
|
|
||||||
public attachmentItemKey: string,
|
|
||||||
public parentItemKey: string,
|
|
||||||
public parentItem?: ZoteroItem,
|
|
||||||
public text: string = "",
|
|
||||||
public comment: string = "",
|
|
||||||
public color: string = "",
|
|
||||||
public pageLabel: string = "",
|
|
||||||
){}
|
|
||||||
|
|
||||||
static fromResponse(item: ZoteroResponse): ZoteroAnnotation {
|
|
||||||
return new ZoteroAnnotation(
|
|
||||||
item.key ?? "",
|
|
||||||
item.data?.parentItem ?? "",
|
|
||||||
"",
|
|
||||||
undefined,
|
|
||||||
item.data?.annotationText ?? "",
|
|
||||||
item.data?.annotationComment ?? "",
|
|
||||||
item.data?.annotationColor ?? "",
|
|
||||||
item.data?.pageLabel ?? "",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return [
|
|
||||||
this.key,
|
|
||||||
this.text,
|
|
||||||
this.comment,
|
|
||||||
this.color,
|
|
||||||
this.pageLabel,
|
|
||||||
this.parentItem?.title,
|
|
||||||
this.parentItem?.creators,
|
|
||||||
this.parentItem?.year,
|
|
||||||
this.parentItemKey,
|
|
||||||
this.attachmentItemKey,
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+4
-5
@@ -1,6 +1,5 @@
|
|||||||
import { Notice, requestUrl } from 'obsidian';
|
import { Notice, requestUrl } from 'obsidian';
|
||||||
import { ZoteroItem } from './ZoteroItem';
|
import { ZoteroItem } from './ZoteroItem';
|
||||||
import { ZoteroAnnotation } from './ZoteroAnnotation';
|
|
||||||
import type { ZoteroResponse } from './ZoteroResponse';
|
import type { ZoteroResponse } from './ZoteroResponse';
|
||||||
|
|
||||||
export class ZoteroClient {
|
export class ZoteroClient {
|
||||||
@@ -90,7 +89,7 @@ export class ZoteroClient {
|
|||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async resolveParentItem(annotation: ZoteroAnnotation): Promise<void> {
|
private async resolveParentItem(annotation: ZoteroItem): Promise<void> {
|
||||||
if (!annotation.attachmentItemKey) return;
|
if (!annotation.attachmentItemKey) return;
|
||||||
|
|
||||||
const attachmentOrParent = await this.getItemByKey(annotation.attachmentItemKey, "citation,bib,data");
|
const attachmentOrParent = await this.getItemByKey(annotation.attachmentItemKey, "citation,bib,data");
|
||||||
@@ -109,7 +108,7 @@ export class ZoteroClient {
|
|||||||
annotation.parentItem = ZoteroItem.fromResponse(fullParentItem);
|
annotation.parentItem = ZoteroItem.fromResponse(fullParentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAnnotations(): Promise<ZoteroAnnotation[]> {
|
async getAnnotations(): Promise<ZoteroItem[]> {
|
||||||
this.params.set("include", "data");
|
this.params.set("include", "data");
|
||||||
this.params.set("itemType", "annotation");
|
this.params.set("itemType", "annotation");
|
||||||
|
|
||||||
@@ -119,8 +118,8 @@ export class ZoteroClient {
|
|||||||
this.params.delete("itemType");
|
this.params.delete("itemType");
|
||||||
|
|
||||||
const annotations = responses
|
const annotations = responses
|
||||||
.map(annotation => ZoteroAnnotation.fromResponse(annotation))
|
.map(annotation => ZoteroItem.fromResponse(annotation))
|
||||||
.filter(a => a.text && a.text.trim() !== "");
|
.filter(a => a.annotationText && a.annotationText.trim() !== "");
|
||||||
|
|
||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
export const ZoteroFields =
|
||||||
|
[
|
||||||
|
"key",
|
||||||
|
"citation",
|
||||||
|
"bibliography",
|
||||||
|
"itemType",
|
||||||
|
"title",
|
||||||
|
"abstractNote",
|
||||||
|
"date",
|
||||||
|
"shortTitle",
|
||||||
|
"language",
|
||||||
|
"libraryCatalog",
|
||||||
|
"publisher",
|
||||||
|
"place",
|
||||||
|
"ISBN",
|
||||||
|
"numPages",
|
||||||
|
"creators",
|
||||||
|
"tags",
|
||||||
|
"collections",
|
||||||
|
"relations",
|
||||||
|
"dateAdded",
|
||||||
|
"dateModified",
|
||||||
|
"attachmentItemKey",
|
||||||
|
"parentItemKey",
|
||||||
|
"parentItem",
|
||||||
|
"annotationText",
|
||||||
|
"annotationComment",
|
||||||
|
"annotationColor",
|
||||||
|
"pageLabel",
|
||||||
|
]
|
||||||
+83
-32
@@ -2,24 +2,83 @@ import type { ZoteroResponse } from "./ZoteroResponse";
|
|||||||
|
|
||||||
export class ZoteroItem {
|
export class ZoteroItem {
|
||||||
constructor(
|
constructor(
|
||||||
public title: string,
|
|
||||||
public year: string,
|
|
||||||
public creators: string,
|
|
||||||
public key: string,
|
public key: string,
|
||||||
public citation: string,
|
public citation: string,
|
||||||
public bibliography: string,
|
public bibliography: string,
|
||||||
|
public itemType: string,
|
||||||
|
public title: string,
|
||||||
|
public abstractNote: string,
|
||||||
|
public date: string,
|
||||||
|
public shortTitle: string,
|
||||||
|
public language: string,
|
||||||
|
public libraryCatalog: string,
|
||||||
|
public publisher: string,
|
||||||
|
public place: string,
|
||||||
|
public ISBN: string,
|
||||||
|
public numPages: string,
|
||||||
|
public creators: string,
|
||||||
|
public tags: string,
|
||||||
|
public collections: string,
|
||||||
|
public relations: string,
|
||||||
|
public dateAdded: string,
|
||||||
|
public dateModified: string,
|
||||||
|
public attachmentItemKey: string,
|
||||||
|
public parentItemKey: string,
|
||||||
|
public parentItem?: ZoteroItem,
|
||||||
|
public annotationText: string,
|
||||||
|
public annotationComment: string,
|
||||||
|
public annotationColor: string,
|
||||||
|
public pageLabel: string,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
static fromResponse(item: ZoteroResponse): ZoteroItem {
|
static fromResponse(item: ZoteroResponse): ZoteroItem {
|
||||||
const title = item.data?.title ?? "Untitled";
|
const data = item.data;
|
||||||
const date = item.data?.date;
|
|
||||||
const yearMatch = date?.match(/\b\d{4}\b/);
|
return new ZoteroItem(
|
||||||
const year = yearMatch ? yearMatch[0] : "n.d.";
|
item.key ?? "",
|
||||||
const creators = this.formatCreators(item.data?.creators);
|
this.html2text(item.citation ?? ""),
|
||||||
const key = item.key ?? "No Key";
|
this.html2text(item.bib ?? ""),
|
||||||
const citation = this.htmlToPlainText(item.citation ?? "");
|
data?.itemType ?? "",
|
||||||
const bibliography = this.htmlToPlainText(item.bib ?? "");
|
data?.title ?? "",
|
||||||
return new ZoteroItem(title, year, creators, key, citation, bibliography);
|
data?.abstractNote ?? "",
|
||||||
|
data?.date ?? "",
|
||||||
|
data?.shortTitle ?? "",
|
||||||
|
data?.language ?? "",
|
||||||
|
data?.libraryCatalog ?? "",
|
||||||
|
data?.publisher ?? "",
|
||||||
|
data?.place ?? "",
|
||||||
|
data?.ISBN ?? "",
|
||||||
|
data?.numPages ?? "",
|
||||||
|
this.formatCreators(data?.creators),
|
||||||
|
this.formatTags(data?.tags),
|
||||||
|
this.array2text(data?.collections),
|
||||||
|
this.object2text(data?.relations),
|
||||||
|
data?.dateAdded ?? "",
|
||||||
|
data?.dateModified ?? "",
|
||||||
|
data?.parentItem ?? "",
|
||||||
|
"",
|
||||||
|
undefined,
|
||||||
|
data?.annotationText ?? "",
|
||||||
|
data?.annotationComment ?? "",
|
||||||
|
this.hex2color(data?.annotationColor),
|
||||||
|
data?.pageLabel ?? "",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static array2text(values?: unknown[]): string {
|
||||||
|
return values?.map(String).join(", ") ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object2text(value?: Record<string, unknown>): string {
|
||||||
|
if (!value) return "";
|
||||||
|
return Object.values(value).flat().map(String).join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static formatTags(tags?: Array<{ tag?: string }>): string {
|
||||||
|
return tags
|
||||||
|
?.map(t => t.tag ?? "")
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(", ") ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static formatCreators(
|
private static formatCreators(
|
||||||
@@ -29,35 +88,27 @@ export class ZoteroItem {
|
|||||||
name?: string;
|
name?: string;
|
||||||
}>
|
}>
|
||||||
): string {
|
): string {
|
||||||
if (!creators || creators.length === 0) return "Unknown author";
|
return creators
|
||||||
|
?.map(c => c.name ?? [c.firstName, c.lastName].filter(Boolean).join(" "))
|
||||||
const names = creators.map(c => {
|
.filter(Boolean)
|
||||||
if (c.name) return c.name;
|
.join(", ") ?? "";
|
||||||
if (c.firstName && c.lastName) return `${c.firstName} ${c.lastName}`;
|
|
||||||
if (c.lastName) return c.lastName;
|
|
||||||
return "Unknown";
|
|
||||||
});
|
|
||||||
|
|
||||||
return names.join(" & ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static htmlToPlainText(html: string): string {
|
private static html2text(html: string): string {
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
div.innerHTML = html;
|
div.innerHTML = html;
|
||||||
|
|
||||||
return div.textContent?.trim() ?? "";
|
return div.textContent?.trim() ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
private static hex2color(hex?: string): string {
|
||||||
return [this.title, this.year, this.creators, this.key, this.citation, this.bibliography]
|
switch (hex?.toLowerCase()) {
|
||||||
.filter(Boolean)
|
case "#a28ae5": return "Purple";
|
||||||
.join(" ");
|
case "#ff6666": return "Red";
|
||||||
|
case "#009980": return "Teal";
|
||||||
|
case "#ffd400": return "Yellow";
|
||||||
|
default: return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
toStringShort(): string {
|
|
||||||
return [this.creators, this.year]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(", ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-7
@@ -6,18 +6,33 @@ export type ZoteroResponse = {
|
|||||||
citation?: string;
|
citation?: string;
|
||||||
bib?: string;
|
bib?: string;
|
||||||
data?: {
|
data?: {
|
||||||
title?: string;
|
|
||||||
date?: string;
|
|
||||||
itemType?: string;
|
itemType?: string;
|
||||||
parentItem?: string;
|
title?: string;
|
||||||
annotationText?: string;
|
abstractNote?: string;
|
||||||
annotationComment?: string;
|
date?: string;
|
||||||
annotationColor?: string;
|
shortTitle?: string;
|
||||||
pageLabel?: string;
|
language?: string;
|
||||||
|
libraryCatalog?: string;
|
||||||
|
publisher?: string;
|
||||||
|
place?: string;
|
||||||
|
ISBN?: string;
|
||||||
|
numPages?: string;
|
||||||
creators?: Array<{
|
creators?: Array<{
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
}>;
|
}>;
|
||||||
|
tags?: Array<{
|
||||||
|
tag?: string;
|
||||||
|
}>;
|
||||||
|
collections?: Array<string>;
|
||||||
|
relations?: Array<any>;
|
||||||
|
dateAdded?: string;
|
||||||
|
dateModified?: string;
|
||||||
|
parentItem?: string;
|
||||||
|
annotationText?: string;
|
||||||
|
annotationComment?: string;
|
||||||
|
annotationColor?: string;
|
||||||
|
pageLabel?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
+7
-6
@@ -1,5 +1,6 @@
|
|||||||
import { App, Editor, MarkdownView, Modal, Plugin, Notice } from 'obsidian';
|
import { App, Editor, MarkdownView, Modal, Plugin } from 'obsidian';
|
||||||
import { DEFAULT_SETTINGS, Settings, SettingTab } from "./settings";
|
import { DEFAULT_SETTINGS, Settings } from "./Settings";
|
||||||
|
import { SettingTab } from "./SettingTab";
|
||||||
import { CiteModal } from "./CiteModal";
|
import { CiteModal } from "./CiteModal";
|
||||||
import { OpenModal } from "./OpenModal";
|
import { OpenModal } from "./OpenModal";
|
||||||
import { AnnotationModal } from "./AnnotationModal";
|
import { AnnotationModal } from "./AnnotationModal";
|
||||||
@@ -17,7 +18,7 @@ export default class Cite extends Plugin {
|
|||||||
id: 'open-command',
|
id: 'open-command',
|
||||||
name: 'open',
|
name: 'open',
|
||||||
callback: () => {
|
callback: () => {
|
||||||
new OpenModal(this.app, this.settings.portSetting).open();
|
new OpenModal(this.app, this.settings).open();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ export default class Cite extends Plugin {
|
|||||||
name: 'insert citation',
|
name: 'insert citation',
|
||||||
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, "citation",(citation: string) => {
|
new CiteModal(this.app, this.settings, "citation",(citation: string) => {
|
||||||
editor.replaceSelection(citation);
|
editor.replaceSelection(citation);
|
||||||
}).open();
|
}).open();
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,7 @@ 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, "bibliography", (bibliography: string) => {
|
||||||
editor.replaceSelection(bibliography);
|
editor.replaceSelection(bibliography);
|
||||||
}).open();
|
}).open();
|
||||||
}
|
}
|
||||||
@@ -48,7 +49,7 @@ export default class Cite extends Plugin {
|
|||||||
name: 'insert annotations',
|
name: 'insert annotations',
|
||||||
editorCallback: (editor: Editor, view: MarkdownView) => {
|
editorCallback: (editor: Editor, view: MarkdownView) => {
|
||||||
const selection = editor.getSelection();
|
const selection = editor.getSelection();
|
||||||
new AnnotationModal(this.app, this.settings.portSetting, this.settings.linkSetting, this.settings.styleSetting, (annotations: string) => {
|
new AnnotationModal(this.app, this.settings, (annotations: string) => {
|
||||||
editor.replaceSelection(annotations);
|
editor.replaceSelection(annotations);
|
||||||
}).open();
|
}).open();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user