mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
Merge branch 'main' of https://github.com/doocs/md
This commit is contained in:
commit
69175a72f2
20
.github/workflows/preview.yml
vendored
Normal file
20
.github/workflows/preview.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: Surge Preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'doocs/md'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: afc163/surge-preview@main
|
||||
with:
|
||||
surge_token: ${{ secrets.SURGE_TOKEN }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
dist: dist
|
||||
build: |
|
||||
npm install
|
||||
npm run build:h5-netlify
|
45
README.md
45
README.md
@ -68,6 +68,7 @@ npm run build:h5-netlify
|
||||
- [x] 支持 <kbd>Ctrl</kbd> + <kbd>F</kbd> 快速格式化文档
|
||||
- [x] 支持色盘取色,快速替换文章整体色调
|
||||
- [x] 支持多图上传,可自定义配置图床
|
||||
- [x] 支持自定义上传逻辑
|
||||
- [x] 支持在编辑框右键弹出功能选项卡
|
||||
|
||||
## 目前支持哪些图床
|
||||
@ -80,6 +81,7 @@ npm run build:h5-netlify
|
||||
| 4 | [阿里云](https://www.aliyun.com/product/oss) | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 参数 | [如何使用阿里云 OSS?](https://help.aliyun.com/document_detail/31883.html) |
|
||||
| 5 | [腾讯云](https://cloud.tencent.com/act/pro/cos) | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 参数 | [如何使用腾讯云 COS?](https://cloud.tencent.com/document/product/436/38484) |
|
||||
| 6 | [七牛云](https://www.qiniu.com/products/kodo) | 配置 `AccessKey`、`SecretKey`、`Bucket`、`Domain`、`Region` 参数 | [如何使用七牛云 Kodo?](https://developer.qiniu.com/kodo) |
|
||||
| - | 自定义上传逻辑 | 是 | 参考[自定义上传逻辑参数详情](#自定义上传逻辑) |
|
||||
|
||||
![select-and-change-color-theme](https://doocs.oss-cn-shenzhen.aliyuncs.com/img//1606034542281-a8c99fa7-c11e-4e43-98da-e36012f54dc8.gif)
|
||||
|
||||
@ -89,6 +91,49 @@ npm run build:h5-netlify
|
||||
|
||||
![doocs-md-upload-image](https://doocs.oss-cn-shenzhen.aliyuncs.com/img//1606034542512-0769a336-b9eb-4d58-83c1-29db7b54f71b.gif)
|
||||
|
||||
## 自定义上传逻辑
|
||||
|
||||
在工具上没有提供预定义图床的情况下,你只需要自定义上传逻辑即可,这对于例如你不方便使用公共图床,而是使用自己的上传服务时非常有用。
|
||||
|
||||
你只需要在给定的函数中更改上传代码即可,为了方便,这个函数提供了可能使用的一些参数:
|
||||
|
||||
示例代码:
|
||||
|
||||
```js
|
||||
const {file, util, okCb, errCb} = CUSTOM_ARG
|
||||
const param = new FormData()
|
||||
param.append('file', file)
|
||||
util.axios.post('http://127.0.0.1:9000/upload', param, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
}).then(res => {
|
||||
okCb(res.url)
|
||||
}).catch(err => {
|
||||
errCb(err)
|
||||
})
|
||||
|
||||
// 提供的可用参数:
|
||||
// CUSTOM_ARG = {
|
||||
// content, // 待上传图片的 base64
|
||||
// file, // 待上传图片的 file 对象
|
||||
// util: {
|
||||
// axios, // axios 实例
|
||||
// CryptoJS, // 加密库
|
||||
// OSS, // ali-oss
|
||||
// COS, // cos-js-sdk-v5
|
||||
// Buffer, // buffer-from
|
||||
// uuidv4, // uuid
|
||||
// qiniu, // qiniu-js
|
||||
// tokenTools, // 一些编码转换函数
|
||||
// getDir, // 获取 年/月/日 形式的目录
|
||||
// getDateFilename, // 根据文件名获取它以 时间戳+uuid 的形式
|
||||
// },
|
||||
// okCb: resolve, // 重要: 上传成功后给此回调传 url 即可
|
||||
// errCb: reject, // 上传失败调用的函数
|
||||
// }
|
||||
```
|
||||
|
||||
如果你创建了适用于其他第三方图床的上传代码,我们非常欢迎你分享它。
|
||||
|
||||
## 注意事项
|
||||
|
||||
如果你使用了某些浏览器脚本修改了网页背景色,可能导致渲染后的文章出现背景色分块的现象,详见 [#63](https://github.com/doocs/md/issues/63)。
|
||||
|
30
mm.config.js
30
mm.config.js
@ -3,15 +3,25 @@
|
||||
* https://hongqiye.com/doc/mockm/config/option.html
|
||||
* @type {import('mockm/@types/config').Config}
|
||||
*/
|
||||
module.exports = {
|
||||
static: [
|
||||
{ // 测试 netlify 部署
|
||||
fileDir: `./dist`,
|
||||
path: `/`,
|
||||
module.exports = (util) => {
|
||||
return {
|
||||
api: {
|
||||
'/upload'(req, res) {
|
||||
res.json({
|
||||
msg: `上传成功`,
|
||||
url: util.libObj.mockjs.mock(`@image`),
|
||||
})
|
||||
},
|
||||
},
|
||||
{ // 测试 gitee/github 部署
|
||||
fileDir: `./dist`,
|
||||
path: `/md`,
|
||||
},
|
||||
],
|
||||
static: [
|
||||
{ // 测试 netlify 部署
|
||||
fileDir: `./dist`,
|
||||
path: `/`,
|
||||
},
|
||||
{ // 测试 gitee/github 部署
|
||||
fileDir: `./dist`,
|
||||
path: `/md`,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import Buffer from "buffer-from";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import * as qiniu from "qiniu-js";
|
||||
import { utf16to8, base64encode, safe64 } from "../assets/scripts/tokenTools";
|
||||
import * as tokenTools from "../assets/scripts/tokenTools";
|
||||
|
||||
function getConfig(useDefault, platform) {
|
||||
if (useDefault) {
|
||||
@ -42,6 +43,10 @@ function getConfig(useDefault, platform) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 `年/月/日` 形式的目录
|
||||
* @returns string
|
||||
*/
|
||||
function getDir() {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
@ -50,6 +55,11 @@ function getDir() {
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件名获取它以 `时间戳+uuid` 的形式
|
||||
* @param {string} filename 文件名
|
||||
* @returns
|
||||
*/
|
||||
function getDateFilename(filename) {
|
||||
const currentTimestamp = new Date().getTime();
|
||||
const fileSuffix = filename.split(".")[1];
|
||||
@ -216,6 +226,42 @@ async function txCOSFileUpload(file) {
|
||||
});
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// formCustom File Upload
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
async function formCustomUpload(content, file) {
|
||||
const str = `
|
||||
async (CUSTOM_ARG) => {
|
||||
${localStorage.getItem(`formCustomConfig`)}
|
||||
}
|
||||
`
|
||||
return new Promise((resolve, reject) => {
|
||||
const exportObj = {
|
||||
content, // 待上传图片的 base64
|
||||
file, // 待上传图片的 file 对象
|
||||
util: {
|
||||
axios: fetch, // axios 实例
|
||||
CryptoJS, // 加密库
|
||||
OSS, // ali-oss
|
||||
COS, // cos-js-sdk-v5
|
||||
Buffer, // buffer-from
|
||||
uuidv4, // uuid
|
||||
qiniu, // qiniu-js
|
||||
tokenTools, // 一些编码转换函数
|
||||
getDir, // 获取 年/月/日 形式的目录
|
||||
getDateFilename, // 根据文件名获取它以 时间戳+uuid 的形式
|
||||
},
|
||||
okCb: resolve, // 重要: 上传成功后给此回调传 url 即可
|
||||
errCb: reject, // 上传失败调用的函数
|
||||
}
|
||||
eval(str)(exportObj).catch(err => {
|
||||
console.error(err)
|
||||
reject(err)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function fileUpload(content, file) {
|
||||
const imgHost = localStorage.getItem("imgHost");
|
||||
!imgHost && localStorage.setItem("imgHost", "default");
|
||||
@ -230,6 +276,8 @@ function fileUpload(content, file) {
|
||||
return giteeUpload(content, file.name);
|
||||
case "github":
|
||||
return ghFileUpload(content, file.name);
|
||||
case "formCustom":
|
||||
return formCustomUpload(content, file);
|
||||
default:
|
||||
// return file.size / 1024 < 1024
|
||||
// ? giteeUpload(content, file.name)
|
||||
|
@ -374,3 +374,21 @@ function getElementStyles(element, excludes = ["width", "height"]) {
|
||||
.map(([key, value]) => `${key}:${value};`)
|
||||
.join("");
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除左边多余空格
|
||||
* @param {*} str
|
||||
* @returns
|
||||
*/
|
||||
export function removeLeft(str) {
|
||||
const lines = str.split('\n')
|
||||
// 获取应该删除的空白符数量
|
||||
const minSpaceNum = lines.filter(item => item.trim())
|
||||
.map(item => item.match(/(^\s+)?/)[0].length)
|
||||
.sort((a, b) => a - b)[0]
|
||||
// 删除空白符
|
||||
const newStr = lines
|
||||
.map(item => item.slice(minSpaceNum))
|
||||
.join('\n')
|
||||
return newStr
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
:visible="value"
|
||||
@close="$emit('close')"
|
||||
>
|
||||
<el-tabs type="activeName" :value="'upload'">
|
||||
<el-tabs type="activeName" v-model="activeName">
|
||||
<el-tab-pane class="upload-panel" label="选择上传" name="upload">
|
||||
<el-select
|
||||
v-model="imgHost"
|
||||
@ -288,12 +288,42 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane class="github-panel formCustom" label="自定义代码" name="formCustom">
|
||||
<el-form
|
||||
class="setting-form"
|
||||
:model="formCustom"
|
||||
label-position="right"
|
||||
>
|
||||
<el-form-item label="" :required="true">
|
||||
<el-input
|
||||
class="formCustomElInput"
|
||||
ref="formCustomElInput"
|
||||
type="textarea"
|
||||
resize="none"
|
||||
placeholder="Your custom code here."
|
||||
v-model="formCustom.code">
|
||||
</el-input>
|
||||
<el-link
|
||||
type="primary"
|
||||
href="https://github.com/doocs/md#自定义上传逻辑"
|
||||
target="_blank"
|
||||
>参数详情?</el-link
|
||||
>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="formCustomSave"
|
||||
>保存配置</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { checkImage } from "../../assets/scripts/util";
|
||||
import { checkImage, removeLeft } from "../../assets/scripts/util";
|
||||
import CodeMirror from "codemirror/lib/codemirror";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -304,6 +334,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: `upload`,
|
||||
|
||||
formGitHub: {
|
||||
repo: "",
|
||||
branch: "",
|
||||
@ -337,6 +369,21 @@ export default {
|
||||
domain: "",
|
||||
region: "",
|
||||
},
|
||||
formCustom: {
|
||||
code: localStorage.getItem(`formCustomConfig`) || removeLeft(`
|
||||
const {file, util, okCb, errCb} = CUSTOM_ARG
|
||||
const param = new FormData()
|
||||
param.append('file', file)
|
||||
util.axios.post('http://127.0.0.1:9000/upload', param, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
}).then(res => {
|
||||
okCb(res.url)
|
||||
}).catch(err => {
|
||||
errCb(err)
|
||||
})
|
||||
`).trim(),
|
||||
editor: undefined,
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: "default",
|
||||
@ -362,6 +409,10 @@ export default {
|
||||
value: "qiniu",
|
||||
label: "七牛云",
|
||||
},
|
||||
{
|
||||
value: "formCustom",
|
||||
label: "自定义代码",
|
||||
},
|
||||
],
|
||||
imgHost: "default",
|
||||
};
|
||||
@ -454,6 +505,11 @@ export default {
|
||||
localStorage.setItem("qiniuConfig", JSON.stringify(this.formQiniu));
|
||||
this.$message.success("保存成功");
|
||||
},
|
||||
formCustomSave() {
|
||||
const str = this.formCustom.editor.getValue()
|
||||
localStorage.setItem(`formCustomConfig`, str)
|
||||
this.$message.success(`保存成功`)
|
||||
},
|
||||
|
||||
beforeImageUpload(file) {
|
||||
// check image
|
||||
@ -479,6 +535,25 @@ export default {
|
||||
this.$emit("uploadImage", params.file);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
activeName: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if(val === `formCustom`) {
|
||||
this.$nextTick(() => {
|
||||
const textarea = this.$refs.formCustomElInput.$el.querySelector(`textarea`)
|
||||
this.formCustom.editor = this.formCustom.editor || CodeMirror.fromTextArea(textarea, {
|
||||
mode: `javascript`,
|
||||
})
|
||||
this.formCustom.editor.setValue(this.formCustom.code)
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -518,6 +593,20 @@ export default {
|
||||
.github-panel {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
&.formCustom {
|
||||
width: 100%;
|
||||
}
|
||||
.formCustomElInput {
|
||||
/deep/ .CodeMirror {
|
||||
border: 1px solid #eee;
|
||||
height: 300px !important;
|
||||
font-family: "Fira Mono", "DejaVu Sans Mono", Menlo, Consolas, "Liberation Mono", Monaco, "Lucida Console", monospace !important;
|
||||
line-height: 20px;
|
||||
.CodeMirror-scroll {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.setting-form {
|
||||
|
Loading…
Reference in New Issue
Block a user