Skip to content

Commit 3cd4ae3

Browse files
committed
Sort Highlights By Location and Filter Discarded Highlights
1 parent 0f7d3eb commit 3cd4ae3

File tree

3 files changed

+88
-19
lines changed

3 files changed

+88
-19
lines changed

CHANGELOG.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Changelog
22

3+
## 1.3.0 (2022-12-10)
4+
### Added
5+
- Sort Highlights by Location (instead of date highlighted).
6+
- This will display highlights in order of page location, from least to greatest.
7+
- Combine with Sort Highlights from Oldest to Newest to reverse the sort order.
8+
- Filter Discarded Highlights.
9+
- With this option enabled, highlights that have been discarded in Readwise will not be displayed in the Obsidian library.
10+
311
## 1.1.1 (2021-08-01)
412
### Added
513
- Added Sync Log functionality. Creates a file (configurable, with a default filename of `Sync.md`) in the Readwise library root folder, which stores a time-based log listing when Readwise sources have synced new highlights
@@ -22,4 +30,4 @@
2230
- Fixes plugin breaking when there is no author (thanks @shabegom!)
2331

2432
### Development
25-
- Added Prettier configuration for project style consistency
33+
- Added Prettier configuration for project style consistency

main.ts

+78-17
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ interface PluginSettings {
1111
lastUpdated: string | null;
1212
autoSync: boolean;
1313
highlightSortOldestToNewest: boolean;
14+
highlightSortByLocation: boolean;
15+
highlightDiscard: boolean;
1416
syncNotesOnly: boolean;
1517
logFile: boolean;
1618
logFileName: string;
@@ -26,6 +28,8 @@ const DEFAULT_SETTINGS: PluginSettings = {
2628
lastUpdated: null,
2729
autoSync: true,
2830
highlightSortOldestToNewest: true,
31+
highlightSortByLocation: true,
32+
highlightDiscard: false,
2933
syncNotesOnly: false,
3034
logFile: true,
3135
logFileName: 'Sync.md',
@@ -110,15 +114,51 @@ export default class ReadwiseMirror extends Plugin {
110114
});
111115
}
112116

113-
private filterHighlight(highlight: Highlight) {
114-
if (this.settings.syncNotesOnly && !highlight.note) return false;
115-
else return true;
117+
private highlightIsDiscarded = (highlight: Highlight) => {
118+
// is_discard is not a field in the API response for (https://readwise.io/api/v2/highlights/), so we need to check if the highlight has the discard tag
119+
// is_discard field only showing under the /export API endpoint in the API docs: https://readwise.io/api_deets
120+
121+
return highlight.tags.some(tag => tag.name === 'discard')
122+
}
123+
124+
125+
126+
private filterHighlights(highlights: Highlight[]) {
127+
return highlights.filter((highlight: Highlight) => {
128+
if (this.settings.syncNotesOnly && !highlight.note) return false;
129+
130+
// Check if is discarded
131+
if (this.settings.highlightDiscard && this.highlightIsDiscarded(highlight)) {
132+
console.log("Readwise: Found discarded highlight, removing", highlight)
133+
return false;
134+
}
135+
136+
return true;
137+
});
116138
}
117139

118140
private formatDate(dateStr: string) {
119141
return dateStr.split('T')[0];
120142
}
121143

144+
private sortHighlights = (highlights: Highlight[]) => {
145+
let sortedHighlights = highlights.slice();
146+
147+
if (this.settings.highlightSortByLocation) {
148+
sortedHighlights = sortedHighlights.sort((highlightA: Highlight, highlightB: Highlight) => {
149+
if (highlightA.location < highlightB.location) return -1;
150+
else if (highlightA.location > highlightB.location) return 1;
151+
return 0;
152+
})
153+
154+
if (!this.settings.highlightSortOldestToNewest) sortedHighlights = sortedHighlights.reverse()
155+
} else {
156+
sortedHighlights = this.settings.highlightSortOldestToNewest ? sortedHighlights.reverse() : sortedHighlights
157+
}
158+
159+
return sortedHighlights
160+
}
161+
122162
async writeLogToMarkdown(library: Library) {
123163
const vault = this.app.vault;
124164

@@ -188,28 +228,26 @@ export default class ReadwiseMirror extends Plugin {
188228
} = book;
189229
const sanitizedTitle = `${title.replace(':', '-').replace(/[<>"'\/\\|?*]+/g, '')}`;
190230

191-
const filteredHighlights = highlights.filter((highlight: Highlight) => this.filterHighlight(highlight));
231+
// Filter highlights
232+
const filteredHighlights = this.filterHighlights(highlights);
192233

193-
if (filteredHighlights.length == 0) {
234+
if (filteredHighlights.length === 0) {
194235
console.log(`Readwise: No highlights found for '${sanitizedTitle}'`);
195236
} else {
196-
const formattedHighlights = (
197-
this.settings.highlightSortOldestToNewest ? filteredHighlights.reverse() : filteredHighlights
198-
)
199-
.map((highlight: Highlight) => this.formatHighlight(highlight, book))
237+
const formattedHighlights = this.sortHighlights(filteredHighlights).map((highlight: Highlight) => this.formatHighlight(highlight, book))
200238
.join('\n');
201239

202240
const authors = author ? author.split(/and |,/) : [];
203241

204242
let authorStr =
205243
authors[0] && authors?.length > 1
206244
? authors
207-
.filter((authorName: string) => authorName.trim() != '')
208-
.map((authorName: string) => `[[${authorName.trim()}]]`)
209-
.join(', ')
245+
.filter((authorName: string) => authorName.trim() != '')
246+
.map((authorName: string) => `[[${authorName.trim()}]]`)
247+
.join(', ')
210248
: author
211-
? `[[${author}]]`
212-
: ``;
249+
? `[[${author}]]`
250+
: ``;
213251

214252
const metadata = {
215253
id: id,
@@ -231,9 +269,8 @@ export default class ReadwiseMirror extends Plugin {
231269
const headerContents = this.headerTemplate.render(metadata);
232270
const contents = `${frontMatterContents}${headerContents}${formattedHighlights}`;
233271

234-
let path = `${this.settings.baseFolderName}/${
235-
category.charAt(0).toUpperCase() + category.slice(1)
236-
}/${sanitizedTitle}.md`;
272+
let path = `${this.settings.baseFolderName}/${category.charAt(0).toUpperCase() + category.slice(1)
273+
}/${sanitizedTitle}.md`;
237274

238275
const abstractFile = vault.getAbstractFileByPath(path);
239276

@@ -475,6 +512,30 @@ class ReadwiseMirrorSettingTab extends PluginSettingTab {
475512
})
476513
);
477514

515+
new Setting(containerEl)
516+
.setName('Sort Highlights by Location')
517+
.setDesc(
518+
'If checked, highlights will be listed in order of Location. Combine with above Sort Highlights from Oldest to Newest option to reverse order.'
519+
)
520+
.addToggle((toggle) =>
521+
toggle.setValue(this.plugin.settings.highlightSortByLocation).onChange(async (value) => {
522+
this.plugin.settings.highlightSortByLocation = value;
523+
await this.plugin.saveSettings();
524+
})
525+
);
526+
527+
new Setting(containerEl)
528+
.setName('Filter Discarded Highlights')
529+
.setDesc(
530+
'If enabled, do not display discarded highlights in the Readwise library.'
531+
)
532+
.addToggle((toggle) =>
533+
toggle.setValue(this.plugin.settings.highlightDiscard).onChange(async (value) => {
534+
this.plugin.settings.highlightDiscard = value;
535+
await this.plugin.saveSettings();
536+
})
537+
);
538+
478539
new Setting(containerEl)
479540
.setName('Only sync highlights with notes')
480541
.setDesc(

manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "readwise-mirror",
33
"name": "Readwise Mirror",
4-
"version": "1.2.0",
4+
"version": "1.3.0",
55
"minAppVersion": "0.11.0",
66
"description": "Mirror your Readwise library directly to an Obsidian vault",
77
"author": "jsonmartin",

0 commit comments

Comments
 (0)