mirror of
https://github.com/marktext/marktext.git
synced 2025-05-03 12:10:38 +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:**
|
**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:
|
Examples for relative paths:
|
||||||
|
|
||||||
@ -22,6 +22,7 @@ Examples for relative paths:
|
|||||||
- `../assets`
|
- `../assets`
|
||||||
- `.`: current file directory
|
- `.`: current file directory
|
||||||
- `assets/123`
|
- `assets/123`
|
||||||
|
- `assets_${filename}` (add the document file name)
|
||||||
|
|
||||||
### Keep original location
|
### Keep original location
|
||||||
|
|
||||||
|
@ -780,6 +780,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async imageAction (image, id, alt = '') {
|
async imageAction (image, id, alt = '') {
|
||||||
|
// TODO(Refactor): Refactor this method.
|
||||||
const {
|
const {
|
||||||
imageInsertAction,
|
imageInsertAction,
|
||||||
imageFolderPath,
|
imageFolderPath,
|
||||||
@ -792,20 +793,29 @@ export default {
|
|||||||
pathname
|
pathname
|
||||||
} = this.currentFile
|
} = 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.
|
// Figure out the current working directory.
|
||||||
let cwd = pathname ? path.dirname(pathname) : null
|
const isTabSavedOnDisk = !!pathname
|
||||||
if (pathname && this.projectTree) {
|
let relativeBasePath = isTabSavedOnDisk ? path.dirname(pathname) : null
|
||||||
|
if (isTabSavedOnDisk && !saveRelativeToFile() && this.projectTree) {
|
||||||
const { pathname: rootPath } = this.projectTree
|
const { pathname: rootPath } = this.projectTree
|
||||||
if (rootPath && isChildOfDirectory(rootPath, pathname)) {
|
if (rootPath && isChildOfDirectory(rootPath, pathname)) {
|
||||||
// Save assets relative to root directory.
|
// Save assets relative to root directory.
|
||||||
cwd = rootPath
|
relativeBasePath = rootPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getResolvedImagePath = imagePath => {
|
const getResolvedImagePath = imagePath => {
|
||||||
// Use filename only when the tab is saved on disk.
|
const replacement = isTabSavedOnDisk
|
||||||
const replacement = pathname ? filename : ''
|
// Filename w/o extension
|
||||||
return imagePath.replace(/\${filename}/g, replacement.replace(/\.[^/.]+$/, ''))
|
? filename.replace(/\.[^/.]+$/, '')
|
||||||
|
: ''
|
||||||
|
return imagePath.replace(/\${filename}/g, replacement)
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedImageFolderPath = getResolvedImagePath(imageFolderPath)
|
const resolvedImageFolderPath = getResolvedImagePath(imageFolderPath)
|
||||||
@ -827,21 +837,22 @@ export default {
|
|||||||
}
|
}
|
||||||
case 'folder': {
|
case 'folder': {
|
||||||
destImagePath = await moveImageToFolder(pathname, image, resolvedImageFolderPath)
|
destImagePath = await moveImageToFolder(pathname, image, resolvedImageFolderPath)
|
||||||
if (cwd && imagePreferRelativeDirectory) {
|
if (isTabSavedOnDisk && imagePreferRelativeDirectory) {
|
||||||
destImagePath = await moveToRelativeFolder(cwd, destImagePath, resolvedImageRelativeDirectoryName)
|
destImagePath = await moveToRelativeFolder(relativeBasePath, resolvedImageRelativeDirectoryName, pathname, destImagePath)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'path': {
|
case 'path': {
|
||||||
if (typeof image === 'string') {
|
if (typeof image === 'string') {
|
||||||
|
// Input is a local path.
|
||||||
destImagePath = image
|
destImagePath = image
|
||||||
} else {
|
} 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)
|
destImagePath = await moveImageToFolder(pathname, image, resolvedImageFolderPath)
|
||||||
|
|
||||||
// Respect user preferences if file exist on disk.
|
// Respect user preferences if tab exists on disk.
|
||||||
if (cwd && imagePreferRelativeDirectory) {
|
if (isTabSavedOnDisk && imagePreferRelativeDirectory) {
|
||||||
destImagePath = await moveToRelativeFolder(cwd, destImagePath, resolvedImageRelativeDirectoryName)
|
destImagePath = await moveToRelativeFolder(relativeBasePath, resolvedImageRelativeDirectoryName, pathname, destImagePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
:regexValidator="/^(?:$|(?![a-zA-Z]:)[^\/\\].*$)/"
|
:regexValidator="/^(?:$|(?![a-zA-Z]:)[^\/\\].*$)/"
|
||||||
:defaultValue="relativeDirectoryNamePlaceholder"
|
:defaultValue="relativeDirectoryNamePlaceholder"
|
||||||
:onChange="value => onSelectChange('imageRelativeDirectoryName', value)"></text-box>
|
: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>
|
</template>
|
||||||
</compound>
|
</compound>
|
||||||
</section>
|
</section>
|
||||||
@ -77,3 +80,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.image-folder .footnote {
|
||||||
|
font-size: 13px;
|
||||||
|
& code {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<div class="pref-image">
|
<div class="pref-image">
|
||||||
<h4>Image</h4>
|
<h4>Image</h4>
|
||||||
<section class="image-ctrl">
|
<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'
|
<el-tooltip class='item' effect='dark'
|
||||||
content='Clipboard handling is only fully supported on macOS and Windows.'
|
content='Clipboard handling is only fully supported on macOS and Windows.'
|
||||||
placement='top-start'>
|
placement='top-start'>
|
||||||
|
@ -33,12 +33,21 @@ export const getContentHash = content => {
|
|||||||
return getHash(content, 'utf8', 'sha1')
|
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) {
|
if (!relativeName) {
|
||||||
// Use fallback name according settings description
|
// Use fallback name according settings description
|
||||||
relativeName = 'assets'
|
relativeName = 'assets'
|
||||||
} else if (path.isAbsolute(relativeName)) {
|
} else if (path.isAbsolute(relativeName)) {
|
||||||
throw new Error('Invalid relative directory name')
|
throw new Error('Invalid relative directory name.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path combination:
|
// Path combination:
|
||||||
@ -49,8 +58,8 @@ export const moveToRelativeFolder = async (cwd, imagePath, relativeName) => {
|
|||||||
await fs.ensureDir(absPath)
|
await fs.ensureDir(absPath)
|
||||||
await fs.move(imagePath, dstPath, { overwrite: true })
|
await fs.move(imagePath, dstPath, { overwrite: true })
|
||||||
|
|
||||||
// dstRelPath: relative directory name + image file name
|
// Find relative path between given file and saved image.
|
||||||
const dstRelPath = path.join(relativeName, path.basename(imagePath))
|
const dstRelPath = path.relative(path.dirname(filePath), dstPath)
|
||||||
|
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
// Use forward slashes for better compatibility with websites.
|
// Use forward slashes for better compatibility with websites.
|
||||||
|
Loading…
Reference in New Issue
Block a user