Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ulisesantana/obsidian-pending-notes
Browse files Browse the repository at this point in the history
  • Loading branch information
ulisesantana committed Jan 26, 2023
2 parents 8005dcc + d497cae commit 7bee437
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 39 deletions.
43 changes: 31 additions & 12 deletions src/core/Notes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,56 @@ export interface Note {
content: Promise<string>
}

type PendingToCreateNote = string
export type NotePendingToBeCreated = {
title: string,
timesLinked: number
}

export class Notes {
static async getPendingToCreate(notes: Note[]): Promise<PendingToCreateNote[]> {
static async getPendingToCreate(notes: Note[]): Promise<NotePendingToBeCreated[]> {
const links = await Notes.getOutlinks(notes);
const allNotes = new Set(notes.map(n => n.name.toLowerCase()))
const missingNotes = new Set<string>()
const missingNotes = {} as Record<string, number>
for (const link of links) {
if (!allNotes.has(link.toLowerCase())) {
missingNotes.add(link)
missingNotes[link] = missingNotes[link] !== undefined
? missingNotes[link] + 1
: 1
}
}
return Array.from(missingNotes)
.filter(n => Boolean(n) && Notes.filterMarkdown(n))
return Object.entries(missingNotes)
.reduce<NotePendingToBeCreated[]>((notes, [title, timesLinked]) => {
if (Boolean(title) && Notes.hasFileExtension(title)) {
return notes.concat({title, timesLinked})
}
return notes
}, [])
.sort(Notes.sortByTitle)
.sort(Notes.sortByTimesLinked)
}

private static sortByTimesLinked(a: NotePendingToBeCreated, b: NotePendingToBeCreated) {
return a.timesLinked < b.timesLinked
? 1
: a.timesLinked > b.timesLinked
? -1
: 0;
}

private static sortByTitle(a: string, b: string) {
return a.toLowerCase() > b.toLowerCase()
private static sortByTitle(a: NotePendingToBeCreated, b: NotePendingToBeCreated) {
return a.title.toLowerCase() > b.title.toLowerCase()
? 1
: a.toLowerCase() < b.toLowerCase()
: a.title.toLowerCase() < b.title.toLowerCase()
? -1
: 0;
}

private static async getOutlinks(notes: Note[]): Promise<Set<string>> {
private static async getOutlinks(notes: Note[]): Promise<string[]> {
const links = []
for await (const note of Notes.cleanNotes(notes)) {
links.push(...Notes.extractNoteOutlinks(note))
}
return new Set(links);
return links;
}

private static extractNoteOutlinks(note: string): string[] {
Expand Down Expand Up @@ -69,7 +88,7 @@ export class Notes {
return Array.from(note.matchAll(expression)).flatMap(([x]) => x);
}

private static filterMarkdown(n: string) {
private static hasFileExtension(n: string) {
// Test if ends with an extension from 1 to 5 characters long
return !/.+\.\w{1,5}/g.test(n);
}
Expand Down
6 changes: 3 additions & 3 deletions src/views/MainView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from "react";
import * as ReactDOM from "react-dom";
import {createRoot} from "react-dom/client";
import {PendingNotesView} from "./PendingNotesView";
import {Note, Notes} from "../core/Notes";
import {Note, NotePendingToBeCreated, Notes} from "../core/Notes";

export const VIEW_TYPE_MAIN = "pending-notes:main";

Expand Down Expand Up @@ -38,7 +38,7 @@ export class MainView extends ItemView {
ReactDOM.unmountComponentAtNode(this.containerEl.children[1]);
}

private createNote(note: string, event: UserEvent): Promise<string[]> {
private createNote(note: string, event: UserEvent): Promise<NotePendingToBeCreated[]> {
const noteFile = note + '.md'
const defaultFolder = this.app.fileManager.getNewFileParent("")
const pathDivider = defaultFolder.path.includes('\\') ? '\\' : '/'
Expand All @@ -50,7 +50,7 @@ export class MainView extends ItemView {
.then(() => this.getPendingNotes())
}

private async getPendingNotes(): Promise<string[]> {
private async getPendingNotes(): Promise<NotePendingToBeCreated[]> {
const notes = this.app.vault.getMarkdownFiles().map(f => this.readNote(f))
return Notes.getPendingToCreate(notes)
}
Expand Down
19 changes: 10 additions & 9 deletions src/views/PendingNotesView.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import * as React from "react";
import {FC, MouseEventHandler, useState} from "react";
import {NotePendingToBeCreated} from "../core/Notes";

interface Props {
notes: string[]
onCreateNote: (note: string, event: MouseEvent) => Promise<string[]>
notes: NotePendingToBeCreated[]
onCreateNote: (note: string, event: MouseEvent) => Promise<NotePendingToBeCreated[]>
}

export const PendingNotesView: FC<Props> = ({notes, onCreateNote}) => {
Expand All @@ -14,18 +15,18 @@ export const PendingNotesView: FC<Props> = ({notes, onCreateNote}) => {
return (
<div className="pending-notes-view-container">
<h1>Pending notes</h1>
<span><strong>{items.length}</strong> notes linked, but not created yet.</span>
<span><strong>{items.length}</strong> notes linked, but not created yet. Times the note is linked is shown in parentheses.</span>
<ul>
{items.map(n => (
<li key={n}>
{items.map(({title, timesLinked}) => (
<li key={title}>
<a
data-href={n}
href={n}
onClick={generateOnClick(n)}
data-href={title}
href={title}
onClick={generateOnClick(title)}
className="internal-link is-unresolved"
target="_blank"
>
{n}
({timesLinked}) {title}
</a>
</li>
))}
Expand Down
6 changes: 3 additions & 3 deletions styles.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
.pending-notes-view-container h1 {
margin-bottom: 4px;
margin-bottom: 4px;
}

.pending-notes-view-container ul {
margin: 0 8px;
padding: 16px 0 32px;
padding: 16px 16px 32px;
}

.pending-notes-view-container ul li {
margin: 0;
padding: 4px 8px;
padding: 4px;
}
54 changes: 42 additions & 12 deletions test/core/Notes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@ import * as fs from "fs/promises";

describe('Notes should', () => {
describe('extract notes pending to be created', () => {
it('successfully', async () => {
it('sort by times linked and then by title', async () => {
const pending = await Notes.getPendingToCreate([
{
"name": "Tiempo y Espacio",
"content": Promise.resolve("[[Tiempo|El tiempo]] y espacio que me ha dado la excedencia me ha venido increíblemente bien. Sin embargo, recuerdo el [[Light and Space.pdf|poema]] de [[Charles Bukowski]] y me encuentro un poco en el medio.\n\nTambién es cierto que Bukowski lo critica desde el punto de vista de *crear*. En ese aspecto estoy de acuerdo con él. La creatividad no tiene nada que ver con el equipo que tengas, sino contigo mismo. Tu pasión y tu [[Actitud|actitud]] serán las que marquen la diferencia a la hora de crear.\n\nYo hablo del tiempo y en espacio para [[Pensar#Reflexionar|reflexionar]], pensar, conocerse a sí mismo. Eso sí que creo que lo es posible en medio de una tormenta.\n\n![[E30BB200-93F5-486D-B293-244788D253DC.mp3]]\n![[E30BB200-93F5-486D-B293-244788D253DC.jpg]]\n![[E30BB200-93F5-486D-B293-244788D253DC.jpeg]]\n![[E30BB200-93F5-486D-B293-244788D253DC.png]]\n![[E30BB200-93F5-486D-B293-244788D253DC.mp4]]\n![[E30BB200-93F5-486D-B293-244788D253DC.ogg]]\n![[E30BB200-93F5-486D-B293-244788D253DC.m4a]]\n![[E30BB200-93F5-486D-B293-244788D253DC.pdf]]\n![[E30BB200-93F5-486D-B293-244788D253DC.pdf]]")
},
{
"name": "Actitud",
"content": Promise.resolve("Esta nota está creada, pero pendiente de ser rellenada.")
"content": Promise.resolve("Esta nota está creada, pero pendiente de ser rellenada. Hay que pararse a [[Pensar]]")
}
])
expect(pending).toEqual([
'Charles Bukowski',
'Pensar',
'Tiempo'
{
"timesLinked": 2,
"title": "Pensar"
},
{
"timesLinked": 1,
"title": "Charles Bukowski"
},
{
"timesLinked": 1,
"title": "Tiempo"
}
])
});

Expand All @@ -29,8 +38,14 @@ describe('Notes should', () => {
},
])
expect(pending).toEqual([
'Concept',
'Ideaverse'
{
"timesLinked": 1,
"title": "Concept"
},
{
"timesLinked": 1,
"title": "Ideaverse"
}
])
});

Expand All @@ -42,7 +57,10 @@ describe('Notes should', () => {
},
])
expect(pending).toEqual([
'Charles Bukowski',
{
"timesLinked": 1,
"title": "Charles Bukowski"
}
])
});

Expand All @@ -54,7 +72,10 @@ describe('Notes should', () => {
},
])
expect(pending).toEqual([
'Chocolate',
{
"timesLinked": 1,
"title": "Chocolate"
}
])
});

Expand All @@ -66,8 +87,14 @@ describe('Notes should', () => {
},
])
expect(pending).toEqual([
'code blocks',
'inline code'
{
"timesLinked": 1,
"title": "code blocks"
},
{
"timesLinked": 1,
"title": "inline code"
}
])
});

Expand All @@ -83,7 +110,10 @@ describe('Notes should', () => {
},
])
expect(pending).toEqual([
'Outlinks'
{
"timesLinked": 1,
"title": "Outlinks"
}
])
});
});
Expand Down

0 comments on commit 7bee437

Please sign in to comment.