mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 11:32:13 +08:00
Fix invalid relative image path (#2935)
This commit is contained in:
parent
a996defacc
commit
b442aafa5a
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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'>
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user