Skip to content

Commit de4f72b

Browse files
committed
refactor: 🚨 fix biomejs warnings & errors
fix warnings and errors raised by `biomejs`, makign the code potentially more robust, cleaner, and better understandable
1 parent 28b4488 commit de4f72b

File tree

5 files changed

+92
-101
lines changed

5 files changed

+92
-101
lines changed

‎deploy-local.mjs

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
import dotenv from 'dotenv';
2929
dotenv.config();
30-
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'fs';
31-
import { join } from 'path';
30+
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs';
31+
import { join } from 'node:path';
3232

3333
// Validate environment
3434
if (!process.env.OBSIDIAN_PLUGIN_ROOT || !process.env.PACKAGE_NAME) {
@@ -65,7 +65,7 @@ try {
6565
const manifestContent = readFileSync(src, 'utf8');
6666
const json = JSON.parse(manifestContent);
6767
json.version = `${json.version}-${new Date().toISOString().replace(/[-:.TZ]/g, '')}`;
68-
writeFileSync(destPath, JSON.stringify(json, null, 4) + '\n');
68+
writeFileSync(destPath, `${JSON.stringify(json, null, 4)}\n`);
6969
console.log(`Written ${src} to ${destPath} with updated version ${json.version}`);
7070
} catch (err) {
7171
throw new Error(`Failed to process manifest.json: ${err.message}`);

‎src/constants/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { PluginSettings } from 'models/settings';
2-
import { ToStringOptions } from 'yaml';
1+
import type { ToStringOptions } from 'yaml';
2+
import type { PluginSettings } from 'models/settings';
33

44
export const DEFAULT_SETTINGS: PluginSettings = {
55
baseFolderName: 'Readwise',

‎src/main.ts

+55-63
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import slugify from '@sindresorhus/slugify';
22
import filenamify from 'filenamify';
3-
import { ConfigureOptions, Environment, Template } from 'nunjucks';
4-
import { CachedMetadata, normalizePath, Plugin, TFile } from 'obsidian';
53
import spacetime from 'spacetime';
4+
import { type CachedMetadata, Plugin, normalizePath, TFile } from 'obsidian';
5+
import { type ConfigureOptions, Template, Environment } from 'nunjucks';
66
import * as YAML from 'yaml';
77

8-
import { DEFAULT_SETTINGS, FRONTMATTER_TO_ESCAPE, YAML_TOSTRING_OPTIONS } from 'constants/index';
9-
import { Export, Highlight, Library, Tag, ReadwiseMetadata } from 'models/readwise';
10-
import { PluginSettings } from 'models/settings';
11-
import { YamlStringState } from 'models/yaml';
8+
// Plugin classes
129
import ReadwiseApi from 'services/readwise-api';
1310
import ReadwiseMirrorSettingTab from 'ui/settings-tab';
1411
import Notify from 'ui/notify';
12+
13+
// Types
14+
import { DEFAULT_SETTINGS, FRONTMATTER_TO_ESCAPE, YAML_TOSTRING_OPTIONS } from 'constants/index';
15+
import type { Export, Highlight, Library, Tag, ReadwiseMetadata } from 'models/readwise';
16+
import type { PluginSettings } from 'models/settings';
17+
import type { YamlStringState } from 'models/yaml';
18+
1519
export default class ReadwiseMirror extends Plugin {
1620
settings: PluginSettings;
1721
readwiseApi: ReadwiseApi;
@@ -20,7 +24,7 @@ export default class ReadwiseMirror extends Plugin {
2024
frontMatterTemplate: Template;
2125
headerTemplate: Template;
2226
highlightTemplate: Template;
23-
isSyncing: boolean = false;
27+
isSyncing = false;
2428

2529
private analyzeStringForFrontmatter(value: string): YamlStringState {
2630
return {
@@ -36,7 +40,7 @@ export default class ReadwiseMirror extends Plugin {
3640
public escapeFrontmatter(metadata: ReadwiseMetadata, fieldsToProcess: Array<string>): ReadwiseMetadata {
3741
// Copy the metadata object to avoid modifying the original
3842
const processedMetadata = { ...metadata } as ReadwiseMetadata;
39-
fieldsToProcess.forEach((field) => {
43+
for (const field of fieldsToProcess) {
4044
if (
4145
field in processedMetadata &&
4246
processedMetadata[field as keyof ReadwiseMetadata] &&
@@ -47,12 +51,11 @@ export default class ReadwiseMirror extends Plugin {
4751
(processedMetadata[key] as unknown) = this.escapeYamlValue(processedMetadata[key] as string);
4852
}
4953
}
50-
});
51-
54+
}
5255
return processedMetadata;
5356
}
5457

55-
private escapeYamlValue(value: string, multiline: boolean = false): string {
58+
private escapeYamlValue(value: string, multiline = false): string {
5659
if (!value) return '""';
5760

5861
const state = this.analyzeStringForFrontmatter(value);
@@ -62,48 +65,46 @@ export default class ReadwiseMirror extends Plugin {
6265

6366
// Handle multi-line strings
6467
if (value.includes('\n') && multiline) {
65-
// Use folded block style (>) for titles, preserve single line ending
6668
const indent = ' ';
6769
return `>-\n${indent}${value.replace(/\n/g, `\n${indent}`)}`;
6870
}
6971

70-
value = value.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
72+
const cleanValue = value.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim();
7173

72-
// No quotes in string - use simple double quotes to catch other special characters
74+
// No quotes in string - use simple double quotes
7375
if (!state.hasSingleQuotes && !state.hasDoubleQuotes) {
74-
return `"${value}"`;
76+
return `"${cleanValue}"`;
7577
}
7678

7779
// Has double quotes but no single quotes - use single quotes
7880
if (state.hasDoubleQuotes && !state.hasSingleQuotes) {
79-
return `'${value}'`;
81+
return `'${cleanValue}'`;
8082
}
8183

8284
// Has single quotes but no double quotes - use double quotes
8385
if (state.hasSingleQuotes && !state.hasDoubleQuotes) {
84-
return `"${value}"`;
86+
return `"${cleanValue}"`;
8587
}
8688

8789
// Has both types of quotes - escape double quotes and use double quotes
88-
return `"${value.replace(/"/g, '\\"')}"`;
90+
return `"${cleanValue.replace(/"/g, '\\"')}"`;
8991
}
9092

91-
private formatTags(tags: Tag[], nohash: boolean = false, q: string = '') {
93+
private formatTags(tags: Tag[], nohash = false, q = '') {
9294
// use unique list of tags
9395
const uniqueTags = [...new Set(tags.map((tag) => tag.name.replace(/\s/, '-')))];
9496

95-
if (nohash) {
97+
if (nohash === true) {
9698
// don't return a hash in the tag name
9799
return uniqueTags.map((tag) => `${q}${tag}${q}`).join(', ');
98-
} else {
99-
return uniqueTags.map((tag) => `${q}#${tag}${q}`).join(', ');
100100
}
101+
return uniqueTags.map((tag) => `${q}#${tag}${q}`).join(', ');
101102
}
102103

103104
private formatHighlight(highlight: Highlight, book: Export) {
104105
const { id, text, note, location, color, url, tags, highlighted_at, created_at, updated_at } = highlight;
105106

106-
const locationUrl = `https://readwise.io/to_kindle?action=open&asin=${book['asin']}&location=${location}`;
107+
const locationUrl = `https://readwise.io/to_kindle?action=open&asin=${book.asin}&location=${location}`;
107108

108109
const formattedTags = tags.filter((tag) => tag.name !== color);
109110
const formattedTagStr = this.formatTags(formattedTags);
@@ -158,7 +159,7 @@ export default class ReadwiseMirror extends Plugin {
158159
if (this.settings.highlightSortByLocation) {
159160
sortedHighlights = sortedHighlights.sort((highlightA: Highlight, highlightB: Highlight) => {
160161
if (highlightA.location < highlightB.location) return -1;
161-
else if (highlightA.location > highlightB.location) return 1;
162+
if (highlightA.location > highlightB.location) return 1;
162163
return 0;
163164
});
164165

@@ -175,10 +176,11 @@ export default class ReadwiseMirror extends Plugin {
175176
// construct an array with unique values
176177

177178
let tags: Tag[] = [];
178-
this.sortHighlights(highlights).forEach((highlight: Highlight) =>
179-
highlight.tags ? (tags = [...tags, ...highlight.tags]) : tags
180-
);
179+
for (const highlight of this.sortHighlights(highlights)) {
180+
if (highlight.tags) tags = [...tags, ...highlight.tags];
181+
}
181182
return tags;
183+
182184
}
183185

184186
async writeLogToMarkdown(library: Library) {
@@ -190,8 +192,8 @@ export default class ReadwiseMirror extends Plugin {
190192
const now = spacetime.now();
191193
let logString = `# [[${now.format('iso-short')}]] *(${now.time()})*`;
192194

193-
for (const bookId in library['books']) {
194-
const book = library['books'][bookId];
195+
for (const bookId in library.books) {
196+
const book = library.books[bookId];
195197

196198
const { title, highlights } = book;
197199
const num_highlights = highlights.length;
@@ -208,12 +210,12 @@ export default class ReadwiseMirror extends Plugin {
208210
console.log('logFile:', logFile);
209211

210212
const logFileContents = await vault.read(logFile);
211-
vault.modify(logFile, logFileContents + '\n\n' + logString);
213+
vault.modify(logFile, `${logFileContents}\n\n${logString}`);
212214
} else {
213215
vault.create(path, logString);
214216
}
215217
} catch (err) {
216-
console.error(`Readwise: Error writing to sync log file`, err);
218+
console.error("Readwise: Error writing to sync log file", err);
217219
}
218220
}
219221

@@ -323,7 +325,7 @@ export default class ReadwiseMirror extends Plugin {
323325

324326
// Create parent directories for all categories synchronously
325327
try {
326-
for (const category of library['categories']) {
328+
for (const category of library.categories) {
327329
const titleCaseCategory = category.charAt(0).toUpperCase() + category.slice(1); // Title Case the directory name
328330
const path = `${this.settings.baseFolderName}/${titleCaseCategory}`;
329331
const abstractFolder = vault.getAbstractFileByPath(path);
@@ -342,14 +344,14 @@ export default class ReadwiseMirror extends Plugin {
342344
// Get total number of records
343345
const booksTotal = Object.keys(library.books).length;
344346
let bookCurrent = 1;
345-
for (const bookId in library['books']) {
347+
for (const bookId in library.books) {
346348
this.notify.setStatusBarText(
347349
`Readwise: Processing - ${Math.floor(
348350
(bookCurrent / booksTotal) * 100
349351
)}% finished (${bookCurrent}/${booksTotal})`
350352
);
351353
bookCurrent += 1;
352-
const book: Export = library['books'][bookId];
354+
const book: Export = library.books[bookId];
353355

354356
const {
355357
user_book_id,
@@ -369,23 +371,19 @@ export default class ReadwiseMirror extends Plugin {
369371
// Get highlight count
370372
const num_highlights = highlights.length;
371373
const created = highlights
372-
.map(function (highlight) {
373-
return highlight.created_at;
374-
})
374+
.map((highlight) => highlight.created_at)
375375
.sort()[0]; // No reverse sort: we want the oldest entry
376376
const updated = highlights
377-
.map(function (highlight) {
378-
return highlight.updated_at;
379-
})
377+
.map((highlight) => highlight.updated_at)
380378
.sort()
381379
.reverse()[0];
380+
382381
const last_highlight_at = highlights
383-
.map(function (highlight) {
384-
return highlight.highlighted_at;
385-
})
382+
.map((highlight) => highlight.highlighted_at)
386383
.sort()
387384
.reverse()[0];
388385

386+
389387
// Sanitize title, replace colon with substitute from settings
390388
const sanitizedTitle = this.settings.useSlugify
391389
? slugify(title.replace(/:/g, this.settings.colonSubstitute ?? '-'), {
@@ -418,12 +416,12 @@ export default class ReadwiseMirror extends Plugin {
418416
const authorStr =
419417
authors[0] && authors?.length > 1
420418
? authors
421-
.filter((authorName: string) => authorName.trim() != '')
419+
.filter((authorName: string) => authorName.trim() !== '')
422420
.map((authorName: string) => `[[${authorName.trim()}]]`)
423421
.join(', ')
424422
: author
425423
? `[[${author}]]`
426-
: ``;
424+
: "";
427425

428426
const metadata: ReadwiseMetadata = {
429427
id: user_book_id,
@@ -451,7 +449,7 @@ export default class ReadwiseMirror extends Plugin {
451449

452450
// Escape specific fields used in frontmatter
453451
// TODO: Tidy up code. It doesn't make sense to remove the frontmatter markers and then add them back
454-
let frontmatterYaml;
452+
let frontmatterYaml: Record<string, unknown>;
455453
try {
456454
const renderedTemplate = this.frontMatterTemplate.render(
457455
this.escapeFrontmatter(metadata, FRONTMATTER_TO_ESCAPE)
@@ -464,13 +462,13 @@ export default class ReadwiseMirror extends Plugin {
464462
if (error instanceof YAML.YAMLParseError) {
465463
console.error('Failed to parse YAML frontmatter:', error.message);
466464
throw new Error(`Invalid YAML frontmatter: ${error.message}`);
467-
} else if (error instanceof Error) {
465+
}
466+
if (error instanceof Error) {
468467
console.error('Error processing frontmatter template:', error.message);
469468
throw new Error(`Failed to process frontmatter: ${error.message}`);
470-
} else {
471-
console.error('Unknown error processing frontmatter:', error);
472-
throw new Error('Failed to process frontmatter due to unknown error');
473469
}
470+
console.error('Unknown error processing frontmatter:', error);
471+
throw new Error('Failed to process frontmatter due to unknown error');
474472
}
475473
const frontMatterContents = this.settings.frontMatter
476474
? ['---', YAML.stringify(frontmatterYaml, YAML_TOSTRING_OPTIONS), '---'].join('\n')
@@ -680,7 +678,7 @@ export default class ReadwiseMirror extends Plugin {
680678
`Readwise: Downloaded ${library.highlightCount} Highlights from ${Object.keys(library.books).length} Sources`
681679
);
682680
} else {
683-
this.notify.notice(`Readwise: No new content available`);
681+
this.notify.notice("Readwise: No new content available");
684682
}
685683

686684
this.settings.lastUpdated = new Date().toISOString();
@@ -723,7 +721,7 @@ export default class ReadwiseMirror extends Plugin {
723721

724722
// Reload settings after external change (e.g. after sync)
725723
async onExternalSettingsChange() {
726-
console.info(`Reloading settings due to external change`);
724+
console.info("Reloading settings due to external change");
727725
await this.loadSettings();
728726
if (this.settings.lastUpdated)
729727
this.notify.setStatusBarText(`Readwise: Updated ${this.lastUpdatedHumanReadableFormat()} elsewhere`);
@@ -792,19 +790,13 @@ export default class ReadwiseMirror extends Plugin {
792790
this.env = new Environment(null, { autoescape: false } as ConfigureOptions);
793791

794792
// Add a nunjucks filter to convert newlines to "newlines + >" for quotes
795-
this.env.addFilter('bq', function (str) {
796-
return str.replace(/\r|\n|\r\n/g, '\r\n> ');
797-
});
793+
this.env.addFilter('bq', (str) => str.replace(/\r|\n|\r\n/g, '\r\n> '));
798794

799795
// Add a nunjukcs filter to test whether we are a ".qa" note
800-
this.env.addFilter('is_qa', function (str) {
801-
return str.includes('.qa');
802-
});
796+
this.env.addFilter('is_qa', (str) => str.includes('.qa'));
803797

804798
// Add a nunjucks filter to convert ".qa" notes to Q& A
805-
this.env.addFilter('qa', function (str) {
806-
return str.replace(/\.qa(.*)\?(.*)/g, '**Q:**$1?\r\n\r\n**A:**$2');
807-
});
799+
this.env.addFilter('qa', (str) => str.replace(/\.qa(.*)\?(.*)/g, '**Q:**$1?\r\n\r\n**A:**$2'));
808800

809801
this.updateFrontmatteTemplate();
810802

@@ -820,7 +812,7 @@ export default class ReadwiseMirror extends Plugin {
820812
this.readwiseApi = new ReadwiseApi(this.settings.apiToken, this.notify);
821813
if (this.settings.lastUpdated)
822814
this.notify.setStatusBarText(`Readwise: Updated ${this.lastUpdatedHumanReadableFormat()}`);
823-
else this.notify.setStatusBarText(`Readwise: Click to Sync`);
815+
else this.notify.setStatusBarText("Readwise: Click to Sync");
824816
}
825817

826818
this.registerDomEvent(statusBarItem, 'click', this.sync.bind(this));
@@ -836,7 +828,7 @@ export default class ReadwiseMirror extends Plugin {
836828
name: 'Test Readwise API key',
837829
callback: async () => {
838830
const isTokenValid = await this.readwiseApi.hasValidToken();
839-
this.notify.notice('Readwise: ' + (isTokenValid ? 'Token is valid' : 'INVALID TOKEN'));
831+
this.notify.notice(`Readwise: ${isTokenValid ? 'Token is valid' : 'INVALID TOKEN'}`);
840832
},
841833
});
842834

0 commit comments

Comments
 (0)