import { viewModes, activeViewMode } from '@/composables/useViewMode' import { useTitle } from '@vueuse/core' import { mdToHtml } from '@/utils/markdown' import { getAllMatches } from '@/utils/helpers' import shortid from 'shortid' const baseNotes = reactive<{ [noteId: string]: BaseNote }>({}) export const notes = computed(() => { return Object.entries(baseNotes) .map(([_, note]) => ({ ...note, wordCount: note.content.split(' ').filter((word) => word.length > 0).length, })) .sort((a, b) => b.modified - a.modified) as Note[] }) watch(notes, () => { if (notes.value.length > 0 && !activeNote.value) setActiveNote(rootNote.value?.id) }) const activeNoteId = ref() export const activeNote = computed(() => notes.value.find((note) => note.id === activeNoteId.value) ) watch(activeNote, () => { if (activeNote.value) { useTitle(`${activeNote.value.title} | Contexted`) } }) export const setActiveNote = (noteId: string | undefined) => { if (noteId) { activeNoteId.value = noteId activeViewMode.value = viewModes.find((mode) => mode.name === 'Note') || viewModes[0] } } export const rootNote = computed(() => { const rootNote = notes.value.find((note: Note) => note.isRoot) return rootNote }) export const setRootNote = (noteId: string) => { if (rootNote.value) { const updatedRootNote = { ...baseNotes[rootNote.value.id], isRoot: false } updateNote(updatedRootNote.id, updatedRootNote) } const note = { ...baseNotes[noteId], isRoot: true } updateNote(noteId, note) setActiveNote(noteId) } export const setDefaultNotes = (defaultNotes: BaseNote[]) => { defaultNotes.forEach((defaultNote) => { baseNotes[defaultNote.id] = defaultNote }) } export const getNoteById = (noteId: string) => { return notes.value.find((note) => note.id === noteId) } export const getNoteByTitle = (title: string) => { return notes.value.find((note) => note.title === title) } export const findNotesByByTitle = (title: string) => { const titleLowerCase = title.toLowerCase() return notes.value.filter((note) => note.title.toLowerCase().includes(titleLowerCase)) } export const findNotes = (query: string): Note[] => { const removeMdFromText = (mdText: string): string => { const div = document.createElement('div') div.innerHTML = mdToHtml(mdText) const textWithoutMd = div.textContent || div.innerText || '' return textWithoutMd } return notes.value.filter((note) => { const matchTitle = note.title.toLowerCase().includes(query.toLowerCase()) const matchContent = removeMdFromText(note.content) .toLowerCase() .includes(query.toLowerCase()) return matchTitle || matchContent }) } export const updateNote = (noteId: string, note: BaseNote) => { const updatedNote: BaseNote = { ...note, modified: new Date().getTime(), } baseNotes[noteId] = updatedNote } export const addNote = (title: string, content: string, goToNote: boolean = false) => { const id = shortid.generate() const newNote: BaseNote = { id, title, content, created: new Date().getTime(), modified: new Date().getTime(), } baseNotes[id] = newNote if (goToNote) setActiveNote(id) } export const deleteNote = (noteId: string) => { delete baseNotes[noteId] } const getNoteLinksByNoteId = (noteId: string): string[] => { const note = baseNotes[noteId] const regex = /\[\[(.*?)\]\]/g const links = getAllMatches(regex, note.content || '') .map((to) => notes.value.find((note) => note.title === to[1])?.id || '') .filter((noteId) => Object.keys(baseNotes).includes(noteId)) return [...links] } interface NoteRelations { id: string to: string[] from: string[] } interface NotesRelations { [noteId: string]: { to: string[] from: string[] } } export const notesRelations = computed(() => { const noteIds = Object.keys(baseNotes) const relations = noteIds .filter((id) => id !== undefined) .map((id) => { const to = getNoteLinksByNoteId(id) return { id, to } }) .map((noteRelations, _, notesRelations): NoteRelations => { const from = [...notesRelations] .map((noteRelation) => noteRelation.to .filter((toId) => toId === noteRelations.id) .map(() => noteRelation.id) ) .reduce((arr, elem) => arr.concat(elem), []) .filter((value, index, self) => self.indexOf(value) === index) return { id: noteRelations.id, to: noteRelations.to, from, } }) .reduce((notes, { id, to, from }) => { notes[id] = { to, from } return notes }, {} as NotesRelations) return relations })