diff --git a/frontend/app.js b/frontend/app.js index c2854b9..259d3d4 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -2248,8 +2248,9 @@ function noteApp() { setTimeout(() => this.scrollToAnchor(anchor), 100); } }); - } else { - alert(this.t('notes.not_found', { path: notePath })); + } else if (confirm(this.t('notes.create_from_link', { path: notePath }))) { + // Note doesn't exist - create it (reuses createNote with duplicate check) + this.createNote(null, notePath); } }, @@ -2825,49 +2826,55 @@ function noteApp() { // UNIFIED CREATION FUNCTIONS (reusable from anywhere) // ===================================================== - async createNote(folderPath = null) { - // Use provided folder path, or dropdown target folder context, or homepage folder - // Note: Check dropdownTargetFolder !== null to distinguish between '' (root) and not set - let targetFolder; - if (folderPath !== null) { - targetFolder = folderPath; - } else if (this.dropdownTargetFolder !== null && this.dropdownTargetFolder !== undefined) { - targetFolder = this.dropdownTargetFolder; // Can be '' for root or a folder path - } else { - targetFolder = this.selectedHomepageFolder || ''; - } - this.closeDropdown(); - - const promptText = targetFolder - ? this.t('notes.prompt_name_in_folder', { folder: targetFolder }) - : this.t('notes.prompt_name_with_path'); - - const noteName = prompt(promptText); - if (!noteName) return; - - // Validate the name/path (may contain / for paths when no target folder) - const validation = targetFolder - ? FilenameValidator.validateFilename(noteName) - : FilenameValidator.validatePath(noteName); - - if (!validation.valid) { - alert(this.getValidationErrorMessage(validation, 'note')); - return; - } - - const validatedName = validation.sanitized; - + async createNote(folderPath = null, directPath = null) { let notePath; - if (targetFolder) { - notePath = `${targetFolder}/${validatedName}.md`; + + if (directPath) { + // Direct path provided (e.g., from wiki link) - skip prompting + notePath = directPath.endsWith('.md') ? directPath : `${directPath}.md`; } else { - notePath = validatedName.endsWith('.md') ? validatedName : `${validatedName}.md`; + // Use provided folder path, or dropdown target folder context, or homepage folder + // Note: Check dropdownTargetFolder !== null to distinguish between '' (root) and not set + let targetFolder; + if (folderPath !== null) { + targetFolder = folderPath; + } else if (this.dropdownTargetFolder !== null && this.dropdownTargetFolder !== undefined) { + targetFolder = this.dropdownTargetFolder; // Can be '' for root or a folder path + } else { + targetFolder = this.selectedHomepageFolder || ''; + } + this.closeDropdown(); + + const promptText = targetFolder + ? this.t('notes.prompt_name_in_folder', { folder: targetFolder }) + : this.t('notes.prompt_name_with_path'); + + const noteName = prompt(promptText); + if (!noteName) return; + + // Validate the name/path (may contain / for paths when no target folder) + const validation = targetFolder + ? FilenameValidator.validateFilename(noteName) + : FilenameValidator.validatePath(noteName); + + if (!validation.valid) { + alert(this.getValidationErrorMessage(validation, 'note')); + return; + } + + const validatedName = validation.sanitized; + + if (targetFolder) { + notePath = `${targetFolder}/${validatedName}.md`; + } else { + notePath = validatedName.endsWith('.md') ? validatedName : `${validatedName}.md`; + } } - // CRITICAL: Check if note already exists + // CRITICAL: Check if note already exists (applies to both prompt and direct path) const existingNote = this.notes.find(note => note.path === notePath); if (existingNote) { - alert(this.t('notes.already_exists', { name: validatedName })); + alert(this.t('notes.already_exists', { name: notePath })); return; } @@ -2879,9 +2886,9 @@ function noteApp() { }); if (response.ok) { - if (targetFolder) { - this.expandedFolders.add(targetFolder); - } + // Expand parent folder if note is in a subfolder + const folderPart = notePath.includes('/') ? notePath.substring(0, notePath.lastIndexOf('/')) : ''; + if (folderPart) this.expandedFolders.add(folderPart); await this.loadNotes(); await this.loadNote(notePath); } else { diff --git a/locales/de-DE.json b/locales/de-DE.json index ad5cd27..c2669bd 100644 --- a/locales/de-DE.json +++ b/locales/de-DE.json @@ -80,6 +80,7 @@ "invalid_name": "Ungültiger Notizname.", "empty_name": "Der Notizname darf nicht leer sein.", "not_found": "Notiz nicht gefunden: {{path}}", + "create_from_link": "Notiz \"{{path}}\" existiert nicht.\n\nMöchten Sie sie erstellen?", "no_content": "Kein Inhalt zum Exportieren", "open_first": "Bitte öffne zuerst eine Notiz, bevor du Bilder hochlädst." }, diff --git a/locales/en-US.json b/locales/en-US.json index fa53d45..10ede19 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -80,6 +80,7 @@ "invalid_name": "Invalid note name.", "empty_name": "Note name cannot be empty.", "not_found": "Note not found: {{path}}", + "create_from_link": "Note \"{{path}}\" doesn't exist.\n\nWould you like to create it?", "no_content": "No note content to export", "open_first": "Please open a note first before uploading images." }, diff --git a/locales/es-ES.json b/locales/es-ES.json index 3747382..6d3fe51 100644 --- a/locales/es-ES.json +++ b/locales/es-ES.json @@ -80,6 +80,7 @@ "invalid_name": "Nombre de nota inválido.", "empty_name": "El nombre de la nota no puede estar vacío.", "not_found": "Nota no encontrada: {{path}}", + "create_from_link": "La nota \"{{path}}\" no existe.\n\n¿Desea crearla?", "no_content": "No hay contenido para exportar", "open_first": "Por favor, abre una nota antes de subir imágenes." }, diff --git a/locales/fr-FR.json b/locales/fr-FR.json index 23805ad..34009d5 100644 --- a/locales/fr-FR.json +++ b/locales/fr-FR.json @@ -80,6 +80,7 @@ "invalid_name": "Nom de note invalide.", "empty_name": "Le nom de la note ne peut pas être vide.", "not_found": "Note introuvable : {{path}}", + "create_from_link": "La note \"{{path}}\" n'existe pas.\n\nVoulez-vous la créer ?", "no_content": "Aucun contenu à exporter", "open_first": "Veuillez d'abord ouvrir une note avant de télécharger des images." }, diff --git a/locales/sl-SI.json b/locales/sl-SI.json index dcd2e5c..ad72096 100644 --- a/locales/sl-SI.json +++ b/locales/sl-SI.json @@ -80,6 +80,7 @@ "invalid_name": "Neveljavno ime zapisa.", "empty_name": "Ime zapisa ne more biti prazno.", "not_found": "Zapisa ni mogoče najti: {{path}}", + "create_from_link": "Zapis \"{{path}}\" ne obstaja.\n\nAli ga želite ustvariti?", "no_content": "Ni vsebine za izvoz", "open_first": "Prosimo, najprej odprite zapis, preden naložite slike." }, diff --git a/locales/zh-CN.json b/locales/zh-CN.json index df3b137..f4daae1 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -80,6 +80,7 @@ "invalid_name": "无效的笔记名称。", "empty_name": "笔记名称不能为空。", "not_found": "未找到笔记:{{path}}", + "create_from_link": "笔记 \"{{path}}\" 不存在。\n\n是否要创建它?", "no_content": "没有可导出的笔记内容", "open_first": "请先打开一篇笔记,然后再上传图片。" },