Fix invalid relative image path (#2935)

This commit is contained in:
Felix Häusler 2022-01-27 22:02:21 +01:00 committed by GitHub
parent a996defacc
commit b442aafa5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 19 deletions

View File

@ -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

View File

@ -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

View File

@ -20,6 +20,9 @@
:regexValidator="/^(?:$|(?![a-zA-Z]:)[^\/\\].*$)/"
:defaultValue="relativeDirectoryNamePlaceholder"
:onChange="value => onSelectChange('imageRelativeDirectoryName', value)"></text-box>
<div class="footnote">
Include <code>${filename}</code> in the text-box above to automatically insert the document file name.
</div>
</template>
</compound>
</section>
@ -77,3 +80,12 @@ export default {
}
}
</script>
<style scoped>
.image-folder .footnote {
font-size: 13px;
& code {
font-size: 13px;
}
}
</style>

View File

@ -2,7 +2,7 @@
<div class="pref-image">
<h4>Image</h4>
<section class="image-ctrl">
<div>Default action after image is inserted from local folder or clipboard
<div>Default action after an image is inserted from local folder or clipboard
<el-tooltip class='item' effect='dark'
content='Clipboard handling is only fully supported on macOS and Windows.'
placement='top-start'>

View File

@ -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.