diff --git a/docs/IMAGES.md b/docs/IMAGES.md index c80a9a63..de3c87ff 100644 --- a/docs/IMAGES.md +++ b/docs/IMAGES.md @@ -12,9 +12,9 @@ All images are automatically copied into the specified local directory that may **Prefer relative assets folder:** -When this option is enabled, all images are copied relative to the opened file or the root directory when a project is opened. You can specify the path via the *relative image folder name* text box. The local resource directory is used if the file is not saved. +When this option is enabled, all images are copied relative to the opened file. The root directory is used when a project is opened and no variables are used. You can specify the path via the *relative image folder name* text box and include variables like `${filename}` to add the file name to the relative directory. The local resource directory is used if the file is not saved. -NB: The assets directory name must be a valid path name and MarkText need write access to the directory. +Note: The assets directory name must be a valid path name and MarkText need write access to the directory. Examples for relative paths: @@ -22,6 +22,7 @@ Examples for relative paths: - `../assets` - `.`: current file directory - `assets/123` +- `assets_${filename}` (add the document file name) ### Keep original location diff --git a/src/renderer/components/editorWithTabs/editor.vue b/src/renderer/components/editorWithTabs/editor.vue index aceae426..22ba59d7 100644 --- a/src/renderer/components/editorWithTabs/editor.vue +++ b/src/renderer/components/editorWithTabs/editor.vue @@ -780,6 +780,7 @@ export default { }, async imageAction (image, id, alt = '') { + // TODO(Refactor): Refactor this method. const { imageInsertAction, imageFolderPath, @@ -792,20 +793,29 @@ export default { pathname } = this.currentFile + // Save an image relative to the file if the relative image directory include the filename variable. + // The image is save relative to the root folder without a variable. + const saveRelativeToFile = () => { + return /\${filename}/.test(imageRelativeDirectoryName) + } + // Figure out the current working directory. - let cwd = pathname ? path.dirname(pathname) : null - if (pathname && this.projectTree) { + const isTabSavedOnDisk = !!pathname + let relativeBasePath = isTabSavedOnDisk ? path.dirname(pathname) : null + if (isTabSavedOnDisk && !saveRelativeToFile() && this.projectTree) { const { pathname: rootPath } = this.projectTree if (rootPath && isChildOfDirectory(rootPath, pathname)) { // Save assets relative to root directory. - cwd = rootPath + relativeBasePath = rootPath } } const getResolvedImagePath = imagePath => { - // Use filename only when the tab is saved on disk. - const replacement = pathname ? filename : '' - return imagePath.replace(/\${filename}/g, replacement.replace(/\.[^/.]+$/, '')) + const replacement = isTabSavedOnDisk + // Filename w/o extension + ? filename.replace(/\.[^/.]+$/, '') + : '' + return imagePath.replace(/\${filename}/g, replacement) } const resolvedImageFolderPath = getResolvedImagePath(imageFolderPath) @@ -827,21 +837,22 @@ export default { } case 'folder': { destImagePath = await moveImageToFolder(pathname, image, resolvedImageFolderPath) - if (cwd && imagePreferRelativeDirectory) { - destImagePath = await moveToRelativeFolder(cwd, destImagePath, resolvedImageRelativeDirectoryName) + if (isTabSavedOnDisk && imagePreferRelativeDirectory) { + destImagePath = await moveToRelativeFolder(relativeBasePath, resolvedImageRelativeDirectoryName, pathname, destImagePath) } break } case 'path': { if (typeof image === 'string') { + // Input is a local path. destImagePath = image } else { - // Move image to image folder if it's Blob object. + // Save and move image to image folder if input is binary. destImagePath = await moveImageToFolder(pathname, image, resolvedImageFolderPath) - // Respect user preferences if file exist on disk. - if (cwd && imagePreferRelativeDirectory) { - destImagePath = await moveToRelativeFolder(cwd, destImagePath, resolvedImageRelativeDirectoryName) + // Respect user preferences if tab exists on disk. + if (isTabSavedOnDisk && imagePreferRelativeDirectory) { + destImagePath = await moveToRelativeFolder(relativeBasePath, resolvedImageRelativeDirectoryName, pathname, destImagePath) } } break diff --git a/src/renderer/prefComponents/image/components/folderSetting/index.vue b/src/renderer/prefComponents/image/components/folderSetting/index.vue index 221305c0..804f723d 100644 --- a/src/renderer/prefComponents/image/components/folderSetting/index.vue +++ b/src/renderer/prefComponents/image/components/folderSetting/index.vue @@ -20,6 +20,9 @@ :regexValidator="/^(?:$|(?![a-zA-Z]:)[^\/\\].*$)/" :defaultValue="relativeDirectoryNamePlaceholder" :onChange="value => onSelectChange('imageRelativeDirectoryName', value)"> +
+ Include ${filename} in the text-box above to automatically insert the document file name. +
@@ -77,3 +80,12 @@ export default { } } + + diff --git a/src/renderer/prefComponents/image/index.vue b/src/renderer/prefComponents/image/index.vue index 28d23dd9..aadaf568 100644 --- a/src/renderer/prefComponents/image/index.vue +++ b/src/renderer/prefComponents/image/index.vue @@ -2,7 +2,7 @@

Image

-
Default action after image is inserted from local folder or clipboard +
Default action after an image is inserted from local folder or clipboard diff --git a/src/renderer/util/fileSystem.js b/src/renderer/util/fileSystem.js index 27038919..2321e49f 100644 --- a/src/renderer/util/fileSystem.js +++ b/src/renderer/util/fileSystem.js @@ -33,12 +33,21 @@ export const getContentHash = content => { return getHash(content, 'utf8', 'sha1') } -export const moveToRelativeFolder = async (cwd, imagePath, relativeName) => { +/** + * Moves an image to a relative position. + * + * @param {String} cwd The relative base path (project root or full folder path of opened file). + * @param {String} relativeName The relative directory name. + * @param {String} filePath The full path to the opened file in editor. + * @param {String} imagePath The image to move. + * @returns {String} The relative path the the image from given `filePath`. + */ +export const moveToRelativeFolder = async (cwd, relativeName, filePath, imagePath) => { if (!relativeName) { // Use fallback name according settings description relativeName = 'assets' } else if (path.isAbsolute(relativeName)) { - throw new Error('Invalid relative directory name') + throw new Error('Invalid relative directory name.') } // Path combination: @@ -49,8 +58,8 @@ export const moveToRelativeFolder = async (cwd, imagePath, relativeName) => { await fs.ensureDir(absPath) await fs.move(imagePath, dstPath, { overwrite: true }) - // dstRelPath: relative directory name + image file name - const dstRelPath = path.join(relativeName, path.basename(imagePath)) + // Find relative path between given file and saved image. + const dstRelPath = path.relative(path.dirname(filePath), dstPath) if (isWindows) { // Use forward slashes for better compatibility with websites.