Skip to content

Commit

Permalink
fix: Convert item URLs to format that opens web library
Browse files Browse the repository at this point in the history
Fixes #172
  • Loading branch information
dvanoni committed Dec 27, 2023
1 parent baf6882 commit c73cd89
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 5 deletions.
8 changes: 5 additions & 3 deletions src/content/sync/__tests__/property-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import {
zoteroMock,
} from '../../../../test/utils/zotero-mock';
import { PageTitleFormat } from '../../prefs/notero-pref';
import { keyValue } from '../../utils';
import { getItemURL, keyValue } from '../../utils';
import type {
DatabasePageProperties,
DatabaseProperties,
DatabasePropertyConfig,
} from '../notion-types';
import { buildProperties } from '../property-builder';

jest.mock('../../utils/get-item-url');

const mockCollection = createZoteroCollectionMock({ name: 'Fake Collection' });
const fakeItemType = 'Journal Article';
const fakePrimaryID = 1;
Expand All @@ -27,7 +29,7 @@ const fakeDate = '2023-10-01';
const fakePublication = 'Fake Publication';
const fakeShortTitle = 'Faking It';
const fakeTitle = 'Faking It: How To Write A Fake Paper';
const fakeURI = 'http://zotero.org/users/local/abcdef/items/abcdef';
const fakeURI = 'https://zotero.org/users/local/abcdef/items/abcdef';
const fakeYear = 2023;
const fakeFullCitation = `${fakeLastName1}. (${fakeYear}). ${fakeTitle}. ${fakePublication}.`;
const fakeInTextCitation = `(${fakeLastName1}, ${fakeYear})`;
Expand Down Expand Up @@ -157,7 +159,7 @@ function setup() {
item.getField.calledWith('year').mockReturnValue(String(fakeYear));
item.getTags.mockReturnValue([{ tag: fakeTag, type: 1 }]);

zoteroMock.URI.getItemURI.mockReturnValue(fakeURI);
jest.mocked(getItemURL).mockReturnValue(fakeURI);

return { item };
}
Expand Down
4 changes: 2 additions & 2 deletions src/content/sync/property-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { APA_STYLE, NOTION_TAG_NAME } from '../constants';
import { PageTitleFormat } from '../prefs/notero-pref';
import { buildCollectionFullName, parseItemDate } from '../utils';
import { buildCollectionFullName, getItemURL, parseItemDate } from '../utils';

import type {
DatabasePageProperties,
Expand Down Expand Up @@ -337,7 +337,7 @@ class PropertyBuilder {
{
name: 'Zotero URI',
type: 'url',
buildRequest: () => Zotero.URI.getItemURI(this.item),
buildRequest: () => getItemURL(this.item),
},
];
}
73 changes: 73 additions & 0 deletions src/content/utils/__tests__/get-item-url.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
createZoteroItemMock,
zoteroMock,
} from '../../../../test/utils/zotero-mock';
import { getItemURL } from '../get-item-url';

const itemMock = createZoteroItemMock();

describe('getItemURL', () => {
it('returns url using https', () => {
zoteroMock.URI.getItemURI.mockReturnValueOnce(
'http://zotero.org/users/local/ZswAJ4Qe/items/WGAMSPG3',
);

expect(getItemURL(itemMock)).toMatch(/^https:\/\/zotero.org/);
});

describe('when item is in a user library', () => {
it('returns local url when user is not signed in', () => {
zoteroMock.URI.getItemURI.mockReturnValueOnce(
'http://zotero.org/users/local/ZswAJ4Qe/items/WGAMSPG3',
);
zoteroMock.Users.getCurrentUsername.mockReturnValueOnce(undefined);

expect(getItemURL(itemMock)).toStrictEqual(
'https://zotero.org/users/local/ZswAJ4Qe/items/WGAMSPG3',
);
});

it('returns web url with username when user is signed in', () => {
zoteroMock.URI.getItemURI.mockReturnValueOnce(
'http://zotero.org/users/8509743/items/DE9YUFJ9',
);
zoteroMock.Users.getCurrentUsername.mockReturnValueOnce(
'SOME user-name',
);

expect(getItemURL(itemMock)).toStrictEqual(
'https://zotero.org/some__user-name/items/DE9YUFJ9',
);
});
});

describe('when item is in a group library', () => {
it('returns web url', () => {
zoteroMock.URI.getItemURI.mockReturnValueOnce(
'http://zotero.org/groups/4873137/items/8XLITSYN',
);
zoteroMock.Users.getCurrentUsername.mockReturnValueOnce(
'SOME user-name',
);

expect(getItemURL(itemMock)).toStrictEqual(
'https://zotero.org/groups/4873137/items/8XLITSYN',
);
});
});

describe('when item is in a feed', () => {
it('returns local url', () => {
zoteroMock.URI.getItemURI.mockReturnValueOnce(
'http://zotero.org/users/local/eHZqskJE/feeds/4/items/3R3PSB8X',
);
zoteroMock.Users.getCurrentUsername.mockReturnValueOnce(
'SOME user-name',
);

expect(getItemURL(itemMock)).toStrictEqual(
'https://zotero.org/users/local/eHZqskJE/feeds/4/items/3R3PSB8X',
);
});
});
});
30 changes: 30 additions & 0 deletions src/content/utils/get-item-url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Return URL to item in web library, if user is signed in.
* If user is not signed in, the URLs will lead to a 404.
*
* @param item Zotero item to return URL for
*/
export function getItemURL(item: Zotero.Item): string {
const zoteroURI = Zotero.URI.getItemURI(item).replace(/^http:/, 'https:');
const username = Zotero.Users.getCurrentUsername();

if (!username) return zoteroURI;

return zoteroURI.replace(/users\/(?!local\/)\w+/, slugify(username));
}

/**
* Generate url friendly slug from name
*
* From https://github.com/zotero/dataserver/blob/97267cbee6441350b66baff4c34e1f8f9833118a/model/Utilities.inc.php#L88-L100
* As suggested in https://forums.zotero.org/discussion/comment/422291/#Comment_422291
*
* @param input name to generate slug from
*/
function slugify(input: string) {
return input
.trim()
.toLowerCase()
.replace('/[^a-z0-9 ._-]/g', '')
.replace(/ /g, '_');
}
1 change: 1 addition & 0 deletions src/content/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { createHTMLElement } from './create-html-element';
export { createXULElement } from './create-xul-element';
export { getAllCollectionItems } from './get-all-collection-items';
export { getDOMParser } from './get-dom-parser';
export { getItemURL } from './get-item-url';
export { getLocalizedString } from './get-localized-string';
export { getXULElementById } from './get-xul-element-by-id';
export { hasErrorStack } from './has-error-stack';
Expand Down
5 changes: 5 additions & 0 deletions types/zotero.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,10 @@ declare namespace Zotero {
getItemURI(item: Item): string;
}

interface Users {
getCurrentUsername(): string | undefined;
}

interface ZoteroPane {
document: Document;

Expand Down Expand Up @@ -461,6 +465,7 @@ declare interface Zotero {
ProgressWindow: Zotero.ProgressWindow;
QuickCopy: Zotero.QuickCopy;
URI: Zotero.URI;
Users: Zotero.Users;

/** Display an alert in a given window */
alert(window: Window, title: string, msg: string): void;
Expand Down

0 comments on commit c73cd89

Please sign in to comment.