mirror of
https://github.com/marktext/marktext.git
synced 2025-05-02 12:22:26 +08:00
refactor: main filesystem code (#1104)
This commit is contained in:
parent
1a92d2de1b
commit
ddc99aa00e
20
.github/CONTRIBUTING.md
vendored
20
.github/CONTRIBUTING.md
vendored
@ -114,16 +114,22 @@ For more scripts please see `package.json`.
|
||||
|
||||
- ES6 and "best practices"
|
||||
- 2 space indent
|
||||
- no semicolons
|
||||
- JSDoc for documentation
|
||||
|
||||
## Project Structure
|
||||
|
||||
- root: Configuration files
|
||||
- `.`: Configuration files
|
||||
- `package.json`: Project settings
|
||||
- `build`: Contains generated binaries
|
||||
- `dist`: Build files for deployment
|
||||
- `docs`: Documentation and assets
|
||||
- `node_modules`: Dependencies
|
||||
- `build/`: Contains generated binaries
|
||||
- `dist/`: Build files for deployment
|
||||
- `docs/`: Documentation and assets
|
||||
- `resources/`: Application assets using at build time
|
||||
- `node_modules/`: Dependencies
|
||||
- `src`: Mark Text source code
|
||||
- `static`: Application assets (images, themes, etc)
|
||||
- `test`: Contains (unit) tests
|
||||
- `common/`: Common source files that only require Node.js APIs. Code from this folder can be used in all other folders except `muya`.
|
||||
- `main/`: Main process source files that require Electron main-process APIs. `main` files can use `common` source code.
|
||||
- `muya/`: Mark Texts backend that only allow pure JavaScript, BOM and DOM APIs. Don't use Electron or Node.js APIs!
|
||||
- `renderer`: Fontend that require Electron renderer-process APIs and may use `common` or `muya` source code.
|
||||
- `static/`: Application assets (images, themes, etc)
|
||||
- `test/`: Contains (unit) tests
|
||||
|
71
src/common/filesystem/index.js
Normal file
71
src/common/filesystem/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
import fs from 'fs-extra'
|
||||
|
||||
/**
|
||||
* Test whether or not the given path exists.
|
||||
*
|
||||
* @param {string} p The path to the file or directory.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const exists = async p => {
|
||||
// Nodes fs.exists is deprecated.
|
||||
try {
|
||||
await fs.access(p)
|
||||
return true
|
||||
} catch(_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a directory exist.
|
||||
*
|
||||
* @param {string} dirPath The directory path.
|
||||
*/
|
||||
export const ensureDirSync = dirPath => {
|
||||
try {
|
||||
fs.ensureDirSync(dirPath)
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a directory with read access.
|
||||
*
|
||||
* @param {string} dirPath The directory path.
|
||||
*/
|
||||
export const isDirectory = dirPath => {
|
||||
try {
|
||||
return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a file with read access.
|
||||
*
|
||||
* @param {string} filepath The file path.
|
||||
*/
|
||||
export const isFile = filepath => {
|
||||
try {
|
||||
return fs.existsSync(filepath) && fs.lstatSync(filepath).isFile()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a symbolic link with read access.
|
||||
*
|
||||
* @param {string} filepath The link path.
|
||||
*/
|
||||
export const isSymbolicLink = filepath => {
|
||||
try {
|
||||
return fs.existsSync(filepath) && fs.lstatSync(filepath).isSymbolicLink()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
116
src/common/filesystem/paths.js
Normal file
116
src/common/filesystem/paths.js
Normal file
@ -0,0 +1,116 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { isFile, isSymbolicLink } from './index'
|
||||
|
||||
export const MARKDOWN_EXTENSIONS = [
|
||||
'markdown',
|
||||
'mdown',
|
||||
'mkdn',
|
||||
'md',
|
||||
'mkd',
|
||||
'mdwn',
|
||||
'mdtxt',
|
||||
'mdtext',
|
||||
'text',
|
||||
'txt'
|
||||
]
|
||||
|
||||
export const IMAGE_EXTENSIONS = [
|
||||
'jpeg',
|
||||
'jpg',
|
||||
'png',
|
||||
'gif',
|
||||
'svg',
|
||||
'webp'
|
||||
]
|
||||
|
||||
/**
|
||||
* Returns true if the filename matches one of the markdown extensions.
|
||||
*
|
||||
* @param {string} filename Path or filename
|
||||
*/
|
||||
export const hasMarkdownExtension = filename => {
|
||||
if (!filename || typeof filename !== 'string') return false
|
||||
return MARKDOWN_EXTENSIONS.some(ext => filename.endsWith(`.${ext}`))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ture if the path is an image file.
|
||||
*
|
||||
* @param {string} filepath The path
|
||||
*/
|
||||
export const isImageFile = filepath => {
|
||||
const extname = path.extname(filepath)
|
||||
return isFile(filepath) && IMAGE_EXTENSIONS.some(ext => {
|
||||
const EXT_REG = new RegExp(ext, 'i')
|
||||
return EXT_REG.test(extname)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a markdown file.
|
||||
*
|
||||
* @param {string} filepath The path or link path.
|
||||
*/
|
||||
export const isMarkdownFile = filepath => {
|
||||
return isFile(filepath) && hasMarkdownExtension(filepath)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the path is a markdown file or symbolic link to a markdown file.
|
||||
*
|
||||
* @param {string} filepath The path or link path.
|
||||
*/
|
||||
export const isMarkdownFileOrLink = filepath => {
|
||||
if (!isFile(filepath)) return false
|
||||
if (hasMarkdownExtension(filepath)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Symbolic link to a markdown file
|
||||
if (isSymbolicLink(filepath)) {
|
||||
const targetPath = fs.readlinkSync(filepath)
|
||||
return isFile(targetPath) && hasMarkdownExtension(targetPath)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the both paths point to the same file.
|
||||
*
|
||||
* @param {string} pathA The first path.
|
||||
* @param {string} pathB The second path.
|
||||
* @param {boolean} [isNormalized] Are both paths already normalized.
|
||||
*/
|
||||
export const isSamePathSync = (pathA, pathB, isNormalized = false) => {
|
||||
if (!pathA || !pathB) return false
|
||||
const a = isNormalized ? pathA : path.normalize(pathA)
|
||||
const b = isNormalized ? pathB : path.normalize(pathB)
|
||||
if (a.length !== b.length) {
|
||||
return false
|
||||
} else if (a === b) {
|
||||
return true
|
||||
} else if (a.toLowerCase() === b.toLowerCase()) {
|
||||
try {
|
||||
const fiA = fs.statSync(a)
|
||||
const fiB = fs.statSync(b)
|
||||
return fiA.ino === fiB.ino
|
||||
} catch (_) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a file or directory is a child of the given directory.
|
||||
*
|
||||
* @param {string} dir The parent directory.
|
||||
* @param {string} child The file or directory path to check.
|
||||
*/
|
||||
export const isChildOfDirectory = (dir, child) => {
|
||||
if (!dir || !child) return false
|
||||
const relative = path.relative(dir, child)
|
||||
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
|
||||
}
|
@ -4,9 +4,9 @@ import { exec } from 'child_process'
|
||||
import dayjs from 'dayjs'
|
||||
import log from 'electron-log'
|
||||
import { app, BrowserWindow, clipboard, dialog, ipcMain, systemPreferences } from 'electron'
|
||||
import { isChildOfDirectory } from 'common/filesystem/paths'
|
||||
import { isLinux, isOsx } from '../config'
|
||||
import parseArgs from '../cli/parser'
|
||||
import { isChildOfDirectory } from '../filesystem'
|
||||
import { normalizeMarkdownPath } from '../filesystem/markdown'
|
||||
import { getMenuItemById } from '../menu'
|
||||
import { selectTheme } from '../menu/actions/theme'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { app } from 'electron'
|
||||
import EnvPaths from 'common/envPaths'
|
||||
import { ensureDirSync } from '../filesystem'
|
||||
import { ensureDirSync } from 'common/filesystem'
|
||||
|
||||
class AppPaths extends EnvPaths {
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import path from 'path'
|
||||
import os from 'os'
|
||||
import { isDirectory } from '../filesystem'
|
||||
import { isDirectory } from 'common/filesystem'
|
||||
import parseArgs from './parser'
|
||||
import { dumpKeyboardInformation } from '../keyboard'
|
||||
import { getPath } from '../utils'
|
||||
|
@ -34,28 +34,6 @@ export const defaultPreferenceWinOptions = {
|
||||
titleBarStyle: 'hiddenInset'
|
||||
}
|
||||
|
||||
export const EXTENSIONS = [
|
||||
'markdown',
|
||||
'mdown',
|
||||
'mkdn',
|
||||
'md',
|
||||
'mkd',
|
||||
'mdwn',
|
||||
'mdtxt',
|
||||
'mdtext',
|
||||
'text',
|
||||
'txt'
|
||||
]
|
||||
|
||||
export const IMAGE_EXTENSIONS = [
|
||||
'jpeg',
|
||||
'jpg',
|
||||
'png',
|
||||
'gif',
|
||||
'svg',
|
||||
'webp'
|
||||
]
|
||||
|
||||
export const PANDOC_EXTENSIONS = [
|
||||
'html',
|
||||
'docx',
|
||||
@ -72,12 +50,6 @@ export const PANDOC_EXTENSIONS = [
|
||||
'epub'
|
||||
]
|
||||
|
||||
// export const PROJECT_BLACK_LIST = [
|
||||
// 'node_modules',
|
||||
// '.git',
|
||||
// '.DS_Store'
|
||||
// ]
|
||||
|
||||
export const BLACK_LIST = [
|
||||
'$RECYCLE.BIN'
|
||||
]
|
||||
|
@ -6,8 +6,8 @@ import keytar from 'keytar'
|
||||
import schema from './schema'
|
||||
import Store from 'electron-store'
|
||||
import log from 'electron-log'
|
||||
import { ensureDirSync } from '../filesystem'
|
||||
import { IMAGE_EXTENSIONS } from '../config'
|
||||
import { ensureDirSync } from 'common/filesystem'
|
||||
import { IMAGE_EXTENSIONS } from 'common/filesystem/paths'
|
||||
|
||||
const DATA_CENTER_NAME = 'dataCenter'
|
||||
|
||||
@ -104,7 +104,7 @@ class DataCenter extends EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param {string} key
|
||||
* return a promise
|
||||
*/
|
||||
|
@ -1,156 +1,6 @@
|
||||
import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import { hasMarkdownExtension } from '../utils'
|
||||
import { IMAGE_EXTENSIONS } from '../config'
|
||||
|
||||
/**
|
||||
* Test whether or not the given path exists.
|
||||
*
|
||||
* @param {string} p The path to the file or directory.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export const exists = async p => {
|
||||
// fs.exists is deprecated.
|
||||
try {
|
||||
await fs.access(p)
|
||||
return true
|
||||
} catch(_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a directory exist.
|
||||
*
|
||||
* @param {string} dirPath The directory path.
|
||||
*/
|
||||
export const ensureDirSync = dirPath => {
|
||||
try {
|
||||
fs.ensureDirSync(dirPath)
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a directory with read access.
|
||||
*
|
||||
* @param {string} dirPath The directory path.
|
||||
*/
|
||||
export const isDirectory = dirPath => {
|
||||
try {
|
||||
return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a file with read access.
|
||||
*
|
||||
* @param {string} filepath The file path.
|
||||
*/
|
||||
export const isFile = filepath => {
|
||||
try {
|
||||
return fs.existsSync(filepath) && fs.lstatSync(filepath).isFile()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a symbolic link with read access.
|
||||
*
|
||||
* @param {string} filepath The link path.
|
||||
*/
|
||||
export const isSymbolicLink = filepath => {
|
||||
try {
|
||||
return fs.existsSync(filepath) && fs.lstatSync(filepath).isSymbolicLink()
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a markdown file.
|
||||
*
|
||||
* @param {string} filepath The path or link path.
|
||||
*/
|
||||
export const isMarkdownFile = filepath => {
|
||||
return isFile(filepath) && hasMarkdownExtension(filepath)
|
||||
}
|
||||
/**
|
||||
* Returns ture if the path is an image file.
|
||||
*
|
||||
* @param {string} filepath The path
|
||||
*/
|
||||
export const isImageFile = filepath => {
|
||||
const extname = path.extname(filepath)
|
||||
return isFile(filepath) && IMAGE_EXTENSIONS.some(ext => {
|
||||
const EXT_REG = new RegExp(ext, 'i')
|
||||
return EXT_REG.test(extname)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the path is a markdown file or symbolic link to a markdown file.
|
||||
*
|
||||
* @param {string} filepath The path or link path.
|
||||
*/
|
||||
export const isMarkdownFileOrLink = filepath => {
|
||||
if (!isFile(filepath)) return false
|
||||
if (hasMarkdownExtension(filepath)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Symbolic link to a markdown file
|
||||
if (isSymbolicLink(filepath)) {
|
||||
const targetPath = fs.readlinkSync(filepath)
|
||||
return isFile(targetPath) && hasMarkdownExtension(targetPath)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the both paths point to the same file.
|
||||
*
|
||||
* @param {string} pathA The first path.
|
||||
* @param {string} pathB The second path.
|
||||
* @param {boolean} [isNormalized] Are both paths already normalized.
|
||||
*/
|
||||
export const isSamePathSync = (pathA, pathB, isNormalized = false) => {
|
||||
if (!pathA || !pathB) return false
|
||||
const a = isNormalized ? pathA : path.normalize(pathA)
|
||||
const b = isNormalized ? pathB : path.normalize(pathB)
|
||||
if (a.length !== b.length) {
|
||||
return false
|
||||
} else if (a === b) {
|
||||
return true
|
||||
} else if (a.toLowerCase() === b.toLowerCase()) {
|
||||
try {
|
||||
const fiA = fs.statSync(a)
|
||||
const fiB = fs.statSync(b)
|
||||
return fiA.ino === fiB.ino
|
||||
} catch (_) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a file or directory is a child of the given directory.
|
||||
*
|
||||
* @param {string} dir The parent directory.
|
||||
* @param {string} child The file or directory path to check.
|
||||
*/
|
||||
export const isChildOfDirectory = (dir, child) => {
|
||||
if (!dir || !child) return false
|
||||
const relative = path.relative(dir, child)
|
||||
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
|
||||
}
|
||||
import { isDirectory, isFile, isSymbolicLink } from 'common/filesystem'
|
||||
|
||||
/**
|
||||
* Normalize the path into an absolute path and resolves the link target if needed.
|
||||
|
@ -2,7 +2,9 @@ import fs from 'fs-extra'
|
||||
import path from 'path'
|
||||
import log from 'electron-log'
|
||||
import { LINE_ENDING_REG, LF_LINE_ENDING_REG, CRLF_LINE_ENDING_REG } from '../config'
|
||||
import { isDirectory, isMarkdownFileOrLink, normalizeAndResolvePath , writeFile } from '../filesystem'
|
||||
import { isDirectory } from 'common/filesystem'
|
||||
import { isMarkdownFileOrLink } from 'common/filesystem/paths'
|
||||
import { normalizeAndResolvePath, writeFile } from '../filesystem'
|
||||
|
||||
const getLineEnding = lineEnding => {
|
||||
if (lineEnding === 'lf') {
|
||||
|
@ -2,8 +2,9 @@ import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import log from 'electron-log'
|
||||
import chokidar from 'chokidar'
|
||||
import { getUniqueId, hasMarkdownExtension } from '../utils'
|
||||
import { exists } from '../filesystem'
|
||||
import { exists } from 'common/filesystem'
|
||||
import { hasMarkdownExtension } from 'common/filesystem/paths'
|
||||
import { getUniqueId } from '../utils'
|
||||
import { loadMarkdownFile } from '../filesystem/markdown'
|
||||
import { isLinux } from '../config'
|
||||
|
||||
|
@ -4,9 +4,9 @@ import path from 'path'
|
||||
import log from 'electron-log'
|
||||
import isAccelerator from 'electron-is-accelerator'
|
||||
import electronLocalshortcut from '@hfelix/electron-localshortcut'
|
||||
import { isFile } from 'common/filesystem'
|
||||
import { isOsx } from '../config'
|
||||
import { getKeyboardLanguage, getVirtualLetters } from '../keyboard'
|
||||
import { isFile } from '../filesystem'
|
||||
|
||||
// Problematic key bindings:
|
||||
// Aidou: Ctrl+/ -> dead key
|
||||
|
@ -3,8 +3,10 @@ import path from 'path'
|
||||
import { promisify } from 'util'
|
||||
import { BrowserWindow, dialog, ipcMain, shell } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import { EXTENSION_HASN, EXTENSIONS, PANDOC_EXTENSIONS, URL_REG } from '../../config'
|
||||
import { isDirectory, isFile, isMarkdownFile, isMarkdownFileOrLink, normalizeAndResolvePath, writeFile } from '../../filesystem'
|
||||
import { isDirectory, isFile } from 'common/filesystem'
|
||||
import { MARKDOWN_EXTENSIONS, isMarkdownFile, isMarkdownFileOrLink } from 'common/filesystem/paths'
|
||||
import { EXTENSION_HASN, PANDOC_EXTENSIONS, URL_REG } from '../../config'
|
||||
import { normalizeAndResolvePath, writeFile } from '../../filesystem'
|
||||
import { writeMarkdownFile } from '../../filesystem/markdown'
|
||||
import { getPath, getRecommendTitleFromMarkdownString } from '../../utils'
|
||||
import pandoc from '../../utils/pandoc'
|
||||
@ -417,7 +419,7 @@ export const openFile = win => {
|
||||
properties: ['openFile', 'multiSelections'],
|
||||
filters: [{
|
||||
name: 'text',
|
||||
extensions: EXTENSIONS
|
||||
extensions: MARKDOWN_EXTENSIONS
|
||||
}]
|
||||
}, paths => {
|
||||
if (paths && Array.isArray(paths)) {
|
||||
|
@ -2,8 +2,8 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { app, ipcMain, Menu } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import { ensureDirSync, isDirectory, isFile } from 'common/filesystem'
|
||||
import { isLinux } from '../config'
|
||||
import { ensureDirSync, isDirectory, isFile } from '../filesystem'
|
||||
import { parseMenu } from '../keyboard/shortcutHandler'
|
||||
import configureMenu, { configSettingMenu } from '../menu/templates'
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import path from 'path'
|
||||
import { shell } from 'electron'
|
||||
import { isFile } from 'common/filesystem'
|
||||
import * as actions from '../actions/help'
|
||||
import { checkUpdates } from '../actions/marktext'
|
||||
import { isFile } from '../../filesystem'
|
||||
|
||||
export default function () {
|
||||
const helpMenu = {
|
||||
|
@ -2,8 +2,9 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { filter } from 'fuzzaldrin'
|
||||
import log from 'electron-log'
|
||||
import { IMAGE_EXTENSIONS, BLACK_LIST } from '../config'
|
||||
import { isDirectory, isFile } from '../filesystem'
|
||||
import { isDirectory, isFile } from 'common/filesystem'
|
||||
import { IMAGE_EXTENSIONS } from 'common/filesystem/paths'
|
||||
import { BLACK_LIST } from '../config'
|
||||
|
||||
// TODO(need::refactor): Refactor this file. Just return an array of directories and files without caching and watching?
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { app } from 'electron'
|
||||
import { EXTENSIONS } from '../config'
|
||||
|
||||
const ID_PREFIX = 'mt-'
|
||||
let id = 0
|
||||
@ -37,16 +36,6 @@ export const getPath = name => {
|
||||
return app.getPath(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the filename matches one of the markdown extensions.
|
||||
*
|
||||
* @param {string} filename Path or filename
|
||||
*/
|
||||
export const hasMarkdownExtension = filename => {
|
||||
if (!filename || typeof filename !== 'string') return false
|
||||
return EXTENSIONS.some(ext => filename.endsWith(`.${ext}`))
|
||||
}
|
||||
|
||||
export const hasSameKeys = (a, b) => {
|
||||
const aKeys = Object.keys(a).sort()
|
||||
const bKeys = Object.keys(b).sort()
|
||||
|
@ -2,10 +2,10 @@ import path from 'path'
|
||||
import { BrowserWindow, dialog, ipcMain } from 'electron'
|
||||
import log from 'electron-log'
|
||||
import windowStateKeeper from 'electron-window-state'
|
||||
import { isChildOfDirectory, isSamePathSync } from 'common/filesystem/paths'
|
||||
import BaseWindow, { WindowLifecycle, WindowType } from './base'
|
||||
import { ensureWindowPosition } from './utils'
|
||||
import { TITLE_BAR_HEIGHT, editorWinOptions, isLinux, isOsx } from '../config'
|
||||
import { isChildOfDirectory, isSamePathSync } from '../filesystem'
|
||||
import { loadMarkdownFile } from '../filesystem/markdown'
|
||||
|
||||
class EditorWindow extends BaseWindow {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { clipboard, ipcRenderer, shell } from 'electron'
|
||||
import path from 'path'
|
||||
import equal from 'deep-equal'
|
||||
import { isSamePathSync } from 'common/filesystem/paths'
|
||||
import bus from '../bus'
|
||||
import { hasKeys, getUniqueId } from '../util'
|
||||
import { isSamePathSync } from '../util/fileSystem'
|
||||
import listToTree from '../util/listToTree'
|
||||
import { createDocumentState, getOptionsFromState, getSingleFileState, getBlankFileState } from './help'
|
||||
import notice from '../services/notification'
|
||||
|
@ -2,7 +2,7 @@ import path from 'path'
|
||||
import fse from 'fs-extra'
|
||||
import dayjs from 'dayjs'
|
||||
import Octokit from '@octokit/rest'
|
||||
import { isImageFile } from '../../main/filesystem'
|
||||
import { isImageFile } from 'common/filesystem/paths'
|
||||
import { dataURItoBlob, getContentHash } from './index'
|
||||
import axios from 'axios'
|
||||
|
||||
@ -22,33 +22,6 @@ export const rename = (src, dest) => {
|
||||
return fse.move(src, dest)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the both paths point to the same file.
|
||||
*
|
||||
* @param {string} pathA The first path.
|
||||
* @param {string} pathB The second path.
|
||||
* @param {boolean} [isNormalized] Are both paths already normalized.
|
||||
*/
|
||||
export const isSamePathSync = (pathA, pathB, isNormalized = false) => {
|
||||
if (!pathA || !pathB) return false
|
||||
const a = isNormalized ? pathA : path.normalize(pathA)
|
||||
const b = isNormalized ? pathB : path.normalize(pathB)
|
||||
if (a.length !== b.length) {
|
||||
return false
|
||||
} else if (a === b) {
|
||||
return true
|
||||
} else if (a.toLowerCase() === b.toLowerCase()) {
|
||||
try {
|
||||
const fiA = fse.statSync(a)
|
||||
const fiB = fse.statSync(b)
|
||||
return fiA.ino === fiB.ino
|
||||
} catch (_) {
|
||||
// Ignore error
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const moveImageToFolder = async (pathname, image, dir) => {
|
||||
const isPath = typeof image === 'string'
|
||||
if (isPath) {
|
||||
|
Loading…
Reference in New Issue
Block a user