mirror of
https://github.com/marktext/marktext.git
synced 2025-05-03 05:09:56 +08:00
added option to use a command line script as image uploader (#2100)
This commit is contained in:
parent
4c517b1632
commit
2d15933c53
@ -53,6 +53,19 @@
|
||||
<el-button size="mini" :disabled="githubDisable" @click="setCurrentUploader('github')">Set as default</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Command-line Script" name="cliScript">
|
||||
<div class="description">The script will be executed with the image file path as its only argument and it should output any valid value for the <code>src</code> attribute of a <em>HTMLImageElement</em>.</div>
|
||||
<div class="form-group">
|
||||
<div class="label">
|
||||
Shell script location
|
||||
</div>
|
||||
<el-input v-model="cliScript" placeholder="Script absolute path" size="mini"></el-input>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<el-button size="mini" :disabled="cliScriptDisable" @click="save('cliScript')">Save</el-button>
|
||||
<el-button size="mini" :disabled="cliScriptDisable" @click="setCurrentUploader('cliScript')">Set as default</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</section>
|
||||
</div>
|
||||
@ -62,6 +75,7 @@
|
||||
import { shell } from 'electron'
|
||||
import services, { isValidService } from './services.js'
|
||||
import legalNoticesCheckbox from './legalNoticesCheckbox'
|
||||
import { isFileExecutable } from '../../util/fileSystem'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -76,6 +90,7 @@ export default {
|
||||
repo: '',
|
||||
branch: ''
|
||||
},
|
||||
cliScript: '',
|
||||
uploadServices: services,
|
||||
legalNoticesErrorStates: {
|
||||
smms: false,
|
||||
@ -99,8 +114,19 @@ export default {
|
||||
return this.$store.state.preferences.githubToken
|
||||
}
|
||||
},
|
||||
prefCliScript: {
|
||||
get: function () {
|
||||
return this.$store.state.preferences.cliScript
|
||||
}
|
||||
},
|
||||
githubDisable () {
|
||||
return !this.githubToken || !this.github.owner || !this.github.repo
|
||||
},
|
||||
cliScriptDisable () {
|
||||
if (!this.cliScript) {
|
||||
return true
|
||||
}
|
||||
return !isFileExecutable(this.cliScript)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -114,6 +140,7 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
this.github = this.imageBed.github
|
||||
this.githubToken = this.prefGithubToken
|
||||
this.cliScript = this.prefCliScript
|
||||
|
||||
if (services.hasOwnProperty(this.currentUploader)) {
|
||||
services[this.currentUploader].agreedToLegalNotices = true
|
||||
@ -143,11 +170,22 @@ export default {
|
||||
value: this.githubToken
|
||||
})
|
||||
}
|
||||
if (withNotice) {
|
||||
if (type === 'cliScript') {
|
||||
this.$store.dispatch('SET_USER_DATA', {
|
||||
type: 'cliScript',
|
||||
value: this.cliScript
|
||||
})
|
||||
}
|
||||
if (withNotice && type === 'github') {
|
||||
new Notification('Save Image Uploader', {
|
||||
body: 'The Github configration has been saved.'
|
||||
})
|
||||
}
|
||||
if (withNotice && type === 'cliScript') {
|
||||
new Notification('Save Image Uploader', {
|
||||
body: 'The command line script configuration has been saved'
|
||||
})
|
||||
}
|
||||
},
|
||||
setCurrentUploader (value) {
|
||||
const service = services[value]
|
||||
@ -162,10 +200,12 @@ export default {
|
||||
return
|
||||
}
|
||||
// Save the setting before set it as default uploader.
|
||||
if (value === 'github') {
|
||||
if (value === 'github' || value === 'cliScript') {
|
||||
this.save(value, false)
|
||||
}
|
||||
this.legalNoticesErrorStates[value] = false
|
||||
if (this.legalNoticesErrorStates[value] !== undefined) {
|
||||
this.legalNoticesErrorStates[value] = false
|
||||
}
|
||||
|
||||
const type = 'currentUploader'
|
||||
this.$store.dispatch('SET_USER_DATA', { type, value })
|
||||
|
@ -35,6 +35,14 @@ const services = {
|
||||
|
||||
// Currently a non-persistent value
|
||||
agreedToLegalNotices: false
|
||||
},
|
||||
|
||||
cliScript: {
|
||||
name: 'command line script',
|
||||
isGdprCompliant: true,
|
||||
privacyUrl: '',
|
||||
tosUrl: '',
|
||||
agreedToLegalNotices: true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,8 @@ const state = {
|
||||
repo: '',
|
||||
branch: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
cliScript: ''
|
||||
}
|
||||
|
||||
const getters = {}
|
||||
|
@ -6,6 +6,9 @@ import dayjs from 'dayjs'
|
||||
import { Octokit } from '@octokit/rest'
|
||||
import { ensureDirSync } from 'common/filesystem'
|
||||
import { isImageFile } from 'common/filesystem/paths'
|
||||
import cp from 'child_process'
|
||||
import { tmpdir } from 'os'
|
||||
import { unlink, writeFileSync, statSync, constants } from 'fs'
|
||||
import { isWindows, dataURItoBlob } from './index'
|
||||
import axios from '../axios'
|
||||
|
||||
@ -104,6 +107,7 @@ export const uploadImage = async (pathname, image, preferences) => {
|
||||
const { currentUploader } = preferences
|
||||
const { owner, repo, branch } = preferences.imageBed.github
|
||||
const token = preferences.githubToken
|
||||
const cliScript = preferences.cliScript
|
||||
const isPath = typeof image === 'string'
|
||||
const MAX_SIZE = 5 * 1024 * 1024
|
||||
let re
|
||||
@ -164,6 +168,25 @@ export const uploadImage = async (pathname, image, preferences) => {
|
||||
})
|
||||
}
|
||||
|
||||
const uploadByCliScript = (filepath, name = null) => {
|
||||
let isPath = true
|
||||
if (typeof filepath !== 'string') {
|
||||
isPath = false
|
||||
const data = new Uint8Array(filepath)
|
||||
filepath = path.join(tmpdir(), name || +new Date())
|
||||
writeFileSync(filepath, data)
|
||||
}
|
||||
cp.execFile(cliScript, [filepath], (err, data) => {
|
||||
if (!isPath) {
|
||||
unlink(filepath)
|
||||
}
|
||||
if (err) {
|
||||
return rj(err)
|
||||
}
|
||||
re(data.trim())
|
||||
})
|
||||
}
|
||||
|
||||
const notification = () => {
|
||||
rj('Cannot upload more than 5M image, the image will be copied to the image folder')
|
||||
}
|
||||
@ -177,6 +200,10 @@ export const uploadImage = async (pathname, image, preferences) => {
|
||||
if (size > MAX_SIZE) {
|
||||
notification()
|
||||
} else {
|
||||
if (currentUploader === 'cliScript') {
|
||||
uploadByCliScript(imagePath)
|
||||
return promise
|
||||
}
|
||||
const imageFile = await fs.readFile(imagePath)
|
||||
const blobFile = new Blob([imageFile])
|
||||
if (currentUploader === 'smms') {
|
||||
@ -196,17 +223,34 @@ export const uploadImage = async (pathname, image, preferences) => {
|
||||
} else {
|
||||
const reader = new FileReader()
|
||||
reader.onload = async () => {
|
||||
const blobFile = dataURItoBlob(reader.result, image.name)
|
||||
if (currentUploader === 'smms') {
|
||||
uploadToSMMS(blobFile)
|
||||
} else {
|
||||
uploadByGithub(reader.result, image.name)
|
||||
switch (currentUploader) {
|
||||
case 'cliScript':
|
||||
uploadByCliScript(reader.result, image.name)
|
||||
break
|
||||
|
||||
case 'smms':
|
||||
uploadToSMMS(dataURItoBlob(reader.result, image.name))
|
||||
break
|
||||
|
||||
default:
|
||||
uploadByGithub(reader.result, image.name)
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsDataURL(image)
|
||||
const readerFunction = currentUploader === 'cliScript' ? 'readAsArrayBuffer' : 'readAsDataURL'
|
||||
reader[readerFunction](image)
|
||||
}
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
export const isFileExecutable = (filepath) => {
|
||||
try {
|
||||
const stat = statSync(filepath)
|
||||
return stat.isFile() && (stat.mode & (constants.S_IXUSR | constants.S_IXGRP | constants.S_IXOTH)) !== 0
|
||||
} catch (err) {
|
||||
// err ignored
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user