Skip to content

Commit cce86ed

Browse files
authored
Merge pull request #86 from VariableThe/refactor/replace-expr-eval
fix: resolve strict mode build errors across the codebase
2 parents 848285c + 9245146 commit cce86ed

20 files changed

Lines changed: 128 additions & 68 deletions

package-lock.json

Lines changed: 58 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@types/node": "^24.12.3",
6161
"@types/react": "^19.2.14",
6262
"@types/react-dom": "^19.2.3",
63+
"@types/three": "^0.185.0",
6364
"@uiw/react-codemirror": "^4.25.10",
6465
"@vitejs/plugin-react": "^6.0.1",
6566
"@vitest/coverage-v8": "^4.1.9",

src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function App() {
173173
} as React.CSSProperties
174174

175175
if (bgType === 'color') {
176-
containerStyle['--bg-color' as string] = bgColor
176+
;(containerStyle as Record<string, string>)['--bg-color'] = bgColor
177177
containerStyle.backgroundImage = 'none'
178178
} else if (bgType === 'image' && bgImage) {
179179
containerStyle.backgroundImage = `url(${bgImage})`
@@ -211,7 +211,7 @@ function App() {
211211
const currentNotes = useAppStore.getState().notes
212212
const idx = currentNotes.findIndex((n) => n.id === noteId)
213213
if (idx === -1) return
214-
const note = currentNotes[idx]
214+
const note = currentNotes[idx]!
215215
const newContent = note.content.slice(0, from) + insert + note.content.slice(to)
216216

217217
window.electronAPI.saveNote(note.id, newContent)

src/GraphView.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export default function GraphView({
8787
bgColor,
8888
accentColor,
8989
}: GraphViewProps) {
90-
const fgRef = useRef<ForceGraphMethods<GraphNode, GraphLink> | undefined>(undefined)
90+
const fgRef = useRef<ForceGraphMethods<GraphNode, GraphLink>>(null)
9191

9292
const draggedNodesRef = useRef<Set<string>>(new Set())
9393
const graphDataRef = useRef<{ nodes: GraphNode[]; links: GraphLink[] }>({ nodes: [], links: [] })
@@ -158,12 +158,12 @@ export default function GraphView({
158158
const nodes: GraphNode[] = notes.map((n) => {
159159
const isAuto = /^\d+\.md$/.test(n.id)
160160
let title = n.id.replace(/\.md$/, '')
161-
const folder = n.id.includes('/') ? n.id.split('/')[0] : ''
161+
const folder = n.id.includes('/') ? n.id.split('/')[0]! : ''
162162

163163
if (isAuto) {
164164
title =
165165
n.content
166-
.split('\n')[0]
166+
.split('\n')[0]!
167167
.trim()
168168
.replace(/^#+\s*/, '') || 'New Note'
169169
}
@@ -180,22 +180,22 @@ export default function GraphView({
180180
const reFile = /\]\(\/file\s+([^)]+)\)/g
181181
let match
182182
while ((match = reFile.exec(note.content)) !== null) {
183-
let targetId = match[1].trim().replace(/\\/g, '/')
183+
let targetId = match[1]!.trim().replace(/\\/g, '/')
184184
if (!targetId.endsWith('.md')) targetId += '.md'
185185
targets.add(targetId)
186186
}
187187

188188
const reMd = /\]\(([^)]+\.md)\)/g
189189
while ((match = reMd.exec(note.content)) !== null) {
190-
let targetId = match[1].trim().replace(/\\/g, '/')
190+
let targetId = match[1]!.trim().replace(/\\/g, '/')
191191
if (targetId.startsWith('./')) targetId = targetId.slice(2)
192192
if (targetId.startsWith('/')) targetId = targetId.slice(1)
193193
targets.add(targetId)
194194
}
195195

196196
const reWiki = /\[\[([^\]]+)\]\]/g
197197
while ((match = reWiki.exec(note.content)) !== null) {
198-
let targetId = match[1].split('|')[0].trim().replace(/\\/g, '/')
198+
let targetId = match[1]!.split('|')[0]!.trim().replace(/\\/g, '/')
199199
if (!targetId.endsWith('.md')) targetId += '.md'
200200
targets.add(targetId)
201201
}
@@ -299,8 +299,9 @@ export default function GraphView({
299299
}, [])
300300

301301
const nodeThreeObject = useCallback(
302-
(node: GraphNode) => {
303-
const color = node.folder ? getFolderColor(node.folder) : accentColor
302+
(node: object) => {
303+
const gNode = node as GraphNode
304+
const color = gNode.folder ? getFolderColor(gNode.folder) : accentColor
304305
const group = new THREE.Group()
305306

306307
const geometry = new THREE.CircleGeometry(NODE_RADIUS, 32)
@@ -315,9 +316,9 @@ export default function GraphView({
315316
const ctx = canvas.getContext('2d')!
316317
ctx.clearRect(0, 0, 256, 64)
317318
const displayName =
318-
node.name.length > MAX_NAME_LENGTH
319-
? node.name.slice(0, MAX_NAME_LENGTH - 3) + '…'
320-
: node.name
319+
gNode.name.length > MAX_NAME_LENGTH
320+
? gNode.name.slice(0, MAX_NAME_LENGTH - 3) + '…'
321+
: gNode.name
321322
ctx.fillStyle = textColor
322323
ctx.font = `bold ${LABEL_FONT_SIZE}px sans-serif`
323324
ctx.textAlign = 'center'
@@ -510,7 +511,7 @@ export default function GraphView({
510511
}
511512
>
512513
<ForceGraph3D
513-
ref={fgRef}
514+
ref={fgRef as never}
514515
graphData={graphData}
515516
numDimensions={2}
516517
nodeLabel="name"

src/components/KeybindsModal.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ export function KeybindsModal({ onClose }: KeybindsModalProps) {
130130
if (sc.section === 'global' && sc.action && sc.oldShortcutStorageKey) {
131131
const oldShortcut = localStorage.getItem(sc.oldShortcutStorageKey) || sc.defaultKey
132132
if (window.electronAPI.updateGlobalShortcut) {
133-
window.electronAPI.updateGlobalShortcut(sc.action, oldShortcut, values[sc.key])
133+
window.electronAPI.updateGlobalShortcut(sc.action, oldShortcut, values[sc.key]!)
134134
}
135-
localStorage.setItem(sc.oldShortcutStorageKey, values[sc.key])
135+
localStorage.setItem(sc.oldShortcutStorageKey, values[sc.key]!)
136136
}
137-
localStorage.setItem(sc.storageKey, values[sc.key])
137+
localStorage.setItem(sc.storageKey, values[sc.key]!)
138138
}
139139

140140
useAppStore
@@ -175,7 +175,7 @@ export function KeybindsModal({ onClose }: KeybindsModalProps) {
175175
<KeybindRow
176176
key={sc.key}
177177
label={sc.label}
178-
value={values[sc.key]}
178+
value={values[sc.key]!}
179179
onChange={(val) => setValues((prev) => ({ ...prev, [sc.key]: val }))}
180180
/>
181181
))}
@@ -187,7 +187,7 @@ export function KeybindsModal({ onClose }: KeybindsModalProps) {
187187
<KeybindRow
188188
key={sc.key}
189189
label={sc.label}
190-
value={values[sc.key]}
190+
value={values[sc.key]!}
191191
onChange={(val) => setValues((prev) => ({ ...prev, [sc.key]: val }))}
192192
/>
193193
))}

src/components/NoteSearch.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function NoteSearch() {
2929
const getNoteTitle = (n: Note) => {
3030
const isAuto = /^\d+\.md$/.test(n.id)
3131
const fileName = n.id.replace(/\.md$/, '').split('/').pop() || ''
32-
return isAuto ? n.content.split('\n')[0].trim() || 'New Note' : fileName
32+
return isAuto ? n.content.split('\n')[0]!.trim() || 'New Note' : fileName
3333
}
3434

3535
const getNoteTags = (n: Note): string[] => {
@@ -197,7 +197,7 @@ export function NoteSearch() {
197197
e.preventDefault()
198198
if (showNoteActionMenu) return
199199
if (filteredNotes.length > 0) {
200-
const selNote = filteredNotes[searchSelectedIndex]
200+
const selNote = filteredNotes[searchSelectedIndex]!
201201
const idx = notes.findIndex((note) => note.id === selNote.id)
202202
if (idx !== -1) setCurrentNoteIndex(idx)
203203
setShowNoteSearch(false)
@@ -404,7 +404,7 @@ export function NoteSearch() {
404404
width: 8,
405405
height: 8,
406406
borderRadius: '50%',
407-
backgroundColor: getFolderColor(pathParts[0]),
407+
backgroundColor: getFolderColor(pathParts[0]!),
408408
}}
409409
/>
410410
<span className="ns-folder">{pathParts.join(' / ')}</span>

src/components/NoteTitleBar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export function NoteTitleBar() {
1313

1414
const isAutoNamed = /^\d+\.md$/.test(activeNote.id)
1515
const displayTitle = isAutoNamed
16-
? activeNote.content.split('\n')[0].trim() || 'New Note'
17-
: activeNote.id.split('/').pop() || ''
16+
? activeNote.content.split('\n')[0]!.trim() || 'New Note'
17+
: activeNote.id.split('/').pop()! || ''
1818

1919
const startRename = () => {
2020
setRenameValue(displayTitle)

src/hooks/useNoteStorage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function useNoteStorage() {
2828
// Save current note index to localStorage
2929
useEffect(() => {
3030
if (notes.length > 0 && currentNoteIndex >= 0 && currentNoteIndex < notes.length) {
31-
localStorage.setItem('papercache-last-open-note', notes[currentNoteIndex].id)
31+
localStorage.setItem('papercache-last-open-note', notes[currentNoteIndex]!.id)
3232
}
3333
}, [currentNoteIndex, notes])
3434

src/hooks/useReminders.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ describe('useReminders', () => {
4848

4949
// Should have called the backend to schedule the reminder
5050
expect(scheduleRemindersMock).toHaveBeenCalledTimes(1)
51-
const reminders = scheduleRemindersMock.mock.calls[0][0] as {
51+
const reminders = scheduleRemindersMock.mock.calls[0]![0] as {
5252
key: string
5353
label: string
5454
dueAt: number
5555
}[]
5656
expect(reminders.length).toBe(1)
57-
expect(reminders[0].label).toBe('Buy bread')
58-
expect(reminders[0].dueAt).toBeGreaterThan(Date.now())
57+
expect(reminders[0]!.label).toBe('Buy bread')
58+
expect(reminders[0]!.dueAt).toBeGreaterThan(Date.now())
5959
})
6060

6161
it('should NOT schedule past-due reminders (already notified by backend on last run)', async () => {
@@ -73,7 +73,7 @@ describe('useReminders', () => {
7373

7474
// Called but with empty array – past reminders are not re-scheduled
7575
expect(scheduleRemindersMock).toHaveBeenCalledTimes(1)
76-
const reminders = scheduleRemindersMock.mock.calls[0][0] as unknown[]
76+
const reminders = scheduleRemindersMock.mock.calls[0]![0] as unknown[]
7777
expect(reminders.length).toBe(0)
7878
})
7979

@@ -90,7 +90,7 @@ describe('useReminders', () => {
9090

9191
renderHook(() => useReminders())
9292

93-
const reminders = scheduleRemindersMock.mock.calls[0][0] as unknown[]
93+
const reminders = scheduleRemindersMock.mock.calls[0]![0] as unknown[]
9494
expect(reminders.length).toBe(0)
9595
})
9696

src/hooks/useVariables.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export function useVariables() {
1717
for (const note of notes) {
1818
let varMatch
1919
while ((varMatch = reVar.exec(note.content)) !== null) {
20-
const name = varMatch[1]
20+
const name = varMatch[1]!
2121
try {
22-
globals[name] = evaluate(varMatch[2], globals)
22+
globals[name] = evaluate(varMatch[2]!, globals)
2323
} catch (e) {
2424
// eslint-disable-next-line no-console
2525
console.error(`useVariables evaluation error for ${name}:`, e)
26-
globals[name] = varMatch[2].trim()
26+
globals[name] = varMatch[2]!.trim()
2727
}
2828
}
2929
}

0 commit comments

Comments
 (0)